mirror of https://github.com/acidanthera/audk.git
643 lines
24 KiB
C
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;
|
|
}
|