]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
1. Impl PI 1.2 PCI part. Major changes include:
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciDeviceSupport.c
diff --git a/IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c b/IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciDeviceSupport.c
deleted file mode 100644 (file)
index 0eb9f9a..0000000
+++ /dev/null
@@ -1,1160 +0,0 @@
-/** @file\r
-  Supporting functions implementaion for PCI devices management.\r
-\r
-Copyright (c) 2006 - 2009, 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
-**/\r
-\r
-#include "PciBus.h"\r
-\r
-//\r
-// This device structure is serviced as a header.\r
-// Its next field points to the first root bridge device node.\r
-//\r
-LIST_ENTRY  mPciDevicePool;\r
-\r
-/**\r
-  Initialize the PCI devices pool.\r
-\r
-**/\r
-VOID\r
-InitializePciDevicePool (\r
-  VOID\r
-  )\r
-{\r
-  InitializeListHead (&mPciDevicePool);\r
-}\r
-\r
-/**\r
-  Insert a root bridge into PCI device pool.\r
-\r
-  @param RootBridge     A pointer to the PCI_IO_DEVICE.\r
-\r
-**/\r
-VOID\r
-InsertRootBridge (\r
-  IN PCI_IO_DEVICE      *RootBridge\r
-  )\r
-{\r
-  InsertTailList (&mPciDevicePool, &(RootBridge->Link));\r
-}\r
-\r
-/**\r
-  This function is used to insert a PCI device node under\r
-  a bridge.\r
-\r
-  @param Bridge         The PCI bridge.\r
-  @param PciDeviceNode  The PCI device needs inserting.\r
-\r
-**/\r
-VOID\r
-InsertPciDevice (\r
-  IN PCI_IO_DEVICE      *Bridge,\r
-  IN PCI_IO_DEVICE      *PciDeviceNode\r
-  )\r
-{\r
-  InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link));\r
-  PciDeviceNode->Parent = Bridge;\r
-}\r
-\r
-/**\r
-  Destroy root bridge and remove it from deivce tree.\r
-\r
-  @param RootBridge     The bridge want to be removed.\r
-\r
-**/\r
-VOID\r
-DestroyRootBridge (\r
-  IN PCI_IO_DEVICE      *RootBridge\r
-  )\r
-{\r
-  DestroyPciDeviceTree (RootBridge);\r
-\r
-  FreePciDevice (RootBridge);\r
-}\r
-\r
-/**\r
-  Destroy a pci device node.\r
-\r
-  All direct or indirect allocated resource for this node will be freed.\r
-\r
-  @param PciIoDevice  A pointer to the PCI_IO_DEVICE to be destoried.\r
-\r
-**/\r
-VOID\r
-FreePciDevice (\r
-  IN PCI_IO_DEVICE    *PciIoDevice\r
-  )\r
-{\r
-  ASSERT (PciIoDevice != NULL);\r
-  //\r
-  // Assume all children have been removed underneath this device\r
-  //\r
-  if (PciIoDevice->ResourcePaddingDescriptors != NULL) {\r
-    FreePool (PciIoDevice->ResourcePaddingDescriptors);\r
-  }\r
-\r
-  if (PciIoDevice->DevicePath != NULL) {\r
-    FreePool (PciIoDevice->DevicePath);\r
-  }\r
-\r
-  FreePool (PciIoDevice);\r
-}\r
-\r
-/**\r
-  Destroy all the pci device node under the bridge.\r
-  Bridge itself is not included.\r
-\r
-  @param Bridge      A pointer to the PCI_IO_DEVICE.\r
-\r
-**/\r
-VOID\r
-DestroyPciDeviceTree (\r
-  IN PCI_IO_DEVICE      *Bridge\r
-  )\r
-{\r
-  LIST_ENTRY      *CurrentLink;\r
-  PCI_IO_DEVICE   *Temp;\r
-\r
-  while (!IsListEmpty (&Bridge->ChildList)) {\r
-\r
-    CurrentLink = Bridge->ChildList.ForwardLink;\r
-\r
-    //\r
-    // Remove this node from the linked list\r
-    //\r
-    RemoveEntryList (CurrentLink);\r
-\r
-    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
-\r
-    if (!IsListEmpty (&Temp->ChildList)) {\r
-      DestroyPciDeviceTree (Temp);\r
-    }\r
-\r
-    FreePciDevice (Temp);\r
-  }\r
-}\r
-\r
-/**\r
-  Destroy all device nodes under the root bridge\r
-  specified by Controller.\r
-\r
-  The root bridge itself is also included.\r
-\r
-  @param  Controller    Root bridge handle.\r
-\r
-  @retval EFI_SUCCESS   Destory all devcie nodes successfully.\r
-  @retval EFI_NOT_FOUND Cannot find any PCI device under specified\r
-                        root bridge.\r
-\r
-**/\r
-EFI_STATUS\r
-DestroyRootBridgeByHandle (\r
-  IN EFI_HANDLE        Controller\r
-  )\r
-{\r
-\r
-  LIST_ENTRY      *CurrentLink;\r
-  PCI_IO_DEVICE   *Temp;\r
-\r
-  CurrentLink = mPciDevicePool.ForwardLink;\r
-\r
-  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
-    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
-\r
-    if (Temp->Handle == Controller) {\r
-\r
-      RemoveEntryList (CurrentLink);\r
-\r
-      DestroyPciDeviceTree (Temp);\r
-\r
-      FreePciDevice (Temp);\r
-\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
-  }\r
-\r
-  return EFI_NOT_FOUND;\r
-}\r
-\r
-/**\r
-  This function registers the PCI IO device.\r
-\r
-  It creates a handle for this PCI IO device (if the handle does not exist), attaches\r
-  appropriate protocols onto the handle, does necessary initialization, and sets up\r
-  parent/child relationship with its bus controller.\r
-\r
-  @param Controller     An EFI handle for the PCI bus controller.\r
-  @param PciIoDevice    A PCI_IO_DEVICE pointer to the PCI IO device to be registered.\r
-  @param Handle         A pointer to hold the returned EFI handle for the PCI IO device.\r
-\r
-  @retval EFI_SUCCESS   The PCI device is successfully registered.\r
-  @retval other         An error occurred when registering the PCI device.\r
-\r
-**/\r
-EFI_STATUS\r
-RegisterPciDevice (\r
-  IN  EFI_HANDLE          Controller,\r
-  IN  PCI_IO_DEVICE       *PciIoDevice,\r
-  OUT EFI_HANDLE          *Handle      OPTIONAL\r
-  )\r
-{\r
-  EFI_STATUS          Status;\r
-  VOID                *PlatformOpRomBuffer;\r
-  UINTN               PlatformOpRomSize;\r
-  UINT8               PciExpressCapRegOffset;\r
-  EFI_PCI_IO_PROTOCOL *PciIo;\r
-  UINT8               Data8;\r
-  BOOLEAN             HasEfiImage;\r
-  PCI_IO_DEVICE       *ParrentPciIoDevice;\r
-  EFI_PCI_IO_PROTOCOL *ParrentPciIo;\r
-  UINT16              Data16;\r
-  UINT32              Data32;\r
-\r
-  //\r
-  // Install the pciio protocol, device path protocol\r
-  //\r
-  Status = gBS->InstallMultipleProtocolInterfaces (\r
-                  &PciIoDevice->Handle,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  PciIoDevice->DevicePath,\r
-                  &gEfiPciIoProtocolGuid,\r
-                  &PciIoDevice->PciIo,\r
-                  NULL\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  //\r
-  // Detect if PCI Express Device\r
-  //\r
-  PciExpressCapRegOffset = 0;\r
-  Status = LocateCapabilityRegBlock (\r
-             PciIoDevice,\r
-             EFI_PCI_CAPABILITY_ID_PCIEXP,\r
-             &PciExpressCapRegOffset,\r
-             NULL\r
-             );\r
-  if (!EFI_ERROR (Status)) {\r
-    PciIoDevice->IsPciExp = TRUE;\r
-  }\r
-\r
-  //\r
-  // Force Interrupt line to "Unknown" or "No Connection"\r
-  //\r
-  PciIo = &(PciIoDevice->PciIo);\r
-  Data8 = PCI_INT_LINE_UNKNOWN;\r
-  PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &Data8);\r
-  \r
-  //\r
-  // PCI-IOV programming\r
-  //\r
-  if (((FeaturePcdGet(PcdAriSupport) & EFI_PCI_IOV_POLICY_ARI) != 0) && (PciIoDevice->AriCapabilityOffset != 0) && ((FeaturePcdGet(PcdSrIovSupport) & EFI_PCI_IOV_POLICY_SRIOV) != 0) &&\r
-      (PciIoDevice->SrIovCapabilityOffset != 0)) {\r
-    //\r
-    // Check its parrent ARI forwarding capability\r
-    //\r
-    ParrentPciIoDevice = PciIoDevice->Parent;\r
-    ParrentPciIo = &(ParrentPciIoDevice->PciIo);\r
-    ParrentPciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET, 1, &Data32);\r
-    if (Data32 & EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING) {\r
-      //\r
-      // ARI forward support in bridge, so enable it.\r
-      //\r
-      ParrentPciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 1, &Data32);\r
-      Data32 |= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING;\r
-      ParrentPciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, ParrentPciIoDevice->PciExpressCapabilityOffset + EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET, 1, &Data32);\r
-\r
-      //\r
-      // Set ARI Capable Hierarchy for device\r
-      //\r
-      PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 1, &Data16);\r
-      Data16 |= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY;\r
-      PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, PciIoDevice->SrIovCapabilityOffset + EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL, 1, &Data16);\r
-    }\r
-  }\r
-  \r
-  //\r
-  // Process OpRom\r
-  //\r
-  if (!PciIoDevice->AllOpRomProcessed) {\r
-\r
-    //\r
-    // Get the OpRom provided by platform\r
-    //\r
-    if (gPciPlatformProtocol != NULL) {\r
-      Status = gPciPlatformProtocol->GetPciRom (\r
-                                       gPciPlatformProtocol,\r
-                                       PciIoDevice->Handle,\r
-                                       &PlatformOpRomBuffer,\r
-                                       &PlatformOpRomSize\r
-                                       );\r
-      if (!EFI_ERROR (Status)) {\r
-        PciIoDevice->RomSize        = PlatformOpRomSize;\r
-        PciIoDevice->PciIo.RomSize  = PlatformOpRomSize;\r
-        PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer;\r
-        //\r
-        // For OpROM read from gPciPlatformProtocol:\r
-        // Add the Rom Image to internal database for later PCI light enumeration\r
-        //\r
-        PciRomAddImageMapping (\r
-          NULL,\r
-          PciIoDevice->PciRootBridgeIo->SegmentNumber,\r
-          PciIoDevice->BusNumber,\r
-          PciIoDevice->DeviceNumber,\r
-          PciIoDevice->FunctionNumber,\r
-          (UINT64) (UINTN) PciIoDevice->PciIo.RomImage,\r
-          PciIoDevice->PciIo.RomSize\r
-          );\r
-      }\r
-    }\r
-  }\r
-\r
-  //\r
-  // Determine if there are EFI images in the option rom\r
-  //\r
-  HasEfiImage = ContainEfiImage (PciIoDevice->PciIo.RomImage, PciIoDevice->PciIo.RomSize);\r
-\r
-  if (HasEfiImage) {\r
-    Status = gBS->InstallMultipleProtocolInterfaces (\r
-                    &PciIoDevice->Handle,\r
-                    &gEfiLoadFile2ProtocolGuid,\r
-                    &PciIoDevice->LoadFile2,\r
-                    NULL\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      gBS->UninstallMultipleProtocolInterfaces (\r
-             &PciIoDevice->Handle,\r
-             &gEfiDevicePathProtocolGuid,\r
-             PciIoDevice->DevicePath,\r
-             &gEfiPciIoProtocolGuid,\r
-             &PciIoDevice->PciIo,\r
-             NULL\r
-             );\r
-      return Status;\r
-    }\r
-  }\r
-\r
-\r
-  if (!PciIoDevice->AllOpRomProcessed) {\r
-\r
-    PciIoDevice->AllOpRomProcessed = TRUE;\r
-\r
-    //\r
-    // Dispatch the EFI OpRom for the PCI device.\r
-    // The OpRom is got from platform in the above code\r
-    // or loaded from device in the previous round of bus enumeration\r
-    //\r
-    if (HasEfiImage) {\r
-      ProcessOpRomImage (PciIoDevice);\r
-    }\r
-  }\r
-\r
-  if (PciIoDevice->BusOverride) {\r
-    //\r
-    // Install Bus Specific Driver Override Protocol\r
-    //\r
-    Status = gBS->InstallMultipleProtocolInterfaces (\r
-                    &PciIoDevice->Handle,\r
-                    &gEfiBusSpecificDriverOverrideProtocolGuid,\r
-                    &PciIoDevice->PciDriverOverride,\r
-                    NULL\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      gBS->UninstallMultipleProtocolInterfaces (\r
-             &PciIoDevice->Handle,\r
-             &gEfiDevicePathProtocolGuid,\r
-             PciIoDevice->DevicePath,\r
-             &gEfiPciIoProtocolGuid,\r
-             &PciIoDevice->PciIo,\r
-             NULL\r
-             );\r
-      if (HasEfiImage) {\r
-        gBS->UninstallMultipleProtocolInterfaces (\r
-               &PciIoDevice->Handle,\r
-               &gEfiLoadFile2ProtocolGuid,\r
-               &PciIoDevice->LoadFile2,\r
-               NULL\r
-               );\r
-      }\r
-\r
-      return Status;\r
-    }\r
-  }\r
-\r
-  Status = gBS->OpenProtocol (\r
-                  Controller,\r
-                  &gEfiPciRootBridgeIoProtocolGuid,\r
-                  (VOID **) &(PciIoDevice->PciRootBridgeIo),\r
-                  gPciBusDriverBinding.DriverBindingHandle,\r
-                  PciIoDevice->Handle,\r
-                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if (Handle != NULL) {\r
-    *Handle = PciIoDevice->Handle;\r
-  }\r
-\r
-  //\r
-  // Indicate the pci device is registered\r
-  //\r
-  PciIoDevice->Registered = TRUE;\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  This function is used to remove the whole PCI devices on the specified bridge from\r
-  the root bridge.\r
-\r
-  @param RootBridgeHandle   The root bridge device handle.\r
-  @param Bridge             The bridge device to be removed.\r
-\r
-**/\r
-VOID\r
-RemoveAllPciDeviceOnBridge (\r
-  EFI_HANDLE               RootBridgeHandle,\r
-  PCI_IO_DEVICE            *Bridge\r
-  )\r
-{\r
-  LIST_ENTRY      *CurrentLink;\r
-  PCI_IO_DEVICE   *Temp;\r
-\r
-  while (!IsListEmpty (&Bridge->ChildList)) {\r
-\r
-    CurrentLink = Bridge->ChildList.ForwardLink;\r
-    Temp        = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
-\r
-    //\r
-    // Check if the current node has been deregistered before\r
-    // If it is not, then deregister it\r
-    //\r
-    if (Temp->Registered) {\r
-      DeRegisterPciDevice (RootBridgeHandle, Temp->Handle);\r
-    }\r
-\r
-    //\r
-    // Remove this node from the linked list\r
-    //\r
-    RemoveEntryList (CurrentLink);\r
-\r
-    if (!IsListEmpty (&Temp->ChildList)) {\r
-      RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);\r
-    }\r
-\r
-    FreePciDevice (Temp);\r
-  }\r
-}\r
-\r
-/**\r
-  This function is used to de-register the PCI IO device.\r
-\r
-  That includes un-installing PciIo protocol from the specified PCI\r
-  device handle.\r
-\r
-  @param Controller    An EFI handle for the PCI bus controller.\r
-  @param Handle        PCI device handle.\r
-\r
-  @retval EFI_SUCCESS  The PCI device is successfully de-registered.\r
-  @retval other        An error occurred when de-registering the PCI device.\r
-\r
-**/\r
-EFI_STATUS\r
-DeRegisterPciDevice (\r
-  IN  EFI_HANDLE                     Controller,\r
-  IN  EFI_HANDLE                     Handle\r
-  )\r
-\r
-{\r
-  EFI_PCI_IO_PROTOCOL             *PciIo;\r
-  EFI_STATUS                      Status;\r
-  PCI_IO_DEVICE                   *PciIoDevice;\r
-  PCI_IO_DEVICE                   *Node;\r
-  LIST_ENTRY                      *CurrentLink;\r
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
-\r
-  Status = gBS->OpenProtocol (\r
-                  Handle,\r
-                  &gEfiPciIoProtocolGuid,\r
-                  (VOID **) &PciIo,\r
-                  gPciBusDriverBinding.DriverBindingHandle,\r
-                  Controller,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-  if (!EFI_ERROR (Status)) {\r
-    PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);\r
-\r
-    //\r
-    // If it is already de-registered\r
-    //\r
-    if (!PciIoDevice->Registered) {\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    //\r
-    // If it is PPB, first de-register its children\r
-    //\r
-\r
-    if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
-\r
-      CurrentLink = PciIoDevice->ChildList.ForwardLink;\r
-\r
-      while (CurrentLink != NULL && CurrentLink != &PciIoDevice->ChildList) {\r
-        Node    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
-        Status  = DeRegisterPciDevice (Controller, Node->Handle);\r
-\r
-        if (EFI_ERROR (Status)) {\r
-          return Status;\r
-        }\r
-\r
-        CurrentLink = CurrentLink->ForwardLink;\r
-      }\r
-    }\r
-\r
-    //\r
-    // Close the child handle\r
-    //\r
-    Status = gBS->CloseProtocol (\r
-                    Controller,\r
-                    &gEfiPciRootBridgeIoProtocolGuid,\r
-                    gPciBusDriverBinding.DriverBindingHandle,\r
-                    Handle\r
-                    );\r
-\r
-    //\r
-    // Un-install the Device Path protocol and PCI I/O protocol\r
-    // and Bus Specific Driver Override protocol if needed.\r
-    //\r
-    if (PciIoDevice->BusOverride) {\r
-      Status = gBS->UninstallMultipleProtocolInterfaces (\r
-                      Handle,\r
-                      &gEfiDevicePathProtocolGuid,\r
-                      PciIoDevice->DevicePath,\r
-                      &gEfiPciIoProtocolGuid,\r
-                      &PciIoDevice->PciIo,\r
-                      &gEfiBusSpecificDriverOverrideProtocolGuid,\r
-                      &PciIoDevice->PciDriverOverride,\r
-                      NULL\r
-                      );\r
-    } else {\r
-      Status = gBS->UninstallMultipleProtocolInterfaces (\r
-                      Handle,\r
-                      &gEfiDevicePathProtocolGuid,\r
-                      PciIoDevice->DevicePath,\r
-                      &gEfiPciIoProtocolGuid,\r
-                      &PciIoDevice->PciIo,\r
-                      NULL\r
-                      );\r
-    }\r
-\r
-    if (!EFI_ERROR (Status)) {\r
-      //\r
-      // Try to uninstall LoadFile2 protocol if exists\r
-      //\r
-      Status = gBS->OpenProtocol (\r
-                      Handle,\r
-                      &gEfiLoadFile2ProtocolGuid,\r
-                      NULL,\r
-                      gPciBusDriverBinding.DriverBindingHandle,\r
-                      Controller,\r
-                      EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                      );\r
-      if (!EFI_ERROR (Status)) {\r
-        Status = gBS->UninstallMultipleProtocolInterfaces (\r
-                        Handle,\r
-                        &gEfiLoadFile2ProtocolGuid,\r
-                        &PciIoDevice->LoadFile2,\r
-                        NULL\r
-                        );\r
-      }\r
-      //\r
-      // Restore Status\r
-      //\r
-      Status = EFI_SUCCESS;\r
-    }\r
-\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      gBS->OpenProtocol (\r
-            Controller,\r
-            &gEfiPciRootBridgeIoProtocolGuid,\r
-            (VOID **) &PciRootBridgeIo,\r
-            gPciBusDriverBinding.DriverBindingHandle,\r
-            Handle,\r
-            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-            );\r
-      return Status;\r
-    }\r
-\r
-    //\r
-    // The Device Driver should disable this device after disconnect\r
-    // so the Pci Bus driver will not touch this device any more.\r
-    // Restore the register field to the original value\r
-    //\r
-    PciIoDevice->Registered = FALSE;\r
-    PciIoDevice->Handle     = NULL;\r
-  } else {\r
-\r
-    //\r
-    // Handle may be closed before\r
-    //\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Start to manage the PCI device on the specified root bridge or PCI-PCI Bridge.\r
-\r
-  @param Controller          The root bridge handle.\r
-  @param RootBridge          A pointer to the PCI_IO_DEVICE.\r
-  @param RemainingDevicePath A pointer to the EFI_DEVICE_PATH_PROTOCOL.\r
-  @param NumberOfChildren    Children number.\r
-  @param ChildHandleBuffer   A pointer to the child handle buffer.\r
-\r
-  @retval EFI_NOT_READY   Device is not allocated.\r
-  @retval EFI_UNSUPPORTED Device only support PCI-PCI bridge.\r
-  @retval EFI_NOT_FOUND   Can not find the specific device.\r
-  @retval EFI_SUCCESS     Success to start Pci devices on bridge.\r
-\r
-**/\r
-EFI_STATUS\r
-StartPciDevicesOnBridge (\r
-  IN EFI_HANDLE                          Controller,\r
-  IN PCI_IO_DEVICE                       *RootBridge,\r
-  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath,\r
-  IN OUT UINT8                           *NumberOfChildren,\r
-  IN OUT EFI_HANDLE                      *ChildHandleBuffer\r
-  )\r
-\r
-{\r
-  PCI_IO_DEVICE             *PciIoDevice;\r
-  EFI_DEV_PATH_PTR          Node;\r
-  EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;\r
-  EFI_STATUS                Status;\r
-  LIST_ENTRY                *CurrentLink;\r
-  UINT64                    Supports;\r
-\r
-  PciIoDevice = NULL;\r
-  CurrentLink = RootBridge->ChildList.ForwardLink;\r
-\r
-  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {\r
-\r
-    PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
-    if (RemainingDevicePath != NULL) {\r
-\r
-      Node.DevPath = RemainingDevicePath;\r
-\r
-      if (Node.Pci->Device != PciIoDevice->DeviceNumber ||\r
-          Node.Pci->Function != PciIoDevice->FunctionNumber) {\r
-        CurrentLink = CurrentLink->ForwardLink;\r
-        continue;\r
-      }\r
-\r
-      //\r
-      // Check if the device has been assigned with required resource\r
-      //\r
-      if (!PciIoDevice->Allocated) {\r
-        return EFI_NOT_READY;\r
-      }\r
-\r
-      //\r
-      // Check if the current node has been registered before\r
-      // If it is not, register it\r
-      //\r
-      if (!PciIoDevice->Registered) {\r
-        Status = RegisterPciDevice (\r
-                   Controller,\r
-                   PciIoDevice,\r
-                   NULL\r
-                   );\r
-\r
-      }\r
-\r
-      if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && PciIoDevice->Registered) {\r
-        ChildHandleBuffer[*NumberOfChildren] = PciIoDevice->Handle;\r
-        (*NumberOfChildren)++;\r
-      }\r
-\r
-      //\r
-      // Get the next device path\r
-      //\r
-      CurrentDevicePath = NextDevicePathNode (RemainingDevicePath);\r
-      if (IsDevicePathEnd (CurrentDevicePath)) {\r
-        return EFI_SUCCESS;\r
-      }\r
-\r
-      //\r
-      // If it is a PPB\r
-      //\r
-      if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
-        Status = StartPciDevicesOnBridge (\r
-                   Controller,\r
-                   PciIoDevice,\r
-                   CurrentDevicePath,\r
-                   NumberOfChildren,\r
-                   ChildHandleBuffer\r
-                   );\r
-\r
-        PciIoDevice->PciIo.Attributes (\r
-                             &(PciIoDevice->PciIo),\r
-                             EfiPciIoAttributeOperationSupported,\r
-                             0,\r
-                             &Supports\r
-                             );\r
-        Supports &= EFI_PCI_DEVICE_ENABLE;\r
-        PciIoDevice->PciIo.Attributes (\r
-                             &(PciIoDevice->PciIo),\r
-                             EfiPciIoAttributeOperationEnable,\r
-                             Supports,\r
-                             NULL\r
-                             );\r
-\r
-        return Status;\r
-      } else {\r
-\r
-        //\r
-        // Currently, the PCI bus driver only support PCI-PCI bridge\r
-        //\r
-        return EFI_UNSUPPORTED;\r
-      }\r
-\r
-    } else {\r
-\r
-      //\r
-      // If remaining device path is NULL,\r
-      // try to enable all the pci devices under this bridge\r
-      //\r
-      if (!PciIoDevice->Registered && PciIoDevice->Allocated) {\r
-        Status = RegisterPciDevice (\r
-                   Controller,\r
-                   PciIoDevice,\r
-                   NULL\r
-                   );\r
-\r
-      }\r
-\r
-      if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && PciIoDevice->Registered) {\r
-        ChildHandleBuffer[*NumberOfChildren] = PciIoDevice->Handle;\r
-        (*NumberOfChildren)++;\r
-      }\r
-\r
-      if (!IsListEmpty (&PciIoDevice->ChildList)) {\r
-        Status = StartPciDevicesOnBridge (\r
-                   Controller,\r
-                   PciIoDevice,\r
-                   RemainingDevicePath,\r
-                   NumberOfChildren,\r
-                   ChildHandleBuffer\r
-                   );\r
-\r
-        PciIoDevice->PciIo.Attributes (\r
-                             &(PciIoDevice->PciIo),\r
-                             EfiPciIoAttributeOperationSupported,\r
-                             0,\r
-                             &Supports\r
-                             );\r
-        Supports &= EFI_PCI_DEVICE_ENABLE;\r
-        PciIoDevice->PciIo.Attributes (\r
-                             &(PciIoDevice->PciIo),\r
-                             EfiPciIoAttributeOperationEnable,\r
-                             Supports,\r
-                             NULL\r
-                             );\r
-\r
-      }\r
-\r
-      CurrentLink = CurrentLink->ForwardLink;\r
-    }\r
-  }\r
-\r
-  if (PciIoDevice == NULL) {\r
-    return EFI_NOT_FOUND;\r
-  } else {\r
-    return EFI_SUCCESS;\r
-  }\r
-}\r
-\r
-/**\r
-  Start to manage all the PCI devices it found previously under\r
-  the entire host bridge.\r
-\r
-  @param Controller          The root bridge handle.\r
-\r
-  @retval EFI_NOT_READY   Device is not allocated.\r
-  @retval EFI_SUCCESS     Success to start Pci device on host bridge.\r
-\r
-**/\r
-EFI_STATUS\r
-StartPciDevices (\r
-  IN EFI_HANDLE                         Controller\r
-  )\r
-{\r
-  PCI_IO_DEVICE     *RootBridge;\r
-  EFI_HANDLE        ThisHostBridge;\r
-  LIST_ENTRY        *CurrentLink;\r
-\r
-  RootBridge = GetRootBridgeByHandle (Controller);\r
-  ASSERT (RootBridge != NULL);\r
-  ThisHostBridge = RootBridge->PciRootBridgeIo->ParentHandle;\r
-\r
-  CurrentLink = mPciDevicePool.ForwardLink;\r
-\r
-  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
-\r
-    RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
-    //\r
-    // Locate the right root bridge to start\r
-    //\r
-    if (RootBridge->PciRootBridgeIo->ParentHandle == ThisHostBridge) {\r
-      StartPciDevicesOnBridge (\r
-         RootBridge->Handle,\r
-         RootBridge,\r
-         NULL,\r
-         NULL,\r
-         NULL\r
-         );\r
-    }\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
-  Create root bridge device.\r
-\r
-  @param RootBridgeHandle    Specified root bridge hanle.\r
-\r
-  @return The crated root bridge device instance, NULL means no\r
-          root bridge device instance created.\r
-\r
-**/\r
-PCI_IO_DEVICE *\r
-CreateRootBridge (\r
-  IN EFI_HANDLE                   RootBridgeHandle\r
-  )\r
-{\r
-  EFI_STATUS                      Status;\r
-  PCI_IO_DEVICE                   *Dev;\r
-  EFI_DEVICE_PATH_PROTOCOL        *ParentDevicePath;\r
-  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;\r
-\r
-  Dev = AllocateZeroPool (sizeof (PCI_IO_DEVICE));\r
-  if (Dev == NULL) {\r
-    return NULL;\r
-  }\r
-\r
-  Dev->Signature  = PCI_IO_DEVICE_SIGNATURE;\r
-  Dev->Handle     = RootBridgeHandle;\r
-  InitializeListHead (&Dev->ChildList);\r
-\r
-  Status = gBS->OpenProtocol (\r
-                  RootBridgeHandle,\r
-                  &gEfiDevicePathProtocolGuid,\r
-                  (VOID **) &ParentDevicePath,\r
-                  gPciBusDriverBinding.DriverBindingHandle,\r
-                  RootBridgeHandle,\r
-                  EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    FreePool (Dev);\r
-    return NULL;\r
-  }\r
-\r
-  //\r
-  // Record the root bridge parent device path\r
-  //\r
-  Dev->DevicePath = DuplicateDevicePath (ParentDevicePath);\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_GET_PROTOCOL\r
-                  );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    FreePciDevice (Dev);\r
-    return NULL;\r
-  }\r
-\r
-  Dev->PciRootBridgeIo = PciRootBridgeIo;\r
-\r
-  //\r
-  // Initialize the PCI I/O instance structure\r
-  //\r
-  InitializePciIoInstance (Dev);\r
-  InitializePciDriverOverrideInstance (Dev);\r
-  InitializePciLoadFile2 (Dev);\r
-\r
-  //\r
-  // Initialize reserved resource list and\r
-  // option rom driver list\r
-  //\r
-  InitializeListHead (&Dev->ReservedResourceList);\r
-  InitializeListHead (&Dev->OptionRomDriverList);\r
-\r
-  return Dev;\r
-}\r
-\r
-/**\r
-  Get root bridge device instance by specific root bridge handle.\r
-\r
-  @param RootBridgeHandle    Given root bridge handle.\r
-\r
-  @return The root bridge device instance, NULL means no root bridge\r
-          device instance found.\r
-\r
-**/\r
-PCI_IO_DEVICE *\r
-GetRootBridgeByHandle (\r
-  EFI_HANDLE RootBridgeHandle\r
-  )\r
-{\r
-  PCI_IO_DEVICE   *RootBridgeDev;\r
-  LIST_ENTRY      *CurrentLink;\r
-\r
-  CurrentLink = mPciDevicePool.ForwardLink;\r
-\r
-  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
-\r
-    RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
-    if (RootBridgeDev->Handle == RootBridgeHandle) {\r
-      return RootBridgeDev;\r
-    }\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
-  }\r
-\r
-  return NULL;\r
-}\r
-\r
-/**\r
-  Judege whether Pci device existed.\r
-\r
-  @param Bridge       Parent bridege instance.\r
-  @param PciIoDevice  Device instance.\r
-\r
-  @retval TRUE        Pci device existed.\r
-  @retval FALSE       Pci device did not exist.\r
-\r
-**/\r
-BOOLEAN\r
-PciDeviceExisted (\r
-  IN PCI_IO_DEVICE    *Bridge,\r
-  IN PCI_IO_DEVICE    *PciIoDevice\r
-  )\r
-{\r
-\r
-  PCI_IO_DEVICE   *Temp;\r
-  LIST_ENTRY      *CurrentLink;\r
-\r
-  CurrentLink = Bridge->ChildList.ForwardLink;\r
-\r
-  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
-\r
-    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
-\r
-    if (Temp == PciIoDevice) {\r
-      return TRUE;\r
-    }\r
-\r
-    if (!IsListEmpty (&Temp->ChildList)) {\r
-      if (PciDeviceExisted (Temp, PciIoDevice)) {\r
-        return TRUE;\r
-      }\r
-    }\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
-  }\r
-\r
-  return FALSE;\r
-}\r
-\r
-/**\r
-  Get the active VGA device on the same segment.\r
-\r
-  @param VgaDevice    PCI IO instance for the VGA device.\r
-\r
-  @return The active VGA device on the same segment.\r
-\r
-**/\r
-PCI_IO_DEVICE *\r
-ActiveVGADeviceOnTheSameSegment (\r
-  IN PCI_IO_DEVICE        *VgaDevice\r
-  )\r
-{\r
-  LIST_ENTRY      *CurrentLink;\r
-  PCI_IO_DEVICE   *Temp;\r
-\r
-  CurrentLink = mPciDevicePool.ForwardLink;\r
-\r
-  while (CurrentLink != NULL && CurrentLink != &mPciDevicePool) {\r
-\r
-    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
-\r
-    if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) {\r
-\r
-      Temp = ActiveVGADeviceOnTheRootBridge (Temp);\r
-\r
-      if (Temp != NULL) {\r
-        return Temp;\r
-      }\r
-    }\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
-  }\r
-\r
-  return NULL;\r
-}\r
-\r
-/**\r
-  Get the active VGA device on the root bridge.\r
-\r
-  @param RootBridge  PCI IO instance for the root bridge.\r
-\r
-  @return The active VGA device.\r
-\r
-**/\r
-PCI_IO_DEVICE *\r
-ActiveVGADeviceOnTheRootBridge (\r
-  IN PCI_IO_DEVICE        *RootBridge\r
-  )\r
-{\r
-  LIST_ENTRY      *CurrentLink;\r
-  PCI_IO_DEVICE   *Temp;\r
-\r
-  CurrentLink = RootBridge->ChildList.ForwardLink;\r
-\r
-  while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {\r
-\r
-    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
-\r
-    if (IS_PCI_VGA(&Temp->Pci) &&\r
-        (Temp->Attributes &\r
-         (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |\r
-          EFI_PCI_IO_ATTRIBUTE_VGA_IO     |\r
-          EFI_PCI_IO_ATTRIBUTE_VGA_IO_16)) != 0) {\r
-      return Temp;\r
-    }\r
-\r
-    if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
-\r
-      Temp = ActiveVGADeviceOnTheRootBridge (Temp);\r
-\r
-      if (Temp != NULL) {\r
-        return Temp;\r
-      }\r
-    }\r
-\r
-    CurrentLink = CurrentLink->ForwardLink;\r
-  }\r
-\r
-  return NULL;\r
-}\r
-\r
-\r
-/**\r
-  Get HPC PCI address according to its device path.\r
-\r
-  @param RootBridge           Root bridege Io instance.\r
-  @param RemainingDevicePath  Given searching device path.\r
-  @param PciAddress           Buffer holding searched result.\r
-\r
-  @retval EFI_SUCCESS         PCI address was stored in PciAddress\r
-  @retval EFI_NOT_FOUND       Can not find the specific device path.\r
-\r
-**/\r
-EFI_STATUS\r
-GetHpcPciAddressFromRootBridge (\r
-  IN  PCI_IO_DEVICE                    *RootBridge,\r
-  IN  EFI_DEVICE_PATH_PROTOCOL         *RemainingDevicePath,\r
-  OUT UINT64                           *PciAddress\r
-  )\r
-{\r
-  EFI_DEV_PATH_PTR          Node;\r
-  PCI_IO_DEVICE             *Temp;\r
-  EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;\r
-  LIST_ENTRY                *CurrentLink;\r
-  BOOLEAN                   MisMatch;\r
-\r
-  MisMatch          = FALSE;\r
-\r
-  CurrentDevicePath = RemainingDevicePath;\r
-  Node.DevPath      = CurrentDevicePath;\r
-  Temp              = NULL;\r
-\r
-  while (!IsDevicePathEnd (CurrentDevicePath)) {\r
-\r
-    CurrentLink   = RootBridge->ChildList.ForwardLink;\r
-    Node.DevPath  = CurrentDevicePath;\r
-\r
-    while (CurrentLink != NULL && CurrentLink != &RootBridge->ChildList) {\r
-      Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
-\r
-      if (Node.Pci->Device   == Temp->DeviceNumber &&\r
-          Node.Pci->Function == Temp->FunctionNumber) {\r
-        RootBridge = Temp;\r
-        break;\r
-      }\r
-\r
-      CurrentLink = CurrentLink->ForwardLink;\r
-    }\r
-\r
-    //\r
-    // Check if we find the bridge\r
-    //\r
-    if (CurrentLink == &RootBridge->ChildList) {\r
-\r
-      MisMatch = TRUE;\r
-      break;\r
-\r
-    }\r
-\r
-    CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);\r
-  }\r
-\r
-  if (MisMatch) {\r
-\r
-    CurrentDevicePath = NextDevicePathNode (CurrentDevicePath);\r
-\r
-    if (IsDevicePathEnd (CurrentDevicePath)) {\r
-      *PciAddress = EFI_PCI_ADDRESS (RootBridge->BusNumber, Node.Pci->Device, Node.Pci->Function, 0);\r
-      return EFI_SUCCESS;\r
-    }\r
-\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  if (Temp != NULL) {\r
-    *PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);\r
-  } else {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-\r
-}\r
-\r