summaryrefslogtreecommitdiff
path: root/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c
diff options
context:
space:
mode:
Diffstat (limited to 'ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c')
-rw-r--r--ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c642
1 files changed, 642 insertions, 0 deletions
diff --git a/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c
new file mode 100644
index 0000000000..de60db7184
--- /dev/null
+++ b/ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c
@@ -0,0 +1,642 @@
+/** @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;
+}