18.3.3 PCI Cards with Multiple PCI Controllers

Some PCI devices have a series of identical devices on a single device, normally behind a PCI bridge. These devices may require additional work if they need to be controlled by a single instance of the UEFI driver. Take the following figure as a sample device.

Figure 20-A multi-controller PCI device

It may be required that the driver in the Option ROM control all 3 controllers on the PCI device. To do this, use the following actions:
  • In the Supported() function, make sure that the UEFI Driver supports the
    controller that is passed into the Support() function. The first controller
    passed in could be any of the controllers on a PCI Card.
  • In the Supported() function, make sure the function does not touch or
    change the HW state. This is very important. If the PCI I/O instance is
    already opened (if some other application or driver is already managing the
    controller), return an error. See Chapter 9 of this guide and the EFI
    Driver Binding Protocol section of the UEFI Specification for details on
    the error return codes from the Driver Binding Protocol Supported()
    function.
  • In the Start() function for the first controller on the PCI Card, open the
    PCI I/O protocol instances on the other handles on the same PCI Card using
    the EFI_OPEN_PROTOCOL_BY_DRIVER attribute. This informs all other UEFI
    Drivers in the platform that all the controllers on the PCI Card are already
    being managed.
    To scan for other PCI controllers on the same PCI Card, use the UEFI Boot
    Service LocateHandleBuffer() to find all handles in the Handle Database
    supporting the PCI I/O Protocol. Use the PCI I/O Protocol function
    GetLocation()to evaluate whether or not the PCI controller is on the same PCI
    bus number. Take care to not modify the HW state of any PCI I/O Protocol
    instance during this evaluation.
  • In the Stop() function, undo everything that was done in Start(). Use a
    private context data structure to keep track of the information required to
    complete a Stop() operation in these more complex use cases.