Add AMD Family 12 cpu Agesa code
[coreboot.git] / src / vendorcode / amd / agesa / f12 / Proc / GNB / Modules / GnbPcieConfig / PcieMapTopology.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * Procedure to map user define topology to processor configuration
6  *
7  *
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:     AGESA
11  * @e sub-project: GNB
12  * @e \$Revision: 49532 $   @e \$Date: 2011-03-25 02:54:43 +0800 (Fri, 25 Mar 2011) $
13  *
14  */
15 /*
16 *****************************************************************************
17 *
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19  * All rights reserved.
20  * 
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions are met:
23  *     * Redistributions of source code must retain the above copyright
24  *       notice, this list of conditions and the following disclaimer.
25  *     * Redistributions in binary form must reproduce the above copyright
26  *       notice, this list of conditions and the following disclaimer in the
27  *       documentation and/or other materials provided with the distribution.
28  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of 
29  *       its contributors may be used to endorse or promote products derived 
30  *       from this software without specific prior written permission.
31  * 
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 * ***************************************************************************
43 *
44 */
45
46 /*----------------------------------------------------------------------------------------
47  *                             M O D U L E S    U S E D
48  *----------------------------------------------------------------------------------------
49  */
50 #include  "AGESA.h"
51 #include  "Ids.h"
52 #include  "amdlib.h"
53 #include  "Gnb.h"
54 #include  "GnbPcie.h"
55 #include  "GnbPcieFamServices.h"
56 #include  "GeneralServices.h"
57 #include  "PcieInputParser.h"
58 #include  "PcieMapTopology.h"
59 #include  "GnbPcieConfig.h"
60 #include  "Filecode.h"
61 #define FILECODE PROC_GNB_MODULES_GNBPCIECONFIG_PCIEMAPTOPOLOGY_FILECODE
62 /*----------------------------------------------------------------------------------------
63  *                   D E F I N I T I O N S    A N D    M A C R O S
64  *----------------------------------------------------------------------------------------
65  */
66
67
68 /*----------------------------------------------------------------------------------------
69  *                  T Y P E D E F S     A N D     S T R U C T U  R E S
70  *----------------------------------------------------------------------------------------
71  */
72
73
74 /*----------------------------------------------------------------------------------------
75  *           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
76  *----------------------------------------------------------------------------------------
77  */
78
79
80 AGESA_STATUS
81 STATIC
82 PcieMapPortsPciAddresses (
83   IN      PCIe_SILICON_CONFIG         *Silicon,
84   IN      PCIe_PLATFORM_CONFIG        *Pcie
85   );
86
87 AGESA_STATUS
88 PcieMapTopologyOnWrapper (
89   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
90   IN OUT  PCIe_WRAPPER_CONFIG         *Wrapper,
91   IN      PCIe_PLATFORM_CONFIG        *Pcie
92  );
93
94 VOID
95 PcieMapInitializeEngineData (
96   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
97   IN OUT  PCIe_WRAPPER_CONFIG         *Wrapper,
98   IN      PCIe_PLATFORM_CONFIG        *Pcie
99  );
100
101 BOOLEAN
102 PcieCheckPortPciDeviceMapping (
103   IN      PCIe_PORT_DESCRIPTOR        *PortDescriptor,
104   IN      PCIe_ENGINE_CONFIG          *Engine
105   );
106
107 VOID
108 PcieComplexConfigConfigDump (
109   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
110   IN      PCIe_PLATFORM_CONFIG        *Pcie
111   );
112
113 BOOLEAN
114 PcieIsDescriptorLinkWidthValid (
115   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor
116   );
117
118 BOOLEAN
119 PcieCheckLanesMatch (
120   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor,
121   IN      PCIe_ENGINE_CONFIG          *Engine
122   );
123
124 AGESA_STATUS
125 PcieEnginesToWrapper (
126   IN      PCIE_ENGINE_TYPE            EngineType,
127   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
128   IN      PCIe_WRAPPER_CONFIG         *Wrapper
129   );
130
131 BOOLEAN
132 PcieCheckDescriptorMapsToWrapper (
133   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor,
134   IN      PCIe_WRAPPER_CONFIG         *Wrapper
135   );
136
137 VOID
138 PcieAllocateEngine (
139   IN      UINT8                       DescriptorIndex,
140   IN      PCIe_ENGINE_CONFIG          *Engine
141   );
142 /*----------------------------------------------------------------------------------------*/
143 /**
144  * Configure engine list to support lane allocation according to configuration ID.
145  *
146  *
147  *
148  * @param[in]  ComplexDescriptor   Pointer to used define complex descriptor
149  * @param[in]  Complex             Pointer to complex descriptor
150  * @param[in]  Pcie                Pointer to global PCIe configuration
151  * @retval     AGESA_SUCCESS       Topology successfully mapped
152  * @retval     AGESA_ERROR         Topology can not be mapped
153  */
154
155 AGESA_STATUS
156 PcieMapTopologyOnComplex (
157   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
158   IN      PCIe_COMPLEX_CONFIG         *Complex,
159   IN      PCIe_PLATFORM_CONFIG        *Pcie
160   )
161 {
162   PCIe_SILICON_CONFIG *Silicon;
163   PCIe_WRAPPER_CONFIG *Wrapper;
164   AGESA_STATUS        AgesaStatus;
165   AGESA_STATUS        Status;
166
167   AgesaStatus = AGESA_SUCCESS;
168   IDS_HDT_CONSOLE (GNB_TRACE, "PcieMapTopologyOnComplex Enter\n");
169   Silicon = PcieConfigGetChildSilicon (Complex);
170   while (Silicon != NULL) {
171     Wrapper = PcieConfigGetChildWrapper (Silicon);
172     while (Wrapper != NULL) {
173       Status = PcieMapTopologyOnWrapper (ComplexDescriptor, Wrapper, Pcie);
174       AGESA_STATUS_UPDATE (Status, AgesaStatus);
175       if (Status == AGESA_ERROR) {
176         PcieConfigDisableAllEngines (PciePortEngine | PcieDdiEngine, Wrapper);
177         IDS_HDT_CONSOLE (PCIE_MISC, "  ERROR! Fail to map topology on %s Wrapper\n",
178           PcieFmDebugGetWrapperNameString (Wrapper)
179           );
180         ASSERT (FALSE);
181       }
182       Wrapper = PcieLibGetNextDescriptor (Wrapper);
183     }
184     Status = PcieMapPortsPciAddresses (Silicon, Pcie);
185     AGESA_STATUS_UPDATE (Status, AgesaStatus);
186     Silicon = PcieLibGetNextDescriptor (Silicon);
187   }
188   IDS_HDT_CONSOLE (GNB_TRACE, "PcieMapTopologyOnComplex Exit [%x]\n", AgesaStatus);
189   return AgesaStatus;
190 }
191
192 /*----------------------------------------------------------------------------------------*/
193 /**
194  * Configure engine list to support lane allocation according to configuration ID.
195  *
196  *
197  *
198  * @param[in]  EngineType          Engine type
199  * @param[in]  ComplexDescriptor   Pointer to used define complex descriptor
200  * @param[in]  Wrapper             Pointer to wrapper config descriptor
201  * @retval     AGESA_SUCCESS       Topology successfully mapped
202  * @retval     AGESA_ERROR         Topology can not be mapped
203  */
204 AGESA_STATUS
205 PcieEnginesToWrapper (
206   IN      PCIE_ENGINE_TYPE            EngineType,
207   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
208   IN      PCIe_WRAPPER_CONFIG         *Wrapper
209   )
210 {
211   AGESA_STATUS                Status;
212   PCIe_ENGINE_CONFIG          *EngineList;
213   PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor;
214   UINT8                       ConfigurationId;
215   UINT8                       Allocations;
216   UINTN                       Index;
217   UINTN                       NumberOfDescriptors;
218
219   ConfigurationId = 0;
220   Allocations = 0;
221   IDS_HDT_CONSOLE (GNB_TRACE, "PcieEnginesToWrapper Enter\n");
222   NumberOfDescriptors = PcieInputParserGetNumberOfEngines (ComplexDescriptor);
223   do {
224     Status = PcieFmConfigureEnginesLaneAllocation (Wrapper, EngineType, ConfigurationId++);
225
226     if (Status == AGESA_SUCCESS) {
227       Allocations = 0;
228       for (Index = 0; Index < NumberOfDescriptors; Index++) {
229         EngineDescriptor = PcieInputParserGetEngineDescriptor (ComplexDescriptor, Index);
230         if (EngineDescriptor->EngineData.EngineType == EngineType) {
231           // Step 1, belongs to wrapper check.
232           if (PcieCheckDescriptorMapsToWrapper (EngineDescriptor, Wrapper)) {
233             ++Allocations;
234             EngineList = PcieConfigGetChildEngine (Wrapper);
235             while (EngineList != NULL) {
236               if (!PcieLibIsEngineAllocated (EngineList)) {
237                 // Step 2.user descriptor less or equal to link width of engine
238                 if (PcieCheckLanesMatch (EngineDescriptor, EngineList)) {
239                   // Step 3, Check if link width is correct.x1, x2, x4, x8, x16.
240                   if (!PcieIsDescriptorLinkWidthValid (EngineDescriptor)) {
241                     PcieConfigDisableEngine (EngineList);
242                     return AGESA_ERROR;
243                   }
244                   if (EngineDescriptor->EngineData.EngineType == PciePortEngine) {
245                     // Step 4, Family specifc, port device number match engine device
246                     if (PcieCheckPortPciDeviceMapping ((PCIe_PORT_DESCRIPTOR*) EngineDescriptor, EngineList)) {
247                       //Step 5, Family specifc, lanes can be muxed.
248                       if (PcieFmCheckPortPcieLaneCanBeMuxed ((PCIe_PORT_DESCRIPTOR*) EngineDescriptor, EngineList)) {
249                         PcieAllocateEngine ((UINT8) Index, EngineList);
250                         --Allocations;
251                         break;
252                       }
253                     }
254                   } else {
255                     PcieAllocateEngine ((UINT8) Index, EngineList);
256                     --Allocations;
257                     break;
258                   }
259                 }
260               }//end if PcieLibIsEngineAllocated
261               EngineList = PcieLibGetNextDescriptor (EngineList);
262             }
263           }//end if PcieCheckDescriptorMapsToWrapper
264         }// end if EngineType
265       }//end for
266     }
267   } while (Status == AGESA_SUCCESS && Allocations != 0);
268   IDS_HDT_CONSOLE (GNB_TRACE, "PcieEnginesToWrapper Exit [%x]\n", Status);
269   return Status;
270 }
271
272 /*----------------------------------------------------------------------------------------*/
273 /**
274  * Check if lane from  user port descriptor (PCIe_PORT_DESCRIPTOR) belongs to wrapper (PCIe_WRAPPER_CONFIG)
275  *
276  *
277  * @param[in]  EngineDescriptor    Pointer to used define engine descriptor
278  * @param[in]  Wrapper             Pointer to PCIe_WRAPPER_CONFIG
279  * @retval     TRUE                Belongs to wrapper
280  * @retval     FALSE               Not belongs to wrapper
281  */
282 BOOLEAN
283 PcieCheckDescriptorMapsToWrapper (
284   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor,
285   IN      PCIe_WRAPPER_CONFIG         *Wrapper
286   )
287 {
288   BOOLEAN Result;
289   UINT16  DescriptorHiLane;
290   UINT16  DescriptorLoLane;
291   UINT16  DescriptorNumberOfLanes;
292
293   DescriptorLoLane = MIN (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
294   DescriptorHiLane = MAX (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
295   DescriptorNumberOfLanes = DescriptorHiLane - DescriptorLoLane + 1;
296   Result = TRUE;
297
298   if (!(DescriptorLoLane >= Wrapper->StartPhyLane && DescriptorHiLane <= Wrapper->EndPhyLane)) {
299     // Lanes of descriptor does not belongs to wrapper
300     Result = FALSE;
301   }
302   return Result;
303 }
304
305 /*----------------------------------------------------------------------------------------*/
306 /**
307  * Set Engine to be allocated.
308  *
309  *
310  * @param[in]  DescriptorIndex    UINT8 index
311  * @param[in]  Engine             Pointer to engine config
312  */
313 VOID
314 PcieAllocateEngine (
315   IN      UINT8                       DescriptorIndex,
316   IN      PCIe_ENGINE_CONFIG          *Engine
317   )
318 {
319   PcieConfigSetDescriptorFlags (Engine, DESCRIPTOR_ALLOCATED);
320   Engine->Scratch = DescriptorIndex;
321 }
322
323 /*----------------------------------------------------------------------------------------*/
324 /**
325  * Configure engine list to support lane allocation according to configuration ID.
326  *
327  * PCIE port
328  *
329  *
330  * 1 Check if lane from  user port descriptor (PCIe_PORT_DESCRIPTOR) belongs to wrapper (PCIe_WRAPPER_CONFIG)
331  * 2 Check if link width from user descriptor less or equal to link width of engine (PCIe_ENGINE_CONFIG)
332  * 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
333  * 4 Check if user port device number (PCIe_PORT_DESCRIPTOR) match engine port device number (PCIe_ENGINE_CONFIG)
334  * 5 Check if lane can be muxed
335  *
336  *
337  * DDI Link
338  *
339  * 1 Check if lane from  user port descriptor (PCIe_DDI_DESCRIPTOR) belongs to wrapper (PCIe_WRAPPER_CONFIG)
340  * 2 Check lane from  (PCIe_DDI_DESCRIPTOR) match exactly phy lane (PCIe_ENGINE_CONFIG)
341  *
342  *
343  *
344  * @param[in]     ComplexDescriptor   Pointer to used define complex descriptor
345  * @param[in,out] Wrapper             Pointer to wrapper config descriptor
346  * @param[in]     Pcie                Pointer to global PCIe configuration
347  * @retval        AGESA_SUCCESS       Topology successfully mapped
348  * @retval        AGESA_ERROR         Topology can not be mapped
349  */
350 AGESA_STATUS
351 PcieMapTopologyOnWrapper (
352   IN       PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
353   IN OUT   PCIe_WRAPPER_CONFIG         *Wrapper,
354   IN       PCIe_PLATFORM_CONFIG        *Pcie
355   )
356 {
357   AGESA_STATUS                AgesaStatus;
358   AGESA_STATUS                Status;
359   PCIe_ENGINE_CONFIG          *EngineList;
360   UINT32                      WrapperPhyLaneBitMap;
361
362   AgesaStatus = AGESA_SUCCESS;
363   if (PcieLibIsPcieWrapper (Wrapper)) {
364     Status = PcieEnginesToWrapper (PciePortEngine, ComplexDescriptor, Wrapper);
365     AGESA_STATUS_UPDATE (Status, AgesaStatus);
366     if (Status == AGESA_ERROR) {
367       // If we can not map topology on wrapper we can not enable any engines.
368       PutEventLog (
369         AGESA_ERROR,
370         GNB_EVENT_INVALID_PCIE_TOPOLOGY_CONFIGURATION,
371         Wrapper->WrapId,
372         Wrapper->StartPhyLane,
373         Wrapper->EndPhyLane,
374         0,
375         GnbLibGetHeader (Pcie)
376         );
377       PcieConfigDisableAllEngines (PciePortEngine, Wrapper);
378     }
379   }
380   if (PcieLibIsDdiWrapper (Wrapper)) {
381     Status = PcieEnginesToWrapper (PcieDdiEngine, ComplexDescriptor, Wrapper);
382     AGESA_STATUS_UPDATE (Status, AgesaStatus);
383     if (Status == AGESA_ERROR) {
384       // If we can not map topology on wrapper we can not enable any engines.
385       PutEventLog (
386         AGESA_ERROR,
387         GNB_EVENT_INVALID_DDI_TOPOLOGY_CONFIGURATION,
388         Wrapper->WrapId,
389         Wrapper->StartPhyLane,
390         Wrapper->EndPhyLane,
391         0,
392         GnbLibGetHeader (Pcie)
393         );
394       PcieConfigDisableAllEngines (PcieDdiEngine, Wrapper);
395     }
396   }
397   // Copy engine data
398   PcieMapInitializeEngineData (ComplexDescriptor, Wrapper, Pcie);
399
400   EngineList = PcieConfigGetChildEngine (Wrapper);
401   // Verify if we oversubscribe lanes and PHY link width
402   WrapperPhyLaneBitMap = 0;
403   while (EngineList != NULL) {
404     UINT32  EnginePhyLaneBitMap;
405     if (PcieLibIsEngineAllocated (EngineList)) {
406       EnginePhyLaneBitMap = PcieConfigGetEnginePhyLaneBitMap (EngineList);
407       if ((WrapperPhyLaneBitMap & EnginePhyLaneBitMap) != 0) {
408         IDS_HDT_CONSOLE (PCIE_MISC, "  ERROR! Lanes double subscribe lanes [Engine Lanes %d..%d]\n",
409           EngineList->EngineData.StartLane,
410           EngineList->EngineData.EndLane
411           );
412         PutEventLog (
413           AGESA_ERROR,
414           GNB_EVENT_INVALID_LANES_CONFIGURATION,
415           EngineList->EngineData.StartLane,
416           EngineList->EngineData.EndLane,
417           0,
418           0,
419           GnbLibGetHeader (Pcie)
420           );
421         PcieConfigDisableEngine (EngineList);
422         Status = AGESA_ERROR;
423         AGESA_STATUS_UPDATE (Status, AgesaStatus);
424       } else {
425         WrapperPhyLaneBitMap |= EnginePhyLaneBitMap;
426       }
427     }
428     EngineList = PcieLibGetNextDescriptor (EngineList);
429   }
430   return AgesaStatus;
431 }
432
433
434 /*----------------------------------------------------------------------------------------*/
435 /**
436  * Initialize engine data
437  *
438  *
439  *
440  * @param[in]     ComplexDescriptor   Pointer to user defined complex descriptor
441  * @param[in,out] Wrapper             Pointer to wrapper config descriptor
442  * @param[in]     Pcie                Pointer to global PCIe configuration
443  */
444 VOID
445 PcieMapInitializeEngineData (
446   IN       PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
447   IN OUT   PCIe_WRAPPER_CONFIG         *Wrapper,
448   IN       PCIe_PLATFORM_CONFIG        *Pcie
449   )
450 {
451   PCIe_ENGINE_CONFIG        *EngineList;
452   PCIe_ENGINE_DESCRIPTOR    *EngineDescriptor;
453
454   EngineList = PcieConfigGetChildEngine (Wrapper);
455   while (EngineList != NULL) {
456     if (PcieLibIsEngineAllocated (EngineList)) {
457       if (EngineList->Scratch != 0xFF) {
458         EngineDescriptor = PcieInputParserGetEngineDescriptor (ComplexDescriptor, EngineList->Scratch);
459         LibAmdMemCopy (&EngineList->EngineData, &EngineDescriptor->EngineData, sizeof (EngineDescriptor->EngineData), GnbLibGetHeader (Pcie));
460         if (PcieLibIsDdiEngine (EngineList)) {
461           LibAmdMemCopy (&EngineList->Type.Ddi, &((PCIe_DDI_DESCRIPTOR*) EngineDescriptor)->Ddi, sizeof (PCIe_DDI_DATA), GnbLibGetHeader (Pcie));
462           EngineList->Type.Ddi.DisplayPriorityIndex = (UINT8) EngineList->Scratch;
463         } else if (PcieLibIsPcieEngine (EngineList)) {
464           LibAmdMemCopy (&EngineList->Type.Port, &((PCIe_PORT_DESCRIPTOR*) EngineDescriptor)->Port, sizeof (PCIe_PORT_DATA), GnbLibGetHeader (Pcie));
465         }
466       }
467     }
468     EngineList = PcieLibGetNextDescriptor (EngineList);
469   }
470 }
471
472 /*----------------------------------------------------------------------------------------*/
473 /**
474  * Allocate PCI addresses for all PCIe engines on silicon
475  *
476  *
477  *
478  * @param[in]  PortDescriptor      Pointer to user defined engine descriptor
479  * @param[in]  Engine              Pointer engine configuration
480  * @retval     TRUE                Descriptor can be mapped to engine
481  * @retval     FALSE               Descriptor can NOT be mapped to engine
482  */
483
484 BOOLEAN
485 PcieCheckPortPciDeviceMapping (
486   IN      PCIe_PORT_DESCRIPTOR  *PortDescriptor,
487   IN      PCIe_ENGINE_CONFIG    *Engine
488   )
489 {
490   BOOLEAN Result;
491
492   if ((PortDescriptor->Port.DeviceNumber == Engine->Type.Port.NativeDevNumber &&
493     PortDescriptor->Port.FunctionNumber == Engine->Type.Port.NativeFunNumber) ||
494     (PortDescriptor->Port.DeviceNumber == 0 && PortDescriptor->Port.FunctionNumber == 0)) {
495     Result = TRUE;
496   } else {
497     Result = PcieFmCheckPortPciDeviceMapping (PortDescriptor, Engine);
498   }
499
500   return Result;
501 }
502
503 /*----------------------------------------------------------------------------------------*/
504 /**
505  * Allocate PCI addresses for all PCIe engines on silicon
506  *
507  *
508  *
509  * @param[in]  Silicon             Pointer to silicon configurration
510  * @param[in]  Pcie                Pointer PCIe configuration
511  * @retval     AGESA_ERROR         Fail to allocate PCI device address
512  * @retval     AGESA_SUCCESS       Successfully allocate PCI address for all PCIe ports
513  */
514
515 AGESA_STATUS
516 STATIC
517 PcieMapPortsPciAddresses (
518   IN      PCIe_SILICON_CONFIG    *Silicon,
519   IN      PCIe_PLATFORM_CONFIG   *Pcie
520   )
521 {
522   AGESA_STATUS        Status;
523   AGESA_STATUS        AgesaStatus;
524   PCIe_WRAPPER_CONFIG *WrapperList;
525   PCIe_ENGINE_CONFIG  *EngineList;
526   AgesaStatus = AGESA_SUCCESS;
527   WrapperList = PcieConfigGetChildWrapper (Silicon);
528   while (WrapperList != NULL) {
529     EngineList = PcieConfigGetChildEngine (WrapperList);
530     while (EngineList != NULL) {
531       if (PcieLibIsPcieEngine (EngineList) && PcieLibIsEngineAllocated (EngineList)) {
532         Status = PcieFmMapPortPciAddress (EngineList);
533         AGESA_STATUS_UPDATE (Status, AgesaStatus);
534         if (Status == AGESA_SUCCESS) {
535           EngineList->Type.Port.Address.AddressValue = MAKE_SBDFO (
536                                                          0,
537                                                          Silicon->Address.Address.Bus,
538                                                          EngineList->Type.Port.PortData.DeviceNumber,
539                                                          EngineList->Type.Port.PortData.FunctionNumber,
540                                                          0
541                                                          );
542         } else {
543           EngineList->Type.Port.PortData.PortPresent = OFF;
544           IDS_HDT_CONSOLE (PCIE_MISC, "  ERROR! Fail to allocate PCI address for PCIe port\n"
545             );
546           //Report error
547           PutEventLog (
548             AGESA_ERROR,
549             GNB_EVENT_INVALID_PCIE_PORT_CONFIGURATION,
550             EngineList->Type.Port.PortData.DeviceNumber,
551             0,
552             0,
553             0,
554             GnbLibGetHeader (Pcie)
555             );
556         }
557       }
558       EngineList = PcieLibGetNextDescriptor (EngineList);
559     }
560     WrapperList = PcieLibGetNextDescriptor (WrapperList);
561   }
562   return AgesaStatus;
563 }
564
565 /*----------------------------------------------------------------------------------------*/
566 /**
567  * If link width from user descriptor less or equal to link width of engine
568  *
569  *
570  * @param[in]  EngineDescriptor    Pointer to used define engine descriptor
571  * @param[in]  Engine              Pointer to engine config
572  * @retval     TRUE                Descriptor can be mapped to engine
573  * @retval     FALSE               Descriptor can NOT be mapped to engine
574  */
575
576 BOOLEAN
577 PcieCheckLanesMatch (
578   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor,
579   IN      PCIe_ENGINE_CONFIG          *Engine
580   )
581 {
582   BOOLEAN Result;
583   UINT16  DescriptorHiLane;
584   UINT16  DescriptorLoLane;
585   UINT16  DescriptorNumberOfLanes;
586
587   DescriptorLoLane = MIN (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
588   DescriptorHiLane = MAX (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
589   DescriptorNumberOfLanes = DescriptorHiLane - DescriptorLoLane + 1;
590   Result = FALSE;
591
592   if (EngineDescriptor->EngineData.EngineType == PciePortEngine) {
593     //
594     // If link width from user descriptor less or equal to link width of engine (PCIe_ENGINE_CONFIG)
595     //
596     if (DescriptorNumberOfLanes <= PcieConfigGetNumberOfCoreLane (Engine)) {
597       Result = TRUE;
598     }
599   } else if (EngineDescriptor->EngineData.EngineType == PcieDdiEngine) {
600     //
601     //For Ddi, check lane from  (PCIe_DDI_DESCRIPTOR) match exactly phy lane (PCIe_ENGINE_CONFIG)
602     //
603     if ((Engine->EngineData.StartLane == DescriptorLoLane) && (Engine->EngineData.EndLane == DescriptorHiLane)) {
604       Result = TRUE;
605     }
606   }
607
608   return Result;
609 }
610
611 /*----------------------------------------------------------------------------------------*/
612 /**
613  * Correct link width for PCIe port x1, x2, x4, x8, x16, correct link width for DDI x4, x8
614  *
615  *
616  * @param[in]  EngineDescriptor    A pointer of PCIe_ENGINE_DESCRIPTOR
617  * @retval     TRUE                Descriptor can be mapped to engine
618  * @retval     FALSE               Descriptor can NOT be mapped to engine
619  */
620
621 BOOLEAN
622 PcieIsDescriptorLinkWidthValid (
623   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor
624   )
625 {
626   BOOLEAN   Result;
627   UINT16    DescriptorHiLane;
628   UINT16    DescriptorLoLane;
629   UINT16    DescriptorNumberOfLanes;
630
631   Result = FALSE;
632   DescriptorLoLane = MIN (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
633   DescriptorHiLane = MAX (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
634   DescriptorNumberOfLanes = DescriptorHiLane - DescriptorLoLane + 1;
635
636   if (EngineDescriptor->EngineData.EngineType == PciePortEngine) {
637     if (DescriptorNumberOfLanes == 1 || DescriptorNumberOfLanes == 2 || DescriptorNumberOfLanes == 4 ||
638         DescriptorNumberOfLanes == 8 || DescriptorNumberOfLanes == 16) {
639       Result = TRUE;
640     }
641   } else if (EngineDescriptor->EngineData.EngineType == PcieDdiEngine) {
642     if (DescriptorNumberOfLanes == 4 || DescriptorNumberOfLanes == 8 || DescriptorNumberOfLanes == 7) {
643       Result = TRUE;
644     }
645   }
646
647   GNB_DEBUG_CODE (
648     if (!Result) {
649       IDS_HDT_CONSOLE (PCIE_MISC, "  Invalid Link width [Engine Lanes %d..%d]\n",
650         DescriptorLoLane,
651         DescriptorHiLane
652       );
653     }
654   );
655
656   return Result;
657 }
658