/** @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.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "PchInit.h" #include #include // // 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")); }