18.6.1 PCI I/O fill operations

The following examples show ways to fill video frame buffer with zeros on a PCI video controller. The frame buffer is 1 MB of memory-mapped I/O accessed through BAR #0 of the PCI video controller. The following four examples of performing this operation are shown from slowest to fastest:

The following two methods can significantly increase performance of a UEFI driver by taking advantage of the fill operations to eliminate loops and writing to a PCI controller at the largest possible size.

Example 182-PCI I/O 8-bit fill with a loop

#include <Uefi.h>
#include <Protocol/PciIo.h>
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT8 Color8;
UINTN Index;
//
// This is the slowest method. It performs SIZE_1MB calls through PCI I/O and
// writes to the frame buffer 8 bits at a time.
//
Color8 = 0;
for (Index = 0; Index < SIZE_1MB; Index++) {
Status = PciIo->Mem.Write (
PciIo, // This
EfiPciIoWidthUint8, // Width
0, // BarIndex
Index, // Offset
1, // Count
&Color8 // Buffer
);
}

Example 183-PCI I/O 32-bit fill with a loop

#include <Uefi.h>
#include <Protocol/PciIo.h>
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT32 Color32;
UINTN Index;
//
// This is the slowest method. It performs SIZE_1MB calls through PCI I/O and
// writes to the frame buffer 8 bits at a time.
//
Color32 = 0;
for (Index = 0; Index < SIZE_1MB; Index += 4) {
Status = PciIo->Mem.Write (
PciIo, // This
EfiPciIoWidthUint32, // Width
0, // BarIndex
Index, // Offset
1, // Count
&Color32 // Buffer
);
}

Example 184-PCI I/O 8-bit fill without a loop

#include <Uefi.h>
#include <Protocol/PciIo.h>
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT8 Color8;
//
// This is much better. It performs 1 call to PCI I/O, but it is writing the
// frame buffer 8 bits at a time.
//
Color8 = 0;
Status = PciIo->Mem.Write (
PciIo, // This
EfiPciIoWidthFillUint8, // Width
0, // BarIndex
0, // Offset
SIZE_1MB, // Count
&Color8 // Buffer
);

Example 185-PCI I/O 32-bit fill without a loop

#include <Uefi.h>
#include <Protocol/PciIo.h>
EFI_STATUS Status;
EFI_PCI_IO_PROTOCOL *PciIo;
UINT32 Color32;
//
// This is the best method. It performs 1 call to PCI I/O, and it is writing
// the frame buffer 32 bits at a time.
//
Color32 = 0;
Status = PciIo->Mem.Write (
PciIo, // This
EfiPciIoWidthFillUint32, // Width
0, // BarIndex
0, // Offset
SIZE_1MB / sizeof (UINT32), // Count
&Color32 // Buffer
);