1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2020 Mellanox Technologies, Ltd
4 #include <rte_windows.h>
10 #include "pci_netuio.h"
15 #if defined RTE_TOOLCHAIN_GCC && (__MINGW64_VERSION_MAJOR < 8)
16 #include <devpropdef.h>
17 DEFINE_DEVPROPKEY(DEVPKEY_Device_Numa_Node, 0x540b947e, 0x8b40, 0x45bc,
18 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 3);
22 * This code is used to simulate a PCI probe by parsing information in
23 * the registry hive for PCI devices.
26 /* Some of the functions below are not implemented on Windows,
27 * but need to be defined for compilation purposes
32 rte_pci_map_device(struct rte_pci_device *dev)
34 /* Only return success for devices bound to netuio.
35 * Devices that are bound to netuio are mapped at
36 * the bus probing stage.
38 if (dev->kdrv == RTE_PCI_KDRV_NIC_UIO)
44 /* Unmap pci device */
46 rte_pci_unmap_device(struct rte_pci_device *dev __rte_unused)
48 /* This function is not implemented on Windows.
49 * We really should short-circuit the call to these functions by
50 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
51 * in the rte_pci_driver flags.
55 /* Read PCI config space. */
57 rte_pci_read_config(const struct rte_pci_device *dev __rte_unused,
58 void *buf __rte_unused, size_t len __rte_unused,
59 off_t offset __rte_unused)
61 /* This function is not implemented on Windows.
62 * We really should short-circuit the call to these functions by
63 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
64 * in the rte_pci_driver flags.
69 /* Write PCI config space. */
71 rte_pci_write_config(const struct rte_pci_device *dev __rte_unused,
72 const void *buf __rte_unused, size_t len __rte_unused,
73 off_t offset __rte_unused)
75 /* This function is not implemented on Windows.
76 * We really should short-circuit the call to these functions by
77 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
78 * in the rte_pci_driver flags.
84 pci_device_iova_mode(const struct rte_pci_driver *pdrv __rte_unused,
85 const struct rte_pci_device *pdev __rte_unused)
87 /* This function is not implemented on Windows.
88 * We really should short-circuit the call to these functions by
89 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
90 * in the rte_pci_driver flags.
96 rte_pci_ioport_map(struct rte_pci_device *dev __rte_unused,
97 int bar __rte_unused, struct rte_pci_ioport *p __rte_unused)
99 /* This function is not implemented on Windows.
100 * We really should short-circuit the call to these functions by
101 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
102 * in the rte_pci_driver flags.
109 rte_pci_ioport_read(struct rte_pci_ioport *p __rte_unused,
110 void *data __rte_unused, size_t len __rte_unused,
111 off_t offset __rte_unused)
113 /* This function is not implemented on Windows.
114 * We really should short-circuit the call to these functions by
115 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
116 * in the rte_pci_driver flags.
121 rte_pci_ioport_unmap(struct rte_pci_ioport *p __rte_unused)
123 /* This function is not implemented on Windows.
124 * We really should short-circuit the call to these functions by
125 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
126 * in the rte_pci_driver flags.
132 pci_device_iommu_support_va(const struct rte_pci_device *dev __rte_unused)
134 /* This function is not implemented on Windows.
135 * We really should short-circuit the call to these functions by
136 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
137 * in the rte_pci_driver flags.
143 rte_pci_ioport_write(struct rte_pci_ioport *p __rte_unused,
144 const void *data __rte_unused, size_t len __rte_unused,
145 off_t offset __rte_unused)
147 /* This function is not implemented on Windows.
148 * We really should short-circuit the call to these functions by
149 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
150 * in the rte_pci_driver flags.
154 /* remap the PCI resource of a PCI device in anonymous virtual memory */
156 pci_uio_remap_resource(struct rte_pci_device *dev __rte_unused)
158 /* This function is not implemented on Windows.
159 * We really should short-circuit the call to these functions by
160 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
161 * in the rte_pci_driver flags.
167 get_device_pci_address(HDEVINFO dev_info,
168 PSP_DEVINFO_DATA device_info_data, struct rte_pci_addr *addr)
171 ULONG bus_num, dev_and_func;
173 res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
174 SPDRP_BUSNUMBER, NULL, (PBYTE)&bus_num, sizeof(bus_num), NULL);
177 "SetupDiGetDeviceRegistryProperty(SPDRP_BUSNUMBER)");
181 res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
182 SPDRP_ADDRESS, NULL, (PBYTE)&dev_and_func, sizeof(dev_and_func),
186 "SetupDiGetDeviceRegistryProperty(SPDRP_ADDRESS)");
190 addr->domain = (bus_num >> 8) & 0xffff;
191 addr->bus = bus_num & 0xff;
192 addr->devid = dev_and_func >> 16;
193 addr->function = dev_and_func & 0xffff;
198 get_device_resource_info(HDEVINFO dev_info,
199 PSP_DEVINFO_DATA dev_info_data, struct rte_pci_device *dev)
201 DEVPROPTYPE property_type;
207 case RTE_PCI_KDRV_NONE:
208 /* mem_resource - Unneeded for RTE_PCI_KDRV_NONE */
209 dev->mem_resource[0].phys_addr = 0;
210 dev->mem_resource[0].len = 0;
211 dev->mem_resource[0].addr = NULL;
213 case RTE_PCI_KDRV_NIC_UIO:
214 /* get device info from netuio kernel driver */
215 ret = get_netuio_device_info(dev_info, dev_info_data, dev);
218 "Could not retrieve device info for PCI device "
220 dev->addr.domain, dev->addr.bus,
221 dev->addr.devid, dev->addr.function);
226 /* kernel driver type is unsupported */
228 "Kernel driver type for PCI device " PCI_PRI_FMT ","
230 dev->addr.domain, dev->addr.bus,
231 dev->addr.devid, dev->addr.function);
235 /* Get NUMA node using DEVPKEY_Device_Numa_Node */
236 res = SetupDiGetDevicePropertyW(dev_info, dev_info_data,
237 &DEVPKEY_Device_Numa_Node, &property_type,
238 (BYTE *)&numa_node, sizeof(numa_node), NULL, 0);
240 DWORD error = GetLastError();
241 if (error == ERROR_NOT_FOUND) {
242 /* On older CPUs, NUMA is not bound to PCIe locality. */
243 dev->device.numa_node = 0;
244 return ERROR_SUCCESS;
246 RTE_LOG_WIN32_ERR("SetupDiGetDevicePropertyW"
247 "(DEVPKEY_Device_Numa_Node)");
250 dev->device.numa_node = numa_node;
252 return ERROR_SUCCESS;
256 * get string that contains the list of hardware IDs for a device
259 get_pci_hardware_id(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data,
260 char *pci_device_info, size_t pci_device_info_len)
264 /* Retrieve PCI device IDs */
265 res = SetupDiGetDeviceRegistryPropertyA(dev_info, device_info_data,
266 SPDRP_HARDWAREID, NULL, (BYTE *)pci_device_info,
267 pci_device_info_len, NULL);
270 "SetupDiGetDeviceRegistryPropertyA(SPDRP_HARDWAREID)");
278 * parse the SPDRP_HARDWAREID output and assign to rte_pci_id
281 parse_pci_hardware_id(const char *buf, struct rte_pci_id *pci_id)
284 uint16_t vendor_id, device_id;
285 uint32_t subvendor_id = 0;
287 ids = sscanf_s(buf, "PCI\\VEN_%" PRIx16 "&DEV_%" PRIx16 "&SUBSYS_%"
288 PRIx32, &vendor_id, &device_id, &subvendor_id);
292 pci_id->vendor_id = vendor_id;
293 pci_id->device_id = device_id;
294 pci_id->subsystem_device_id = subvendor_id >> 16;
295 pci_id->subsystem_vendor_id = subvendor_id & 0xffff;
300 set_kernel_driver_type(PSP_DEVINFO_DATA device_info_data,
301 struct rte_pci_device *dev)
303 /* set kernel driver type based on device class */
304 if (IsEqualGUID(&(device_info_data->ClassGuid), &GUID_DEVCLASS_NETUIO))
305 dev->kdrv = RTE_PCI_KDRV_NIC_UIO;
307 dev->kdrv = RTE_PCI_KDRV_NONE;
311 pci_scan_one(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data)
313 struct rte_pci_device *dev;
315 char pci_device_info[REGSTR_VAL_MAX_HCID_LEN];
316 struct rte_pci_addr addr;
317 struct rte_pci_id pci_id;
319 dev = malloc(sizeof(*dev));
323 memset(dev, 0, sizeof(*dev));
325 ret = get_pci_hardware_id(dev_info, device_info_data,
326 pci_device_info, sizeof(pci_device_info));
330 ret = parse_pci_hardware_id((const char *)&pci_device_info, &pci_id);
333 * We won't add this device, but we want to continue
334 * looking for supported devices
336 ret = ERROR_CONTINUE;
340 ret = get_device_pci_address(dev_info, device_info_data, &addr);
346 dev->max_vfs = 0; /* TODO: get max_vfs */
350 set_kernel_driver_type(device_info_data, dev);
353 if (get_device_resource_info(dev_info, device_info_data, dev)
358 /* device is valid, add in list (sorted) */
359 if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
360 rte_pci_add_device(dev);
362 struct rte_pci_device *dev2 = NULL;
365 TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
366 ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
369 } else if (ret < 0) {
370 rte_pci_insert_device(dev2, dev);
371 } else { /* already registered */
372 dev2->kdrv = dev->kdrv;
373 dev2->max_vfs = dev->max_vfs;
374 memmove(dev2->mem_resource, dev->mem_resource,
375 sizeof(dev->mem_resource));
380 rte_pci_add_device(dev);
391 * Scan the contents of the PCI bus
392 * and add all network class devices into the devices list.
398 DWORD device_index = 0, found_device = 0;
400 SP_DEVINFO_DATA device_info_data;
402 /* for debug purposes, PCI can be disabled */
403 if (!rte_eal_has_pci())
406 dev_info = SetupDiGetClassDevs(NULL, TEXT("PCI"), NULL,
407 DIGCF_PRESENT | DIGCF_ALLCLASSES);
408 if (dev_info == INVALID_HANDLE_VALUE) {
409 RTE_LOG_WIN32_ERR("SetupDiGetClassDevs(pci_scan)");
410 RTE_LOG(ERR, EAL, "Unable to enumerate PCI devices.\n");
414 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
417 while (SetupDiEnumDeviceInfo(dev_info, device_index,
418 &device_info_data)) {
420 /* we only want to enumerate net & netuio class devices */
421 if (IsEqualGUID(&(device_info_data.ClassGuid),
422 &GUID_DEVCLASS_NET) ||
423 IsEqualGUID(&(device_info_data.ClassGuid),
424 &GUID_DEVCLASS_NETUIO)) {
425 ret = pci_scan_one(dev_info, &device_info_data);
426 if (ret == ERROR_SUCCESS)
428 else if (ret != ERROR_CONTINUE)
431 memset(&device_info_data, 0, sizeof(SP_DEVINFO_DATA));
432 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
435 RTE_LOG(DEBUG, EAL, "PCI scan found %lu devices\n", found_device);
438 if (dev_info != INVALID_HANDLE_VALUE)
439 SetupDiDestroyDeviceInfoList(dev_info);