예제 #1
0
/**
 * Configure engine list to support lane allocation according to configuration ID.
 *
 *
 *
 * @param[in]  Wrapper             Pointer to wrapper config descriptor
 * @param[in]  PcieLaneConfig       Lane configuration descriptor
 * @param[in]  ConfigurationId     Configuration ID
 * @retval     AGESA_SUCCESS       Configuration successfully applied
 * @retval     AGESA_ERROR         Requested configuration not supported
 */
AGESA_STATUS
PcieConfigurePcieEnginesLaneAllocationML (
  IN      PCIe_WRAPPER_CONFIG           *Wrapper,
  IN      PCIe_LANE_ALLOC_DESCRIPTOR    *PcieLaneConfig,
  IN      UINT8                         ConfigurationId
  )
{
  UINT8               CoreLaneIndex;
  PCIe_ENGINE_CONFIG  *EnginesList;

  if (ConfigurationId >= PcieLaneConfig->NumberOfConfigurations) {
    return AGESA_ERROR;
  }
  EnginesList = PcieConfigGetChildEngine (Wrapper);
  CoreLaneIndex = ConfigurationId * PcieLaneConfig->NumberOfEngines * 2;

  while (EnginesList != NULL) {
    if (PcieLibIsPcieEngine (EnginesList)) {
      PcieConfigResetDescriptorFlags (EnginesList, DESCRIPTOR_ALLOCATED);
      EnginesList->Type.Port.StartCoreLane = PcieLaneConfig->ConfigTable[CoreLaneIndex++];
      EnginesList->Type.Port.EndCoreLane = PcieLaneConfig->ConfigTable[CoreLaneIndex++];
    }
    EnginesList = PcieLibGetNextDescriptor (EnginesList);
  }
  return AGESA_SUCCESS;
}
예제 #2
0
UINT32
PcieUtilGetWrapperLaneBitMap (
  IN      UINT32                         IncludeLaneType,
  IN      UINT32                         ExcludeLaneType,
  IN      PCIe_WRAPPER_CONFIG            *Wrapper
  )
{
  PCIe_ENGINE_CONFIG        *EngineList;
  UINT32                    LaneBitmap;
  EngineList = PcieConfigGetChildEngine (Wrapper);
  LaneBitmap = 0;
  if ((IncludeLaneType | ExcludeLaneType) != 0) {
    if ((IncludeLaneType & LANE_TYPE_ALL) == LANE_TYPE_ALL) {
      LaneBitmap = (1 << (Wrapper->NumberOfLanes)) - 1;
      if (ExcludeLaneType != 0) {
        LaneBitmap &= (~PcieUtilGetWrapperLaneBitMap (ExcludeLaneType, 0, Wrapper));
      }
    } else {
      while (EngineList != NULL) {
        LaneBitmap |= PcieUtilGetEngineLaneBitMap (IncludeLaneType, ExcludeLaneType, EngineList);
        EngineList = PcieLibGetNextDescriptor (EngineList);
      }
      if ((IncludeLaneType & LANE_TYPE_PCIE_PHY_NATIVE_MASTER_PLL) != 0) {
        LaneBitmap |= PcieUtilGetMasterPllLaneBitMap (Wrapper);
      }
      if ((ExcludeLaneType & LANE_TYPE_PCIE_PHY_NATIVE_MASTER_PLL) != 0) {
        LaneBitmap &= (~PcieUtilGetMasterPllLaneBitMap (Wrapper));
      }
    }
  }
  return LaneBitmap;
}
예제 #3
0
/**
 * Initialize engine data
 *
 *
 *
 * @param[in]     ComplexDescriptor   Pointer to user defined complex descriptor
 * @param[in,out] Wrapper             Pointer to wrapper config descriptor
 * @param[in]     Pcie                Pointer to global PCIe configuration
 */
