/** @file | |
Pci Host Bridge driver for a simple IIO. There is only one PCI Root Bridge in the system. | |
Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation. | |
Copyright (c) 2013-2015 Intel Corporation. | |
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" | |
#include <IntelQNCRegs.h> | |
// | |
// We can hardcode the following for a Simple IIO - | |
// Root Bridge Count within the host bridge | |
// Root Bridge's device path | |
// Root Bridge's resource appeture | |
// | |
EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath[ROOT_BRIDGE_COUNT] = { | |
{ | |
{ | |
{ | |
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 | |
} | |
} | |
} | |
}; | |
EFI_HANDLE mDriverImageHandle; | |
PCI_ROOT_BRIDGE_RESOURCE_APERTURE *mResAperture; | |
// | |
// Implementation | |
// | |
EFI_STATUS | |
EFIAPI | |
InitializePciHostBridge ( | |
IN EFI_HANDLE ImageHandle, | |
IN EFI_SYSTEM_TABLE *SystemTable | |
) | |
/*++ | |
Routine Description: | |
Entry point of this driver. | |
Arguments: | |
ImageHandle - Image handle of this driver. | |
SystemTable - Pointer to standard EFI system table. | |
Returns: | |
EFI_SUCCESS - Succeed. | |
EFI_DEVICE_ERROR - Fail to install PCI_ROOT_BRIDGE_IO protocol. | |
--*/ | |
{ | |
EFI_STATUS Status; | |
UINTN TotalRootBridgeFound; | |
PCI_HOST_BRIDGE_INSTANCE *HostBridge; | |
PCI_ROOT_BRIDGE_INSTANCE *PrivateData; | |
UINT64 AllocAttributes; | |
EFI_PHYSICAL_ADDRESS BaseAddress; | |
PrivateData = NULL; | |
mDriverImageHandle = ImageHandle; | |
// | |
// Most systems in the world including complex servers | |
// have only one Host Bridge. Create Host Bridge Device Handle | |
// | |
Status = gBS->AllocatePool(EfiBootServicesData, sizeof(PCI_HOST_BRIDGE_INSTANCE), (VOID **) &HostBridge); | |
ASSERT_EFI_ERROR (Status); | |
ZeroMem (HostBridge, sizeof (PCI_HOST_BRIDGE_INSTANCE)); | |
HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE; | |
HostBridge->RootBridgeCount = 1; | |
HostBridge->ResourceSubmited = FALSE; | |
HostBridge->CanRestarted = TRUE; | |
// | |
// InitializeListHead (&HostBridge->Head); | |
// | |
HostBridge->ResAlloc.NotifyPhase = NotifyPhase; | |
HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge; | |
HostBridge->ResAlloc.GetAllocAttributes = GetAttributes; | |
HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration; | |
HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers; | |
HostBridge->ResAlloc.SubmitResources = SubmitResources; | |
HostBridge->ResAlloc.GetProposedResources = GetProposedResources; | |
HostBridge->ResAlloc.PreprocessController = PreprocessController; | |
Status = gBS->InstallProtocolInterface ( | |
&HostBridge->HostBridgeHandle, | |
&gEfiPciHostBridgeResourceAllocationProtocolGuid, | |
EFI_NATIVE_INTERFACE, | |
&HostBridge->ResAlloc | |
); | |
if (EFI_ERROR (Status)) { | |
gBS->FreePool (HostBridge); | |
return EFI_DEVICE_ERROR; | |
} | |
Status = gBS->AllocatePool (EfiBootServicesData, | |
HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE), | |
(VOID **) &mResAperture); | |
ASSERT_EFI_ERROR (Status); | |
ZeroMem (mResAperture, HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE)); | |
DEBUG ((EFI_D_INFO, "Address of resource Aperture: %x\n", mResAperture)); | |
// | |
// Create Root Bridge Device Handle in this Host Bridge | |
// | |
InitializeListHead (&HostBridge->Head); | |
TotalRootBridgeFound = 0; | |
Status = gBS->AllocatePool ( EfiBootServicesData,sizeof (PCI_ROOT_BRIDGE_INSTANCE), (VOID **) &PrivateData); | |
ASSERT_EFI_ERROR (Status); | |
ZeroMem (PrivateData, sizeof (PCI_ROOT_BRIDGE_INSTANCE)); | |
PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE; | |
PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &mEfiPciRootBridgeDevicePath[TotalRootBridgeFound]; | |
AllocAttributes = GetAllocAttributes (TotalRootBridgeFound); | |
SimpleIioRootBridgeConstructor ( | |
&PrivateData->Io, | |
HostBridge->HostBridgeHandle, | |
&(mResAperture[TotalRootBridgeFound]), | |
AllocAttributes | |
); | |
// | |
// Update Root Bridge with UDS resource information | |
// | |
PrivateData->Aperture.BusBase = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE; | |
PrivateData->Aperture.BusLimit = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT; | |
PrivateData->Aperture.Mem32Base = PcdGet32 (PcdPciHostBridgeMemory32Base); | |
PrivateData->Aperture.Mem32Limit = PcdGet32 (PcdPciHostBridgeMemory32Base) + (PcdGet32 (PcdPciHostBridgeMemory32Size) - 1); | |
PrivateData->Aperture.IoBase = PcdGet16 (PcdPciHostBridgeIoBase); | |
PrivateData->Aperture.IoLimit = PcdGet16 (PcdPciHostBridgeIoBase) + (PcdGet16 (PcdPciHostBridgeIoSize) - 1); | |
DEBUG ((EFI_D_INFO, "PCI Host Bridge BusBase: %x\n", QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE)); | |
DEBUG ((EFI_D_INFO, "PCI Host Bridge BusLimit: %x\n", QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT)); | |
DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem32Base: %x\n", PcdGet32 (PcdPciHostBridgeMemory32Base))); | |
DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem32Limit: %x\n", PcdGet32 (PcdPciHostBridgeMemory32Base) + (PcdGet32 (PcdPciHostBridgeMemory32Size) - 1))); | |
DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem64Base: %lX\n", PcdGet64 (PcdPciHostBridgeMemory64Base))); | |
DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem64Limit: %lX\n", PcdGet64 (PcdPciHostBridgeMemory64Base) + (PcdGet64 (PcdPciHostBridgeMemory64Size) - 1))); | |
DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceIoBase: %x\n", PcdGet16 (PcdPciHostBridgeIoBase))); | |
DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceIoLimit: %x\n", PcdGet16 (PcdPciHostBridgeIoBase) + (PcdGet16 (PcdPciHostBridgeIoSize) - 1))); | |
PrivateData->Handle = NULL; | |
Status = gBS->InstallMultipleProtocolInterfaces ( | |
&PrivateData->Handle, | |
&gEfiDevicePathProtocolGuid, | |
PrivateData->DevicePath, | |
&gEfiPciRootBridgeIoProtocolGuid, | |
&PrivateData->Io, | |
NULL | |
); | |
ASSERT_EFI_ERROR (Status); | |
InsertTailList (&HostBridge->Head, &PrivateData->Link); | |
TotalRootBridgeFound++; // This is a valid rootbridge so imcrement total root bridges found | |
// | |
// Add PCIE base into Runtime memory so that it can be reported in E820 table | |
// | |
Status = gDS->AddMemorySpace ( | |
EfiGcdMemoryTypeMemoryMappedIo, | |
PcdGet64 (PcdPciExpressBaseAddress), | |
PcdGet64 (PcdPciExpressSize), | |
EFI_MEMORY_RUNTIME | EFI_MEMORY_UC | |
); | |
ASSERT_EFI_ERROR(Status); | |
BaseAddress = PcdGet64 (PcdPciExpressBaseAddress); | |
Status = gDS->AllocateMemorySpace ( | |
EfiGcdAllocateAddress, | |
EfiGcdMemoryTypeMemoryMappedIo, | |
0, | |
PcdGet64 (PcdPciExpressSize), | |
&BaseAddress, | |
ImageHandle, | |
NULL | |
); | |
ASSERT_EFI_ERROR(Status); | |
Status = gDS->SetMemorySpaceAttributes ( | |
PcdGet64 (PcdPciExpressBaseAddress), | |
PcdGet64 (PcdPciExpressSize), | |
EFI_MEMORY_RUNTIME | |
); | |
ASSERT_EFI_ERROR (Status); | |
if (PcdGet16 (PcdPciHostBridgeIoSize) > 0) { | |
// | |
// At present, we use up the first 4k for fixed ranges like | |
// ICH GPIO, ACPI and ISA devices. The first 4k is not | |
// tracked through GCD. It should be. | |
// | |
Status = gDS->AddIoSpace ( | |
EfiGcdIoTypeIo, | |
PcdGet16(PcdPciHostBridgeIoBase), | |
PcdGet16(PcdPciHostBridgeIoSize) | |
); | |
ASSERT_EFI_ERROR (Status); | |
} | |
if (PcdGet32(PcdPciHostBridgeMemory32Size) > 0) { | |
// | |
// Shouldn't the capabilities be UC? | |
// | |
Status = gDS->AddMemorySpace ( | |
EfiGcdMemoryTypeMemoryMappedIo, | |
PcdGet32(PcdPciHostBridgeMemory32Base), | |
PcdGet32(PcdPciHostBridgeMemory32Size), | |
0 | |
); | |
ASSERT_EFI_ERROR (Status); | |
} | |
return Status; | |
} | |
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: | |
EFI_SUCCESS - Succeed. | |
EFI_INVALID_PARAMETER - Wrong phase parameter passed in. | |
EFI_NOT_READY - Resources have not been submitted yet. | |
--*/ | |
{ | |
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; | |
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; | |
PCI_RESOURCE_TYPE Index; | |
EFI_LIST_ENTRY *List; | |
EFI_PHYSICAL_ADDRESS BaseAddress; | |
UINT64 AddrLen; | |
UINTN BitsOfAlignment; | |
UINT64 Alignment; | |
EFI_STATUS Status; | |
EFI_STATUS ReturnStatus; | |
PCI_RESOURCE_TYPE Index1; | |
PCI_RESOURCE_TYPE Index2; | |
BOOLEAN ResNodeHandled[TypeMax]; | |
UINT64 MaxAlignment; | |
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This); | |
switch (Phase) { | |
case EfiPciHostBridgeBeginEnumeration: | |
if (HostBridgeInstance->CanRestarted) { | |
// | |
// Reset 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; | |
} // for | |
List = List->ForwardLink; | |
} // while | |
HostBridgeInstance->ResourceSubmited = FALSE; | |
HostBridgeInstance->CanRestarted = TRUE; | |
} else { | |
// | |
// Can not restart | |
// | |
return EFI_NOT_READY; | |
} // if | |
break; | |
case EfiPciHostBridgeEndEnumeration: | |
return EFI_SUCCESS; | |
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) { | |
List = HostBridgeInstance->Head.ForwardLink; | |
while (List != &HostBridgeInstance->Head) { | |
for (Index1 = TypeIo; Index1 < TypeBus; Index1++) { | |
ResNodeHandled[Index1] = FALSE; | |
} | |
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); | |
DEBUG ((EFI_D_INFO, "Address of RootBridgeInstance: %x)\n", RootBridgeInstance)); | |
DEBUG ((EFI_D_INFO, " Signature: %x\n", RootBridgeInstance->Signature)); | |
DEBUG ((EFI_D_INFO, " Bus Number Assigned: %x\n", RootBridgeInstance->BusNumberAssigned)); | |
DEBUG ((EFI_D_INFO, " Bus Scan Count: %x\n", RootBridgeInstance->BusScanCount)); | |
for (Index1 = TypeIo; Index1 < TypeBus; Index1++) { | |
if (RootBridgeInstance->ResAllocNode[Index1].Status == ResNone) { | |
ResNodeHandled[Index1] = TRUE; | |
} else { | |
// | |
// Allocate the resource node with max alignment at first | |
// | |
MaxAlignment = 0; | |
Index = TypeMax; | |
for (Index2 = TypeIo; Index2 < TypeBus; Index2++) { | |
if (ResNodeHandled[Index2]) { | |
continue; | |
} | |
if (MaxAlignment <= RootBridgeInstance->ResAllocNode[Index2].Alignment) { | |
MaxAlignment = RootBridgeInstance->ResAllocNode[Index2].Alignment; | |
Index = Index2; | |
} | |
} // for | |
if (Index < TypeMax) { | |
ResNodeHandled[Index] = TRUE; | |
} else { | |
ASSERT (FALSE); | |
} | |
Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment; | |
// | |
// Get the number of '1' in Alignment. | |
// | |
for (BitsOfAlignment = 0; Alignment != 0; BitsOfAlignment++) { | |
Alignment = RShiftU64 (Alignment, 1); | |
} | |
AddrLen = RootBridgeInstance->ResAllocNode[Index].Length; | |
Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment; | |
DEBUG ((EFI_D_INFO, "\n\nResource Type to assign : %x\n", Index)); | |
DEBUG ((EFI_D_INFO, " Length to allocate: %x\n", RootBridgeInstance->ResAllocNode[Index].Length)); | |
DEBUG ((EFI_D_INFO, " Aligment: %x\n", Alignment)); | |
switch (Index) { | |
case TypeIo: | |
if (RootBridgeInstance->Aperture.IoBase < RootBridgeInstance->Aperture.IoLimit) { | |
// | |
// It is impossible for 0xFFFF Alignment for IO16 | |
// | |
if (BitsOfAlignment >= 16) | |
Alignment = 0; | |
BaseAddress = RootBridgeInstance->Aperture.IoBase; | |
// | |
// Have to make sure Aligment is handled seeing we are doing direct address allocation | |
// | |
if ((BaseAddress & ~(Alignment)) != BaseAddress) | |
BaseAddress = ((BaseAddress + Alignment) & ~(Alignment)); | |
while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.IoLimit + 1) { | |
Status = gDS->AllocateIoSpace ( EfiGcdAllocateAddress, EfiGcdIoTypeIo, BitsOfAlignment, | |
AddrLen, &BaseAddress, mDriverImageHandle, NULL ); | |
if (!EFI_ERROR (Status)) { | |
RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress; | |
RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated; | |
goto TypeIoFound; | |
} | |
BaseAddress += (Alignment + 1); | |
} // while | |
} // if | |
TypeIoFound: | |
if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) { | |
// | |
// No Room at the Inn for this resources request | |
// | |
ReturnStatus = EFI_OUT_OF_RESOURCES; | |
} // if | |
break; | |
case TypeMem32: | |
if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) { | |
BaseAddress = RootBridgeInstance->Aperture.Mem32Base; | |
// | |
// Have to make sure Aligment is handled seeing we are doing direct address allocation | |
// | |
if ((BaseAddress & ~(Alignment)) != BaseAddress) | |
BaseAddress = ((BaseAddress + Alignment) & ~(Alignment)); | |
while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.Mem32Limit + 1) { | |
Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo, | |
BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL); | |
if (!EFI_ERROR (Status)) { | |
RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress; | |
RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated; | |
goto TypeMem32Found; | |
} // if | |
BaseAddress += (Alignment + 1); | |
} // while | |
} // if | |
TypeMem32Found: | |
if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) { | |
// | |
// No Room at the Inn for this resources request | |
// | |
ReturnStatus = EFI_OUT_OF_RESOURCES; | |
} | |
break; | |
case TypePMem32: | |
StartTypePMem32: | |
if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) { | |
BaseAddress = RootBridgeInstance->Aperture.Mem32Limit + 1; | |
BaseAddress -= AddrLen; | |
// | |
// Have to make sure Aligment is handled seeing we are doing direct address allocation | |
// | |
if ((BaseAddress & ~(Alignment)) != BaseAddress) | |
BaseAddress = ((BaseAddress) & ~(Alignment)); | |
while(RootBridgeInstance->Aperture.Mem32Base <= BaseAddress) { | |
DEBUG ((EFI_D_INFO, " Attempting %x allocation at 0x%lx .....", Index, BaseAddress)); | |
Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo, | |
BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL); | |
if (!EFI_ERROR (Status)) { | |
RootBridgeInstance->ResAllocNode[Index].Base = (UINT64) BaseAddress; | |
RootBridgeInstance->ResAllocNode[Index].Status = ResAllocated; | |
DEBUG ((EFI_D_INFO, "... Passed!!\n")); | |
goto TypePMem32Found; | |
} | |
DEBUG ((EFI_D_INFO, "... Failed!!\n")); | |
BaseAddress -= (Alignment + 1); | |
} // while | |
} // if | |
TypePMem32Found: | |
if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) { | |
// | |
// No Room at the Inn for this resources request | |
// | |
ReturnStatus = EFI_OUT_OF_RESOURCES; | |
} | |
break; | |
case TypeMem64: | |
case TypePMem64: | |
if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) { | |
// | |
// If 64-bit resourcing is not available, then try as PMem32 | |
// | |
goto StartTypePMem32; | |
} | |
break; | |
default: | |
break; | |
} // End switch (Index) | |
DEBUG ((EFI_D_INFO, "Resource Type Assigned: %x\n", Index)); | |
if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) { | |
DEBUG ((EFI_D_INFO, " Base Address Assigned: %x\n", RootBridgeInstance->ResAllocNode[Index].Base)); | |
DEBUG ((EFI_D_INFO, " Length Assigned: %x\n", RootBridgeInstance->ResAllocNode[Index].Length)); | |
} else { | |
DEBUG ((DEBUG_ERROR, " Resource Allocation failed! There was no room at the inn\n")); | |
} | |
} | |
} | |
List = List->ForwardLink; | |
} | |
if (ReturnStatus == EFI_OUT_OF_RESOURCES) { | |
DEBUG ((DEBUG_ERROR, "Resource allocation Failed. Continue booting the system.\n")); | |
} | |
// | |
// Set resource to zero for nodes where allocation fails | |
// | |
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) { | |
RootBridgeInstance->ResAllocNode[Index].Length = 0; | |
} | |
} | |
List = List->ForwardLink; | |
} | |
return ReturnStatus; | |
} else { | |
return EFI_NOT_READY; | |
} | |
// | |
// HostBridgeInstance->CanRestarted = FALSE; | |
// | |
break; | |
case EfiPciHostBridgeSetResources: | |
// | |
// HostBridgeInstance->CanRestarted = FALSE; | |
// | |
break; | |
case EfiPciHostBridgeFreeResources: | |
// | |
// HostBridgeInstance->CanRestarted = FALSE; | |
// | |
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 = (EFI_PHYSICAL_ADDRESS) 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: | |
Status = gDS->FreeMemorySpace (BaseAddress, AddrLen); | |
if (EFI_ERROR (Status)) { | |
ReturnStatus = Status; | |
} | |
break; | |
default: | |
break; | |
} // end switch (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; | |
return ReturnStatus; | |
break; | |
case EfiPciHostBridgeEndResourceAllocation: | |
// | |
// Resource enumeration is done. Perform any activities that | |
// must wait until that time. | |
// | |
break; | |
default: | |
return EFI_INVALID_PARAMETER; | |
} // End switch (Phase) | |
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: | |
EFI_SUCCESS - Succeed. | |
EFI_NOT_FOUND - Next PCI root bridge not found. | |
EFI_INVALID_PARAMETER - Wrong parameter passed in. | |
--*/ | |
{ | |
BOOLEAN NoRootBridge; | |
EFI_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. | |
Attributes - The pointer to attributes of the PCI Root Bridge. | |
Returns: | |
EFI_SUCCESS - Succeed. | |
EFI_INVALID_PARAMETER - Attributes parameter passed in is NULL or | |
RootBridgeHandle is not an EFI_HANDLE | |
that was returned on a previous call to | |
GetNextRootBridge(). | |
--*/ | |
{ | |
EFI_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->RootBridgeAllocAttrib; | |
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: | |
EFI_SUCCESS - Succeed. | |
EFI_OUT_OF_RESOURCES - Not enough pool to be allocated. | |
EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle. | |
--*/ | |
{ | |
EFI_LIST_ENTRY *List; | |
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; | |
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; | |
VOID *Buffer; | |
UINT8 *Temp; | |
EFI_STATUS Status; | |
UINTN BusStart; | |
UINTN BusEnd; | |
UINT64 BusReserve; | |
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->Aperture.BusBase; | |
BusEnd = RootBridgeInstance->Aperture.BusLimit; | |
BusReserve = RootBridgeInstance->Aperture.BusReserve; | |
// | |
// Program the Hardware(if needed) if error return EFI_DEVICE_ERROR | |
// | |
Status = gBS->AllocatePool ( | |
EfiBootServicesData, | |
sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR), | |
&Buffer | |
); | |
if (EFI_ERROR (Status)) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
Temp = (UINT8 *) Buffer; | |
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; | |
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Len = 0x2B; | |
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS; | |
((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 = BusReserve; | |
((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 = ACPI_END_TAG_DESCRIPTOR; | |
((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: | |
EFI_SUCCESS - Succeed. | |
EFI_INVALID_PARAMETER - Wrong parameters passed in. | |
--*/ | |
{ | |
EFI_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 != ACPI_ADDRESS_SPACE_TYPE_BUS) { | |
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->Aperture.BusBase) || (BusEnd > RootBridgeInstance->Aperture.BusLimit)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// Update the Bus Range | |
// | |
RootBridgeInstance->ResAllocNode[TypeBus].Base = BusStart; | |
RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen; | |
RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated; | |
RootBridgeInstance->BusScanCount++; | |
if (RootBridgeInstance->BusScanCount > 0) { | |
// | |
// Only care about the 2nd PCI bus scanning | |
// | |
RootBridgeInstance->BusNumberAssigned = TRUE; | |
} | |
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: | |
EFI_SUCCESS - Succeed. | |
EFI_INVALID_PARAMETER - Wrong parameters passed in. | |
--*/ | |
{ | |
EFI_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; | |
UINT64 Value; | |
// | |
// 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 (List != &HostBridgeInstance->Head) { | |
RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List); | |
if (RootBridgeHandle == RootBridgeInstance->Handle) { | |
// | |
// Check the resource descriptors. | |
// If the Configuration includes one or more invalid resource descriptors, all the resource | |
// descriptors are ignored and the function returns EFI_INVALID_PARAMETER. | |
// | |
while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) { | |
ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp; | |
DEBUG ((EFI_D_INFO, " ptr->ResType:%x \n",ptr->ResType)); | |
DEBUG ((EFI_D_INFO, " ptr->AddrLen:0x%lx AddrRangeMin:0x%lx AddrRangeMax:0x%lx\n\n",ptr->AddrLen,ptr->AddrRangeMin,ptr->AddrRangeMax)); | |
switch (ptr->ResType) { | |
case ACPI_ADDRESS_SPACE_TYPE_MEM: | |
if (ptr->AddrSpaceGranularity != 32 && ptr->AddrSpaceGranularity != 64) { | |
return EFI_INVALID_PARAMETER; | |
} | |
if (ptr->AddrSpaceGranularity == 32 && ptr->AddrLen > 0xffffffff) { | |
return EFI_INVALID_PARAMETER; | |
} | |
// | |
// If the PCI root bridge does not support separate windows for nonprefetchable and | |
// prefetchable memory, then the PCI bus driver needs to include requests for | |
// prefetchable memory in the nonprefetchable memory pool. | |
// | |
if ((RootBridgeInstance->RootBridgeAllocAttrib & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 && | |
((ptr->SpecificFlag & (BIT2 | BIT1)) != 0)) { | |
return EFI_INVALID_PARAMETER; | |
} | |
case ACPI_ADDRESS_SPACE_TYPE_IO: | |
// | |
// Check aligment, it should be of the form 2^n-1 | |
// | |
Value = Power2MaxMemory (ptr->AddrRangeMax + 1); | |
if (Value != (ptr->AddrRangeMax + 1)) { | |
CpuDeadLoop(); | |
return EFI_INVALID_PARAMETER; | |
} | |
break; | |
case ACPI_ADDRESS_SPACE_TYPE_BUS: | |
default: | |
return EFI_INVALID_PARAMETER; | |
} | |
Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ; | |
} | |
if (*Temp != ACPI_END_TAG_DESCRIPTOR) { | |
return EFI_INVALID_PARAMETER; | |
} | |
Temp = (UINT8 *) Configuration; | |
while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) { | |
ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp; | |
switch (ptr->ResType) { | |
case ACPI_ADDRESS_SPACE_TYPE_MEM: | |
AddrLen = (UINT64) ptr->AddrLen; | |
Alignment = (UINT64) 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].Length = AddrLen; | |
RootBridgeInstance->ResAllocNode[TypeMem64].Alignment = Alignment; | |
RootBridgeInstance->ResAllocNode[TypeMem64].Status = ResSubmitted; | |
HostBridgeInstance->ResourceSubmited = TRUE; | |
} | |
} | |
break; | |
case ACPI_ADDRESS_SPACE_TYPE_IO: | |
AddrLen = (UINT64) ptr->AddrLen; | |
Alignment = (UINT64) 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: | |
EFI_SUCCESS - Succeed. | |
EFI_OUT_OF_RESOURCES - Not enough pool to be allocated. | |
EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle. | |
--*/ | |
{ | |
EFI_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; | |
EFI_STATUS Status; | |
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) { | |
Status = gBS->AllocatePool ( | |
EfiBootServicesData, | |
Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR), | |
&Buffer | |
); | |
if (EFI_ERROR (Status)) { | |
return EFI_OUT_OF_RESOURCES; | |
} | |
ZeroMem (Buffer, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Number + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)); | |
} | |
ASSERT (Buffer != NULL); | |
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 = 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 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; | |
} | |
EFI_STATUS | |
EFIAPI | |
PreprocessController ( | |
IN 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. | |
PciAddress - Address of the controller on the PCI bus. | |
Phase - The Phase during resource allocation. | |
Returns: | |
EFI_SUCCESS - Succeed. | |
EFI_INVALID_PARAMETER - RootBridgeHandle is not a valid handle. | |
--*/ | |
{ | |
BOOLEAN RootBridgeFound; | |
EFI_LIST_ENTRY *List; | |
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance; | |
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance; | |
if (RootBridgeHandle == NULL) { | |
return EFI_INVALID_PARAMETER; | |
} | |
RootBridgeFound = FALSE; | |
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) { | |
RootBridgeFound = TRUE; | |
break; | |
} | |
// | |
// Get next if have | |
// | |
List = List->ForwardLink; | |
} | |
if (RootBridgeFound == FALSE) { | |
return EFI_INVALID_PARAMETER; | |
} | |
return EFI_SUCCESS; | |
} | |
UINT64 | |
Power2MaxMemory ( | |
IN UINT64 MemoryLength | |
) | |
/*++ | |
Routine Description: | |
Calculate maximum memory length that can be fit to a mtrr. | |
Arguments: | |
MemoryLength - Input memory length. | |
Returns: | |
Returned Maximum length. | |
--*/ | |
{ | |
UINT64 Result; | |
if (RShiftU64 (MemoryLength, 32)) { | |
Result = LShiftU64 ((UINT64) GetPowerOfTwo64 ((UINT32) RShiftU64 (MemoryLength, 32)), 32); | |
} else { | |
Result = (UINT64) GetPowerOfTwo64 ((UINT32) MemoryLength); | |
} | |
return Result; | |
} |