mirror of https://github.com/acidanthera/audk.git
1202 lines
37 KiB
C
1202 lines
37 KiB
C
|
/** @file
|
||
|
Pci Host Bridge driver:
|
||
|
Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation
|
||
|
|
||
|
Copyright (c) 2008 - 2009, Intel Corporation<BR> 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 "PciHostBridge.h"
|
||
|
|
||
|
//
|
||
|
// Support 64 K IO space
|
||
|
//
|
||
|
#define RES_IO_BASE 0x1000
|
||
|
#define RES_IO_LIMIT 0xFFFF
|
||
|
//
|
||
|
// Support 4G address space
|
||
|
//
|
||
|
#define RES_MEM_BASE_1 0xF8000000
|
||
|
#define RES_MEM_LIMIT_1 (0xFEC00000 - 1)
|
||
|
|
||
|
//
|
||
|
// Hard code: Root Bridge Number within the host bridge
|
||
|
// Root Bridge's attribute
|
||
|
// Root Bridge's device path
|
||
|
// Root Bridge's resource appeture
|
||
|
//
|
||
|
UINTN RootBridgeNumber[1] = { 1 };
|
||
|
|
||
|
UINT64 RootBridgeAttribute[1][1] = { EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM };
|
||
|
|
||
|
EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[1][1] = {
|
||
|
{
|
||
|
ACPI_DEVICE_PATH,
|
||
|
ACPI_DP,
|
||
|
(UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
|
||
|
(UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8),
|
||
|
EISA_PNP_ID(0x0A03),
|
||
|
0,
|
||
|
END_DEVICE_PATH_TYPE,
|
||
|
END_ENTIRE_DEVICE_PATH_SUBTYPE,
|
||
|
END_DEVICE_PATH_LENGTH,
|
||
|
0
|
||
|
}
|
||
|
};
|
||
|
|
||
|
PCI_ROOT_BRIDGE_RESOURCE_APPETURE mResAppeture[1][1] = {
|
||
|
{0, 0, 0, 0xffffffff, 0, 1 << 16}
|
||
|
};
|
||
|
|
||
|
EFI_HANDLE mDriverImageHandle;
|
||
|
|
||
|
PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
|
||
|
PCI_HOST_BRIDGE_SIGNATURE, // Signature
|
||
|
NULL, // HostBridgeHandle
|
||
|
0, // RootBridgeNumber
|
||
|
{NULL, NULL}, // Head
|
||
|
FALSE, // ResourceSubiteed
|
||
|
TRUE, // CanRestarted
|
||
|
{
|
||
|
NotifyPhase,
|
||
|
GetNextRootBridge,
|
||
|
GetAttributes,
|
||
|
StartBusEnumeration,
|
||
|
SetBusNumbers,
|
||
|
SubmitResources,
|
||
|
GetProposedResources,
|
||
|
PreprocessController
|
||
|
}
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Implementation
|
||
|
//
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
InitializePciHostBridge (
|
||
|
IN EFI_HANDLE ImageHandle,
|
||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Entry point of this driver
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ImageHandle -
|
||
|
|
||
|
SystemTable -
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
UINTN Loop1;
|
||
|
UINTN Loop2;
|
||
|
PCI_HOST_BRIDGE_INSTANCE *HostBridge;
|
||
|
PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
|
||
|
IN EFI_PHYSICAL_ADDRESS BaseAddress;
|
||
|
IN UINT64 Length;
|
||
|
|
||
|
mDriverImageHandle = ImageHandle;
|
||
|
|
||
|
//
|
||
|
// Create Host Bridge Device Handle
|
||
|
//
|
||
|
for (Loop1 = 0; Loop1 < HOST_BRIDGE_NUMBER; Loop1++) {
|
||
|
HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE), &mPciHostBridgeInstanceTemplate);
|
||
|
if (HostBridge == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
HostBridge->RootBridgeNumber = RootBridgeNumber[Loop1];
|
||
|
InitializeListHead (&HostBridge->Head);
|
||
|
|
||
|
Status = gBS->InstallMultipleProtocolInterfaces (
|
||
|
&HostBridge->HostBridgeHandle,
|
||
|
&gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
|
||
|
NULL
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
FreePool (HostBridge);
|
||
|
return EFI_DEVICE_ERROR;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Create Root Bridge Device Handle in this Host Bridge
|
||
|
//
|
||
|
|
||
|
for (Loop2 = 0; Loop2 < HostBridge->RootBridgeNumber; Loop2++) {
|
||
|
PrivateData = AllocateZeroPool (sizeof(PCI_ROOT_BRIDGE_INSTANCE));
|
||
|
if (PrivateData == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
|
||
|
PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[Loop1][Loop2];
|
||
|
|
||
|
RootBridgeConstructor (
|
||
|
&PrivateData->Io,
|
||
|
HostBridge->HostBridgeHandle,
|
||
|
RootBridgeAttribute[Loop1][Loop2],
|
||
|
&mResAppeture[Loop1][Loop2]
|
||
|
);
|
||
|
|
||
|
Status = gBS->InstallMultipleProtocolInterfaces(
|
||
|
&PrivateData->Handle,
|
||
|
&gEfiDevicePathProtocolGuid, PrivateData->DevicePath,
|
||
|
&gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,
|
||
|
NULL
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
FreePool(PrivateData);
|
||
|
return EFI_DEVICE_ERROR;
|
||
|
}
|
||
|
|
||
|
InsertTailList (&HostBridge->Head, &PrivateData->Link);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Status = gDS->AddIoSpace (
|
||
|
EfiGcdIoTypeIo,
|
||
|
RES_IO_BASE,
|
||
|
RES_IO_LIMIT - RES_IO_BASE + 1
|
||
|
);
|
||
|
|
||
|
// PCI memory space from 3.75Gbytes->(4GBytes - BIOSFWH local APIC etc)
|
||
|
Status = gDS->AddMemorySpace (
|
||
|
EfiGcdMemoryTypeMemoryMappedIo,
|
||
|
RES_MEM_BASE_1,
|
||
|
(RES_MEM_LIMIT_1 - RES_MEM_BASE_1 + 1),
|
||
|
0
|
||
|
);
|
||
|
|
||
|
BaseAddress = 0x80000000;
|
||
|
Length = RES_MEM_BASE_1 - BaseAddress;
|
||
|
Status = gDS->AddMemorySpace (
|
||
|
EfiGcdMemoryTypeMemoryMappedIo,
|
||
|
BaseAddress,
|
||
|
Length,
|
||
|
0
|
||
|
);
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
NotifyPhase(
|
||
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Enter a certain phase of the PCI enumeration process
|
||
|
|
||
|
Arguments:
|
||
|
This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance
|
||
|
Phase -- The phase during enumeration
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
|
||
|
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||
|
PCI_RESOURCE_TYPE Index;
|
||
|
LIST_ENTRY *List;
|
||
|
EFI_PHYSICAL_ADDRESS BaseAddress;
|
||
|
UINT64 AddrLen;
|
||
|
UINTN BitsOfAlignment;
|
||
|
EFI_STATUS Status;
|
||
|
EFI_STATUS ReturnStatus;
|
||
|
|
||
|
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
|
||
|
|
||
|
switch (Phase) {
|
||
|
|
||
|
case EfiPciHostBridgeBeginEnumeration:
|
||
|
if (HostBridgeInstance->CanRestarted) {
|
||
|
//
|
||
|
// Reset the Each Root Bridge
|
||
|
//
|
||
|
List = HostBridgeInstance->Head.ForwardLink;
|
||
|
|
||
|
while (List != &HostBridgeInstance->Head) {
|
||
|
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
|
||
|
for (Index = TypeIo; Index < TypeMax; Index++) {
|
||
|
RootBridgeInstance->ResAllocNode[Index].Type = Index;
|
||
|
RootBridgeInstance->ResAllocNode[Index].Base = 0;
|
||
|
RootBridgeInstance->ResAllocNode[Index].Length = 0;
|
||
|
RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
|
||
|
}
|
||
|
|
||
|
List = List->ForwardLink;
|
||
|
}
|
||
|
|
||
|
HostBridgeInstance->ResourceSubmited = FALSE;
|
||
|
HostBridgeInstance->CanRestarted = TRUE;
|
||
|
} else {
|
||
|
//
|
||
|
// Can not restart
|
||
|
//
|
||
|
return EFI_NOT_READY;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case EfiPciHostBridgeBeginBusAllocation:
|
||
|
//
|
||
|
// No specific action is required here, can perform any chipset specific programing
|
||
|
//
|
||
|
HostBridgeInstance->CanRestarted = FALSE;
|
||
|
return EFI_SUCCESS;
|
||
|
break;
|
||
|
|
||
|
case EfiPciHostBridgeEndBusAllocation:
|
||
|
//
|
||
|
// No specific action is required here, can perform any chipset specific programing
|
||
|
//
|
||
|
//HostBridgeInstance->CanRestarted = FALSE;
|
||
|
return EFI_SUCCESS;
|
||
|
break;
|
||
|
|
||
|
case EfiPciHostBridgeBeginResourceAllocation:
|
||
|
//
|
||
|
// No specific action is required here, can perform any chipset specific programing
|
||
|
//
|
||
|
//HostBridgeInstance->CanRestarted = FALSE;
|
||
|
return EFI_SUCCESS;
|
||
|
break;
|
||
|
|
||
|
case EfiPciHostBridgeAllocateResources:
|
||
|
ReturnStatus = EFI_SUCCESS;
|
||
|
if (HostBridgeInstance->ResourceSubmited) {
|
||
|
//
|
||
|
// Take care of the resource dependencies between the root bridges
|
||
|
//
|
||
|
List = HostBridgeInstance->Head.ForwardLink;
|
||
|
|
||
|
while (List != &HostBridgeInstance->Head) {
|
||
|
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
|
||
|
for (Index = TypeIo; Index < TypeBus; Index++) {
|
||
|
if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
|
||
|
|
||
|
AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
|
||
|
|
||
|
//
|
||
|
// Get the number of '1' in Alignment.
|
||
|
//
|
||
|
BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAllocNode[Index].Alignment) + 1;
|
||
|
|
||
|
switch (Index) {
|
||
|
|
||
|
case TypeIo:
|
||
|
//
|
||
|
// It is impossible for this chipset to align 0xFFFF for IO16
|
||
|
// So clear it
|
||
|
//
|
||
|
if (BitsOfAlignment >= 16) {
|
||
|
BitsOfAlignment = 0;
|
||
|
}
|
||
|
|
||
|
Status = gDS->AllocateIoSpace (
|
||
|
EfiGcdAllocateAnySearchBottomUp,
|
||
|
EfiGcdIoTypeIo,
|
||
|
BitsOfAlignment,
|
||
|
AddrLen,
|
||
|
&BaseAddress,
|
||
|
mDriverImageHandle,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (!EFI_ERROR (Status)) {
|
||
|
RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress;
|
||
|
RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
|
||
|
} else {
|
||
|
ReturnStatus = Status;
|
||
|
if (Status != EFI_OUT_OF_RESOURCES) {
|
||
|
RootBridgeInstance->ResAllocNode[Index].Length = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
|
||
|
case TypeMem32:
|
||
|
//
|
||
|
// It is impossible for this chipset to align 0xFFFFFFFF for Mem32
|
||
|
// So clear it
|
||
|
//
|
||
|
|
||
|
if (BitsOfAlignment >= 32) {
|
||
|
BitsOfAlignment = 0;
|
||
|
}
|
||
|
|
||
|
Status = gDS->AllocateMemorySpace (
|
||
|
EfiGcdAllocateAnySearchBottomUp,
|
||
|
EfiGcdMemoryTypeMemoryMappedIo,
|
||
|
BitsOfAlignment,
|
||
|
AddrLen,
|
||
|
&BaseAddress,
|
||
|
mDriverImageHandle,
|
||
|
NULL
|
||
|
);
|
||
|
|
||
|
if (!EFI_ERROR (Status)) {
|
||
|
// We were able to allocate the PCI memory
|
||
|
RootBridgeInstance->ResAllocNode[Index].Base = (UINTN)BaseAddress;
|
||
|
RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated;
|
||
|
|
||
|
} else {
|
||
|
// Not able to allocate enough PCI memory
|
||
|
ReturnStatus = Status;
|
||
|
|
||
|
if (Status != EFI_OUT_OF_RESOURCES) {
|
||
|
RootBridgeInstance->ResAllocNode[Index].Length = 0;
|
||
|
}
|
||
|
ASSERT (FALSE);
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TypePMem32:
|
||
|
case TypeMem64:
|
||
|
case TypePMem64:
|
||
|
ReturnStatus = EFI_ABORTED;
|
||
|
break;
|
||
|
default:
|
||
|
ASSERT (FALSE);
|
||
|
break;
|
||
|
}; //end switch
|
||
|
}
|
||
|
}
|
||
|
|
||
|
List = List->ForwardLink;
|
||
|
}
|
||
|
|
||
|
return ReturnStatus;
|
||
|
|
||
|
} else {
|
||
|
return EFI_NOT_READY;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case EfiPciHostBridgeSetResources:
|
||
|
break;
|
||
|
|
||
|
case EfiPciHostBridgeFreeResources:
|
||
|
ReturnStatus = EFI_SUCCESS;
|
||
|
List = HostBridgeInstance->Head.ForwardLink;
|
||
|
while (List != &HostBridgeInstance->Head) {
|
||
|
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
|
||
|
for (Index = TypeIo; Index < TypeBus; Index++) {
|
||
|
if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
|
||
|
AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
|
||
|
BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
|
||
|
switch (Index) {
|
||
|
|
||
|
case TypeIo:
|
||
|
Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
ReturnStatus = Status;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TypeMem32:
|
||
|
Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
ReturnStatus = Status;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TypePMem32:
|
||
|
break;
|
||
|
|
||
|
case TypeMem64:
|
||
|
break;
|
||
|
|
||
|
case TypePMem64:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
ASSERT (FALSE);
|
||
|
break;
|
||
|
|
||
|
}; //end switch
|
||
|
RootBridgeInstance->ResAllocNode[Index].Type = Index;
|
||
|
RootBridgeInstance->ResAllocNode[Index].Base = 0;
|
||
|
RootBridgeInstance->ResAllocNode[Index].Length = 0;
|
||
|
RootBridgeInstance->ResAllocNode[Index].Status = ResNone;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
List = List->ForwardLink;
|
||
|
}
|
||
|
|
||
|
HostBridgeInstance->ResourceSubmited = FALSE;
|
||
|
HostBridgeInstance->CanRestarted = TRUE;
|
||
|
return ReturnStatus;
|
||
|
break;
|
||
|
|
||
|
case EfiPciHostBridgeEndResourceAllocation:
|
||
|
HostBridgeInstance->CanRestarted = FALSE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}; // end switch
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
GetNextRootBridge(
|
||
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||
|
IN OUT EFI_HANDLE *RootBridgeHandle
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Return the device handle of the next PCI root bridge that is associated with
|
||
|
this Host Bridge
|
||
|
|
||
|
Arguments:
|
||
|
This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
|
||
|
RootBridgeHandle -- Returns the device handle of the next PCI Root Bridge.
|
||
|
On input, it holds the RootBridgeHandle returned by the most
|
||
|
recent call to GetNextRootBridge().The handle for the first
|
||
|
PCI Root Bridge is returned if RootBridgeHandle is NULL on input
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
BOOLEAN NoRootBridge;
|
||
|
LIST_ENTRY *List;
|
||
|
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
|
||
|
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||
|
|
||
|
NoRootBridge = TRUE;
|
||
|
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
|
||
|
List = HostBridgeInstance->Head.ForwardLink;
|
||
|
|
||
|
|
||
|
while (List != &HostBridgeInstance->Head) {
|
||
|
NoRootBridge = FALSE;
|
||
|
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
|
||
|
if (*RootBridgeHandle == NULL) {
|
||
|
//
|
||
|
// Return the first Root Bridge Handle of the Host Bridge
|
||
|
//
|
||
|
*RootBridgeHandle = RootBridgeInstance->Handle;
|
||
|
return EFI_SUCCESS;
|
||
|
} else {
|
||
|
if (*RootBridgeHandle == RootBridgeInstance->Handle) {
|
||
|
//
|
||
|
// Get next if have
|
||
|
//
|
||
|
List = List->ForwardLink;
|
||
|
if (List!=&HostBridgeInstance->Head) {
|
||
|
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
|
||
|
*RootBridgeHandle = RootBridgeInstance->Handle;
|
||
|
return EFI_SUCCESS;
|
||
|
} else {
|
||
|
return EFI_NOT_FOUND;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
List = List->ForwardLink;
|
||
|
} //end while
|
||
|
|
||
|
if (NoRootBridge) {
|
||
|
return EFI_NOT_FOUND;
|
||
|
} else {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
GetAttributes(
|
||
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||
|
IN EFI_HANDLE RootBridgeHandle,
|
||
|
OUT UINT64 *Attributes
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Returns the attributes of a PCI Root Bridge.
|
||
|
|
||
|
Arguments:
|
||
|
This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
|
||
|
RootBridgeHandle -- The device handle of the PCI Root Bridge
|
||
|
that the caller is interested in
|
||
|
Attribute -- The pointer to attributes of the PCI Root Bridge
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LIST_ENTRY *List;
|
||
|
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
|
||
|
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||
|
|
||
|
if (Attributes == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
|
||
|
List = HostBridgeInstance->Head.ForwardLink;
|
||
|
|
||
|
while (List != &HostBridgeInstance->Head) {
|
||
|
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
|
||
|
if (RootBridgeHandle == RootBridgeInstance->Handle) {
|
||
|
*Attributes = RootBridgeInstance->RootBridgeAttrib;
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
List = List->ForwardLink;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// RootBridgeHandle is not an EFI_HANDLE
|
||
|
// that was returned on a previous call to GetNextRootBridge()
|
||
|
//
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
StartBusEnumeration(
|
||
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||
|
IN EFI_HANDLE RootBridgeHandle,
|
||
|
OUT VOID **Configuration
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
This is the request from the PCI enumerator to set up
|
||
|
the specified PCI Root Bridge for bus enumeration process.
|
||
|
|
||
|
Arguments:
|
||
|
This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
|
||
|
RootBridgeHandle -- The PCI Root Bridge to be set up
|
||
|
Configuration -- Pointer to the pointer to the PCI bus resource descriptor
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LIST_ENTRY *List;
|
||
|
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
|
||
|
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||
|
VOID *Buffer;
|
||
|
UINT8 *Temp;
|
||
|
UINT64 BusStart;
|
||
|
UINT64 BusEnd;
|
||
|
|
||
|
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
|
||
|
List = HostBridgeInstance->Head.ForwardLink;
|
||
|
|
||
|
while (List != &HostBridgeInstance->Head) {
|
||
|
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
|
||
|
if (RootBridgeHandle == RootBridgeInstance->Handle) {
|
||
|
//
|
||
|
// Set up the Root Bridge for Bus Enumeration
|
||
|
//
|
||
|
BusStart = RootBridgeInstance->BusBase;
|
||
|
BusEnd = RootBridgeInstance->BusLimit;
|
||
|
//
|
||
|
// Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
|
||
|
//
|
||
|
|
||
|
Buffer = AllocatePool (sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
|
||
|
if (Buffer == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
Temp = (UINT8 *)Buffer;
|
||
|
|
||
|
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;
|
||
|
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len = 0x2B;
|
||
|
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;
|
||
|
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
|
||
|
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;
|
||
|
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;
|
||
|
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;
|
||
|
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;
|
||
|
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
|
||
|
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen = BusEnd - BusStart + 1;
|
||
|
|
||
|
Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
|
||
|
((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
|
||
|
((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
|
||
|
|
||
|
*Configuration = Buffer;
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
List = List->ForwardLink;
|
||
|
}
|
||
|
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SetBusNumbers(
|
||
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||
|
IN EFI_HANDLE RootBridgeHandle,
|
||
|
IN VOID *Configuration
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
This function programs the PCI Root Bridge hardware so that
|
||
|
it decodes the specified PCI bus range
|
||
|
|
||
|
Arguments:
|
||
|
This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
|
||
|
RootBridgeHandle -- The PCI Root Bridge whose bus range is to be programmed
|
||
|
Configuration -- The pointer to the PCI bus resource descriptor
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LIST_ENTRY *List;
|
||
|
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
|
||
|
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||
|
UINT8 *Ptr;
|
||
|
UINTN BusStart;
|
||
|
UINTN BusEnd;
|
||
|
UINTN BusLen;
|
||
|
|
||
|
if (Configuration == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
Ptr = Configuration;
|
||
|
|
||
|
//
|
||
|
// Check the Configuration is valid
|
||
|
//
|
||
|
if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
|
||
|
if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
|
||
|
List = HostBridgeInstance->Head.ForwardLink;
|
||
|
|
||
|
Ptr = Configuration;
|
||
|
|
||
|
while (List != &HostBridgeInstance->Head) {
|
||
|
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
|
||
|
if (RootBridgeHandle == RootBridgeInstance->Handle) {
|
||
|
BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
|
||
|
BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
|
||
|
BusEnd = BusStart + BusLen - 1;
|
||
|
|
||
|
if (BusStart > BusEnd) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if ((BusStart < RootBridgeInstance->BusBase) || (BusEnd > RootBridgeInstance->BusLimit)) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Update the Bus Range
|
||
|
//
|
||
|
RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart;
|
||
|
RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
|
||
|
RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
|
||
|
|
||
|
//
|
||
|
// Program the Root Bridge Hardware
|
||
|
//
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
List = List->ForwardLink;
|
||
|
}
|
||
|
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
SubmitResources(
|
||
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||
|
IN EFI_HANDLE RootBridgeHandle,
|
||
|
IN VOID *Configuration
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
Submits the I/O and memory resource requirements for the specified PCI Root Bridge
|
||
|
|
||
|
Arguments:
|
||
|
This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
|
||
|
RootBridgeHandle -- The PCI Root Bridge whose I/O and memory resource requirements
|
||
|
are being submitted
|
||
|
Configuration -- The pointer to the PCI I/O and PCI memory resource descriptor
|
||
|
Returns:
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LIST_ENTRY *List;
|
||
|
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
|
||
|
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||
|
UINT8 *Temp;
|
||
|
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
|
||
|
UINT64 AddrLen;
|
||
|
UINT64 Alignment;
|
||
|
|
||
|
//
|
||
|
// Check the input parameter: Configuration
|
||
|
//
|
||
|
if (Configuration == NULL) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
|
||
|
List = HostBridgeInstance->Head.ForwardLink;
|
||
|
|
||
|
Temp = (UINT8 *)Configuration;
|
||
|
while ( *Temp == 0x8A) {
|
||
|
Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
|
||
|
}
|
||
|
if (*Temp != 0x79) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
Temp = (UINT8 *)Configuration;
|
||
|
while (List != &HostBridgeInstance->Head) {
|
||
|
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
|
||
|
if (RootBridgeHandle == RootBridgeInstance->Handle) {
|
||
|
while ( *Temp == 0x8A) {
|
||
|
ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
|
||
|
|
||
|
//
|
||
|
// Check Address Length
|
||
|
//
|
||
|
if (ptr->AddrLen > 0xffffffff) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Check address range alignment
|
||
|
//
|
||
|
if (ptr->AddrRangeMax >= 0xffffffff || ptr->AddrRangeMax != (GetPowerOfTwo64 (ptr->AddrRangeMax + 1) - 1)) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
switch (ptr->ResType) {
|
||
|
|
||
|
case 0:
|
||
|
|
||
|
//
|
||
|
// Check invalid Address Sapce Granularity
|
||
|
//
|
||
|
if (ptr->AddrSpaceGranularity != 32) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// check the memory resource request is supported by PCI root bridge
|
||
|
//
|
||
|
if (RootBridgeInstance->RootBridgeAttrib == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
|
||
|
ptr->SpecificFlag == 0x06) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
AddrLen = ptr->AddrLen;
|
||
|
Alignment = ptr->AddrRangeMax;
|
||
|
if (ptr->AddrSpaceGranularity == 32) {
|
||
|
if (ptr->SpecificFlag == 0x06) {
|
||
|
//
|
||
|
// Apply from GCD
|
||
|
//
|
||
|
RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted;
|
||
|
} else {
|
||
|
RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
|
||
|
RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;
|
||
|
RootBridgeInstance->ResAllocNode[TypeMem32].Status = ResRequested;
|
||
|
HostBridgeInstance->ResourceSubmited = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ptr->AddrSpaceGranularity == 64) {
|
||
|
if (ptr->SpecificFlag == 0x06) {
|
||
|
RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;
|
||
|
} else {
|
||
|
RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 1:
|
||
|
AddrLen = (UINTN)ptr->AddrLen;
|
||
|
Alignment = (UINTN)ptr->AddrRangeMax;
|
||
|
RootBridgeInstance->ResAllocNode[TypeIo].Length = AddrLen;
|
||
|
RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
|
||
|
RootBridgeInstance->ResAllocNode[TypeIo].Status = ResRequested;
|
||
|
HostBridgeInstance->ResourceSubmited = TRUE;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
};
|
||
|
|
||
|
Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
|
||
|
}
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
List = List->ForwardLink;
|
||
|
}
|
||
|
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
GetProposedResources(
|
||
|
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||
|
IN EFI_HANDLE RootBridgeHandle,
|
||
|
OUT VOID **Configuration
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
This function returns the proposed resource settings for the specified
|
||
|
PCI Root Bridge
|
||
|
|
||
|
Arguments:
|
||
|
This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
|
||
|
RootBridgeHandle -- The PCI Root Bridge handle
|
||
|
Configuration -- The pointer to the pointer to the PCI I/O
|
||
|
and memory resource descriptor
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
LIST_ENTRY *List;
|
||
|
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
|
||
|
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||
|
UINTN Index;
|
||
|
UINTN Number;
|
||
|
VOID *Buffer;
|
||
|
UINT8 *Temp;
|
||
|
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
|
||
|
UINT64 ResStatus;
|
||
|
|
||
|
Buffer = NULL;
|
||
|
Number = 0;
|
||
|
//
|
||
|
// Get the Host Bridge Instance from the resource allocation protocol
|
||
|
//
|
||
|
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
|
||
|
List = HostBridgeInstance->Head.ForwardLink;
|
||
|
|
||
|
//
|
||
|
// Enumerate the root bridges in this host bridge
|
||
|
//
|
||
|
while (List != &HostBridgeInstance->Head) {
|
||
|
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
|
||
|
if (RootBridgeHandle == RootBridgeInstance->Handle) {
|
||
|
for (Index = 0; Index < TypeBus; Index ++) {
|
||
|
if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
|
||
|
Number ++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (Number == 0) {
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
Buffer = AllocateZeroPool (Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof(EFI_ACPI_END_TAG_DESCRIPTOR));
|
||
|
if (Buffer == NULL) {
|
||
|
return EFI_OUT_OF_RESOURCES;
|
||
|
}
|
||
|
|
||
|
Temp = Buffer;
|
||
|
for (Index = 0; Index < TypeBus; Index ++) {
|
||
|
if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
|
||
|
ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
|
||
|
ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
|
||
|
|
||
|
switch (Index) {
|
||
|
|
||
|
case TypeIo:
|
||
|
//
|
||
|
// Io
|
||
|
//
|
||
|
ptr->Desc = 0x8A;
|
||
|
ptr->Len = 0x2B;
|
||
|
ptr->ResType = 1;
|
||
|
ptr->GenFlag = 0;
|
||
|
ptr->SpecificFlag = 0;
|
||
|
ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
|
||
|
ptr->AddrRangeMax = 0;
|
||
|
ptr->AddrTranslationOffset = \
|
||
|
(ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
|
||
|
ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
|
||
|
break;
|
||
|
|
||
|
case TypeMem32:
|
||
|
//
|
||
|
// Memory 32
|
||
|
//
|
||
|
ptr->Desc = 0x8A;
|
||
|
ptr->Len = 0x2B;
|
||
|
ptr->ResType = 0;
|
||
|
ptr->GenFlag = 0;
|
||
|
ptr->SpecificFlag = 0;
|
||
|
ptr->AddrSpaceGranularity = 32;
|
||
|
ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
|
||
|
ptr->AddrRangeMax = 0;
|
||
|
ptr->AddrTranslationOffset = \
|
||
|
(ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
|
||
|
ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
|
||
|
break;
|
||
|
|
||
|
case TypePMem32:
|
||
|
//
|
||
|
// Prefetch memory 32
|
||
|
//
|
||
|
ptr->Desc = 0x8A;
|
||
|
ptr->Len = 0x2B;
|
||
|
ptr->ResType = 0;
|
||
|
ptr->GenFlag = 0;
|
||
|
ptr->SpecificFlag = 6;
|
||
|
ptr->AddrSpaceGranularity = 32;
|
||
|
ptr->AddrRangeMin = 0;
|
||
|
ptr->AddrRangeMax = 0;
|
||
|
ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
|
||
|
ptr->AddrLen = 0;
|
||
|
break;
|
||
|
|
||
|
case TypeMem64:
|
||
|
//
|
||
|
// Memory 64
|
||
|
//
|
||
|
ptr->Desc = 0x8A;
|
||
|
ptr->Len = 0x2B;
|
||
|
ptr->ResType = 0;
|
||
|
ptr->GenFlag = 0;
|
||
|
ptr->SpecificFlag = 0;
|
||
|
ptr->AddrSpaceGranularity = 64;
|
||
|
ptr->AddrRangeMin = 0;
|
||
|
ptr->AddrRangeMax = 0;
|
||
|
ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
|
||
|
ptr->AddrLen = 0;
|
||
|
break;
|
||
|
|
||
|
case TypePMem64:
|
||
|
//
|
||
|
// Prefetch memory 64
|
||
|
//
|
||
|
ptr->Desc = 0x8A;
|
||
|
ptr->Len = 0x2B;
|
||
|
ptr->ResType = 0;
|
||
|
ptr->GenFlag = 0;
|
||
|
ptr->SpecificFlag = 6;
|
||
|
ptr->AddrSpaceGranularity = 64;
|
||
|
ptr->AddrRangeMin = 0;
|
||
|
ptr->AddrRangeMax = 0;
|
||
|
ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
|
||
|
ptr->AddrLen = 0;
|
||
|
break;
|
||
|
};
|
||
|
|
||
|
Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
|
||
|
((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
|
||
|
|
||
|
*Configuration = Buffer;
|
||
|
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
|
||
|
List = List->ForwardLink;
|
||
|
}
|
||
|
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
STATIC
|
||
|
VOID
|
||
|
UpdateRootBridgeAttributes (
|
||
|
IN PCI_ROOT_BRIDGE_INSTANCE *RootBridge,
|
||
|
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
|
||
|
)
|
||
|
{
|
||
|
EFI_STATUS Status;
|
||
|
PCI_TYPE01 PciConfigurationHeader;
|
||
|
UINT64 Attributes;
|
||
|
|
||
|
//
|
||
|
// Read the PCI Configuration Header for the device
|
||
|
//
|
||
|
Status = RootBridge->Io.Pci.Read (
|
||
|
&RootBridge->Io,
|
||
|
EfiPciWidthUint16,
|
||
|
EFI_PCI_ADDRESS(
|
||
|
PciAddress.Bus,
|
||
|
PciAddress.Device,
|
||
|
PciAddress.Function,
|
||
|
0
|
||
|
),
|
||
|
sizeof (PciConfigurationHeader) / sizeof (UINT16),
|
||
|
&PciConfigurationHeader
|
||
|
);
|
||
|
if (EFI_ERROR (Status)) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Attributes = RootBridge->Attributes;
|
||
|
|
||
|
//
|
||
|
// Look for devices with the VGA Palette Snoop enabled in the COMMAND register of the PCI Config Header
|
||
|
//
|
||
|
if (PciConfigurationHeader.Hdr.Command & 0x20) {
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If the device is a PCI-PCI Bridge, then look at the Subordinate Bus Number
|
||
|
//
|
||
|
if (IS_PCI_BRIDGE(&PciConfigurationHeader)) {
|
||
|
//
|
||
|
// Look at the PPB Configuration for legacy decoding attributes
|
||
|
//
|
||
|
if (PciConfigurationHeader.Bridge.BridgeControl & 0x04) {
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_ISA_IO;
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO;
|
||
|
}
|
||
|
if (PciConfigurationHeader.Bridge.BridgeControl & 0x08) {
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
|
||
|
}
|
||
|
} else {
|
||
|
//
|
||
|
// See if the PCI device is an IDE controller
|
||
|
//
|
||
|
if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x01 &&
|
||
|
PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
|
||
|
if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x80) {
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
|
||
|
}
|
||
|
if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x01) {
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO;
|
||
|
}
|
||
|
if (PciConfigurationHeader.Hdr.ClassCode[0] & 0x04) {
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// See if the PCI device is a legacy VGA controller
|
||
|
//
|
||
|
if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x00 &&
|
||
|
PciConfigurationHeader.Hdr.ClassCode[1] == 0x01 ) {
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// See if the PCI device is a standard VGA controller
|
||
|
//
|
||
|
if (PciConfigurationHeader.Hdr.ClassCode[2] == 0x03 &&
|
||
|
PciConfigurationHeader.Hdr.ClassCode[1] == 0x00 ) {
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO;
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_VGA_MEMORY;
|
||
|
Attributes |= EFI_PCI_ATTRIBUTE_VGA_IO;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
RootBridge->Attributes = Attributes;
|
||
|
RootBridge->Supports = Attributes;
|
||
|
}
|
||
|
|
||
|
EFI_STATUS
|
||
|
EFIAPI
|
||
|
PreprocessController (
|
||
|
IN struct _EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
|
||
|
IN EFI_HANDLE RootBridgeHandle,
|
||
|
IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
|
||
|
IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
This function is called for all the PCI controllers that the PCI
|
||
|
bus driver finds. Can be used to Preprogram the controller.
|
||
|
|
||
|
Arguments:
|
||
|
This -- The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
|
||
|
RootBridgeHandle -- The PCI Root Bridge handle
|
||
|
PciBusAddress -- Address of the controller on the PCI bus
|
||
|
Phase -- The Phase during resource allocation
|
||
|
|
||
|
Returns:
|
||
|
EFI_SUCCESS
|
||
|
--*/
|
||
|
{
|
||
|
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
|
||
|
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
|
||
|
LIST_ENTRY *List;
|
||
|
|
||
|
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
|
||
|
List = HostBridgeInstance->Head.ForwardLink;
|
||
|
|
||
|
//
|
||
|
// Enumerate the root bridges in this host bridge
|
||
|
//
|
||
|
while (List != &HostBridgeInstance->Head) {
|
||
|
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
|
||
|
if (RootBridgeHandle == RootBridgeInstance->Handle) {
|
||
|
UpdateRootBridgeAttributes (
|
||
|
RootBridgeInstance,
|
||
|
PciAddress
|
||
|
);
|
||
|
return EFI_SUCCESS;
|
||
|
}
|
||
|
List = List->ForwardLink;
|
||
|
}
|
||
|
|
||
|
return EFI_INVALID_PARAMETER;
|
||
|
}
|