VOID
PcieMapInitializeEngineData (
    IN       PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
    IN OUT   PCIe_WRAPPER_CONFIG         *Wrapper,
    IN       PCIe_PLATFORM_CONFIG        *Pcie
)
{
    PCIe_ENGINE_CONFIG        *EngineList;
    PCIe_ENGINE_DESCRIPTOR    *EngineDescriptor;

    EngineList = PcieConfigGetChildEngine (Wrapper);
    while (EngineList != NULL) {
        if (PcieLibIsEngineAllocated (EngineList)) {
            if (EngineList->Scratch != 0xFF) {
                EngineDescriptor = PcieInputParserGetEngineDescriptor (ComplexDescriptor, EngineList->Scratch);
                LibAmdMemCopy (&EngineList->EngineData, &EngineDescriptor->EngineData, sizeof (EngineDescriptor->EngineData), GnbLibGetHeader (Pcie));
                if (PcieLibIsDdiEngine (EngineList)) {
                    LibAmdMemCopy (&EngineList->Type.Ddi, &((PCIe_DDI_DESCRIPTOR*) EngineDescriptor)->Ddi, sizeof (PCIe_DDI_DATA), GnbLibGetHeader (Pcie));
                    EngineList->Type.Ddi.DisplayPriorityIndex = (UINT8) EngineList->Scratch;
                } else if (PcieLibIsPcieEngine (EngineList)) {
                    LibAmdMemCopy (&EngineList->Type.Port, &((PCIe_PORT_DESCRIPTOR*) EngineDescriptor)->Port, sizeof (PCIe_PORT_DATA), GnbLibGetHeader (Pcie));
                }
            }
        }
        EngineList = PcieLibGetNextDescriptor (EngineList);
    }
}
예제 #4
0
VOID
STATIC
PcieSiliconControlPortsV5 (
  IN      PCIE_PORT_VISIBILITY    Control,
  IN      PCIe_SILICON_CONFIG     *Silicon,
  IN      PCIe_PLATFORM_CONFIG    *Pcie
  )
{
  PCIe_ENGINE_CONFIG  *EngineList;
  UINT32              Value;
  Value = (Control == HidePorts) ? ((1 << D0F0xCC_x01_BridgeDis_OFFSET) | (1 << D0F0xCC_x01_CfgDis_OFFSET)) : 0;
  Value |= (1 << D0F0xCC_x01_CsrEnable_OFFSET) | (1 << D0F0xCC_x01_SetPowEn_OFFSET);
  EngineList = PcieConfigGetChildEngine (Silicon);
  while (EngineList != NULL) {
    if (PcieConfigIsPcieEngine (EngineList)) {
      GnbLibPciIndirectRMW (
        Silicon->Address.AddressValue | D0F0xC8_ADDRESS,
        D0F0xCC_x01_ADDRESS | ((EngineList->Type.Port.NativeDevNumber << 3 | EngineList->Type.Port.NativeFunNumber) << D0F0xC8_NB_DEV_IND_SEL_OFFSET),
        AccessS3SaveWidth32,
        (UINT32)~(D0F0xCC_x01_BridgeDis_MASK | D0F0xCC_x01_CfgDis_MASK | D0F0xCC_x01_CsrEnable_MASK | D0F0xCC_x01_SetPowEn_MASK),
        Value,
        GnbLibGetHeader (Pcie)
        );
    }
    EngineList = (PCIe_ENGINE_CONFIG *) PcieConfigGetNextTopologyDescriptor (EngineList, DESCRIPTOR_TERMINATE_GNB);
  }
}
예제 #5
0
VOID
STATIC
PcieSiliconEnablePortsV5 (
  IN      PCIe_SILICON_CONFIG   *Silicon,
  IN      PCIe_PLATFORM_CONFIG  *Pcie
  )
{
  PCIe_ENGINE_CONFIG  *EngineList;
  EngineList = PcieConfigGetChildEngine (Silicon);
  while (EngineList != NULL) {
    if (PcieConfigIsPcieEngine (EngineList)) {
      if (!PcieConfigIsSbPcieEngine (EngineList) &&
        (PcieConfigCheckPortStatus (EngineList, INIT_STATUS_PCIE_TRAINING_SUCCESS) ||
        ((EngineList->Type.Port.PortData.LinkHotplug != HotplugDisabled) &&
        (EngineList->Type.Port.PortData.LinkHotplug != HotplugInboard)))) {
        GnbLibPciIndirectRMW (
          Silicon->Address.AddressValue | D0F0xC8_ADDRESS,
          D0F0xCC_x01_ADDRESS | ((EngineList->Type.Port.PortData.DeviceNumber << 3 | EngineList->Type.Port.PortData.FunctionNumber)  << D0F0xC8_NB_DEV_IND_SEL_OFFSET),
          AccessS3SaveWidth32,
          (UINT32)~(D0F0xCC_x01_BridgeDis_MASK | D0F0xCC_x01_CfgDis_MASK | D0F0xCC_x01_CsrEnable_MASK | D0F0xCC_x01_SetPowEn_MASK),
          ((1 << D0F0xCC_x01_CsrEnable_OFFSET) | (1 << D0F0xCC_x01_SetPowEn_OFFSET)),
          GnbLibGetHeader (Pcie)
        );
      }
    }
    EngineList = (PCIe_ENGINE_CONFIG *) PcieConfigGetNextTopologyDescriptor (EngineList, DESCRIPTOR_TERMINATE_GNB);
  }
}
예제 #6
0
BOOLEAN
PcieTopologyIsGen3SupportedV5 (
  IN      PCIe_WRAPPER_CONFIG   *Wrapper
  )
{
  UINT8                 LaneNibbleArray [4];
  UINT32                LaneBitmap;
  UINT8                 Nibble;
  UINT8                 NibbleBitmap;
  PCIe_ENGINE_CONFIG    *Engine;


  LibAmdMemFill (&LaneNibbleArray[0], 0x00, sizeof (LaneNibbleArray), PcieConfigGetStdHeader (Wrapper));
  Engine = PcieConfigGetChildEngine (Wrapper);
  while (Engine != NULL) {
    LaneBitmap = PcieUtilGetEngineLaneBitMap (LANE_TYPE_PCIE_PHY_NATIVE, 0, Engine);
    for (Nibble = 0; Nibble < 4; Nibble++) {
      NibbleBitmap = (0xF << (Nibble * 4));
      if ((LaneBitmap & NibbleBitmap) != 0) {
        if (++LaneNibbleArray [Nibble] > 1) {
          return FALSE;
        }
      }
    }
    Engine = PcieLibGetNextDescriptor (Engine);
  }
  return TRUE;
}
예제 #7
0
AGESA_STATUS
STATIC
PcieLnConfigureGppEnginesLaneAllocation (
  IN      PCIe_WRAPPER_CONFIG           *Wrapper,
  IN      UINT8                         ConfigurationId
  )
{
  PCIe_ENGINE_CONFIG  *EnginesList;
  UINTN               CoreLaneIndex;
  UINTN               PortIdIndex;
  if (ConfigurationId > ((sizeof (GppLaneConfigurationTable) / (NUMBER_OF_GPP_PORTS * 2)) - 1)) {
    return AGESA_ERROR;
  }
  EnginesList = PcieConfigGetChildEngine (Wrapper);
  CoreLaneIndex = 0;
  PortIdIndex = 0;
  while (EnginesList != NULL) {
    PcieConfigResetDescriptorFlags (EnginesList, DESCRIPTOR_ALLOCATED);
    EnginesList->Type.Port.PortId = GppPortIdConfigurationTable [ConfigurationId][PortIdIndex++];
    EnginesList->Type.Port.StartCoreLane = GppLaneConfigurationTable [ConfigurationId][CoreLaneIndex++];
    EnginesList->Type.Port.EndCoreLane = GppLaneConfigurationTable [ConfigurationId][CoreLaneIndex++];
    EnginesList = PcieLibGetNextDescriptor (EnginesList);
  }
  return  AGESA_SUCCESS;
}
예제 #8
0
/**
 * Helper function to dump wrapper configuration
 *
 *
 * @param[in]  WrapperList           Wrapper Configuration
 */
VOID
PcieConfigWrapperDebugDump (
  IN      PCIe_WRAPPER_CONFIG        *WrapperList
  )
{
  PCIe_ENGINE_CONFIG    *EngineList;
  IDS_HDT_CONSOLE (PCIE_MISC, "      <---------Wrapper - %s Config -------->\n",
    PcieFmDebugGetWrapperNameString (WrapperList)
    );
  IDS_HDT_CONSOLE (PCIE_MISC, "        Start PHY lane - %02d\n", WrapperList->StartPhyLane);
  IDS_HDT_CONSOLE (PCIE_MISC, "        End   PHY lane - %02d\n", WrapperList->EndPhyLane);
  IDS_HDT_CONSOLE (PCIE_MISC, "        Descriptor Flags - 0x%08x\n", WrapperList->Header.DescriptorFlags);
  IDS_HDT_CONSOLE (PCIE_MISC, "        PowerOffUnusedLanes - %x\n        PowerOffUnusedPlls - %x\n        ClkGating - %x\n"
                              "        LclkGating - %x\n        TxclkGatingPllPowerDown - %x\n        PllOffInL1 - %x\n",
    WrapperList->Features.PowerOffUnusedLanes,
    WrapperList->Features.PowerOffUnusedPlls,
    WrapperList->Features.ClkGating,
    WrapperList->Features.LclkGating,
    WrapperList->Features.TxclkGatingPllPowerDown,
    WrapperList->Features.PllOffInL1
    );
  IDS_HDT_CONSOLE (PCIE_MISC, "      <---------Wrapper - %s Config End----->\n",
    PcieFmDebugGetWrapperNameString (WrapperList)
    );
  EngineList = PcieConfigGetChildEngine (WrapperList);
  while (EngineList != NULL) {
    if (PcieLibIsEngineAllocated (EngineList)) {
      PcieConfigEngineDebugDump (EngineList);
    }
    EngineList = PcieLibGetNextDescriptor (EngineList);
  }
}
예제 #9
0
/**
 * Enable lane reversal
 *
 *
 * @param[in]  Wrapper             Pointer to wrapper config descriptor
 * @param[in]  Pcie                Pointer to global PCIe configuration
 */
