In Linux, How to Find Out Which Pci Card Is Plugged into Which Pci Slot

Get device name from PCIE slot number

You may try searching for device name somewhat like this:

grep "3b:00.0" /sys/class/nvme/*/device/uevent

Then you will need to extract device name from the output:

/sys/class/nvme/nvme0n1/device/uevent:PCI_SLOT_NAME=0000:3b:00.0

This will be the string in place of the asterisk.

How does lspci find out physical slot number of a PCI(E) device?

After digging deeper in the source and succeeding to run lspci in the debugger (thanks to Netbeans) I found out that lspci uses sysfs to gather information.
In particular /sys/bus/pci/slots/slot_num/address file contains the bus address of the slot. And that's what lspci uses to attribute slots to bus addresses in the function sysfs_fill_slots (in sysfs.c)

Unfortunately this method turns out to be unsuitable for my purposes, since it is not possible to perform file I/O from kernel module.

Determine what (if any) PCI devices are plugged into motherboard PCI(e) slots

After many hours I came up with a 'reasonably' reliable approach.

This logic fundamentally assumes that the slotted PCI device bus ID is unique and separate from all other (onboard) PCI bus IDs. So far my tests have shown this to be the case; regardless this is still an assumption.

My code is rather long and I'm sure it could be improved so instead I'll explain the process in pseudo-code:

  1. Determine how many slots are in use (and only proceed if at least one slot is actually in use):

    "SELECT SlotDesignation FROM Win32_SystemSlot WHERE CurrentUsage = 4"

  2. Store all the device IDs that belong to the PCI bus:

    "SELECT DeviceID FROM Win32_Bus where BusType = 5"

  3. Capture all system and logical device associations:

    "SELECT * FROM Win32_DeviceBus"

  4. Search all system and logical device associations (antecedent property) and count each time each deviceID occurs.

  5. You can now determine the DeviceID where the slotted PCI devices reside by finding the DeviceID that occurs the same number of times as the number of devices found in the system slots.

  6. For each of the Win32_DeviceBus results that contain the DeviceID (in the antecedent property) the dependent property will reference another DeviceID to be used for the Win32_PnPEntity class.

  7. Query the Win32_PnPEntity with the newly captured DeviceID and you now have all your device info (or rather, all information the the Win32_PnPEntity provides)!

    "SELECT * FROM Win32_PnPEntity WHERE DeviceID = '" + deviceID + "'"

Unfortunately I could not find ANY way to utilize the severely limited information returned by the Win32_SystemSlot class (that would have made life too easy!) other than the count of results returned by the 'in use' query.

Note that it may be possible to encounter more than one PCI bus that has the same number of devices as the count of slots that are in use. If this scenario were to arise (I haven't encountered it yet) then it'd suggest raising an exception rather than continuing and assuming you're querying the correct PCI bus.

BASH find which port a USB drive is attached to by the PCI ID

This is how I would do it on my system:

Step 1: Find the device node:

# blkid | grep MyDisk
/dev/sdj1: LABEL="MyDisk-0" UUID="4876-5945" TYPE="vfat"

The device node is /dev/sdj1.

Step 2: /sys is your friend:

# ll /sys/block/sdj
lrwxrwxrwx 1 root root 0 Feb 3 00:40 /sys/block/sdj -> ../devices/pci0000:00/0000:00:1a.7/usb1/1-2/1-2:1.0/host15/target15:0:0/15:0:0:0/block/sdj/

The symbolic link target above contains a lot of useful information, including the path from your flash drive back to the PCI bridge via the SCSI and USB subsystems.

Step 3: From the link target above isolate the PCI bus ID (00:1a.7 in this case) and check with lspci:

# lspci | grep 00:1a.7
00:1a.7 USB Controller: Intel Corporation 82801JI (ICH10 Family) USB2 EHCI Controller #2

If in doubt, inspect the lspci output visually...

EDIT:

Here is an extremely crude and extremely fragile way to automate the process above:

blkid |
grep Label |
cut -d : -f 1 |
sed 's|[0-9]*$||; s|^/dev/|/sys/block/|' |
xargs readlink |
cut -d / -f 4 |
xargs -n 1 lspci -s

NOTE: This works on my system, but it is by no means safe (or recommended):

  1. It will break if a kernel update changes the layout of the /sys filesystem.

  2. It can break if you have a different device layout, although you should be able to adjust for that.



Related Topics



Leave a reply



Submit