From: Tal Shnaiderman <tal...@mellanox.com>

Uses SetupAPI.h functions to scan PCI tree.
Uses DEVPKEY_Device_Numa_Node to get the PCI NUMA node.
Uses SPDRP_BUSNUMBER and SPDRP_BUSNUMBER to get the BDF.
scanning currently supports types RTE_KDRV_NONE.

Signed-off-by: Tal Shnaiderman <tal...@mellanox.com>
---
 drivers/bus/pci/windows/pci.c                | 225 ++++++++++++++++++++++++++-
 lib/librte_eal/windows/include/rte_windows.h |   1 +
 2 files changed, 224 insertions(+), 2 deletions(-)

diff --git a/drivers/bus/pci/windows/pci.c b/drivers/bus/pci/windows/pci.c
index b1d34ae11..e8eff4f6f 100644
--- a/drivers/bus/pci/windows/pci.c
+++ b/drivers/bus/pci/windows/pci.c
@@ -1,14 +1,24 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  * Copyright 2020 Mellanox Technologies, Ltd
  */
+#include <rte_windows.h>
 #include <rte_errno.h>
 #include <rte_log.h>
-
 #include <rte_string_fns.h>
 #include <rte_eal_memconfig.h>
 
 #include "private.h"
 
+#include <devpkey.h>
+
+#define  MAX_STR_TOKENS        8
+#define  DEC                   10
+#define  HEX                   16
+/*
+ * This code is used to simulate a PCI probe by parsing information in
+ * the registry hive for PCI devices.
+ */
+
 /* The functions below are not implemented on Windows,
  * but need to be defined for compilation purposes
  */
@@ -158,6 +168,184 @@ pci_uio_remap_resource(struct rte_pci_device *dev 
__rte_unused)
         */
        return -1;
 }