VOID
PcieTopologySetLinkReversal (
  IN      PCIe_WRAPPER_CONFIG   *Wrapper,
  IN      PCIe_PLATFORM_CONFIG  *Pcie
  )
{
  PCIe_ENGINE_CONFIG  *EngineList;
  IDS_HDT_CONSOLE (GNB_TRACE, "PcieTopologySetLinkReversal Enter\n");
  EngineList = PcieConfigGetChildEngine (Wrapper);
  while (EngineList != NULL) {
    if (PcieLibIsEngineAllocated (EngineList)) {
      if (PcieLibIsPcieEngine (EngineList)) {
        if (EngineList->EngineData.StartLane > EngineList->EngineData.EndLane) {
            PciePortRegisterWriteField (
              EngineList,
              DxF0xE4_xC1_ADDRESS,
              DxF0xE4_xC1_StrapReverseLanes_OFFSET,
              DxF0xE4_xC1_StrapReverseLanes_WIDTH,
              0x1,
              FALSE,
              Pcie
              );
        }
      }
    }
    EngineList = PcieLibGetNextDescriptor (EngineList);
  }
  IDS_HDT_CONSOLE (GNB_TRACE, "PcieTopologySetLinkReversal Exit\n");
}
예제 #10
0
UINT32
PcieLanesToPowerDownPllInL1 (
  IN       UINT8                  PllPowerUpLatency,
  IN       PCIe_WRAPPER_CONFIG    *Wrapper,
  IN       PCIe_PLATFORM_CONFIG   *Pcie
  )
{
  UINT8               LaneGroupExitLatency [4];
  UINT32              LaneBitmapForPllOffInL1;
  PCIe_ENGINE_CONFIG  *EngineList;
  UINTN               Index;
  IDS_HDT_CONSOLE (GNB_TRACE, "PcieLanesToPowerDownPllInL1 Enter\n");
  LaneBitmapForPllOffInL1 = 0;
  if (PcieUtilGetWrapperLaneBitMap (LANE_TYPE_PCIE_PHY_NATIVE_ALLOC_ACTIVE | LANE_TYPE_PCIE_PHY_NATIVE_HOTPLUG, 0, Wrapper) != 0) {
    if (Wrapper->Features.PllOffInL1 != 0) {
      LibAmdMemFill (&LaneGroupExitLatency[0], 0xFF, sizeof (LaneGroupExitLatency), GnbLibGetHeader (Pcie));
      EngineList = PcieConfigGetChildEngine (Wrapper);
      while (EngineList != NULL) {
        PCIe_ASPM_LATENCY_INFO  LinkLatencyInfo;
        UINT32                  ActiveLanesBitmap;
        UINT32                  HotplugLanesBitmap;
        if (EngineList->EngineData.EngineType == PciePortEngine) {
          LinkLatencyInfo.MaxL1ExitLatency = 0;
          LinkLatencyInfo.MaxL0sExitLatency = 0;
          ActiveLanesBitmap = PcieUtilGetEngineLaneBitMap (LANE_TYPE_PCIE_PHY_NATIVE_ALLOC_ACTIVE, 0, EngineList);
          HotplugLanesBitmap = PcieUtilGetEngineLaneBitMap (LANE_TYPE_PCIE_PHY_NATIVE_HOTPLUG, 0, EngineList);
          if (ActiveLanesBitmap != 0 && HotplugLanesBitmap == 0 && !PcieConfigIsSbPcieEngine (EngineList)) {
            PcieAspmGetMaxExitLatency (EngineList->Type.Port.Address, &LinkLatencyInfo, GnbLibGetHeader (Pcie));
          }
          if (HotplugLanesBitmap != 0 || PcieConfigIsSbPcieEngine (EngineList)) {
            LinkLatencyInfo.MaxL1ExitLatency = 0xff;
          }
          IDS_HDT_CONSOLE (GNB_TRACE, "  Engine %d Active Lanes 0x%x, Hotplug Lanes 0x%x\n", EngineList->Type.Port.NativeDevNumber, ActiveLanesBitmap, HotplugLanesBitmap);
          for (Index = 0; Index < 4; Index++) {
            if ((ActiveLanesBitmap  & (0xF << (Index * 4))) != 0) {
              if (LaneGroupExitLatency [Index] > LinkLatencyInfo.MaxL1ExitLatency) {
                IDS_HDT_CONSOLE (GNB_TRACE, "  Index %d Latency %d\n", Index, LinkLatencyInfo.MaxL1ExitLatency);
                LaneGroupExitLatency [Index] = LinkLatencyInfo.MaxL1ExitLatency;
              }
            }
          }
        }
        EngineList = PcieLibGetNextDescriptor (EngineList);
      }
      LaneBitmapForPllOffInL1 = 0;
      for (Index = 0; Index < 4; Index++) {
        IDS_HDT_CONSOLE (GNB_TRACE, "  Index %d Final Latency %d\n", Index, LaneGroupExitLatency[Index]);
        if (LaneGroupExitLatency[Index] > PllPowerUpLatency) {
          LaneBitmapForPllOffInL1 |= (0xF << (Index * 4));
        }
      }
    }
  }
  IDS_HDT_CONSOLE (GNB_TRACE, "  Lane bitmap %04x\n", LaneBitmapForPllOffInL1);
  IDS_HDT_CONSOLE (GNB_TRACE, "PcieLanesToPowerDownPllInL1 Exit\n");
  return LaneBitmapForPllOffInL1;
}
예제 #11
0
AGESA_STATUS
STATIC
PcieMapPortsPciAddresses (
    IN      PCIe_SILICON_CONFIG    *Silicon,
    IN      PCIe_PLATFORM_CONFIG   *Pcie
)
{
    AGESA_STATUS        Status;
    AGESA_STATUS        AgesaStatus;
    PCIe_WRAPPER_CONFIG *WrapperList;
    PCIe_ENGINE_CONFIG  *EngineList;
    AgesaStatus = AGESA_SUCCESS;
    WrapperList = PcieConfigGetChildWrapper (Silicon);
    while (WrapperList != NULL) {
        EngineList = PcieConfigGetChildEngine (WrapperList);
        while (EngineList != NULL) {
            if (PcieLibIsPcieEngine (EngineList) && PcieLibIsEngineAllocated (EngineList)) {
                Status = PcieFmMapPortPciAddress (EngineList);
                AGESA_STATUS_UPDATE (Status, AgesaStatus);
                if (Status == AGESA_SUCCESS) {
                    EngineList->Type.Port.Address.AddressValue = MAKE_SBDFO (
                                0,
                                Silicon->Address.Address.Bus,
                                EngineList->Type.Port.PortData.DeviceNumber,
                                EngineList->Type.Port.PortData.FunctionNumber,
                                0
                            );
                } else {
                    EngineList->Type.Port.PortData.PortPresent = OFF;
                    IDS_HDT_CONSOLE (PCIE_MISC, "  ERROR! Fail to allocate PCI address for PCIe port\n"
                                    );
                    //Report error
                    PutEventLog (
                        AGESA_ERROR,
                        GNB_EVENT_INVALID_PCIE_PORT_CONFIGURATION,
                        EngineList->Type.Port.PortData.DeviceNumber,
                        0,
                        0,
                        0,
                        GnbLibGetHeader (Pcie)
                    );
                }
            }
            EngineList = PcieLibGetNextDescriptor (EngineList);
        }
        WrapperList = PcieLibGetNextDescriptor (WrapperList);
    }
    return AgesaStatus;
}
예제 #12
0
/**
 * Disable all engines on wrapper
 *
 *
 *
 * @param[in]  EngineTypeMask Engine type bitmap.
 * @param[in]  Wrapper        Pointer to wrapper config descriptor
 */
