/** @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.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that 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 "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")); }