xref: /dpdk/drivers/bus/pci/windows/pci.c (revision c3adf8144a172902b51d273eca2765a1681b5cc4)
133031608STal Shnaiderman /* SPDX-License-Identifier: BSD-3-Clause
233031608STal Shnaiderman  * Copyright 2020 Mellanox Technologies, Ltd
333031608STal Shnaiderman  */
4b762221aSTal Shnaiderman #include <rte_windows.h>
533031608STal Shnaiderman #include <rte_errno.h>
633031608STal Shnaiderman #include <rte_log.h>
733031608STal Shnaiderman #include <rte_eal_memconfig.h>
8b762221aSTal Shnaiderman #include <rte_eal.h>
933031608STal Shnaiderman 
1033031608STal Shnaiderman #include "private.h"
1133031608STal Shnaiderman 
12b762221aSTal Shnaiderman #include <devpkey.h>
13b762221aSTal Shnaiderman 
14b762221aSTal Shnaiderman #ifdef RTE_TOOLCHAIN_GCC
15b762221aSTal Shnaiderman #include <devpropdef.h>
16b762221aSTal Shnaiderman DEFINE_DEVPROPKEY(DEVPKEY_Device_Numa_Node, 0x540b947e, 0x8b40, 0x45bc,
17b762221aSTal Shnaiderman 	0xa8, 0xa2, 0x6a, 0x0b, 0x89, 0x4c, 0xbd, 0xa2, 3);
18b762221aSTal Shnaiderman #endif
19b762221aSTal Shnaiderman 
20b762221aSTal Shnaiderman /*
21b762221aSTal Shnaiderman  * This code is used to simulate a PCI probe by parsing information in
22b762221aSTal Shnaiderman  * the registry hive for PCI devices.
23b762221aSTal Shnaiderman  */
24b762221aSTal Shnaiderman 
2533031608STal Shnaiderman /* The functions below are not implemented on Windows,
2633031608STal Shnaiderman  * but need to be defined for compilation purposes
2733031608STal Shnaiderman  */
2833031608STal Shnaiderman 
2933031608STal Shnaiderman /* Map pci device */
3033031608STal Shnaiderman int
3133031608STal Shnaiderman rte_pci_map_device(struct rte_pci_device *dev __rte_unused)
3233031608STal Shnaiderman {
3333031608STal Shnaiderman 	/* This function is not implemented on Windows.
3433031608STal Shnaiderman 	 * We really should short-circuit the call to these functions by
3533031608STal Shnaiderman 	 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
3633031608STal Shnaiderman 	 * in the rte_pci_driver flags.
3733031608STal Shnaiderman 	 */
3833031608STal Shnaiderman 	return 0;
3933031608STal Shnaiderman }
4033031608STal Shnaiderman 
4133031608STal Shnaiderman /* Unmap pci device */
4233031608STal Shnaiderman void
4333031608STal Shnaiderman rte_pci_unmap_device(struct rte_pci_device *dev __rte_unused)
4433031608STal Shnaiderman {
4533031608STal Shnaiderman 	/* This function is not implemented on Windows.
4633031608STal Shnaiderman 	 * We really should short-circuit the call to these functions by
4733031608STal Shnaiderman 	 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
4833031608STal Shnaiderman 	 * in the rte_pci_driver flags.
4933031608STal Shnaiderman 	 */
5033031608STal Shnaiderman }
5133031608STal Shnaiderman 
5233031608STal Shnaiderman int
5333031608STal Shnaiderman pci_update_device(const struct rte_pci_addr *addr __rte_unused)
5433031608STal Shnaiderman {
5533031608STal Shnaiderman 	/* This function is not implemented on Windows.
5633031608STal Shnaiderman 	 * We really should short-circuit the call to these functions by
5733031608STal Shnaiderman 	 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
5833031608STal Shnaiderman 	 * in the rte_pci_driver flags.
5933031608STal Shnaiderman 	 */
6033031608STal Shnaiderman 	return 0;
6133031608STal Shnaiderman }
6233031608STal Shnaiderman 
6333031608STal Shnaiderman /* Read PCI config space. */
6433031608STal Shnaiderman int
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
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 
9133031608STal Shnaiderman enum rte_iova_mode
9233031608STal Shnaiderman pci_device_iova_mode(const struct rte_pci_driver *pdrv __rte_unused,
9333031608STal Shnaiderman 		const struct rte_pci_device *pdev __rte_unused)
9433031608STal Shnaiderman {
9533031608STal Shnaiderman 	/* This function is not implemented on Windows.
9633031608STal Shnaiderman 	 * We really should short-circuit the call to these functions by
9733031608STal Shnaiderman 	 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
9833031608STal Shnaiderman 	 * in the rte_pci_driver flags.
9933031608STal Shnaiderman 	 */
10033031608STal Shnaiderman 	return RTE_IOVA_DC;
10133031608STal Shnaiderman }
10233031608STal Shnaiderman 
10333031608STal Shnaiderman int
10433031608STal Shnaiderman rte_pci_ioport_map(struct rte_pci_device *dev __rte_unused,
10533031608STal Shnaiderman 	int bar __rte_unused, struct rte_pci_ioport *p __rte_unused)
10633031608STal Shnaiderman {
10733031608STal Shnaiderman 	/* This function is not implemented on Windows.
10833031608STal Shnaiderman 	 * We really should short-circuit the call to these functions by
10933031608STal Shnaiderman 	 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
11033031608STal Shnaiderman 	 * in the rte_pci_driver flags.
11133031608STal Shnaiderman 	 */
11233031608STal Shnaiderman 	return -1;
11333031608STal Shnaiderman }
11433031608STal Shnaiderman 
11533031608STal Shnaiderman 
11633031608STal Shnaiderman void
11733031608STal Shnaiderman rte_pci_ioport_read(struct rte_pci_ioport *p __rte_unused,
11833031608STal Shnaiderman 	void *data __rte_unused, size_t len __rte_unused,
11933031608STal Shnaiderman 	off_t offset __rte_unused)
12033031608STal Shnaiderman {
12133031608STal Shnaiderman 	/* This function is not implemented on Windows.
12233031608STal Shnaiderman 	 * We really should short-circuit the call to these functions by
12333031608STal Shnaiderman 	 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
12433031608STal Shnaiderman 	 * in the rte_pci_driver flags.
12533031608STal Shnaiderman 	 */
12633031608STal Shnaiderman }
12733031608STal Shnaiderman 
12833031608STal Shnaiderman int
12933031608STal Shnaiderman rte_pci_ioport_unmap(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 bool
14033031608STal Shnaiderman pci_device_iommu_support_va(const struct rte_pci_device *dev __rte_unused)
14133031608STal Shnaiderman {
14233031608STal Shnaiderman 	/* This function is not implemented on Windows.
14333031608STal Shnaiderman 	 * We really should short-circuit the call to these functions by
14433031608STal Shnaiderman 	 * clearing the RTE_PCI_DRV_NEED_MAPPING flag
14533031608STal Shnaiderman 	 * in the rte_pci_driver flags.
14633031608STal Shnaiderman 	 */
14733031608STal Shnaiderman 	return false;
14833031608STal Shnaiderman }
14933031608STal Shnaiderman 
15033031608STal Shnaiderman void
15133031608STal Shnaiderman rte_pci_ioport_write(struct rte_pci_ioport *p __rte_unused,
15233031608STal Shnaiderman 		const void *data __rte_unused, size_t len __rte_unused,
15333031608STal Shnaiderman 		off_t offset __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 }
16133031608STal Shnaiderman 
16233031608STal Shnaiderman /* remap the PCI resource of a PCI device in anonymous virtual memory */
16333031608STal Shnaiderman int
16433031608STal Shnaiderman pci_uio_remap_resource(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 -1;
17233031608STal Shnaiderman }
173b762221aSTal Shnaiderman 
174b762221aSTal Shnaiderman static int
175b762221aSTal Shnaiderman get_device_pci_address(HDEVINFO dev_info,
176b762221aSTal Shnaiderman 	PSP_DEVINFO_DATA device_info_data, struct rte_pci_addr *addr)
177b762221aSTal Shnaiderman {
178b762221aSTal Shnaiderman 	BOOL  res;
179b762221aSTal Shnaiderman 	ULONG bus_num, dev_and_func;
180b762221aSTal Shnaiderman 
181b762221aSTal Shnaiderman 	res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
182b762221aSTal Shnaiderman 		SPDRP_BUSNUMBER, NULL, (PBYTE)&bus_num, sizeof(bus_num), NULL);
183b762221aSTal Shnaiderman 	if (!res) {
184b762221aSTal Shnaiderman 		RTE_LOG_WIN32_ERR(
185b762221aSTal Shnaiderman 			"SetupDiGetDeviceRegistryProperty(SPDRP_BUSNUMBER)");
186b762221aSTal Shnaiderman 		return -1;
187b762221aSTal Shnaiderman 	}
188b762221aSTal Shnaiderman 
189b762221aSTal Shnaiderman 	res = SetupDiGetDeviceRegistryProperty(dev_info, device_info_data,
190b762221aSTal Shnaiderman 		SPDRP_ADDRESS, NULL, (PBYTE)&dev_and_func, sizeof(dev_and_func),
191b762221aSTal Shnaiderman 		NULL);
192b762221aSTal Shnaiderman 	if (!res) {
193b762221aSTal Shnaiderman 		RTE_LOG_WIN32_ERR(
194b762221aSTal Shnaiderman 			"SetupDiGetDeviceRegistryProperty(SPDRP_ADDRESS)");
195b762221aSTal Shnaiderman 		return -1;
196b762221aSTal Shnaiderman 	}
197b762221aSTal Shnaiderman 
198*c3adf814STal Shnaiderman 	addr->domain = bus_num >> 8;
199*c3adf814STal Shnaiderman 	addr->bus = bus_num & 0xff;
200b762221aSTal Shnaiderman 	addr->devid = dev_and_func >> 16;
201b762221aSTal Shnaiderman 	addr->function = dev_and_func & 0xffff;
202b762221aSTal Shnaiderman 	return 0;
203b762221aSTal Shnaiderman }
204b762221aSTal Shnaiderman 
205b762221aSTal Shnaiderman static int
206b762221aSTal Shnaiderman get_device_resource_info(HDEVINFO dev_info,
207b762221aSTal Shnaiderman 	PSP_DEVINFO_DATA dev_info_data, struct rte_pci_device *dev)
208b762221aSTal Shnaiderman {
209b762221aSTal Shnaiderman 	DEVPROPTYPE property_type;
210b762221aSTal Shnaiderman 	DWORD numa_node;
211b762221aSTal Shnaiderman 	BOOL  res;
212b762221aSTal Shnaiderman 
213b762221aSTal Shnaiderman 	switch (dev->kdrv) {
2147c0d798aSDavid Marchand 	case RTE_PCI_KDRV_NONE:
215b762221aSTal Shnaiderman 		/* Get NUMA node using DEVPKEY_Device_Numa_Node */
216b762221aSTal Shnaiderman 		res = SetupDiGetDevicePropertyW(dev_info, dev_info_data,
217b762221aSTal Shnaiderman 			&DEVPKEY_Device_Numa_Node, &property_type,
218b762221aSTal Shnaiderman 			(BYTE *)&numa_node, sizeof(numa_node), NULL, 0);
219b762221aSTal Shnaiderman 		if (!res) {
220b762221aSTal Shnaiderman 			RTE_LOG_WIN32_ERR(
221b762221aSTal Shnaiderman 				"SetupDiGetDevicePropertyW"
222b762221aSTal Shnaiderman 				"(DEVPKEY_Device_Numa_Node)");
223b762221aSTal Shnaiderman 			return -1;
224b762221aSTal Shnaiderman 		}
225b762221aSTal Shnaiderman 		dev->device.numa_node = numa_node;
2267c0d798aSDavid Marchand 		/* mem_resource - Unneeded for RTE_PCI_KDRV_NONE */
227b762221aSTal Shnaiderman 		dev->mem_resource[0].phys_addr = 0;
228b762221aSTal Shnaiderman 		dev->mem_resource[0].len = 0;
229b762221aSTal Shnaiderman 		dev->mem_resource[0].addr = NULL;
230b762221aSTal Shnaiderman 		break;
231b762221aSTal Shnaiderman 	default:
232b762221aSTal Shnaiderman 		/* kernel driver type is unsupported */
233b762221aSTal Shnaiderman 		RTE_LOG(DEBUG, EAL,
234b762221aSTal Shnaiderman 			"Kernel driver type for PCI device " PCI_PRI_FMT ","
235b762221aSTal Shnaiderman 			" is unsupported",
236b762221aSTal Shnaiderman 			dev->addr.domain, dev->addr.bus,
237b762221aSTal Shnaiderman 			dev->addr.devid, dev->addr.function);
238b762221aSTal Shnaiderman 		return -1;
239b762221aSTal Shnaiderman 	}
240b762221aSTal Shnaiderman 
241b762221aSTal Shnaiderman 	return ERROR_SUCCESS;
242b762221aSTal Shnaiderman }
243b762221aSTal Shnaiderman 
244b762221aSTal Shnaiderman /*
245b762221aSTal Shnaiderman  * get string that contains the list of hardware IDs for a device
246b762221aSTal Shnaiderman  */
247b762221aSTal Shnaiderman static int
248b762221aSTal Shnaiderman get_pci_hardware_id(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data,
249b762221aSTal Shnaiderman 	char *pci_device_info, size_t pci_device_info_len)
250b762221aSTal Shnaiderman {
251b762221aSTal Shnaiderman 	BOOL  res;
252b762221aSTal Shnaiderman 
253b762221aSTal Shnaiderman 	/* Retrieve PCI device IDs */
254b762221aSTal Shnaiderman 	res = SetupDiGetDeviceRegistryPropertyA(dev_info, device_info_data,
255b762221aSTal Shnaiderman 			SPDRP_HARDWAREID, NULL, (BYTE *)pci_device_info,
256b762221aSTal Shnaiderman 			pci_device_info_len, NULL);
257b762221aSTal Shnaiderman 	if (!res) {
258b762221aSTal Shnaiderman 		RTE_LOG_WIN32_ERR(
259b762221aSTal Shnaiderman 			"SetupDiGetDeviceRegistryPropertyA(SPDRP_HARDWAREID)");
260b762221aSTal Shnaiderman 		return -1;
261b762221aSTal Shnaiderman 	}
262b762221aSTal Shnaiderman 
263b762221aSTal Shnaiderman 	return 0;
264b762221aSTal Shnaiderman }
265b762221aSTal Shnaiderman 
266b762221aSTal Shnaiderman /*
267b762221aSTal Shnaiderman  * parse the SPDRP_HARDWAREID output and assign to rte_pci_id
268b762221aSTal Shnaiderman  */
269b762221aSTal Shnaiderman static int
270b762221aSTal Shnaiderman parse_pci_hardware_id(const char *buf, struct rte_pci_id *pci_id)
271b762221aSTal Shnaiderman {
272b762221aSTal Shnaiderman 	int ids = 0;
2732dceae68STal Shnaiderman 	uint16_t vendor_id, device_id;
2742dceae68STal Shnaiderman 	uint32_t subvendor_id = 0;
275b762221aSTal Shnaiderman 
2762dceae68STal Shnaiderman 	ids = sscanf_s(buf, "PCI\\VEN_%" PRIx16 "&DEV_%" PRIx16 "&SUBSYS_%"
2772dceae68STal Shnaiderman 		PRIx32, &vendor_id, &device_id, &subvendor_id);
278b762221aSTal Shnaiderman 	if (ids != 3)
279b762221aSTal Shnaiderman 		return -1;
280b762221aSTal Shnaiderman 
281b762221aSTal Shnaiderman 	pci_id->vendor_id = vendor_id;
282b762221aSTal Shnaiderman 	pci_id->device_id = device_id;
2832dceae68STal Shnaiderman 	pci_id->subsystem_device_id = subvendor_id >> 16;
2842dceae68STal Shnaiderman 	pci_id->subsystem_vendor_id = subvendor_id & 0xffff;
285b762221aSTal Shnaiderman 	return 0;
286b762221aSTal Shnaiderman }
287b762221aSTal Shnaiderman 
288b762221aSTal Shnaiderman static void
289b762221aSTal Shnaiderman get_kernel_driver_type(struct rte_pci_device *dev)
290b762221aSTal Shnaiderman {
291b762221aSTal Shnaiderman 	/*
292b762221aSTal Shnaiderman 	 * If another kernel driver is supported the relevant checking
293b762221aSTal Shnaiderman 	 * functions should be here
294b762221aSTal Shnaiderman 	 */
2957c0d798aSDavid Marchand 	dev->kdrv = RTE_PCI_KDRV_NONE;
296b762221aSTal Shnaiderman }
297b762221aSTal Shnaiderman 
298b762221aSTal Shnaiderman static int
299b762221aSTal Shnaiderman pci_scan_one(HDEVINFO dev_info, PSP_DEVINFO_DATA device_info_data)
300b762221aSTal Shnaiderman {
301b762221aSTal Shnaiderman 	struct rte_pci_device *dev;
302b762221aSTal Shnaiderman 	int ret = -1;
303b762221aSTal Shnaiderman 	char  pci_device_info[PATH_MAX];
304b762221aSTal Shnaiderman 	struct rte_pci_addr addr;
305b762221aSTal Shnaiderman 	struct rte_pci_id pci_id;
306b762221aSTal Shnaiderman 
307b762221aSTal Shnaiderman 	dev = malloc(sizeof(*dev));
308b762221aSTal Shnaiderman 	if (dev == NULL)
309b762221aSTal Shnaiderman 		goto end;
310b762221aSTal Shnaiderman 
311b762221aSTal Shnaiderman 	memset(dev, 0, sizeof(*dev));
312b762221aSTal Shnaiderman 
313b762221aSTal Shnaiderman 	ret = get_pci_hardware_id(dev_info, device_info_data,
314b762221aSTal Shnaiderman 		pci_device_info, PATH_MAX);
315b762221aSTal Shnaiderman 	if (ret != 0)
316b762221aSTal Shnaiderman 		goto end;
317b762221aSTal Shnaiderman 
318b762221aSTal Shnaiderman 	ret = parse_pci_hardware_id((const char *)&pci_device_info, &pci_id);
319b762221aSTal Shnaiderman 	if (ret != 0) {
320b762221aSTal Shnaiderman 		/*
321b762221aSTal Shnaiderman 		 * We won't add this device, but we want to continue
322b762221aSTal Shnaiderman 		 * looking for supported devices
323b762221aSTal Shnaiderman 		 */
324b762221aSTal Shnaiderman 		ret = ERROR_CONTINUE;
325b762221aSTal Shnaiderman 		goto end;
326b762221aSTal Shnaiderman 	}
327b762221aSTal Shnaiderman 
328b762221aSTal Shnaiderman 	ret = get_device_pci_address(dev_info, device_info_data, &addr);
329b762221aSTal Shnaiderman 	if (ret != 0)
330b762221aSTal Shnaiderman 		goto end;
331b762221aSTal Shnaiderman 
332b762221aSTal Shnaiderman 	dev->addr = addr;
333b762221aSTal Shnaiderman 	dev->id = pci_id;
334b762221aSTal Shnaiderman 	dev->max_vfs = 0; /* TODO: get max_vfs */
335b762221aSTal Shnaiderman 
336b762221aSTal Shnaiderman 	pci_name_set(dev);
337b762221aSTal Shnaiderman 
338b762221aSTal Shnaiderman 	get_kernel_driver_type(dev);
339b762221aSTal Shnaiderman 
340b762221aSTal Shnaiderman 	/* get resources */
341b762221aSTal Shnaiderman 	if (get_device_resource_info(dev_info, device_info_data, dev)
342b762221aSTal Shnaiderman 			!= ERROR_SUCCESS) {
343b762221aSTal Shnaiderman 		goto end;
344b762221aSTal Shnaiderman 	}
345b762221aSTal Shnaiderman 
346b762221aSTal Shnaiderman 	/* device is valid, add in list (sorted) */
347b762221aSTal Shnaiderman 	if (TAILQ_EMPTY(&rte_pci_bus.device_list)) {
348b762221aSTal Shnaiderman 		rte_pci_add_device(dev);
349b762221aSTal Shnaiderman 	} else {
350b762221aSTal Shnaiderman 		struct rte_pci_device *dev2 = NULL;
351b762221aSTal Shnaiderman 		int ret;
352b762221aSTal Shnaiderman 
353b762221aSTal Shnaiderman 		TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) {
354b762221aSTal Shnaiderman 			ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr);
355b762221aSTal Shnaiderman 			if (ret > 0) {
356b762221aSTal Shnaiderman 				continue;
357b762221aSTal Shnaiderman 			} else if (ret < 0) {
358b762221aSTal Shnaiderman 				rte_pci_insert_device(dev2, dev);
359b762221aSTal Shnaiderman 			} else { /* already registered */
360b762221aSTal Shnaiderman 				dev2->kdrv = dev->kdrv;
361b762221aSTal Shnaiderman 				dev2->max_vfs = dev->max_vfs;
362b762221aSTal Shnaiderman 				memmove(dev2->mem_resource, dev->mem_resource,
363b762221aSTal Shnaiderman 					sizeof(dev->mem_resource));
364b762221aSTal Shnaiderman 				free(dev);
365b762221aSTal Shnaiderman 			}
366b762221aSTal Shnaiderman 			return 0;
367b762221aSTal Shnaiderman 		}
368b762221aSTal Shnaiderman 		rte_pci_add_device(dev);
369b762221aSTal Shnaiderman 	}
370b762221aSTal Shnaiderman 
371b762221aSTal Shnaiderman 	return 0;
372b762221aSTal Shnaiderman end:
373b762221aSTal Shnaiderman 	if (dev)
374b762221aSTal Shnaiderman 		free(dev);
375b762221aSTal Shnaiderman 	return ret;
376b762221aSTal Shnaiderman }
377b762221aSTal Shnaiderman 
37833031608STal Shnaiderman /*
37933031608STal Shnaiderman  * Scan the contents of the PCI bus
38033031608STal Shnaiderman  * and add all network class devices into the devices list.
38133031608STal Shnaiderman  */
38233031608STal Shnaiderman int
38333031608STal Shnaiderman rte_pci_scan(void)
38433031608STal Shnaiderman {
385b762221aSTal Shnaiderman 	int   ret = -1;
386b762221aSTal Shnaiderman 	DWORD device_index = 0, found_device = 0;
387b762221aSTal Shnaiderman 	HDEVINFO dev_info;
388b762221aSTal Shnaiderman 	SP_DEVINFO_DATA device_info_data;
389b762221aSTal Shnaiderman 
390b762221aSTal Shnaiderman 	/* for debug purposes, PCI can be disabled */
391b762221aSTal Shnaiderman 	if (!rte_eal_has_pci())
39233031608STal Shnaiderman 		return 0;
393b762221aSTal Shnaiderman 
394b762221aSTal Shnaiderman 	dev_info = SetupDiGetClassDevs(&GUID_DEVCLASS_NET, TEXT("PCI"), NULL,
395b762221aSTal Shnaiderman 				DIGCF_PRESENT);
396b762221aSTal Shnaiderman 	if (dev_info == INVALID_HANDLE_VALUE) {
397b762221aSTal Shnaiderman 		RTE_LOG_WIN32_ERR("SetupDiGetClassDevs(pci_scan)");
398b762221aSTal Shnaiderman 		RTE_LOG(ERR, EAL, "Unable to enumerate PCI devices.\n");
399b762221aSTal Shnaiderman 		goto end;
400b762221aSTal Shnaiderman 	}
401b762221aSTal Shnaiderman 
402b762221aSTal Shnaiderman 	device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
403b762221aSTal Shnaiderman 	device_index = 0;
404b762221aSTal Shnaiderman 
405b762221aSTal Shnaiderman 	while (SetupDiEnumDeviceInfo(dev_info, device_index,
406b762221aSTal Shnaiderman 	    &device_info_data)) {
407b762221aSTal Shnaiderman 		device_index++;
408b762221aSTal Shnaiderman 		ret = pci_scan_one(dev_info, &device_info_data);
409b762221aSTal Shnaiderman 		if (ret == ERROR_SUCCESS)
410b762221aSTal Shnaiderman 			found_device++;
411b762221aSTal Shnaiderman 		else if (ret != ERROR_CONTINUE)
412b762221aSTal Shnaiderman 			goto end;
413b762221aSTal Shnaiderman 
414b762221aSTal Shnaiderman 		memset(&device_info_data, 0, sizeof(SP_DEVINFO_DATA));
415b762221aSTal Shnaiderman 		device_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
416b762221aSTal Shnaiderman 	}
417b762221aSTal Shnaiderman 
418b762221aSTal Shnaiderman 	RTE_LOG(DEBUG, EAL, "PCI scan found %lu devices\n", found_device);
419b762221aSTal Shnaiderman 	ret = 0;
420b762221aSTal Shnaiderman end:
421b762221aSTal Shnaiderman 	if (dev_info != INVALID_HANDLE_VALUE)
422b762221aSTal Shnaiderman 		SetupDiDestroyDeviceInfoList(dev_info);
423b762221aSTal Shnaiderman 
424b762221aSTal Shnaiderman 	return ret;
42533031608STal Shnaiderman }
426