mirror of https://github.com/acidanthera/audk.git
2160 lines
54 KiB
C
2160 lines
54 KiB
C
/**@file
|
|
|
|
Copyright (c) 2006, Intel Corporation
|
|
All rights reserved. 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.
|
|
|
|
**/
|
|
|
|
|
|
#include "pcibus.h"
|
|
#include "PciEnumerator.h"
|
|
#include "PciResourceSupport.h"
|
|
#include "PciOptionRomSupport.h"
|
|
|
|
EFI_STATUS
|
|
PciEnumerator (
|
|
IN EFI_HANDLE Controller
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to enumerate entire pci bus system
|
|
in a given platform
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: Controller - add argument and description to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
|
|
EFI_HANDLE HostBridgeHandle;
|
|
EFI_STATUS Status;
|
|
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;
|
|
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
|
|
|
|
//
|
|
// If PCI bus has already done the full enumeration, never do it again
|
|
//
|
|
if (!gFullEnumeration) {
|
|
return PciEnumeratorLight (Controller);
|
|
}
|
|
|
|
//
|
|
// If this host bridge has been already enumerated, then return successfully
|
|
//
|
|
if (RootBridgeExisted (Controller)) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Get the rootbridge Io protocol to find the host bridge handle
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiPciRootBridgeIoProtocolGuid,
|
|
(VOID **) &PciRootBridgeIo,
|
|
gPciBusDriverBinding.DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Get the host bridge handle
|
|
//
|
|
HostBridgeHandle = PciRootBridgeIo->ParentHandle;
|
|
|
|
//
|
|
// Get the pci host bridge resource allocation protocol
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
HostBridgeHandle,
|
|
&gEfiPciHostBridgeResourceAllocationProtocolGuid,
|
|
(VOID **) &PciResAlloc,
|
|
gPciBusDriverBinding.DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Notify the pci bus enumeration is about to begin
|
|
//
|
|
NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);
|
|
|
|
//
|
|
// Start the bus allocation phase
|
|
//
|
|
Status = PciHostBridgeEnumerator (PciResAlloc);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Submit the resource request
|
|
//
|
|
Status = PciHostBridgeResourceAllocator (PciResAlloc);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Process P2C
|
|
//
|
|
Status = PciHostBridgeP2CProcess (PciResAlloc);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Process attributes for devices on this host bridge
|
|
//
|
|
Status = PciHostBridgeDeviceAttribute (PciResAlloc);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
gFullEnumeration = FALSE;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
PciRootBridgeEnumerator (
|
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
|
|
IN PCI_IO_DEVICE *RootBridgeDev
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: PciResAlloc - add argument and description to function comment
|
|
// TODO: RootBridgeDev - add argument and description to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *pConfiguration;
|
|
UINT8 SubBusNumber;
|
|
UINT8 StartBusNumber;
|
|
UINT8 PaddedBusRange;
|
|
EFI_HANDLE RootBridgeHandle;
|
|
|
|
SubBusNumber = 0;
|
|
StartBusNumber = 0;
|
|
PaddedBusRange = 0;
|
|
|
|
//
|
|
// Get the root bridge handle
|
|
//
|
|
RootBridgeHandle = RootBridgeDev->Handle;
|
|
|
|
REPORT_STATUS_CODE_WITH_DEVICE_PATH (
|
|
EFI_PROGRESS_CODE,
|
|
EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM,
|
|
RootBridgeDev->DevicePath
|
|
);
|
|
|
|
//
|
|
// Get the Bus information
|
|
//
|
|
Status = PciResAlloc->StartBusEnumeration (
|
|
PciResAlloc,
|
|
RootBridgeHandle,
|
|
(VOID **) &pConfiguration
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Get the bus number to start with
|
|
//
|
|
StartBusNumber = (UINT8) (pConfiguration->AddrRangeMin);
|
|
|
|
//
|
|
// Initialize the subordinate bus number
|
|
//
|
|
SubBusNumber = StartBusNumber;
|
|
|
|
//
|
|
// Assign bus number
|
|
//
|
|
Status = PciScanBus (
|
|
RootBridgeDev,
|
|
(UINT8) (pConfiguration->AddrRangeMin),
|
|
&SubBusNumber,
|
|
&PaddedBusRange
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
|
|
//
|
|
// Assign max bus number scanned
|
|
//
|
|
pConfiguration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange;
|
|
|
|
//
|
|
// Set bus number
|
|
//
|
|
Status = PciResAlloc->SetBusNumbers (
|
|
PciResAlloc,
|
|
RootBridgeHandle,
|
|
pConfiguration
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
ProcessOptionRom (
|
|
IN PCI_IO_DEVICE *Bridge,
|
|
IN UINT64 RomBase,
|
|
IN UINT64 MaxLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to process option rom on a certain root bridge
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: Bridge - add argument and description to function comment
|
|
// TODO: RomBase - add argument and description to function comment
|
|
// TODO: MaxLength - add argument and description to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
LIST_ENTRY *CurrentLink;
|
|
PCI_IO_DEVICE *Temp;
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Go through bridges to reach all devices
|
|
//
|
|
CurrentLink = Bridge->ChildList.ForwardLink;
|
|
while (CurrentLink && CurrentLink != &Bridge->ChildList) {
|
|
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
|
|
if (!IsListEmpty (&Temp->ChildList)) {
|
|
|
|
//
|
|
// Go further to process the option rom under this bridge
|
|
//
|
|
Status = ProcessOptionRom (Temp, RomBase, MaxLength);
|
|
}
|
|
|
|
if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {
|
|
|
|
//
|
|
// Load and process the option rom
|
|
//
|
|
Status = LoadOpRomImage (Temp, RomBase);
|
|
if (Status == EFI_SUCCESS) {
|
|
Status = ProcessOpRomImage (Temp);
|
|
}
|
|
}
|
|
|
|
CurrentLink = CurrentLink->ForwardLink;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
PciAssignBusNumber (
|
|
IN PCI_IO_DEVICE *Bridge,
|
|
IN UINT8 StartBusNumber,
|
|
OUT UINT8 *SubBusNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to assign bus number to the given PCI bus system
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: Bridge - add argument and description to function comment
|
|
// TODO: StartBusNumber - add argument and description to function comment
|
|
// TODO: SubBusNumber - add argument and description to function comment
|
|
// TODO: EFI_DEVICE_ERROR - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
EFI_STATUS Status;
|
|
PCI_TYPE00 Pci;
|
|
UINT8 Device;
|
|
UINT8 Func;
|
|
UINT64 Address;
|
|
UINTN SecondBus;
|
|
UINT16 Register;
|
|
UINT8 Register8;
|
|
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
|
|
|
|
PciRootBridgeIo = Bridge->PciRootBridgeIo;
|
|
|
|
SecondBus = 0;
|
|
Register = 0;
|
|
|
|
*SubBusNumber = StartBusNumber;
|
|
|
|
//
|
|
// First check to see whether the parent is ppb
|
|
//
|
|
for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
|
|
for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
|
|
|
|
//
|
|
// Check to see whether a pci device is present
|
|
//
|
|
|
|
Status = PciDevicePresent (
|
|
PciRootBridgeIo,
|
|
&Pci,
|
|
StartBusNumber,
|
|
Device,
|
|
Func
|
|
);
|
|
|
|
if (!EFI_ERROR (Status) &&
|
|
(IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
|
|
|
|
//
|
|
// Reserved one bus for cardbus bridge
|
|
//
|
|
SecondBus = ++(*SubBusNumber);
|
|
|
|
Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
|
|
|
|
Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
|
|
|
|
Status = PciRootBridgeIoWrite (
|
|
PciRootBridgeIo,
|
|
&Pci,
|
|
EfiPciWidthUint16,
|
|
Address,
|
|
1,
|
|
&Register
|
|
);
|
|
|
|
//
|
|
// Initialize SubBusNumber to SecondBus
|
|
//
|
|
Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
|
|
Status = PciRootBridgeIoWrite (
|
|
PciRootBridgeIo,
|
|
&Pci,
|
|
EfiPciWidthUint8,
|
|
Address,
|
|
1,
|
|
SubBusNumber
|
|
);
|
|
//
|
|
// If it is PPB, resursively search down this bridge
|
|
//
|
|
if (IS_PCI_BRIDGE (&Pci)) {
|
|
|
|
Register8 = 0xFF;
|
|
Status = PciRootBridgeIoWrite (
|
|
PciRootBridgeIo,
|
|
&Pci,
|
|
EfiPciWidthUint8,
|
|
Address,
|
|
1,
|
|
&Register8
|
|
);
|
|
|
|
Status = PciAssignBusNumber (
|
|
Bridge,
|
|
(UINT8) (SecondBus),
|
|
SubBusNumber
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Set the current maximum bus number under the PPB
|
|
//
|
|
|
|
Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
|
|
|
|
Status = PciRootBridgeIoWrite (
|
|
PciRootBridgeIo,
|
|
&Pci,
|
|
EfiPciWidthUint8,
|
|
Address,
|
|
1,
|
|
SubBusNumber
|
|
);
|
|
|
|
}
|
|
|
|
if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
|
|
|
|
//
|
|
// Skip sub functions, this is not a multi function device
|
|
//
|
|
|
|
Func = PCI_MAX_FUNC;
|
|
}
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
DetermineRootBridgeAttributes (
|
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
|
|
IN PCI_IO_DEVICE *RootBridgeDev
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine is used to determine the root bridge attribute by interfacing
|
|
the host bridge resource allocation protocol.
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: PciResAlloc - add argument and description to function comment
|
|
// TODO: RootBridgeDev - add argument and description to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
UINT64 Attributes;
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE RootBridgeHandle;
|
|
|
|
Attributes = 0;
|
|
RootBridgeHandle = RootBridgeDev->Handle;
|
|
|
|
//
|
|
// Get root bridge attribute by calling into pci host bridge resource allocation protocol
|
|
//
|
|
Status = PciResAlloc->GetAllocAttributes (
|
|
PciResAlloc,
|
|
RootBridgeHandle,
|
|
&Attributes
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Here is the point where PCI bus driver calls HOST bridge allocation protocol
|
|
// Currently we hardcoded for ea815
|
|
//
|
|
|
|
if (Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) {
|
|
RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;
|
|
}
|
|
|
|
if (Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) {
|
|
RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
|
|
}
|
|
|
|
RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
|
|
RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
|
|
RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
UINT64
|
|
GetMaxOptionRomSize (
|
|
IN PCI_IO_DEVICE *Bridge
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get Max Option Rom size on this bridge
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: Bridge - add argument and description to function comment
|
|
{
|
|
LIST_ENTRY *CurrentLink;
|
|
PCI_IO_DEVICE *Temp;
|
|
UINT64 MaxOptionRomSize;
|
|
UINT64 TempOptionRomSize;
|
|
|
|
MaxOptionRomSize = 0;
|
|
|
|
//
|
|
// Go through bridges to reach all devices
|
|
//
|
|
CurrentLink = Bridge->ChildList.ForwardLink;
|
|
while (CurrentLink && CurrentLink != &Bridge->ChildList) {
|
|
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
|
|
if (!IsListEmpty (&Temp->ChildList)) {
|
|
|
|
//
|
|
// Get max option rom size under this bridge
|
|
//
|
|
TempOptionRomSize = GetMaxOptionRomSize (Temp);
|
|
|
|
//
|
|
// Compare with the option rom size of the bridge
|
|
// Get the larger one
|
|
//
|
|
if (Temp->RomSize > TempOptionRomSize) {
|
|
TempOptionRomSize = Temp->RomSize;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// For devices get the rom size directly
|
|
//
|
|
TempOptionRomSize = Temp->RomSize;
|
|
}
|
|
|
|
//
|
|
// Get the largest rom size on this bridge
|
|
//
|
|
if (TempOptionRomSize > MaxOptionRomSize) {
|
|
MaxOptionRomSize = TempOptionRomSize;
|
|
}
|
|
|
|
CurrentLink = CurrentLink->ForwardLink;
|
|
}
|
|
|
|
return MaxOptionRomSize;
|
|
}
|
|
|
|
EFI_STATUS
|
|
PciHostBridgeDeviceAttribute (
|
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process attributes of devices on this host bridge
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: PciResAlloc - add argument and description to function comment
|
|
// TODO: EFI_NOT_FOUND - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
EFI_HANDLE RootBridgeHandle;
|
|
PCI_IO_DEVICE *RootBridgeDev;
|
|
EFI_STATUS Status;
|
|
|
|
RootBridgeHandle = NULL;
|
|
|
|
while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
|
|
|
|
//
|
|
// Get RootBridg Device by handle
|
|
//
|
|
RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
|
|
|
|
if (RootBridgeDev == NULL) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
//
|
|
// Set the attributes for devcies behind the Root Bridge
|
|
//
|
|
Status = DetermineDeviceAttribute (RootBridgeDev);
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetResourceAllocationStatus (
|
|
VOID *AcpiConfig,
|
|
OUT UINT64 *IoResStatus,
|
|
OUT UINT64 *Mem32ResStatus,
|
|
OUT UINT64 *PMem32ResStatus,
|
|
OUT UINT64 *Mem64ResStatus,
|
|
OUT UINT64 *PMem64ResStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get resource allocation status from the ACPI pointer
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: AcpiConfig - add argument and description to function comment
|
|
// TODO: IoResStatus - add argument and description to function comment
|
|
// TODO: Mem32ResStatus - add argument and description to function comment
|
|
// TODO: PMem32ResStatus - add argument and description to function comment
|
|
// TODO: Mem64ResStatus - add argument and description to function comment
|
|
// TODO: PMem64ResStatus - add argument and description to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
|
|
UINT8 *Temp;
|
|
UINT64 ResStatus;
|
|
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
|
|
|
|
Temp = (UINT8 *) AcpiConfig;
|
|
|
|
while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
|
|
|
|
ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
|
|
ResStatus = ptr->AddrTranslationOffset;
|
|
|
|
switch (ptr->ResType) {
|
|
case 0:
|
|
if (ptr->AddrSpaceGranularity == 32) {
|
|
if (ptr->SpecificFlag == 0x06) {
|
|
//
|
|
// Pmem32
|
|
//
|
|
*PMem32ResStatus = ResStatus;
|
|
} else {
|
|
//
|
|
// Mem32
|
|
//
|
|
*Mem32ResStatus = ResStatus;
|
|
}
|
|
}
|
|
|
|
if (ptr->AddrSpaceGranularity == 64) {
|
|
if (ptr->SpecificFlag == 0x06) {
|
|
//
|
|
// PMem64
|
|
//
|
|
*PMem64ResStatus = ResStatus;
|
|
} else {
|
|
//
|
|
// Mem64
|
|
//
|
|
*Mem64ResStatus = ResStatus;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
//
|
|
// Io
|
|
//
|
|
*IoResStatus = ResStatus;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
RejectPciDevice (
|
|
IN PCI_IO_DEVICE *PciDevice
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Remove a PCI device from device pool and mark its bar
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: PciDevice - add argument and description to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
// TODO: EFI_ABORTED - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
// TODO: EFI_ABORTED - add return value to function comment
|
|
{
|
|
PCI_IO_DEVICE *Bridge;
|
|
PCI_IO_DEVICE *Temp;
|
|
LIST_ENTRY *CurrentLink;
|
|
|
|
//
|
|
// Remove the padding resource from a bridge
|
|
//
|
|
if ( IS_PCI_BRIDGE(&PciDevice->Pci) && \
|
|
PciDevice->ResourcePaddingDescriptors ) {
|
|
gBS->FreePool (PciDevice->ResourcePaddingDescriptors);
|
|
PciDevice->ResourcePaddingDescriptors = NULL;
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Skip RB and PPB
|
|
//
|
|
if (IS_PCI_BRIDGE (&PciDevice->Pci) || (!PciDevice->Parent)) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {
|
|
//
|
|
// Get the root bridge device
|
|
//
|
|
Bridge = PciDevice;
|
|
while (Bridge->Parent) {
|
|
Bridge = Bridge->Parent;
|
|
}
|
|
|
|
RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);
|
|
|
|
//
|
|
// Mark its bar
|
|
//
|
|
InitializeP2C (PciDevice);
|
|
}
|
|
|
|
//
|
|
// Remove the device
|
|
//
|
|
Bridge = PciDevice->Parent;
|
|
CurrentLink = Bridge->ChildList.ForwardLink;
|
|
while (CurrentLink && CurrentLink != &Bridge->ChildList) {
|
|
Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
|
|
if (Temp == PciDevice) {
|
|
InitializePciDevice (Temp);
|
|
RemoveEntryList (CurrentLink);
|
|
FreePciDevice (Temp);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
CurrentLink = CurrentLink->ForwardLink;
|
|
}
|
|
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
BOOLEAN
|
|
IsRejectiveDevice (
|
|
IN PCI_RESOURCE_NODE *PciResNode
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine whethter a PCI device can be rejected
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: PciResNode - add argument and description to function comment
|
|
{
|
|
PCI_IO_DEVICE *Temp;
|
|
|
|
Temp = PciResNode->PciDev;
|
|
|
|
//
|
|
// Ensure the device is present
|
|
//
|
|
if (!Temp) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// PPB and RB should go ahead
|
|
//
|
|
if (IS_PCI_BRIDGE (&Temp->Pci) || (!Temp->Parent)) {
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Skip device on Bus0
|
|
//
|
|
if ((Temp->Parent) && (Temp->BusNumber == 0)) {
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Skip VGA
|
|
//
|
|
if (IS_PCI_VGA (&Temp->Pci)) {
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
PCI_RESOURCE_NODE *
|
|
GetLargerConsumerDevice (
|
|
IN PCI_RESOURCE_NODE *PciResNode1,
|
|
IN PCI_RESOURCE_NODE *PciResNode2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the larger resource consumer
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: PciResNode1 - add argument and description to function comment
|
|
// TODO: PciResNode2 - add argument and description to function comment
|
|
{
|
|
if (!PciResNode2) {
|
|
return PciResNode1;
|
|
}
|
|
|
|
if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || !(PciResNode2->PciDev->Parent)) \
|
|
&& (PciResNode2->ResourceUsage != PciResUsagePadding) )
|
|
{
|
|
return PciResNode1;
|
|
}
|
|
|
|
if (!PciResNode1) {
|
|
return PciResNode2;
|
|
}
|
|
|
|
if ((PciResNode1->Length) > (PciResNode2->Length)) {
|
|
return PciResNode1;
|
|
}
|
|
|
|
return PciResNode2;
|
|
|
|
}
|
|
|
|
PCI_RESOURCE_NODE *
|
|
GetMaxResourceConsumerDevice (
|
|
IN PCI_RESOURCE_NODE *ResPool
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the max resource consumer in the host resource pool
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: ResPool - add argument and description to function comment
|
|
{
|
|
PCI_RESOURCE_NODE *Temp;
|
|
LIST_ENTRY *CurrentLink;
|
|
PCI_RESOURCE_NODE *PciResNode;
|
|
PCI_RESOURCE_NODE *PPBResNode;
|
|
|
|
PciResNode = NULL;
|
|
|
|
CurrentLink = ResPool->ChildList.ForwardLink;
|
|
while (CurrentLink && CurrentLink != &ResPool->ChildList) {
|
|
|
|
Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
|
|
|
|
if (!IsRejectiveDevice (Temp)) {
|
|
CurrentLink = CurrentLink->ForwardLink;
|
|
continue;
|
|
}
|
|
|
|
if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (!Temp->PciDev->Parent)) \
|
|
&& (Temp->ResourceUsage != PciResUsagePadding))
|
|
{
|
|
PPBResNode = GetMaxResourceConsumerDevice (Temp);
|
|
PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode);
|
|
} else {
|
|
PciResNode = GetLargerConsumerDevice (PciResNode, Temp);
|
|
}
|
|
|
|
CurrentLink = CurrentLink->ForwardLink;
|
|
}
|
|
|
|
return PciResNode;
|
|
}
|
|
|
|
EFI_STATUS
|
|
PciHostBridgeAdjustAllocation (
|
|
IN PCI_RESOURCE_NODE *IoPool,
|
|
IN PCI_RESOURCE_NODE *Mem32Pool,
|
|
IN PCI_RESOURCE_NODE *PMem32Pool,
|
|
IN PCI_RESOURCE_NODE *Mem64Pool,
|
|
IN PCI_RESOURCE_NODE *PMem64Pool,
|
|
IN UINT64 IoResStatus,
|
|
IN UINT64 Mem32ResStatus,
|
|
IN UINT64 PMem32ResStatus,
|
|
IN UINT64 Mem64ResStatus,
|
|
IN UINT64 PMem64ResStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Adjust host bridge allocation so as to reduce resource requirement
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: IoPool - add argument and description to function comment
|
|
// TODO: Mem32Pool - add argument and description to function comment
|
|
// TODO: PMem32Pool - add argument and description to function comment
|
|
// TODO: Mem64Pool - add argument and description to function comment
|
|
// TODO: PMem64Pool - add argument and description to function comment
|
|
// TODO: IoResStatus - add argument and description to function comment
|
|
// TODO: Mem32ResStatus - add argument and description to function comment
|
|
// TODO: PMem32ResStatus - add argument and description to function comment
|
|
// TODO: Mem64ResStatus - add argument and description to function comment
|
|
// TODO: PMem64ResStatus - add argument and description to function comment
|
|
// TODO: EFI_ABORTED - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
// TODO: EFI_ABORTED - add return value to function comment
|
|
{
|
|
BOOLEAN AllocationAjusted;
|
|
PCI_RESOURCE_NODE *PciResNode;
|
|
PCI_RESOURCE_NODE *ResPool[5];
|
|
PCI_IO_DEVICE *RemovedPciDev[5];
|
|
UINT64 ResStatus[5];
|
|
UINTN RemovedPciDevNum;
|
|
UINTN DevIndex;
|
|
UINTN ResType;
|
|
EFI_STATUS Status;
|
|
EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;
|
|
|
|
PciResNode = NULL;
|
|
ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));
|
|
RemovedPciDevNum = 0;
|
|
|
|
ResPool[0] = IoPool;
|
|
ResPool[1] = Mem32Pool;
|
|
ResPool[2] = PMem32Pool;
|
|
ResPool[3] = Mem64Pool;
|
|
ResPool[4] = PMem64Pool;
|
|
|
|
ResStatus[0] = IoResStatus;
|
|
ResStatus[1] = Mem32ResStatus;
|
|
ResStatus[2] = PMem32ResStatus;
|
|
ResStatus[3] = Mem64ResStatus;
|
|
ResStatus[4] = PMem64ResStatus;
|
|
|
|
AllocationAjusted = FALSE;
|
|
|
|
for (ResType = 0; ResType < 5; ResType++) {
|
|
|
|
if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {
|
|
continue;
|
|
}
|
|
|
|
if (ResStatus[ResType] == EFI_RESOURCE_NONEXISTENT) {
|
|
//
|
|
// Hostbridge hasn't this resource type
|
|
//
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
//
|
|
// Hostbridge hasn't enough resource
|
|
//
|
|
PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);
|
|
if (!PciResNode) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Check if the device has been removed before
|
|
//
|
|
for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {
|
|
if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Remove the device if it isn't in the array
|
|
//
|
|
Status = RejectPciDevice (PciResNode->PciDev);
|
|
if (Status == EFI_SUCCESS) {
|
|
|
|
//
|
|
// Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
|
|
//
|
|
//
|
|
// Have no way to get ReqRes, AllocRes & Bar here
|
|
//
|
|
ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
|
|
AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);
|
|
AllocFailExtendedData.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath;
|
|
AllocFailExtendedData.Bar = PciResNode->Bar;
|
|
|
|
REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
|
|
EFI_PROGRESS_CODE,
|
|
EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
|
|
(VOID *) &AllocFailExtendedData,
|
|
sizeof (AllocFailExtendedData)
|
|
);
|
|
|
|
//
|
|
// Add it to the array and indicate at least a device has been rejected
|
|
//
|
|
RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;
|
|
AllocationAjusted = TRUE;
|
|
}
|
|
}
|
|
//
|
|
// End for
|
|
//
|
|
|
|
if (AllocationAjusted) {
|
|
return EFI_SUCCESS;
|
|
} else {
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
|
|
EFI_STATUS
|
|
ConstructAcpiResourceRequestor (
|
|
IN PCI_IO_DEVICE *Bridge,
|
|
IN PCI_RESOURCE_NODE *IoNode,
|
|
IN PCI_RESOURCE_NODE *Mem32Node,
|
|
IN PCI_RESOURCE_NODE *PMem32Node,
|
|
IN PCI_RESOURCE_NODE *Mem64Node,
|
|
IN PCI_RESOURCE_NODE *PMem64Node,
|
|
OUT VOID **pConfig
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: Bridge - add argument and description to function comment
|
|
// TODO: IoNode - add argument and description to function comment
|
|
// TODO: Mem32Node - add argument and description to function comment
|
|
// TODO: PMem32Node - add argument and description to function comment
|
|
// TODO: Mem64Node - add argument and description to function comment
|
|
// TODO: PMem64Node - add argument and description to function comment
|
|
// TODO: pConfig - add argument and description to function comment
|
|
// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
|
|
// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
UINT8 NumConfig;
|
|
UINT8 Aperture;
|
|
UINT8 *Configuration;
|
|
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
|
|
EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
|
|
|
|
NumConfig = 0;
|
|
Aperture = 0;
|
|
|
|
*pConfig = NULL;
|
|
|
|
//
|
|
// if there is io request, add to the io aperture
|
|
//
|
|
if (ResourceRequestExisted (IoNode)) {
|
|
NumConfig++;
|
|
Aperture |= 0x01;
|
|
}
|
|
|
|
//
|
|
// if there is mem32 request, add to the mem32 aperture
|
|
//
|
|
if (ResourceRequestExisted (Mem32Node)) {
|
|
NumConfig++;
|
|
Aperture |= 0x02;
|
|
}
|
|
|
|
//
|
|
// if there is pmem32 request, add to the pmem32 aperture
|
|
//
|
|
if (ResourceRequestExisted (PMem32Node)) {
|
|
NumConfig++;
|
|
Aperture |= 0x04;
|
|
}
|
|
|
|
//
|
|
// if there is mem64 request, add to the mem64 aperture
|
|
//
|
|
if (ResourceRequestExisted (Mem64Node)) {
|
|
NumConfig++;
|
|
Aperture |= 0x08;
|
|
}
|
|
|
|
//
|
|
// if there is pmem64 request, add to the pmem64 aperture
|
|
//
|
|
if (ResourceRequestExisted (PMem64Node)) {
|
|
NumConfig++;
|
|
Aperture |= 0x10;
|
|
}
|
|
|
|
if (NumConfig != 0) {
|
|
|
|
//
|
|
// If there is at least one type of resource request,
|
|
// allocate a acpi resource node
|
|
//
|
|
Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
|
|
if (Configuration == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
ZeroMem (
|
|
Configuration,
|
|
sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
|
|
);
|
|
|
|
Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
|
|
|
|
//
|
|
// Deal with io aperture
|
|
//
|
|
if (Aperture & 0x01) {
|
|
Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
|
|
Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
|
|
//
|
|
// Io
|
|
//
|
|
Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
|
|
//
|
|
// non ISA range
|
|
//
|
|
Ptr->SpecificFlag = 1;
|
|
Ptr->AddrLen = IoNode->Length;
|
|
Ptr->AddrRangeMax = IoNode->Alignment;
|
|
|
|
Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
|
|
}
|
|
//
|
|
// Deal with mem32 aperture
|
|
//
|
|
if (Aperture & 0x02) {
|
|
Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
|
|
Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
|
|
//
|
|
// Mem
|
|
//
|
|
Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
|
|
//
|
|
// Nonprefechable
|
|
//
|
|
Ptr->SpecificFlag = 0;
|
|
//
|
|
// 32 bit
|
|
//
|
|
Ptr->AddrSpaceGranularity = 32;
|
|
Ptr->AddrLen = Mem32Node->Length;
|
|
Ptr->AddrRangeMax = Mem32Node->Alignment;
|
|
|
|
Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
|
|
}
|
|
|
|
//
|
|
// Deal with Pmem32 aperture
|
|
//
|
|
if (Aperture & 0x04) {
|
|
Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
|
|
Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
|
|
//
|
|
// Mem
|
|
//
|
|
Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
|
|
//
|
|
// prefechable
|
|
//
|
|
Ptr->SpecificFlag = 0x6;
|
|
//
|
|
// 32 bit
|
|
//
|
|
Ptr->AddrSpaceGranularity = 32;
|
|
Ptr->AddrLen = PMem32Node->Length;
|
|
Ptr->AddrRangeMax = PMem32Node->Alignment;
|
|
|
|
Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
|
|
}
|
|
//
|
|
// Deal with mem64 aperture
|
|
//
|
|
if (Aperture & 0x08) {
|
|
Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
|
|
Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
|
|
//
|
|
// Mem
|
|
//
|
|
Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
|
|
//
|
|
// nonprefechable
|
|
//
|
|
Ptr->SpecificFlag = 0;
|
|
//
|
|
// 64 bit
|
|
//
|
|
Ptr->AddrSpaceGranularity = 64;
|
|
Ptr->AddrLen = Mem64Node->Length;
|
|
Ptr->AddrRangeMax = Mem64Node->Alignment;
|
|
|
|
Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
|
|
}
|
|
//
|
|
// Deal with Pmem64 aperture
|
|
//
|
|
if (Aperture & 0x10) {
|
|
Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
|
|
Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
|
|
//
|
|
// Mem
|
|
//
|
|
Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
|
|
//
|
|
// prefechable
|
|
//
|
|
Ptr->SpecificFlag = 0x06;
|
|
//
|
|
// 64 bit
|
|
//
|
|
Ptr->AddrSpaceGranularity = 64;
|
|
Ptr->AddrLen = PMem64Node->Length;
|
|
Ptr->AddrRangeMax = PMem64Node->Alignment;
|
|
|
|
Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
|
|
}
|
|
|
|
//
|
|
// put the checksum
|
|
//
|
|
PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr);
|
|
|
|
PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
|
|
PtrEnd->Checksum = 0;
|
|
|
|
} else {
|
|
|
|
//
|
|
// If there is no resource request
|
|
//
|
|
Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
|
|
if (Configuration == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
ZeroMem (Configuration, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
|
|
|
|
Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);
|
|
Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
|
|
|
|
PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR));
|
|
PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
|
|
PtrEnd->Checksum = 0;
|
|
}
|
|
|
|
*pConfig = Configuration;
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetResourceBase (
|
|
IN VOID *pConfig,
|
|
OUT UINT64 *IoBase,
|
|
OUT UINT64 *Mem32Base,
|
|
OUT UINT64 *PMem32Base,
|
|
OUT UINT64 *Mem64Base,
|
|
OUT UINT64 *PMem64Base
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: pConfig - add argument and description to function comment
|
|
// TODO: IoBase - add argument and description to function comment
|
|
// TODO: Mem32Base - add argument and description to function comment
|
|
// TODO: PMem32Base - add argument and description to function comment
|
|
// TODO: Mem64Base - add argument and description to function comment
|
|
// TODO: PMem64Base - add argument and description to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
UINT8 *Temp;
|
|
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
|
|
UINT64 ResStatus;
|
|
|
|
*IoBase = 0xFFFFFFFFFFFFFFFFULL;
|
|
*Mem32Base = 0xFFFFFFFFFFFFFFFFULL;
|
|
*PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
|
|
*Mem64Base = 0xFFFFFFFFFFFFFFFFULL;
|
|
*PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
|
|
|
|
Temp = (UINT8 *) pConfig;
|
|
|
|
while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
|
|
|
|
Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
|
|
ResStatus = Ptr->AddrTranslationOffset;
|
|
|
|
if (ResStatus == EFI_RESOURCE_SATISFIED) {
|
|
|
|
switch (Ptr->ResType) {
|
|
|
|
//
|
|
// Memory type aperture
|
|
//
|
|
case 0:
|
|
|
|
//
|
|
// Check to see the granularity
|
|
//
|
|
if (Ptr->AddrSpaceGranularity == 32) {
|
|
if (Ptr->SpecificFlag & 0x06) {
|
|
*PMem32Base = Ptr->AddrRangeMin;
|
|
} else {
|
|
*Mem32Base = Ptr->AddrRangeMin;
|
|
}
|
|
}
|
|
|
|
if (Ptr->AddrSpaceGranularity == 64) {
|
|
if (Ptr->SpecificFlag & 0x06) {
|
|
*PMem64Base = Ptr->AddrRangeMin;
|
|
} else {
|
|
*Mem64Base = Ptr->AddrRangeMin;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
|
|
//
|
|
// Io type aperture
|
|
//
|
|
*IoBase = Ptr->AddrRangeMin;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
|
|
}
|
|
//
|
|
// End switch
|
|
//
|
|
}
|
|
//
|
|
// End for
|
|
//
|
|
Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
PciBridgeEnumerator (
|
|
IN PCI_IO_DEVICE *BridgeDev
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: BridgeDev - add argument and description to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
UINT8 SubBusNumber;
|
|
UINT8 StartBusNumber;
|
|
EFI_PCI_IO_PROTOCOL *PciIo;
|
|
EFI_STATUS Status;
|
|
|
|
SubBusNumber = 0;
|
|
StartBusNumber = 0;
|
|
PciIo = &(BridgeDev->PciIo);
|
|
Status = PciIoRead (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = PciAssignBusNumber (
|
|
BridgeDev,
|
|
StartBusNumber,
|
|
&SubBusNumber
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = PciBridgeResourceAllocator (BridgeDev);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = DetermineDeviceAttribute (BridgeDev);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
EFI_STATUS
|
|
PciBridgeResourceAllocator (
|
|
IN PCI_IO_DEVICE *Bridge
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: Bridge - add argument and description to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
PCI_RESOURCE_NODE *IoBridge;
|
|
PCI_RESOURCE_NODE *Mem32Bridge;
|
|
PCI_RESOURCE_NODE *PMem32Bridge;
|
|
PCI_RESOURCE_NODE *Mem64Bridge;
|
|
PCI_RESOURCE_NODE *PMem64Bridge;
|
|
UINT64 IoBase;
|
|
UINT64 Mem32Base;
|
|
UINT64 PMem32Base;
|
|
UINT64 Mem64Base;
|
|
UINT64 PMem64Base;
|
|
EFI_STATUS Status;
|
|
|
|
IoBridge = CreateResourceNode (
|
|
Bridge,
|
|
0,
|
|
0xFFF,
|
|
0,
|
|
PciBarTypeIo16,
|
|
PciResUsageTypical
|
|
);
|
|
|
|
Mem32Bridge = CreateResourceNode (
|
|
Bridge,
|
|
0,
|
|
0xFFFFF,
|
|
0,
|
|
PciBarTypeMem32,
|
|
PciResUsageTypical
|
|
);
|
|
|
|
PMem32Bridge = CreateResourceNode (
|
|
Bridge,
|
|
0,
|
|
0xFFFFF,
|
|
0,
|
|
PciBarTypePMem32,
|
|
PciResUsageTypical
|
|
);
|
|
|
|
Mem64Bridge = CreateResourceNode (
|
|
Bridge,
|
|
0,
|
|
0xFFFFF,
|
|
0,
|
|
PciBarTypeMem64,
|
|
PciResUsageTypical
|
|
);
|
|
|
|
PMem64Bridge = CreateResourceNode (
|
|
Bridge,
|
|
0,
|
|
0xFFFFF,
|
|
0,
|
|
PciBarTypePMem64,
|
|
PciResUsageTypical
|
|
);
|
|
|
|
//
|
|
// Create resourcemap by going through all the devices subject to this root bridge
|
|
//
|
|
Status = CreateResourceMap (
|
|
Bridge,
|
|
IoBridge,
|
|
Mem32Bridge,
|
|
PMem32Bridge,
|
|
Mem64Bridge,
|
|
PMem64Bridge
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
Status = GetResourceBaseFromBridge (
|
|
Bridge,
|
|
&IoBase,
|
|
&Mem32Base,
|
|
&PMem32Base,
|
|
&Mem64Base,
|
|
&PMem64Base
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Program IO resources
|
|
//
|
|
ProgramResource (
|
|
IoBase,
|
|
IoBridge
|
|
);
|
|
|
|
//
|
|
// Program Mem32 resources
|
|
//
|
|
ProgramResource (
|
|
Mem32Base,
|
|
Mem32Bridge
|
|
);
|
|
|
|
//
|
|
// Program PMem32 resources
|
|
//
|
|
ProgramResource (
|
|
PMem32Base,
|
|
PMem32Bridge
|
|
);
|
|
|
|
//
|
|
// Program Mem64 resources
|
|
//
|
|
ProgramResource (
|
|
Mem64Base,
|
|
Mem64Bridge
|
|
);
|
|
|
|
//
|
|
// Program PMem64 resources
|
|
//
|
|
ProgramResource (
|
|
PMem64Base,
|
|
PMem64Bridge
|
|
);
|
|
|
|
DestroyResourceTree (IoBridge);
|
|
DestroyResourceTree (Mem32Bridge);
|
|
DestroyResourceTree (PMem32Bridge);
|
|
DestroyResourceTree (PMem64Bridge);
|
|
DestroyResourceTree (Mem64Bridge);
|
|
|
|
gBS->FreePool (IoBridge);
|
|
gBS->FreePool (Mem32Bridge);
|
|
gBS->FreePool (PMem32Bridge);
|
|
gBS->FreePool (PMem64Bridge);
|
|
gBS->FreePool (Mem64Bridge);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
GetResourceBaseFromBridge (
|
|
IN PCI_IO_DEVICE *Bridge,
|
|
OUT UINT64 *IoBase,
|
|
OUT UINT64 *Mem32Base,
|
|
OUT UINT64 *PMem32Base,
|
|
OUT UINT64 *Mem64Base,
|
|
OUT UINT64 *PMem64Base
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: Bridge - add argument and description to function comment
|
|
// TODO: IoBase - add argument and description to function comment
|
|
// TODO: Mem32Base - add argument and description to function comment
|
|
// TODO: PMem32Base - add argument and description to function comment
|
|
// TODO: Mem64Base - add argument and description to function comment
|
|
// TODO: PMem64Base - add argument and description to function comment
|
|
// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
if (!Bridge->Allocated) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
*IoBase = gAllOne;
|
|
*Mem32Base = gAllOne;
|
|
*PMem32Base = gAllOne;
|
|
*Mem64Base = gAllOne;
|
|
*PMem64Base = gAllOne;
|
|
|
|
if (IS_PCI_BRIDGE (&Bridge->Pci)) {
|
|
|
|
if (Bridge->PciBar[PPB_IO_RANGE].Length) {
|
|
*IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
|
|
}
|
|
|
|
if (Bridge->PciBar[PPB_MEM32_RANGE].Length) {
|
|
*Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
|
|
}
|
|
|
|
if (Bridge->PciBar[PPB_PMEM32_RANGE].Length) {
|
|
*PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
|
|
}
|
|
|
|
if (Bridge->PciBar[PPB_PMEM64_RANGE].Length) {
|
|
*PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
|
|
} else {
|
|
*PMem64Base = gAllOne;
|
|
}
|
|
|
|
}
|
|
|
|
if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
|
|
if (Bridge->PciBar[P2C_IO_1].Length) {
|
|
*IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
|
|
} else {
|
|
if (Bridge->PciBar[P2C_IO_2].Length) {
|
|
*IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
|
|
}
|
|
}
|
|
|
|
if (Bridge->PciBar[P2C_MEM_1].Length) {
|
|
if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
|
|
*PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
|
|
}
|
|
|
|
if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
|
|
*Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
|
|
}
|
|
}
|
|
|
|
if (Bridge->PciBar[P2C_MEM_2].Length) {
|
|
if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
|
|
*PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
|
|
}
|
|
|
|
if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
|
|
*Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
|
|
}
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
NotifyPhase (
|
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
|
|
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: PciResAlloc - add argument and description to function comment
|
|
// TODO: Phase - add argument and description to function comment
|
|
// TODO: EFI_NOT_FOUND - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
EFI_HANDLE HostBridgeHandle;
|
|
EFI_HANDLE RootBridgeHandle;
|
|
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
|
|
EFI_STATUS Status;
|
|
|
|
HostBridgeHandle = NULL;
|
|
RootBridgeHandle = NULL;
|
|
if (gPciPlatformProtocol != NULL) {
|
|
//
|
|
// Get Host Bridge Handle.
|
|
//
|
|
PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
|
|
|
|
//
|
|
// Get the rootbridge Io protocol to find the host bridge handle
|
|
//
|
|
Status = gBS->HandleProtocol (
|
|
RootBridgeHandle,
|
|
&gEfiPciRootBridgeIoProtocolGuid,
|
|
(VOID **) &PciRootBridgeIo
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
HostBridgeHandle = PciRootBridgeIo->ParentHandle;
|
|
|
|
//
|
|
// Call PlatformPci::PhaseNotify() if the protocol is present.
|
|
//
|
|
gPciPlatformProtocol->PhaseNotify (
|
|
gPciPlatformProtocol,
|
|
HostBridgeHandle,
|
|
Phase,
|
|
ChipsetEntry
|
|
);
|
|
}
|
|
|
|
Status = PciResAlloc->NotifyPhase (
|
|
PciResAlloc,
|
|
Phase
|
|
);
|
|
|
|
if (gPciPlatformProtocol != NULL) {
|
|
//
|
|
// Call PlatformPci::PhaseNotify() if the protocol is present.
|
|
//
|
|
gPciPlatformProtocol->PhaseNotify (
|
|
gPciPlatformProtocol,
|
|
HostBridgeHandle,
|
|
Phase,
|
|
ChipsetExit
|
|
);
|
|
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
PreprocessController (
|
|
IN PCI_IO_DEVICE *Bridge,
|
|
IN UINT8 Bus,
|
|
IN UINT8 Device,
|
|
IN UINT8 Func,
|
|
IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: Bridge - add argument and description to function comment
|
|
// TODO: Bus - add argument and description to function comment
|
|
// TODO: Device - add argument and description to function comment
|
|
// TODO: Func - add argument and description to function comment
|
|
// TODO: Phase - add argument and description to function comment
|
|
// TODO: EFI_UNSUPPORTED - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress;
|
|
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;
|
|
EFI_HANDLE RootBridgeHandle;
|
|
EFI_HANDLE HostBridgeHandle;
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Get the host bridge handle
|
|
//
|
|
HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
|
|
|
|
//
|
|
// Get the pci host bridge resource allocation protocol
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
HostBridgeHandle,
|
|
&gEfiPciHostBridgeResourceAllocationProtocolGuid,
|
|
(VOID **) &PciResAlloc,
|
|
NULL,
|
|
NULL,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
//
|
|
// Get Root Brige Handle
|
|
//
|
|
while (Bridge->Parent) {
|
|
Bridge = Bridge->Parent;
|
|
}
|
|
|
|
RootBridgeHandle = Bridge->Handle;
|
|
|
|
RootBridgePciAddress.Register = 0;
|
|
RootBridgePciAddress.Function = Func;
|
|
RootBridgePciAddress.Device = Device;
|
|
RootBridgePciAddress.Bus = Bus;
|
|
RootBridgePciAddress.ExtendedRegister = 0;
|
|
|
|
if (gPciPlatformProtocol != NULL) {
|
|
//
|
|
// Call PlatformPci::PrepController() if the protocol is present.
|
|
//
|
|
gPciPlatformProtocol->PlatformPrepController (
|
|
gPciPlatformProtocol,
|
|
HostBridgeHandle,
|
|
RootBridgeHandle,
|
|
RootBridgePciAddress,
|
|
Phase,
|
|
ChipsetEntry
|
|
);
|
|
}
|
|
|
|
Status = PciResAlloc->PreprocessController (
|
|
PciResAlloc,
|
|
RootBridgeHandle,
|
|
RootBridgePciAddress,
|
|
Phase
|
|
);
|
|
|
|
if (gPciPlatformProtocol != NULL) {
|
|
//
|
|
// Call PlatformPci::PrepController() if the protocol is present.
|
|
//
|
|
gPciPlatformProtocol->PlatformPrepController (
|
|
gPciPlatformProtocol,
|
|
HostBridgeHandle,
|
|
RootBridgeHandle,
|
|
RootBridgePciAddress,
|
|
Phase,
|
|
ChipsetExit
|
|
);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PciHotPlugRequestNotify (
|
|
IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
|
|
IN EFI_PCI_HOTPLUG_OPERATION Operation,
|
|
IN EFI_HANDLE Controller,
|
|
IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,
|
|
IN OUT UINT8 *NumberOfChildren,
|
|
IN OUT EFI_HANDLE * ChildHandleBuffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Hot plug request notify.
|
|
|
|
Arguments:
|
|
|
|
This - A pointer to the hot plug request protocol.
|
|
Operation - The operation.
|
|
Controller - A pointer to the controller.
|
|
RemainningDevicePath - A pointer to the device path.
|
|
NumberOfChildren - A the number of child handle in the ChildHandleBuffer.
|
|
ChildHandleBuffer - A pointer to the array contain the child handle.
|
|
|
|
Returns:
|
|
|
|
Status code.
|
|
|
|
--*/
|
|
// TODO: RemainingDevicePath - add argument and description to function comment
|
|
// TODO: EFI_NOT_FOUND - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
PCI_IO_DEVICE *Bridge;
|
|
PCI_IO_DEVICE *Temp;
|
|
EFI_PCI_IO_PROTOCOL *PciIo;
|
|
UINTN Index;
|
|
EFI_HANDLE RootBridgeHandle;
|
|
EFI_STATUS Status;
|
|
|
|
Status = gBS->OpenProtocol (
|
|
Controller,
|
|
&gEfiPciIoProtocolGuid,
|
|
(VOID **) &PciIo,
|
|
gPciBusDriverBinding.DriverBindingHandle,
|
|
Controller,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
|
|
|
|
//
|
|
// Get root bridge handle
|
|
//
|
|
Temp = Bridge;
|
|
while (Temp->Parent) {
|
|
Temp = Temp->Parent;
|
|
}
|
|
|
|
RootBridgeHandle = Temp->Handle;
|
|
|
|
if (Operation == EfiPciHotPlugRequestAdd) {
|
|
|
|
if (NumberOfChildren != NULL) {
|
|
*NumberOfChildren = 0;
|
|
}
|
|
|
|
if (IsListEmpty (&Bridge->ChildList)) {
|
|
|
|
Status = PciBridgeEnumerator (Bridge);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
Status = StartPciDevicesOnBridge (
|
|
RootBridgeHandle,
|
|
Bridge,
|
|
RemainingDevicePath,
|
|
NumberOfChildren,
|
|
ChildHandleBuffer
|
|
);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (Operation == EfiPciHotplugRequestRemove) {
|
|
|
|
if (*NumberOfChildren == 0) {
|
|
//
|
|
// Remove all devices on the bridge
|
|
//
|
|
Status = RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
|
|
return Status;
|
|
|
|
}
|
|
|
|
for (Index = 0; Index < *NumberOfChildren; Index++) {
|
|
//
|
|
// De register all the pci device
|
|
//
|
|
Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return Status;
|
|
}
|
|
|
|
}
|
|
//
|
|
// End for
|
|
//
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
BOOLEAN
|
|
SearchHostBridgeHandle (
|
|
IN EFI_HANDLE RootBridgeHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: RootBridgeHandle - add argument and description to function comment
|
|
{
|
|
EFI_HANDLE HostBridgeHandle;
|
|
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
|
|
UINTN Index;
|
|
EFI_STATUS Status;
|
|
|
|
//
|
|
// Get the rootbridge Io protocol to find the host bridge handle
|
|
//
|
|
Status = gBS->OpenProtocol (
|
|
RootBridgeHandle,
|
|
&gEfiPciRootBridgeIoProtocolGuid,
|
|
(VOID **) &PciRootBridgeIo,
|
|
gPciBusDriverBinding.DriverBindingHandle,
|
|
RootBridgeHandle,
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
return FALSE;
|
|
}
|
|
|
|
HostBridgeHandle = PciRootBridgeIo->ParentHandle;
|
|
for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
|
|
if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
EFI_STATUS
|
|
AddHostBridgeEnumerator (
|
|
IN EFI_HANDLE HostBridgeHandle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
None
|
|
|
|
--*/
|
|
// TODO: HostBridgeHandle - add argument and description to function comment
|
|
// TODO: EFI_ABORTED - add return value to function comment
|
|
// TODO: EFI_ABORTED - add return value to function comment
|
|
// TODO: EFI_SUCCESS - add return value to function comment
|
|
{
|
|
UINTN Index;
|
|
|
|
if (!HostBridgeHandle) {
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
|
|
if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
|
|
if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
|
|
gPciHostBrigeHandles[Index] = HostBridgeHandle;
|
|
gPciHostBridgeNumber++;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|