VOID
PcieConfigDisableAllEngines (
  IN      UINTN                          EngineTypeMask,
  IN      PCIe_WRAPPER_CONFIG            *Wrapper
  )
{
  PCIe_ENGINE_CONFIG        *EngineList;
  EngineList = PcieConfigGetChildEngine (Wrapper);
  while (EngineList != NULL) {
    if ((EngineList->EngineData.EngineType & EngineTypeMask) != 0) {
      PcieConfigDisableEngine (EngineList);
    }
    EngineList = PcieLibGetNextDescriptor (EngineList);
  }
}
예제 #13
0
/**
 * Locate SB engine on wrapper
 *
 *
 *
 * @param[in]  Wrapper     Pointer to wrapper config descriptor
 * @retval                 SB engine pointer or NULL
 */
PCIe_ENGINE_CONFIG *
PcieConfigLocateSbEngine (
  IN      PCIe_WRAPPER_CONFIG            *Wrapper
  )
{
  PCIe_ENGINE_CONFIG  *EngineList;
  EngineList = PcieConfigGetChildEngine (Wrapper);
  while (EngineList != NULL) {
    if (PcieConfigIsSbPcieEngine (EngineList)) {
      return EngineList;
    }
    EngineList = PcieLibGetNextDescriptor (EngineList);
  }
  return NULL;
}
예제 #14
0
VOID
PcieSiliconHidePorts (
  IN      PCIe_SILICON_CONFIG   *Silicon,
  IN      PCIe_PLATFORM_CONFIG  *Pcie
  )
{
  D0F0x64_x0C_STRUCT    D0F0x64_x0C;
  PCIe_WRAPPER_CONFIG   *WrapperList;
  D0F0x64_x0C.Value =  0;
  IDS_HDT_CONSOLE (GNB_TRACE, "PcieSiliconHidePorts Enter\n");

  D0F0x64_x0C.Value =  BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7;
  WrapperList = PcieConfigGetChildWrapper (Silicon);
  while (WrapperList != NULL) {
    PCIe_ENGINE_CONFIG   *EngineList;
    EngineList = PcieConfigGetChildEngine (WrapperList);
    while (EngineList != NULL) {
      if (PcieConfigIsPcieEngine (EngineList)) {
        if (PcieConfigIsActivePcieEngine (EngineList) && !PcieConfigIsSbPcieEngine (EngineList)) {
          D0F0x64_x0C.Value &= ~(1 << EngineList->Type.Port.Address.Address.Device);
        }
      }
      EngineList = PcieLibGetNextDescriptor (EngineList);
    }
    WrapperList = PcieLibGetNextDescriptor (WrapperList);
  }

  GnbLibPciIndirectRMW (
    Silicon->Address.AddressValue | D0F0x60_ADDRESS,
    D0F0x64_x0C_ADDRESS | IOC_WRITE_ENABLE,
    AccessS3SaveWidth32,
    (UINT32)~(BIT2 | BIT3 | BIT4 | BIT5 | BIT6 | BIT7),
    D0F0x64_x0C.Value,
    GnbLibGetHeader (Pcie)
    );
  GnbLibPciIndirectRMW (
    Silicon->Address.AddressValue | D0F0x60_ADDRESS,
    D0F0x64_x00_ADDRESS | IOC_WRITE_ENABLE,
    AccessS3SaveWidth32,
    (UINT32)~BIT6,
    0x0,
    GnbLibGetHeader (Pcie)
    );
  IDS_HDT_CONSOLE (GNB_TRACE, "Write D0F0x64_x0C.Value = %x\n", D0F0x64_x0C.Value);
  IDS_HDT_CONSOLE (GNB_TRACE, "PcieSiliconHidePorts Exit\n");
}
예제 #15
0
/**
 * Get port configuration signature for given wrapper and core
 *
 * Support for unify register access through index/data pair on GNB
 *
 * @param[in]  Wrapper     Pointer to wrapper config descriptor
 * @param[in]  CoreId      Core ID
 * @retval                 Configuration Signature
 */
