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 } 189