Remove the references to DuetPkg.  Copy the files from revision
ffea0a2ce2 of DuetPkg into
CorebootModulePkg.  The components include:
* PciBusNoEnumerationDxe
* PciRootBridgeNoEnumerationDxe
* SataControllerDxe
TEST=Build and run on Galileo Gen2
Change-Id: Id07185f7e226749e5f7c6b6cb427bcef7eac8496
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Lee Leahy <leroy.p.leahy@intel.com>
Reviewed-by: Maurice Ma <maurice.ma@intel.com>
Reviewed-by: Prince Agyeman <prince.agyeman@intel.com>
		
	
		
			
				
	
	
		
			974 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			974 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*++
 | 
						|
 | 
						|
Copyright (c) 2005 - 2006, Intel Corporation. All rights reserved.<BR>
 | 
						|
This program and the accompanying materials                          
 | 
						|
are licensed and made available under the terms and conditions of the BSD License         
 | 
						|
which accompanies this distribution.  The full text of the license may be found at        
 | 
						|
http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
                                                                                          
 | 
						|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | 
						|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | 
						|
 | 
						|
Module Name:
 | 
						|
 | 
						|
  PciDeviceSupport.c
 | 
						|
  
 | 
						|
Abstract:
 | 
						|
 | 
						|
  This file provides routine to support Pci device node manipulation
 | 
						|
 | 
						|
Revision History
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
#include "PciBus.h"
 | 
						|
 | 
						|
//
 | 
						|
// This device structure is serviced as a header.
 | 
						|
// Its Next field points to the first root bridge device node
 | 
						|
//
 | 
						|
