/* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2020 Intel Corporation. */ #include #include #include #include #include "private.h" #include "pci_netuio.h" static int send_ioctl(HANDLE f, DWORD ioctl, void *in_buf, DWORD in_buf_size, void *out_buf, DWORD out_buf_size) { BOOL res; DWORD bytes_ret = 0; res = DeviceIoControl(f, ioctl, in_buf, in_buf_size, out_buf, out_buf_size, &bytes_ret, NULL); if (!res) { RTE_LOG_WIN32_ERR("DeviceIoControl:IOCTL query failed"); return -1; } return ERROR_SUCCESS; } static HDEVINFO get_netuio_device_information_set(HDEVINFO dev_info, PSP_DEVINFO_DATA dev_info_data) { BOOL res; DWORD required_size = 0; TCHAR dev_instance_id[MAX_DEVICENAME_SZ]; HDEVINFO di_set = INVALID_HANDLE_VALUE; /* obtain the driver interface for this device */ res = SetupDiGetDeviceInstanceId(dev_info, dev_info_data, dev_instance_id, sizeof(dev_instance_id), &required_size); if (!res) { RTE_LOG_WIN32_ERR("SetupDiGetDeviceInstanceId"); goto end; } /* return the device information set for this device */ di_set = SetupDiGetClassDevs(&GUID_DEVINTERFACE_NETUIO, dev_instance_id, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); if (di_set == INVALID_HANDLE_VALUE) { RTE_LOG_WIN32_ERR("SetupDiGetClassDevs(device information set)"); goto end; } end: return di_set; } static PSP_DEVICE_INTERFACE_DETAIL_DATA get_netuio_device_interface_detail(HDEVINFO di_set) { BOOL res; DWORD required_size = 0; SP_DEVICE_INTERFACE_DATA dev_ifx_data = { 0 }; PSP_DEVICE_INTERFACE_DETAIL_DATA dev_ifx_detail = NULL; dev_ifx_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); /* enumerate the netUIO interfaces for this device information set */ res = SetupDiEnumDeviceInterfaces(di_set, 0, &GUID_DEVINTERFACE_NETUIO, 0, &dev_ifx_data); if (!res) { RTE_LOG_WIN32_ERR("SetupDiEnumDeviceInterfaces: no device interface"); goto end; } /* request and allocate required size for the device interface detail */ required_size = 0; res = SetupDiGetDeviceInterfaceDetail(di_set, &dev_ifx_data, NULL, 0, &required_size, NULL); if (!res) { /* ERROR_INSUFFICIENT_BUFFER is expected */ if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) { RTE_LOG_WIN32_ERR("SetupDiGetDeviceInterfaceDetail"); goto end; } } dev_ifx_detail = malloc(required_size); if (!dev_ifx_detail) { RTE_LOG(ERR, EAL, "Could not allocate memory for dev interface.\n"); goto end; } dev_ifx_detail->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); res = SetupDiGetDeviceInterfaceDetail(di_set, &dev_ifx_data, dev_ifx_detail, required_size, NULL, NULL); if (!res) { RTE_LOG_WIN32_ERR("SetupDiGetDeviceInterfaceDetail"); free(dev_ifx_detail); dev_ifx_detail = NULL; goto end; } end: return dev_ifx_detail; } /* * get device resource information by sending ioctl to netuio driver */ int get_netuio_device_info(HDEVINFO dev_info, PSP_DEVINFO_DATA dev_info_data, struct rte_pci_device *dev) { int ret = -1; HDEVINFO di_set = INVALID_HANDLE_VALUE; PSP_DEVICE_INTERFACE_DETAIL_DATA dev_ifx_detail = NULL; HANDLE netuio = INVALID_HANDLE_VALUE; struct device_info hw_info = { 0 }; unsigned int idx; /* obtain the device information set for this device */ di_set = get_netuio_device_information_set(dev_info, dev_info_data); if (di_set == INVALID_HANDLE_VALUE) goto end; /* obtain the device interface detail for this device */ dev_ifx_detail = get_netuio_device_interface_detail(di_set); if (!dev_ifx_detail) goto end; /* open the kernel driver */ netuio = CreateFile(dev_ifx_detail->DevicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (netuio == INVALID_HANDLE_VALUE) { RTE_LOG_WIN32_ERR("CreateFile"); RTE_LOG(ERR, EAL, "Unable to open driver file \"%s\".\n", dev_ifx_detail->DevicePath); goto end; } /* send ioctl to retrieve device information */ if (send_ioctl(netuio, IOCTL_NETUIO_MAP_HW_INTO_USERSPACE, NULL, 0, &hw_info, sizeof(hw_info)) != ERROR_SUCCESS) { RTE_LOG(ERR, EAL, "Unable to send ioctl to driver.\n"); goto end; } /* set relevant values into the dev structure */ for (idx = 0; idx < PCI_MAX_RESOURCE; idx++) { dev->mem_resource[idx].phys_addr = hw_info.hw[idx].phys_addr.QuadPart; dev->mem_resource[idx].addr = hw_info.hw[idx].user_mapped_virt_addr; dev->mem_resource[idx].len = hw_info.hw[idx].size; } ret = ERROR_SUCCESS; end: if (ret != ERROR_SUCCESS) { /* Only close the handle to the driver in case of an error. * Otherwise, we want to keep the handle open. Closing it * here will cause the driver to unmap all the process-mapped * values resulting in invalid addresses. */ if (netuio != INVALID_HANDLE_VALUE) CloseHandle(netuio); } if (dev_ifx_detail) free(dev_ifx_detail); if (di_set != INVALID_HANDLE_VALUE) SetupDiDestroyDeviceInfoList(di_set); return ret; }