1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright 2020 Mellanox Technologies, Ltd
4 #include <rte_windows.h>
7 #include <rte_eal_memconfig.h>
14 #ifdef RTE_TOOLCHAIN_GCC
15 #include <devpropdef.h>
16 DEFINE_DEVPROPKEY(DEVPKEY_Device_Numa_Node, 0x540b947e, 0x8b40, 0x45bc,
17 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 3);
21 * This code is used to simulate a PCI probe by parsing information in
22 * the registry hive for PCI devices.
25 /* The functions below are not implemented on Windows,
26 * but need to be defined for compilation purposes
31 rte_pci_map_device(struct rte_pci_device *dev __rte_unused)
33 /* This function is not implemented on Windows.
34 * We really should short-circuit the call to these functions by
35 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
36 * in the rte_pci_driver flags.
41 /* Unmap pci device */
43 rte_pci_unmap_device(struct rte_pci_device *dev __rte_unused)
45 /* This function is not implemented on Windows.
46 * We really should short-circuit the call to these functions by
47 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
48 * in the rte_pci_driver flags.
53 pci_update_device(const struct rte_pci_addr *addr __rte_unused)
55 /* This function is not implemented on Windows.
56 * We really should short-circuit the call to these functions by
57 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
58 * in the rte_pci_driver flags.
63 /* Read PCI config space. */
65 rte_pci_read_config(const struct rte_pci_device *dev __rte_unused,
66 void *buf __rte_unused, size_t len __rte_unused,
67 off_t offset __rte_unused)
69 /* This function is not implemented on Windows.
70 * We really should short-circuit the call to these functions by
71 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
72 * in the rte_pci_driver flags.
77 /* Write PCI config space. */
79 rte_pci_write_config(const struct rte_pci_device *dev __rte_unused,
80 const void *buf __rte_unused, size_t len __rte_unused,
81 off_t offset __rte_unused)
83 /* This function is not implemented on Windows.
84 * We really should short-circuit the call to these functions by
85 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
86 * in the rte_pci_driver flags.
92 pci_device_iova_mode(const struct rte_pci_driver *pdrv __rte_unused,
93 const struct rte_pci_device *pdev __rte_unused)
95 /* This function is not implemented on Windows.
96 * We really should short-circuit the call to these functions by
97 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
98 * in the rte_pci_driver flags.
104 rte_pci_ioport_map(struct rte_pci_device *dev __rte_unused,
105 int bar __rte_unused, struct rte_pci_ioport *p __rte_unused)
107 /* This function is not implemented on Windows.
108 * We really should short-circuit the call to these functions by
109 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
110 * in the rte_pci_driver flags.
117 rte_pci_ioport_read(struct rte_pci_ioport *p __rte_unused,
118 void *data __rte_unused, size_t len __rte_unused,
119 off_t offset __rte_unused)
121 /* This function is not implemented on Windows.
122 * We really should short-circuit the call to these functions by
123 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
124 * in the rte_pci_driver flags.
129 rte_pci_ioport_unmap(struct rte_pci_ioport *p __rte_unused)
131 /* This function is not implemented on Windows.
132 * We really should short-circuit the call to these functions by
133 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
134 * in the rte_pci_driver flags.
140 pci_device_iommu_support_va(const struct rte_pci_device *dev __rte_unused)
142 /* This function is not implemented on Windows.
143 * We really should short-circuit the call to these functions by
144 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
145 * in the rte_pci_driver flags.
151 rte_pci_ioport_write(struct rte_pci_ioport *p __rte_unused,
152 const void *data __rte_unused, size_t len __rte_unused,
153 off_t offset __rte_unused)
155 /* This function is not implemented on Windows.
156 * We really should short-circuit the call to these functions by
157 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
158 * in the rte_pci_driver flags.
162 /* remap the PCI resource of a PCI device in anonymous virtual memory */
164 pci_uio_remap_resource(struct rte_pci_device *dev __rte_unused)
166 /* This function is not implemented on Windows.
167 * We really should short-circuit the call to these functions by
168 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
169 * in the rte_pci_driver flags.
175 get_device_pci_address(HDEVINFO dev_info,
176 PSP_DEVINFO_DATA device_info_data, struct rte_pci_addr *addr)
179 ULONG bus_num, dev_and_func;
181 res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
182 SPDRP_BUSNUMBER, NULL, (PBYTE)&bus_num, sizeof(bus_num), NULL);
185 "SetupDiGetDeviceRegistryProperty(SPDRP_BUSNUMBER)");
189 res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
190 SPDRP_ADDRESS, NULL, (PBYTE)&dev_and_func, sizeof(dev_and_func),
194 "SetupDiGetDeviceRegistryProperty(SPDRP_ADDRESS)");
200 addr->devid = dev_and_func >> 16;
201 addr->function = dev_and_func & 0xffff;
206 get_device_resource_info(HDEVINFO dev_info,
207 PSP_DEVINFO_DATA dev_info_data, struct rte_pci_device *dev)
209 DEVPROPTYPE property_type;
215 /* Get NUMA node using DEVPKEY_Device_Numa_Node */
216 res = SetupDiGetDevicePropertyW(dev_info, dev_info_data,
217 &DEVPKEY_Device_Numa_Node, &property_type,
218 (BYTE *)&numa_node, sizeof(numa_node), NULL, 0);
221 "SetupDiGetDevicePropertyW"
222 "(DEVPKEY_Device_Numa_Node)");
225 dev->device.numa_node = numa_node;
226 /* mem_resource - Unneeded for RTE_KDRV_NONE */
227 dev->mem_resource[0].phys_addr = 0;
228 dev->mem_resource[0].len = 0;
229 dev->mem_resource[0].addr = NULL;
232 /* kernel driver type is unsupported */
234 "Kernel driver type for PCI device " PCI_PRI_FMT ","
236 dev->addr.domain, dev->addr.bus,
237 dev->addr.devid, dev->addr.function);
241 return ERROR_SUCCESS;
245 * get string that contains the list of hardware IDs for a device
248 get_pci_hardware_id(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data,
249 char *pci_device_info, size_t pci_device_info_len)
253 /* Retrieve PCI device IDs */
254 res = SetupDiGetDeviceRegistryPropertyA(dev_info, device_info_data,
255 SPDRP_HARDWAREID, NULL, (BYTE *)pci_device_info,
256 pci_device_info_len, NULL);
259 "SetupDiGetDeviceRegistryPropertyA(SPDRP_HARDWAREID)");
267 * parse the SPDRP_HARDWAREID output and assign to rte_pci_id
270 parse_pci_hardware_id(const char *buf, struct rte_pci_id *pci_id)
273 uint16_t vendor_id, device_id, subvendor_id = 0;
275 ids = sscanf_s(buf, "PCI\\VEN_%x&DEV_%x&SUBSYS_%x", &vendor_id,
276 &device_id, &subvendor_id);
280 pci_id->vendor_id = vendor_id;
281 pci_id->device_id = device_id;
282 pci_id->subsystem_vendor_id = subvendor_id >> 16;
283 pci_id->subsystem_device_id = subvendor_id & 0xffff;
288 get_kernel_driver_type(struct rte_pci_device *dev)
291 * If another kernel driver is supported the relevant checking
292 * functions should be here
294 dev->kdrv = RTE_KDRV_NONE;
298 pci_scan_one(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data)
300 struct rte_pci_device *dev;
302 char pci_device_info[PATH_MAX];
303 struct rte_pci_addr addr;
304 struct rte_pci_id pci_id;
306 dev = malloc(sizeof(*dev));
310 memset(dev, 0, sizeof(*dev));
312 ret = get_pci_hardware_id(dev_info, device_info_data,
313 pci_device_info, PATH_MAX);
317 ret = parse_pci_hardware_id((const char *)&pci_device_info, &pci_id);
320 * We won't add this device, but we want to continue
321 * looking for supported devices
323 ret = ERROR_CONTINUE;
327 ret = get_device_pci_address(dev_info, device_info_data, &addr);
333 dev->max_vfs = 0; /* TODO: get max_vfs */
337 get_kernel_driver_type(dev);
340 if (get_device_resource_info(dev_info, device_info_data, dev)
345 /* device is valid, add in list (sorted) */
346 if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
347 rte_pci_add_device(dev);
349 struct rte_pci_device *dev2 = NULL;
352 TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
353 ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
356 } else if (ret < 0) {
357 rte_pci_insert_device(dev2, dev);
358 } else { /* already registered */
359 dev2->kdrv = dev->kdrv;
360 dev2->max_vfs = dev->max_vfs;
361 memmove(dev2->mem_resource, dev->mem_resource,
362 sizeof(dev->mem_resource));
367 rte_pci_add_device(dev);
378 * Scan the contents of the PCI bus
379 * and add all network class devices into the devices list.
385 DWORD device_index = 0, found_device = 0;
387 SP_DEVINFO_DATA device_info_data;
389 /* for debug purposes, PCI can be disabled */
390 if (!rte_eal_has_pci())
393 dev_info = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, TEXT("PCI"), NULL,
395 if (dev_info == INVALID_HANDLE_VALUE) {
396 RTE_LOG_WIN32_ERR("SetupDiGetClassDevs(pci_scan)");
397 RTE_LOG(ERR, EAL, "Unable to enumerate PCI devices.\n");
401 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
404 while (SetupDiEnumDeviceInfo(dev_info, device_index,
405 &device_info_data)) {
407 ret = pci_scan_one(dev_info, &device_info_data);
408 if (ret == ERROR_SUCCESS)
410 else if (ret != ERROR_CONTINUE)
413 memset(&device_info_data, 0, sizeof(SP_DEVINFO_DATA));
414 device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
417 RTE_LOG(DEBUG, EAL, "PCI scan found %lu devices\n", found_device);
420 if (dev_info != INVALID_HANDLE_VALUE)
421 SetupDiDestroyDeviceInfoList(dev_info);