About the author

Related Articles

4 Comments

  1. 1
    Dan

    Dan Lovinger

    Here is a version of the script that does not need to parse the registry. All of the information (used here) is available within win32_pnpentity.

    Function Get-BusFunctionID { 
    
        gwmi -namespace rootcimv2 -class Win32_PnPEntity |% {
    
            if ($_.PNPDeviceID -like "PCI*") {
    
                $locationInfo = $_.GetDeviceProperties('DEVPKEY_Device_LocationInfo').deviceProperties.Data
    
                if ($locationInfo -match 'PCI bus (d+), device (d+), function (d+)') {
    
                    new-object psobject -property @{ 
                        "Name"       = $_.Name
                        "PnPID"      = $_.PNPDeviceID
                        "BusID"      = $matches[1]
                        "DeviceID"   = $matches[2]
                        "FunctionID" = $matches[3]
                    }
                }
            }
        }
    } 
    
    Reply
  2. 2
    Erwin

    Erwin H.

    For Windows a ready to run Powershell-script:

    Function Get-BusFunctionID { 
        #gwmi -query "SELECT * FROM Win32_PnPEntity"
        $Devices = get-wmiobject -namespace rootcimv2 -class Win32_PnPEntity
    
        for($i=0; $i -lt $Devices.length; $i++) { 
    
            if(!($Devices[$i].PNPDeviceID -match "PCI\*")) {
                continue
            }
            $deviceId = $Devices[$i].PNPDeviceID
            $locationInfo = (get-itemproperty -path "HKLM:SYSTEMCurrentControlSetEnum$deviceID" -name locationinformation).locationINformation
    
            $businfo = Resolve-PCIBusInfo -locationInfo $locationinfo 
    
            new-object psobject -property @{ 
                "Name"        = $Devices[$i].Name;
                "PnPID"       = $Devices[$i].PNPDeviceID
                "PCIBusID"      = $businfo.BusID; 
                "PCIDeviceID"   = $businfo.DeviceID; 
                "PCIFunctionID" = $businfo.FunctionID 
            } 
        }
    }
    
    Function Resolve-PCIBusInfo { 
    
    param ( 
    [parameter(ValueFromPipeline=$true,Mandatory=$true)] 
    [string] 
    $locationInfo 
    ) 
    PROCESS { 
    [void]($locationInfo -match  "d+,d+,d+")
    $busId,$deviceID,$functionID = $matches[0] -split "," 
    
    new-object psobject -property @{ 
              "BusID" = $busID; 
              "DeviceID" = "$deviceID" 
              "FunctionID" = "$functionID" 
              } 
    }          
    }
    

    Usage example:

    Get-BusFunctionID | Where-Object {$_.PCIBusID -eq 0 -and $_.PCIDeviceID -eq 0} | Format-Table
    Get-BusFunctionID | Sort-Object PCIBusID, PCIDeviceID, PCIFunctionID | Format-Table -GroupBy
    
    Reply
  3. 3
    Erwin

    Erwin H.

    On Windows you can use e.g.: the following Powershell-Script with the devcon.exe tool from the Windows Device Driver Kit:

    Function Get-BusFunctionID { 
        $Devices = .devcon.exe find PCI*
    
        for($i=0; $i -lt $Devices.length; $i++) { 
    
            if(!($Devices[$i] -match "PCI\*")) {
                continue
            }
            $DevInfo = $Devices[$i].split(":")
            $deviceId = $DevInfo[0]
            $locationInfo = (get-itemproperty -path "HKLM:SYSTEMCurrentControlSetEnum$deviceID" -name locationinformation).locationINformation
    
            $businfo = Resolve-PCIBusInfo -locationInfo $locationinfo 
    
            new-object psobject -property @{ 
                "Name"        = $DevInfo[1];
                "PnPID"       = $DevInfo[0]
                "PCIBusID"      = $businfo.BusID; 
                "PCIDeviceID"   = $businfo.DeviceID; 
                "PCIFunctionID" = $businfo.FunctionID 
            } 
        }
    }
    
    Function Resolve-PCIBusInfo { 
    
    param ( 
    [parameter(ValueFromPipeline=$true,Mandatory=$true)] 
    [string] 
    $locationInfo 
    ) 
    PROCESS { 
    [void]($locationInfo -match  "d+,d+,d+")
    $busId,$deviceID,$functionID = $matches[0] -split "," 
    
    new-object psobject -property @{ 
              "BusID" = $busID; 
              "DeviceID" = "$deviceID" 
              "FunctionID" = "$functionID" 
              } 
    }          
    }
    

    Usage example:

    Get-BusFunctionID | Where-Object {$_.PCIBusID -eq 0 -and $_.PCIDeviceID -eq 0} | Format-Table
    Get-BusFunctionID | Sort-Object PCIBusID, PCIDeviceID, PCIFunctionID | Format-Table -GroupBy PCIBusID
    Get-BusFunctionID | Sort-Object PCIBusID, PCIDeviceID, PCIFunctionID | Out-GridView
    
    Reply
  4. 4
    Paebbels@email.null'

    Paebbels

    PCI devices (endpoints) have a unique address. This address has 3 parts:

    • BusID
    • DeviceID
    • FunctionID

    For example function 3 of device 12 on bus 3 is written in BDF notion: 03:0C.3. An extended BDF notation adds a domain (mostly 0000) as a prefix: 0000:03:0c.3.

    Linux lists these devices in /sys/bus/pci/devices

    paebbels@debian8:~$ ll /sys/bus/pci/devices/
    drwxr-xr-x 2 root root 0 Aug 19 11:44 .
    drwxr-xr-x 5 root root 0 Aug  5 15:14 ..
    lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:00.0 -> ../../../devices/pci0000:00/0000:00:00.0
    lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:01.0 -> ../../../devices/pci0000:00/0000:00:01.0
    lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:07.0 -> ../../../devices/pci0000:00/0000:00:07.0
    lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:07.1 -> ../../../devices/pci0000:00/0000:00:07.1
    ...
    lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:18.6 -> ../../../devices/pci0000:00/0000:00:18.6
    lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:00:18.7 -> ../../../devices/pci0000:00/0000:00:18.7
    lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:02:00.0 -> ../../../devices/pci0000:00/0000:00:11.0/0000:02:00.0
    lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:02:01.0 -> ../../../devices/pci0000:00/0000:00:11.0/0000:02:01.0
    lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:02:02.0 -> ../../../devices/pci0000:00/0000:00:11.0/0000:02:02.0
    lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:02:03.0 -> ../../../devices/pci0000:00/0000:00:11.0/0000:02:03.0
    lrwxrwxrwx 1 root root 0 Aug 19 11:44 0000:03:00.0 -> ../../../devices/pci0000:00/0000:00:15.0/0000:03:00.0
    

    Here you can see that sys-fs lists devices 00 to 03 of bus 02 as connected to bus 00, device 11, function 0

    From these information, you can rebuilt the complete PCI bus-tree. The tree is always the same after a boot up, unless you add or remove devices.

    The windows device manager offers the same information. The property dialog shows you the device type, vendor and location: e.g. PCI bus 0, device 2, function 0 for an integrated Intel HD 4600 graphics.

    Currently, I don’t know how you can get these information by scripting or programming language in a Windows environment, but there are commercial and free tools in the internet, that provide these information. Maybe there is an API.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Copyright © 2017 SolutionMmyself.com