UINT64
PcieConfigGetConfigurationSignature (
  IN      PCIe_WRAPPER_CONFIG            *Wrapper,
  IN      UINT8                          CoreId
  )
{
  UINT64              ConfigurationSignature;
  PCIe_ENGINE_CONFIG  *EngineList;
  ConfigurationSignature = 0;
  EngineList = PcieConfigGetChildEngine (Wrapper);
  while (EngineList != NULL) {
    if (PcieConfigIsPcieEngine (EngineList) && EngineList->Type.Port.CoreId == CoreId) {
      ConfigurationSignature = (ConfigurationSignature << 8) | PcieConfigGetNumberOfCoreLane (EngineList);
    }
    EngineList = PcieLibGetNextDescriptor (EngineList);
  }
  return ConfigurationSignature;
}
예제 #16
0
VOID
STATIC
GnbIommuMidInitCheckGfxPciePorts (
  IN      PCIe_PLATFORM_CONFIG  *Pcie
  )
{
  PCIe_WRAPPER_CONFIG   *WrapperList;
  BOOLEAN               GfxPciePortUsed;
  D0F2xF4_x57_STRUCT    D0F2xF4_x57;

  IDS_HDT_CONSOLE (GNB_TRACE, "GnbIommuMidInitCheckGfxPciePorts Enter\n");
  GfxPciePortUsed = FALSE;

  WrapperList = PcieConfigGetChildWrapper (Pcie);
  ASSERT (WrapperList != NULL);
  if (WrapperList->WrapId == GFX_WRAP_ID) {
    PCIe_ENGINE_CONFIG   *EngineList;
    EngineList = PcieConfigGetChildEngine (WrapperList);
    while (EngineList != NULL) {
      if (PcieConfigIsPcieEngine (EngineList)) {
        IDS_HDT_CONSOLE (GNB_TRACE, "Checking Gfx ports device number %x\n", EngineList->Type.Port.NativeDevNumber);
        if (PcieConfigCheckPortStatus (EngineList, INIT_STATUS_PCIE_TRAINING_SUCCESS) ||
           ((EngineList->Type.Port.PortData.LinkHotplug != HotplugDisabled) && (EngineList->Type.Port.PortData.LinkHotplug != HotplugInboard))) {
          // GFX PCIe ports beeing used
          GfxPciePortUsed = TRUE;
          IDS_HDT_CONSOLE (GNB_TRACE, "GFX PCIe ports beeing used\n");
          break;
        }
      }
      EngineList = PcieLibGetNextDescriptor (EngineList);
    }
  }

  if (!GfxPciePortUsed) {
    //D0F2xF4_x57.Field.L1ImuPcieGfxDis needs to be set
    GnbRegisterReadTN (D0F2xF4_x57_TYPE, D0F2xF4_x57_ADDRESS, &D0F2xF4_x57.Value, 0, GnbLibGetHeader (Pcie));
    D0F2xF4_x57.Field.L1ImuPcieGfxDis = 1;
    GnbRegisterWriteTN (D0F2xF4_x57_TYPE, D0F2xF4_x57_ADDRESS, &D0F2xF4_x57.Value, GNB_REG_ACC_FLAG_S3SAVE, GnbLibGetHeader (Pcie));
  }
  IDS_HDT_CONSOLE (GNB_TRACE, "GnbIommuMidInitCheckGfxPciePorts Exit\n");
}
예제 #17
0
AGESA_STATUS
STATIC
PcieLnConfigureDdiEnginesLaneAllocation (
  IN      PCIe_WRAPPER_CONFIG           *Wrapper,
  IN      UINT8                         ConfigurationId
  )
{
  PCIe_ENGINE_CONFIG  *EnginesList;
  UINTN               LaneIndex;
  EnginesList = PcieConfigGetChildEngine (Wrapper);
  if (ConfigurationId > ((sizeof (DdiLaneConfigurationTable) / (NUMBER_OF_DDIS * 2)) - 1)) {
    return AGESA_ERROR;
  }
  LaneIndex = 0;
  while (EnginesList != NULL) {
    PcieConfigResetDescriptorFlags (EnginesList, DESCRIPTOR_ALLOCATED);
    EnginesList->EngineData.StartLane = DdiLaneConfigurationTable [ConfigurationId][LaneIndex++] + Wrapper->StartPhyLane;
    EnginesList->EngineData.EndLane = DdiLaneConfigurationTable [ConfigurationId][LaneIndex++] + Wrapper->StartPhyLane;
    EnginesList = PcieLibGetNextDescriptor (EnginesList);
  }
  return  AGESA_SUCCESS;
}
예제 #18
0
/**
 * Configure engine list to support lane allocation according to configuration ID.
 *
 *
 *
 * @param[in]  Wrapper             Pointer to wrapper config descriptor
 * @param[in]  DdiLaneConfig       Lane configuration descriptor
 * @param[in]  ConfigurationId     Configuration ID
 * @retval     AGESA_SUCCESS       Configuration successfully applied
 * @retval     AGESA_ERROR         Requested configuration not supported
 */
