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