Report the PCI Device Hierarchy By Using Parent DeviceIDs

This example describes a simple way to enumerate the PCI devices present in the managed server. This information is useful to system administrators who want to troubleshoot device problems or upgrade the hardware in a managed server.

The PCI Device profile specification allows flexibility in how the profile is implemented. Designers can apply one of three approaches to modeling PCI device connections, or they can combine these approaches for a more complete implementation. Device connections can be modeled with a combination of the following approaches.

  • DeviceConnection associations
  • PCIPortGroup instances that express relationships between PCI ports
  • Primary and secondary bus numbers that relate PCI devices to bridges and switches

The VMware implementation supports the first two modeling approaches. For an example that uses the second approach to relating PCI devices, see Report the Path to a PCI Device By Using PortGroups.

For convenience, the VMware implementation also provides a fourth way to model device connections: ParentDeviceID.

The ParentDeviceID property relates a PCI device directly to the bridge or switch through which the device accesses the CPU. The value of the property is the value of the DeviceID property of that bridge or switch, which can be called its parent device. A CIM client that is aware of the ParentDeviceID property can map the hierarchy of PCI devices by using only that property to determine the relationships between devices.

This example shows how you can map the PCI device hierarchy by using the ParentDeviceID property. For illustration, this example enumerates PCI device instances by their VMware-specific class names, rather than by a parent class. Alternatively, you could enumerate the CIM_PCIDevice class, because all three of the VMware classes derive, directly or indirectly, from that class, as shown in Inheritance Relationships of PCI Device Classes.

Figure 1. Inheritance Relationships of PCI Device Classes
Diagram shows subclasses used for PCI devices.

This pseudocode depends on the pseudocode in Make a Connection to the CIMOM.

To report the PCI device hierarchy

Procedure

  1. Connect to the server URL.

    Specify the Implementation namespace, supplied as a parameter, for the connection.

    The actual namespace you will use depends on your implementation.

    use wbemlib
    use sys
    use connection renamed cnx
    connection = Null
    
    params = cnx.get_params()
    if params is Null
       sys.exit(-1)
    connection = cnx.connect_to_host( params )
    if connection is Null
       print 'Failed to connect to: ' + params['host'] + ' as user: ' + params['user']
       sys.exit(-1)
  2. Enumerate the VMware_PCIDevice, VMware_PCIBridge, and VMware_PCIeSwitch instances.

    Save each instance in an associative array, keyed by its parent’s DeviceID, or "none" if it has no parent. This example saves the children of each parent device as a nested associative array of instances indexed by the device’s own ID.

    dev_entries = {}
    enum_devs( ’VMware_PCIDevice’ )
    enum_devs( ’VMware_PCIBridge’ )
    enum_devs( ’VMware_PCIeSwitch’ )
    
    function enum_devs( class_name )
       dev_instances = connection.EnumerateInstances( class_name )
       for dev in dev_instances
          parent = dev[ ’ParentDeviceID’ ]
          if not parent
             parent = ’none’
          id = dev[ ’DeviceID’ ]
          if not dev_entries.key( parent )
             dev_entries[ parent ] = {}
          dev_entries[ parent ][ id ] = dev
  3. Starting with the value "none" for devices that have no parent, access the children of each parent.

    For each child, print the DeviceID, the BusNumber, DeviceNumber, and FunctionNumber, and the ElementName properties. Recursively do the same for the children of each child device.

    parent = ’none’
    print_children( ’’, parent )
    
    function print_children( indent, id )
       if dev_entries.key( id )
          dev_list = dev_entries[ id ]
          for key in dev_list.keys()
             dev = dev_list[ key ]
             print indent, print_dev( dev )
             print_children( indent + ’   ’, dev[ ’DeviceID’ ] )
    
    function print_dev( dev )
       dev_summary = ’ID=%s B/D/F=%s/%s/%s (%s)’ % \
          (dev[ ’DeviceID ], dev[ ’BusNumber’ ], dev[ ’DeviceNumber’ ], \
           dev[ ’FunctionNumber’ ], dev[ ’ElementName’ ])
       return dev_summary

    This pseudocode displays an indented representation of the hierarchy of PCI devices. A sample of the output looks like the following:

     ID=PCI 0:0:1:0 B/D/F=0/1/0 (Plutonic Devices PD-631 PCI-X Bridge)
        ID=PCI 0:2:1:0 B/D/F=2/1/0 (Trans-Oort Networks E-1500 Terabit Ethernet Adapter)
        ID=PCI 0:2:1:1 B/D/F=2/1/1 (Trans-Oort Networks E-1500 Terabit Ethernet Adapter)
     ID=PCI 0:0:2:0 B/D/F=0/2/0 (Plutonic Devices PD-631 PCI-X Bridge)
        ID=PCI 0:3:1:0 B/D/F=3/1/0 (Haumea HINA-15K Block Storage Adapter)
        ID=PCI 0:3:1:1 B/D/F=3/1/1 (Haumea HINA-15K Block Storage Adapter)
        ID=PCI 0:3:2:0 B/D/F=3/2/0 (Haumea HINA-15K Block Storage Adapter)
        ID=PCI 0:3:2:1 B/D/F=3/2/1 (Haumea HINA-15K Block Storage Adapter)
        ID=PCI 0:3:3:0 B/D/F=3/3/0 (Plutonic Devices PD-631 PCI-X Bridge)
           ID=PCI 0:4:1:0 B/D/F=4/1/0 (Mercuricity Generic USB OHCI Hub)
           ID=PCI 0:4:1:1 B/D/F=4/1/1 (Mercuricity Generic USB OHCI Hub)
           ID=PCI 0:4:1:2 B/D/F=4/1/2 (Mercuricity Generic USB OHCI Hub)
     ID=PCI 0:0:3:0 B/D/F=0/3/0 (Albedo-Kuiper Grafix Super X-Treme Duo)
     ID=PCI 0:0:3:1 B/D/F=0/3/1 (Albedo-Kuiper Grafix Super X-Treme Duo)
     ID=PCI 0:0:4:0 B/D/F=0/4/0 (vAndromeda FCoW Adapter)