AGESA_STATUS
PcieConfigureDdiEnginesLaneAllocationML (
  IN      PCIe_WRAPPER_CONFIG           *Wrapper,
  IN      PCIe_LANE_ALLOC_DESCRIPTOR    *DdiLaneConfig,
  IN      UINT8                         ConfigurationId
  )
{
  UINTN               LaneIndex;
  PCIe_ENGINE_CONFIG  *EnginesList;
  if (ConfigurationId >= DdiLaneConfig->NumberOfConfigurations) {
    return AGESA_ERROR;
  }
  LaneIndex = ConfigurationId * DdiLaneConfig->NumberOfEngines * 2;
  EnginesList = PcieConfigGetChildEngine (Wrapper);
  while (EnginesList != NULL) {
    if (PcieLibIsDdiEngine (EnginesList)) {
      PcieConfigResetDescriptorFlags (EnginesList, DESCRIPTOR_ALLOCATED);
      EnginesList->EngineData.StartLane = DdiLaneConfig->ConfigTable[LaneIndex++] + Wrapper->StartPhyLane;
      EnginesList->EngineData.EndLane = DdiLaneConfig->ConfigTable[LaneIndex++] + Wrapper->StartPhyLane;
    }
    EnginesList = PcieLibGetNextDescriptor (EnginesList);
  }
  return  AGESA_SUCCESS;
}
예제 #19
0
VOID
PcieTopologySelectMasterPll (
  IN       PCIe_WRAPPER_CONFIG   *Wrapper,
     OUT   BOOLEAN               *ConfigChanged,
  IN       PCIe_PLATFORM_CONFIG  *Pcie
  )
{
  PCIe_ENGINE_CONFIG        *EngineList;
  UINT16                    MasterLane;
  UINT16                    MasterHotplugLane;
  D0F0xE4_WRAP_8013_STRUCT  D0F0xE4_WRAP_8013;
  D0F0xE4_WRAP_8013_STRUCT  D0F0xE4_WRAP_8013_BASE;
  IDS_HDT_CONSOLE (GNB_TRACE, "PcieTopologySelectMasterPll Enter\n");
  MasterLane = 0xFFFF;
  MasterHotplugLane = 0xFFFF;
  EngineList = PcieConfigGetChildEngine (Wrapper);
  while (EngineList != NULL) {
    if (PcieConfigIsEngineAllocated (EngineList) && EngineList->Type.Port.PortData.PortPresent != PortDisabled && PcieConfigIsPcieEngine (EngineList)) {
      if (EngineList->Type.Port.PortData.LinkHotplug != HotplugDisabled) {
        MasterHotplugLane = PcieConfigGetPcieEngineMasterLane (EngineList);
      } else {
        MasterLane = PcieConfigGetPcieEngineMasterLane (EngineList);
        if (PcieConfigIsSbPcieEngine (EngineList)) {
          break;
        }
      }
    }
    EngineList = PcieLibGetNextDescriptor (EngineList);
  }

  if (MasterLane == 0xffff) {
    if (MasterHotplugLane != 0xffff) {
      MasterLane = MasterHotplugLane;
    } else {
      MasterLane = 0x0;
    }
  }

  D0F0xE4_WRAP_8013.Value = PcieRegisterRead (
                              Wrapper,
                              WRAP_SPACE (Wrapper->WrapId, D0F0xE4_WRAP_8013_ADDRESS),
                              Pcie
                              );
  D0F0xE4_WRAP_8013_BASE.Value = D0F0xE4_WRAP_8013.Value;
  if ( MasterLane <= 3 ) {
    D0F0xE4_WRAP_8013.Field.MasterPciePllA = 0x1;
    D0F0xE4_WRAP_8013.Field.MasterPciePllB = 0x0;
    D0F0xE4_WRAP_8013.Field.MasterPciePllC = 0x0;
    D0F0xE4_WRAP_8013.Field.MasterPciePllD = 0x0;
    Wrapper->MasterPll = 0xA;
  } else if (MasterLane <= 7) {
    D0F0xE4_WRAP_8013.Field.MasterPciePllA = 0x0;
    D0F0xE4_WRAP_8013.Field.MasterPciePllB = 0x1;
    D0F0xE4_WRAP_8013.Field.MasterPciePllC = 0x0;
    D0F0xE4_WRAP_8013.Field.MasterPciePllD = 0x0;
    Wrapper->MasterPll = 0xB;
  } else if (MasterLane <= 11) {
    D0F0xE4_WRAP_8013.Field.MasterPciePllA = 0x0;
    D0F0xE4_WRAP_8013.Field.MasterPciePllB = 0x0;
    D0F0xE4_WRAP_8013.Field.MasterPciePllC = 0x1;
    D0F0xE4_WRAP_8013.Field.MasterPciePllD = 0x0;
    Wrapper->MasterPll = 0xC;
  } else {
    D0F0xE4_WRAP_8013.Field.MasterPciePllA = 0x0;
    D0F0xE4_WRAP_8013.Field.MasterPciePllB = 0x0;
    D0F0xE4_WRAP_8013.Field.MasterPciePllC = 0x0;
    D0F0xE4_WRAP_8013.Field.MasterPciePllD = 0x1;
    Wrapper->MasterPll = 0xD;
  }
  if (ConfigChanged != NULL) {
    *ConfigChanged = (D0F0xE4_WRAP_8013.Value == D0F0xE4_WRAP_8013_BASE.Value) ? FALSE : TRUE;
  }
  PcieRegisterWrite (
    Wrapper,
    WRAP_SPACE (Wrapper->WrapId, D0F0xE4_WRAP_8013_ADDRESS),
    D0F0xE4_WRAP_8013.Value,
    FALSE,
    Pcie
    );

  IDS_HDT_CONSOLE (GNB_TRACE, "PcieTopologySelectMasterPll Exit\n");
}
예제 #20
0
VOID
PcieTopologyApplyLaneMux (
  IN      PCIe_WRAPPER_CONFIG   *Wrapper,
  IN      PCIe_PLATFORM_CONFIG  *Pcie
  )
{
  PCIe_ENGINE_CONFIG  *EngineList;
  UINT8               CurrentPhyLane;
  UINT8               CurrentCoreLane;
  UINT8               CoreLaneIndex;
  UINT8               PhyLaneIndex;
  UINT8               NumberOfPhyLane;
  UINT8               TxLaneMuxSelectorArray [sizeof (LaneMuxSelectorTable)];
  UINT8               RxLaneMuxSelectorArray [sizeof (LaneMuxSelectorTable)];
  UINT8               Index;
  UINT32              TxMaxSelectorValue;
  UINT32              RxMaxSelectorValue;

  IDS_HDT_CONSOLE (GNB_TRACE, "PcieTopologyApplyLaneMux Enter\n");
  if (PcieLibIsPcieWrapper (Wrapper)) {
    EngineList = PcieConfigGetChildEngine (Wrapper);
    LibAmdMemCopy (
      &TxLaneMuxSelectorArray[0],
      &LaneMuxSelectorTable[0],
      sizeof (LaneMuxSelectorTable),
      GnbLibGetHeader (Pcie)
      );
    LibAmdMemCopy (
      &RxLaneMuxSelectorArray[0],
      &LaneMuxSelectorTable[0],
      sizeof (LaneMuxSelectorTable),
      GnbLibGetHeader (Pcie)
      );
    while (EngineList != NULL) {
      if (PcieLibIsPcieEngine (EngineList) && PcieLibIsEngineAllocated (EngineList)) {
        CurrentPhyLane = (UINT8) PcieLibGetLoPhyLane (EngineList) - Wrapper->StartPhyLane;
        NumberOfPhyLane = (UINT8) PcieConfigGetNumberOfPhyLane (EngineList);
        CurrentCoreLane = (UINT8) EngineList->Type.Port.StartCoreLane;
        if (PcieUtilIsLinkReversed (FALSE, EngineList, Pcie)) {
          CurrentCoreLane = CurrentCoreLane + PcieConfigGetNumberOfCoreLane (EngineList) - NumberOfPhyLane;
        }
        for (Index = 0; Index < NumberOfPhyLane; Index = Index + 2 ) {
          CoreLaneIndex = (CurrentCoreLane + Index) / 2;
          PhyLaneIndex = (CurrentPhyLane + Index) / 2;

          if (RxLaneMuxSelectorArray [CoreLaneIndex] != PhyLaneIndex) {
            RxLaneMuxSelectorArray [PcieTopologyLocateMuxIndex (RxLaneMuxSelectorArray, PhyLaneIndex)] = RxLaneMuxSelectorArray [CoreLaneIndex];
            RxLaneMuxSelectorArray [CoreLaneIndex] = PhyLaneIndex;
          }
          if (TxLaneMuxSelectorArray [PhyLaneIndex] != CoreLaneIndex) {
            TxLaneMuxSelectorArray [PcieTopologyLocateMuxIndex (TxLaneMuxSelectorArray, CoreLaneIndex)] =  TxLaneMuxSelectorArray [PhyLaneIndex];
            TxLaneMuxSelectorArray [PhyLaneIndex] = CoreLaneIndex;
          }
        }
      }
      EngineList = PcieLibGetNextDescriptor (EngineList);
    }
    RxMaxSelectorValue = 0;
    TxMaxSelectorValue = 0;
    for (Index = 0; Index < sizeof (LaneMuxSelectorTable); Index++) {
      RxMaxSelectorValue |= (RxLaneMuxSelectorArray[Index] << (Index * 4));
      TxMaxSelectorValue |= (TxLaneMuxSelectorArray[Index] << (Index * 4));
    }
    PcieRegisterWrite (
      Wrapper,
      WRAP_SPACE (Wrapper->WrapId, D0F0xE4_WRAP_8021_ADDRESS),
      TxMaxSelectorValue,
      FALSE,
      Pcie
      );
    PcieRegisterWrite (
      Wrapper,
      WRAP_SPACE (Wrapper->WrapId, D0F0xE4_WRAP_8022_ADDRESS),
      RxMaxSelectorValue,
      FALSE,
      Pcie
      );
  }
  IDS_HDT_CONSOLE (GNB_TRACE, "PcieTopologyApplyLaneMux Exit\n");
}
예제 #21
0
VOID
STATIC
PcieTopologyApplyLaneMuxCZ (
  IN      PCIe_WRAPPER_CONFIG   *Wrapper,
  IN      PCIe_PLATFORM_CONFIG  *Pcie
  )
{
  PCIe_ENGINE_CONFIG  *EngineList;
  UINT32              Index;
  UINT8               RxLaneMuxSelectorArray [sizeof (LaneMuxSelectorArrayCZ)];
  UINT8               TxLaneMuxSelectorArray [sizeof (LaneMuxSelectorArrayCZ)];

  IDS_HDT_CONSOLE (GNB_TRACE, "PcieTopologyApplyLaneMuxCZ Enter\n");
  if (PcieLibIsPcieWrapper (Wrapper)) {
    LibAmdMemCopy (
      &TxLaneMuxSelectorArray[0],
      &LaneMuxSelectorArrayCZ[0],
      sizeof (LaneMuxSelectorArrayCZ),
      GnbLibGetHeader (Pcie)
      );
    LibAmdMemCopy (
      &RxLaneMuxSelectorArray[0],
      &LaneMuxSelectorArrayCZ[0],
      sizeof (LaneMuxSelectorArrayCZ),
      GnbLibGetHeader (Pcie)
      );
    EngineList = PcieConfigGetChildEngine (Wrapper);
    while (EngineList != NULL) {
      if (PcieLibIsPcieEngine (EngineList) && PcieLibIsEngineAllocated (EngineList)) {
        UINT32  CoreLaneBitmap;
        UINT32  PifLaneBitmap;
        UINT8   CurrentCoreLane;
        UINT8   CurrentPifLane;

        CoreLaneBitmap = PcieUtilGetEngineLaneBitMap (LANE_TYPE_PCIE_CORE_ALLOC, 0, EngineList);
        PifLaneBitmap = PcieUtilGetEngineLaneBitMap (LANE_TYPE_PCIE_PHY_NATIVE, 0, EngineList);
        IDS_HDT_CONSOLE (GNB_TRACE, "CoreLaneBitmap - %x, CurrentPifLane - %x\n", CoreLaneBitmap, PifLaneBitmap);


        while (CoreLaneBitmap != 0) {
          CurrentCoreLane = LibAmdBitScanForward (CoreLaneBitmap);
          CurrentPifLane = LibAmdBitScanForward (PifLaneBitmap);
          if (TxLaneMuxSelectorArray[CurrentPifLane] != CurrentCoreLane) {
            TxLaneMuxSelectorArray[PcieTopologyLocateMuxIndexCZ (TxLaneMuxSelectorArray, CurrentCoreLane)] = TxLaneMuxSelectorArray[CurrentPifLane];
            TxLaneMuxSelectorArray[CurrentPifLane] = CurrentCoreLane;
          }

          if (RxLaneMuxSelectorArray[CurrentCoreLane] != CurrentPifLane) {
            RxLaneMuxSelectorArray[PcieTopologyLocateMuxIndexCZ (RxLaneMuxSelectorArray, CurrentPifLane)] = RxLaneMuxSelectorArray[CurrentCoreLane];
            RxLaneMuxSelectorArray[CurrentCoreLane] = CurrentPifLane;
          }

          CoreLaneBitmap &= (~ (1 << CurrentCoreLane));
          PifLaneBitmap &= (~ (1 << CurrentPifLane));
        }
      }
      EngineList = PcieLibGetNextDescriptor (EngineList);
    }
    for (Index = 0; Index < 2; ++Index) {
      PcieRegisterWrite (
        Wrapper,
        CORE_SPACE (Wrapper->StartPcieCoreId, D0F0xE4_CORE_0121_ADDRESS + Index),
        ((UINT32 *) TxLaneMuxSelectorArray) [Index],
        FALSE,
        Pcie
        );
      PcieRegisterWrite (
        Wrapper,
        CORE_SPACE (Wrapper->StartPcieCoreId, D0F0xE4_CORE_0125_ADDRESS + Index),
        ((UINT32 *) RxLaneMuxSelectorArray) [Index],
        FALSE,
        Pcie
        );
    }
  }
  IDS_HDT_CONSOLE (GNB_TRACE, "PcieTopologyApplyLaneMuxCZ Exit\n");
}
예제 #22
0
/**
 * Configure engine list to support lane allocation according to configuration ID.
 *
 * PCIE port
 *
 *
 * 1 Check if lane from  user port descriptor (PCIe_PORT_DESCRIPTOR) belongs to wrapper (PCIe_WRAPPER_CONFIG)
 * 2 Check if link width from user descriptor less or equal to link width of engine (PCIe_ENGINE_CONFIG)
 * 3 Check if link width is correct. Correct link width for PCIe port x1, x2, x4, x8, x16, correct link width for DDI x4, x8
 * 4 Check if user port device number (PCIe_PORT_DESCRIPTOR) match engine port device number (PCIe_ENGINE_CONFIG)
 * 5 Check if lane can be muxed
 *
 *
 * DDI Link
 *
 * 1 Check if lane from  user port descriptor (PCIe_DDI_DESCRIPTOR) belongs to wrapper (PCIe_WRAPPER_CONFIG)
 * 2 Check lane from  (PCIe_DDI_DESCRIPTOR) match exactly phy lane (PCIe_ENGINE_CONFIG)
 *
 *
 *
 * @param[in]     ComplexDescriptor   Pointer to used define complex descriptor
 * @param[in,out] Wrapper             Pointer to wrapper config descriptor
 * @param[in]     Pcie                Pointer to global PCIe configuration
 * @retval        AGESA_SUCCESS       Topology successfully mapped
 * @retval        AGESA_ERROR         Topology can not be mapped
 */
