/* Transfer bytes between the config space of a given PCI device and a memory buffer. */
STATIC EFI_STATUS ProtoDevTransferConfig(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_PCI_IO_PROTOCOL_CONFIG TransferFunction, IN UINT16 ConfigOffset, IN OUT UINT8 *Buffer, IN UINT16 Size)
/* Transfer bytes between the config space of a given PCI device and a memory buffer. */
STATIC EFI_STATUS ProtoDevTransferConfig(IN EFI_PCI_IO_PROTOCOL *PciIo, IN EFI_PCI_IO_PROTOCOL_CONFIG TransferFunction, IN UINT16 ConfigOffset, IN OUT UINT8 *Buffer, IN UINT16 Size)
{
  while (Size > 0) {
    EFI_PCI_IO_PROTOCOL_WIDTH  Width;
    UINT16                     Count;
    EFI_STATUS                 Status;
    UINT16                     Progress;
    if ((Size >= 4) && ((ConfigOffset & 3) == 0)) {
      Width = EfiPciIoWidthUint32;
      Count = Size >> Width;
    } else if ((Size >= 2) && ((ConfigOffset & 1) == 0)) {
      Width = EfiPciIoWidthUint16;
      Count = 1;
    } else {
      Width = EfiPciIoWidthUint8;
      Count = 1;
    }
    Status = TransferFunction (PciIo, Width, ConfigOffset, Count, Buffer);
    if (EFI_ERROR (Status)) {
      return Status;
    }
    Progress      = Count << Width;
    ConfigOffset += Progress;
    Buffer       += Progress;
    Size         -= Progress;
  }
  return EFI_SUCCESS;
}