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