audk/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAlloca...

643 lines
24 KiB
C

/** @file
* Implementation of the Pci Host Bridge Resource Allocation for the Xpress-RICH3 PCIe Root Complex
*
* Copyright (c) 2011-2015, ARM Ltd. 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"
EFI_STATUS
PciHbRaNotifyPhase (
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
)
{
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
EFI_STATUS Status;
EFI_PHYSICAL_ADDRESS BaseAddress;
UINT64 AddrLen;
UINTN BitsOfAlignment;
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
PCI_TRACE ("PciHbRaNotifyPhase()");
// Check RootBridge Signature
ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
// The enumeration cannot be restarted after the process has been further than the first phase
if (Phase == EfiPciHostBridgeBeginEnumeration) {
if (!HostBridgeInstance->CanRestarted) {
return EFI_NOT_READY;
}
} else {
HostBridgeInstance->CanRestarted = FALSE;
}
switch (Phase) {
case EfiPciHostBridgeBeginEnumeration:
PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginEnumeration)");
// Resets the host bridge PCI apertures and internal data structures
Status = HWPciRbInit (HostBridgeInstance->CpuIo);
if (EFI_ERROR (Status)) {
return Status;
}
break;
case EfiPciHostBridgeBeginBusAllocation:
PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginBusAllocation)");
// The bus allocation phase is about to begin
break;
case EfiPciHostBridgeEndBusAllocation:
PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndBusAllocation)");
// The bus allocation and bus programming phase is complete. All the PCI-to-PCI bridges have been given and written back
// a bus number range into their configuration
break;
case EfiPciHostBridgeBeginResourceAllocation:
PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginResourceAllocation)");
// The resource allocation phase is about to begin.
break;
case EfiPciHostBridgeAllocateResources:
PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeAllocateResources)");
// Allocates resources per previously submitted requests for all the PCI root bridges. The resources have been submitted to
// PciHbRaSubmitResources() before.
RootBridgeInstance = HostBridgeInstance->RootBridge;
if (RootBridgeInstance->ResAlloc[ResTypeIo].Length != 0) {
BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeIo].Alignment) + 1; // Get the number of '1' in Alignment
AddrLen = RootBridgeInstance->ResAlloc[ResTypeIo].Length;
Status = gDS->AllocateIoSpace (
EfiGcdAllocateAnySearchBottomUp,
EfiGcdIoTypeIo,
BitsOfAlignment,
AddrLen,
&BaseAddress,
HostBridgeInstance->ImageHandle,
NULL
);
// If error then ResAlloc[n].Base ==0
if (!EFI_ERROR (Status)) {
RootBridgeInstance->ResAlloc[ResTypeIo].Base = (UINTN)BaseAddress;
}
}
if (RootBridgeInstance->ResAlloc[ResTypeMem32].Length != 0) {
BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem32].Alignment) + 1; // Get the number of '1' in Alignment
AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem32].Length;
// Top of the 32bit PCI Memory space
BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size);
Status = gDS->AllocateMemorySpace (
EfiGcdAllocateMaxAddressSearchTopDown,
EfiGcdMemoryTypeMemoryMappedIo,
BitsOfAlignment,
AddrLen,
&BaseAddress,
HostBridgeInstance->ImageHandle,
NULL
);
// Ensure the allocation is in the 32bit PCI memory space
if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) {
RootBridgeInstance->ResAlloc[ResTypeMem32].Base = (UINTN)BaseAddress;
}
}
if (RootBridgeInstance->ResAlloc[ResTypePMem32].Length != 0) {
BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem32].Alignment) + 1; // Get the number of '1' in Alignment
AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem32].Length;
// Top of the 32bit PCI Memory space
BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size);
Status = gDS->AllocateMemorySpace (
EfiGcdAllocateMaxAddressSearchTopDown,
EfiGcdMemoryTypeMemoryMappedIo,
BitsOfAlignment,
AddrLen,
&BaseAddress,
HostBridgeInstance->ImageHandle,
NULL
);
// Ensure the allocation is in the 32bit PCI memory space
if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) {
RootBridgeInstance->ResAlloc[ResTypePMem32].Base = (UINTN)BaseAddress;
}
}
if (RootBridgeInstance->ResAlloc[ResTypeMem64].Length != 0) {
BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem64].Alignment) + 1; // Get the number of '1' in Alignment
AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem64].Length;
// Top of the 64bit PCI Memory space
BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size);
Status = gDS->AllocateMemorySpace (
EfiGcdAllocateMaxAddressSearchTopDown,
EfiGcdMemoryTypeMemoryMappedIo,
BitsOfAlignment,
AddrLen,
&BaseAddress,
HostBridgeInstance->ImageHandle,
NULL
);
// Ensure the allocation is in the 64bit PCI memory space
if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) {
RootBridgeInstance->ResAlloc[ResTypeMem64].Base = (UINTN)BaseAddress;
}
}
if (RootBridgeInstance->ResAlloc[ResTypePMem64].Length != 0) {
BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem64].Alignment) + 1; //Get the number of '1' in Alignment
AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem64].Length;
// Top of the 64bit PCI Memory space
BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size);
Status = gDS->AllocateMemorySpace (
EfiGcdAllocateMaxAddressSearchTopDown,
EfiGcdMemoryTypeMemoryMappedIo,
BitsOfAlignment,
AddrLen,
&BaseAddress,
HostBridgeInstance->ImageHandle,
NULL
);
// Ensure the allocation is in the 64bit PCI memory space
if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) {
RootBridgeInstance->ResAlloc[ResTypePMem64].Base = (UINTN)BaseAddress;
}
}
break;
case EfiPciHostBridgeSetResources:
PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeSetResources)");
// Programs the host bridge hardware to decode previously allocated resources (proposed resources)
// for all the PCI root bridges. The PCI bus driver will now program the resources
break;
case EfiPciHostBridgeFreeResources:
PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeFreeResources)");
// Deallocates resources that were previously allocated for all the PCI root bridges and resets the
// I/O and memory apertures to their initial state.*/
break;
case EfiPciHostBridgeEndResourceAllocation:
PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndResourceAllocation)");
break;
case EfiPciHostBridgeEndEnumeration:
PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndEnumeration)");
break;
default:
DEBUG ((EFI_D_INFO, "PciHbRaNotifyPhase(Phase:%d)\n", Phase));
ASSERT (0);
}
return EFI_SUCCESS;
}
/**
* PciHbRaGetNextRootBridge() returns the next root bridge attached to the 'This' PCI Host Bridge.
* As we have only got one PCI Root Bridge in this PCI interface, we return either this root bridge
* if it the first time we call this function (*RootBridgeHandle == NULL) or we return EFI_NOT_FOUND
**/
EFI_STATUS
PciHbRaGetNextRootBridge (
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
IN OUT EFI_HANDLE *RootBridgeHandle
)
{
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_TRACE ("PciHbRaGetNextRootBridge()");
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
ASSERT (HostBridgeInstance->RootBridge != NULL);
//Check RootBridge Signature
ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
if (*RootBridgeHandle == NULL) {
*RootBridgeHandle = HostBridgeInstance->RootBridge->Handle;
return EFI_SUCCESS;
} else if (*RootBridgeHandle == HostBridgeInstance->RootBridge->Handle) {
return EFI_NOT_FOUND;
} else {
return EFI_INVALID_PARAMETER;
}
}
/** PciHbRaGetAllocAttributes() returns the resource allocation attributes supported by this PCI Root Bridge.
* A PCI Root bridge could support these types :
* - EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM : does not support separate windows for nonprefetchable and prefetchable memory.
* - EFI_PCI_HOST_BRIDGE_MEM64_DECODE : supports 64-bit memory windows
**/
EFI_STATUS
PciHbRaGetAllocAttributes (
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
IN EFI_HANDLE RootBridgeHandle,
OUT UINT64 *Attributes
)
{
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_TRACE ("PciHbRaGetAllocAttributes()");
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
// Check if the RootBridgeHandle is the one managed by this PCI Host Bridge
ASSERT (HostBridgeInstance->RootBridge != NULL);
if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
return EFI_INVALID_PARAMETER;
}
*Attributes = HostBridgeInstance->RootBridge->MemAllocAttributes;
return EFI_SUCCESS;
}
EFI_STATUS
PciHbRaStartBusEnumeration (
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
IN EFI_HANDLE RootBridgeHandle,
OUT VOID **Configuration
)
{
VOID *Buffer;
UINT8 *Ptr;
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
// Fill an ACPI descriptor table with the Bus Number Range. This information will be used by the PCI Bus driver
// to set bus numbers to PCI-to-PCI bridge.
PCI_TRACE ("PciHbRaStartBusEnumeration()");
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
Buffer = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Ptr = (UINT8 *)Buffer;
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; // QWORD Address space Descriptor
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Len = 0x2B; // Length of this descriptor in bytes not including the first two fields
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS; // Resource Type Bus Number Range
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->GenFlag = 0;
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->SpecificFlag = 0;
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrSpaceGranularity = 0;
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin = HostBridgeInstance->RootBridge->BusStart; // Bus Start
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMax = 0; // Bus Max
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrTranslationOffset = 0;
((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
Ptr = Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
*Configuration = Buffer;
return EFI_SUCCESS;
}
EFI_STATUS
PciHbRaSetBusNumbers (
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
IN EFI_HANDLE RootBridgeHandle,
IN VOID *Configuration
)
{
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
UINT8 *Ptr;
UINTN BusStart;
UINTN BusEnd;
UINTN BusLen;
PCI_TRACE ("PciHbRaSetBusNumbers()");
Ptr = Configuration;
if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
return EFI_INVALID_PARAMETER;
}
// Check if the passed ACPI descriptor table define a Bus Number Range
if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {
return EFI_INVALID_PARAMETER;
}
// Check if the Configuration only passed one ACPI Descriptor (+ End Descriptor)
if (*((UINT8*)(Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR))) != ACPI_END_TAG_DESCRIPTOR) {
return EFI_INVALID_PARAMETER;
}
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
ASSERT (HostBridgeInstance->RootBridge != NULL);
if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
return EFI_INVALID_PARAMETER;
}
BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
BusEnd = BusStart + BusLen - 1;
ASSERT (BusStart <= BusEnd); // We should at least have PCI_BUS_ROOT and PCI_SWITCH_BUS
ASSERT ((BusStart >= HostBridgeInstance->RootBridge->BusStart) && (BusLen <= HostBridgeInstance->RootBridge->BusLength));
HostBridgeInstance->RootBridge->BusStart = BusStart;
HostBridgeInstance->RootBridge->BusLength = BusLen;
return EFI_SUCCESS;
}
/**
* This function is used to submit all the I/O and memory resources that are required by the specified
* PCI root bridge.
**/
EFI_STATUS
PciHbRaSubmitResources (
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
IN EFI_HANDLE RootBridgeHandle,
IN VOID *Configuration
)
{
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
UINT8 *Ptr;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
PCI_RESOURCE_TYPE ResType;
PCI_TRACE ("PciHbRaSubmitResources()");
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
if (Configuration == NULL) {
return EFI_INVALID_PARAMETER;
}
// Check if the ACPI Descriptor tables is conformed
Ptr = (UINT8 *)Configuration;
while (*Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // QWORD Address Space descriptor
Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
}
if (*Ptr != ACPI_END_TAG_DESCRIPTOR) { // End tag
return EFI_INVALID_PARAMETER;
}
// Check the RootBridgeHandle
RootBridgeInstance = HostBridgeInstance->RootBridge;
ASSERT (RootBridgeInstance != NULL);
if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
return EFI_INVALID_PARAMETER;
}
Ptr = (UINT8 *)Configuration;
while ( *Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // While the entry is an ACPI Descriptor Table
Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
// Check if the description is valid
if (Desc->AddrLen > 0xffffffff) {
return EFI_INVALID_PARAMETER;
}
if ((Desc->AddrRangeMax >= 0xffffffff) || (Desc->AddrRangeMax != (GetPowerOfTwo64 (Desc->AddrRangeMax + 1) - 1))) {
return EFI_INVALID_PARAMETER;
}
switch (Desc->ResType) {
case ACPI_ADDRESS_SPACE_TYPE_MEM:
// Check invalid Address Space Granularity
if ((Desc->AddrSpaceGranularity != 32) && (Desc->AddrSpaceGranularity != 64)) {
return EFI_INVALID_PARAMETER;
}
// check the memory resource request is supported by PCI root bridge
if (RootBridgeInstance->MemAllocAttributes == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM && Desc->SpecificFlag == 0x06) {
return EFI_INVALID_PARAMETER;
}
if (Desc->AddrSpaceGranularity == 32) {
if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
ResType = ResTypePMem32;
} else {
ResType = ResTypeMem32;
}
} else {
if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
ResType = ResTypePMem64;
} else {
ResType = ResTypeMem64;
}
}
RootBridgeInstance->ResAlloc[ResType].Length = Desc->AddrLen;
RootBridgeInstance->ResAlloc[ResType].Alignment = Desc->AddrRangeMax;
RootBridgeInstance->ResAlloc[ResType].Base = Desc->AddrRangeMin;
break;
case ACPI_ADDRESS_SPACE_TYPE_IO:
RootBridgeInstance->ResAlloc[ResTypeIo].Length = Desc->AddrLen;
RootBridgeInstance->ResAlloc[ResTypeIo].Alignment = Desc->AddrRangeMax;
RootBridgeInstance->ResAlloc[ResTypeIo].Base = 0;
break;
default:
ASSERT (0); // Could be the case Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS
break;
}
Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
}
return EFI_SUCCESS;
}
/** Returns the proposed resource settings for the specified PCI root bridge. The resources have been submitted by
* PciHbRaSubmitResources() before
**/
EFI_STATUS
PciHbRaGetProposedResources (
IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
IN EFI_HANDLE RootBridgeHandle,
OUT VOID **Configuration
)
{
PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
UINT32 i;
UINT32 ResAllocCount;
VOID *Buffer;
UINT8 *Ptr;
EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
PCI_TRACE ("PciHbRaGetProposedResources()");
HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
// Check the RootBridgeHandle
RootBridgeInstance = HostBridgeInstance->RootBridge;
ASSERT (RootBridgeInstance != NULL);
if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
return EFI_INVALID_PARAMETER;
}
// Count the number of Resource Allocated for this Root Bridge
ResAllocCount = 0;
for (i = 0; i < ResTypeMax; i++) {
if (RootBridgeInstance->ResAlloc[i].Length != 0) ResAllocCount++;
}
if (ResAllocCount == 0) {
return EFI_INVALID_PARAMETER;
}
Buffer = AllocateZeroPool (ResAllocCount * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
if (Buffer == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Ptr = Buffer;
for (i = 0; i < ResTypeMax; i++) {
if (RootBridgeInstance->ResAlloc[i].Length != 0) { // Base != 0 if the resource has been allocated
Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
Desc->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
Desc->Len = 0x2B;
Desc->GenFlag = 0;
Desc->AddrRangeMax = 0;
switch (i) {
case ResTypeIo:
Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
Desc->SpecificFlag = 0;
Desc->AddrSpaceGranularity = 0;
break;
case ResTypeMem32:
Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
Desc->SpecificFlag = 0;
Desc->AddrSpaceGranularity = 32;
break;
case ResTypePMem32:
Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE;
Desc->AddrSpaceGranularity = 32;
break;
case ResTypeMem64:
Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
Desc->SpecificFlag = 0;
Desc->AddrSpaceGranularity = 64;
break;
case ResTypePMem64:
Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE;
Desc->AddrSpaceGranularity = 64;
break;
}
Desc->AddrRangeMin = RootBridgeInstance->ResAlloc[i].Base;
Desc->AddrTranslationOffset = (RootBridgeInstance->ResAlloc[i].Base != 0) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
Desc->AddrLen = RootBridgeInstance->ResAlloc[i].Length;
Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
}
}
((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
*Configuration = Buffer;
return EFI_SUCCESS;
}
EFI_STATUS
PciHbRaPreprocessController (
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
)
{
PCI_HOST_BRIDGE_INSTANCE* HostBridge;
PCI_ROOT_BRIDGE_INSTANCE* RootBridge;
UINT32 CapabilityPtr;
UINT32 CapabilityEntry;
UINT16 CapabilityID;
UINT32 DeviceCapability;
PCI_TRACE ("PciHbRaPreprocessController()");
if (FeaturePcdGet (PcdPciMaxPayloadFixup)) {
// Do Max payload fixup for every devices
if (Phase == EfiPciBeforeResourceCollection) {
// Get RootBridge Instance from Host Bridge Instance
HostBridge = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
RootBridge = HostBridge->RootBridge;
// Get the first PCI Capability
CapabilityPtr = PCI_CAPBILITY_POINTER_OFFSET;
RootBridge->Io.Pci.Read (
&RootBridge->Io,
EfiPciWidthUint8,
EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
1,
&CapabilityPtr
);
CapabilityPtr &= 0x1FF;
// Get Pci Express Capability
while (CapabilityPtr != 0) {
RootBridge->Io.Pci.Read (
&RootBridge->Io,
EfiPciWidthUint16,
EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
1,
&CapabilityEntry
);
CapabilityID = (UINT8)CapabilityEntry;
// Is PCIe capability ?
if (CapabilityID == EFI_PCI_CAPABILITY_ID_PCIEXP) {
// Get PCIe Device Capabilities
RootBridge->Io.Pci.Read (
&RootBridge->Io,
EfiPciWidthUint32,
EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
1,
&DeviceCapability
);
// Force the Max Payload to 128 Bytes (128 Bytes Max Payload Size = 0)
DeviceCapability &= ~ ((UINT32)(0x7 << 5 ));
// Max Read Request Size to 128 Bytes (128 Bytes Max Read Request Size = 0)
DeviceCapability &= ~ ((UINT32)(0x7 << 12));
// Enable all error reporting
DeviceCapability |= 0xF;
RootBridge->Io.Pci.Write (
&RootBridge->Io,
EfiPciWidthUint32,
EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
1,
&DeviceCapability
);
return EFI_SUCCESS;
}
CapabilityPtr = (CapabilityEntry >> 8) & 0xFF;
}
}
}
return EFI_SUCCESS;
}