AGESA_STATUS
PcieMapTopologyOnWrapper (
    IN       PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
    IN OUT   PCIe_WRAPPER_CONFIG         *Wrapper,
    IN       PCIe_PLATFORM_CONFIG        *Pcie
)
{
    AGESA_STATUS                AgesaStatus;
    AGESA_STATUS                Status;
    PCIe_ENGINE_CONFIG          *EngineList;
    UINT32                      WrapperPhyLaneBitMap;
    IDS_HDT_CONSOLE (GNB_TRACE, "PcieMapTopologyOnWrapper Enter\n");
    AgesaStatus = AGESA_SUCCESS;
    if (PcieLibIsPcieWrapper (Wrapper)) {
        Status = PcieEnginesToWrapper (PciePortEngine, ComplexDescriptor, Wrapper);
        AGESA_STATUS_UPDATE (Status, AgesaStatus);
        if (Status == AGESA_ERROR) {
            // If we can not map topology on wrapper we can not enable any engines.
            PutEventLog (
                AGESA_ERROR,
                GNB_EVENT_INVALID_PCIE_TOPOLOGY_CONFIGURATION,
                Wrapper->WrapId,
                Wrapper->StartPhyLane,
                Wrapper->EndPhyLane,
                0,
                GnbLibGetHeader (Pcie)
            );
            PcieConfigDisableAllEngines (PciePortEngine, Wrapper);
        }
    }
    if (PcieLibIsDdiWrapper (Wrapper)) {
        Status = PcieEnginesToWrapper (PcieDdiEngine, ComplexDescriptor, Wrapper);
        AGESA_STATUS_UPDATE (Status, AgesaStatus);
        if (Status == AGESA_ERROR) {
            // If we can not map topology on wrapper we can not enable any engines.
            PutEventLog (
                AGESA_ERROR,
                GNB_EVENT_INVALID_DDI_TOPOLOGY_CONFIGURATION,
                Wrapper->WrapId,
                Wrapper->StartPhyLane,
                Wrapper->EndPhyLane,
                0,
                GnbLibGetHeader (Pcie)
            );
            PcieConfigDisableAllEngines (PcieDdiEngine, Wrapper);
        }
    }
    // Copy engine data
    PcieMapInitializeEngineData (ComplexDescriptor, Wrapper, Pcie);

    EngineList = PcieConfigGetChildEngine (Wrapper);
    // Verify if we oversubscribe lanes and PHY link width
    WrapperPhyLaneBitMap = 0;
    while (EngineList != NULL) {
        UINT32  EnginePhyLaneBitMap;
        if (PcieLibIsEngineAllocated (EngineList)) {
            EnginePhyLaneBitMap = PcieConfigGetEnginePhyLaneBitMap (EngineList);
            if ((WrapperPhyLaneBitMap & EnginePhyLaneBitMap) != 0) {
                IDS_HDT_CONSOLE (PCIE_MISC, "  ERROR! Lanes double subscribe lanes [Engine Lanes %d..%d]\n",
                                 EngineList->EngineData.StartLane,
                                 EngineList->EngineData.EndLane
                                );
                PutEventLog (
                    AGESA_ERROR,
                    GNB_EVENT_INVALID_LANES_CONFIGURATION,
                    EngineList->EngineData.StartLane,
                    EngineList->EngineData.EndLane,
                    0,
                    0,
                    GnbLibGetHeader (Pcie)
                );
                PcieConfigDisableEngine (EngineList);
                Status = AGESA_ERROR;
                AGESA_STATUS_UPDATE (Status, AgesaStatus);
            } else {
                WrapperPhyLaneBitMap |= EnginePhyLaneBitMap;
            }
        }
        EngineList = PcieLibGetNextDescriptor (EngineList);
    }
    IDS_HDT_CONSOLE (GNB_TRACE, "PcieMapTopologyOnWrapper Exit [%d]\n", AgesaStatus);
    return AgesaStatus;
}
예제 #23
0
/**
 * Configure engine list to support lane allocation according to configuration ID.
 *
 *
 *
 * @param[in]  EngineType          Engine type
 * @param[in]  ComplexDescriptor   Pointer to used define complex descriptor
 * @param[in]  Wrapper             Pointer to wrapper config descriptor
 * @retval     AGESA_SUCCESS       Topology successfully mapped
 * @retval     AGESA_ERROR         Topology can not be mapped
 */
