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 /* Class ID consists of hexadecimal digits */
27 #define RTE_PCI_DRV_CLASSID_DIGIT "0123456789abcdefABCDEF"
29 /* Some of the functions below are not implemented on Windows,
30 * but need to be defined for compilation purposes
35 rte_pci_map_device(struct rte_pci_device *dev)
37 /* Only return success for devices bound to netuio.
38 * Devices that are bound to netuio are mapped at
39 * the bus probing stage.
41 if (dev->kdrv == RTE_PCI_KDRV_NET_UIO)
47 /* Unmap pci device */
49 rte_pci_unmap_device(struct rte_pci_device *dev __rte_unused)
51 /* This function is not implemented on Windows.
52 * We really should short-circuit the call to these functions by
53 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
54 * in the rte_pci_driver flags.
58 /* Read PCI config space. */
60 rte_pci_read_config(const struct rte_pci_device *dev __rte_unused,
61 void *buf __rte_unused, size_t len __rte_unused,
62 off_t offset __rte_unused)
64 /* This function is not implemented on Windows.
65 * We really should short-circuit the call to these functions by
66 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
67 * in the rte_pci_driver flags.
72 /* Write PCI config space. */
74 rte_pci_write_config(const struct rte_pci_device *dev __rte_unused,
75 const void *buf __rte_unused, size_t len __rte_unused,
76 off_t offset __rte_unused)
78 /* This function is not implemented on Windows.
79 * We really should short-circuit the call to these functions by
80 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
81 * in the rte_pci_driver flags.
87 pci_device_iova_mode(const struct rte_pci_driver *pdrv __rte_unused,
88 const struct rte_pci_device *pdev __rte_unused)
90 /* This function is not implemented on Windows.
91 * We really should short-circuit the call to these functions by
92 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
93 * in the rte_pci_driver flags.
99 rte_pci_ioport_map(struct rte_pci_device *dev __rte_unused,
100 int bar __rte_unused, struct rte_pci_ioport *p __rte_unused)
102 /* This function is not implemented on Windows.
103 * We really should short-circuit the call to these functions by
104 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
105 * in the rte_pci_driver flags.
112 rte_pci_ioport_read(struct rte_pci_ioport *p __rte_unused,
113 void *data __rte_unused, size_t len __rte_unused,
114 off_t offset __rte_unused)
116 /* This function is not implemented on Windows.
117 * We really should short-circuit the call to these functions by
118 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
119 * in the rte_pci_driver flags.
124 rte_pci_ioport_unmap(struct rte_pci_ioport *p __rte_unused)
126 /* This function is not implemented on Windows.
127 * We really should short-circuit the call to these functions by
128 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
129 * in the rte_pci_driver flags.
135 pci_device_iommu_support_va(const struct rte_pci_device *dev __rte_unused)
137 /* This function is not implemented on Windows.
138 * We really should short-circuit the call to these functions by
139 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
140 * in the rte_pci_driver flags.
146 rte_pci_ioport_write(struct rte_pci_ioport *p __rte_unused,
147 const void *data __rte_unused, size_t len __rte_unused,
148 off_t offset __rte_unused)
150 /* This function is not implemented on Windows.
151 * We really should short-circuit the call to these functions by
152 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
153 * in the rte_pci_driver flags.
157 /* remap the PCI resource of a PCI device in anonymous virtual memory */
159 pci_uio_remap_resource(struct rte_pci_device *dev __rte_unused)
161 /* This function is not implemented on Windows.
162 * We really should short-circuit the call to these functions by
163 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
164 * in the rte_pci_driver flags.
170 get_device_pci_address(HDEVINFO dev_info,
171 PSP_DEVINFO_DATA device_info_data, struct rte_pci_addr *addr)
174 ULONG bus_num, dev_and_func;
176 res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
177 SPDRP_BUSNUMBER, NULL, (PBYTE)&bus_num, sizeof(bus_num), NULL);
180 "SetupDiGetDeviceRegistryProperty(SPDRP_BUSNUMBER)");
184 res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
185 SPDRP_ADDRESS, NULL, (PBYTE)&dev_and_func, sizeof(dev_and_func),
189 "SetupDiGetDeviceRegistryProperty(SPDRP_ADDRESS)");
193 addr->domain = (bus_num >> 8) & 0xffff;
194 addr->bus = bus_num & 0xff;
195 addr->devid = dev_and_func >> 16;
196 addr->function = dev_and_func & 0xffff;
201 get_device_resource_info(HDEVINFO dev_info,
202 PSP_DEVINFO_DATA dev_info_data, struct rte_pci_device *dev)
204 DEVPROPTYPE property_type;
210 case RTE_PCI_KDRV_UNKNOWN:
211 /* bifurcated driver case - mem_resource is unneeded */
212 dev->mem_resource[0].phys_addr = 0;
213 dev->mem_resource[0].len = 0;
214 dev->mem_resource[0].addr = NULL;
216 case RTE_PCI_KDRV_NET_UIO:
217 /* get device info from NetUIO kernel driver */
218 ret = get_netuio_device_info(dev_info, dev_info_data, dev);
221 "Could not retrieve device info for PCI device "
223 dev->addr.domain, dev->addr.bus,
224 dev->addr.devid, dev->addr.function);
229 /* kernel driver type is unsupported */
231 "Kernel driver type for PCI device " PCI_PRI_FMT ","
233 dev->addr.domain, dev->addr.bus,
234 dev->addr.devid, dev->addr.function);
238 /* Get NUMA node using DEVPKEY_Device_Numa_Node */
239 res = SetupDiGetDevicePropertyW(dev_info, dev_info_data,
240 &DEVPKEY_Device_Numa_Node, &property_type,
241 (BYTE *)&numa_node, sizeof(numa_node), NULL, 0);
243 DWORD error = GetLastError();
244 if (error == ERROR_NOT_FOUND) {
245 /* On older CPUs, NUMA is not bound to PCIe locality. */
246 dev->device.numa_node = 0;
247 return ERROR_SUCCESS;
249 RTE_LOG_WIN32_ERR("SetupDiGetDevicePropertyW"
250 "(DEVPKEY_Device_Numa_Node)");
253 dev->device.numa_node = numa_node;
255 return ERROR_SUCCESS;
259 * get string that contains the list of hardware IDs for a device
262 get_pci_hardware_id(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data,
263 char *pci_device_info, size_t pci_device_info_len)
267 /* Retrieve PCI device IDs */
268 res = SetupDiGetDeviceRegistryPropertyA(dev_info, device_info_data,
269 SPDRP_HARDWAREID, NULL, (BYTE *)pci_device_info,
270 pci_device_info_len, NULL);
273 "SetupDiGetDeviceRegistryPropertyA(SPDRP_HARDWAREID)");
281 * parse the SPDRP_HARDWAREID output and assign to rte_pci_id
283 * A list of the device identification string formats can be found at:
284 * https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-pci-devices
287 parse_pci_hardware_id(const char *buf, struct rte_pci_id *pci_id)
290 uint16_t vendor_id, device_id;
291 uint32_t subvendor_id = 0, class_id = 0;
294 ids = sscanf_s(buf, "PCI\\VEN_%" PRIx16 "&DEV_%" PRIx16 "&SUBSYS_%"
295 PRIx32, &vendor_id, &device_id, &subvendor_id);
299 /* Try and find PCI class ID */
300 for (cp = buf; !(cp[0] == 0 && cp[1] == 0); cp++)
301 if (*cp == '&' && sscanf_s(cp,
302 "&CC_%" PRIx32, &class_id) == 1) {
304 * If the Programming Interface code is not specified,
305 * assume that it is zero.
307 if (strspn(cp + 4, RTE_PCI_DRV_CLASSID_DIGIT) == 4)
312 pci_id->vendor_id = vendor_id;
313 pci_id->device_id = device_id;
314 pci_id->subsystem_device_id = subvendor_id >> 16;
315 pci_id->subsystem_vendor_id = subvendor_id & 0xffff;
316 pci_id->class_id = class_id;
321 set_kernel_driver_type(PSP_DEVINFO_DATA device_info_data,
322 struct rte_pci_device *dev)
324 /* set kernel driver type based on device class */
325 if (IsEqualGUID(&(device_info_data->ClassGuid), &GUID_DEVCLASS_NETUIO))
326 dev->kdrv = RTE_PCI_KDRV_NET_UIO;
328 dev->kdrv = RTE_PCI_KDRV_UNKNOWN;
332 pci_scan_one(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data)
334 struct rte_pci_device *dev = NULL;
336 char pci_device_info[REGSTR_VAL_MAX_HCID_LEN];
337 struct rte_pci_addr addr;
338 struct rte_pci_id pci_id;
340 ret = get_device_pci_address(dev_info, device_info_data, &addr);
344 if (rte_pci_ignore_device(&addr)) {
346 * We won't add this device, but we want to continue
347 * looking for supported devices
349 ret = ERROR_CONTINUE;
353 ret = get_pci_hardware_id(dev_info, device_info_data,
354 pci_device_info, sizeof(pci_device_info));
358 ret = parse_pci_hardware_id((const char *)&pci_device_info, &pci_id);
361 * We won't add this device, but we want to continue
362 * looking for supported devices
364 ret = ERROR_CONTINUE;
368 dev = malloc(sizeof(*dev));
372 memset(dev, 0, sizeof(*dev));
374 dev->device.bus = &rte_pci_bus.bus;
377 dev->max_vfs = 0; /* TODO: get max_vfs */
381 set_kernel_driver_type(device_info_data, dev);
384 if (get_device_resource_info(dev_info, device_info_data, dev)
389 /* device is valid, add in list (sorted) */
390 if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
391 rte_pci_add_device(dev);
393 struct rte_pci_device *dev2 = NULL;
396 TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
397 ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
400 } else if (ret < 0) {
401 rte_pci_insert_device(dev2, dev);
402 } else { /* already registered */
403 dev2->kdrv = dev->kdrv;
404 dev2->max_vfs = dev->max_vfs;
405 memmove(dev2->mem_resource, dev->mem_resource,
406 sizeof(dev->mem_resource));
411 rte_pci_add_device(dev);
422 * Scan the contents of the PCI bus
423 * and add all network class devices into the devices list.
429 DWORD device_index = 0, found_device = 0;
431 SP_DEVINFO_DATA device_info_data;
433 /* for debug purposes, PCI can be disabled */
434 if (!rte_eal_has_pci())
437 dev_info = SetupDiGetClassDevs(NULL, TEXT("PCI"), NULL,
438 DIGCF_PRESENT | DIGCF_ALLCLASSES);
439 if (dev_info == INVALID_HANDLE_VALUE) {
440 RTE_LOG_WIN32_ERR("SetupDiGetClassDevs(pci_scan)");
441 RTE_LOG(ERR, EAL, "Unable to enumerate PCI devices.\n");
445 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
448 while (SetupDiEnumDeviceInfo(dev_info, device_index,
449 &device_info_data)) {
451 /* we only want to enumerate net & netuio class devices */
452 if (IsEqualGUID(&(device_info_data.ClassGuid),
453 &GUID_DEVCLASS_NET) ||
454 IsEqualGUID(&(device_info_data.ClassGuid),
455 &GUID_DEVCLASS_NETUIO)) {
456 ret = pci_scan_one(dev_info, &device_info_data);
457 if (ret == ERROR_SUCCESS)
459 else if (ret != ERROR_CONTINUE)
462 memset(&device_info_data, 0, sizeof(SP_DEVINFO_DATA));
463 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
466 RTE_LOG(DEBUG, EAL, "PCI scan found %lu devices\n", found_device);
469 if (dev_info != INVALID_HANDLE_VALUE)
470 SetupDiDestroyDeviceInfoList(dev_info);