| /* $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; |
| } |