xref: /dpdk/drivers/bus/pci/windows/pci_netuio.c (revision 849f773b7645216954022a47e466043a23125af9)
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 #include <rte_bus_pci.h>
12 
13 #ifdef __MINGW32__
14 #include <ddk/ndisguid.h>
15 #else
16 #include <ndisguid.h>
17 #endif
18 
19 #include "private.h"
20 #include "pci_netuio.h"
21 
22 static int
send_ioctl(HANDLE f,DWORD ioctl,void * in_buf,DWORD in_buf_size,void * out_buf,DWORD out_buf_size)23 send_ioctl(HANDLE f, DWORD ioctl,
24 	void *in_buf, DWORD in_buf_size, void *out_buf, DWORD out_buf_size)
25 {
26 	BOOL res;
27 	DWORD bytes_ret = 0;
28 
29 	res = DeviceIoControl(f, ioctl, in_buf, in_buf_size,
30 		out_buf, out_buf_size, &bytes_ret, NULL);
31 	if (!res) {
32 		RTE_LOG_WIN32_ERR("DeviceIoControl:IOCTL query failed");
33 		return -1;
34 	}
35 
36 	return ERROR_SUCCESS;
37 }
38 
39 static HDEVINFO
get_netuio_device_information_set(HDEVINFO dev_info,PSP_DEVINFO_DATA dev_info_data)40 get_netuio_device_information_set(HDEVINFO dev_info,
41 	PSP_DEVINFO_DATA dev_info_data)
42 {
43 	BOOL res;
44 	DWORD required_size = 0;
45 	TCHAR dev_instance_id[MAX_DEVICENAME_SZ];
46 	HDEVINFO di_set = INVALID_HANDLE_VALUE;
47 
48 	/* obtain the driver interface for this device */
49 	res = SetupDiGetDeviceInstanceId(dev_info, dev_info_data,
50 		dev_instance_id, sizeof(dev_instance_id), &required_size);
51 	if (!res) {
52 		RTE_LOG_WIN32_ERR("SetupDiGetDeviceInstanceId");
53 		goto end;
54 	}
55 
56 	/* return the device information set for this device */
57 	di_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_NETUIO,
58 		dev_instance_id, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
59 	if (di_set == INVALID_HANDLE_VALUE) {
60 		RTE_LOG_WIN32_ERR("SetupDiGetClassDevs(device information set)");
61 		goto end;
62 	}
63 end:
64 	return di_set;
65 }
66 
67 static PSP_DEVICE_INTERFACE_DETAIL_DATA
get_netuio_device_interface_detail(HDEVINFO di_set)68 get_netuio_device_interface_detail(HDEVINFO di_set)
69 {
70 	BOOL res;
71 	DWORD required_size = 0;
72 	SP_DEVICE_INTERFACE_DATA  dev_ifx_data = { 0 };
73 	PSP_DEVICE_INTERFACE_DETAIL_DATA dev_ifx_detail = NULL;
74 
75 	dev_ifx_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
76 
77 	/* enumerate the netUIO interfaces for this device information set */
78 	res = SetupDiEnumDeviceInterfaces(di_set, 0, &GUID_DEVINTERFACE_NETUIO,
79 		0, &dev_ifx_data);
80 	if (!res) {
81 		RTE_LOG_WIN32_ERR("SetupDiEnumDeviceInterfaces: no device interface");
82 		goto end;
83 	}
84 
85 	/* request and allocate required size for the device interface detail */
86 	required_size = 0;
87 	res = SetupDiGetDeviceInterfaceDetail(di_set, &dev_ifx_data, NULL, 0,
88 		&required_size, NULL);
89 	if (!res) {
90 		/* ERROR_INSUFFICIENT_BUFFER is expected */
91 		if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
92 			RTE_LOG_WIN32_ERR("SetupDiGetDeviceInterfaceDetail");
93 			goto end;
94 		}
95 	}
96 
97 	dev_ifx_detail = malloc(required_size);
98 	if (!dev_ifx_detail) {
99 		PCI_LOG(ERR, "Could not allocate memory for dev interface.");
100 		goto end;
101 	}
102 	dev_ifx_detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
103 
104 	res = SetupDiGetDeviceInterfaceDetail(di_set, &dev_ifx_data,
105 		dev_ifx_detail, required_size, NULL, NULL);
106 	if (!res) {
107 		RTE_LOG_WIN32_ERR("SetupDiGetDeviceInterfaceDetail");
108 		free(dev_ifx_detail);
109 		dev_ifx_detail = NULL;
110 		goto end;
111 	}
112 
113 end:
114 	return dev_ifx_detail;
115 }
116 
117 /*
118  * get device resource information by sending ioctl to netuio driver
119  */
120 int
get_netuio_device_info(HDEVINFO dev_info,PSP_DEVINFO_DATA dev_info_data,struct rte_pci_device * dev)121 get_netuio_device_info(HDEVINFO dev_info, PSP_DEVINFO_DATA dev_info_data,
122 	struct rte_pci_device *dev)
123 {
124 	int ret = -1;
125 	HDEVINFO di_set = INVALID_HANDLE_VALUE;
126 	PSP_DEVICE_INTERFACE_DETAIL_DATA dev_ifx_detail = NULL;
127 	HANDLE netuio = INVALID_HANDLE_VALUE;
128 	struct device_info hw_info = { 0 };
129 	unsigned int idx;
130 
131 	/* obtain the device information set for this device */
132 	di_set = get_netuio_device_information_set(dev_info, dev_info_data);
133 	if (di_set == INVALID_HANDLE_VALUE)
134 		goto end;
135 
136 	/* obtain the device interface detail for this device */
137 	dev_ifx_detail = get_netuio_device_interface_detail(di_set);
138 	if (!dev_ifx_detail)
139 		goto end;
140 
141 	/* open the kernel driver */
142 	netuio = CreateFile(dev_ifx_detail->DevicePath,
143 		GENERIC_READ | GENERIC_WRITE,
144 		FILE_SHARE_READ | FILE_SHARE_WRITE,
145 		NULL,
146 		OPEN_EXISTING,
147 		FILE_ATTRIBUTE_NORMAL,
148 		NULL);
149 	if (netuio == INVALID_HANDLE_VALUE) {
150 		RTE_LOG_WIN32_ERR("CreateFile");
151 		PCI_LOG(ERR, "Unable to open driver file \"%s\".", 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 		PCI_LOG(ERR, "Unable to send ioctl to driver.");
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 	free(dev_ifx_detail);
184 
185 	if (di_set != INVALID_HANDLE_VALUE)
186 		SetupDiDestroyDeviceInfoList(di_set);
187 
188 	return ret;
189 }
190