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 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 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 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 RTE_LOG(ERR, EAL, "Could not allocate memory for dev interface.\n"); 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 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 RTE_LOG(ERR, EAL, "Unable to open driver file \"%s\".\n", 152 dev_ifx_detail->DevicePath); 153 goto end; 154 } 155 156 /* send ioctl to retrieve device information */ 157 if (send_ioctl(netuio, IOCTL_NETUIO_MAP_HW_INTO_USERSPACE, NULL, 0, 158 &hw_info, sizeof(hw_info)) != ERROR_SUCCESS) { 159 RTE_LOG(ERR, EAL, "Unable to send ioctl to driver.\n"); 160 goto end; 161 } 162 163 /* set relevant values into the dev structure */ 164 for (idx = 0; idx < PCI_MAX_RESOURCE; idx++) { 165 dev->mem_resource[idx].phys_addr = 166 hw_info.hw[idx].phys_addr.QuadPart; 167 dev->mem_resource[idx].addr = 168 hw_info.hw[idx].user_mapped_virt_addr; 169 dev->mem_resource[idx].len = hw_info.hw[idx].size; 170 } 171 172 ret = ERROR_SUCCESS; 173 end: 174 if (ret != ERROR_SUCCESS) { 175 /* Only close the handle to the driver in case of an error. 176 * Otherwise, we want to keep the handle open. Closing it 177 * here will cause the driver to unmap all the process-mapped 178 * values resulting in invalid addresses. 179 */ 180 if (netuio != INVALID_HANDLE_VALUE) 181 CloseHandle(netuio); 182 } 183 184 free(dev_ifx_detail); 185 186 if (di_set != INVALID_HANDLE_VALUE) 187 SetupDiDestroyDeviceInfoList(di_set); 188 189 return ret; 190 } 191