eal: remove sys/queue.h from public headers
[dpdk.git] / drivers / bus / pci / windows / pci_netuio.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2020 Intel Corporation.
3  */
4
5 #include <sys/queue.h>
6
7 #include <rte_windows.h>
8 #include <rte_errno.h>
9 #include <rte_log.h>
10 #include <rte_eal.h>
11
12 #ifdef __MINGW32__
13 #include <ddk/ndisguid.h>
14 #else
15 #include <ndisguid.h>
16 #endif
17
18 #include "private.h"
19 #include "pci_netuio.h"
20
21 static int
22 send_ioctl(HANDLE f, DWORD ioctl,
23         void *in_buf, DWORD in_buf_size, void *out_buf, DWORD out_buf_size)
24 {
25         BOOL res;
26         DWORD bytes_ret = 0;
27
28         res = DeviceIoControl(f, ioctl, in_buf, in_buf_size,
29                 out_buf, out_buf_size, &bytes_ret, NULL);
30         if (!res) {
31                 RTE_LOG_WIN32_ERR("DeviceIoControl:IOCTL query failed");
32                 return -1;
33         }
34
35         return ERROR_SUCCESS;
36 }
37
38 static HDEVINFO
39 get_netuio_device_information_set(HDEVINFO dev_info,
40         PSP_DEVINFO_DATA dev_info_data)
41 {
42         BOOL res;
43         DWORD required_size = 0;
44         TCHAR dev_instance_id[MAX_DEVICENAME_SZ];
45         HDEVINFO di_set = INVALID_HANDLE_VALUE;
46
47         /* obtain the driver interface for this device */
48         res = SetupDiGetDeviceInstanceId(dev_info, dev_info_data,
49                 dev_instance_id, sizeof(dev_instance_id), &required_size);
50         if (!res) {
51                 RTE_LOG_WIN32_ERR("SetupDiGetDeviceInstanceId");
52                 goto end;
53         }
54
55         /* return the device information set for this device */
56         di_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_NETUIO,
57                 dev_instance_id, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
58         if (di_set == INVALID_HANDLE_VALUE) {
59                 RTE_LOG_WIN32_ERR("SetupDiGetClassDevs(device information set)");
60                 goto end;
61         }
62 end:
63         return di_set;
64 }
65
66 static PSP_DEVICE_INTERFACE_DETAIL_DATA
67 get_netuio_device_interface_detail(HDEVINFO di_set)
68 {
69         BOOL res;
70         DWORD required_size = 0;
71         SP_DEVICE_INTERFACE_DATA  dev_ifx_data = { 0 };
72         PSP_DEVICE_INTERFACE_DETAIL_DATA dev_ifx_detail = NULL;
73
74         dev_ifx_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
75
76         /* enumerate the netUIO interfaces for this device information set */
77         res = SetupDiEnumDeviceInterfaces(di_set, 0, &GUID_DEVINTERFACE_NETUIO,
78                 0, &dev_ifx_data);
79         if (!res) {
80                 RTE_LOG_WIN32_ERR("SetupDiEnumDeviceInterfaces: no device interface");
81                 goto end;
82         }
83
84         /* request and allocate required size for the device interface detail */
85         required_size = 0;
86         res = SetupDiGetDeviceInterfaceDetail(di_set, &dev_ifx_data, NULL, 0,
87                 &required_size, NULL);
88         if (!res) {
89                 /* ERROR_INSUFFICIENT_BUFFER is expected */
90                 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
91                         RTE_LOG_WIN32_ERR("SetupDiGetDeviceInterfaceDetail");
92                         goto end;
93                 }
94         }
95
96         dev_ifx_detail = malloc(required_size);
97         if (!dev_ifx_detail) {
98                 RTE_LOG(ERR, EAL, "Could not allocate memory for dev interface.\n");
99                 goto end;
100         }
101         dev_ifx_detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
102
103         res = SetupDiGetDeviceInterfaceDetail(di_set, &dev_ifx_data,
104                 dev_ifx_detail, required_size, NULL, NULL);
105         if (!res) {
106                 RTE_LOG_WIN32_ERR("SetupDiGetDeviceInterfaceDetail");
107                 free(dev_ifx_detail);
108                 dev_ifx_detail = NULL;
109                 goto end;
110         }
111
112 end:
113         return dev_ifx_detail;
114 }
115
116 /*
117  * get device resource information by sending ioctl to netuio driver
118  */
119 int
120 get_netuio_device_info(HDEVINFO dev_info, PSP_DEVINFO_DATA dev_info_data,
121         struct rte_pci_device *dev)
122 {
123         int ret = -1;
124         HDEVINFO di_set = INVALID_HANDLE_VALUE;
125         PSP_DEVICE_INTERFACE_DETAIL_DATA dev_ifx_detail = NULL;
126         HANDLE netuio = INVALID_HANDLE_VALUE;
127         struct device_info hw_info = { 0 };
128         unsigned int idx;
129
130         /* obtain the device information set for this device */
131         di_set = get_netuio_device_information_set(dev_info, dev_info_data);
132         if (di_set == INVALID_HANDLE_VALUE)
133                 goto end;
134
135         /* obtain the device interface detail for this device */
136         dev_ifx_detail = get_netuio_device_interface_detail(di_set);
137         if (!dev_ifx_detail)
138                 goto end;
139
140         /* open the kernel driver */
141         netuio = CreateFile(dev_ifx_detail->DevicePath,
142                 GENERIC_READ | GENERIC_WRITE,
143                 FILE_SHARE_READ | FILE_SHARE_WRITE,
144                 NULL,
145                 OPEN_EXISTING,
146                 FILE_ATTRIBUTE_NORMAL,
147                 NULL);
148         if (netuio == INVALID_HANDLE_VALUE) {
149                 RTE_LOG_WIN32_ERR("CreateFile");
150                 RTE_LOG(ERR, EAL, "Unable to open driver file \"%s\".\n",
151                         dev_ifx_detail->DevicePath);
152                 goto end;
153         }
154
155         /* send ioctl to retrieve device information */
156         if (send_ioctl(netuio, IOCTL_NETUIO_MAP_HW_INTO_USERSPACE, NULL, 0,
157                 &hw_info, sizeof(hw_info)) != ERROR_SUCCESS) {
158                 RTE_LOG(ERR, EAL, "Unable to send ioctl to driver.\n");
159                 goto end;
160         }
161
162         /* set relevant values into the dev structure */
163         for (idx = 0; idx < PCI_MAX_RESOURCE; idx++) {
164                 dev->mem_resource[idx].phys_addr =
165                     hw_info.hw[idx].phys_addr.QuadPart;
166                 dev->mem_resource[idx].addr =
167                     hw_info.hw[idx].user_mapped_virt_addr;
168                 dev->mem_resource[idx].len = hw_info.hw[idx].size;
169         }
170
171         ret = ERROR_SUCCESS;
172 end:
173         if (ret != ERROR_SUCCESS) {
174                 /* Only close the handle to the driver in case of an error.
175                  * Otherwise, we want to keep the handle open. Closing it
176                  * here will cause the driver to unmap all the process-mapped
177                  * values resulting in invalid addresses.
178                  */
179                 if (netuio != INVALID_HANDLE_VALUE)
180                         CloseHandle(netuio);
181         }
182
183         if (dev_ifx_detail)
184                 free(dev_ifx_detail);
185
186         if (di_set != INVALID_HANDLE_VALUE)
187                 SetupDiDestroyDeviceInfoList(di_set);
188
189         return ret;
190 }