18.6.6 PCI I/O Polling Operations

These same types of optimization can be applied to polling as well. In the following examples, two different polling methods are shown:

  • A loop with 10 μs stalls to wait up to 1 minute

  • A single call to PCI I/O protocol to perform the entire operation

These types of polling operations are usually performed when a driver is waiting for the hardware to complete an operation with the completion status indicated by a bit changing state in an I/O port or a memory-mapped I/O port. The examples below poll offset 0x20 in BAR #1 for bit 0 to change from 0 to 1.

The PollIo() and PollMem() functions in the PCI I/O Protocol are very flexible and can simplify the operation of polling for bits to change state in status registers.

Example 195-Using Mem.Read() and Stall() to poll for 1 second
#include <Uefi.h>
#include <Protocol/PciIo.h>
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
UINTN TimeOut;
UINT8 Result8;
//
// Loop for up to 1 second waiting for Bit #0 in
// register 0x20 of BAR #1 to be set.
//
for (TimeOut = 0; TimeOut < 1000000; TimeOut += 10) {
  Status = PciIo->Mem.Read (
                        PciIo, // This
                        EfiPciIoWidthUint8, // Width
                        1, // BarIndex
                        0x20, // Offset
                        1, // Count
                        &Result8 // Value
                        );
  if ((Result8 & BIT0) == BIT0) {
    return EFI_SUCCESS;
  }
  gBS->Stall (10);
}
return EFI_TIMEOUT;
Example 196-Using PollIo() to poll for 1 second
#include <Uefi.h>
#include <Protocol/PciIo.h>
#include <Library/UefiLib.h>
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT64 Result64;
//
// Call PollIo() to poll for Bit #0 in register 0x20 of Bar #1 to be set.
//
Status = PciIo->PollIo (
                  PciIo, // This
                  EfiPciIoWidthUint8, // Width
                  1, // BarIndex
                  0x20, // Offset
                  BIT0, // Mask
                  BIT0, // Value
                  EFI_TIMER_PERIOD_SECONDS (1), // Timeout
                  &Result64 // Result
                  );