STATIC AGESA_STATUS
PcieEnginesToWrapper (
    IN      PCIE_ENGINE_TYPE            EngineType,
    IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
    IN      PCIe_WRAPPER_CONFIG         *Wrapper
)
{
    AGESA_STATUS                Status;
    PCIe_ENGINE_CONFIG          *EngineList;
    PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor;
    UINT8                       ConfigurationId;
    UINT8                       Allocations;
    UINTN                       Index;
    UINTN                       NumberOfDescriptors;

    ConfigurationId = 0;
    Allocations = 0;
    IDS_HDT_CONSOLE (GNB_TRACE, "PcieEnginesToWrapper Enter\n");
    NumberOfDescriptors = PcieInputParserGetNumberOfEngines (ComplexDescriptor);
    do {
        Status = PcieFmConfigureEnginesLaneAllocation (Wrapper, EngineType, ConfigurationId++);
        if (Status == AGESA_SUCCESS) {
            Allocations = 0;
            for (Index = 0; Index < NumberOfDescriptors; Index++) {
                EngineDescriptor = PcieInputParserGetEngineDescriptor (ComplexDescriptor, Index);
                if (EngineDescriptor->EngineData.EngineType == EngineType) {
                    // Step 1, belongs to wrapper check.
                    if (PcieCheckDescriptorMapsToWrapper (EngineDescriptor, Wrapper)) {
                        ++Allocations;
                        EngineList = PcieConfigGetChildEngine (Wrapper);
                        while (EngineList != NULL) {
                            if (!PcieLibIsEngineAllocated (EngineList)) {
                                // Step 2.user descriptor less or equal to link width of engine
                                if (PcieCheckLanesMatch (EngineDescriptor, EngineList)) {
                                    // Step 3, Check if link width is correct.x1, x2, x4, x8, x16.
                                    if (!PcieIsDescriptorLinkWidthValid (EngineDescriptor)) {
                                        PcieConfigDisableEngine (EngineList);
                                        return AGESA_ERROR;
                                    }
                                    if (EngineDescriptor->EngineData.EngineType == PciePortEngine) {
                                        // Step 4, Family specifc, port device number match engine device
                                        if (PcieCheckPortPciDeviceMapping ((PCIe_PORT_DESCRIPTOR*) EngineDescriptor, EngineList)) {
                                            //Step 5, Family specifc, lanes can be muxed.
                                            if (PcieFmCheckPortPcieLaneCanBeMuxed ((PCIe_PORT_DESCRIPTOR*) EngineDescriptor, EngineList)) {
                                                PcieAllocateEngine ((UINT8) Index, EngineList);
                                                --Allocations;
                                                break;
                                            }
                                        }
                                    } else {
                                        PcieAllocateEngine ((UINT8) Index, EngineList);
                                        --Allocations;
                                        break;
                                    }
                                }
                            } //end if PcieLibIsEngineAllocated
                            EngineList = PcieLibGetNextDescriptor (EngineList);
                        }
                    } //end if PcieCheckDescriptorMapsToWrapper
                } // end if EngineType
            } //end for
        }
    } while (Status == AGESA_SUCCESS && Allocations != 0);
    IDS_HDT_CONSOLE (GNB_TRACE, "PcieEnginesToWrapper Exit [%x]\n", Status);
    return Status;
}