LIST_ENTRY  gPciDevicePool;
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
InitializePciDevicePool (
 | 
						|
  VOID
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Initialize the gPciDevicePool
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  InitializeListHead (&gPciDevicePool);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
InsertRootBridge (
 | 
						|
  IN PCI_IO_DEVICE *RootBridge
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Insert a root bridge into PCI device pool
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  RootBridge    - A pointer to the PCI_IO_DEVICE.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  InsertTailList (&gPciDevicePool, &(RootBridge->Link));
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
InsertPciDevice (
 | 
						|
  PCI_IO_DEVICE *Bridge,
 | 
						|
  PCI_IO_DEVICE *PciDeviceNode
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function is used to insert a PCI device node under
 | 
						|
  a bridge
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Bridge        - A pointer to the PCI_IO_DEVICE.
 | 
						|
  PciDeviceNode - A pointer to the PCI_IO_DEVICE.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
 | 
						|
{
 | 
						|
 | 
						|
  InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link));
 | 
						|
  PciDeviceNode->Parent = Bridge;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DestroyRootBridge (
 | 
						|
  IN PCI_IO_DEVICE *RootBridge
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
  RootBridge   - A pointer to the PCI_IO_DEVICE.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  DestroyPciDeviceTree (RootBridge);
 | 
						|
 | 
						|
  gBS->FreePool (RootBridge);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DestroyPciDeviceTree (
 | 
						|
  IN PCI_IO_DEVICE *Bridge
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Destroy all the pci device node under the bridge.
 | 
						|
  Bridge itself is not included.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Bridge   - A pointer to the PCI_IO_DEVICE.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  LIST_ENTRY  *CurrentLink;
 | 
						|
  PCI_IO_DEVICE   *Temp;
 | 
						|
 | 
						|
  while (!IsListEmpty (&Bridge->ChildList)) {
 | 
						|
 | 
						|
    CurrentLink = Bridge->ChildList.ForwardLink;
 | 
						|
 | 
						|
    //
 | 
						|
    // Remove this node from the linked list
 | 
						|
    //
 | 
						|
    RemoveEntryList (CurrentLink);
 | 
						|
 | 
						|
    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
 | 
						|
 | 
						|
    if (IS_PCI_BRIDGE (&(Temp->Pci))) {
 | 
						|
      DestroyPciDeviceTree (Temp);
 | 
						|
    }
 | 
						|
    gBS->FreePool (Temp);
 | 
						|
  }
 | 
						|
  
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DestroyRootBridgeByHandle (
 | 
						|
  EFI_HANDLE Controller
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Destroy all device nodes under the root bridge
 | 
						|
  specified by Controller. 
 | 
						|
  The root bridge itself is also included.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Controller   - An efi handle.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
 | 
						|
  LIST_ENTRY  *CurrentLink;
 | 
						|
  PCI_IO_DEVICE   *Temp;
 | 
						|
 | 
						|
  CurrentLink = gPciDevicePool.ForwardLink;
 | 
						|
 | 
						|
  while (CurrentLink && CurrentLink != &gPciDevicePool) {
 | 
						|
    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
 | 
						|
 | 
						|
    if (Temp->Handle == Controller) {
 | 
						|
 | 
						|
      RemoveEntryList (CurrentLink);
 | 
						|
 | 
						|
      DestroyPciDeviceTree (Temp);
 | 
						|
 | 
						|
      gBS->FreePool(Temp);
 | 
						|
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentLink = CurrentLink->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
RegisterPciDevice (
 | 
						|
  IN  EFI_HANDLE                     Controller,
 | 
						|
  IN  PCI_IO_DEVICE                  *PciIoDevice,
 | 
						|
  OUT EFI_HANDLE                     *Handle OPTIONAL
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function registers the PCI IO device. It creates a handle for this PCI IO device 
 | 
						|
  (if the handle does not exist), attaches appropriate protocols onto the handle, does
 | 
						|
  necessary initialization, and sets up parent/child relationship with its bus controller.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Controller    - An EFI handle for the PCI bus controller.
 | 
						|
  PciIoDevice   - A PCI_IO_DEVICE pointer to the PCI IO device to be registered.
 | 
						|
  Handle        - A pointer to hold the EFI handle for the PCI IO device.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  EFI_SUCCESS   - The PCI device is successfully registered.
 | 
						|
  Others        - An error occurred when registering the PCI device.
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  UINT8               PciExpressCapRegOffset;
 | 
						|
 | 
						|
  //
 | 
						|
  // Install the pciio protocol, device path protocol and 
 | 
						|
  // Bus Specific Driver Override Protocol
 | 
						|
  //
 | 
						|
 | 
						|
  if (PciIoDevice->BusOverride) {
 | 
						|
    Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &PciIoDevice->Handle,             
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  PciIoDevice->DevicePath,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  &PciIoDevice->PciIo,
 | 
						|
                  &gEfiBusSpecificDriverOverrideProtocolGuid,
 | 
						|
                  &PciIoDevice->PciDriverOverride,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  } else {
 | 
						|
    Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &PciIoDevice->Handle,             
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  PciIoDevice->DevicePath,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  &PciIoDevice->PciIo,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  } else {
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    Controller,           
 | 
						|
                    &gEfiPciRootBridgeIoProtocolGuid, 
 | 
						|
                    (VOID **)&(PciIoDevice->PciRootBridgeIo),
 | 
						|
                    gPciBusDriverBinding.DriverBindingHandle,
 | 
						|
                    PciIoDevice->Handle,   
 | 
						|
                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  if (Handle != NULL) {
 | 
						|
    *Handle = PciIoDevice->Handle;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Detect if PCI Express Device
 | 
						|
  //
 | 
						|
  PciExpressCapRegOffset = 0;
 | 
						|
  Status = LocateCapabilityRegBlock (
 | 
						|
             PciIoDevice,
 | 
						|
             EFI_PCI_CAPABILITY_ID_PCIEXP,
 | 
						|
             &PciExpressCapRegOffset,
 | 
						|
             NULL
 | 
						|
             );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    PciIoDevice->IsPciExp = TRUE;
 | 
						|
    DEBUG ((EFI_D_ERROR, "PciExp - %x (B-%x, D-%x, F-%x)\n", PciIoDevice->IsPciExp, PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber));
 | 
						|
  }
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Indicate the pci device is registered
 | 
						|
  //
 | 
						|
  PciIoDevice->Registered = TRUE;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
DeRegisterPciDevice (
 | 
						|
  IN  EFI_HANDLE                     Controller,
 | 
						|
  IN  EFI_HANDLE                     Handle
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function is used to de-register the PCI device from the EFI,
 | 
						|
  That includes un-installing PciIo protocol from the specified PCI 
 | 
						|
  device handle.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Controller   - An efi handle.
 | 
						|
  Handle       - An efi handle.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_PCI_IO_PROTOCOL             *PciIo;
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  PCI_IO_DEVICE                   *PciIoDevice;
 | 
						|
  PCI_IO_DEVICE                   *Node;
 | 
						|
  LIST_ENTRY                  *CurrentLink;
 | 
						|
  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Handle,
 | 
						|
                  &gEfiPciIoProtocolGuid,
 | 
						|
                  (VOID **) &PciIo,
 | 
						|
                  gPciBusDriverBinding.DriverBindingHandle,
 | 
						|
                  Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
 | 
						|
 | 
						|
    //
 | 
						|
    // If it is already de-registered
 | 
						|
    //
 | 
						|
    if (!PciIoDevice->Registered) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // If it is PPB, first de-register its children
 | 
						|
    //
 | 
						|
 | 
						|
    if (IS_PCI_BRIDGE (&(PciIoDevice->Pci))) {
 | 
						|
 | 
						|
      CurrentLink = PciIoDevice->ChildList.ForwardLink;
 | 
						|
 | 
						|
      while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) {
 | 
						|
        Node    = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
 | 
						|
        Status  = DeRegisterPciDevice (Controller, Node->Handle);
 | 
						|
 | 
						|
        if (EFI_ERROR (Status)) {
 | 
						|
          return Status;
 | 
						|
        }
 | 
						|
 | 
						|
        CurrentLink = CurrentLink->ForwardLink;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // First disconnect this device
 | 
						|
    //
 | 
						|
//    PciIoDevice->PciIo.Attributes(&(PciIoDevice->PciIo),
 | 
						|
//                                    EfiPciIoAttributeOperationDisable,
 | 
						|
//                                    EFI_PCI_DEVICE_ENABLE,
 | 
						|
//                                    NULL
 | 
						|
//                                    );
 | 
						|
       
 | 
						|
    //
 | 
						|
    // Close the child handle
 | 
						|
    //
 | 
						|
    Status = gBS->CloseProtocol (
 | 
						|
                    Controller,
 | 
						|
                    &gEfiPciRootBridgeIoProtocolGuid,
 | 
						|
                    gPciBusDriverBinding.DriverBindingHandle,
 | 
						|
                    Handle
 | 
						|
                    );
 | 
						|
 | 
						|
    //
 | 
						|
    // Un-install the device path protocol and pci io protocol
 | 
						|
    //
 | 
						|
    if (PciIoDevice->BusOverride) {
 | 
						|
      Status = gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
                      Handle,
 | 
						|
                      &gEfiDevicePathProtocolGuid,
 | 
						|
                      PciIoDevice->DevicePath,
 | 
						|
                      &gEfiPciIoProtocolGuid,
 | 
						|
                      &PciIoDevice->PciIo,
 | 
						|
                      &gEfiBusSpecificDriverOverrideProtocolGuid,
 | 
						|
                      &PciIoDevice->PciDriverOverride,
 | 
						|
                      NULL
 | 
						|
                      );
 | 
						|
    } else {
 | 
						|
      Status = gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
                      Handle,
 | 
						|
                      &gEfiDevicePathProtocolGuid,
 | 
						|
                      PciIoDevice->DevicePath,
 | 
						|
                      &gEfiPciIoProtocolGuid,
 | 
						|
                      &PciIoDevice->PciIo,
 | 
						|
                      NULL
 | 
						|
                      );
 | 
						|
    }
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      gBS->OpenProtocol (
 | 
						|
            Controller,
 | 
						|
            &gEfiPciRootBridgeIoProtocolGuid,
 | 
						|
            (VOID **) &PciRootBridgeIo,
 | 
						|
            gPciBusDriverBinding.DriverBindingHandle,
 | 
						|
            Handle,
 | 
						|
            EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
            );
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    
 | 
						|
    //
 | 
						|
    // The Device Driver should disable this device after disconnect
 | 
						|
    // so the Pci Bus driver will not touch this device any more.
 | 
						|
    // Restore the register field to the original value
 | 
						|
    //
 | 
						|
    PciIoDevice->Registered = FALSE;
 | 
						|
    PciIoDevice->Handle     = NULL;
 | 
						|
  } else {
 | 
						|
 | 
						|
    //
 | 
						|
    // Handle may be closed before
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EnableBridgeAttributes (
 | 
						|
  IN PCI_IO_DEVICE                       *PciIoDevice
 | 
						|
  )
 | 
						|
{
 | 
						|
  PCI_TYPE01                PciData;
 | 
						|
 | 
						|
  //
 | 
						|
  // NOTE: We should not set EFI_PCI_DEVICE_ENABLE for a bridge
 | 
						|
  //       directly, because some legacy BIOS will NOT assign
 | 
						|
  //       IO or Memory resource for a bridge who has no child
 | 
						|
  //       device. So we add check IO or Memory here.
 | 
						|
  //
 | 
						|
 | 
						|
  PciIoDevice->PciIo.Pci.Read (
 | 
						|
                           &PciIoDevice->PciIo,
 | 
						|
                           EfiPciIoWidthUint8,
 | 
						|
                           0,
 | 
						|
                           sizeof (PciData),
 | 
						|
                           &PciData
 | 
						|
                           );
 | 
						|
 | 
						|
  if ((((PciData.Bridge.IoBase & 0xF) == 0) &&
 | 
						|
        (PciData.Bridge.IoBase != 0 || PciData.Bridge.IoLimit != 0)) ||
 | 
						|
      (((PciData.Bridge.IoBase & 0xF) == 1) &&
 | 
						|
        ((PciData.Bridge.IoBase & 0xF0) != 0 || (PciData.Bridge.IoLimit & 0xF0) != 0 || PciData.Bridge.IoBaseUpper16 != 0 || PciData.Bridge.IoLimitUpper16 != 0))) {
 | 
						|
    PciIoDevice->PciIo.Attributes(
 | 
						|
                         &(PciIoDevice->PciIo),
 | 
						|
                         EfiPciIoAttributeOperationEnable,
 | 
						|
                         (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
 | 
						|
                         NULL
 | 
						|
                         );
 | 
						|
  }
 | 
						|
  if ((PciData.Bridge.MemoryBase & 0xFFF0) != 0 || (PciData.Bridge.MemoryLimit & 0xFFF0) != 0) {
 | 
						|
    PciIoDevice->PciIo.Attributes(
 | 
						|
                         &(PciIoDevice->PciIo),
 | 
						|
                         EfiPciIoAttributeOperationEnable,
 | 
						|
                         (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
 | 
						|
                         NULL
 | 
						|
                         );
 | 
						|
  }
 | 
						|
  if ((((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 0) &&
 | 
						|
        (PciData.Bridge.PrefetchableMemoryBase != 0 || PciData.Bridge.PrefetchableMemoryLimit != 0)) ||
 | 
						|
      (((PciData.Bridge.PrefetchableMemoryBase & 0xF) == 1) &&
 | 
						|
        ((PciData.Bridge.PrefetchableMemoryBase & 0xFFF0) != 0 || (PciData.Bridge.PrefetchableMemoryLimit & 0xFFF0) != 0 || PciData.Bridge.PrefetchableBaseUpper32 != 0 || PciData.Bridge.PrefetchableLimitUpper32 != 0))) {
 | 
						|
    PciIoDevice->PciIo.Attributes(
 | 
						|
                         &(PciIoDevice->PciIo),
 | 
						|
                         EfiPciIoAttributeOperationEnable,
 | 
						|
                         (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER),
 | 
						|
                         NULL
 | 
						|
                         );
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS 
 | 
						|
StartPciDevicesOnBridge (
 | 
						|
  IN EFI_HANDLE                          Controller,
 | 
						|
  IN PCI_IO_DEVICE                       *RootBridge,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL            *RemainingDevicePath 
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Controller          - An efi handle.
 | 
						|
  RootBridge          - A pointer to the PCI_IO_DEVICE.
 | 
						|
  RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
 | 
						|
  NumberOfChildren    - Children number.
 | 
						|
  ChildHandleBuffer   - A pointer to the child handle buffer.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  PCI_IO_DEVICE             *Temp;
 | 
						|
  PCI_IO_DEVICE             *PciIoDevice;
 | 
						|
  EFI_DEV_PATH_PTR          Node;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  *CurrentDevicePath;
 | 
						|
  EFI_STATUS                Status;
 | 
						|
  LIST_ENTRY            *CurrentLink;
 | 
						|
 | 
						|
  CurrentLink = RootBridge->ChildList.ForwardLink;
 | 
						|
 | 
						|
  while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
 | 
						|
 | 
						|
    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
 | 
						|
    if (RemainingDevicePath != NULL) {
 | 
						|
 | 
						|
      Node.DevPath = RemainingDevicePath;
 | 
						|
 | 
						|
      if (Node.Pci->Device != Temp->DeviceNumber || 
 | 
						|
          Node.Pci->Function != Temp->FunctionNumber) {
 | 
						|
        CurrentLink = CurrentLink->ForwardLink;
 | 
						|
        continue;
 | 
						|
      }
 | 
						|
 | 
						|
      //
 | 
						|
      // Check if the device has been assigned with required resource
 | 
						|
      //
 | 
						|
      if (!Temp->Allocated) {
 | 
						|
        return EFI_NOT_READY;
 | 
						|
      }
 | 
						|
      
 | 
						|
      //
 | 
						|
      // Check if the current node has been registered before
 | 
						|
      // If it is not, register it
 | 
						|
      //
 | 
						|
      if (!Temp->Registered) {
 | 
						|
        PciIoDevice = Temp;
 | 
						|
 | 
						|
        Status = RegisterPciDevice (
 | 
						|
                  Controller,
 | 
						|
                  PciIoDevice,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
 | 
						|
      }
 | 
						|
      
 | 
						|
      //
 | 
						|
      // Get the next device path
 | 
						|
      //
 | 
						|
      CurrentDevicePath = NextDevicePathNode (RemainingDevicePath);
 | 
						|
      if (IsDevicePathEnd (CurrentDevicePath)) {
 | 
						|
        return EFI_SUCCESS;
 | 
						|
      }
 | 
						|
  
 | 
						|
      //
 | 
						|
      // If it is a PPB
 | 
						|
      //
 | 
						|
      if (IS_PCI_BRIDGE (&(Temp->Pci))) {
 | 
						|
        Status = StartPciDevicesOnBridge (
 | 
						|
                  Controller,
 | 
						|
                  Temp,
 | 
						|
                  CurrentDevicePath
 | 
						|
                  );
 | 
						|
        EnableBridgeAttributes (Temp);
 | 
						|
 | 
						|
        return Status;
 | 
						|
      } else {
 | 
						|
 | 
						|
        //
 | 
						|
        // Currently, the PCI bus driver only support PCI-PCI bridge
 | 
						|
        //
 | 
						|
        return EFI_UNSUPPORTED;
 | 
						|
      }
 | 
						|
 | 
						|
    } else {
 | 
						|
 | 
						|
      //
 | 
						|
      // If remaining device path is NULL,
 | 
						|
      // try to enable all the pci devices under this bridge
 | 
						|
      //
 | 
						|
 | 
						|
      if (!Temp->Registered && Temp->Allocated) {
 | 
						|
 | 
						|
        PciIoDevice = Temp;
 | 
						|
 | 
						|
        Status = RegisterPciDevice (
 | 
						|
                  Controller,
 | 
						|
                  PciIoDevice,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
 | 
						|
      }
 | 
						|
 | 
						|
      if (IS_PCI_BRIDGE (&(Temp->Pci))) {
 | 
						|
        Status = StartPciDevicesOnBridge ( 
 | 
						|
                   Controller,
 | 
						|
                   Temp,
 | 
						|
                   RemainingDevicePath
 | 
						|
                   );
 | 
						|
        EnableBridgeAttributes (Temp);
 | 
						|
      }
 | 
						|
 | 
						|
      CurrentLink = CurrentLink->ForwardLink;
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
StartPciDevices (
 | 
						|
  IN EFI_HANDLE                         Controller,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL           *RemainingDevicePath
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  Start to manage the PCI device according to RemainingDevicePath
 | 
						|
  If RemainingDevicePath == NULL, the PCI bus driver will start 
 | 
						|
  to manage all the PCI devices it found previously
 | 
						|
 | 
						|
Arguments:
 | 
						|
  Controller          - An efi handle.
 | 
						|
  RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  EFI_DEV_PATH_PTR  Node;
 | 
						|
  PCI_IO_DEVICE     *RootBridge;
 | 
						|
  LIST_ENTRY    *CurrentLink;
 | 
						|
 | 
						|
  if (RemainingDevicePath != NULL) {
 | 
						|
 | 
						|
    //
 | 
						|
    // Check if the RemainingDevicePath is valid
 | 
						|
    //
 | 
						|
    Node.DevPath = RemainingDevicePath;
 | 
						|
    if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||
 | 
						|
        Node.DevPath->SubType != HW_PCI_DP         ||
 | 
						|
        DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH)
 | 
						|
        ) {
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  CurrentLink = gPciDevicePool.ForwardLink;
 | 
						|
 | 
						|
  while (CurrentLink && CurrentLink != &gPciDevicePool) {
 | 
						|
 | 
						|
    RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
 | 
						|
    //
 | 
						|
    // Locate the right root bridge to start
 | 
						|
    //
 | 
						|
    if (RootBridge->Handle == Controller) {
 | 
						|
      StartPciDevicesOnBridge (
 | 
						|
        Controller,
 | 
						|
        RootBridge,
 | 
						|
        RemainingDevicePath
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentLink = CurrentLink->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
PCI_IO_DEVICE *
 | 
						|
CreateRootBridge (
 | 
						|
  IN EFI_HANDLE RootBridgeHandle
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
 | 
						|
Arguments:
 | 
						|
  RootBridgeHandle   - An efi handle.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  PCI_IO_DEVICE                   *Dev;
 | 
						|
 | 
						|
  Dev = NULL;
 | 
						|
  Status = gBS->AllocatePool (
 | 
						|
                  EfiBootServicesData,
 | 
						|
                  sizeof (PCI_IO_DEVICE),
 | 
						|
                  (VOID **) &Dev
 | 
						|
                  );
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return NULL;
 | 
						|
  }
 | 
						|
 | 
						|
  ZeroMem (Dev, sizeof (PCI_IO_DEVICE));
 | 
						|
  Dev->Signature  = PCI_IO_DEVICE_SIGNATURE;
 | 
						|
  Dev->Handle     = RootBridgeHandle;
 | 
						|
  InitializeListHead (&Dev->ChildList);
 | 
						|
 | 
						|
  return Dev;
 | 
						|
}
 | 
						|
 | 
						|
PCI_IO_DEVICE *
 | 
						|
GetRootBridgeByHandle (
 | 
						|
  EFI_HANDLE RootBridgeHandle
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  RootBridgeHandle    - An efi handle.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  PCI_IO_DEVICE   *RootBridgeDev;
 | 
						|
  LIST_ENTRY  *CurrentLink;
 | 
						|
 | 
						|
  CurrentLink = gPciDevicePool.ForwardLink;
 | 
						|
 | 
						|
  while (CurrentLink && CurrentLink != &gPciDevicePool) {
 | 
						|
 | 
						|
    RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
 | 
						|
    if (RootBridgeDev->Handle == RootBridgeHandle) {
 | 
						|
      return RootBridgeDev;
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentLink = CurrentLink->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
RootBridgeExisted (
 | 
						|
  IN EFI_HANDLE RootBridgeHandle
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
  This function searches if RootBridgeHandle has already existed
 | 
						|
  in current device pool.
 | 
						|
 | 
						|
  If so, it means the given root bridge has been already enumerated.
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  RootBridgeHandle   - An efi handle.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  PCI_IO_DEVICE *Bridge;
 | 
						|
 | 
						|
  Bridge = GetRootBridgeByHandle (RootBridgeHandle);
 | 
						|
 | 
						|
  if (Bridge != NULL) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
PciDeviceExisted (
 | 
						|
  IN PCI_IO_DEVICE    *Bridge,
 | 
						|
  IN PCI_IO_DEVICE    *PciIoDevice
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
  
 | 
						|
Arguments:
 | 
						|
 | 
						|
  Bridge       - A pointer to the PCI_IO_DEVICE.
 | 
						|
  PciIoDevice  - A pointer to the PCI_IO_DEVICE.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
 | 
						|
  PCI_IO_DEVICE   *Temp;
 | 
						|
  LIST_ENTRY  *CurrentLink;
 | 
						|
 | 
						|
  CurrentLink = Bridge->ChildList.ForwardLink;
 | 
						|
 | 
						|
  while (CurrentLink && CurrentLink != &Bridge->ChildList) {
 | 
						|
 | 
						|
    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
 | 
						|
 | 
						|
    if (Temp == PciIoDevice) {
 | 
						|
      return TRUE;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!IsListEmpty (&Temp->ChildList)) {
 | 
						|
      if (PciDeviceExisted (Temp, PciIoDevice)) {
 | 
						|
        return TRUE;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentLink = CurrentLink->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
PCI_IO_DEVICE *
 | 
						|
ActiveVGADeviceOnTheSameSegment (
 | 
						|
  IN PCI_IO_DEVICE        *VgaDevice
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  VgaDevice    - A pointer to the PCI_IO_DEVICE.
 | 
						|
  
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  LIST_ENTRY  *CurrentLink;
 | 
						|
  PCI_IO_DEVICE   *Temp;
 | 
						|
 | 
						|
  CurrentLink = gPciDevicePool.ForwardLink;
 | 
						|
 | 
						|
  while (CurrentLink && CurrentLink != &gPciDevicePool) {
 | 
						|
 | 
						|
    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
 | 
						|
 | 
						|
    if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) {
 | 
						|
 | 
						|
      Temp = ActiveVGADeviceOnTheRootBridge (Temp);
 | 
						|
 | 
						|
      if (Temp != NULL) {
 | 
						|
        return Temp;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentLink = CurrentLink->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 | 
						|
 | 
						|
PCI_IO_DEVICE *
 | 
						|
ActiveVGADeviceOnTheRootBridge (
 | 
						|
  IN PCI_IO_DEVICE        *RootBridge
 | 
						|
  )
 | 
						|
/*++
 | 
						|
 | 
						|
Routine Description:
 | 
						|
 | 
						|
Arguments:
 | 
						|
 | 
						|
  RootBridge    - A pointer to the PCI_IO_DEVICE.
 | 
						|
 | 
						|
Returns:
 | 
						|
 | 
						|
  None
 | 
						|
 | 
						|
--*/
 | 
						|
{
 | 
						|
  LIST_ENTRY  *CurrentLink;
 | 
						|
  PCI_IO_DEVICE   *Temp;
 | 
						|
 | 
						|
  CurrentLink = RootBridge->ChildList.ForwardLink;
 | 
						|
 | 
						|
  while (CurrentLink && CurrentLink != &RootBridge->ChildList) {
 | 
						|
 | 
						|
    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
 | 
						|
 | 
						|
    if (IS_PCI_VGA(&Temp->Pci) && 
 | 
						|
        (Temp->Attributes &
 | 
						|
         (EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY |
 | 
						|
          EFI_PCI_IO_ATTRIBUTE_VGA_IO     |
 | 
						|
          EFI_PCI_IO_ATTRIBUTE_VGA_IO_16))) {
 | 
						|
      return Temp;
 | 
						|
    }
 | 
						|
 | 
						|
    if (IS_PCI_BRIDGE (&Temp->Pci)) {
 | 
						|
 | 
						|
      Temp = ActiveVGADeviceOnTheRootBridge (Temp);
 | 
						|
 | 
						|
      if (Temp != NULL) {
 | 
						|
        return Temp;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    CurrentLink = CurrentLink->ForwardLink;
 | 
						|
  }
 | 
						|
 | 
						|
  return NULL;
 | 
						|
}
 |