/** @file
|
Configures the remapping for PCH Intel RST PCie Storage
|
In order to use this feature, Intel RST Driver is required
|
|
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
**/
|
#include "PchInit.h"
|
#include <Library/RstPrivateLib.h>
|
#include <PchPcieStorageDetectHob.h>
|
|
//
|
// Variables below indicate the memory range to be allocated to the PCIe storage device BAR usage when it is HIDDEN,
|
// thus it does not overlapped with the SGREG_BAR from the host perspective
|
//
|
#define RST_PCIE_STORAGE_MEMORY_START_RANGE PCH_PCR_BASE_ADDRESS
|
#define RST_PCIE_STORAGE_MEMORY_END_RANGE (PCH_PCR_BASE_ADDRESS + PCH_PCR_MMIO_SIZE - 1)
|
|
#define PCI_CARD_PM_CAP_ID 0x01
|
#define PCI_CARD_MSIX_CAP_ID 0x11
|
#define PCI_CARD_SATA_CAP_ID 0x12
|
#define PCI_CARD_BAR_TOTAL 6
|
#define PCI_CARD_LINK_SPEED_GEN1_GEN2 0
|
#define PCI_CARD_LINK_SPEED_GEN3 1
|
#define PCI_CARD_LINK_WIDTH_1 0
|
#define PCI_CARD_LINK_WIDTH_2 1
|
#define PCI_CARD_LINK_WIDTH_4 2
|
#define PCI_CARD_REVISION 0x08
|
#define PCI_CARD_BASE_ADDR0 0x10
|
#define PCI_CARD_BASE_ADDR1 0x14
|
#define PCI_CARD_BASE_ADDR5 0x24
|
|
GLOBAL_REMOVE_IF_UNREFERENCED PCH_RST_PCIE_STORAGE_DETECTION mRstPcieStorageDetection [PCH_MAX_RST_PCIE_STORAGE_CR];
|
|
UINT32 PchRstPcieStorageCurrentMemoryRange = RST_PCIE_STORAGE_MEMORY_START_RANGE;
|
|
|
/**
|
Function to perform dump for PCH_RST_PCIE_STORAGE_DETECTION
|
|
@param[in] Index Index for RST PCIe Storage Cycle Router Instance
|
|
@retval None
|
**/
|
VOID
|
PchRstPcieStorageRemappingDump (
|
IN UINTN Index
|
)
|
{
|
DEBUG_CODE_BEGIN ();
|
DEBUG ((DEBUG_INFO, "PchRstPcieStorageRemappingDump() Started\n"));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].SupportRstPcieStoragRemapping = %x\n", Index, mRstPcieStorageDetection[Index].SupportRstPcieStoragRemapping));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].RootPortNum = %x\n", Index, mRstPcieStorageDetection[Index].RootPortNum));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].RootPortLane = %x\n", Index, mRstPcieStorageDetection[Index].RootPortLane));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].DeviceInterface = %x\n", Index, mRstPcieStorageDetection[Index].DeviceInterface));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].IsMsixSupported = %x\n", Index, mRstPcieStorageDetection[Index].IsMsixSupported));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].MsixStartingVector = %x\n", Index, mRstPcieStorageDetection[Index].MsixStartingVector));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].MsixEndingVector = %x\n", Index, mRstPcieStorageDetection[Index].MsixEndingVector));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointBarSize = %x\n", Index, mRstPcieStorageDetection[Index].EndPointBarSize));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixTableBar = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixTableBar));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixTableBarValue = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixTableBarValue));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixPbaBar = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixPbaBar));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointUniqueMsixPbaBarValue = %x\n", Index, mRstPcieStorageDetection[Index].EndPointUniqueMsixPbaBarValue));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointBcc = %x\n", Index, mRstPcieStorageDetection[Index].EndPointBcc));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointScc = %x\n", Index, mRstPcieStorageDetection[Index].EndPointScc));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].EndPointPi = %x\n", Index, mRstPcieStorageDetection[Index].EndPointPi));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.PmCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.PmCapPtr));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.PcieCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.PcieCapPtr));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.L1ssCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.L1ssCapPtr));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointL1ssControl2 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointL1ssControl2));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointL1ssControl1 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointL1ssControl1));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.LtrCapPtr = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.LtrCapPtr));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointLtrData = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointLtrData));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointLctlData16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointLctlData16));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointDctlData16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointDctlData16));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.EndpointDctl2Data16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.EndpointDctl2Data16));
|
DEBUG ((DEBUG_INFO, "mRstPcieStorageDetection[%d].PchRstPcieStorageSaveRestore.RootPortDctl2Data16 = %x\n", Index, mRstPcieStorageDetection[Index].PchRstPcieStorageSaveRestore.RootPortDctl2Data16));
|
DEBUG ((DEBUG_INFO, "PchRstPcieStorageRemappingDump() Ended\n"));
|
DEBUG_CODE_END ();
|
}
|
|
/**
|
Perform memory space allocation or free memory pool for AHCI BAR
|
|
@param[in] Operation True: Perform memory space allocation for AHCI BAR
|
False: Perform memory pool free for AHCI BAR
|
@param[in,out] MemBaseAddress The base memory address used by AHCI BAR
|
**/
|
VOID
|
AbarMemorySpaceOperation (
|
IN BOOLEAN Operation,
|
IN OUT EFI_PHYSICAL_ADDRESS *MemBaseAddress
|
)
|
{
|
EFI_STATUS Status;
|
EFI_PHYSICAL_ADDRESS BaseAddress;
|
UINTN AhciBarAlignment;
|
UINTN AhciBarLength;
|
|
//
|
// Assign a 512k size memory space to the ABAR when NVM Remapping is enabled
|
//
|
AhciBarAlignment = N_PCH_SATA_AHCI_BAR_ALIGNMENT_512K; // 2^19: 512K Alignment
|
AhciBarLength = V_PCH_SATA_AHCI_BAR_LENGTH_512K; // 512K Length
|
|
|
if (Operation == TRUE) {
|
///
|
/// If MemBaseAddress is not allocated yet, allocate the AHCI BAR
|
///
|
if ((PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchBottomUp) || (PcdGet8 (PcdEfiGcdAllocateType) == EfiGcdAllocateMaxAddressSearchTopDown)) {
|
BaseAddress = 0x0ffffffff;
|
}
|
Status = gDS->AllocateMemorySpace (
|
PcdGet8 (PcdEfiGcdAllocateType),
|
EfiGcdMemoryTypeMemoryMappedIo,
|
AhciBarAlignment,
|
AhciBarLength,
|
&BaseAddress,
|
mImageHandle,
|
NULL
|
);
|
ASSERT_EFI_ERROR (Status);
|
*MemBaseAddress = BaseAddress;
|
} else {
|
///
|
/// Else, free the GCD pool
|
///
|
gDS->FreeMemorySpace (
|
*MemBaseAddress,
|
AhciBarLength
|
);
|
}
|
}
|
|
/**
|
Function to perform memory allocation for PCIe storage device that support unique BAR
|
|
@param[in] BarSize The BAR size required for memory allocation
|
@param[in,out] AllocAddr The Address that been allocated by this function
|
|
@retval EFI_SUCCESS The function completed successfully
|
@retval EFI_OUT_OF_RESOURCES Memory or storage is not enough
|
**/
|
EFI_STATUS
|
PchRstPcieStorageMemAllocation (
|
IN UINT32 BarSize,
|
IN OUT UINT32 *AllocAddr
|
)
|
{
|
if ((PchRstPcieStorageCurrentMemoryRange + BarSize) > RST_PCIE_STORAGE_MEMORY_END_RANGE) {
|
return EFI_OUT_OF_RESOURCES;
|
}
|
|
if ((PchRstPcieStorageCurrentMemoryRange & (BarSize - 1)) != 0) {
|
*AllocAddr = (PchRstPcieStorageCurrentMemoryRange + BarSize) & ~(BarSize-1);
|
} else {
|
*AllocAddr = PchRstPcieStorageCurrentMemoryRange;
|
}
|
|
PchRstPcieStorageCurrentMemoryRange = *AllocAddr + BarSize;
|
return EFI_SUCCESS;
|
}
|
|
/**
|
Check and detect PCIe storage device per policies, and if existed, indicate if it should be subjected for remapping
|
Populate the mRstPcieStorageDetection structure along with it for later usages
|
|
@param[in, out] RemappingRequired Boolean value with TRUE indicates that RST PCIe Storage Remapping is required
|
@param[in] TempPciBusMin The temporary minimum Bus number for root port initialization
|
@param[in] SataRegBase SATA Register Base
|
|
@retval None
|
**/
|
VOID
|
DetectPcieStorageDevices (
|
IN OUT BOOLEAN *RemappingRequired,
|
IN UINT8 TempPciBusMin,
|
IN UINTN SataRegBase
|
)
|
{
|
EFI_STATUS Status;
|
PCH_SERIES PchSeries;
|
UINT8 DeviceInterface;
|
UINT32 PortNum;
|
UINTN PciRootPortRegBase;
|
UINTN RpDev;
|
UINTN RpFunc;
|
UINT8 RootPortLane;
|
PCIE_STORAGE_INFO_HOB *PcieStorageInfoHob;
|
VOID *Hob;
|
UINT32 CycleRouterNum;
|
|
DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: DetectPcieStorageDevices Started\n"));
|
|
Hob = NULL;
|
Hob = GetFirstGuidHob (&gPchPcieStorageDetectHobGuid);
|
if (Hob != NULL) {
|
PcieStorageInfoHob = (PCIE_STORAGE_INFO_HOB *) GET_GUID_HOB_DATA (Hob);
|
} else {
|
return;
|
}
|
|
PchSeries = GetPchSeries ();
|
|
for (PortNum = 0; PortNum < GetPchMaxPciePortNum (); PortNum++) {
|
|
//
|
// Check Info hob for Cycle Router avaliable
|
// skip to next root port if Cr is not avaliable
|
//
|
CycleRouterNum = PcieStorageInfoHob->RstCycleRouterMap[PortNum / 4];
|
if (CycleRouterNum == RST_PCIE_STORAGE_CR_INVALID) {
|
DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: cycle router not avaliable on Rp = %d\n", PortNum));
|
continue;
|
}
|
|
Status = GetPchPcieRpDevFun (PortNum, &RpDev, &RpFunc);
|
ASSERT_EFI_ERROR (Status);
|
|
PciRootPortRegBase = MmPciBase (DEFAULT_PCI_BUS_NUMBER_PCH, (UINT32) RpDev, (UINT32) RpFunc);
|
RootPortLane = RstGetRpLaneOccupyMask (PortNum);
|
|
|
if (RootPortLane == 0) {
|
DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: root port lane is not occupied\n"));
|
continue;
|
}
|
|
///
|
/// Check if the RST PCIe Storage Cycle Router is enabled, continue to the next root port in the next x4 lane if it is disabled
|
///
|
if (mPchConfigHob->Sata.RstPcieStorageRemap[CycleRouterNum].Enable == 0) {
|
DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: RST PCIe Storage Cycle Router %d is disabled\n", CycleRouterNum));
|
DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: Proceed to root port in the next x4 lane (@ port %d)\n", PortNum + 1));
|
PortNum += 3 - (PortNum % 4);
|
continue;
|
}
|
|
///
|
/// Check if the current root port is matching selected root port from policy, continue to next port if they are not matched
|
///
|
if ((mPchConfigHob->Sata.RstPcieStorageRemap[CycleRouterNum].RstPcieStoragePort != 0) &&
|
(mPchConfigHob->Sata.RstPcieStorageRemap[CycleRouterNum].RstPcieStoragePort != PortNum + 1)) {
|
DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: root port %d not matched with selected root port, proceed to next port\n", PortNum + 1));
|
continue;
|
}
|
|
|
// Read device programming interface from info hob
|
// if no device is present continue
|
if (PcieStorageInfoHob->PcieStorageLinkWidth[PortNum]) {
|
DeviceInterface = PcieStorageInfoHob->PcieStorageProgrammingInterface[PortNum];
|
DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: Device present on RP# %d, PiInterface = %d\n", PortNum + 1, DeviceInterface));
|
} else {
|
DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: RP# %d no device present\n", PortNum + 1));
|
continue;
|
}
|
|
|
///
|
/// Update the remapping detail for detected PCIe storage device, and move to the root port in the next x4 lane
|
///
|
if ((DeviceInterface != RST_PCIE_STORAGE_INTERFACE_NONE)) {
|
mRstPcieStorageDetection[CycleRouterNum].SupportRstPcieStoragRemapping = TRUE;
|
mRstPcieStorageDetection[CycleRouterNum].RootPortNum = (UINT8) PortNum;
|
mRstPcieStorageDetection[CycleRouterNum].RootPortLane = RootPortLane;
|
mRstPcieStorageDetection[CycleRouterNum].DeviceInterface = DeviceInterface;
|
PortNum += 3 - (PortNum % 4);
|
*RemappingRequired = TRUE;
|
} else {
|
continue;
|
}
|
}
|
|
DEBUG ((DEBUG_INFO, "DetectPcieStorageDevices: DetectPcieStorageDevices() Ended\n"));
|
}
|
|
|