]> git.proxmox.com Git - mirror_edk2.git/blobdiff - DuetPkg/PciBusNoEnumerationDxe/PciIo.c
Add PciBusNoEnumeration module
[mirror_edk2.git] / DuetPkg / PciBusNoEnumerationDxe / PciIo.c
diff --git a/DuetPkg/PciBusNoEnumerationDxe/PciIo.c b/DuetPkg/PciBusNoEnumerationDxe/PciIo.c
new file mode 100644 (file)
index 0000000..e5485dc
--- /dev/null
@@ -0,0 +1,1867 @@
+/*++\r
+\r
+Copyright (c) 2005 - 2007, Intel Corporation                                                         \r
+All rights reserved. This program and the accompanying materials                          \r
+are licensed and made available under the terms and conditions of the BSD License         \r
+which accompanies this distribution.  The full text of the license may be found at        \r
+http://opensource.org/licenses/bsd-license.php                                            \r
+                                                                                          \r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     \r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             \r
+\r
+Module Name:\r
+\r
+  PciIo.c\r
+  \r
+Abstract:\r
+\r
+  PCI I/O Abstraction Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "Pcibus.h"\r
+\r
+//\r
+// PCI I/O Support Function Prototypes\r
+//\r
+//\r
+\r
+BOOLEAN \r
+PciDevicesOnTheSamePath (\r
+  IN PCI_IO_DEVICE       *PciDevice1,\r
+  IN PCI_IO_DEVICE       *PciDevice2\r
+);\r
+\r
+\r
+EFI_STATUS \r
+UpStreamBridgesAttributes (\r
+  IN  PCI_IO_DEVICE                            *PciIoDevice,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN  UINT64                                   Attributes\r
+);\r
+\r
+\r
+BOOLEAN \r
+CheckBarType ( \r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  UINT8             BarIndex,\r
+  PCI_BAR_TYPE      BarType\r
+);\r
+\r
+\r
+EFI_STATUS \r
+SetBootVGA ( \r
+  IN  PCI_IO_DEVICE                  *PciIoDevice\r
+);\r
+\r
+EFI_STATUS \r
+DisableBootVGA ( \r
+  IN  PCI_IO_DEVICE                  *PciIoDevice\r
+);\r
+\r
+\r
+EFI_STATUS\r
+PciIoVerifyBarAccess (\r
+  PCI_IO_DEVICE                 *PciIoDevice,\r
+  UINT8                         BarIndex,\r
+  PCI_BAR_TYPE                  Type,\r
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN UINTN                      Count,\r
+  UINT64                        *Offset\r
+);\r
+\r
+EFI_STATUS\r
+PciIoVerifyConfigAccess (\r
+  PCI_IO_DEVICE                 *PciIoDevice,\r
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN UINTN                      Count,\r
+  IN UINT64                     *Offset\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollMem (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+);\r
+  \r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollIo (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+);    \r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoCopyMem (\r
+  IN     EFI_PCI_IO_PROTOCOL  *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT8                        DestBarIndex,\r
+  IN     UINT64                       DestOffset,\r
+  IN     UINT8                        SrcBarIndex,\r
+  IN     UINT64                       SrcOffset,\r
+  IN     UINTN                        Count\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMap (\r
+  IN     EFI_PCI_IO_PROTOCOL            *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,\r
+  IN     VOID                           *HostAddress,\r
+  IN OUT UINTN                          *NumberOfBytes,\r
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,\r
+  OUT    VOID                           **Mapping\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoUnmap (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  IN  VOID                 *Mapping\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAllocateBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL    *This,\r
+  IN  EFI_ALLOCATE_TYPE      Type,\r
+  IN  EFI_MEMORY_TYPE        MemoryType,\r
+  IN  UINTN                  Pages,\r
+  OUT VOID                   **HostAddress,\r
+  IN  UINT64                 Attributes\r
+);\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFreeBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL   *This,\r
+  IN  UINTN                 Pages,\r
+  IN  VOID                  *HostAddress\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFlush (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetLocation (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  OUT UINTN                *Segment,\r
+  OUT UINTN                *Bus,\r
+  OUT UINTN                *Device,\r
+  OUT UINTN                *Function\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAttributes (\r
+  IN  EFI_PCI_IO_PROTOCOL              *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN  UINT64                                   Attributes,\r
+  OUT UINT64                                   *Result   OPTIONAL\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetBarAttributes(\r
+  IN  EFI_PCI_IO_PROTOCOL    *This,\r
+  IN  UINT8                          BarIndex,\r
+  OUT UINT64                         *Supports,   OPTIONAL\r
+  OUT VOID                           **Resources  OPTIONAL\r
+  );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoSetBarAttributes(\r
+  IN     EFI_PCI_IO_PROTOCOL  *This,\r
+  IN     UINT64                       Attributes,\r
+  IN     UINT8                        BarIndex,\r
+  IN OUT UINT64                       *Offset,\r
+  IN OUT UINT64                       *Length\r
+  );\r
+\r
+\r
+//\r
+// Pci Io Protocol Interface\r
+//\r
+static EFI_PCI_IO_PROTOCOL  PciIoInterface = {\r
+  PciIoPollMem,\r
+  PciIoPollIo,\r
+  {\r
+    PciIoMemRead,\r
+    PciIoMemWrite\r
+  },\r
+  {\r
+    PciIoIoRead,\r
+    PciIoIoWrite\r
+  },\r
+  {\r
+    PciIoConfigRead,\r
+    PciIoConfigWrite\r
+  },\r
+  PciIoCopyMem,\r
+  PciIoMap,\r
+  PciIoUnmap,\r
+  PciIoAllocateBuffer,\r
+  PciIoFreeBuffer,\r
+  PciIoFlush,\r
+  PciIoGetLocation,\r
+  PciIoAttributes,\r
+  PciIoGetBarAttributes,\r
+  PciIoSetBarAttributes,\r
+  0,\r
+  NULL\r
+};\r
+\r
+\r
+EFI_STATUS\r
+InitializePciIoInstance (\r
+  PCI_IO_DEVICE  *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Initializes a PCI I/O Instance\r
+\r
+Arguments:\r
+  \r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+\r
+{\r
+  CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL));\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoVerifyBarAccess (\r
+  PCI_IO_DEVICE                   *PciIoDevice,\r
+  UINT8                           BarIndex,\r
+  PCI_BAR_TYPE                    Type,\r
+  IN EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN UINTN                        Count,\r
+  UINT64                          *Offset\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Verifies access to a PCI Base Address Register (BAR)\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // BarIndex 0-5 is legal\r
+  //\r
+  if (BarIndex >= PCI_MAX_BAR) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (!CheckBarType (PciIoDevice, BarIndex, Type)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX\r
+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
+  //\r
+  if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {\r
+    Count = 1;\r
+  }\r
+\r
+  Width &= 0x03;\r
+\r
+  if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciIoVerifyConfigAccess (\r
+  PCI_IO_DEVICE                 *PciIoDevice,\r
+  IN EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN UINTN                      Count,\r
+  IN UINT64                     *Offset\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Verifies access to a PCI Config Header\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  UINT64  ExtendOffset;\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX\r
+  // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX\r
+  //\r
+  Width &= 0x03;\r
+\r
+  if (PciIoDevice->IsPciExp) {\r
+    if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    ExtendOffset  = LShiftU64 (*Offset, 32);\r
+    *Offset       = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0);\r
+    *Offset       = (*Offset) | ExtendOffset;\r
+\r
+  } else {\r
+    if ((*Offset + Count * ((UINTN)1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) {\r
+      return EFI_UNSUPPORTED;\r
+    }\r
+\r
+    *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollMem (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Poll PCI Memmory\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (Width > EfiPciIoWidthUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->PollMem (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                          Offset,\r
+                                          Mask,\r
+                                          Value,\r
+                                          Delay,\r
+                                          Result\r
+                                          );\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoPollIo (\r
+  IN  EFI_PCI_IO_PROTOCOL        *This,\r
+  IN  EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN  UINT8                      BarIndex,\r
+  IN  UINT64                     Offset,\r
+  IN  UINT64                     Mask,\r
+  IN  UINT64                     Value,\r
+  IN  UINT64                     Delay,\r
+  OUT UINT64                     *Result\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Poll PCI IO\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width > EfiPciIoWidthUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->PollIo (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                          Offset,\r
+                                          Mask,\r
+                                          Value,\r
+                                          Delay,\r
+                                          Result\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI Memory Read Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  if (Buffer == NULL){\r
+         return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Mem.Read (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMemWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI Memory Write Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  if (Buffer == NULL){\r
+         return EFI_INVALID_PARAMETER;\r
+  }\r
+  \r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Mem.Write (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI I/O Read Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  if (Buffer == NULL){\r
+         return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Io.Read (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoIoWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT8                      BarIndex,\r
+  IN     UINT64                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI I/O Write Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  if (Buffer == NULL){\r
+         return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Io.Write (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Offset,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigRead (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI Configuration Read Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  UINT64        Address;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Address     = Offset;\r
+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Pci.Read (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Address,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoConfigWrite (\r
+  IN     EFI_PCI_IO_PROTOCOL        *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH  Width,\r
+  IN     UINT32                     Offset,\r
+  IN     UINTN                      Count,\r
+  IN OUT VOID                       *Buffer\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Performs a PCI Configuration Write Cycle\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  UINT64        Address;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Address     = Offset;\r
+  Status      = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Pci.Write (\r
+                                              PciIoDevice->PciRootBridgeIo,\r
+                                              (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                              Address,\r
+                                              Count,\r
+                                              Buffer\r
+                                              );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoCopyMem (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_WIDTH    Width,\r
+  IN     UINT8                        DestBarIndex,\r
+  IN     UINT64                       DestOffset,\r
+  IN     UINT8                        SrcBarIndex,\r
+  IN     UINT64                       SrcOffset,\r
+  IN     UINTN                        Count\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Copy PCI Memory\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Width < 0 || Width >= EfiPciIoWidthMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (Width == EfiPciIoWidthFifoUint8  ||\r
+      Width == EfiPciIoWidthFifoUint16 ||\r
+      Width == EfiPciIoWidthFifoUint32 ||\r
+      Width == EfiPciIoWidthFifoUint64 ||\r
+      Width == EfiPciIoWidthFillUint8  ||\r
+      Width == EfiPciIoWidthFillUint16 ||\r
+      Width == EfiPciIoWidthFillUint32 ||\r
+      Width == EfiPciIoWidthFillUint64) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->CopyMem (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width,\r
+                                          DestOffset,\r
+                                          SrcOffset,\r
+                                          Count\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoMap (\r
+  IN     EFI_PCI_IO_PROTOCOL            *This,\r
+  IN     EFI_PCI_IO_PROTOCOL_OPERATION  Operation,\r
+  IN     VOID                           *HostAddress,\r
+  IN OUT UINTN                          *NumberOfBytes,\r
+  OUT    EFI_PHYSICAL_ADDRESS           *DeviceAddress,\r
+  OUT    VOID                           **Mapping\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Maps a memory region for DMA\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {\r
+    Operation = Operation + EfiPciOperationBusMasterRead64;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Map (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation,\r
+                                          HostAddress,\r
+                                          NumberOfBytes,\r
+                                          DeviceAddress,\r
+                                          Mapping\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoUnmap (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  IN  VOID                 *Mapping\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Unmaps a memory region for DMA\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->Unmap (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          Mapping\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAllocateBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL   *This,\r
+  IN  EFI_ALLOCATE_TYPE     Type,\r
+  IN  EFI_MEMORY_TYPE       MemoryType,\r
+  IN  UINTN                 Pages,\r
+  OUT VOID                  **HostAddress,\r
+  IN  UINT64                Attributes\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Allocates a common buffer for DMA\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  if (Attributes &\r
+      (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) {\r
+    Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+  }\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          Type,\r
+                                          MemoryType,\r
+                                          Pages,\r
+                                          HostAddress,\r
+                                          Attributes\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFreeBuffer (\r
+  IN  EFI_PCI_IO_PROTOCOL   *This,\r
+  IN  UINTN                 Pages,\r
+  IN  VOID                  *HostAddress\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Frees a common buffer \r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  \r
+  if( HostAddress == NULL ){\r
+        return EFI_INVALID_PARAMETER;\r
+  } \r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  Status = PciIoDevice->PciRootBridgeIo->FreeBuffer (\r
+                                          PciIoDevice->PciRootBridgeIo,\r
+                                          Pages,\r
+                                          HostAddress\r
+                                          );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoFlush (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Flushes a DMA buffer\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+\r
+{\r
+  EFI_STATUS    Status;\r
+  UINT32         Register;\r
+  PCI_IO_DEVICE  *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  //\r
+  // If the device is behind a PCI-PCI Bridge, then perform a read cycles to the device to \r
+  // flush the posted write cycles through the PCI-PCI bridges\r
+  //\r
+  if (PciIoDevice->Parent != NULL) {\r
+    Status = This->Pci.Read (This, EfiPciIoWidthUint32, 0, 1, &Register);\r
+  }\r
+\r
+  //\r
+  // Call the PCI Root Bridge I/O Protocol to flush the posted write cycles through the chipset\r
+  //\r
+  Status = PciIoDevice->PciRootBridgeIo->Flush (\r
+                                           PciIoDevice->PciRootBridgeIo\r
+                                           );\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetLocation (\r
+  IN  EFI_PCI_IO_PROTOCOL  *This,\r
+  OUT UINTN                *Segment,\r
+  OUT UINTN                *Bus,\r
+  OUT UINTN                *Device,\r
+  OUT UINTN                *Function\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Gets a PCI device's current bus number, device number, and function number.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  *Segment  = PciIoDevice->PciRootBridgeIo->SegmentNumber;\r
+  *Bus      = PciIoDevice->BusNumber;\r
+  *Device   = PciIoDevice->DeviceNumber;\r
+  *Function = PciIoDevice->FunctionNumber;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+CheckBarType (\r
+  IN PCI_IO_DEVICE       *PciIoDevice,\r
+  UINT8                  BarIndex,\r
+  PCI_BAR_TYPE           BarType\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Sets a PCI controllers attributes on a resource range\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  switch (BarType) {\r
+\r
+  case PciBarTypeMem:\r
+\r
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32  &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64    ) {\r
+      return FALSE;\r
+    }\r
+\r
+    return TRUE;\r
+\r
+  case PciBarTypeIo:\r
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 &&\r
+        PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){\r
+      return FALSE;\r
+    }\r
+\r
+    return TRUE;\r
+\r
+  default:\r
+    break;\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL                       * This,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN  UINT64                                   Attributes,\r
+  OUT UINT64                                   *Result OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  PCI_IO_DEVICE *Temp;\r
+  UINT64         NewAttributes;\r
+  UINT64         PciRootBridgeSupports;\r
+  UINT64         PciRootBridgeAttributes;\r
+  UINT64         NewPciRootBridgeAttributes;\r
+  UINT64         NewUpStreamBridgeAttributes;\r
+  UINT64         ModifiedPciRootBridgeAttributes;\r
+  UINT16         EnableCommand;\r
+  UINT16         DisableCommand;\r
+  UINT16         EnableBridge;\r
+  UINT16         DisableBridge;\r
+  UINT16         Command;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+  NewUpStreamBridgeAttributes = 0;\r
+\r
+  EnableCommand   = 0;\r
+  DisableCommand  = 0;\r
+  EnableBridge    = 0;\r
+  DisableBridge   = 0;\r
+\r
+  switch (Operation) {\r
+  case EfiPciIoAttributeOperationGet:\r
+    if (Result == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    *Result = PciIoDevice->Attributes;\r
+    return EFI_SUCCESS;\r
+\r
+  case EfiPciIoAttributeOperationSupported:\r
+    if (Result == NULL) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    *Result = PciIoDevice->Supports;\r
+    return EFI_SUCCESS;\r
+\r
+  case EfiPciIoAttributeOperationEnable:\r
+         if(Attributes & ~(PciIoDevice->Supports)) {\r
+                 return EFI_UNSUPPORTED;\r
+         }\r
+         NewAttributes = PciIoDevice->Attributes | Attributes;\r
+    break;\r
+  case EfiPciIoAttributeOperationDisable:\r
+         if(Attributes & ~(PciIoDevice->Supports)) {\r
+                 return EFI_UNSUPPORTED;\r
+         }\r
+    NewAttributes = PciIoDevice->Attributes & (~Attributes);\r
+    break;\r
+  case EfiPciIoAttributeOperationSet:\r
+         if(Attributes & ~(PciIoDevice->Supports)) {\r
+                 return EFI_UNSUPPORTED;\r
+         }\r
+    NewAttributes = Attributes;\r
+    break;\r
+  default:\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  //\r
+  // If VGA_IO is set, then set VGA_MEMORY too.  This driver can not enable them seperately.\r
+  //\r
+  if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {\r
+    NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
+  }\r
+\r
+  //\r
+  // If VGA_MEMORY is set, then set VGA_IO too.  This driver can not enable them seperately.\r
+  //\r
+  if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY) {\r
+    NewAttributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+  }\r
+\r
+  //\r
+  // If the attributes are already set correctly, then just return EFI_SUCCESS;\r
+  //\r
+  if ((NewAttributes ^ PciIoDevice->Attributes) == 0) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // This driver takes care of EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_MEMORY, and\r
+  // EFI_PCI_IO_ATTRIBUTE_BUS_MASTER.  Strip these 3 bits off the new attribute mask so\r
+  // a call to the PCI Root Bridge I/O Protocol can be made\r
+  //\r
+\r
+  if (!IS_PCI_BRIDGE(&PciIoDevice->Pci)) {\r
+    NewPciRootBridgeAttributes = NewAttributes & (~(EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));\r
+\r
+    //  \r
+    // Get the current attributes of this PCI device's PCI Root Bridge\r
+    //\r
+    Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
+                                            PciIoDevice->PciRootBridgeIo,\r
+                                            &PciRootBridgeSupports,\r
+                                            &PciRootBridgeAttributes\r
+                                            );\r
+\r
+    //\r
+    // Check to see if any of the PCI Root Bridge attributes are being modified\r
+    //\r
+    ModifiedPciRootBridgeAttributes = NewPciRootBridgeAttributes ^ PciRootBridgeAttributes;\r
+    if (ModifiedPciRootBridgeAttributes) {\r
+\r
+      //\r
+      // Check to see if the PCI Root Bridge supports modifiying the attributes that are changing\r
+      //\r
+      if ((ModifiedPciRootBridgeAttributes & PciRootBridgeSupports) != ModifiedPciRootBridgeAttributes) {\r
+  //     return EFI_UNSUPPORTED;\r
+      }\r
+      //\r
+      // Call the PCI Root Bridge to attempt to modify the attributes\r
+      //\r
+      Status = PciIoDevice->PciRootBridgeIo->SetAttributes (\r
+                                             PciIoDevice->PciRootBridgeIo,\r
+                                             NewPciRootBridgeAttributes,\r
+                                             NULL,\r
+                                             NULL\r
+                                             );\r
+      if (EFI_ERROR (Status)) {\r
+      //\r
+      // The PCI Root Bridge could not modify the attributes, so return the error.\r
+      //\r
+        return Status;\r
+      }\r
+    }\r
+  }\r
+\r
+\r
+  if (IS_PCI_BRIDGE(&PciIoDevice->Pci)) {\r
+\r
+\r
+    //\r
+    // Check to see if an VGA related attributes are being set.\r
+    //\r
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {\r
+\r
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {\r
+        EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;\r
+      } else {\r
+        DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_VGA;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Check to see if an VGA related attributes are being set.\r
+    // If ISA Enable on the PPB is set, the PPB will block the\r
+    // 0x100-0x3FF for each 1KB block in the first 64K I/O block\r
+    //\r
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO)) {\r
+\r
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) {\r
+        DisableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;\r
+      } else {\r
+        EnableBridge  |= EFI_PCI_BRIDGE_CONTROL_ISA;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Check to see if an VGA related attributes are being set.\r
+    //\r
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {\r
+\r
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) {\r
+        EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+      } else {\r
+        DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+      }\r
+    }\r
+\r
+  } else {\r
+\r
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO)) {\r
+\r
+      if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) {\r
+\r
+        //\r
+        //Check if there have been an active VGA device on the same segment\r
+        //\r
+        Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+\r
+        if (Temp && Temp != PciIoDevice) {\r
+          return EFI_UNSUPPORTED;\r
+        }\r
+      }\r
+    }\r
+\r
+    if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO)) {\r
+      if (IS_PCI_GFX(&PciIoDevice->Pci)) {\r
+\r
+        //\r
+        //Get the boot VGA on the same segement\r
+        //\r
+        Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice);\r
+\r
+        if (!Temp) {\r
+\r
+          //\r
+          // If there is no VGA device on the segement, set\r
+          // this graphics card to decode the palette range\r
+          //\r
+          DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+        } else {\r
+\r
+          //\r
+          // Check these two agents are on the same path\r
+          //\r
+          if (PciDevicesOnTheSamePath(Temp, PciIoDevice)) {\r
+\r
+            //\r
+            // Check if they are on the same bus\r
+            //\r
+            if (Temp->Parent == PciIoDevice->Parent) {\r
+\r
+              PciReadCommandRegister (Temp, &Command);\r
+\r
+              //\r
+              // If they are on the same bus, either one can\r
+              // be set to snoop, the other set to decode\r
+              //\r
+              if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {\r
+                DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+              } else {\r
+                EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+              }\r
+            } else {\r
+\r
+              //\r
+              // If they are on  the same path but on the different bus\r
+              // The first agent is set to snoop, the second one set to\r
+              // decode\r
+              //\r
+              if (Temp->BusNumber > PciIoDevice->BusNumber) {\r
+                PciEnableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+                DisableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+              } else {\r
+                PciDisableCommandRegister(Temp,EFI_PCI_COMMAND_VGA_PALETTE_SNOOP);\r
+                EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+              }\r
+            }\r
+          } else {\r
+\r
+            EnableCommand  |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+          }\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check to see of the I/O enable is being modified\r
+  //\r
+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_IO)) {\r
+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_IO) {\r
+      EnableCommand |= EFI_PCI_COMMAND_IO_SPACE;\r
+    } else {\r
+      DisableCommand |= EFI_PCI_COMMAND_IO_SPACE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check to see of the Memory enable is being modified\r
+  //\r
+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)) {\r
+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) {\r
+      EnableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;\r
+    } else {\r
+      DisableCommand |= EFI_PCI_COMMAND_MEMORY_SPACE;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check to see of the Bus Master enable is being modified\r
+  //\r
+  if ((NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) ^ (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER)) {\r
+    if (NewAttributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) {\r
+      EnableCommand  |= EFI_PCI_COMMAND_BUS_MASTER;\r
+    } else {\r
+      DisableCommand |= EFI_PCI_COMMAND_BUS_MASTER;\r
+    }\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+  if (EnableCommand) {\r
+    Status = PciEnableCommandRegister(PciIoDevice, EnableCommand);\r
+  } \r
+\r
+  if (DisableCommand) {\r
+    Status = PciDisableCommandRegister(PciIoDevice, DisableCommand);\r
+  }\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  if (EnableBridge) {\r
+    Status = PciEnableBridgeControlRegister(PciIoDevice, EnableBridge);\r
+  }\r
+\r
+  if (DisableBridge) {\r
+    Status = PciDisableBridgeControlRegister(PciIoDevice, DisableBridge);\r
+  }\r
+   \r
+  if (EFI_ERROR(Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Set the upstream bridge attributes\r
+  //\r
+  if (Operation != EfiPciIoAttributeOperationGet && Operation != EfiPciIoAttributeOperationSupported) {\r
+\r
+    //\r
+    // EFI_PCI_IO_ATTRIBUTE_MEMORY, EFI_PCI_IO_ATTRIBUTE_IO, EFI_PCI_IO_ATTRIBUTE_BUS_MASTER\r
+    // EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED\r
+    // EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE will not effect to upstream bridge\r
+    // \r
+    NewUpStreamBridgeAttributes = Attributes & \\r
+                                (~(EFI_PCI_IO_ATTRIBUTE_IO | \\r
+                                EFI_PCI_IO_ATTRIBUTE_MEMORY | \\r
+                                EFI_PCI_IO_ATTRIBUTE_BUS_MASTER | \\r
+                                EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | \\r
+                                EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | \\r
+                                EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE));\r
+\r
+    if (NewUpStreamBridgeAttributes){\r
+      UpStreamBridgesAttributes(PciIoDevice, Operation, NewUpStreamBridgeAttributes);\r
+    }\r
+  }\r
+  \r
+  PciIoDevice->Attributes = NewAttributes;\r
+\r
+  return Status;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoGetBarAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL             * This,\r
+  IN  UINT8                          BarIndex,\r
+  OUT UINT64                         *Supports, OPTIONAL\r
+  OUT VOID                           **Resources OPTIONAL\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+\r
+  UINT8                             *Configuration;\r
+  UINT8                             NumConfig;\r
+  PCI_IO_DEVICE                     *PciIoDevice;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+  EFI_ACPI_END_TAG_DESCRIPTOR       *PtrEnd;\r
+\r
+  NumConfig   = 0;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  if (Supports == NULL && Resources == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (BarIndex >= PCI_MAX_BAR) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // This driver does not support modifications to the WRITE_COMBINE or\r
+  // CACHED attributes for BAR ranges.\r
+  //\r
+  if (Supports != NULL) {\r
+    *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
+  }\r
+\r
+  if (Resources != NULL) {\r
+\r
+    if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) {\r
+      NumConfig = 1;\r
+    }\r
+\r
+    Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));\r
+    if (Configuration == NULL) {\r
+      return EFI_OUT_OF_RESOURCES;\r
+    }\r
+\r
+    ZeroMem (\r
+      Configuration,\r
+      sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)\r
+      );\r
+\r
+    Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+\r
+    if (NumConfig == 1) {\r
+      Ptr->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;\r
+      Ptr->Len          = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;\r
+\r
+      Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress;\r
+      Ptr->AddrLen      = PciIoDevice->PciBar[BarIndex].Length;\r
+      Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment;\r
+\r
+      switch (PciIoDevice->PciBar[BarIndex].BarType) {\r
+      case PciBarTypeIo16:\r
+      case PciBarTypeIo32:\r
+        //\r
+        // Io\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;\r
+        break;\r
+\r
+      case PciBarTypeMem32:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // 32 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 32;\r
+        break;\r
+\r
+      case PciBarTypePMem32:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // prefechable\r
+        //\r
+        Ptr->SpecificFlag = 0x6;\r
+        //\r
+        // 32 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 32;\r
+        break;\r
+\r
+      case PciBarTypeMem64:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // 64 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 64;\r
+        break;\r
+\r
+      case PciBarTypePMem64:\r
+        //\r
+        // Mem\r
+        //\r
+        Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;\r
+        //\r
+        // prefechable\r
+        //\r
+        Ptr->SpecificFlag = 0x6;\r
+        //\r
+        // 64 bit\r
+        //\r
+        Ptr->AddrSpaceGranularity = 64;\r
+        break;\r
+      }\r
+\r
+      Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));\r
+    }\r
+    \r
+    //\r
+    // put the checksum\r
+    //\r
+    PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);\r
+    PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;\r
+    PtrEnd->Checksum  = 0;\r
+\r
+    *Resources        = Configuration;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+PciIoSetBarAttributes (\r
+  IN EFI_PCI_IO_PROTOCOL              *This,\r
+  IN     UINT64                       Attributes,\r
+  IN     UINT8                        BarIndex,\r
+  IN OUT UINT64                       *Offset,\r
+  IN OUT UINT64                       *Length\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+  UINT64        NonRelativeOffset;\r
+  UINT64        Supports;\r
+\r
+  PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This);\r
+\r
+  //\r
+  // Make sure Offset and Length are not NULL\r
+  //\r
+  if (Offset == NULL || Length == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // This driver does not support setting the WRITE_COMBINE or the CACHED attributes.\r
+  // If Attributes is not 0, then return EFI_UNSUPPORTED.\r
+  //\r
+  Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE;\r
+\r
+  if (Attributes != (Attributes & Supports)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+  //\r
+  // Attributes must be supported.  Make sure the BAR range describd by BarIndex, Offset, and\r
+  // Length are valid for this PCI device.\r
+  //\r
+  NonRelativeOffset = *Offset;\r
+  Status = PciIoVerifyBarAccess (\r
+            PciIoDevice,\r
+            BarIndex,\r
+            PciBarTypeMem,\r
+            EfiPciIoWidthUint8,\r
+            (UINT32) *Length,\r
+            &NonRelativeOffset\r
+            );\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+UpStreamBridgesAttributes (\r
+  IN  PCI_IO_DEVICE                            *PciIoDevice,\r
+  IN  EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION  Operation,\r
+  IN  UINT64                                   Attributes\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+{\r
+  PCI_IO_DEVICE       *Parent;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  Parent = PciIoDevice->Parent;\r
+\r
+  while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) {\r
+\r
+    //\r
+    // Get the PciIo Protocol\r
+    //\r
+    PciIo = &Parent->PciIo;\r
+\r
+    PciIo->Attributes (PciIo, Operation, Attributes, NULL);\r
+\r
+    Parent = Parent->Parent;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+BOOLEAN\r
+PciDevicesOnTheSamePath (\r
+  IN PCI_IO_DEVICE        *PciDevice1,\r
+  IN PCI_IO_DEVICE        *PciDevice2\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+  PciDevice1  -  The pointer to the first PCI_IO_DEVICE.\r
+  PciDevice2  -  The pointer to the second PCI_IO_DEVICE.\r
+\r
+Returns:\r
+\r
+  TRUE   -  The two Pci devices are on the same path.\r
+  FALSE  -  The two Pci devices are not on the same path.\r
+\r
+--*/\r
+{\r
+\r
+  if (PciDevice1->Parent == PciDevice2->Parent) {\r
+    return TRUE;\r
+  }\r
+\r
+  return (PciDeviceExisted (PciDevice1->Parent, PciDevice2)|| PciDeviceExisted (PciDevice2->Parent, PciDevice1));\r
+}\r