/** @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; }