+
+static
+int get_device_pci_address(HDEVINFO hDevInfo,
+       PSP_DEVINFO_DATA pDeviceInfoData, struct rte_pci_addr *addr)
+{
+       BOOL  bResult;
+       ULONG bus_num, dev_and_func;
+
+       bResult = SetupDiGetDeviceRegistryProperty(hDevInfo, pDeviceInfoData,
+               SPDRP_BUSNUMBER, NULL, (PBYTE)&bus_num, sizeof(bus_num), NULL);
+       if (!bResult)
+               goto end;
+
+       bResult = SetupDiGetDeviceRegistryProperty(hDevInfo, pDeviceInfoData,
+               SPDRP_ADDRESS, NULL, (PBYTE)&dev_and_func, sizeof(dev_and_func),
+               NULL);
+       if (!bResult)
+               goto end;
+
+       addr->domain = 0;
+       addr->bus = bus_num;
+       addr->devid = dev_and_func >> 16;
+       addr->function = dev_and_func & 0xffff;
+       return 0;
+end:
+       return GetLastError();
+
+}
+
+static
+int get_device_resource_info(HDEVINFO hDevInfo,
+       PSP_DEVINFO_DATA pDeviceInfoData, struct rte_pci_device *dev)
+{
+       int  ret = -1;
+       DEVPROPTYPE uPropertyType;
+       DWORD uNumaNode;
+       BOOL  bResult;
+
+       switch (dev->kdrv) {
+       case RTE_KDRV_NONE:
+               /* Get NUMA node using DEVPKEY_Device_Numa_Node */
+               bResult = SetupDiGetDevicePropertyW(hDevInfo, pDeviceInfoData,
+                       &DEVPKEY_Device_Numa_Node, &uPropertyType,
+                       (BYTE *)&uNumaNode, sizeof(uNumaNode), NULL, 0);
+               if (!bResult) {
+                       ret = GetLastError();
+                       goto end;
+               }
+               dev->device.numa_node = uNumaNode;
+               /* mem_resource - Unneeded for RTE_KDRV_NONE */
+               dev->mem_resource[0].phys_addr = 0;
+               dev->mem_resource[0].len = 0;
+               dev->mem_resource[0].addr = NULL;
+               break;
+       default:
+               ret = ERROR_NOT_SUPPORTED;
+               goto end;
+       }
+
+       ret = ERROR_SUCCESS;
+end:
+       return ret;
+}
+/*
+ * get_pci_hardware_info from the SPDRP_HARDWAREID output
+ */
+static int
+get_pci_hardware_info(const char *buf, struct rte_pci_id *pci_id)
+{
+       int ids = 0;
+       unsigned int  vendorID, deviceID, subvendorID = 0;
+
+       ids = sscanf_s(buf, "PCI\\VEN_%x&DEV_%x&SUBSYS_%x", &vendorID,
+               &deviceID, &subvendorID);
+       if (ids != 3)
+               return -1;
+
+       pci_id->vendor_id = vendorID;
+       pci_id->device_id = deviceID;
+       pci_id->subsystem_vendor_id = subvendorID >> 16;
+       pci_id->subsystem_device_id = subvendorID & 0xffff;
+       return 0;
+}
+
+static void
+get_kernel_driver_type(struct rte_pci_device *dev __rte_unused)
+{
+       /*
+        * If another kernel driver is supported the relevant checking
+        * functions should be here
+        */
+       dev->kdrv = RTE_KDRV_NONE;
+}
+
+static int
+pci_scan_one(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDeviceInfoData)
+{
+       struct rte_pci_device *dev;
+       int    ret = -1;
+
+       dev = malloc(sizeof(struct rte_pci_device));
+       if (dev == NULL) {
+               ret = -1;
+               goto end;
+       }
+
+       memset(dev, 0, sizeof(*dev));
+
+       char  strPCIDeviceInfo[PATH_MAX];
+       BOOL  bResult;
+       struct rte_pci_addr addr;
+       struct rte_pci_id pci_id;
+
+       /* Retrieve PCI device IDs */
+       bResult = SetupDiGetDeviceRegistryPropertyA(hDevInfo, pDeviceInfoData,
+                       SPDRP_HARDWAREID, NULL, (BYTE *)&strPCIDeviceInfo,
+                       sizeof(strPCIDeviceInfo), NULL);
+
+       ret = get_pci_hardware_info((const char *)&strPCIDeviceInfo, &pci_id);
+       if (ret != 0) {
+               /*
+                * We won't add this device, but we want to continue
+                * looking for supported devices
+                */
+               ret = ERROR_CONTINUE;
+               goto end;
+       }
+
+       ret = get_device_pci_address(hDevInfo, pDeviceInfoData, &addr);
+       if (ret != 0)
+               goto end;
+
+       dev->addr = addr;
+       dev->id = pci_id;
+       dev->max_vfs = 0; /* TODO: get max_vfs */
+
+       pci_name_set(dev);
+
+       get_kernel_driver_type(dev);
+
+       /* get resources */
+       if (get_device_resource_info(hDevInfo, pDeviceInfoData, dev)
+                       != ERROR_SUCCESS) {
+               goto end;
+       }
+
+       /* device is valid, add in list (sorted) */
+       if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
+               rte_pci_add_device(dev);
+       } else {
+               struct rte_pci_device *dev2 = NULL;
+               int ret;
+
+               TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
+                       ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
+                       if (ret > 0) {
+                               continue;
+                       } else if (ret < 0) {
+                               rte_pci_insert_device(dev2, dev);
+                       } else { /* already registered */
+                               dev2->kdrv = dev->kdrv;
+                               dev2->max_vfs = dev->max_vfs;
+                               memmove(dev2->mem_resource, dev->mem_resource,
+                                       sizeof(dev->mem_resource));
+                               free(dev);
+                       }
+                       return 0;
+               }
+               rte_pci_add_device(dev);
+       }
+
+       return 0;
+end:
+       if (dev)
+               free(dev);
+       return ret;
+}
+
 /*
  * Scan the contents of the PCI bus
  * and add all network class devices into the devices list.
@@ -165,5 +353,38 @@ pci_uio_remap_resource(struct rte_pci_device *dev 
__rte_unused)
 int
 rte_pci_scan(void)
 {
-       return 0;
+       DWORD                   DeviceIndex = 0, FoundDevice = 0;
+       HDEVINFO                hDevInfo = NULL;
+       SP_DEVINFO_DATA DeviceInfoData = { 0 };
+       int                             ret = -1;
+
+       hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, NULL, NULL,
+                               DIGCF_PRESENT);
+       if (hDevInfo == INVALID_HANDLE_VALUE) {
+               RTE_LOG(ERR, EAL, "Unable to enumerate PCI devices.\n");
+               goto end;
+       }
+
+       DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+       DeviceIndex = 0;
+
+       while (SetupDiEnumDeviceInfo(hDevInfo, DeviceIndex, &DeviceInfoData)) {
+               DeviceIndex++;
+               ret = pci_scan_one(hDevInfo, &DeviceInfoData);
+               if (ret == ERROR_SUCCESS)
+                       FoundDevice++;
+               else if (ret != ERROR_CONTINUE)
+                       goto end;
+
+               memset(&DeviceInfoData, 0, sizeof(SP_DEVINFO_DATA));
+               DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
+       }
+
+       RTE_LOG(ERR, EAL, "PCI scan found %lu devices\n", FoundDevice);
+       ret = (FoundDevice != 0) ? 0 : -1;
+end:
+       if (hDevInfo != INVALID_HANDLE_VALUE)
+               SetupDiDestroyDeviceInfoList(hDevInfo);
+
+       return ret;
 }
diff --git a/lib/librte_eal/windows/include/rte_windows.h 
b/lib/librte_eal/windows/include/rte_windows.h
index 899ed7d87..725ac4f9b 100644
--- a/lib/librte_eal/windows/include/rte_windows.h
+++ b/lib/librte_eal/windows/include/rte_windows.h
@@ -25,6 +25,7 @@
 #include <psapi.h>
 #include <setupapi.h>
 #include <winioctl.h>
+#include <devguid.h>
 
 /* Have GUIDs defined. */
 #ifndef INITGUID
-- 
2.16.1.windows.4

Reply via email to