1002 lines
45 KiB
C
1002 lines
45 KiB
C
/** @file
|
|
Provide OEM to get the HotPlugBridgeInfo table.
|
|
|
|
;******************************************************************************
|
|
;* Copyright (c) 2014 - 2020, Insyde Software Corp. All Rights Reserved.
|
|
;*
|
|
;* You may not reproduce, distribute, publish, display, perform, modify, adapt,
|
|
;* transmit, broadcast, present, recite, release, license or otherwise exploit
|
|
;* any part of this publication in any form, by any means, without the prior
|
|
;* written permission of Insyde Software Corporation.
|
|
;*
|
|
;******************************************************************************
|
|
*/
|
|
|
|
#include <Library/DxeOemSvcKernelLib.h>
|
|
#include <ChipsetSetupConfig.h>
|
|
#include <Protocol/SetupUtility.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <OemThunderbolt.h>
|
|
#include <PiDxe.h>
|
|
#include <Include/Guid/HobList.h>
|
|
#include <Include/Library/HobLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/VariableLib.h>
|
|
#include <ITbtInfoHob.h>
|
|
#include <DTbtInfoHob.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <SetupVariable.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Protocol/ITbtPolicy.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/TbtCommonLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Protocol/ITbtPolicy.h>
|
|
#include <Protocol/DxeDTbtPolicy.h>
|
|
//#include <Register/SaRegsItbtPcie.h>
|
|
#include <Library/PchInfoLib.h>
|
|
#include <Library/PchPcieRpLib.h>
|
|
#include <Library/CpuPcieInfoFruLib.h>
|
|
#include <Library/CpuPcieRpLib.h>
|
|
#include <PcieRegs.h>
|
|
#include <Register/CpuPcieRegs.h>
|
|
#include <Guid/H2OCp.h>
|
|
#include <Library/H2OCpLib.h>
|
|
#include <Library/PciSegmentLib.h>
|
|
#include <Library/PcieHelperLib.h>
|
|
#include <Library/DevicePathLib.h>
|
|
|
|
#define DTBT_CONTROLLER 0x00
|
|
#define ITBT_CONTROLLER 0x80
|
|
|
|
#define DTBT_TYPE_PCH 0x01
|
|
#define DTBT_TYPE_PEG 0x02
|
|
#define DTBT_SMI_HANDLER_NUMBER 0xF7
|
|
|
|
#define MAX_P2PB_OF_TBT_DAISY_CHAIN ((MAX_DTBT_CONTROLLER_NUMBER + MAX_ITBT_PCIE_PORT) * 64)
|
|
#define PCI_ROOT_0_STRING L"PciRoot(0x0)"
|
|
#define PCI_ROOT_1_STRING L"PciRoot(0x1)"
|
|
|
|
typedef struct {
|
|
EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath;
|
|
UINT64 HpcPciAddress; // Bit[15:8]:Function, Bit[23:16]:Device, Bit[31:24]:Bus, Bit[32]:Segment
|
|
UINT8 RsvdExtraBusNum;
|
|
UINT16 RsvdPcieMegaMem;
|
|
UINT8 PcieMemAddrRngMax;
|
|
UINT16 RsvdPciePMegaMem;
|
|
UINT8 PciePMemAddrRngMax;
|
|
UINT8 RsvdPcieKiloIo;
|
|
} P2PB_RESOURCE_RECORD;
|
|
|
|
typedef struct {
|
|
UINT8 P2pbSegNum;
|
|
UINT8 P2pbBusNum;
|
|
UINT8 P2pbLastDevNum;
|
|
UINT8 NumOfP2pbHotPlug;
|
|
UINT8 NumOfP2pbNonHotPlug;
|
|
} NUMBER_OF_HOTPLUG_BRIDGE;
|
|
|
|
GLOBAL_REMOVE_IF_UNREFERENCED P2PB_RESOURCE_RECORD mP2pbResourceRecord[MAX_P2PB_OF_TBT_DAISY_CHAIN];
|
|
GLOBAL_REMOVE_IF_UNREFERENCED UINT8 mP2pbResourceRecordCount = 0;
|
|
// Record the number of HotPlug capability Bridge on the same Bus.
|
|
GLOBAL_REMOVE_IF_UNREFERENCED NUMBER_OF_HOTPLUG_BRIDGE mNumOfHotPlugBridge[MAX_P2PB_OF_TBT_DAISY_CHAIN];
|
|
|
|
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mRemainderBus = 0;
|
|
|
|
BOOLEAN mEnableAbove4GBMmio = FALSE;
|
|
//TBT_INFO_HOB *gTbtInfoHob;
|
|
|
|
//
|
|
// Please base on your project to fill this table.
|
|
// 1. If your Pcie devices/slots do not support Hotplug, Please disable it by setup variable PcieRootPortHPE[Index]
|
|
// 2. Alderlake S support Port1-Port28
|
|
// Alderlake P support Port1-Port12
|
|
// Alderlake M support Port1-Port10
|
|
// 3. Current CRB BIOS set PcieRootPortHPE[0] - PcieRootPortHPE[20] disabled as default
|
|
//
|
|
HOT_PLUG_BRIDGE_INFO HotPlugBridgeInfo [] = {
|
|
// NodeUID, DevNum, FuncNum, ReservedBusCount, ReservedIoRange, ReservedNonPrefetchableMmio, AlignemntOfReservedNonPrefetchableMmio, ReservedPrefetchableMmio, AlignemntOfReservedPrefetchableMmio
|
|
{ 0x00, 0x1C, 0, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F0 PCI Express* Root Port #1
|
|
{ 0x00, 0x1C, 1, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F1 PCI Express* Root Port #2
|
|
{ 0x00, 0x1C, 2, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F2 PCI Express* Root Port #3
|
|
{ 0x00, 0x1C, 3, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F3 PCI Express* Root Port #4
|
|
{ 0x00, 0x1C, 4, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F4 PCI Express* Root Port #5
|
|
{ 0x00, 0x1C, 5, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F5 PCI Express* Root Port #6
|
|
{ 0x00, 0x1C, 6, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F6 PCI Express* Root Port #7
|
|
{ 0x00, 0x1C, 7, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D28/F7 PCI Express* Root Port #8
|
|
{ 0x00, 0x1D, 0, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F0 PCI Express* Root Port #9
|
|
{ 0x00, 0x1D, 1, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F1 PCI Express* Root Port #10
|
|
{ 0x00, 0x1D, 2, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F2 PCI Express* Root Port #11
|
|
{ 0x00, 0x1D, 3, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D29/F3 PCI Express* Root Port #12
|
|
{ 0x00, 0x01, 0, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D01/F0 PCIe RC 010 G5
|
|
{ 0x00, 0x06, 0, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D06/F0 PCIe RC 060 (x4) G4
|
|
{ 0x00, 0x06, 2, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D06/F2 PCIe RC 062 (x4) G4
|
|
{ 0x00, 0x07, 0, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D07/F0 TBT PCIe0
|
|
{ 0x00, 0x07, 1, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D07/F1 TBT PCIe1
|
|
{ 0x00, 0x07, 2, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D07/F2 TBT PCIe2
|
|
{ 0x00, 0x07, 3, 5, 0x1000, 0x1000000, 0x1000000, 0x1000000, 0x1000000}, // D07/F3 TBT PCIe3
|
|
{ END_OF_TABLE, 0, 0, 0, 0, 0, 0, 0, 0}, //End of Table, Cannot be removed.
|
|
};
|
|
|
|
/**
|
|
Get resource padding information from record.
|
|
|
|
@param[in] Event A pointer to the Event that triggered the callback.
|
|
@param[in] Handle Checkpoint handle.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PciHpcGetResourcePaddingCallback (
|
|
IN EFI_EVENT Event,
|
|
IN H2O_CP_HANDLE Handle
|
|
);
|
|
|
|
/**
|
|
Dump HotPlugBridgeInfo table for debug purpose.
|
|
**/
|
|
VOID
|
|
DumpHotPlugBridgeInfo (
|
|
VOID
|
|
)
|
|
{
|
|
UINT16 Index;
|
|
|
|
DEBUG ((DEBUG_INFO, "\nDump HotPlugBridgeInfo table:\n"));
|
|
DEBUG ((DEBUG_INFO, "NodeUID DevNum FuncNum BusCount IoRange NonPrefetchableMmio AlignemntOfNonPrefetchableMmio PrefetchableMmio AlignemntOfPrefetchableMmio\n"));
|
|
|
|
for (Index = 0; HotPlugBridgeInfo[Index].NodeUID != END_OF_TABLE; Index++) {
|
|
DEBUG ((DEBUG_INFO, "0x%02X 0x%02X 0x%02X 0x%02X 0x%04X",\
|
|
HotPlugBridgeInfo[Index].NodeUID,\
|
|
HotPlugBridgeInfo[Index].DevNum,\
|
|
HotPlugBridgeInfo[Index].FuncNum,\
|
|
HotPlugBridgeInfo[Index].ReservedBusCount,\
|
|
HotPlugBridgeInfo[Index].ReservedIoRange));
|
|
DEBUG ((DEBUG_INFO, " 0x%016llX", HotPlugBridgeInfo[Index].ReservedNonPrefetchableMmio));
|
|
DEBUG ((DEBUG_INFO, " 0x%016llX", HotPlugBridgeInfo[Index].AlignemntOfReservedNonPrefetchableMmio));
|
|
DEBUG ((DEBUG_INFO, " 0x%016llX", HotPlugBridgeInfo[Index].ReservedPrefetchableMmio));
|
|
DEBUG ((DEBUG_INFO, " 0x%016llX\n", HotPlugBridgeInfo[Index].AlignemntOfReservedPrefetchableMmio));
|
|
}
|
|
}
|
|
|
|
/**
|
|
Provide OEM to get the HotPlugBridgeInfo table.
|
|
This table contains the hot plug bridge address info and defines reserved BUS, I/O and memory range for bridge device.
|
|
|
|
@param[out] *HotPlugBridgeInfoTable Point to HOT_PLUG_BRIDGE_INFO Table
|
|
|
|
@retval EFI_MEDIA_CHANGED Get hot plug bridge info success.
|
|
@retval Others Depends on customization.
|
|
**/
|
|
EFI_STATUS
|
|
OemSvcGetHotplugBridgeInfo (
|
|
OUT HOT_PLUG_BRIDGE_INFO **HotPlugBridgeInfoTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
SETUP_DATA *SystemConfiguration = NULL;
|
|
CHIPSET_CONFIGURATION *ChipsetConfiguration = NULL;
|
|
UINT8 Index;
|
|
PCH_SETUP *PchSetup = NULL;
|
|
SA_SETUP SaSetup;
|
|
UINTN VariableSize;
|
|
UINTN SaVariableSize;
|
|
UINTN RpDevice;
|
|
UINTN RpFunction;
|
|
DTBT_INFO_HOB *DTbtInfoHob = NULL;
|
|
UINT8 Rootportselected = 0;
|
|
ITBT_POLICY_PROTOCOL *ITbtPolicy;
|
|
DXE_ITBT_CONFIG *DxeITbtConfig;
|
|
DXE_DTBT_POLICY_PROTOCOL *DxeDTbtConfig;
|
|
UINT64 RpBase;
|
|
H2O_CP_HANDLE CpGetResourcePaddingHandle;
|
|
|
|
ITbtPolicy = NULL;
|
|
DxeITbtConfig = NULL;
|
|
DxeDTbtConfig = NULL;
|
|
RpBase = 0;
|
|
|
|
if (PcdGetBool(PcdITbtEnable)) {
|
|
Status = gBS->LocateProtocol (&gITbtPolicyProtocolGuid, NULL, (VOID **) &ITbtPolicy);
|
|
ASSERT_EFI_ERROR (Status);
|
|
Status = GetConfigBlock ((VOID *) ITbtPolicy, &gDxeITbtConfigGuid, (VOID *)&DxeITbtConfig);
|
|
ASSERT_EFI_ERROR (Status);
|
|
}
|
|
|
|
VariableSize = sizeof (PCH_SETUP);
|
|
PchSetup = AllocateZeroPool (VariableSize);
|
|
if (PchSetup == NULL) {
|
|
return EFI_OUT_OF_RESOURCES;
|
|
}
|
|
|
|
if (PcdGetBool(PcdDTbtEnable)) {
|
|
Status = gBS->LocateProtocol (
|
|
&gDxeDTbtPolicyProtocolGuid,
|
|
NULL,
|
|
(VOID **) &DxeDTbtConfig
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, " gDxeDTbtPolicyProtocolGuid Not installed!!!\n"));
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
Status = gRT->GetVariable (
|
|
PCH_SETUP_VARIABLE_NAME,
|
|
&gPchSetupVariableGuid,
|
|
NULL,
|
|
&VariableSize,
|
|
PchSetup
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool (PchSetup);
|
|
return Status;
|
|
}
|
|
SaVariableSize = sizeof (SA_SETUP);
|
|
Status = gRT->GetVariable (
|
|
SA_SETUP_VARIABLE_NAME,
|
|
&gSaSetupVariableGuid,
|
|
NULL,
|
|
&SaVariableSize,
|
|
&SaSetup
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
FreePool (PchSetup);
|
|
return Status;
|
|
}
|
|
|
|
mEnableAbove4GBMmio = SaSetup.EnableAbove4GBMmio;
|
|
if (PcdGetBool (PcdH2ODxeCpPciHpcGetResourcePaddingSupported)) {
|
|
Status = H2OCpRegisterHandler (
|
|
&gH2ODxeCpPciHpcGetResourcePaddingGuid,
|
|
PciHpcGetResourcePaddingCallback,
|
|
H2O_CP_MEDIUM_HIGH,
|
|
&CpGetResourcePaddingHandle
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "Checkpoint Register Fail: %g (%r)\n", &gH2ODxeCpPciHpcGetResourcePaddingGuid, Status));
|
|
}
|
|
DEBUG ((EFI_D_INFO, "Checkpoint Registered: %g (%r)\n", &gH2ODxeCpPciHpcGetResourcePaddingGuid, Status));
|
|
}
|
|
|
|
//
|
|
// Get NVRAM data
|
|
//
|
|
SystemConfiguration = CommonGetVariableData (PLATFORM_SETUP_VARIABLE_NAME, &gSetupVariableGuid);
|
|
ChipsetConfiguration = CommonGetVariableData (SETUP_VARIABLE_NAME, &gSystemConfigurationGuid);
|
|
|
|
if ((SystemConfiguration != NULL) && (ChipsetConfiguration != NULL)) {
|
|
for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
|
|
//
|
|
// The max number of PCH root ports will different by PCH type.
|
|
// PCH_P : 12
|
|
// PCH_M : 10
|
|
// PCH_S : 28
|
|
//
|
|
if (Index >= GetPchMaxPciePortNum ()) {
|
|
continue;
|
|
}
|
|
//
|
|
// Get correct Device and Function number for root port.
|
|
//
|
|
Status = GetPchPcieRpDevFun (Index, &RpDevice, &RpFunction);
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
//
|
|
// Update Device and Function number to HotPlugBridgeInfo table.
|
|
//
|
|
HotPlugBridgeInfo[Index].DevNum = (UINT8)RpDevice;
|
|
HotPlugBridgeInfo[Index].FuncNum = (UINT8)RpFunction;
|
|
|
|
//
|
|
// PCH Rootports Hotplug Capability Check.
|
|
//
|
|
RpBase = PchPcieBase (Index);
|
|
if (((PciSegmentRead32 (RpBase + R_PCIE_SLCAP) >> 6) & BIT0) != 1) {
|
|
HotPlugBridgeInfo[Index].NodeUID = IGNORE_DEVICE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// CPU Rootports.
|
|
//
|
|
for (Index = 0; Index < GetMaxCpuPciePortNum (); Index++) {
|
|
if (Index >= GetMaxCpuPciePortNum ()) {
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Get correct Device and Function number for root port.
|
|
//
|
|
Status = GetCpuPcieRpDevFun (Index, &RpDevice, &RpFunction);
|
|
|
|
//
|
|
// Update Device and Function number to HotPlugBridgeInfo table.
|
|
//
|
|
Rootportselected = GetPchMaxPciePortNum () + Index;
|
|
HotPlugBridgeInfo[Rootportselected].DevNum = (UINT8)RpDevice;
|
|
HotPlugBridgeInfo[Rootportselected].FuncNum = (UINT8)RpFunction;
|
|
|
|
//
|
|
// CPU Rootports Hotplug Capability Check.
|
|
//
|
|
RpBase = PCI_SEGMENT_LIB_ADDRESS (SA_SEG_NUM, SA_MC_BUS, (UINT32)RpDevice, (UINT32)RpFunction, 0);
|
|
if (((PciSegmentRead32 (RpBase + R_PCIE_CLIST + R_PCIE_SLCAP_OFFSET) >> 6) & BIT0) != 1) {
|
|
HotPlugBridgeInfo[Rootportselected].NodeUID = IGNORE_DEVICE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// iTBT Rootports Resource Update
|
|
//
|
|
if (PcdGetBool(PcdITbtEnable)) {
|
|
if (SystemConfiguration->IntegratedTbtSupport == 1) {
|
|
for (Index = 0; Index < MAX_ITBT_PCIE_PORT; Index++) {
|
|
//
|
|
// Check if Controller is set to AUTO and Enabled by default.
|
|
//
|
|
Rootportselected = GetPchMaxPciePortNum () + GetMaxCpuPciePortNum () + Index;
|
|
if (SystemConfiguration->ITbtRootPort[Index] == 0x01) {
|
|
//
|
|
// Get the Exact Root port number corresponding to the Controller Selected
|
|
//
|
|
HotPlugBridgeInfo[Rootportselected].ReservedBusCount = DxeITbtConfig->ITbtResourceConfig[Index].TbtPcieExtraBusRsvd;
|
|
HotPlugBridgeInfo[Rootportselected].ReservedIoRange = 0;
|
|
HotPlugBridgeInfo[Rootportselected].ReservedNonPrefetchableMmio = LShiftU64 (DxeITbtConfig->ITbtResourceConfig[Index].TbtPcieMemRsvd, 20);
|
|
HotPlugBridgeInfo[Rootportselected].ReservedPrefetchableMmio = LShiftU64 (DxeITbtConfig->ITbtResourceConfig[Index].TbtPciePMemRsvd, 20);
|
|
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedNonPrefetchableMmio = LShiftU64 (1, DxeITbtConfig->ITbtResourceConfig[Index].TbtPcieMemAddrRngMax);
|
|
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedPrefetchableMmio = LShiftU64 (1, DxeITbtConfig->ITbtResourceConfig[Index].TbtPciePMemAddrRngMax);
|
|
} else {
|
|
HotPlugBridgeInfo[Rootportselected].ReservedBusCount = 0;
|
|
HotPlugBridgeInfo[Rootportselected].ReservedIoRange = 0;
|
|
HotPlugBridgeInfo[Rootportselected].ReservedNonPrefetchableMmio = 0;
|
|
HotPlugBridgeInfo[Rootportselected].ReservedPrefetchableMmio = 0;
|
|
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedNonPrefetchableMmio = 0;
|
|
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedPrefetchableMmio = 0;
|
|
}
|
|
} // for loop
|
|
}
|
|
}
|
|
|
|
//[-start-190611-IB16990047-add]//
|
|
//
|
|
// dTBT Rootports Resource Update
|
|
//
|
|
if (PcdGetBool(PcdDTbtEnable)) {
|
|
if (SystemConfiguration->DiscreteTbtSupport == 1) {
|
|
DTbtInfoHob = (DTBT_INFO_HOB *) GetFirstGuidHob (&gDTbtInfoHobGuid);
|
|
if (DTbtInfoHob == NULL) {
|
|
DEBUG ((DEBUG_INFO, "TbtInfoHob not found\n"));
|
|
ASSERT (FALSE);
|
|
} else {
|
|
|
|
for (Index = 0; Index < MAX_DTBT_CONTROLLER_NUMBER; Index++) {
|
|
if (DTbtInfoHob->DTbtControllerConfig[Index].DTbtControllerEn == 0x01) {
|
|
//
|
|
// Check if Root Index is for PCH PCIe or PEG
|
|
//
|
|
if (DTbtInfoHob->DTbtControllerConfig[Index].Type == (DTBT_CONTROLLER + DTBT_TYPE_PCH)) {
|
|
//
|
|
// Get the Exact Root port number corresponding to the Controller Selected
|
|
//
|
|
Rootportselected = (DTbtInfoHob->DTbtControllerConfig[Index].PcieRpNumber - 1);
|
|
} else if (DTbtInfoHob->DTbtControllerConfig[Index].Type == (DTBT_CONTROLLER + DTBT_TYPE_PEG)) {
|
|
Rootportselected = GetPchMaxPciePortNum () + Index;
|
|
} else {
|
|
continue;
|
|
}// Type
|
|
|
|
HotPlugBridgeInfo[Rootportselected].ReservedBusCount = DxeDTbtConfig->DTbtResourceConfig[Index].TbtPcieExtraBusRsvd;
|
|
HotPlugBridgeInfo[Rootportselected].ReservedIoRange = 0;
|
|
HotPlugBridgeInfo[Rootportselected].ReservedNonPrefetchableMmio = LShiftU64 (DxeDTbtConfig->DTbtResourceConfig[Index].TbtPcieMemRsvd, 20);
|
|
HotPlugBridgeInfo[Rootportselected].ReservedPrefetchableMmio = LShiftU64 (DxeDTbtConfig->DTbtResourceConfig[Index].TbtPciePMemRsvd, 20);
|
|
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedNonPrefetchableMmio = LShiftU64 (1, DxeDTbtConfig->DTbtResourceConfig[Index].TbtPcieMemAddrRngMax);
|
|
HotPlugBridgeInfo[Rootportselected].AlignemntOfReservedPrefetchableMmio = LShiftU64 (1, DxeDTbtConfig->DTbtResourceConfig[Index].TbtPciePMemAddrRngMax);
|
|
}
|
|
} // for loop
|
|
}
|
|
}
|
|
}
|
|
//[-end-190611-IB16990047-add]//
|
|
|
|
gBS->FreePool (SystemConfiguration);
|
|
gBS->FreePool (ChipsetConfiguration);
|
|
}
|
|
|
|
#ifdef EFI_DEBUG
|
|
//
|
|
// Dump HotPlugBridgeInfo table for debug purpose.
|
|
//
|
|
DumpHotPlugBridgeInfo ();
|
|
#endif
|
|
|
|
*HotPlugBridgeInfoTable = HotPlugBridgeInfo;
|
|
if (PchSetup != NULL) {
|
|
FreePool (PchSetup);
|
|
}
|
|
return EFI_MEDIA_CHANGED;
|
|
}
|
|
|
|
|
|
/**
|
|
Get the Parent Pci Address
|
|
|
|
@param[in] Segment Segment Number
|
|
@param[in] CurrentRpBus P2P Bridge Bus Number
|
|
|
|
@retval ParentP2PBridgeBase Parent Pci Address
|
|
**/
|
|
UINT64
|
|
GetParentPciAddress (
|
|
IN UINT8 Segment,
|
|
IN UINT64 CurrentRpBus
|
|
)
|
|
{
|
|
UINT16 ParentRpBus;
|
|
UINT8 ParentRpDev;
|
|
UINT8 ParentRpFunc;
|
|
UINT64 ParentP2PBridgeBase;
|
|
UINT8 BaseClass;
|
|
UINT8 SubClass;
|
|
UINT8 CapHeaderOffset;
|
|
PCI_REG_PCIE_CAPABILITY PcieCap;
|
|
|
|
ParentRpBus = 0;
|
|
ParentRpDev = 0;
|
|
ParentRpFunc = 0;
|
|
|
|
for (ParentRpBus = 0; ParentRpBus <= 0xFF; ++ParentRpBus) {
|
|
for (ParentRpDev = 0; ParentRpDev <= PCI_MAX_DEVICE; ++ParentRpDev) {
|
|
for (ParentRpFunc = 0; ParentRpFunc <= PCI_MAX_FUNC; ++ParentRpFunc) {
|
|
ParentP2PBridgeBase = PCI_SEGMENT_LIB_ADDRESS (Segment, ParentRpBus, ParentRpDev, ParentRpFunc, 0);
|
|
if (PciSegmentRead16 (ParentP2PBridgeBase + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
|
|
if (ParentRpFunc == 0) {
|
|
//
|
|
// IF Fun is zero, stop enumerating other functions of the particular bridge
|
|
//
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
BaseClass = PciSegmentRead8 (ParentP2PBridgeBase + PCI_CLASSCODE_OFFSET + 2);
|
|
if (BaseClass == PCI_CLASS_BRIDGE) {
|
|
SubClass = PciSegmentRead8 (ParentP2PBridgeBase + PCI_CLASSCODE_OFFSET + 1);
|
|
if (SubClass == PCI_CLASS_BRIDGE_P2P) {
|
|
CapHeaderOffset = PcieFindCapId (Segment, (UINT8)ParentRpBus, ParentRpDev, ParentRpFunc, EFI_PCI_CAPABILITY_ID_PCIEXP);
|
|
PciSegmentReadBuffer (ParentP2PBridgeBase + CapHeaderOffset + OFFSET_OF (PCI_CAPABILITY_PCIEXP, Capability), sizeof (UINT16), &PcieCap);
|
|
if (PcieCap.Bits.DevicePortType == PCIE_DEVICE_PORT_TYPE_PCIE_ENDPOINT) {
|
|
continue;
|
|
}
|
|
if (PciSegmentRead8 (ParentP2PBridgeBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET) == CurrentRpBus) {
|
|
if (PcieCap.Bits.DevicePortType == PCIE_DEVICE_PORT_TYPE_UPSTREAM_PORT) {
|
|
//
|
|
// If the parent is a UPSTREAM_PORT, then it must inherit all resource from grand parent
|
|
// And since UPSTREAM_PORT is not a HotPlug P2PB, so check the resoruce from grand parent.
|
|
//
|
|
ParentP2PBridgeBase = GetParentPciAddress (Segment, ParentRpBus);
|
|
return ParentP2PBridgeBase;
|
|
}
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Exit:
|
|
DEBUG ((DEBUG_INFO, "Parent P2PB is Segment 0x%x, Bus 0x%x, Device 0x%x, Function 0x%x \n", Segment, ParentRpBus, ParentRpDev, ParentRpFunc));
|
|
DEBUG ((DEBUG_INFO, "PcieCap.Bits.DevicePortType = 0x%x \n", PcieCap.Bits.DevicePortType));
|
|
ParentP2PBridgeBase = (((UINT64)Segment << 32) | ((UINT64)ParentRpBus << 24) | ((UINT64)ParentRpDev << 16) | ((UINT64)ParentRpFunc << 8));
|
|
return ParentP2PBridgeBase;
|
|
}
|
|
|
|
/**
|
|
Get the Parent Resource
|
|
|
|
@param[in] HpcPciAddress The address of the Hot Plug Controller function on the PCI bus.
|
|
@param[out] ParentBusNum Parent Reserved Bus resource Number.
|
|
@param[out] ParentPcieMegaMem Parent Reserved Alignment of MEM resource.
|
|
@param[out] ParentPciePMegaMem Parent Reserved Alignment of PMEM resource.
|
|
@param[out] ParentPcieKiloIo Parent Reserved Pcie Kilo Io Number.
|
|
|
|
@retval EFI_SUCCESS.
|
|
**/
|
|
EFI_STATUS
|
|
GetParentResourceSize (
|
|
IN UINT64 HpcPciAddress,
|
|
OUT UINT8 *ParentBusNum,
|
|
OUT UINT16 *ParentPcieMegaMem,
|
|
OUT UINT16 *ParentPciePMegaMem,
|
|
OUT UINT8 *ParentPcieKiloIo
|
|
)
|
|
{
|
|
UINT16 Index;
|
|
UINTN RpBus;
|
|
UINTN RpDev;
|
|
UINTN RpFunc;
|
|
|
|
RpBus = (UINTN) ((HpcPciAddress >> 24) & 0xFF);
|
|
RpDev = (UINTN) ((HpcPciAddress >> 16) & 0xFF);
|
|
RpFunc = (UINTN) ((HpcPciAddress >> 8) & 0xFF);
|
|
|
|
DEBUG ((DEBUG_INFO, "[GetParentResourceSize] Segment 0x%x, Bus 0x%x, Device 0x%x, Function 0x%x \n", ((HpcPciAddress >> 32) & 0x01), RpBus, RpDev, RpFunc));
|
|
|
|
for (Index = 0; Index < MAX_P2PB_OF_TBT_DAISY_CHAIN; Index++) {
|
|
if (mP2pbResourceRecord[Index].HpcPciAddress == 0) {
|
|
continue;
|
|
}
|
|
if ((UINT64)HpcPciAddress == (UINT64)mP2pbResourceRecord[Index].HpcPciAddress) {
|
|
*ParentBusNum = mP2pbResourceRecord[Index].RsvdExtraBusNum;
|
|
*ParentPcieMegaMem = mP2pbResourceRecord[Index].RsvdPcieMegaMem;
|
|
*ParentPciePMegaMem = mP2pbResourceRecord[Index].RsvdPciePMegaMem;
|
|
*ParentPcieKiloIo = mP2pbResourceRecord[Index].RsvdPcieKiloIo;
|
|
break;
|
|
}
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Check the HotPlug Capable of P2P bridge at the same Bus
|
|
|
|
@param[in] Segment Segment Number
|
|
@param[in] CurrentRpBus P2P Bridge Bus Number.
|
|
@param[out] *StrucIndex Indxe number of NUMBER_OF_HOTPLUG_BRIDGE struct.
|
|
|
|
@retval EFI_SUCCESS The function completed successfully
|
|
@retval EFI_INVALID_PARAMETER Invalid Bus number.
|
|
@retval EFI_ABORTED No matched P2P Bridge, exit without recorded.
|
|
**/
|
|
EFI_STATUS
|
|
GetCurrentBusP2pbHotPlug (
|
|
IN UINT8 Segment,
|
|
IN UINT8 CurrentRpBus,
|
|
OUT UINT8 *StrucIndex
|
|
)
|
|
{
|
|
UINT8 CurrentRpDev;
|
|
UINT8 CurrentRpFunc;
|
|
UINT64 CurrentP2PBridgeBase;
|
|
UINT8 BaseClass;
|
|
UINT8 SubClass;
|
|
UINT8 CapHeaderOffset;
|
|
UINT16 Index;
|
|
PCI_REG_PCIE_SLOT_CAPABILITY PcieSlotCap;
|
|
|
|
DEBUG ((DEBUG_INFO, "[GetCurrentBusP2pbHotPlug] Segment 0x%x, Bus 0x%x\n", Segment, CurrentRpBus));
|
|
if ((CurrentRpBus == 0) | (CurrentRpBus > 0xff)) {
|
|
DEBUG ((DEBUG_INFO, "Invalid Bus Number\n"));
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
for (Index = 0; Index <= 0xff; Index++) {
|
|
if (mNumOfHotPlugBridge[Index].P2pbBusNum == 0) {
|
|
for (CurrentRpDev = 0; CurrentRpDev <= PCI_MAX_DEVICE; ++CurrentRpDev) {
|
|
for (CurrentRpFunc = 0; CurrentRpFunc <= PCI_MAX_FUNC; ++CurrentRpFunc) {
|
|
CurrentP2PBridgeBase = PCI_SEGMENT_LIB_ADDRESS (Segment, CurrentRpBus, CurrentRpDev, CurrentRpFunc, 0);
|
|
if (PciSegmentRead16 (CurrentP2PBridgeBase + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
|
|
if (CurrentRpFunc == 0) {
|
|
//
|
|
// IF Fun is zero, stop enumerating other functions of the particular bridge
|
|
//
|
|
break;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
BaseClass = PciSegmentRead8 (CurrentP2PBridgeBase + PCI_CLASSCODE_OFFSET + 2);
|
|
if (BaseClass == PCI_CLASS_BRIDGE) {
|
|
SubClass = PciSegmentRead8 (CurrentP2PBridgeBase + PCI_CLASSCODE_OFFSET + 1);
|
|
if (SubClass == PCI_CLASS_BRIDGE_P2P) {
|
|
mNumOfHotPlugBridge[Index].P2pbSegNum = Segment;
|
|
mNumOfHotPlugBridge[Index].P2pbBusNum = CurrentRpBus;
|
|
// Check HotPlugCapable from PCI_CAPABILITY
|
|
CapHeaderOffset = PcieFindCapId (Segment, CurrentRpBus, CurrentRpDev, CurrentRpFunc, EFI_PCI_CAPABILITY_ID_PCIEXP);
|
|
PciSegmentReadBuffer (CurrentP2PBridgeBase + CapHeaderOffset + OFFSET_OF (PCI_CAPABILITY_PCIEXP, SlotCapability), sizeof (UINT16), &PcieSlotCap);
|
|
if (PcieSlotCap.Bits.HotPlugCapable) {
|
|
mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug += 1;
|
|
mNumOfHotPlugBridge[Index].P2pbLastDevNum = CurrentRpDev; // Record the last device number in the same layer of Bus
|
|
} else {
|
|
mNumOfHotPlugBridge[Index].NumOfP2pbNonHotPlug += 1;
|
|
}
|
|
*StrucIndex = (UINT8)Index;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DEBUG ((DEBUG_INFO, "Data structure Index: 0x%x, Number of P2PB with Hot-Plug: %x, Number of P2PB without Hot-Plug: %x\n", *StrucIndex, mNumOfHotPlugBridge[*StrucIndex].NumOfP2pbHotPlug, mNumOfHotPlugBridge[*StrucIndex].NumOfP2pbNonHotPlug));
|
|
return EFI_SUCCESS;
|
|
} else if ((mNumOfHotPlugBridge[Index].P2pbBusNum == CurrentRpBus) && (mNumOfHotPlugBridge[Index].P2pbSegNum == Segment)) {
|
|
*StrucIndex = (UINT8)Index;
|
|
DEBUG ((DEBUG_INFO, "The number of HotPlug Bridge of Bus already recorded in data structure Index: 0x%x\n", *StrucIndex));
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
return EFI_ABORTED;
|
|
}
|
|
|
|
/**
|
|
Calculate the number of Bus consumed by Root port, Upstream port and Downstream port.
|
|
|
|
@param[in] ParentPciAddress The address of the Parent device.
|
|
@param[in] CurrentPciAddress The address of the Current device.
|
|
@param[in, out] *ConsumedBusNumber Consumed Bus number.
|
|
|
|
@retval None
|
|
**/
|
|
VOID
|
|
CalculateBusConsumptionBeforeAssign (
|
|
IN UINT64 ParentPciAddress,
|
|
IN UINT64 CurrentPciAddress,
|
|
IN OUT UINT8 *ConsumedBusNumber
|
|
)
|
|
{
|
|
UINTN UpBus;
|
|
UINTN DpBus;
|
|
UINT8 Segment;
|
|
UINTN ParentRpBus;
|
|
UINTN ParentRpDev;
|
|
UINTN ParentRpFunc;
|
|
UINT64 ParentP2PBridgeBase;
|
|
|
|
UpBus = 0;
|
|
DpBus = 0;
|
|
Segment = (UINT8) ((ParentPciAddress >> 32) & 0x01);
|
|
ParentRpBus = (UINTN) ((ParentPciAddress >> 24) & 0xFF);
|
|
ParentRpDev = (UINTN) ((ParentPciAddress >> 16) & 0xFF);
|
|
ParentRpFunc = (UINTN) ((ParentPciAddress >> 8) & 0xFF);
|
|
|
|
ParentP2PBridgeBase = PCI_SEGMENT_LIB_ADDRESS (Segment, ParentRpBus, ParentRpDev, ParentRpFunc, 0);
|
|
UpBus = PciSegmentRead8 (ParentP2PBridgeBase + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
|
|
DpBus = (UINTN) ((CurrentPciAddress >> 24) & 0xFF);
|
|
DEBUG ((DEBUG_INFO, "Upstream Port Bus 0x%x and Downstream Port Bus 0x%x consume 2 bus\n", UpBus, DpBus));
|
|
*ConsumedBusNumber = *ConsumedBusNumber + 2;
|
|
}
|
|
|
|
/**
|
|
Check if P2pb device is the last one in the same layer bus.
|
|
|
|
@param[in] HpcPciAddress The address of the Hot Plug Controller function on the PCI bus.
|
|
|
|
@retval TRUE This P2pb device is the last one.
|
|
@retval FALSE This P2pb device is not the last one.
|
|
**/
|
|
BOOLEAN
|
|
IsLastP2pbDevice (
|
|
IN UINT64 HpcPciAddress
|
|
)
|
|
{
|
|
UINT8 RpSeg;
|
|
UINTN RpBus;
|
|
UINTN RpDev;
|
|
UINT16 Index;
|
|
|
|
RpSeg = (UINT8)((HpcPciAddress >> 32) & 0x01);
|
|
RpBus = (UINTN)((HpcPciAddress >> 24) & 0xFF);
|
|
RpDev = (UINTN)((HpcPciAddress >> 16) & 0xFF);
|
|
|
|
for (Index = 0; Index <= 0xff; Index++) {
|
|
if (mNumOfHotPlugBridge[Index].P2pbBusNum != 0) {
|
|
if ((mNumOfHotPlugBridge[Index].P2pbSegNum == RpSeg) && (mNumOfHotPlugBridge[Index].P2pbBusNum == RpBus) && (mNumOfHotPlugBridge[Index].P2pbLastDevNum == RpDev)) {
|
|
return TRUE;
|
|
}
|
|
} else {
|
|
// if P2pbBusNum = 0, the record has ended.
|
|
return FALSE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
/**
|
|
Update P2P Bridge Resource Record
|
|
|
|
@param[in] *HpcDevicePath The Device Path to the HPC that is being initialized.
|
|
@param[in] HpcPciAddress The address of the Hot Plug Controller function on the PCI bus.
|
|
@param[in] RsvdExtraBusNum Reserved Bus resource Number.
|
|
@param[in] RsvdPcieMegaMem Reserved Alignment of MEM resource.
|
|
@param[in] PcieMemAddrRngMax Alignment of MEM resource.
|
|
@param[in] RsvdPciePMegaMem Reserved Pcie Kilo Io Number.
|
|
@param[in] PciePMemAddrRngMax Alignment of PMEM resource.
|
|
@param[in] RsvdPcieKiloIo Reserved Pcie Kilo Io Number.
|
|
|
|
@retval EFI_SUCCESS.
|
|
**/
|
|
EFI_STATUS
|
|
UpdateP2pbResourceRecord (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
|
|
IN UINT64 HpcPciAddress,
|
|
IN UINT8 RsvdExtraBusNum,
|
|
IN UINT16 RsvdPcieMegaMem,
|
|
IN UINT8 PcieMemAddrRngMax,
|
|
IN UINT16 RsvdPciePMegaMem,
|
|
IN UINT8 PciePMemAddrRngMax,
|
|
IN UINT8 RsvdPcieKiloIo
|
|
)
|
|
{
|
|
UINT16 Index;
|
|
|
|
for (Index = 0; Index < MAX_P2PB_OF_TBT_DAISY_CHAIN; Index++) {
|
|
if (mP2pbResourceRecord[Index].HpcPciAddress == 0) {
|
|
continue;
|
|
}
|
|
if (mP2pbResourceRecord[Index].HpcPciAddress == HpcPciAddress) {
|
|
//
|
|
// Record already existed, so ignore it.
|
|
//
|
|
return EFI_ABORTED;
|
|
}
|
|
}
|
|
//
|
|
// Record the current HPC's resource assignment
|
|
//
|
|
mP2pbResourceRecord[mP2pbResourceRecordCount].HpcDevicePath = HpcDevicePath;
|
|
mP2pbResourceRecord[mP2pbResourceRecordCount].HpcPciAddress = HpcPciAddress;
|
|
mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdExtraBusNum = RsvdExtraBusNum;
|
|
mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPcieMegaMem = RsvdPcieMegaMem;
|
|
mP2pbResourceRecord[mP2pbResourceRecordCount].PcieMemAddrRngMax = PcieMemAddrRngMax;
|
|
mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPciePMegaMem = RsvdPciePMegaMem;
|
|
mP2pbResourceRecord[mP2pbResourceRecordCount].PciePMemAddrRngMax = PciePMemAddrRngMax;
|
|
mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPcieKiloIo = RsvdPcieKiloIo;
|
|
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].HpcDevicePath = %s \n", mP2pbResourceRecordCount, ConvertDevicePathToText (mP2pbResourceRecord[mP2pbResourceRecordCount].HpcDevicePath, TRUE, TRUE)));
|
|
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].HpcPciAddress = %lx \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].HpcPciAddress));
|
|
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].RsvdExtraBusNum = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdExtraBusNum));
|
|
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].RsvdPcieMegaMem = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPcieMegaMem));
|
|
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].PcieMemAddrRngMax = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].PcieMemAddrRngMax));
|
|
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].RsvdPciePMegaMem = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPciePMegaMem));
|
|
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].PciePMemAddrRngMax = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].PciePMemAddrRngMax));
|
|
DEBUG ((DEBUG_INFO, "mP2pbResourceRecord[%x].RsvdPcieKiloIo = %x \n", mP2pbResourceRecordCount, mP2pbResourceRecord[mP2pbResourceRecordCount].RsvdPcieKiloIo));
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Handle the Resource Padding For Non-RootPort
|
|
|
|
@param[in] *HpcDevicePath The Device Path to the HPC that is being initialized.
|
|
@param[in] HpcPciAddress The address of the Hot Plug Controller function on the PCI bus.
|
|
@param[in] RsvdExtraBusNum Reserved Bus resource Number.
|
|
@param[in] RsvdPcieMegaMem Reserved Alignment of MEM resource.
|
|
@param[in] PcieMemAddrRngMax Alignment of MEM resource.
|
|
@param[in] RsvdPciePMegaMem Reserved Pcie Kilo Io Number.
|
|
@param[in] PciePMemAddrRngMax Alignment of PMEM resource.
|
|
@param[in] RsvdPcieKiloIo Reserved Pcie Kilo Io Number.
|
|
|
|
**/
|
|
VOID
|
|
HandleResourcePaddingForNonRootPort (
|
|
IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath,
|
|
IN UINT64 HpcPciAddress,
|
|
OUT UINT8 *RsvdExtraBusNum,
|
|
OUT UINT16 *RsvdPcieMegaMem,
|
|
OUT UINT8 *PcieMemAddrRngMax,
|
|
OUT UINT16 *RsvdPciePMegaMem,
|
|
OUT UINT8 *PciePMemAddrRngMax,
|
|
OUT UINT8 *RsvdPcieKiloIo
|
|
)
|
|
{
|
|
UINT8 RpSeg;
|
|
UINTN RpBus;
|
|
UINTN RpDev;
|
|
UINTN RpFunc;
|
|
UINT64 ParentPciAddress;
|
|
EFI_STATUS Status;
|
|
UINT8 Index;
|
|
UINT8 ConsumedBusNumber;
|
|
|
|
RpSeg = (UINT8) ((HpcPciAddress >> 32) & 0x01);
|
|
RpBus = (UINTN) ((HpcPciAddress >> 24) & 0xFF);
|
|
RpDev = (UINTN) ((HpcPciAddress >> 16) & 0xFF);
|
|
RpFunc = (UINTN) ((HpcPciAddress >> 8) & 0xFF);
|
|
|
|
// Non-Rootport
|
|
DEBUG ((DEBUG_INFO, "GetResourcePadding : Non-Rootport Seg 0x%x, Bus 0x%x, Device 0x%x, Function 0x%x \n", RpSeg, RpBus, RpDev, RpFunc));
|
|
|
|
*RsvdPcieKiloIo = 0;
|
|
ConsumedBusNumber = 0;
|
|
|
|
ParentPciAddress = GetParentPciAddress (RpSeg, RpBus);
|
|
|
|
GetParentResourceSize (ParentPciAddress, RsvdExtraBusNum, RsvdPcieMegaMem, RsvdPciePMegaMem, RsvdPcieKiloIo);
|
|
DEBUG ((DEBUG_INFO, "Parent's resource as below \n"));
|
|
DEBUG ((DEBUG_INFO, "BusNum = %x \n", *RsvdExtraBusNum));
|
|
DEBUG ((DEBUG_INFO, "PcieMegaMem = %x \n", *RsvdPcieMegaMem));
|
|
DEBUG ((DEBUG_INFO, "PciePMegaMem = %x \n", *RsvdPciePMegaMem));
|
|
DEBUG ((DEBUG_INFO, "PcieKiloIo = %x \n", *RsvdPcieKiloIo));
|
|
|
|
CalculateBusConsumptionBeforeAssign (ParentPciAddress, HpcPciAddress, &ConsumedBusNumber);
|
|
|
|
Index = 0;
|
|
Status = GetCurrentBusP2pbHotPlug(RpSeg, (UINT8)RpBus, &Index);
|
|
if (Status == EFI_SUCCESS) {
|
|
// RsvdExtraBusNum = (Reserved Bus - UpStream Bus - DownStream Bus - Tatal Non-HotPlug Bus) / Total HotPlug P2pb
|
|
if (mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug != 0) {
|
|
*RsvdExtraBusNum = (UINT8) DivU64x32Remainder ((UINT64)(*RsvdExtraBusNum - ConsumedBusNumber - mNumOfHotPlugBridge[Index].NumOfP2pbNonHotPlug), (UINT32)mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug, &mRemainderBus);
|
|
}
|
|
|
|
// If mRemainderBus not equal zero, check this device is the last one or not.
|
|
if (mRemainderBus != 0) {
|
|
DEBUG((DEBUG_INFO, "Remainder Bus = %x in the Seg:%x Bus:%x layer\n", mRemainderBus, RpSeg, RpBus));
|
|
if (IsLastP2pbDevice(HpcPciAddress)) {
|
|
DEBUG((DEBUG_INFO, "This device is the last P2pb in the same layer, so we need to add Remainder Bus\n"));
|
|
*RsvdExtraBusNum = (UINT8)(*RsvdExtraBusNum + mRemainderBus);
|
|
}
|
|
}
|
|
*RsvdPcieMegaMem = (*RsvdPcieMegaMem - mNumOfHotPlugBridge[Index].NumOfP2pbNonHotPlug)/mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug;
|
|
*RsvdPciePMegaMem = (*RsvdPciePMegaMem)/mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug;
|
|
*RsvdPcieKiloIo = (*RsvdPcieKiloIo)/mNumOfHotPlugBridge[Index].NumOfP2pbHotPlug;
|
|
DEBUG ((DEBUG_INFO, "Current resource as below \n"));
|
|
DEBUG ((DEBUG_INFO, "BusNum = %x \n", *RsvdExtraBusNum));
|
|
DEBUG ((DEBUG_INFO, "PcieMegaMem = %x \n", *RsvdPcieMegaMem));
|
|
DEBUG ((DEBUG_INFO, "PciePMegaMem = %x \n", *RsvdPciePMegaMem));
|
|
DEBUG ((DEBUG_INFO, "PcieKiloIo = %x \n", *RsvdPcieKiloIo));
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "GetCurrentBusP2pbHotPlug Status =%r\n", Status));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
Get resource padding information from record.
|
|
|
|
@param[in] Event A pointer to the Event that triggered the callback.
|
|
@param[in] Handle Checkpoint handle.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PciHpcGetResourcePaddingCallback (
|
|
IN EFI_EVENT Event,
|
|
IN H2O_CP_HANDLE Handle
|
|
) {
|
|
EFI_STATUS Status;
|
|
H2O_DXE_CP_PCI_HPC_GET_RESOURCE_PADDING_DATA *PciHpcGetResourcePaddingData;
|
|
UINT8 RsvdExtraBusNum = 0;
|
|
UINT16 RsvdPcieMegaMem = 10;
|
|
UINT8 PcieMemAddrRngMax = 1;
|
|
UINT16 RsvdPciePMegaMem = 10;
|
|
UINT8 PciePMemAddrRngMax = 1;
|
|
UINT8 RsvdPcieKiloIo = 4;
|
|
UINTN RpBus;
|
|
CHAR16 *DevicePathStr;
|
|
UINT64 AlignmentTemp = 0;
|
|
|
|
|
|
Status = H2OCpLookup (Handle, (VOID **) &PciHpcGetResourcePaddingData, &gH2ODxeCpPciHpcGetResourcePaddingGuid);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "Checkpoint Data Not Found: %x (%r)\n", Handle, Status));
|
|
DEBUG ((EFI_D_ERROR, " %a\n", __FUNCTION__));
|
|
return;
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "PciHpcGetResourcePaddingCallback start. \n"));
|
|
|
|
// Record the segment number in Bit[32] of HpcPciAddress.
|
|
DevicePathStr = ConvertDevicePathToText (PciHpcGetResourcePaddingData->PciDevicePath, TRUE, TRUE);
|
|
if (DevicePathStr != NULL) {
|
|
if (StrnCmp (DevicePathStr, PCI_ROOT_0_STRING, StrLen (PCI_ROOT_0_STRING)) == 0) {
|
|
DEBUG ((DEBUG_INFO, "Segment0 \n"));
|
|
PciHpcGetResourcePaddingData->PciAddress &= ~BIT32;
|
|
} else if (StrnCmp (DevicePathStr, PCI_ROOT_1_STRING, StrLen (PCI_ROOT_1_STRING)) == 0) {
|
|
DEBUG ((DEBUG_INFO, "Segment1 \n"));
|
|
PciHpcGetResourcePaddingData->PciAddress |= BIT32;
|
|
}
|
|
} else {
|
|
DEBUG ((DEBUG_ERROR, "Segment error. \n"));
|
|
}
|
|
|
|
RpBus = (UINTN) ((PciHpcGetResourcePaddingData->PciAddress >> 24) & 0xFF);
|
|
|
|
if (RpBus == 0x00) {
|
|
//
|
|
// Record RootPort resource
|
|
//
|
|
if (PciHpcGetResourcePaddingData->ResourcePaddingFound) {
|
|
//
|
|
// PciHotPlug driver had found resource,
|
|
// Just record it.
|
|
// Transform value to RC code record format.
|
|
//
|
|
RsvdExtraBusNum = PciHpcGetResourcePaddingData->ReservedBusCount;
|
|
RsvdPcieKiloIo = (UINT8)(PciHpcGetResourcePaddingData->ReservedIoRange / 0x400);
|
|
RsvdPcieMegaMem = (UINT16)(PciHpcGetResourcePaddingData->ReservedNonPrefetchableMmio / 0x100000);
|
|
AlignmentTemp = PciHpcGetResourcePaddingData->AlignmentOfReservedNonPrefetchableMmio;
|
|
//
|
|
// Change Alignment from value to shift bits.
|
|
//
|
|
if (AlignmentTemp != 0) {
|
|
AlignmentTemp = AlignmentTemp - 1;
|
|
while (AlignmentTemp > 1) {
|
|
AlignmentTemp = RShiftU64(AlignmentTemp, 1);
|
|
PcieMemAddrRngMax++;
|
|
}
|
|
}
|
|
RsvdPciePMegaMem = (UINT16)(PciHpcGetResourcePaddingData->ReservedPrefetchableMmio / 0x100000);
|
|
//
|
|
// Change Alignment from value to shift bits.
|
|
//
|
|
AlignmentTemp = PciHpcGetResourcePaddingData->AlignmentOfReservedPrefetchableMmio;
|
|
if (AlignmentTemp != 0) {
|
|
AlignmentTemp = AlignmentTemp - 1;
|
|
while (AlignmentTemp > 1) {
|
|
AlignmentTemp = RShiftU64(AlignmentTemp, 1);
|
|
PciePMemAddrRngMax++;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// PciHotPlug driver didn't find resource,
|
|
// Give default resource.
|
|
//
|
|
PciHpcGetResourcePaddingData->ReservedBusCount = RsvdExtraBusNum;
|
|
PciHpcGetResourcePaddingData->ReservedIoRange = RsvdPcieKiloIo * 0x400;
|
|
PciHpcGetResourcePaddingData->ReservedNonPrefetchableMmio = RsvdPcieMegaMem * 0x100000;
|
|
PciHpcGetResourcePaddingData->AlignmentOfReservedNonPrefetchableMmio = LShiftU64(1, PcieMemAddrRngMax);
|
|
PciHpcGetResourcePaddingData->ReservedPrefetchableMmio = RsvdPciePMegaMem * 0x100000;
|
|
PciHpcGetResourcePaddingData->AlignmentOfReservedPrefetchableMmio = LShiftU64(1, PciePMemAddrRngMax);
|
|
}
|
|
|
|
} else {
|
|
//
|
|
// Handle the GetResourcePadding for Non-RootPort
|
|
//
|
|
HandleResourcePaddingForNonRootPort (
|
|
PciHpcGetResourcePaddingData->PciDevicePath,
|
|
PciHpcGetResourcePaddingData->PciAddress,
|
|
&RsvdExtraBusNum,
|
|
&RsvdPcieMegaMem,
|
|
&PcieMemAddrRngMax,
|
|
&RsvdPciePMegaMem,
|
|
&PciePMemAddrRngMax,
|
|
&RsvdPcieKiloIo
|
|
);
|
|
}
|
|
|
|
//
|
|
// Record resource.
|
|
//
|
|
Status = UpdateP2pbResourceRecord (
|
|
PciHpcGetResourcePaddingData->PciDevicePath,
|
|
PciHpcGetResourcePaddingData->PciAddress,
|
|
RsvdExtraBusNum,
|
|
RsvdPcieMegaMem,
|
|
PcieMemAddrRngMax,
|
|
RsvdPciePMegaMem,
|
|
PciePMemAddrRngMax,
|
|
RsvdPcieKiloIo
|
|
);
|
|
if (Status == EFI_SUCCESS) {
|
|
mP2pbResourceRecordCount ++;
|
|
}
|
|
|
|
PciHpcGetResourcePaddingData->ResourcePaddingFound = TRUE;
|
|
PciHpcGetResourcePaddingData->Status = H2O_CP_TASK_UPDATE;
|
|
PciHpcGetResourcePaddingData->Above4GbMmioSupported = mEnableAbove4GBMmio;
|
|
|
|
//
|
|
// Return value with the format that PciHotPlugDxe used.
|
|
//
|
|
PciHpcGetResourcePaddingData->ReservedBusCount = RsvdExtraBusNum - 1;
|
|
PciHpcGetResourcePaddingData->ReservedIoRange = RsvdPcieKiloIo * 0x400;
|
|
PciHpcGetResourcePaddingData->ReservedNonPrefetchableMmio = RsvdPcieMegaMem * 0x100000;
|
|
PciHpcGetResourcePaddingData->AlignmentOfReservedNonPrefetchableMmio = LShiftU64(1, PcieMemAddrRngMax);
|
|
PciHpcGetResourcePaddingData->ReservedPrefetchableMmio = RsvdPciePMegaMem * 0x100000;
|
|
PciHpcGetResourcePaddingData->AlignmentOfReservedPrefetchableMmio = LShiftU64(1, PciePMemAddrRngMax);
|
|
|
|
DEBUG ((DEBUG_INFO, "Resource Padding infomation\n"));
|
|
DEBUG ((DEBUG_INFO, " Bus: 0x%x, Dev: 0x%x, Func: 0x%x\n", ((UINT8)(PciHpcGetResourcePaddingData->PciAddress >> 24) & 0xFF),
|
|
((UINT8)(PciHpcGetResourcePaddingData->PciAddress >> 16) & 0xFF),
|
|
((UINT8)(PciHpcGetResourcePaddingData->PciAddress >> 8) & 0xFF)));
|
|
DEBUG ((DEBUG_INFO, " ReservedBusCount : 0x%x\n", PciHpcGetResourcePaddingData->ReservedBusCount));
|
|
DEBUG ((DEBUG_INFO, " ReservedIoRange : 0x%x\n", PciHpcGetResourcePaddingData->ReservedIoRange));
|
|
DEBUG ((DEBUG_INFO, " ReservedNonPrefetchableMmio : 0x%x\n", PciHpcGetResourcePaddingData->ReservedNonPrefetchableMmio));
|
|
DEBUG ((DEBUG_INFO, " AlignmentOfReservedNonPrefetchableMmio: 0x%x\n", PciHpcGetResourcePaddingData->AlignmentOfReservedNonPrefetchableMmio - 1));
|
|
DEBUG ((DEBUG_INFO, " ReservedPrefetchableMmio : 0x%x\n", PciHpcGetResourcePaddingData->ReservedPrefetchableMmio));
|
|
DEBUG ((DEBUG_INFO, " AlignmentOfReservedPrefetchableMmio : 0x%x\n", PciHpcGetResourcePaddingData->AlignmentOfReservedPrefetchableMmio - 1));
|
|
DEBUG ((DEBUG_INFO, " Above4GbMmioSupported : 0x%x\n", PciHpcGetResourcePaddingData->Above4GbMmioSupported));
|
|
|
|
|
|
return;
|
|
} |