]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c
Add PciBus & IdeBus
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBus / Dxe / PciEnumeratorSupport.c
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c b/IntelFrameworkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c
new file mode 100644 (file)
index 0000000..8020ab1
--- /dev/null
@@ -0,0 +1,2254 @@
+/*++\r
+\r
+Copyright (c) 2006 - 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
+  PciEnumeratorSupport.c\r
+\r
+Abstract:\r
+\r
+  PCI Bus Driver\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+#include "pcibus.h"\r
+#include "PciEnumeratorSupport.h"\r
+#include "PciCommand.h"\r
+#include "PciIo.h"\r
+\r
+EFI_STATUS\r
+PciDevicePresent (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  PCI_TYPE00                          *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine is used to check whether the pci device is present\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciRootBridgeIo - add argument and description to function comment\r
+// TODO:    Pci - add argument and description to function comment\r
+// TODO:    Bus - add argument and description to function comment\r
+// TODO:    Device - add argument and description to function comment\r
+// TODO:    Func - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+// TODO:    EFI_NOT_FOUND - add return value to function comment\r
+{\r
+  UINT64      Address;\r
+  EFI_STATUS  Status;\r
+\r
+  //\r
+  // Create PCI address map in terms of Bus, Device and Func\r
+  //\r
+  Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0);\r
+\r
+  //\r
+  // Read the Vendor Id register\r
+  //\r
+  Status = PciRootBridgeIoRead (\r
+                                  PciRootBridgeIo,\r
+                                  NULL,\r
+                                  EfiPciWidthUint32,\r
+                                  Address,\r
+                                  1,\r
+                                  Pci\r
+                                  );\r
+\r
+  if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) {\r
+\r
+    //\r
+    // Read the entire config header for the device\r
+    //\r
+\r
+    Status = PciRootBridgeIoRead (\r
+                                    PciRootBridgeIo,\r
+                                    NULL,\r
+                                    EfiPciWidthUint32,\r
+                                    Address,\r
+                                    sizeof (PCI_TYPE00) / sizeof (UINT32),\r
+                                    Pci\r
+                                    );\r
+\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+PciPciDeviceInfoCollector (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  UINT8                                 StartBusNumber\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    StartBusNumber - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_STATUS          Status;\r
+  PCI_TYPE00          Pci;\r
+  UINT8               Device;\r
+  UINT8               Func;\r
+  UINT8               SecBus;\r
+  PCI_IO_DEVICE       *PciIoDevice;\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  Status  = EFI_SUCCESS;\r
+  SecBus  = 0;\r
+\r
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+\r
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
+\r
+      //\r
+      // Check to see whether PCI device is present\r
+      //\r
+\r
+      Status = PciDevicePresent (\r
+                Bridge->PciRootBridgeIo,\r
+                &Pci,\r
+                (UINT8) StartBusNumber,\r
+                (UINT8) Device,\r
+                (UINT8) Func\r
+                );\r
+\r
+      if (!EFI_ERROR (Status)) {\r
+\r
+        //\r
+        // Call back to host bridge function\r
+        //\r
+        PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection);\r
+\r
+        //\r
+        // Collect all the information about the PCI device discovered\r
+        //\r
+        Status = PciSearchDevice (\r
+                  Bridge,\r
+                  &Pci,\r
+                  (UINT8) StartBusNumber,\r
+                  Device,\r
+                  Func,\r
+                  &PciIoDevice\r
+                  );\r
+\r
+        //\r
+        // Recursively scan PCI busses on the other side of PCI-PCI bridges\r
+        //\r
+        //\r
+\r
+        if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {\r
+\r
+          //\r
+          // If it is PPB, we need to get the secondary bus to continue the enumeration\r
+          //\r
+          PciIo   = &(PciIoDevice->PciIo);\r
+\r
+          Status  = PciIoRead (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus);\r
+\r
+          if (EFI_ERROR (Status)) {\r
+            return Status;\r
+          }\r
+\r
+          //\r
+          // Get resource padding for PPB\r
+          //\r
+          GetResourcePaddingPpb (PciIoDevice);\r
+\r
+          //\r
+          // Deep enumerate the next level bus\r
+          //\r
+          Status = PciPciDeviceInfoCollector (\r
+                    PciIoDevice,\r
+                    (UINT8) (SecBus)\r
+                    );\r
+\r
+        }\r
+\r
+        if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
+\r
+          //\r
+          // Skip sub functions, this is not a multi function device\r
+          //\r
+          Func = PCI_MAX_FUNC;\r
+        }\r
+      }\r
+\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciSearchDevice (\r
+  IN  PCI_IO_DEVICE                         *Bridge,\r
+  IN  PCI_TYPE00                            *Pci,\r
+  IN  UINT8                                 Bus,\r
+  IN  UINT8                                 Device,\r
+  IN  UINT8                                 Func,\r
+  OUT PCI_IO_DEVICE                         **PciDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Search required device.\r
+\r
+Arguments:\r
+\r
+  Bridge     - A pointer to the PCI_IO_DEVICE.\r
+  Pci        - A pointer to the PCI_TYPE00.\r
+  Bus        - Bus number.\r
+  Device     - Device number.\r
+  Func       - Function number.\r
+  PciDevice  - The Required pci device.\r
+\r
+Returns:\r
+\r
+  Status code.\r
+\r
+--*/\r
+// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// TODO:    EFI_OUT_OF_RESOURCES - add return value to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = NULL;\r
+\r
+  if (!IS_PCI_BRIDGE (Pci)) {\r
+\r
+    if (IS_CARDBUS_BRIDGE (Pci)) {\r
+      PciIoDevice = GatherP2CInfo (\r
+                      Bridge,\r
+                      Pci,\r
+                      Bus,\r
+                      Device,\r
+                      Func\r
+                      );\r
+      if ((PciIoDevice != NULL) && gFullEnumeration) {\r
+        InitializeP2C (PciIoDevice);\r
+      }\r
+    } else {\r
+\r
+      //\r
+      // Create private data for Pci Device\r
+      //\r
+      PciIoDevice = GatherDeviceInfo (\r
+                      Bridge,\r
+                      Pci,\r
+                      Bus,\r
+                      Device,\r
+                      Func\r
+                      );\r
+\r
+    }\r
+\r
+  } else {\r
+\r
+    //\r
+    // Create private data for PPB\r
+    //\r
+    PciIoDevice = GatherPpbInfo (\r
+                    Bridge,\r
+                    Pci,\r
+                    Bus,\r
+                    Device,\r
+                    Func\r
+                    );\r
+\r
+    //\r
+    // Special initialization for PPB including making the PPB quiet\r
+    //\r
+    if ((PciIoDevice != NULL) && gFullEnumeration) {\r
+      InitializePpb (PciIoDevice);\r
+    }\r
+  }\r
+\r
+  if (!PciIoDevice) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Update the bar information for this PCI device so as to support some specific device\r
+  //\r
+  if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask) & PCI_INCOMPATIBLE_ACPI_RESOURCE_SUPPORT) {\r
+    UpdatePciInfo (PciIoDevice);\r
+  }\r
+\r
+  if (PciIoDevice->DevicePath == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  //\r
+  // Detect this function has option rom\r
+  //\r
+  if (gFullEnumeration) {\r
+\r
+    if (!IS_CARDBUS_BRIDGE (Pci)) {\r
+\r
+      GetOpRomInfo (PciIoDevice);\r
+\r
+    }\r
+\r
+    ResetPowerManagementFeature (PciIoDevice);\r
+\r
+  }\r
+\r
+  //\r
+  // Insert it into a global tree for future reference\r
+  //\r
+  InsertPciDevice (Bridge, PciIoDevice);\r
+\r
+  //\r
+  // Determine PCI device attributes\r
+  //\r
+\r
+  if (PciDevice != NULL) {\r
+    *PciDevice = PciIoDevice;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+GatherDeviceInfo (\r
+  IN PCI_IO_DEVICE                    *Bridge,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    Pci - add argument and description to function comment\r
+// TODO:    Bus - add argument and description to function comment\r
+// TODO:    Device - add argument and description to function comment\r
+// TODO:    Func - add argument and description to function comment\r
+{\r
+  UINTN                           Offset;\r
+  UINTN                           BarIndex;\r
+  PCI_IO_DEVICE                   *PciIoDevice;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+  PciIoDevice = CreatePciIoDevice (\r
+                  PciRootBridgeIo,\r
+                  Pci,\r
+                  Bus,\r
+                  Device,\r
+                  Func\r
+                  );\r
+\r
+  if (!PciIoDevice) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Create a device path for this PCI device and store it into its private data\r
+  //\r
+  CreatePciDevicePath (\r
+    Bridge->DevicePath,\r
+    PciIoDevice\r
+    );\r
+\r
+  //\r
+  // If it is a full enumeration, disconnect the device in advance\r
+  //\r
+  if (gFullEnumeration) {\r
+\r
+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+  }\r
+\r
+  //\r
+  // Start to parse the bars\r
+  //\r
+  for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) {\r
+    Offset = PciParseBar (PciIoDevice, Offset, BarIndex);\r
+  }\r
+\r
+  return PciIoDevice;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+GatherPpbInfo (\r
+  IN PCI_IO_DEVICE                    *Bridge,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    Pci - add argument and description to function comment\r
+// TODO:    Bus - add argument and description to function comment\r
+// TODO:    Device - add argument and description to function comment\r
+// TODO:    Func - add argument and description to function comment\r
+{\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+  PCI_IO_DEVICE                   *PciIoDevice;\r
+  EFI_STATUS                      Status;\r
+  UINT32                          Value;\r
+  EFI_PCI_IO_PROTOCOL             *PciIo;\r
+  UINT8                           Temp;\r
+\r
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+  PciIoDevice = CreatePciIoDevice (\r
+                  PciRootBridgeIo,\r
+                  Pci,\r
+                  Bus,\r
+                  Device,\r
+                  Func\r
+                  );\r
+\r
+  if (!PciIoDevice) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Create a device path for this PCI device and store it into its private data\r
+  //\r
+  CreatePciDevicePath (\r
+    Bridge->DevicePath,\r
+    PciIoDevice\r
+    );\r
+\r
+  if (gFullEnumeration) {\r
+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+    //\r
+    // Initalize the bridge control register\r
+    //\r
+    PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED);\r
+\r
+  }\r
+\r
+  //\r
+  // PPB can have two BARs\r
+  //\r
+  if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) {\r
+    //\r
+    // Not 64-bit bar\r
+    //\r
+    PciParseBar (PciIoDevice, 0x14, PPB_BAR_1);\r
+  }\r
+\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  //\r
+  // Test whether it support 32 decode or not\r
+  //\r
+  PciIoRead (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
+  PciIoRead (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value);\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp);\r
+\r
+  if (Value) {\r
+    if (Value & 0x01) {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
+    } else {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;\r
+    }\r
+  }\r
+\r
+  Status = BarExisted (\r
+            PciIoDevice,\r
+            0x24,\r
+            NULL,\r
+            NULL\r
+            );\r
+\r
+  //\r
+  // test if it supports 64 memory or not\r
+  //\r
+  if (!EFI_ERROR (Status)) {\r
+\r
+    Status = BarExisted (\r
+              PciIoDevice,\r
+              0x28,\r
+              NULL,\r
+              NULL\r
+              );\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;\r
+    } else {\r
+      PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Memory 32 code is required for ppb\r
+  //\r
+  PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;\r
+\r
+  GetResourcePaddingPpb (PciIoDevice);\r
+\r
+  return PciIoDevice;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+GatherP2CInfo (\r
+  IN PCI_IO_DEVICE                    *Bridge,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Bridge - add argument and description to function comment\r
+// TODO:    Pci - add argument and description to function comment\r
+// TODO:    Bus - add argument and description to function comment\r
+// TODO:    Device - add argument and description to function comment\r
+// TODO:    Func - add argument and description to function comment\r
+{\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+  PCI_IO_DEVICE                   *PciIoDevice;\r
+\r
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+  PciIoDevice = CreatePciIoDevice (\r
+                  PciRootBridgeIo,\r
+                  Pci,\r
+                  Bus,\r
+                  Device,\r
+                  Func\r
+                  );\r
+\r
+  if (!PciIoDevice) {\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Create a device path for this PCI device and store it into its private data\r
+  //\r
+  CreatePciDevicePath (\r
+    Bridge->DevicePath,\r
+    PciIoDevice\r
+    );\r
+\r
+  if (gFullEnumeration) {\r
+    PciDisableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_BITS_OWNED);\r
+\r
+    //\r
+    // Initalize the bridge control register\r
+    //\r
+    PciDisableBridgeControlRegister (PciIoDevice, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED);\r
+\r
+  }\r
+  //\r
+  // P2C only has one bar that is in 0x10\r
+  //\r
+  PciParseBar (PciIoDevice, 0x10, P2C_BAR_0);\r
+\r
+  //\r
+  // Read PciBar information from the bar register\r
+  //\r
+  GetBackPcCardBar (PciIoDevice);\r
+  PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED  |\r
+                         EFI_BRIDGE_PMEM32_DECODE_SUPPORTED |\r
+                         EFI_BRIDGE_IO32_DECODE_SUPPORTED;\r
+\r
+  return PciIoDevice;\r
+}\r
+\r
+EFI_DEVICE_PATH_PROTOCOL *\r
+CreatePciDevicePath (\r
+  IN  EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath,\r
+  IN  PCI_IO_DEVICE            *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    ParentDevicePath - add argument and description to function comment\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+{\r
+\r
+  PCI_DEVICE_PATH PciNode;\r
+\r
+  //\r
+  // Create PCI device path\r
+  //\r
+  PciNode.Header.Type     = HARDWARE_DEVICE_PATH;\r
+  PciNode.Header.SubType  = HW_PCI_DP;\r
+  SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode));\r
+\r
+  PciNode.Device          = PciIoDevice->DeviceNumber;\r
+  PciNode.Function        = PciIoDevice->FunctionNumber;\r
+  PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header);\r
+\r
+  return PciIoDevice->DevicePath;\r
+}\r
+\r
+EFI_STATUS\r
+BarExisted (\r
+  IN PCI_IO_DEVICE *PciIoDevice,\r
+  IN UINTN         Offset,\r
+  OUT UINT32       *BarLengthValue,\r
+  OUT UINT32       *OriginalBarValue\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Check the bar is existed or not.\r
+\r
+Arguments:\r
+\r
+  PciIoDevice       - A pointer to the PCI_IO_DEVICE.\r
+  Offset            - The offset.\r
+  BarLengthValue    - The bar length value.\r
+  OriginalBarValue  - The original bar value.\r
+\r
+Returns:\r
+\r
+  EFI_NOT_FOUND     - The bar don't exist.\r
+  EFI_SUCCESS       - The bar exist.\r
+\r
+--*/\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT32              OriginalValue;\r
+  UINT32              Value;\r
+  EFI_TPL             OldTpl;\r
+\r
+  PciIo = &PciIoDevice->PciIo;\r
+\r
+  //\r
+  // Preserve the original value\r
+  //\r
+\r
+  PciIoRead (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
+\r
+  //\r
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+  //\r
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne);\r
+  PciIoRead (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value);\r
+\r
+  //\r
+  // Write back the original value\r
+  //\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue);\r
+\r
+  //\r
+  // Restore TPL to its original level\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  if (BarLengthValue != NULL) {\r
+    *BarLengthValue = Value;\r
+  }\r
+\r
+  if (OriginalBarValue != NULL) {\r
+    *OriginalBarValue = OriginalValue;\r
+  }\r
+\r
+  if (Value == 0) {\r
+    return EFI_NOT_FOUND;\r
+  } else {\r
+    return EFI_SUCCESS;\r
+  }\r
+}\r
+\r
+EFI_STATUS\r
+PciTestSupportedAttribute (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice,\r
+  IN UINT16                             *Command,\r
+  IN UINT16                             *BridgeControl,\r
+  IN UINT16                             *OldCommand,\r
+  IN UINT16                             *OldBridgeControl\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+// TODO:    Command - add argument and description to function comment\r
+// TODO:    BridgeControl - add argument and description to function comment\r
+// TODO:    OldCommand - add argument and description to function comment\r
+// TODO:    OldBridgeControl - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_TPL OldTpl;\r
+\r
+  //\r
+  // Preserve the original value\r
+  //\r
+  PciReadCommandRegister (PciIoDevice, OldCommand);\r
+\r
+  //\r
+  // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+  //\r
+  OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+  PciSetCommandRegister (PciIoDevice, *Command);\r
+  PciReadCommandRegister (PciIoDevice, Command);\r
+\r
+  //\r
+  // Write back the original value\r
+  //\r
+  PciSetCommandRegister (PciIoDevice, *OldCommand);\r
+\r
+  //\r
+  // Restore TPL to its original level\r
+  //\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+\r
+    //\r
+    // Preserve the original value\r
+    //\r
+    PciReadBridgeControlRegister (PciIoDevice, OldBridgeControl);\r
+\r
+    //\r
+    // Raise TPL to high level to disable timer interrupt while the BAR is probed\r
+    //\r
+    OldTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);\r
+\r
+    PciSetBridgeControlRegister (PciIoDevice, *BridgeControl);\r
+    PciReadBridgeControlRegister (PciIoDevice, BridgeControl);\r
+\r
+    //\r
+    // Write back the original value\r
+    //\r
+    PciSetBridgeControlRegister (PciIoDevice, *OldBridgeControl);\r
+\r
+    //\r
+    // Restore TPL to its original level\r
+    //\r
+    gBS->RestoreTPL (OldTpl);\r
+\r
+  } else {\r
+    *OldBridgeControl = 0;\r
+    *BridgeControl    = 0;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciSetDeviceAttribute (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice,\r
+  IN UINT16                             Command,\r
+  IN UINT16                             BridgeControl,\r
+  IN UINTN                              Option\r
+  )\r
+/*++\r
+\r
+  Routine Description:\r
+    Set the supported or current attributes of a PCI device\r
+\r
+  Arguments:\r
+    PciIoDevice   - Structure pointer for PCI device.\r
+    Command       - Command register value.\r
+    BridgeControl - Bridge control value for PPB or P2C.\r
+    Option        - Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.\r
+\r
+  Returns:\r
+\r
+--*/\r
+\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+\r
+Arguments:\r
+\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS   Always success\r
+\r
+\r
+--*/\r
+{\r
+  UINT64  Attributes;\r
+\r
+  Attributes = 0;\r
+\r
+  if (Command & EFI_PCI_COMMAND_IO_SPACE) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_IO;\r
+  }\r
+\r
+  if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY;\r
+  }\r
+\r
+  if (Command & EFI_PCI_COMMAND_BUS_MASTER) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER;\r
+  }\r
+\r
+  if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
+  }\r
+\r
+  if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
+  }\r
+\r
+  if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO;\r
+  }\r
+\r
+  if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA_16) {\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16;\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16;\r
+  }\r
+\r
+  if (Option == EFI_SET_SUPPORTS) {\r
+\r
+    Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE |\r
+                  EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED        |\r
+                  EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE       |\r
+                  EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE      |\r
+                  EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM         |\r
+                  EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE;\r
+\r
+    if (Attributes & EFI_PCI_IO_ATTRIBUTE_IO) {\r
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;\r
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO;\r
+    }\r
+\r
+    if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+      //\r
+      // For bridge, it should support IDE attributes\r
+      //\r
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
+      Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
+    } else {\r
+\r
+      if (IS_PCI_IDE (&PciIoDevice->Pci)) {\r
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO;\r
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO;\r
+      }\r
+\r
+      if (IS_PCI_VGA (&PciIoDevice->Pci)) {\r
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY;\r
+        Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO;\r
+      }\r
+    }\r
+\r
+    PciIoDevice->Supports = Attributes;\r
+    PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \\r
+                               EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \\r
+                               EFI_PCI_IO_ATTRIBUTE_BUS_MASTER );\r
+\r
+  } else {\r
+    PciIoDevice->Attributes = Attributes;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+GetFastBackToBackSupport (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice,\r
+  IN UINT8                              StatusIndex\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Determine if the device can support Fast Back to Back attribute\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+// TODO:    StatusIndex - add argument and description to function comment\r
+// TODO:    EFI_UNSUPPORTED - add return value to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+// TODO:    EFI_UNSUPPORTED - add return value to function comment\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  EFI_STATUS          Status;\r
+  UINT32              StatusRegister;\r
+\r
+  //\r
+  // Read the status register\r
+  //\r
+  PciIo   = &PciIoDevice->PciIo;\r
+  Status  = PciIoRead (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister);\r
+  if (EFI_ERROR (Status)) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+  //\r
+  // Check the Fast B2B bit\r
+  //\r
+  if (StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) {\r
+    return EFI_SUCCESS;\r
+  } else {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
+}\r
+\r
+STATIC\r
+EFI_STATUS\r
+ProcessOptionRomLight (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Process the option ROM for all the children of the specified parent PCI device.\r
+  It can only be used after the first full Option ROM process.\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  PCI_IO_DEVICE   *Temp;\r
+  LIST_ENTRY      *CurrentLink;\r
+\r
+  //\r
+  // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
+  //\r
+  CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+  while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {\r
+\r
+    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+\r
+    if (!IsListEmpty (&Temp->ChildList)) {\r
+      ProcessOptionRomLight (Temp);\r
+    }\r
+\r
+    PciRomGetImageMapping (Temp);\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+DetermineDeviceAttribute (\r
+  IN PCI_IO_DEVICE                      *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Determine the related attributes of all devices under a Root Bridge\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  UINT16          Command;\r
+  UINT16          BridgeControl;\r
+  UINT16          OldCommand;\r
+  UINT16          OldBridgeControl;\r
+  BOOLEAN         FastB2BSupport;\r
+\r
+  /*\r
+  UINT8  IdePI;\r
+  EFI_PCI_IO_PROTOCOL   *PciIo;\r
+  */\r
+  PCI_IO_DEVICE   *Temp;\r
+  LIST_ENTRY      *CurrentLink;\r
+  EFI_STATUS      Status;\r
+\r
+  //\r
+  // For Root Bridge, just copy it by RootBridgeIo proctocol\r
+  // so as to keep consistent with the actual attribute\r
+  //\r
+  if (!PciIoDevice->Parent) {\r
+    Status = PciIoDevice->PciRootBridgeIo->GetAttributes (\r
+                                            PciIoDevice->PciRootBridgeIo,\r
+                                            &PciIoDevice->Supports,\r
+                                            &PciIoDevice->Attributes\r
+                                            );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  } else {\r
+\r
+    //\r
+    // Set the attributes to be checked for common PCI devices and PPB or P2C\r
+    // Since some devices only support part of them, it is better to set the\r
+    // attribute according to its command or bridge control register\r
+    //\r
+    Command = EFI_PCI_COMMAND_IO_SPACE     |\r
+              EFI_PCI_COMMAND_MEMORY_SPACE |\r
+              EFI_PCI_COMMAND_BUS_MASTER   |\r
+              EFI_PCI_COMMAND_VGA_PALETTE_SNOOP;\r
+\r
+    BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA | EFI_PCI_BRIDGE_CONTROL_VGA_16;\r
+\r
+    //\r
+    // Test whether the device can support attributes above\r
+    //\r
+    PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl);\r
+\r
+    //\r
+    // Set the supported attributes for specified PCI device\r
+    //\r
+    PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS);\r
+\r
+    //\r
+    // Set the current attributes for specified PCI device\r
+    //\r
+    PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES);\r
+\r
+    //\r
+    // Enable other supported attributes but not defined in PCI_IO_PROTOCOL\r
+    //\r
+    PciEnableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE);\r
+\r
+    //\r
+    // Enable IDE native mode\r
+    //\r
+    /*\r
+    if (IS_PCI_IDE(&PciIoDevice->Pci)) {\r
+\r
+      PciIo = &PciIoDevice->PciIo;\r
+\r
+      PciIoRead (\r
+                              PciIo,\r
+                              EfiPciIoWidthUint8,\r
+                              0x09,\r
+                              1,\r
+                              &IdePI\r
+                              );\r
+\r
+      //\r
+      // Set native mode if it can be supported\r
+      //\r
+      IdePI |= (((IdePI & 0x0F) >> 1) & 0x05);\r
+\r
+      PciIoWrite (\r
+                              PciIo,\r
+                              EfiPciIoWidthUint8,\r
+                              0x09,\r
+                              1,\r
+                              &IdePI\r
+                              );\r
+\r
+    }\r
+    */\r
+  }\r
+\r
+  FastB2BSupport = TRUE;\r
+\r
+  //\r
+  // P2C can not support FB2B on the secondary side\r
+  //\r
+  if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+    FastB2BSupport = FALSE;\r
+  }\r
+\r
+  //\r
+  // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
+  //\r
+  CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+  while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {\r
+\r
+    Temp    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+    Status  = DetermineDeviceAttribute (Temp);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+    //\r
+    // Detect Fast Bact to Bact support for the device under the bridge\r
+    //\r
+    Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET);\r
+    if (FastB2BSupport && EFI_ERROR (Status)) {\r
+      FastB2BSupport = FALSE;\r
+    }\r
+\r
+    CurrentLink = CurrentLink->ForwardLink;\r
+  }\r
+  //\r
+  // Set or clear Fast Back to Back bit for the whole bridge\r
+  //\r
+  if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
+\r
+    if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
+\r
+      Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET);\r
+\r
+      if (EFI_ERROR (Status) || (!FastB2BSupport)) {\r
+        FastB2BSupport = FALSE;\r
+        PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
+      } else {\r
+        PciEnableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK);\r
+      }\r
+    }\r
+\r
+    CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
+    while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {\r
+      Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
+      if (FastB2BSupport) {\r
+        PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
+      } else {\r
+        PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK);\r
+      }\r
+\r
+      CurrentLink = CurrentLink->ForwardLink;\r
+    }\r
+  }\r
+  //\r
+  // End for IsListEmpty\r
+  //\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+UpdatePciInfo (\r
+  IN PCI_IO_DEVICE  *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine is used to update the bar information for those incompatible PCI device\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+// TODO:    EFI_UNSUPPORTED - add return value to function comment\r
+{\r
+  EFI_STATUS                        Status;\r
+  UINTN                             BarIndex;\r
+  UINTN                             BarEndIndex;\r
+  BOOLEAN                           SetFlag;\r
+  EFI_PCI_DEVICE_INFO               PciDeviceInfo;\r
+  VOID                              *Configuration;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
+\r
+  Configuration = NULL;\r
+\r
+  //\r
+  // Check whether the device belongs to incompatible devices or not\r
+  // If it is , then get its special requirement in the ACPI table\r
+  //\r
+  PciDeviceInfo.VendorID          = PciIoDevice->Pci.Hdr.VendorId;\r
+  PciDeviceInfo.DeviceID          = PciIoDevice->Pci.Hdr.DeviceId;\r
+  PciDeviceInfo.RevisionID        = PciIoDevice->Pci.Hdr.RevisionID;\r
+  PciDeviceInfo.SubsystemVendorID = PciIoDevice->Pci.Device.SubsystemVendorID;\r
+  PciDeviceInfo.SubsystemID       = PciIoDevice->Pci.Device.SubsystemID;\r
+\r
+  Status = PciResourceUpdateCheck (&PciDeviceInfo, &Configuration);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Update PCI device information from the ACPI table\r
+  //\r
+  Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
+\r
+  while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+\r
+    if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
+      //\r
+      // The format is not support\r
+      //\r
+      break;\r
+    }\r
+\r
+    BarIndex    = (UINTN) Ptr->AddrTranslationOffset;\r
+    BarEndIndex = BarIndex;\r
+\r
+    //\r
+    // Update all the bars in the device\r
+    //\r
+    if (BarIndex == PCI_BAR_ALL) {\r
+      BarIndex    = 0;\r
+      BarEndIndex = PCI_MAX_BAR - 1;\r
+    }\r
+\r
+    if (BarIndex >= PCI_MAX_BAR) {\r
+      Ptr++;\r
+      continue;\r
+    }\r
+\r
+    for (; BarIndex <= BarEndIndex; BarIndex++) {\r
+      SetFlag = FALSE;\r
+      switch (Ptr->ResType) {\r
+      case ACPI_ADDRESS_SPACE_TYPE_MEM:\r
+\r
+        //\r
+        // Make sure the bar is memory type\r
+        //\r
+        if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) {\r
+          SetFlag = TRUE;\r
+        }\r
+        break;\r
+\r
+      case ACPI_ADDRESS_SPACE_TYPE_IO:\r
+\r
+        //\r
+        // Make sure the bar is IO type\r
+        //\r
+        if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) {\r
+          SetFlag = TRUE;\r
+        }\r
+        break;\r
+      }\r
+\r
+      if (SetFlag) {\r
+\r
+        //\r
+        // Update the new alignment for the device\r
+        //\r
+        SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax);\r
+\r
+        //\r
+        // Update the new length for the device\r
+        //\r
+        if (Ptr->AddrLen != PCI_BAR_NOCHANGE) {\r
+          PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen;\r
+        }\r
+      }\r
+    }\r
+\r
+    Ptr++;\r
+  }\r
+\r
+  gBS->FreePool (Configuration);\r
+  return Status;\r
+\r
+}\r
+\r
+VOID\r
+SetNewAlign (\r
+  IN UINT64 *Alignment,\r
+  IN UINT64 NewAlignment\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine will update the alignment with the new alignment\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Alignment - add argument and description to function comment\r
+// TODO:    NewAlignment - add argument and description to function comment\r
+{\r
+  UINT64  OldAlignment;\r
+  UINTN   ShiftBit;\r
+\r
+  //\r
+  // The new alignment is the same as the original,\r
+  // so skip it\r
+  //\r
+  if (NewAlignment == PCI_BAR_OLD_ALIGN) {\r
+    return ;\r
+  }\r
+  //\r
+  // Check the validity of the parameter\r
+  //\r
+   if (NewAlignment != PCI_BAR_EVEN_ALIGN  &&\r
+       NewAlignment != PCI_BAR_SQUAD_ALIGN &&\r
+       NewAlignment != PCI_BAR_DQUAD_ALIGN ) {\r
+    *Alignment = NewAlignment;\r
+    return ;\r
+  }\r
+\r
+  OldAlignment  = (*Alignment) + 1;\r
+  ShiftBit      = 0;\r
+\r
+  //\r
+  // Get the first non-zero hex value of the length\r
+  //\r
+  while ((OldAlignment & 0x0F) == 0x00) {\r
+    OldAlignment = RShiftU64 (OldAlignment, 4);\r
+    ShiftBit += 4;\r
+  }\r
+\r
+  //\r
+  // Adjust the alignment to even, quad or double quad boundary\r
+  //\r
+  if (NewAlignment == PCI_BAR_EVEN_ALIGN) {\r
+    if (OldAlignment & 0x01) {\r
+      OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01);\r
+    }\r
+  } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) {\r
+    if (OldAlignment & 0x03) {\r
+      OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03);\r
+    }\r
+  } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) {\r
+    if (OldAlignment & 0x07) {\r
+      OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07);\r
+    }\r
+  }\r
+\r
+  //\r
+  // Update the old value\r
+  //\r
+  NewAlignment  = LShiftU64 (OldAlignment, ShiftBit) - 1;\r
+  *Alignment    = NewAlignment;\r
+\r
+  return ;\r
+}\r
+\r
+UINTN\r
+PciParseBar (\r
+  IN PCI_IO_DEVICE  *PciIoDevice,\r
+  IN UINTN          Offset,\r
+  IN UINTN          BarIndex\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+// TODO:    Offset - add argument and description to function comment\r
+// TODO:    BarIndex - add argument and description to function comment\r
+{\r
+  UINT32      Value;\r
+  UINT32      OriginalValue;\r
+  UINT32      Mask;\r
+  UINT32      Data;\r
+  UINT8       Index;\r
+  EFI_STATUS  Status;\r
+\r
+  OriginalValue = 0;\r
+  Value         = 0;\r
+\r
+  Status = BarExisted (\r
+            PciIoDevice,\r
+            Offset,\r
+            &Value,\r
+            &OriginalValue\r
+            );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
+    PciIoDevice->PciBar[BarIndex].Length      = 0;\r
+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;\r
+\r
+    //\r
+    // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway\r
+    //\r
+    PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
+    return Offset + 4;\r
+  }\r
+\r
+  PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset;\r
+  if (Value & 0x01) {\r
+    //\r
+    // Device I/Os\r
+    //\r
+    Mask = 0xfffffffc;\r
+\r
+    if (Value & 0xFFFF0000) {\r
+      //\r
+      // It is a IO32 bar\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo32;\r
+      PciIoDevice->PciBar[BarIndex].Length    = ((~(Value & Mask)) + 1);\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+    } else {\r
+      //\r
+      // It is a IO16 bar\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeIo16;\r
+      PciIoDevice->PciBar[BarIndex].Length    = 0x0000FFFF & ((~(Value & Mask)) + 1);\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+    }\r
+    //\r
+    // Workaround. Some platforms inplement IO bar with 0 length\r
+    // Need to treat it as no-bar\r
+    //\r
+    if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
+      PciIoDevice->PciBar[BarIndex].BarType = (PCI_BAR_TYPE) 0;\r
+    }\r
+\r
+    PciIoDevice->PciBar[BarIndex].Prefetchable  = FALSE;\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress   = OriginalValue & Mask;\r
+\r
+  } else {\r
+\r
+    Mask  = 0xfffffff0;\r
+\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask;\r
+\r
+    switch (Value & 0x07) {\r
+\r
+    //\r
+    //memory space; anywhere in 32 bit address space\r
+    //\r
+    case 0x00:\r
+      if (Value & 0x08) {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32;\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32;\r
+      }\r
+\r
+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+      break;\r
+\r
+    //\r
+    // memory space; anywhere in 64 bit address space\r
+    //\r
+    case 0x04:\r
+      if (Value & 0x08) {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64;\r
+      } else {\r
+        PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64;\r
+      }\r
+\r
+      //\r
+      // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar\r
+      // is regarded as an extension for the first bar. As a result\r
+      // the sizing will be conducted on combined 64 bit value\r
+      // Here just store the masked first 32bit value for future size\r
+      // calculation\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].Length    = Value & Mask;\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+      //\r
+      // Increment the offset to point to next DWORD\r
+      //\r
+      Offset += 4;\r
+\r
+      Status = BarExisted (\r
+                PciIoDevice,\r
+                Offset,\r
+                &Value,\r
+                &OriginalValue\r
+                );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        return Offset + 4;\r
+      }\r
+\r
+      //\r
+      // Fix the length to support some spefic 64 bit BAR\r
+      //\r
+      Data  = Value;\r
+      Index = 0;\r
+      for (Data = Value; Data != 0; Data >>= 1) {\r
+       Index ++;\r
+      }\r
+      Value |= ((UINT32)(-1) << Index);\r
+\r
+      //\r
+      // Calculate the size of 64bit bar\r
+      //\r
+      PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32);\r
+\r
+      PciIoDevice->PciBar[BarIndex].Length    = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32);\r
+      PciIoDevice->PciBar[BarIndex].Length    = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1;\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+      break;\r
+\r
+    //\r
+    // reserved\r
+    //\r
+    default:\r
+      PciIoDevice->PciBar[BarIndex].BarType   = PciBarTypeUnknown;\r
+      PciIoDevice->PciBar[BarIndex].Length    = (~(Value & Mask)) + 1;\r
+      PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1;\r
+\r
+      break;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Check the length again so as to keep compatible with some special bars\r
+  //\r
+  if (PciIoDevice->PciBar[BarIndex].Length == 0) {\r
+    PciIoDevice->PciBar[BarIndex].BarType     = PciBarTypeUnknown;\r
+    PciIoDevice->PciBar[BarIndex].BaseAddress = 0;\r
+    PciIoDevice->PciBar[BarIndex].Alignment   = 0;\r
+  }\r
+\r
+  //\r
+  // Increment number of bar\r
+  //\r
+  return Offset + 4;\r
+}\r
+\r
+EFI_STATUS\r
+InitializePciDevice (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine is used to initialize the bar of a PCI device\r
+  It can be called typically when a device is going to be rejected\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+  UINT8               Offset;\r
+\r
+  PciIo = &(PciIoDevice->PciIo);\r
+\r
+  //\r
+  // Put all the resource apertures\r
+  // Resource base is set to all ones so as to indicate its resource\r
+  // has not been alloacted\r
+  //\r
+  for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) {\r
+    PciIoWrite (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializePpb (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  PciIo = &(PciIoDevice->PciIo);\r
+\r
+  //\r
+  // Put all the resource apertures including IO16\r
+  // Io32, pMem32, pMem64 to quiescent state\r
+  // Resource base all ones, Resource limit all zeros\r
+  //\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne);\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero);\r
+\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne);\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero);\r
+\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne);\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero);\r
+\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne);\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero);\r
+\r
+  //\r
+  // don't support use io32 as for now\r
+  //\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne);\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero);\r
+\r
+  //\r
+  // Force Interrupt line to zero for cards that come up randomly\r
+  //\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+InitializeP2C (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_PCI_IO_PROTOCOL *PciIo;\r
+\r
+  PciIo = &(PciIoDevice->PciIo);\r
+\r
+  //\r
+  // Put all the resource apertures including IO16\r
+  // Io32, pMem32, pMem64 to quiescent state(\r
+  // Resource base all ones, Resource limit all zeros\r
+  //\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne);\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero);\r
+\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne);\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero);\r
+\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne);\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero);\r
+\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne);\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero);\r
+\r
+  //\r
+  // Force Interrupt line to zero for cards that come up randomly\r
+  //\r
+  PciIoWrite (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+PCI_IO_DEVICE *\r
+CreatePciIoDevice (\r
+  IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *PciRootBridgeIo,\r
+  IN PCI_TYPE00                       *Pci,\r
+  UINT8                               Bus,\r
+  UINT8                               Device,\r
+  UINT8                               Func\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    PciRootBridgeIo - add argument and description to function comment\r
+// TODO:    Pci - add argument and description to function comment\r
+// TODO:    Bus - add argument and description to function comment\r
+// TODO:    Device - add argument and description to function comment\r
+// TODO:    Func - add argument and description to function comment\r
+{\r
+\r
+  EFI_STATUS    Status;\r
+  PCI_IO_DEVICE *PciIoDevice;\r
+\r
+  PciIoDevice = NULL;\r
+\r
+  Status = gBS->AllocatePool (\r
+                  EfiBootServicesData,\r
+                  sizeof (PCI_IO_DEVICE),\r
+                  (VOID **) &PciIoDevice\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE));\r
+\r
+  PciIoDevice->Signature        = PCI_IO_DEVICE_SIGNATURE;\r
+  PciIoDevice->Handle           = NULL;\r
+  PciIoDevice->PciRootBridgeIo  = PciRootBridgeIo;\r
+  PciIoDevice->DevicePath       = NULL;\r
+  PciIoDevice->BusNumber        = Bus;\r
+  PciIoDevice->DeviceNumber     = Device;\r
+  PciIoDevice->FunctionNumber   = Func;\r
+  PciIoDevice->Decodes          = 0;\r
+  if (gFullEnumeration) {\r
+    PciIoDevice->Allocated = FALSE;\r
+  } else {\r
+    PciIoDevice->Allocated = TRUE;\r
+  }\r
+\r
+  PciIoDevice->Registered         = FALSE;\r
+  PciIoDevice->Attributes         = 0;\r
+  PciIoDevice->Supports           = 0;\r
+  PciIoDevice->BusOverride        = FALSE;\r
+  PciIoDevice->AllOpRomProcessed  = FALSE;\r
+\r
+  PciIoDevice->IsPciExp           = FALSE;\r
+\r
+  CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01));\r
+\r
+  //\r
+  // Initialize the PCI I/O instance structure\r
+  //\r
+\r
+  Status  = InitializePciIoInstance (PciIoDevice);\r
+  Status  = InitializePciDriverOverrideInstance (PciIoDevice);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->FreePool (PciIoDevice);\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Initialize the reserved resource list\r
+  //\r
+  InitializeListHead (&PciIoDevice->ReservedResourceList);\r
+\r
+  //\r
+  // Initialize the driver list\r
+  //\r
+  InitializeListHead (&PciIoDevice->OptionRomDriverList);\r
+\r
+  //\r
+  // Initialize the child list\r
+  //\r
+  InitializeListHead (&PciIoDevice->ChildList);\r
+\r
+  return PciIoDevice;\r
+}\r
+\r
+EFI_STATUS\r
+PciEnumeratorLight (\r
+  IN EFI_HANDLE                    Controller\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine is used to enumerate entire pci bus system\r
+  in a given platform\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    Controller - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+\r
+  EFI_STATUS                        Status;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;\r
+  PCI_IO_DEVICE                     *RootBridgeDev;\r
+  UINT16                            MinBus;\r
+  UINT16                            MaxBus;\r
+  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;\r
+\r
+  MinBus      = 0;\r
+  MaxBus      = PCI_MAX_BUS;\r
+  Descriptors = NULL;\r
+\r
+  //\r
+  // If this host bridge has been already enumerated, then return successfully\r
+  //\r
+  if (RootBridgeExisted (Controller)) {\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Open pci root bridge io protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  Controller,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  (VOID **) &PciRootBridgeIo,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  Controller,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    return Status;\r
+  }\r
+\r
+  Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) {\r
+\r
+    //\r
+    // Create a device node for root bridge device with a NULL host bridge controller handle\r
+    //\r
+    RootBridgeDev = CreateRootBridge (Controller);\r
+\r
+    if (!RootBridgeDev) {\r
+      Descriptors++;\r
+      continue;\r
+    }\r
+\r
+    //\r
+    // Record the root bridge io protocol\r
+    //\r
+    RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
+\r
+    Status = PciPciDeviceInfoCollector (\r
+              RootBridgeDev,\r
+              (UINT8) MinBus\r
+              );\r
+\r
+    if (!EFI_ERROR (Status)) {\r
+\r
+      //\r
+      // Remove those PCI devices which are rejected when full enumeration\r
+      //\r
+      RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev);\r
+\r
+      //\r
+      // Process option rom light\r
+      //\r
+      ProcessOptionRomLight (RootBridgeDev);\r
+\r
+      //\r
+      // Determine attributes for all devices under this root bridge\r
+      //\r
+      DetermineDeviceAttribute (RootBridgeDev);\r
+\r
+      //\r
+      // If successfully, insert the node into device pool\r
+      //\r
+      InsertRootBridge (RootBridgeDev);\r
+    } else {\r
+\r
+      //\r
+      // If unsuccessly, destroy the entire node\r
+      //\r
+      DestroyRootBridge (RootBridgeDev);\r
+    }\r
+\r
+    Descriptors++;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+EFI_STATUS\r
+PciGetBusRange (\r
+  IN     EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  **Descriptors,\r
+  OUT    UINT16                             *MinBus,\r
+  OUT    UINT16                             *MaxBus,\r
+  OUT    UINT16                             *BusRange\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Get the bus range.\r
+\r
+Arguments:\r
+\r
+  Descriptors     - A pointer to the address space descriptor.\r
+  MinBus          - The min bus.\r
+  MaxBus          - The max bus.\r
+  BusRange        - The bus range.\r
+\r
+Returns:\r
+\r
+  Status Code.\r
+\r
+--*/\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+// TODO:    EFI_NOT_FOUND - add return value to function comment\r
+{\r
+\r
+  while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
+    if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {\r
+      if (MinBus != NULL) {\r
+        *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;\r
+      }\r
+\r
+      if (MaxBus != NULL) {\r
+        *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;\r
+      }\r
+\r
+      if (BusRange != NULL) {\r
+        *BusRange = (UINT16) (*Descriptors)->AddrLen;\r
+      }\r
+\r
+      return EFI_SUCCESS;\r
+    }\r
+\r
+    (*Descriptors)++;\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+EFI_STATUS\r
+StartManagingRootBridge (\r
+  IN PCI_IO_DEVICE *RootBridgeDev\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  None\r
+\r
+--*/\r
+// TODO:    RootBridgeDev - add argument and description to function comment\r
+// TODO:    EFI_SUCCESS - add return value to function comment\r
+{\r
+  EFI_HANDLE                      RootBridgeHandle;\r
+  EFI_STATUS                      Status;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  //\r
+  // Get the root bridge handle\r
+  //\r
+  RootBridgeHandle  = RootBridgeDev->Handle;\r
+  PciRootBridgeIo   = NULL;\r
+\r
+  //\r
+  // Get the pci root bridge io protocol\r
+  //\r
+  Status = gBS->OpenProtocol (\r
+                  RootBridgeHandle,\r
+                  &gEfiPciRootBridgeIoProtocolGuid,\r
+                  (VOID **) &PciRootBridgeIo,\r
+                  gPciBusDriverBinding.DriverBindingHandle,\r
+                  RootBridgeHandle,\r
+                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                  );\r
+\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Store the PciRootBridgeIo protocol into root bridge private data\r
+  //\r
+  RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo;\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+BOOLEAN\r
+IsPciDeviceRejected (\r
+  IN PCI_IO_DEVICE *PciIoDevice\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  This routine can be used to check whether a PCI device should be rejected when light enumeration\r
+\r
+Arguments:\r
+\r
+Returns:\r
+\r
+  TRUE      This device should be rejected\r
+  FALSE     This device shouldn't be rejected\r
+\r
+--*/\r
+// TODO:    PciIoDevice - add argument and description to function comment\r
+{\r
+  EFI_STATUS  Status;\r
+  UINT32      TestValue;\r
+  UINT32      OldValue;\r
+  UINT32      Mask;\r
+  UINT8       BarOffset;\r
+\r
+  //\r
+  // PPB should be skip!\r
+  //\r
+  if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) {\r
+    //\r
+    // Only test base registers for P2C\r
+    //\r
+    for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) {\r
+\r
+      Mask    = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;\r
+      Status  = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
+      if (EFI_ERROR (Status)) {\r
+        continue;\r
+      }\r
+\r
+      TestValue = TestValue & Mask;\r
+      if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+        //\r
+        // The bar isn't programed, so it should be rejected\r
+        //\r
+        return TRUE;\r
+      }\r
+    }\r
+\r
+    return FALSE;\r
+  }\r
+\r
+  for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) {\r
+    //\r
+    // Test PCI devices\r
+    //\r
+    Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    if (TestValue & 0x01) {\r
+\r
+      //\r
+      // IO Bar\r
+      //\r
+\r
+      Mask      = 0xFFFFFFFC;\r
+      TestValue = TestValue & Mask;\r
+      if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+        return TRUE;\r
+      }\r
+\r
+    } else {\r
+\r
+      //\r
+      // Mem Bar\r
+      //\r
+\r
+      Mask      = 0xFFFFFFF0;\r
+      TestValue = TestValue & Mask;\r
+\r
+      if ((TestValue & 0x07) == 0x04) {\r
+\r
+        //\r
+        // Mem64 or PMem64\r
+        //\r
+        BarOffset += sizeof (UINT32);\r
+        if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+\r
+          //\r
+          // Test its high 32-Bit BAR\r
+          //\r
+\r
+          Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue);\r
+          if (TestValue == OldValue) {\r
+            return TRUE;\r
+          }\r
+        }\r
+\r
+      } else {\r
+\r
+        //\r
+        // Mem32 or PMem32\r
+        //\r
+        if ((TestValue != 0) && (TestValue == (OldValue & Mask))) {\r
+          return TRUE;\r
+        }\r
+      }\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
+EFI_STATUS\r
+ResetAllPpbBusReg (\r
+  IN PCI_IO_DEVICE                      *Bridge,\r
+  IN UINT8                              StartBusNumber\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  Bridge          - TODO: add argument description\r
+  StartBusNumber  - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  EFI_SUCCESS - TODO: Add description for return value\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                      Status;\r
+  PCI_TYPE00                      Pci;\r
+  UINT8                           Device;\r
+  UINT32                          Register;\r
+  UINT8                           Func;\r
+  UINT64                          Address;\r
+  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
+\r
+  PciRootBridgeIo = Bridge->PciRootBridgeIo;\r
+\r
+  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {\r
+    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {\r
+\r
+      //\r
+      // Check to see whether a pci device is present\r
+      //\r
+      Status = PciDevicePresent (\r
+                PciRootBridgeIo,\r
+                &Pci,\r
+                StartBusNumber,\r
+                Device,\r
+                Func\r
+                );\r
+\r
+      if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) {\r
+        Register  = 0;\r
+        Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);\r
+        Status   = PciRootBridgeIoRead (\r
+                                        PciRootBridgeIo,\r
+                                        &Pci,\r
+                                        EfiPciWidthUint32,\r
+                                        Address,\r
+                                        1,\r
+                                        &Register\r
+                                        );\r
+        //\r
+        // Reset register 18h, 19h, 1Ah on PCI Bridge\r
+        //\r
+        Register &= 0xFF000000;\r
+        Status = PciRootBridgeIoWrite (\r
+                                        PciRootBridgeIo,\r
+                                        &Pci,\r
+                                        EfiPciWidthUint32,\r
+                                        Address,\r
+                                        1,\r
+                                        &Register\r
+                                        );\r
+      }\r
+\r
+      if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {\r
+        //\r
+        // Skip sub functions, this is not a multi function device\r
+        //\r
+        Func = PCI_MAX_FUNC;\r
+      }\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r