133031608STal Shnaiderman /* SPDX-License-Identifier: BSD-3-Clause
233031608STal Shnaiderman * Copyright 2020 Mellanox Technologies, Ltd
333031608STal Shnaiderman */
4f1f6ebc0SWilliam Tu
5f1f6ebc0SWilliam Tu #include <sys/queue.h>
6f1f6ebc0SWilliam Tu
7b762221aSTal Shnaiderman #include <rte_windows.h>
833031608STal Shnaiderman #include <rte_errno.h>
933031608STal Shnaiderman #include <rte_log.h>
10b762221aSTal Shnaiderman #include <rte_eal.h>
11bf7cf1f9SPallavi Kadam #include <rte_memory.h>
121f37cb2bSDavid Marchand #include <rte_bus_pci.h>
1333031608STal Shnaiderman
1433031608STal Shnaiderman #include "private.h"
15c76ec01bSPallavi Kadam #include "pci_netuio.h"
1633031608STal Shnaiderman
17b762221aSTal Shnaiderman #include <devpkey.h>
186d10ddb4SDmitry Kozlyuk #include <regstr.h>
19b762221aSTal Shnaiderman
20de785ba0SDmitry Kozlyuk #if defined RTE_TOOLCHAIN_GCC && (__MINGW64_VERSION_MAJOR < 8)
21b762221aSTal Shnaiderman #include <devpropdef.h>
22b762221aSTal Shnaiderman DEFINE_DEVPROPKEY(DEVPKEY_Device_Numa_Node, 0x540b947e, 0x8b40, 0x45bc,
23b762221aSTal Shnaiderman 0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 3);
24b762221aSTal Shnaiderman #endif
25b762221aSTal Shnaiderman
26b762221aSTal Shnaiderman /*
27b762221aSTal Shnaiderman * This code is used to simulate a PCI probe by parsing information in
28b762221aSTal Shnaiderman * the registry hive for PCI devices.
29b762221aSTal Shnaiderman */
30b762221aSTal Shnaiderman
31d9b02d2bSNick Connolly /* Class ID consists of hexadecimal digits */
32d9b02d2bSNick Connolly #define RTE_PCI_DRV_CLASSID_DIGIT "0123456789abcdefABCDEF"
33d9b02d2bSNick Connolly
34de04405bSPallavi Kadam /* Some of the functions below are not implemented on Windows,
3533031608STal Shnaiderman * but need to be defined for compilation purposes
3633031608STal Shnaiderman */
3733031608STal Shnaiderman
3833031608STal Shnaiderman /* Map pci device */
3933031608STal Shnaiderman int
rte_pci_map_device(struct rte_pci_device * dev)40de04405bSPallavi Kadam rte_pci_map_device(struct rte_pci_device *dev)
4133031608STal Shnaiderman {
42de04405bSPallavi Kadam /* Only return success for devices bound to netuio.
43de04405bSPallavi Kadam * Devices that are bound to netuio are mapped at
44de04405bSPallavi Kadam * the bus probing stage.
4533031608STal Shnaiderman */
4641e026c1SThomas Monjalon if (dev->kdrv == RTE_PCI_KDRV_NET_UIO)
4733031608STal Shnaiderman return 0;
48de04405bSPallavi Kadam else
49de04405bSPallavi Kadam return -1;
5033031608STal Shnaiderman }
5133031608STal Shnaiderman
5233031608STal Shnaiderman /* Unmap pci device */
5333031608STal Shnaiderman void
rte_pci_unmap_device(struct rte_pci_device * dev __rte_unused)5433031608STal Shnaiderman rte_pci_unmap_device(struct rte_pci_device *dev __rte_unused)
5533031608STal Shnaiderman {
5633031608STal Shnaiderman /* This function is not implemented on Windows.
5733031608STal Shnaiderman * We really should short-circuit the call to these functions by
5833031608STal Shnaiderman * clearing the RTE_PCI_DRV_NEED_MAPPING flag
5933031608STal Shnaiderman * in the rte_pci_driver flags.
6033031608STal Shnaiderman */
6133031608STal Shnaiderman }
6233031608STal Shnaiderman
6333031608STal Shnaiderman /* Read PCI config space. */
6433031608STal Shnaiderman int
rte_pci_read_config(const struct rte_pci_device * dev __rte_unused,void * buf __rte_unused,size_t len __rte_unused,off_t offset __rte_unused)6533031608STal Shnaiderman rte_pci_read_config(const struct rte_pci_device *dev __rte_unused,
6633031608STal Shnaiderman void *buf __rte_unused, size_t len __rte_unused,
6733031608STal Shnaiderman off_t offset __rte_unused)
6833031608STal Shnaiderman {
6933031608STal Shnaiderman /* This function is not implemented on Windows.
7033031608STal Shnaiderman * We really should short-circuit the call to these functions by
7133031608STal Shnaiderman * clearing the RTE_PCI_DRV_NEED_MAPPING flag
7233031608STal Shnaiderman * in the rte_pci_driver flags.
7333031608STal Shnaiderman */
7433031608STal Shnaiderman return 0;
7533031608STal Shnaiderman }
7633031608STal Shnaiderman
7733031608STal Shnaiderman /* Write PCI config space. */
7833031608STal Shnaiderman int
rte_pci_write_config(const struct rte_pci_device * dev __rte_unused,const void * buf __rte_unused,size_t len __rte_unused,off_t offset __rte_unused)7933031608STal Shnaiderman rte_pci_write_config(const struct rte_pci_device *dev __rte_unused,
8033031608STal Shnaiderman const void *buf __rte_unused, size_t len __rte_unused,
8133031608STal Shnaiderman off_t offset __rte_unused)
8233031608STal Shnaiderman {
8333031608STal Shnaiderman /* This function is not implemented on Windows.
8433031608STal Shnaiderman * We really should short-circuit the call to these functions by
8533031608STal Shnaiderman * clearing the RTE_PCI_DRV_NEED_MAPPING flag
8633031608STal Shnaiderman * in the rte_pci_driver flags.
8733031608STal Shnaiderman */
8833031608STal Shnaiderman return 0;
8933031608STal Shnaiderman }
9033031608STal Shnaiderman
912125ed73SChenbo Xia /* Read PCI MMIO space. */
922125ed73SChenbo Xia int
rte_pci_mmio_read(const struct rte_pci_device * dev,int bar,void * buf,size_t len,off_t offset)932125ed73SChenbo Xia rte_pci_mmio_read(const struct rte_pci_device *dev, int bar,
942125ed73SChenbo Xia void *buf, size_t len, off_t offset)
952125ed73SChenbo Xia {
962125ed73SChenbo Xia if (bar >= PCI_MAX_RESOURCE || dev->mem_resource[bar].addr == NULL ||
972125ed73SChenbo Xia (uint64_t)offset + len > dev->mem_resource[bar].len)
982125ed73SChenbo Xia return -1;
992125ed73SChenbo Xia memcpy(buf, (uint8_t *)dev->mem_resource[bar].addr + offset, len);
1002125ed73SChenbo Xia return len;
1012125ed73SChenbo Xia }
1022125ed73SChenbo Xia
1032125ed73SChenbo Xia /* Write PCI MMIO space. */
1042125ed73SChenbo Xia int
rte_pci_mmio_write(const struct rte_pci_device * dev,int bar,const void * buf,size_t len,off_t offset)1052125ed73SChenbo Xia rte_pci_mmio_write(const struct rte_pci_device *dev, int bar,
1062125ed73SChenbo Xia const void *buf, size_t len, off_t offset)
1072125ed73SChenbo Xia {
1082125ed73SChenbo Xia if (bar >= PCI_MAX_RESOURCE || dev->mem_resource[bar].addr == NULL ||
1092125ed73SChenbo Xia (uint64_t)offset + len > dev->mem_resource[bar].len)
1102125ed73SChenbo Xia return -1;
1112125ed73SChenbo Xia memcpy((uint8_t *)dev->mem_resource[bar].addr + offset, buf, len);
1122125ed73SChenbo Xia return len;
1132125ed73SChenbo Xia }
1142125ed73SChenbo Xia
11533031608STal Shnaiderman enum rte_iova_mode
pci_device_iova_mode(const struct rte_pci_driver * pdrv __rte_unused,const struct rte_pci_device * pdev __rte_unused)11633031608STal Shnaiderman pci_device_iova_mode(const struct rte_pci_driver *pdrv __rte_unused,
11733031608STal Shnaiderman const struct rte_pci_device *pdev __rte_unused)
11833031608STal Shnaiderman {
11933031608STal Shnaiderman /* This function is not implemented on Windows.
12033031608STal Shnaiderman * We really should short-circuit the call to these functions by
12133031608STal Shnaiderman * clearing the RTE_PCI_DRV_NEED_MAPPING flag
12233031608STal Shnaiderman * in the rte_pci_driver flags.
12333031608STal Shnaiderman */
12433031608STal Shnaiderman return RTE_IOVA_DC;
12533031608STal Shnaiderman }
12633031608STal Shnaiderman
12733031608STal Shnaiderman int
rte_pci_ioport_map(struct rte_pci_device * dev __rte_unused,int bar __rte_unused,struct rte_pci_ioport * p __rte_unused)12833031608STal Shnaiderman rte_pci_ioport_map(struct rte_pci_device *dev __rte_unused,
12933031608STal Shnaiderman int bar __rte_unused, struct rte_pci_ioport *p __rte_unused)
13033031608STal Shnaiderman {
13133031608STal Shnaiderman /* This function is not implemented on Windows.
13233031608STal Shnaiderman * We really should short-circuit the call to these functions by
13333031608STal Shnaiderman * clearing the RTE_PCI_DRV_NEED_MAPPING flag
13433031608STal Shnaiderman * in the rte_pci_driver flags.
13533031608STal Shnaiderman */
13633031608STal Shnaiderman return -1;
13733031608STal Shnaiderman }
13833031608STal Shnaiderman
13933031608STal Shnaiderman
14033031608STal Shnaiderman void
rte_pci_ioport_read(struct rte_pci_ioport * p __rte_unused,void * data __rte_unused,size_t len __rte_unused,off_t offset __rte_unused)14133031608STal Shnaiderman rte_pci_ioport_read(struct rte_pci_ioport *p __rte_unused,
14233031608STal Shnaiderman void *data __rte_unused, size_t len __rte_unused,
14333031608STal Shnaiderman off_t offset __rte_unused)
14433031608STal Shnaiderman {
14533031608STal Shnaiderman /* This function is not implemented on Windows.
14633031608STal Shnaiderman * We really should short-circuit the call to these functions by
14733031608STal Shnaiderman * clearing the RTE_PCI_DRV_NEED_MAPPING flag
14833031608STal Shnaiderman * in the rte_pci_driver flags.
14933031608STal Shnaiderman */
15033031608STal Shnaiderman }
15133031608STal Shnaiderman
15233031608STal Shnaiderman int
rte_pci_ioport_unmap(struct rte_pci_ioport * p __rte_unused)15333031608STal Shnaiderman rte_pci_ioport_unmap(struct rte_pci_ioport *p __rte_unused)
15433031608STal Shnaiderman {
15533031608STal Shnaiderman /* This function is not implemented on Windows.
15633031608STal Shnaiderman * We really should short-circuit the call to these functions by
15733031608STal Shnaiderman * clearing the RTE_PCI_DRV_NEED_MAPPING flag
15833031608STal Shnaiderman * in the rte_pci_driver flags.
15933031608STal Shnaiderman */
16033031608STal Shnaiderman return -1;
16133031608STal Shnaiderman }
16233031608STal Shnaiderman
16333031608STal Shnaiderman bool
pci_device_iommu_support_va(const struct rte_pci_device * dev __rte_unused)16433031608STal Shnaiderman pci_device_iommu_support_va(const struct rte_pci_device *dev __rte_unused)
16533031608STal Shnaiderman {
16633031608STal Shnaiderman /* This function is not implemented on Windows.
16733031608STal Shnaiderman * We really should short-circuit the call to these functions by
16833031608STal Shnaiderman * clearing the RTE_PCI_DRV_NEED_MAPPING flag
16933031608STal Shnaiderman * in the rte_pci_driver flags.
17033031608STal Shnaiderman */
17133031608STal Shnaiderman return false;
17233031608STal Shnaiderman }
17333031608STal Shnaiderman
17433031608STal Shnaiderman void
rte_pci_ioport_write(struct rte_pci_ioport * p __rte_unused,const void * data __rte_unused,size_t len __rte_unused,off_t offset __rte_unused)17533031608STal Shnaiderman rte_pci_ioport_write(struct rte_pci_ioport *p __rte_unused,
17633031608STal Shnaiderman const void *data __rte_unused, size_t len __rte_unused,
17733031608STal Shnaiderman off_t offset __rte_unused)
17833031608STal Shnaiderman {
17933031608STal Shnaiderman /* This function is not implemented on Windows.
18033031608STal Shnaiderman * We really should short-circuit the call to these functions by
18133031608STal Shnaiderman * clearing the RTE_PCI_DRV_NEED_MAPPING flag
18233031608STal Shnaiderman * in the rte_pci_driver flags.
18333031608STal Shnaiderman */
18433031608STal Shnaiderman }
18533031608STal Shnaiderman
18633031608STal Shnaiderman /* remap the PCI resource of a PCI device in anonymous virtual memory */
18733031608STal Shnaiderman int
pci_uio_remap_resource(struct rte_pci_device * dev __rte_unused)18833031608STal Shnaiderman pci_uio_remap_resource(struct rte_pci_device *dev __rte_unused)
18933031608STal Shnaiderman {
19033031608STal Shnaiderman /* This function is not implemented on Windows.
19133031608STal Shnaiderman * We really should short-circuit the call to these functions by
19233031608STal Shnaiderman * clearing the RTE_PCI_DRV_NEED_MAPPING flag
19333031608STal Shnaiderman * in the rte_pci_driver flags.
19433031608STal Shnaiderman */
19533031608STal Shnaiderman return -1;
19633031608STal Shnaiderman }
197b762221aSTal Shnaiderman
198b762221aSTal Shnaiderman static int
get_device_pci_address(HDEVINFO dev_info,PSP_DEVINFO_DATA device_info_data,struct rte_pci_addr * addr)199b762221aSTal Shnaiderman get_device_pci_address(HDEVINFO dev_info,
200b762221aSTal Shnaiderman PSP_DEVINFO_DATA device_info_data, struct rte_pci_addr *addr)
201b762221aSTal Shnaiderman {
202b762221aSTal Shnaiderman BOOL res;
203b762221aSTal Shnaiderman ULONG bus_num, dev_and_func;
204b762221aSTal Shnaiderman
205b762221aSTal Shnaiderman res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
206b762221aSTal Shnaiderman SPDRP_BUSNUMBER, NULL, (PBYTE)&bus_num, sizeof(bus_num), NULL);
207b762221aSTal Shnaiderman if (!res) {
208b762221aSTal Shnaiderman RTE_LOG_WIN32_ERR(
209b762221aSTal Shnaiderman "SetupDiGetDeviceRegistryProperty(SPDRP_BUSNUMBER)");
210b762221aSTal Shnaiderman return -1;
211b762221aSTal Shnaiderman }
212b762221aSTal Shnaiderman
213b762221aSTal Shnaiderman res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
214b762221aSTal Shnaiderman SPDRP_ADDRESS, NULL, (PBYTE)&dev_and_func, sizeof(dev_and_func),
215b762221aSTal Shnaiderman NULL);
216b762221aSTal Shnaiderman if (!res) {
217b762221aSTal Shnaiderman RTE_LOG_WIN32_ERR(
218b762221aSTal Shnaiderman "SetupDiGetDeviceRegistryProperty(SPDRP_ADDRESS)");
219b762221aSTal Shnaiderman return -1;
220b762221aSTal Shnaiderman }
221b762221aSTal Shnaiderman
222c12b1488STal Shnaiderman addr->domain = (bus_num >> 8) & 0xffff;
223c3adf814STal Shnaiderman addr->bus = bus_num & 0xff;
224b762221aSTal Shnaiderman addr->devid = dev_and_func >> 16;
225b762221aSTal Shnaiderman addr->function = dev_and_func & 0xffff;
226b762221aSTal Shnaiderman return 0;
227b762221aSTal Shnaiderman }
228b762221aSTal Shnaiderman
229b762221aSTal Shnaiderman static int
get_device_resource_info(HDEVINFO dev_info,PSP_DEVINFO_DATA dev_info_data,struct rte_pci_device * dev)230b762221aSTal Shnaiderman get_device_resource_info(HDEVINFO dev_info,
231b762221aSTal Shnaiderman PSP_DEVINFO_DATA dev_info_data, struct rte_pci_device *dev)
232b762221aSTal Shnaiderman {
233b762221aSTal Shnaiderman DEVPROPTYPE property_type;
234b762221aSTal Shnaiderman DWORD numa_node;
235b762221aSTal Shnaiderman BOOL res;
236c76ec01bSPallavi Kadam int ret;
237b762221aSTal Shnaiderman
238b762221aSTal Shnaiderman switch (dev->kdrv) {
23941e026c1SThomas Monjalon case RTE_PCI_KDRV_UNKNOWN:
24041e026c1SThomas Monjalon /* bifurcated driver case - mem_resource is unneeded */
241b762221aSTal Shnaiderman dev->mem_resource[0].phys_addr = 0;
242b762221aSTal Shnaiderman dev->mem_resource[0].len = 0;
243b762221aSTal Shnaiderman dev->mem_resource[0].addr = NULL;
244b762221aSTal Shnaiderman break;
24541e026c1SThomas Monjalon case RTE_PCI_KDRV_NET_UIO:
24641e026c1SThomas Monjalon /* get device info from NetUIO kernel driver */
247c76ec01bSPallavi Kadam ret = get_netuio_device_info(dev_info, dev_info_data, dev);
248c76ec01bSPallavi Kadam if (ret != 0) {
249*849f773bSDavid Marchand PCI_LOG(DEBUG, "Could not retrieve device info for PCI device "
250c76ec01bSPallavi Kadam PCI_PRI_FMT,
251c76ec01bSPallavi Kadam dev->addr.domain, dev->addr.bus,
252c76ec01bSPallavi Kadam dev->addr.devid, dev->addr.function);
253c76ec01bSPallavi Kadam return ret;
254c76ec01bSPallavi Kadam }
255c76ec01bSPallavi Kadam break;
256b762221aSTal Shnaiderman default:
257b762221aSTal Shnaiderman /* kernel driver type is unsupported */
258*849f773bSDavid Marchand PCI_LOG(DEBUG, "Kernel driver type for PCI device " PCI_PRI_FMT ", is unsupported",
259b762221aSTal Shnaiderman dev->addr.domain, dev->addr.bus,
260b762221aSTal Shnaiderman dev->addr.devid, dev->addr.function);
261b762221aSTal Shnaiderman return -1;
262b762221aSTal Shnaiderman }
263b762221aSTal Shnaiderman
264c76ec01bSPallavi Kadam /* Get NUMA node using DEVPKEY_Device_Numa_Node */
2653c6e5810SPallavi Kadam dev->device.numa_node = SOCKET_ID_ANY;
266c76ec01bSPallavi Kadam res = SetupDiGetDevicePropertyW(dev_info, dev_info_data,
267c76ec01bSPallavi Kadam &DEVPKEY_Device_Numa_Node, &property_type,
268c76ec01bSPallavi Kadam (BYTE *)&numa_node, sizeof(numa_node), NULL, 0);
269c76ec01bSPallavi Kadam if (!res) {
270ac7c98d0STal Shnaiderman DWORD error = GetLastError();
271ac7c98d0STal Shnaiderman if (error == ERROR_NOT_FOUND) {
272ac7c98d0STal Shnaiderman /* On older CPUs, NUMA is not bound to PCIe locality. */
273ac7c98d0STal Shnaiderman return ERROR_SUCCESS;
274ac7c98d0STal Shnaiderman }
275c76ec01bSPallavi Kadam RTE_LOG_WIN32_ERR("SetupDiGetDevicePropertyW"
276c76ec01bSPallavi Kadam "(DEVPKEY_Device_Numa_Node)");
277c76ec01bSPallavi Kadam return -1;
278c76ec01bSPallavi Kadam }
279c76ec01bSPallavi Kadam dev->device.numa_node = numa_node;
280c76ec01bSPallavi Kadam
281b762221aSTal Shnaiderman return ERROR_SUCCESS;
282b762221aSTal Shnaiderman }
283b762221aSTal Shnaiderman
284b762221aSTal Shnaiderman /*
285b762221aSTal Shnaiderman * get string that contains the list of hardware IDs for a device
286b762221aSTal Shnaiderman */
287b762221aSTal Shnaiderman static int
get_pci_hardware_id(HDEVINFO dev_info,PSP_DEVINFO_DATA device_info_data,char * pci_device_info,size_t pci_device_info_len)288b762221aSTal Shnaiderman get_pci_hardware_id(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data,
289b762221aSTal Shnaiderman char *pci_device_info, size_t pci_device_info_len)
290b762221aSTal Shnaiderman {
291b762221aSTal Shnaiderman BOOL res;
292b762221aSTal Shnaiderman
293b762221aSTal Shnaiderman /* Retrieve PCI device IDs */
294b762221aSTal Shnaiderman res = SetupDiGetDeviceRegistryPropertyA(dev_info, device_info_data,
295b762221aSTal Shnaiderman SPDRP_HARDWAREID, NULL, (BYTE *)pci_device_info,
296b762221aSTal Shnaiderman pci_device_info_len, NULL);
297b762221aSTal Shnaiderman if (!res) {
298b762221aSTal Shnaiderman RTE_LOG_WIN32_ERR(
299b762221aSTal Shnaiderman "SetupDiGetDeviceRegistryPropertyA(SPDRP_HARDWAREID)");
300b762221aSTal Shnaiderman return -1;
301b762221aSTal Shnaiderman }
302b762221aSTal Shnaiderman
303b762221aSTal Shnaiderman return 0;
304b762221aSTal Shnaiderman }
305b762221aSTal Shnaiderman
306b762221aSTal Shnaiderman /*
307b762221aSTal Shnaiderman * parse the SPDRP_HARDWAREID output and assign to rte_pci_id
308d9b02d2bSNick Connolly *
309d9b02d2bSNick Connolly * A list of the device identification string formats can be found at:
310d9b02d2bSNick Connolly * https://docs.microsoft.com/en-us/windows-hardware/drivers/install/identifiers-for-pci-devices
311b762221aSTal Shnaiderman */
312b762221aSTal Shnaiderman static int
parse_pci_hardware_id(const char * buf,struct rte_pci_id * pci_id)313b762221aSTal Shnaiderman parse_pci_hardware_id(const char *buf, struct rte_pci_id *pci_id)
314b762221aSTal Shnaiderman {
315b762221aSTal Shnaiderman int ids = 0;
3162dceae68STal Shnaiderman uint16_t vendor_id, device_id;
317d9b02d2bSNick Connolly uint32_t subvendor_id = 0, class_id = 0;
318d9b02d2bSNick Connolly const char *cp;
319b762221aSTal Shnaiderman
3202dceae68STal Shnaiderman ids = sscanf_s(buf, "PCI\\VEN_%" PRIx16 "&DEV_%" PRIx16 "&SUBSYS_%"
3212dceae68STal Shnaiderman PRIx32, &vendor_id, &device_id, &subvendor_id);
322b762221aSTal Shnaiderman if (ids != 3)
323b762221aSTal Shnaiderman return -1;
324b762221aSTal Shnaiderman
325d9b02d2bSNick Connolly /* Try and find PCI class ID */
326d9b02d2bSNick Connolly for (cp = buf; !(cp[0] == 0 && cp[1] == 0); cp++)
327d9b02d2bSNick Connolly if (*cp == '&' && sscanf_s(cp,
328d9b02d2bSNick Connolly "&CC_%" PRIx32, &class_id) == 1) {
329d9b02d2bSNick Connolly /*
330d9b02d2bSNick Connolly * If the Programming Interface code is not specified,
331d9b02d2bSNick Connolly * assume that it is zero.
332d9b02d2bSNick Connolly */
333d9b02d2bSNick Connolly if (strspn(cp + 4, RTE_PCI_DRV_CLASSID_DIGIT) == 4)
334d9b02d2bSNick Connolly class_id <<= 8;
335d9b02d2bSNick Connolly break;
336d9b02d2bSNick Connolly }
337d9b02d2bSNick Connolly
338b762221aSTal Shnaiderman pci_id->vendor_id = vendor_id;
339b762221aSTal Shnaiderman pci_id->device_id = device_id;
3402dceae68STal Shnaiderman pci_id->subsystem_device_id = subvendor_id >> 16;
3412dceae68STal Shnaiderman pci_id->subsystem_vendor_id = subvendor_id & 0xffff;
342d9b02d2bSNick Connolly pci_id->class_id = class_id;
343b762221aSTal Shnaiderman return 0;
344b762221aSTal Shnaiderman }
345b762221aSTal Shnaiderman
346b762221aSTal Shnaiderman static void
set_kernel_driver_type(PSP_DEVINFO_DATA device_info_data,struct rte_pci_device * dev)347c76ec01bSPallavi Kadam set_kernel_driver_type(PSP_DEVINFO_DATA device_info_data,
348c76ec01bSPallavi Kadam struct rte_pci_device *dev)
349b762221aSTal Shnaiderman {
350c76ec01bSPallavi Kadam /* set kernel driver type based on device class */
351c76ec01bSPallavi Kadam if (IsEqualGUID(&(device_info_data->ClassGuid), &GUID_DEVCLASS_NETUIO))
35241e026c1SThomas Monjalon dev->kdrv = RTE_PCI_KDRV_NET_UIO;
353c76ec01bSPallavi Kadam else
35441e026c1SThomas Monjalon dev->kdrv = RTE_PCI_KDRV_UNKNOWN;
355b762221aSTal Shnaiderman }
356b762221aSTal Shnaiderman
357b762221aSTal Shnaiderman static int
pci_scan_one(HDEVINFO dev_info,PSP_DEVINFO_DATA device_info_data)358b762221aSTal Shnaiderman pci_scan_one(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data)
359b762221aSTal Shnaiderman {
36087a02023SChenbo Xia struct rte_pci_device_internal *pdev = NULL;
3616857cb63SKhoa To struct rte_pci_device *dev = NULL;
362b762221aSTal Shnaiderman int ret = -1;
3636d10ddb4SDmitry Kozlyuk char pci_device_info[REGSTR_VAL_MAX_HCID_LEN];
364b762221aSTal Shnaiderman struct rte_pci_addr addr;
365b762221aSTal Shnaiderman struct rte_pci_id pci_id;
366b762221aSTal Shnaiderman
3676857cb63SKhoa To ret = get_device_pci_address(dev_info, device_info_data, &addr);
3686857cb63SKhoa To if (ret != 0)
369b762221aSTal Shnaiderman goto end;
370b762221aSTal Shnaiderman
3716857cb63SKhoa To if (rte_pci_ignore_device(&addr)) {
3726857cb63SKhoa To /*
3736857cb63SKhoa To * We won't add this device, but we want to continue
3746857cb63SKhoa To * looking for supported devices
3756857cb63SKhoa To */
3766857cb63SKhoa To ret = ERROR_CONTINUE;
3776857cb63SKhoa To goto end;
3786857cb63SKhoa To }
379b762221aSTal Shnaiderman
380b762221aSTal Shnaiderman ret = get_pci_hardware_id(dev_info, device_info_data,
3816d10ddb4SDmitry Kozlyuk pci_device_info, sizeof(pci_device_info));
382b762221aSTal Shnaiderman if (ret != 0)
383b762221aSTal Shnaiderman goto end;
384b762221aSTal Shnaiderman
385b762221aSTal Shnaiderman ret = parse_pci_hardware_id((const char *)&pci_device_info, &pci_id);
386b762221aSTal Shnaiderman if (ret != 0) {
387b762221aSTal Shnaiderman /*
388b762221aSTal Shnaiderman * We won't add this device, but we want to continue
389b762221aSTal Shnaiderman * looking for supported devices
390b762221aSTal Shnaiderman */
391b762221aSTal Shnaiderman ret = ERROR_CONTINUE;
392b762221aSTal Shnaiderman goto end;
393b762221aSTal Shnaiderman }
394b762221aSTal Shnaiderman
39587a02023SChenbo Xia pdev = malloc(sizeof(*pdev));
39687a02023SChenbo Xia if (pdev == NULL) {
397*849f773bSDavid Marchand PCI_LOG(ERR, "Cannot allocate memory for internal pci device");
398b762221aSTal Shnaiderman goto end;
39987a02023SChenbo Xia }
400b762221aSTal Shnaiderman
40187a02023SChenbo Xia memset(pdev, 0, sizeof(*pdev));
40287a02023SChenbo Xia dev = &pdev->device;
4036857cb63SKhoa To
404d9b02d2bSNick Connolly dev->device.bus = &rte_pci_bus.bus;
405b762221aSTal Shnaiderman dev->addr = addr;
406b762221aSTal Shnaiderman dev->id = pci_id;
407b762221aSTal Shnaiderman dev->max_vfs = 0; /* TODO: get max_vfs */
408b762221aSTal Shnaiderman
4098f4de2dbSDavid Marchand pci_common_set(dev);
410b762221aSTal Shnaiderman
411c76ec01bSPallavi Kadam set_kernel_driver_type(device_info_data, dev);
412b762221aSTal Shnaiderman
413b762221aSTal Shnaiderman /* get resources */
414b762221aSTal Shnaiderman if (get_device_resource_info(dev_info, device_info_data, dev)
415b762221aSTal Shnaiderman != ERROR_SUCCESS) {
416b762221aSTal Shnaiderman goto end;
417b762221aSTal Shnaiderman }
418b762221aSTal Shnaiderman
419b762221aSTal Shnaiderman /* device is valid, add in list (sorted) */
420b762221aSTal Shnaiderman if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
421b762221aSTal Shnaiderman rte_pci_add_device(dev);
422b762221aSTal Shnaiderman } else {
423b762221aSTal Shnaiderman struct rte_pci_device *dev2 = NULL;
424b762221aSTal Shnaiderman int ret;
425b762221aSTal Shnaiderman
426b762221aSTal Shnaiderman TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
427b762221aSTal Shnaiderman ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
428b762221aSTal Shnaiderman if (ret > 0) {
429b762221aSTal Shnaiderman continue;
430b762221aSTal Shnaiderman } else if (ret < 0) {
431b762221aSTal Shnaiderman rte_pci_insert_device(dev2, dev);
432b762221aSTal Shnaiderman } else { /* already registered */
433b762221aSTal Shnaiderman dev2->kdrv = dev->kdrv;
434b762221aSTal Shnaiderman dev2->max_vfs = dev->max_vfs;
435b762221aSTal Shnaiderman memmove(dev2->mem_resource, dev->mem_resource,
436b762221aSTal Shnaiderman sizeof(dev->mem_resource));
43787a02023SChenbo Xia pci_free(pdev);
438b762221aSTal Shnaiderman }
439b762221aSTal Shnaiderman return 0;
440b762221aSTal Shnaiderman }
441b762221aSTal Shnaiderman rte_pci_add_device(dev);
442b762221aSTal Shnaiderman }
443b762221aSTal Shnaiderman
444b762221aSTal Shnaiderman return 0;
445b762221aSTal Shnaiderman end:
44687a02023SChenbo Xia pci_free(pdev);
447b762221aSTal Shnaiderman return ret;
448b762221aSTal Shnaiderman }
449b762221aSTal Shnaiderman
45033031608STal Shnaiderman /*
45133031608STal Shnaiderman * Scan the contents of the PCI bus
45233031608STal Shnaiderman * and add all network class devices into the devices list.
45333031608STal Shnaiderman */
45433031608STal Shnaiderman int
rte_pci_scan(void)45533031608STal Shnaiderman rte_pci_scan(void)
45633031608STal Shnaiderman {
457b762221aSTal Shnaiderman int ret = -1;
458b762221aSTal Shnaiderman DWORD device_index = 0, found_device = 0;
459b762221aSTal Shnaiderman HDEVINFO dev_info;
460b762221aSTal Shnaiderman SP_DEVINFO_DATA device_info_data;
461b762221aSTal Shnaiderman
462b762221aSTal Shnaiderman /* for debug purposes, PCI can be disabled */
463b762221aSTal Shnaiderman if (!rte_eal_has_pci())
46433031608STal Shnaiderman return 0;
465b762221aSTal Shnaiderman
466c76ec01bSPallavi Kadam dev_info = SetupDiGetClassDevs(NULL, TEXT("PCI"), NULL,
467c76ec01bSPallavi Kadam DIGCF_PRESENT | DIGCF_ALLCLASSES);
468b762221aSTal Shnaiderman if (dev_info == INVALID_HANDLE_VALUE) {
469b762221aSTal Shnaiderman RTE_LOG_WIN32_ERR("SetupDiGetClassDevs(pci_scan)");
470*849f773bSDavid Marchand PCI_LOG(ERR, "Unable to enumerate PCI devices.");
471b762221aSTal Shnaiderman goto end;
472b762221aSTal Shnaiderman }
473b762221aSTal Shnaiderman
474b762221aSTal Shnaiderman device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
475b762221aSTal Shnaiderman device_index = 0;
476b762221aSTal Shnaiderman
477b762221aSTal Shnaiderman while (SetupDiEnumDeviceInfo(dev_info, device_index,
478b762221aSTal Shnaiderman &device_info_data)) {
479b762221aSTal Shnaiderman device_index++;
480c76ec01bSPallavi Kadam /* we only want to enumerate net & netuio class devices */
481c76ec01bSPallavi Kadam if (IsEqualGUID(&(device_info_data.ClassGuid),
482c76ec01bSPallavi Kadam &GUID_DEVCLASS_NET) ||
483c76ec01bSPallavi Kadam IsEqualGUID(&(device_info_data.ClassGuid),
484c76ec01bSPallavi Kadam &GUID_DEVCLASS_NETUIO)) {
485b762221aSTal Shnaiderman ret = pci_scan_one(dev_info, &device_info_data);
486b762221aSTal Shnaiderman if (ret == ERROR_SUCCESS)
487b762221aSTal Shnaiderman found_device++;
488b762221aSTal Shnaiderman else if (ret != ERROR_CONTINUE)
489b762221aSTal Shnaiderman goto end;
490c76ec01bSPallavi Kadam }
491b762221aSTal Shnaiderman memset(&device_info_data, 0, sizeof(SP_DEVINFO_DATA));
492b762221aSTal Shnaiderman device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
493b762221aSTal Shnaiderman }
494b762221aSTal Shnaiderman
495*849f773bSDavid Marchand PCI_LOG(DEBUG, "PCI scan found %lu devices", found_device);
496b762221aSTal Shnaiderman ret = 0;
497b762221aSTal Shnaiderman end:
498b762221aSTal Shnaiderman if (dev_info != INVALID_HANDLE_VALUE)
499b762221aSTal Shnaiderman SetupDiDestroyDeviceInfoList(dev_info);
500b762221aSTal Shnaiderman
501b762221aSTal Shnaiderman return ret;
50233031608STal Shnaiderman }
503