PCI bus device location

I’m trying to determine a consistent way to determine the device number of my PCI bus devices.

SPDRP_LOCATION_INFORMATION returned from SetupDiGetDeviceRegistryProperty gives me
PCI bus 3, device 0, function 0
and
PCI bus 3, device 1, function 0
for my two devices.
The problem is that in different versions of Windows(Win7 vs Win10) these ‘device’ values seem to get swapped. These are identical devices but are connected externally in different ways. I need to be able to consistently know which board I’m accessing. Is there a consistent way to know which PCI slot is which?

eric_heim wrote:

I’m trying to determine a consistent way to determine the device number of my PCI bus devices.

SPDRP_LOCATION_INFORMATION returned from SetupDiGetDeviceRegistryProperty gives me

PCI bus 3, device 0, function 0
and
PCI bus 3, device 1, function 0

for my two devices.

The problem is that in different versions of Windows(Win7 vs Win10) these ‘device’ values seem to get swapped. These are identical devices but are connected externally in different ways. I need to be able to consistently know which board I’m accessing. Is there a consistent way to know which PCI slot is which?

No.  The PCI “device” number is an arbitrary assignment that does not
necessarily map to physical slots in any rational way.  It’s assigned at
boot time.  Further, most motherboards do not number their slots in a
human-visible way.  You will need to come up with some other way to
distinguish the two devices.

Is there an LED you can light up and ask the user to confirm?

Thank you. I have an eeprom I can use to write in a distinguishing value. I was just hoping to not repeat this for various sets of boards. Now that I know it’s arbitrary, as I suspected, I can proceed accordingly.

This is very strange. PCI device numbers are defined by hardware and should not change from one Windows version to other. Can you re-check?
If this is PCIe device, you can set a “serial number” in its config space.

Regards,
– pa

How PCI bus numbers are assigned will depend on how bus numbers are allocated previously in the enumeration. If you have a device showing up at BDF 3:0:0 and then you pop in a fancy SR-IOV NIC in the previous slot, don’t be surprised if your device is now at 20:0:0. Different OS flavors have definitely had some adjustments in this area. Devices that might dynamically add child devices, like Thunderbolt, may have gaps inserted in the enumeration to allow space for not yet connected devices, this avoids having to move devices later. In general ONLY boot critical devices are assured of keeping their firmware assigned PCI BDF assignments.

There are some ACPI methods that can expose a slot stable identity, but you usually only get to control the ACPI tables if you’re the system vendor. The system also tries to use device serial numbers to keep device configurations associated with the correct device. The exact behavior has varied with the OS flavor. Some bridges also unfortunately seem to use duplicate serial numbers, which makes things not work ideally.

Really, the BDF is only meaningful at a particular time, and is used for routing requests along the PCIe fabric. Any change to the fabric topology and the BDF could change. BDFs are definitely not like unique network MAC addresses, static IP addresses or even sticky DHCP addresses. BDFs are dynamically assigned addresses. On a system with no PCIe fabric topology, or enumerating agent (an OS) changes, they end up getting assigned the same value.

Device serial numbers are there for a reason, make sure you device has a unique stable value.

Jan

@Jan, you’re right about bus numbers, but what I mean is assignment of function numbers. In your example, device on 3:0:0 may jump to 20:0:0, but not to 20:1:0.

Regards,
– pa

IMHO Ethernet MAC addresses are not unique either; and forget about IP addresses being unique whether static or any other kind.

GUIDs are almost unique and WWNs are verifiably unique