summaryrefslogtreecommitdiff
path: root/src/vendorcode/amd/agesa/f15tn/Proc/GNB/Modules/GnbPcieConfig/PcieConfigData.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/amd/agesa/f15tn/Proc/GNB/Modules/GnbPcieConfig/PcieConfigData.c')
-rw-r--r--src/vendorcode/amd/agesa/f15tn/Proc/GNB/Modules/GnbPcieConfig/PcieConfigData.c561
1 files changed, 561 insertions, 0 deletions
diff --git a/src/vendorcode/amd/agesa/f15tn/Proc/GNB/Modules/GnbPcieConfig/PcieConfigData.c b/src/vendorcode/amd/agesa/f15tn/Proc/GNB/Modules/GnbPcieConfig/PcieConfigData.c
new file mode 100644
index 0000000000..febae7f986
--- /dev/null
+++ b/src/vendorcode/amd/agesa/f15tn/Proc/GNB/Modules/GnbPcieConfig/PcieConfigData.c
@@ -0,0 +1,561 @@
+/* $NoKeywords:$ */
+/**
+ * @file
+ *
+ * GNB function to create/locate PCIe configuration data area
+ *
+ * Contain code that create/locate and rebase configuration data area.
+ *
+ * @xrefitem bom "File Content Label" "Release Content"
+ * @e project: AGESA
+ * @e sub-project: GNB
+ * @e \$Revision: 63425 $ @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
+ *
+ */
+/*
+*****************************************************************************
+*
+* Copyright 2008 - 2012 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
+*
+* AMD is granting you permission to use this software (the Materials)
+* pursuant to the terms and conditions of your Software License Agreement
+* with AMD. This header does *NOT* give you permission to use the Materials
+* or any rights under AMD's intellectual property. Your use of any portion
+* of these Materials shall constitute your acceptance of those terms and
+* conditions. If you do not agree to the terms and conditions of the Software
+* License Agreement, please do not use any portion of these Materials.
+*
+* CONFIDENTIALITY: The Materials and all other information, identified as
+* confidential and provided to you by AMD shall be kept confidential in
+* accordance with the terms and conditions of the Software License Agreement.
+*
+* LIMITATION OF LIABILITY: THE MATERIALS AND ANY OTHER RELATED INFORMATION
+* PROVIDED TO YOU BY AMD ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED
+* WARRANTY OF ANY KIND, INCLUDING BUT NOT LIMITED TO WARRANTIES OF
+* MERCHANTABILITY, NONINFRINGEMENT, TITLE, FITNESS FOR ANY PARTICULAR PURPOSE,
+* OR WARRANTIES ARISING FROM CONDUCT, COURSE OF DEALING, OR USAGE OF TRADE.
+* IN NO EVENT SHALL AMD OR ITS LICENSORS BE LIABLE FOR ANY DAMAGES WHATSOEVER
+* (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
+* INTERRUPTION, OR LOSS OF INFORMATION) ARISING OUT OF AMD'S NEGLIGENCE,
+* GROSS NEGLIGENCE, THE USE OF OR INABILITY TO USE THE MATERIALS OR ANY OTHER
+* RELATED INFORMATION PROVIDED TO YOU BY AMD, EVEN IF AMD HAS BEEN ADVISED OF
+* THE POSSIBILITY OF SUCH DAMAGES. BECAUSE SOME JURISDICTIONS PROHIBIT THE
+* EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES,
+* THE ABOVE LIMITATION MAY NOT APPLY TO YOU.
+*
+* AMD does not assume any responsibility for any errors which may appear in
+* the Materials or any other related information provided to you by AMD, or
+* result from use of the Materials or any related information.
+*
+* You agree that you will not reverse engineer or decompile the Materials.
+*
+* NO SUPPORT OBLIGATION: AMD is not obligated to furnish, support, or make any
+* further information, software, technical information, know-how, or show-how
+* available to you. Additionally, AMD retains the right to modify the
+* Materials at any time, without notice, and is not obligated to provide such
+* modified Materials to you.
+*
+* U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
+* "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
+* subject to the restrictions as set forth in FAR 52.227-14 and
+* DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
+* Government constitutes acknowledgement of AMD's proprietary rights in them.
+*
+* EXPORT ASSURANCE: You agree and certify that neither the Materials, nor any
+* direct product thereof will be exported directly or indirectly, into any
+* country prohibited by the United States Export Administration Act and the
+* regulations thereunder, without the required authorization from the U.S.
+* government nor will be used for any purpose prohibited by the same.
+* ***************************************************************************
+*
+*/
+
+/*----------------------------------------------------------------------------------------
+ * M O D U L E S U S E D
+ *----------------------------------------------------------------------------------------
+ */
+#include "AGESA.h"
+#include "Ids.h"
+#include "amdlib.h"
+#include "heapManager.h"
+#include "OptionGnb.h"
+#include "Gnb.h"
+#include "GnbPcie.h"
+#include "GnbPcieFamServices.h"
+#include "GnbFamServices.h"
+#include "cpuServices.h"
+#include "GnbCommonLib.h"
+#include "GnbPcieConfig.h"
+#include "PcieMapTopology.h"
+#include "PcieInputParser.h"
+#include "PcieConfigLib.h"
+#include "Filecode.h"
+#define FILECODE PROC_GNB_MODULES_GNBPCIECONFIG_PCIECONFIGDATA_FILECODE
+/*----------------------------------------------------------------------------------------
+ * D E F I N I T I O N S A N D M A C R O S
+ *----------------------------------------------------------------------------------------
+ */
+
+extern BUILD_OPT_CFG UserOptions;
+extern GNB_BUILD_OPTIONS ROMDATA GnbBuildOptions;
+
+/*----------------------------------------------------------------------------------------
+ * T Y P E D E F S A N D S T R U C T U R E S
+ *----------------------------------------------------------------------------------------
+ */
+
+#define PcieConfigAttachChild(P, C) (P)->Child = (UINT16) ((UINT8 *) C - (UINT8 *) P);
+#define PcieConfigAttachParent(P, C) (C)->Parent = (UINT16) ((UINT8 *) C - (UINT8 *) P);
+
+/*----------------------------------------------------------------------------------------
+ * P R O T O T Y P E S O F L O C A L F U N C T I O N S
+ *----------------------------------------------------------------------------------------
+ */
+
+VOID
+STATIC
+PcieConfigAttachComplexes (
+ IN OUT PCIe_COMPLEX_CONFIG *Base,
+ IN OUT PCIe_COMPLEX_CONFIG *New
+ );
+
+AGESA_STATUS
+PcieUpdateConfigurationData (
+ IN PCIe_PLATFORM_CONFIG *Pcie
+ );
+
+PCIe_COMPLEX_DESCRIPTOR *
+PcieConfigProcessUserConfig (
+ IN PCIe_COMPLEX_DESCRIPTOR *PcieComplexList,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+PcieConfigurationInit (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+AGESA_STATUS
+PcieConfigurationMap (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ );
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Create internal PCIe configuration topology
+ *
+ *
+ *
+ * @param[in] StdHeader Standard configuration header
+ * @retval AGESA_SUCCESS Configuration data successfully allocated.
+ * @retval AGESA_FATAL Configuration data allocation failed.
+ */
+
+AGESA_STATUS
+PcieConfigurationInit (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+
+ AGESA_STATUS Status;
+ PCIe_PLATFORM_CONFIG *Pcie;
+ PCIe_SILICON_CONFIG *Silicon;
+ UINT8 SocketId;
+ UINTN CurrentComplexesDataLength;
+ UINTN ComplexesDataLength;
+ UINT8 ComplexIndex;
+ VOID *Buffer;
+ ComplexesDataLength = 0;
+ Status = AGESA_SUCCESS;
+ IDS_HDT_CONSOLE (GNB_TRACE, "PcieConfigurationInit Enter\n");
+ for (SocketId = 0; SocketId < GetPlatformNumberOfSockets (); SocketId++) {
+ if (IsProcessorPresent (SocketId, StdHeader)) {
+ Status = PcieFmGetComplexDataLength (SocketId, &CurrentComplexesDataLength, StdHeader);
+ ASSERT (Status == AGESA_SUCCESS);
+ ComplexesDataLength += CurrentComplexesDataLength;
+ }
+ }
+ ComplexIndex = 0;
+ Pcie = GnbAllocateHeapBufferAndClear (AMD_PCIE_COMPLEX_DATA_HANDLE, sizeof (PCIe_PLATFORM_CONFIG) + ComplexesDataLength, StdHeader);
+ ASSERT (Pcie != NULL);
+ if (Pcie != NULL) {
+ PcieConfigAttachChild (&Pcie->Header, &Pcie->ComplexList[ComplexIndex].Header);
+ PcieConfigSetDescriptorFlags (Pcie, DESCRIPTOR_PLATFORM | DESCRIPTOR_TERMINATE_LIST | DESCRIPTOR_TERMINATE_TOPOLOGY);
+ Buffer = (UINT8 *) (Pcie) + sizeof (PCIe_PLATFORM_CONFIG);
+ for (SocketId = 0; SocketId < GetPlatformNumberOfSockets (); SocketId++) {
+ if (IsProcessorPresent (SocketId, StdHeader)) {
+ Pcie->ComplexList[ComplexIndex].SocketId = SocketId;
+ //Attache Comples to Silicon which will be created by PcieFmBuildComplexConfiguration
+ PcieConfigAttachChild (&Pcie->ComplexList[ComplexIndex].Header, &((PCIe_SILICON_CONFIG *) Buffer)->Header);
+ //Attach Comples to Pcie
+ PcieConfigAttachParent (&Pcie->Header, &Pcie->ComplexList[ComplexIndex].Header);
+ PcieConfigSetDescriptorFlags (&Pcie->ComplexList[ComplexIndex], DESCRIPTOR_COMPLEX | DESCRIPTOR_TERMINATE_LIST | DESCRIPTOR_TERMINATE_GNB | DESCRIPTOR_TERMINATE_TOPOLOGY);
+ PcieFmBuildComplexConfiguration (SocketId, Buffer, StdHeader);
+ Silicon = PcieConfigGetChildSilicon (&Pcie->ComplexList[ComplexIndex]);
+ while (Silicon != NULL) {
+ PcieConfigAttachParent (&Pcie->ComplexList[ComplexIndex].Header, &Silicon->Header);
+ GetNodeId (SocketId, Silicon->SiliconId, &Silicon->NodeId, StdHeader);
+ GnbFmGetLinkId ((GNB_HANDLE*) Silicon, &Silicon->LinkId, StdHeader);
+ Silicon = (PCIe_SILICON_CONFIG *) PcieConfigGetNextTopologyDescriptor (Silicon, DESCRIPTOR_TERMINATE_TOPOLOGY);
+ }
+
+ if (ComplexIndex > 0) {
+ PcieConfigAttachComplexes (&Pcie->ComplexList[ComplexIndex - 1], &Pcie->ComplexList[ComplexIndex]);
+ }
+ PcieFmGetComplexDataLength (SocketId, &CurrentComplexesDataLength, StdHeader);
+ Buffer = (VOID *) ((UINT8 *) Buffer + CurrentComplexesDataLength);
+ ComplexIndex++;
+ }
+ }
+ } else {
+ Status = AGESA_FATAL;
+ }
+ IDS_HDT_CONSOLE (GNB_TRACE, "PcieConfigurationInit Exit [0x%x]\n", Status);
+ return Status;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Create internal PCIe configuration topology
+ *
+ *
+ *
+ * @param[in] StdHeader Standard configuration header
+ * @retval AGESA_SUCCESS Configuration data successfully allocated.
+ * @retval AGESA_FATAL Configuration data allocation failed.
+ */
+
+AGESA_STATUS
+PcieConfigurationMap (
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ AMD_EARLY_PARAMS *EarlyParamsPtr;
+ PCIe_COMPLEX_DESCRIPTOR *PcieComplexList;
+ PCIe_PLATFORM_CONFIG *Pcie;
+ PCIe_COMPLEX_CONFIG *Complex;
+ PCIe_COMPLEX_DESCRIPTOR *ComplexDescriptor;
+ AGESA_STATUS Status;
+ AGESA_STATUS AgesaStatus;
+ UINTN Index;
+ UINTN NumberOfComplexes;
+ IDS_HDT_CONSOLE (GNB_TRACE, "PcieConfigurationMap Enter\n");
+ AgesaStatus = AGESA_SUCCESS;
+ EarlyParamsPtr = (AMD_EARLY_PARAMS *) StdHeader;
+ PcieComplexList = PcieConfigProcessUserConfig (EarlyParamsPtr->GnbConfig.PcieComplexList, StdHeader);
+ GNB_DEBUG_CODE (
+ if (PcieComplexList != NULL) {
+ PcieUserConfigConfigDump (PcieComplexList);
+ }
+ );
+ Status = PcieLocateConfigurationData (StdHeader, &Pcie);
+ ASSERT (Status == AGESA_SUCCESS);
+ if (Status == AGESA_SUCCESS) {
+ Complex = (PCIe_COMPLEX_CONFIG *) PcieConfigGetChild (DESCRIPTOR_COMPLEX, &Pcie->Header);
+ NumberOfComplexes = PcieInputParserGetNumberOfComplexes (PcieComplexList);
+ while (Complex != NULL) {
+ for (Index = 0; Index < NumberOfComplexes; Index++) {
+ ComplexDescriptor = PcieInputParserGetComplexDescriptor (PcieComplexList, Index);
+ if (ComplexDescriptor->SocketId == Complex->SocketId) {
+ Status = PcieMapTopologyOnComplex (ComplexDescriptor, Complex, Pcie);
+ AGESA_STATUS_UPDATE (Status, AgesaStatus);
+ }
+ }
+ Complex = PcieLibGetNextDescriptor (Complex);
+ }
+ }
+ Pcie->LinkReceiverDetectionPooling = GnbBuildOptions.CfgGnbLinkReceiverDetectionPooling;
+ Pcie->LinkL0Pooling = GnbBuildOptions.CfgGnbLinkL0Pooling;
+ Pcie->LinkGpioResetAssertionTime = GnbBuildOptions.CfgGnbLinkGpioResetAssertionTime;
+ Pcie->LinkResetToTrainingTime = GnbBuildOptions.CfgGnbLinkResetToTrainingTime;
+ Pcie->GfxCardWorkaround = GfxWorkaroundEnable;
+ Pcie->TrainingExitState = LinkStateTrainingCompleted;
+ Pcie->TrainingAlgorithm = GnbBuildOptions.CfgGnbTrainingAlgorithm;
+ if ((UserOptions.CfgAmdPlatformType & AMD_PLATFORM_MOBILE) != 0) {
+ Pcie->GfxCardWorkaround = GfxWorkaroundDisable;
+ }
+ Pcie->PsppPolicy = EarlyParamsPtr->GnbConfig.PsppPolicy;
+ IDS_OPTION_CALLOUT (IDS_CALLOUT_GNB_PCIE_PLATFORM_CONFIG, Pcie, StdHeader);
+ GNB_DEBUG_CODE (
+ PcieConfigDebugDump (Pcie);
+ );
+ HeapDeallocateBuffer (AMD_GNB_TEMP_DATA_HANDLE, StdHeader);
+ IDS_HDT_CONSOLE (GNB_TRACE, "PcieConfigurationInit Exit [0x%x]\n", AgesaStatus);
+ return AgesaStatus;
+}
+
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Locate global PCIe configuration data
+ *
+ *
+ *
+ * @param[in] PcieComplexList User PCIe topology configuration
+ * @param[out] StdHeader Standard configuration header
+ * @retval Updated topology configuration
+ */
+PCIe_COMPLEX_DESCRIPTOR *
+PcieConfigProcessUserConfig (
+ IN PCIe_COMPLEX_DESCRIPTOR *PcieComplexList,
+ IN AMD_CONFIG_PARAMS *StdHeader
+ )
+{
+ UINT32 Node0SocketId;
+ UINT32 Node0SiliconId;
+ UINTN NumberOfComplexes;
+ UINTN NumberOfPorts;
+ UINTN Index;
+ UINT16 DescriptorLoLane;
+ UINT16 DescriptorHiLane;
+ PCIe_COMPLEX_DESCRIPTOR *ResultComplexConfig;
+ PCIe_COMPLEX_DESCRIPTOR *SbComplexDescriptor;
+ PCIe_PORT_DESCRIPTOR *SbPortDescriptor;
+ PCIe_PORT_DESCRIPTOR DefaultSbPortDescriptor;
+ PCIe_ENGINE_DESCRIPTOR *EngineDescriptor;
+ AGESA_STATUS Status;
+ SbPortDescriptor = NULL;
+ GetSocketModuleOfNode (0, &Node0SocketId, &Node0SiliconId, StdHeader);
+ Status = PcieFmGetSbConfigInfo ((UINT8) Node0SocketId, &DefaultSbPortDescriptor, StdHeader);
+ if (Status == AGESA_UNSUPPORTED) {
+ return PcieComplexList;
+ }
+ if (PcieComplexList == NULL) {
+ // No complex descriptor for any silicon was provided
+ // 1. Create complex descriptor
+ // 2. Create SB port descriptor
+ // 3. Attach SB descriptor to complex descriptor created in step #1
+ ResultComplexConfig = (PCIe_COMPLEX_DESCRIPTOR *) GnbAllocateHeapBufferAndClear (
+ AMD_GNB_TEMP_DATA_HANDLE,
+ sizeof (PCIe_COMPLEX_DESCRIPTOR) + sizeof (PCIe_PORT_DESCRIPTOR),
+ StdHeader
+ );
+ SbComplexDescriptor = ResultComplexConfig;
+ SbPortDescriptor = (PCIe_PORT_DESCRIPTOR *) ((UINT8 *) ResultComplexConfig + sizeof (PCIe_COMPLEX_DESCRIPTOR));
+ LibAmdMemCopy (SbPortDescriptor, &DefaultSbPortDescriptor, sizeof (PCIe_PORT_DESCRIPTOR), StdHeader);
+ SbPortDescriptor->Flags |= DESCRIPTOR_TERMINATE_LIST;
+ // Attach post array to complex descriptor
+ SbComplexDescriptor->PciePortList = SbPortDescriptor;
+ SbComplexDescriptor->SocketId = Node0SocketId;
+ SbComplexDescriptor->Flags |= DESCRIPTOR_TERMINATE_LIST;
+ } else {
+ NumberOfComplexes = PcieInputParserGetNumberOfComplexes (PcieComplexList);
+ SbComplexDescriptor = PcieInputParserGetComplexDescriptorOfSocket (PcieComplexList, Node0SocketId);
+ if (SbComplexDescriptor == NULL) {
+ // No complex descriptor for silicon that have SB attached.
+ // 1. Create complex descriptor. Will be first one in the list
+ // 2. Create SB port descriptor
+ // 3. Attach SB descriptor to complex descriptor created in step #1
+ ResultComplexConfig = (PCIe_COMPLEX_DESCRIPTOR *) GnbAllocateHeapBufferAndClear (
+ AMD_GNB_TEMP_DATA_HANDLE,
+ (NumberOfComplexes + 1) * sizeof (PCIe_COMPLEX_DESCRIPTOR) + sizeof (PCIe_PORT_DESCRIPTOR),
+ StdHeader
+ );
+ SbComplexDescriptor = ResultComplexConfig;
+ SbPortDescriptor = (PCIe_PORT_DESCRIPTOR *) ((UINT8 *) ResultComplexConfig + (NumberOfComplexes + 1) * sizeof (PCIe_COMPLEX_DESCRIPTOR));
+ LibAmdMemCopy (SbPortDescriptor, &DefaultSbPortDescriptor, sizeof (PCIe_PORT_DESCRIPTOR), StdHeader);
+ SbPortDescriptor->Flags |= DESCRIPTOR_TERMINATE_LIST;
+ // Attach post array to complex descriptor
+ SbComplexDescriptor->PciePortList = SbPortDescriptor;
+ SbComplexDescriptor->SocketId = Node0SocketId;
+ SbComplexDescriptor->Flags |= DESCRIPTOR_TERMINATE_LIST;
+ LibAmdMemCopy (
+ (UINT8 *) ResultComplexConfig + sizeof (PCIe_COMPLEX_DESCRIPTOR),
+ PcieComplexList,
+ NumberOfComplexes * sizeof (PCIe_COMPLEX_DESCRIPTOR),
+ StdHeader
+ );
+
+ } else {
+ // Complex descriptor that represent silicon that have SB attached exist
+ // 1. Determine if complex have descriptor for SB
+ // 2. Create new descriptor for SB if needed
+ NumberOfPorts = PcieInputParserGetLengthOfPcieEnginesList (SbComplexDescriptor);
+ ResultComplexConfig = (PCIe_COMPLEX_DESCRIPTOR *) GnbAllocateHeapBuffer (
+ AMD_GNB_TEMP_DATA_HANDLE,
+ NumberOfComplexes * sizeof (PCIe_COMPLEX_DESCRIPTOR) + (NumberOfPorts + 1) * sizeof (PCIe_PORT_DESCRIPTOR),
+ StdHeader
+ );
+ // Copy complex descriptor array
+ LibAmdMemCopy (
+ ResultComplexConfig,
+ PcieComplexList,
+ NumberOfComplexes * sizeof (PCIe_COMPLEX_DESCRIPTOR),
+ StdHeader
+ );
+ if (NumberOfPorts != 0) {
+ // Copy port descriptor array associated with complex with SB attached
+ LibAmdMemCopy (
+ (UINT8*) ResultComplexConfig + NumberOfComplexes * sizeof (PCIe_COMPLEX_DESCRIPTOR) + sizeof (PCIe_PORT_DESCRIPTOR),
+ SbComplexDescriptor->PciePortList,
+ NumberOfPorts * sizeof (PCIe_PORT_DESCRIPTOR),
+ StdHeader
+ );
+ // Update SB complex pointer on in memory list
+ SbComplexDescriptor = PcieInputParserGetComplexDescriptorOfSocket ((PCIe_COMPLEX_DESCRIPTOR *) ResultComplexConfig, Node0SocketId);
+ // Attach port descriptor array to complex
+ SbComplexDescriptor->PciePortList = (PCIe_PORT_DESCRIPTOR *) ((UINT8*) ResultComplexConfig + NumberOfComplexes * sizeof (PCIe_COMPLEX_DESCRIPTOR) + sizeof (PCIe_PORT_DESCRIPTOR));
+ for (Index = 0; Index < NumberOfPorts; ++Index) {
+ EngineDescriptor = PcieInputParserGetEngineDescriptor (SbComplexDescriptor, Index);
+ if (EngineDescriptor->EngineData.EngineType == PciePortEngine) {
+ DescriptorLoLane = MIN (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
+ DescriptorHiLane = MAX (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
+ if (DescriptorLoLane >= DefaultSbPortDescriptor.EngineData.StartLane && DescriptorLoLane <= DefaultSbPortDescriptor.EngineData.EndLane) {
+ SbPortDescriptor = (PCIe_PORT_DESCRIPTOR *) EngineDescriptor;
+ }
+ }
+ }
+ }
+ if (SbPortDescriptor == NULL) {
+ // No descriptor that represent SB where found, create new one, will be first one in list
+ SbPortDescriptor = (PCIe_PORT_DESCRIPTOR *) ((UINT8*) ResultComplexConfig + NumberOfComplexes * sizeof (PCIe_COMPLEX_DESCRIPTOR));
+ // Copy default config info
+ LibAmdMemCopy (SbPortDescriptor, &DefaultSbPortDescriptor, sizeof (PCIe_PORT_DESCRIPTOR), StdHeader);
+ // Reattach descriptor list to complex
+ SbComplexDescriptor->PciePortList = SbPortDescriptor;
+ } else {
+ // Move SB descriptor to be first one in array
+ LibAmdMemCopy (
+ (UINT8*) ResultComplexConfig + NumberOfComplexes * sizeof (PCIe_COMPLEX_DESCRIPTOR),
+ SbPortDescriptor,
+ sizeof (PCIe_PORT_DESCRIPTOR),
+ StdHeader
+ );
+ // Disable original SB descriptor
+ SbPortDescriptor->EngineData.EngineType = PcieUnusedEngine;
+ //Update pointer to new SB descriptor
+ SbPortDescriptor = (PCIe_PORT_DESCRIPTOR *) ((UINT8*) ResultComplexConfig + NumberOfComplexes * sizeof (PCIe_COMPLEX_DESCRIPTOR));
+ //It is no longer a descriptor that terminates list
+ SbPortDescriptor->Flags &= (~ DESCRIPTOR_TERMINATE_LIST);
+ // Reattach descriptor list to complex
+ SbComplexDescriptor->PciePortList = SbPortDescriptor;
+ }
+ }
+ }
+ // Mark descriptor as SB link
+ SbPortDescriptor->Port.MiscControls.SbLink = 0x1;
+ return ResultComplexConfig;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Locate global PCIe configuration data
+ *
+ *
+ *
+ * @param[in] StdHeader Standard configuration header
+ * @param[out] Pcie Pointer to global PCIe configuration
+ * @retval AGESA_SUCCESS Configuration data successfully located
+ * @retval AGESA_FATAL Configuration can not be located.
+ */
+AGESA_STATUS
+PcieLocateConfigurationData (
+ IN AMD_CONFIG_PARAMS *StdHeader,
+ OUT PCIe_PLATFORM_CONFIG **Pcie
+ )
+{
+ *Pcie = GnbLocateHeapBuffer (AMD_PCIE_COMPLEX_DATA_HANDLE, StdHeader);
+ if (*Pcie == NULL) {
+ IDS_ERROR_TRAP;
+ return AGESA_FATAL;
+ }
+ (*Pcie)->StdHeader = /* (PVOID) */ (UINT32)StdHeader;
+ PcieUpdateConfigurationData (*Pcie);
+ return AGESA_SUCCESS;
+}
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Attache descriptors
+ *
+ *
+ * @param[in] Type Descriptor type
+ * @param[in,out] Base Base descriptor
+ * @param[in,out] New New descriptor
+ */
+VOID
+STATIC
+PcieConfigAttachDescriptors (
+ IN UINT32 Type,
+ IN OUT PCIe_DESCRIPTOR_HEADER *Base,
+ IN OUT PCIe_DESCRIPTOR_HEADER *New
+ )
+{
+ PCIe_DESCRIPTOR_HEADER *Left;
+ PCIe_DESCRIPTOR_HEADER *Right;
+
+ Left = PcieConfigGetPeer (DESCRIPTOR_TERMINATE_GNB, PcieConfigGetChild (Type, Base));
+ ASSERT (Left != NULL);
+ Right = PcieConfigGetChild (Type, New);
+ Left->Peer = (UINT16) ((UINT8 *) Right - (UINT8 *) Left);
+ PcieConfigResetDescriptorFlags (Left, DESCRIPTOR_TERMINATE_TOPOLOGY);
+}
+
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Attach configurations of two GNB to each other.
+ *
+ * Function will link all data structure to linked lists
+ *
+ * @param[in,out] Base Base complex descriptor
+ * @param[in,out] New New complex descriptor
+ */
+VOID
+STATIC
+PcieConfigAttachComplexes (
+ IN OUT PCIe_COMPLEX_CONFIG *Base,
+ IN OUT PCIe_COMPLEX_CONFIG *New
+ )
+{
+ // Connect Complex
+ Base->Header.Peer = (UINT16) ((UINT8 *) New - (UINT8 *) Base);
+ PcieConfigResetDescriptorFlags (Base, DESCRIPTOR_TERMINATE_TOPOLOGY);
+ // Connect Silicon
+ PcieConfigAttachDescriptors (DESCRIPTOR_SILICON, &Base->Header, &New->Header);
+ // Connect Wrappers
+ PcieConfigAttachDescriptors (DESCRIPTOR_PCIE_WRAPPER | DESCRIPTOR_DDI_WRAPPER, &Base->Header, &New->Header);
+ // Connect Engines
+ PcieConfigAttachDescriptors (DESCRIPTOR_PCIE_ENGINE | DESCRIPTOR_DDI_ENGINE, &Base->Header, &New->Header);
+}
+
+
+/*----------------------------------------------------------------------------------------*/
+/**
+ * Update configuration data
+ *
+ * Puprouse of this structure to update config data that base on programming of
+ * other silicon compoments. For instance PCI address of GNB and PCIe ports
+ * can change by AGESA or external agent
+ *
+ *
+ * @param[in,out] Pcie Pointer to global PCIe configuration
+ * @retval AGESA_SUCCESS Configuration data successfully update
+ * @retval AGESA_FATAL Failt to update configuration
+ */
+AGESA_STATUS
+PcieUpdateConfigurationData (
+ IN PCIe_PLATFORM_CONFIG *Pcie
+ )
+{
+ PCIe_SILICON_CONFIG *Silicon;
+ PCIe_ENGINE_CONFIG *Engine;
+ PCI_ADDR NewAddress;
+ // Update silicon configuration
+ Silicon = PcieConfigGetChildSilicon (Pcie);
+ while (Silicon != NULL) {
+ NewAddress = GnbFmGetPciAddress ((GNB_HANDLE *) PcieConfigGetParentComplex (Silicon), GnbLibGetHeader (Pcie));
+ if (Silicon->Address.AddressValue != NewAddress.AddressValue) {
+ Silicon->Address.AddressValue = NewAddress.AddressValue;
+ Engine = PcieConfigGetChildEngine (Silicon);
+ while (Engine != NULL) {
+ if (PcieConfigIsPcieEngine (Engine)) {
+ Engine->Type.Port.Address.Address.Bus = Silicon->Address.Address.Bus;
+ }
+ Engine = (PCIe_ENGINE_CONFIG *) PcieConfigGetNextTopologyDescriptor (Engine, DESCRIPTOR_TERMINATE_GNB);
+ }
+ }
+ Silicon = (PCIe_SILICON_CONFIG *) PcieConfigGetNextTopologyDescriptor (Silicon, DESCRIPTOR_TERMINATE_TOPOLOGY);
+ }
+ return AGESA_SUCCESS;
+}