6605c7f02e
NetUIO device class and interface GUIDs are defined in system
headers starting from platform SDK v10.0.20253. Inspect SDK
version to avoid redefinition.
Pre-release SDKs do not promise compatibility and a narrow
subset of SDKs may still be subject to redefinition.
Fixes: c76ec01b45
(bus/pci: support netuio on Windows)
Cc: stable@dpdk.org
Signed-off-by: Tyler Retzlaff <roretzla@linux.microsoft.com>
Acked-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>
Acked-by: Ranjit Menon <ranjit.menon@intel.com>
189 lines
5.0 KiB
C
189 lines
5.0 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright(c) 2020 Intel Corporation.
|
|
*/
|
|
|
|
#include <rte_windows.h>
|
|
#include <rte_errno.h>
|
|
#include <rte_log.h>
|
|
#include <rte_eal.h>
|
|
|
|
#ifdef __MINGW32__
|
|
#include <ddk/ndisguid.h>
|
|
#else
|
|
#include <ndisguid.h>
|
|
#endif
|
|
|
|
#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;
|
|
}
|