• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   PCI resouces support functions implemntation for PCI Bus module.
3 
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "PciBus.h"
16 
17 //
18 // The default policy for the PCI bus driver is NOT to reserve I/O ranges for both ISA aliases and VGA aliases.
19 //
20 BOOLEAN mReserveIsaAliases = FALSE;
21 BOOLEAN mReserveVgaAliases = FALSE;
22 BOOLEAN mPolicyDetermined  = FALSE;
23 
24 /**
25   The function is used to skip VGA range.
26 
27   @param Start    Returned start address including VGA range.
28   @param Length   The length of VGA range.
29 
30 **/
31 VOID
SkipVGAAperture(OUT UINT64 * Start,IN UINT64 Length)32 SkipVGAAperture (
33   OUT UINT64   *Start,
34   IN  UINT64   Length
35   )
36 {
37   UINT64  Original;
38   UINT64  Mask;
39   UINT64  StartOffset;
40   UINT64  LimitOffset;
41 
42   ASSERT (Start != NULL);
43   //
44   // For legacy VGA, bit 10 to bit 15 is not decoded
45   //
46   Mask        = 0x3FF;
47 
48   Original    = *Start;
49   StartOffset = Original & Mask;
50   LimitOffset = ((*Start) + Length - 1) & Mask;
51   if (LimitOffset >= VGABASE1) {
52     *Start = *Start - StartOffset + VGALIMIT2 + 1;
53   }
54 }
55 
56 /**
57   This function is used to skip ISA aliasing aperture.
58 
59   @param Start    Returned start address including ISA aliasing aperture.
60   @param Length   The length of ISA aliasing aperture.
61 
62 **/
63 VOID
SkipIsaAliasAperture(OUT UINT64 * Start,IN UINT64 Length)64 SkipIsaAliasAperture (
65   OUT UINT64   *Start,
66   IN  UINT64   Length
67   )
68 {
69 
70   UINT64  Original;
71   UINT64  Mask;
72   UINT64  StartOffset;
73   UINT64  LimitOffset;
74 
75   ASSERT (Start != NULL);
76 
77   //
78   // For legacy ISA, bit 10 to bit 15 is not decoded
79   //
80   Mask        = 0x3FF;
81 
82   Original    = *Start;
83   StartOffset = Original & Mask;
84   LimitOffset = ((*Start) + Length - 1) & Mask;
85 
86   if (LimitOffset >= ISABASE) {
87     *Start = *Start - StartOffset + ISALIMIT + 1;
88   }
89 }
90 
91 /**
92   This function inserts a resource node into the resource list.
93   The resource list is sorted in descend order.
94 
95   @param Bridge  PCI resource node for bridge.
96   @param ResNode Resource node want to be inserted.
97 
98 **/
99 VOID
InsertResourceNode(IN OUT PCI_RESOURCE_NODE * Bridge,IN PCI_RESOURCE_NODE * ResNode)100 InsertResourceNode (
101   IN OUT PCI_RESOURCE_NODE   *Bridge,
102   IN     PCI_RESOURCE_NODE   *ResNode
103   )
104 {
105   LIST_ENTRY        *CurrentLink;
106   PCI_RESOURCE_NODE *Temp;
107   UINT64            ResNodeAlignRest;
108   UINT64            TempAlignRest;
109 
110   ASSERT (Bridge  != NULL);
111   ASSERT (ResNode != NULL);
112 
113   InsertHeadList (&Bridge->ChildList, &ResNode->Link);
114 
115   CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;
116   while (CurrentLink != &Bridge->ChildList) {
117     Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
118 
119     if (ResNode->Alignment > Temp->Alignment) {
120       break;
121     } else if (ResNode->Alignment == Temp->Alignment) {
122       ResNodeAlignRest  = ResNode->Length & ResNode->Alignment;
123       TempAlignRest     = Temp->Length & Temp->Alignment;
124       if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {
125         break;
126       }
127     }
128 
129     SwapListEntries (&ResNode->Link, CurrentLink);
130 
131     CurrentLink = ResNode->Link.ForwardLink;
132   }
133 }
134 
135 /**
136   This routine is used to merge two different resource trees in need of
137   resoure degradation.
138 
139   For example, if an upstream PPB doesn't support,
140   prefetchable memory decoding, the PCI bus driver will choose to call this function
141   to merge prefectchable memory resource list into normal memory list.
142 
143   If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
144   type.
145   If Dst is NULL or Res is NULL, ASSERT ().
146 
147   @param Dst        Point to destination resource tree.
148   @param Res        Point to source resource tree.
149   @param TypeMerge  If the TypeMerge is TRUE, Res resource type is changed to the type of
150                     destination resource type.
151 
152 **/
153 VOID
MergeResourceTree(IN PCI_RESOURCE_NODE * Dst,IN PCI_RESOURCE_NODE * Res,IN BOOLEAN TypeMerge)154 MergeResourceTree (
155   IN PCI_RESOURCE_NODE   *Dst,
156   IN PCI_RESOURCE_NODE   *Res,
157   IN BOOLEAN             TypeMerge
158   )
159 {
160 
161   LIST_ENTRY        *CurrentLink;
162   PCI_RESOURCE_NODE *Temp;
163 
164   ASSERT (Dst != NULL);
165   ASSERT (Res != NULL);
166 
167   while (!IsListEmpty (&Res->ChildList)) {
168     CurrentLink = Res->ChildList.ForwardLink;
169 
170     Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);
171 
172     if (TypeMerge) {
173       Temp->ResType = Dst->ResType;
174     }
175 
176     RemoveEntryList (CurrentLink);
177     InsertResourceNode (Dst, Temp);
178   }
179 }
180 
181 /**
182   This function is used to calculate the IO16 aperture
183   for a bridge.
184 
185   @param Bridge    PCI resource node for bridge.
186 
187 **/
188 VOID
CalculateApertureIo16(IN PCI_RESOURCE_NODE * Bridge)189 CalculateApertureIo16 (
190   IN PCI_RESOURCE_NODE    *Bridge
191   )
192 {
193   EFI_STATUS              Status;
194   UINT64                  Aperture;
195   LIST_ENTRY              *CurrentLink;
196   PCI_RESOURCE_NODE       *Node;
197   UINT64                  Offset;
198   EFI_PCI_PLATFORM_POLICY PciPolicy;
199   UINT64                  PaddingAperture;
200 
201   if (!mPolicyDetermined) {
202     //
203     // Check PciPlatform policy
204     //
205     Status = EFI_NOT_FOUND;
206     PciPolicy = 0;
207     if (gPciPlatformProtocol != NULL) {
208       Status = gPciPlatformProtocol->GetPlatformPolicy (
209                                        gPciPlatformProtocol,
210                                        &PciPolicy
211                                        );
212     }
213 
214     if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
215       Status = gPciOverrideProtocol->GetPlatformPolicy (
216                                        gPciOverrideProtocol,
217                                        &PciPolicy
218                                        );
219     }
220 
221     if (!EFI_ERROR (Status)) {
222       if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
223         mReserveIsaAliases = TRUE;
224       }
225       if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {
226         mReserveVgaAliases = TRUE;
227       }
228     }
229     mPolicyDetermined = TRUE;
230   }
231 
232   Aperture        = 0;
233   PaddingAperture = 0;
234 
235   if (Bridge == NULL) {
236     return ;
237   }
238 
239   //
240   // Assume the bridge is aligned
241   //
242   for ( CurrentLink = GetFirstNode (&Bridge->ChildList)
243       ; !IsNull (&Bridge->ChildList, CurrentLink)
244       ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)
245       ) {
246 
247     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
248     if (Node->ResourceUsage == PciResUsagePadding) {
249       ASSERT (PaddingAperture == 0);
250       PaddingAperture = Node->Length;
251       continue;
252     }
253     //
254     // Consider the aperture alignment
255     //
256     Offset = Aperture & (Node->Alignment);
257 
258     if (Offset != 0) {
259 
260       Aperture = Aperture + (Node->Alignment + 1) - Offset;
261 
262     }
263 
264     //
265     // IsaEnable and VGAEnable can not be implemented now.
266     // If both of them are enabled, then the IO resource would
267     // become too limited to meet the requirement of most of devices.
268     //
269     if (mReserveIsaAliases || mReserveVgaAliases) {
270       if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
271         //
272         // Check if there is need to support ISA/VGA decoding
273         // If so, we need to avoid isa/vga aliasing range
274         //
275         if (mReserveIsaAliases) {
276           SkipIsaAliasAperture (
277             &Aperture,
278             Node->Length
279             );
280           Offset = Aperture & (Node->Alignment);
281           if (Offset != 0) {
282             Aperture = Aperture + (Node->Alignment + 1) - Offset;
283           }
284         } else if (mReserveVgaAliases) {
285           SkipVGAAperture (
286             &Aperture,
287             Node->Length
288             );
289           Offset = Aperture & (Node->Alignment);
290           if (Offset != 0) {
291             Aperture = Aperture + (Node->Alignment + 1) - Offset;
292           }
293         }
294       }
295     }
296 
297     Node->Offset = Aperture;
298 
299     //
300     // Increment aperture by the length of node
301     //
302     Aperture += Node->Length;
303   }
304 
305   //
306   // Adjust the aperture with the bridge's alignment
307   //
308   Offset = Aperture & (Bridge->Alignment);
309 
310   if (Offset != 0) {
311     Aperture = Aperture + (Bridge->Alignment + 1) - Offset;
312   }
313 
314   Bridge->Length = Aperture;
315   //
316   // At last, adjust the bridge's alignment to the first child's alignment
317   // if the bridge has at least one child
318   //
319   CurrentLink = Bridge->ChildList.ForwardLink;
320   if (CurrentLink != &Bridge->ChildList) {
321     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
322     if (Node->Alignment > Bridge->Alignment) {
323       Bridge->Alignment = Node->Alignment;
324     }
325   }
326 
327   //
328   // Hotplug controller needs padding resources.
329   // Use the larger one between the padding resource and actual occupied resource.
330   //
331   Bridge->Length = MAX (Bridge->Length, PaddingAperture);
332 }
333 
334 /**
335   This function is used to calculate the resource aperture
336   for a given bridge device.
337 
338   @param Bridge      PCI resouce node for given bridge device.
339 
340 **/
341 VOID
CalculateResourceAperture(IN PCI_RESOURCE_NODE * Bridge)342 CalculateResourceAperture (
343   IN PCI_RESOURCE_NODE    *Bridge
344   )
345 {
346   UINT64            Aperture;
347   LIST_ENTRY        *CurrentLink;
348   PCI_RESOURCE_NODE *Node;
349   UINT64            PaddingAperture;
350   UINT64            Offset;
351 
352   Aperture        = 0;
353   PaddingAperture = 0;
354 
355   if (Bridge == NULL) {
356     return ;
357   }
358 
359   if (Bridge->ResType == PciBarTypeIo16) {
360 
361     CalculateApertureIo16 (Bridge);
362     return ;
363   }
364 
365   //
366   // Assume the bridge is aligned
367   //
368   for ( CurrentLink = GetFirstNode (&Bridge->ChildList)
369       ; !IsNull (&Bridge->ChildList, CurrentLink)
370       ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)
371       ) {
372 
373     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
374     if (Node->ResourceUsage == PciResUsagePadding) {
375       ASSERT (PaddingAperture == 0);
376       PaddingAperture = Node->Length;
377       continue;
378     }
379 
380     //
381     // Apply padding resource if available
382     //
383     Offset = Aperture & (Node->Alignment);
384 
385     if (Offset != 0) {
386 
387       Aperture = Aperture + (Node->Alignment + 1) - Offset;
388 
389     }
390 
391     //
392     // Recode current aperture as a offset
393     // this offset will be used in future real allocation
394     //
395     Node->Offset = Aperture;
396 
397     //
398     // Increment aperture by the length of node
399     //
400     Aperture += Node->Length;
401   }
402 
403   //
404   // At last, adjust the aperture with the bridge's
405   // alignment
406   //
407   Offset = Aperture & (Bridge->Alignment);
408   if (Offset != 0) {
409     Aperture = Aperture + (Bridge->Alignment + 1) - Offset;
410   }
411 
412   //
413   // If the bridge has already padded the resource and the
414   // amount of padded resource is larger, then keep the
415   // padded resource
416   //
417   if (Bridge->Length < Aperture) {
418     Bridge->Length = Aperture;
419   }
420 
421   //
422   // Adjust the bridge's alignment to the first child's alignment
423   // if the bridge has at least one child
424   //
425   CurrentLink = Bridge->ChildList.ForwardLink;
426   if (CurrentLink != &Bridge->ChildList) {
427     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
428     if (Node->Alignment > Bridge->Alignment) {
429       Bridge->Alignment = Node->Alignment;
430     }
431   }
432 
433   //
434   // Hotplug controller needs padding resources.
435   // Use the larger one between the padding resource and actual occupied resource.
436   //
437   Bridge->Length = MAX (Bridge->Length, PaddingAperture);
438 }
439 
440 /**
441   Get IO/Memory resource infor for given PCI device.
442 
443   @param PciDev     Pci device instance.
444   @param IoNode     Resource info node for IO .
445   @param Mem32Node  Resource info node for 32-bit memory.
446   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
447   @param Mem64Node  Resource info node for 64-bit memory.
448   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
449 
450 **/
451 VOID
GetResourceFromDevice(IN PCI_IO_DEVICE * PciDev,IN OUT PCI_RESOURCE_NODE * IoNode,IN OUT PCI_RESOURCE_NODE * Mem32Node,IN OUT PCI_RESOURCE_NODE * PMem32Node,IN OUT PCI_RESOURCE_NODE * Mem64Node,IN OUT PCI_RESOURCE_NODE * PMem64Node)452 GetResourceFromDevice (
453   IN     PCI_IO_DEVICE     *PciDev,
454   IN OUT PCI_RESOURCE_NODE *IoNode,
455   IN OUT PCI_RESOURCE_NODE *Mem32Node,
456   IN OUT PCI_RESOURCE_NODE *PMem32Node,
457   IN OUT PCI_RESOURCE_NODE *Mem64Node,
458   IN OUT PCI_RESOURCE_NODE *PMem64Node
459   )
460 {
461 
462   UINT8             Index;
463   PCI_RESOURCE_NODE *Node;
464   BOOLEAN           ResourceRequested;
465 
466   Node              = NULL;
467   ResourceRequested = FALSE;
468 
469   for (Index = 0; Index < PCI_MAX_BAR; Index++) {
470 
471     switch ((PciDev->PciBar)[Index].BarType) {
472 
473     case PciBarTypeMem32:
474 
475       Node = CreateResourceNode (
476               PciDev,
477               (PciDev->PciBar)[Index].Length,
478               (PciDev->PciBar)[Index].Alignment,
479               Index,
480               PciBarTypeMem32,
481               PciResUsageTypical
482               );
483 
484       InsertResourceNode (
485         Mem32Node,
486         Node
487         );
488 
489       ResourceRequested = TRUE;
490       break;
491 
492     case PciBarTypeMem64:
493 
494       Node = CreateResourceNode (
495               PciDev,
496               (PciDev->PciBar)[Index].Length,
497               (PciDev->PciBar)[Index].Alignment,
498               Index,
499               PciBarTypeMem64,
500               PciResUsageTypical
501               );
502 
503       InsertResourceNode (
504         Mem64Node,
505         Node
506         );
507 
508       ResourceRequested = TRUE;
509       break;
510 
511     case PciBarTypePMem64:
512 
513       Node = CreateResourceNode (
514               PciDev,
515               (PciDev->PciBar)[Index].Length,
516               (PciDev->PciBar)[Index].Alignment,
517               Index,
518               PciBarTypePMem64,
519               PciResUsageTypical
520               );
521 
522       InsertResourceNode (
523         PMem64Node,
524         Node
525         );
526 
527       ResourceRequested = TRUE;
528       break;
529 
530     case PciBarTypePMem32:
531 
532       Node = CreateResourceNode (
533               PciDev,
534               (PciDev->PciBar)[Index].Length,
535               (PciDev->PciBar)[Index].Alignment,
536               Index,
537               PciBarTypePMem32,
538               PciResUsageTypical
539               );
540 
541       InsertResourceNode (
542         PMem32Node,
543         Node
544         );
545       ResourceRequested = TRUE;
546       break;
547 
548     case PciBarTypeIo16:
549     case PciBarTypeIo32:
550 
551       Node = CreateResourceNode (
552               PciDev,
553               (PciDev->PciBar)[Index].Length,
554               (PciDev->PciBar)[Index].Alignment,
555               Index,
556               PciBarTypeIo16,
557               PciResUsageTypical
558               );
559 
560       InsertResourceNode (
561         IoNode,
562         Node
563         );
564       ResourceRequested = TRUE;
565       break;
566 
567     case PciBarTypeUnknown:
568       break;
569 
570     default:
571       break;
572     }
573   }
574 
575   //
576   // Add VF resource
577   //
578   for (Index = 0; Index < PCI_MAX_BAR; Index++) {
579 
580     switch ((PciDev->VfPciBar)[Index].BarType) {
581 
582     case PciBarTypeMem32:
583 
584       Node = CreateVfResourceNode (
585               PciDev,
586               (PciDev->VfPciBar)[Index].Length,
587               (PciDev->VfPciBar)[Index].Alignment,
588               Index,
589               PciBarTypeMem32,
590               PciResUsageTypical
591               );
592 
593       InsertResourceNode (
594         Mem32Node,
595         Node
596         );
597 
598       break;
599 
600     case PciBarTypeMem64:
601 
602       Node = CreateVfResourceNode (
603               PciDev,
604               (PciDev->VfPciBar)[Index].Length,
605               (PciDev->VfPciBar)[Index].Alignment,
606               Index,
607               PciBarTypeMem64,
608               PciResUsageTypical
609               );
610 
611       InsertResourceNode (
612         Mem64Node,
613         Node
614         );
615 
616       break;
617 
618     case PciBarTypePMem64:
619 
620       Node = CreateVfResourceNode (
621               PciDev,
622               (PciDev->VfPciBar)[Index].Length,
623               (PciDev->VfPciBar)[Index].Alignment,
624               Index,
625               PciBarTypePMem64,
626               PciResUsageTypical
627               );
628 
629       InsertResourceNode (
630         PMem64Node,
631         Node
632         );
633 
634       break;
635 
636     case PciBarTypePMem32:
637 
638       Node = CreateVfResourceNode (
639               PciDev,
640               (PciDev->VfPciBar)[Index].Length,
641               (PciDev->VfPciBar)[Index].Alignment,
642               Index,
643               PciBarTypePMem32,
644               PciResUsageTypical
645               );
646 
647       InsertResourceNode (
648         PMem32Node,
649         Node
650         );
651       break;
652 
653     case PciBarTypeIo16:
654     case PciBarTypeIo32:
655       break;
656 
657     case PciBarTypeUnknown:
658       break;
659 
660     default:
661       break;
662     }
663   }
664   // If there is no resource requested from this device,
665   // then we indicate this device has been allocated naturally.
666   //
667   if (!ResourceRequested) {
668     PciDev->Allocated = TRUE;
669   }
670 }
671 
672 /**
673   This function is used to create a resource node.
674 
675   @param PciDev       Pci device instance.
676   @param Length       Length of Io/Memory resource.
677   @param Alignment    Alignment of resource.
678   @param Bar          Bar index.
679   @param ResType      Type of resource: IO/Memory.
680   @param ResUsage     Resource usage.
681 
682   @return PCI resource node created for given PCI device.
683           NULL means PCI resource node is not created.
684 
685 **/
686 PCI_RESOURCE_NODE *
CreateResourceNode(IN PCI_IO_DEVICE * PciDev,IN UINT64 Length,IN UINT64 Alignment,IN UINT8 Bar,IN PCI_BAR_TYPE ResType,IN PCI_RESOURCE_USAGE ResUsage)687 CreateResourceNode (
688   IN PCI_IO_DEVICE         *PciDev,
689   IN UINT64                Length,
690   IN UINT64                Alignment,
691   IN UINT8                 Bar,
692   IN PCI_BAR_TYPE          ResType,
693   IN PCI_RESOURCE_USAGE    ResUsage
694   )
695 {
696   PCI_RESOURCE_NODE *Node;
697 
698   Node    = NULL;
699 
700   Node    = AllocateZeroPool (sizeof (PCI_RESOURCE_NODE));
701   ASSERT (Node != NULL);
702   if (Node == NULL) {
703     return NULL;
704   }
705 
706   Node->Signature     = PCI_RESOURCE_SIGNATURE;
707   Node->PciDev        = PciDev;
708   Node->Length        = Length;
709   Node->Alignment     = Alignment;
710   Node->Bar           = Bar;
711   Node->ResType       = ResType;
712   Node->Reserved      = FALSE;
713   Node->ResourceUsage = ResUsage;
714   InitializeListHead (&Node->ChildList);
715 
716   return Node;
717 }
718 
719 /**
720   This function is used to create a IOV VF resource node.
721 
722   @param PciDev       Pci device instance.
723   @param Length       Length of Io/Memory resource.
724   @param Alignment    Alignment of resource.
725   @param Bar          Bar index.
726   @param ResType      Type of resource: IO/Memory.
727   @param ResUsage     Resource usage.
728 
729   @return PCI resource node created for given VF PCI device.
730           NULL means PCI resource node is not created.
731 
732 **/
733 PCI_RESOURCE_NODE *
CreateVfResourceNode(IN PCI_IO_DEVICE * PciDev,IN UINT64 Length,IN UINT64 Alignment,IN UINT8 Bar,IN PCI_BAR_TYPE ResType,IN PCI_RESOURCE_USAGE ResUsage)734 CreateVfResourceNode (
735   IN PCI_IO_DEVICE         *PciDev,
736   IN UINT64                Length,
737   IN UINT64                Alignment,
738   IN UINT8                 Bar,
739   IN PCI_BAR_TYPE          ResType,
740   IN PCI_RESOURCE_USAGE    ResUsage
741   )
742 {
743   PCI_RESOURCE_NODE *Node;
744 
745   Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);
746   if (Node == NULL) {
747     return Node;
748   }
749 
750   Node->Virtual = TRUE;
751 
752   return Node;
753 }
754 
755 /**
756   This function is used to extract resource request from
757   device node list.
758 
759   @param Bridge     Pci device instance.
760   @param IoNode     Resource info node for IO.
761   @param Mem32Node  Resource info node for 32-bit memory.
762   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
763   @param Mem64Node  Resource info node for 64-bit memory.
764   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
765 
766 **/
767 VOID
CreateResourceMap(IN PCI_IO_DEVICE * Bridge,IN OUT PCI_RESOURCE_NODE * IoNode,IN OUT PCI_RESOURCE_NODE * Mem32Node,IN OUT PCI_RESOURCE_NODE * PMem32Node,IN OUT PCI_RESOURCE_NODE * Mem64Node,IN OUT PCI_RESOURCE_NODE * PMem64Node)768 CreateResourceMap (
769   IN     PCI_IO_DEVICE     *Bridge,
770   IN OUT PCI_RESOURCE_NODE *IoNode,
771   IN OUT PCI_RESOURCE_NODE *Mem32Node,
772   IN OUT PCI_RESOURCE_NODE *PMem32Node,
773   IN OUT PCI_RESOURCE_NODE *Mem64Node,
774   IN OUT PCI_RESOURCE_NODE *PMem64Node
775   )
776 {
777   PCI_IO_DEVICE     *Temp;
778   PCI_RESOURCE_NODE *IoBridge;
779   PCI_RESOURCE_NODE *Mem32Bridge;
780   PCI_RESOURCE_NODE *PMem32Bridge;
781   PCI_RESOURCE_NODE *Mem64Bridge;
782   PCI_RESOURCE_NODE *PMem64Bridge;
783   LIST_ENTRY        *CurrentLink;
784 
785   CurrentLink = Bridge->ChildList.ForwardLink;
786 
787   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
788 
789     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
790 
791     //
792     // Create resource nodes for this device by scanning the
793     // Bar array in the device private data
794     // If the upstream bridge doesn't support this device,
795     // no any resource node will be created for this device
796     //
797     GetResourceFromDevice (
798       Temp,
799       IoNode,
800       Mem32Node,
801       PMem32Node,
802       Mem64Node,
803       PMem64Node
804       );
805 
806     if (IS_PCI_BRIDGE (&Temp->Pci)) {
807 
808       //
809       // If the device has children, create a bridge resource node for this PPB
810       // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
811       // is aligned with 4KB (smaller alignments may be supported).
812       //
813       IoBridge = CreateResourceNode (
814                    Temp,
815                    0,
816                    Temp->BridgeIoAlignment,
817                    PPB_IO_RANGE,
818                    PciBarTypeIo16,
819                    PciResUsageTypical
820                    );
821 
822       Mem32Bridge = CreateResourceNode (
823                       Temp,
824                       0,
825                       0xFFFFF,
826                       PPB_MEM32_RANGE,
827                       PciBarTypeMem32,
828                       PciResUsageTypical
829                       );
830 
831       PMem32Bridge = CreateResourceNode (
832                        Temp,
833                        0,
834                        0xFFFFF,
835                        PPB_PMEM32_RANGE,
836                        PciBarTypePMem32,
837                        PciResUsageTypical
838                        );
839 
840       Mem64Bridge = CreateResourceNode (
841                       Temp,
842                       0,
843                       0xFFFFF,
844                       PPB_MEM64_RANGE,
845                       PciBarTypeMem64,
846                       PciResUsageTypical
847                       );
848 
849       PMem64Bridge = CreateResourceNode (
850                        Temp,
851                        0,
852                        0xFFFFF,
853                        PPB_PMEM64_RANGE,
854                        PciBarTypePMem64,
855                        PciResUsageTypical
856                        );
857 
858       //
859       // Recursively create resouce map on this bridge
860       //
861       CreateResourceMap (
862         Temp,
863         IoBridge,
864         Mem32Bridge,
865         PMem32Bridge,
866         Mem64Bridge,
867         PMem64Bridge
868         );
869 
870       if (ResourceRequestExisted (IoBridge)) {
871         InsertResourceNode (
872           IoNode,
873           IoBridge
874           );
875       } else {
876         FreePool (IoBridge);
877         IoBridge = NULL;
878       }
879 
880       //
881       // If there is node under this resource bridge,
882       // then calculate bridge's aperture of this type
883       // and insert it into the respective resource tree.
884       // If no, delete this resource bridge
885       //
886       if (ResourceRequestExisted (Mem32Bridge)) {
887         InsertResourceNode (
888           Mem32Node,
889           Mem32Bridge
890           );
891       } else {
892         FreePool (Mem32Bridge);
893         Mem32Bridge = NULL;
894       }
895 
896       //
897       // If there is node under this resource bridge,
898       // then calculate bridge's aperture of this type
899       // and insert it into the respective resource tree.
900       // If no, delete this resource bridge
901       //
902       if (ResourceRequestExisted (PMem32Bridge)) {
903         InsertResourceNode (
904           PMem32Node,
905           PMem32Bridge
906           );
907       } else {
908         FreePool (PMem32Bridge);
909         PMem32Bridge = NULL;
910       }
911 
912       //
913       // If there is node under this resource bridge,
914       // then calculate bridge's aperture of this type
915       // and insert it into the respective resource tree.
916       // If no, delete this resource bridge
917       //
918       if (ResourceRequestExisted (Mem64Bridge)) {
919         InsertResourceNode (
920           Mem64Node,
921           Mem64Bridge
922           );
923       } else {
924         FreePool (Mem64Bridge);
925         Mem64Bridge = NULL;
926       }
927 
928       //
929       // If there is node under this resource bridge,
930       // then calculate bridge's aperture of this type
931       // and insert it into the respective resource tree.
932       // If no, delete this resource bridge
933       //
934       if (ResourceRequestExisted (PMem64Bridge)) {
935         InsertResourceNode (
936           PMem64Node,
937           PMem64Bridge
938           );
939       } else {
940         FreePool (PMem64Bridge);
941         PMem64Bridge = NULL;
942       }
943 
944     }
945 
946     //
947     // If it is P2C, apply hard coded resource padding
948     //
949     if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
950       ResourcePaddingForCardBusBridge (
951         Temp,
952         IoNode,
953         Mem32Node,
954         PMem32Node,
955         Mem64Node,
956         PMem64Node
957         );
958     }
959 
960     CurrentLink = CurrentLink->ForwardLink;
961   }
962 
963   //
964   // To do some platform specific resource padding ...
965   //
966   ResourcePaddingPolicy (
967     Bridge,
968     IoNode,
969     Mem32Node,
970     PMem32Node,
971     Mem64Node,
972     PMem64Node
973     );
974 
975   //
976   // Degrade resource if necessary
977   //
978   DegradeResource (
979     Bridge,
980     Mem32Node,
981     PMem32Node,
982     Mem64Node,
983     PMem64Node
984     );
985 
986   //
987   // Calculate resource aperture for this bridge device
988   //
989   CalculateResourceAperture (Mem32Node);
990   CalculateResourceAperture (PMem32Node);
991   CalculateResourceAperture (Mem64Node);
992   CalculateResourceAperture (PMem64Node);
993   CalculateResourceAperture (IoNode);
994 }
995 
996 /**
997   This function is used to do the resource padding for a specific platform.
998 
999   @param PciDev     Pci device instance.
1000   @param IoNode     Resource info node for IO.
1001   @param Mem32Node  Resource info node for 32-bit memory.
1002   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1003   @param Mem64Node  Resource info node for 64-bit memory.
1004   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1005 
1006 **/
1007 VOID
ResourcePaddingPolicy(IN PCI_IO_DEVICE * PciDev,IN PCI_RESOURCE_NODE * IoNode,IN PCI_RESOURCE_NODE * Mem32Node,IN PCI_RESOURCE_NODE * PMem32Node,IN PCI_RESOURCE_NODE * Mem64Node,IN PCI_RESOURCE_NODE * PMem64Node)1008 ResourcePaddingPolicy (
1009   IN PCI_IO_DEVICE     *PciDev,
1010   IN PCI_RESOURCE_NODE *IoNode,
1011   IN PCI_RESOURCE_NODE *Mem32Node,
1012   IN PCI_RESOURCE_NODE *PMem32Node,
1013   IN PCI_RESOURCE_NODE *Mem64Node,
1014   IN PCI_RESOURCE_NODE *PMem64Node
1015   )
1016 {
1017   //
1018   // Create padding resource node
1019   //
1020   if (PciDev->ResourcePaddingDescriptors != NULL) {
1021     ApplyResourcePadding (
1022       PciDev,
1023       IoNode,
1024       Mem32Node,
1025       PMem32Node,
1026       Mem64Node,
1027       PMem64Node
1028       );
1029   }
1030 }
1031 
1032 /**
1033   This function is used to degrade resource if the upstream bridge
1034   doesn't support certain resource. Degradation path is
1035   PMEM64 -> MEM64  -> MEM32
1036   PMEM64 -> PMEM32 -> MEM32
1037   IO32   -> IO16.
1038 
1039   @param Bridge     Pci device instance.
1040   @param Mem32Node  Resource info node for 32-bit memory.
1041   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1042   @param Mem64Node  Resource info node for 64-bit memory.
1043   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1044 
1045 **/
1046 VOID
DegradeResource(IN PCI_IO_DEVICE * Bridge,IN PCI_RESOURCE_NODE * Mem32Node,IN PCI_RESOURCE_NODE * PMem32Node,IN PCI_RESOURCE_NODE * Mem64Node,IN PCI_RESOURCE_NODE * PMem64Node)1047 DegradeResource (
1048   IN PCI_IO_DEVICE     *Bridge,
1049   IN PCI_RESOURCE_NODE *Mem32Node,
1050   IN PCI_RESOURCE_NODE *PMem32Node,
1051   IN PCI_RESOURCE_NODE *Mem64Node,
1052   IN PCI_RESOURCE_NODE *PMem64Node
1053   )
1054 {
1055   PCI_IO_DEVICE        *PciIoDevice;
1056   LIST_ENTRY           *ChildDeviceLink;
1057   LIST_ENTRY           *ChildNodeLink;
1058   LIST_ENTRY           *NextChildNodeLink;
1059   PCI_RESOURCE_NODE    *ResourceNode;
1060 
1061   if (FeaturePcdGet (PcdPciDegradeResourceForOptionRom)) {
1062     //
1063     // If any child device has both option ROM and 64-bit BAR, degrade its PMEM64/MEM64
1064     // requests in case that if a legacy option ROM image can not access 64-bit resources.
1065     //
1066     ChildDeviceLink = Bridge->ChildList.ForwardLink;
1067     while (ChildDeviceLink != NULL && ChildDeviceLink != &Bridge->ChildList) {
1068       PciIoDevice = PCI_IO_DEVICE_FROM_LINK (ChildDeviceLink);
1069       if (PciIoDevice->RomSize != 0) {
1070         if (!IsListEmpty (&Mem64Node->ChildList)) {
1071           ChildNodeLink = Mem64Node->ChildList.ForwardLink;
1072           while (ChildNodeLink != &Mem64Node->ChildList) {
1073             ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);
1074             NextChildNodeLink = ChildNodeLink->ForwardLink;
1075 
1076             if ((ResourceNode->PciDev == PciIoDevice) &&
1077                 (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)
1078                 ) {
1079               RemoveEntryList (ChildNodeLink);
1080               InsertResourceNode (Mem32Node, ResourceNode);
1081             }
1082             ChildNodeLink = NextChildNodeLink;
1083           }
1084         }
1085 
1086         if (!IsListEmpty (&PMem64Node->ChildList)) {
1087           ChildNodeLink = PMem64Node->ChildList.ForwardLink;
1088           while (ChildNodeLink != &PMem64Node->ChildList) {
1089             ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);
1090             NextChildNodeLink = ChildNodeLink->ForwardLink;
1091 
1092             if ((ResourceNode->PciDev == PciIoDevice) &&
1093                 (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)
1094                 ) {
1095               RemoveEntryList (ChildNodeLink);
1096               InsertResourceNode (PMem32Node, ResourceNode);
1097             }
1098             ChildNodeLink = NextChildNodeLink;
1099           }
1100         }
1101 
1102       }
1103       ChildDeviceLink = ChildDeviceLink->ForwardLink;
1104     }
1105   }
1106 
1107   //
1108   // If firmware is in 32-bit mode,
1109   // then degrade PMEM64/MEM64 requests
1110   //
1111   if (sizeof (UINTN) <= 4) {
1112     MergeResourceTree (
1113       Mem32Node,
1114       Mem64Node,
1115       TRUE
1116       );
1117 
1118     MergeResourceTree (
1119       PMem32Node,
1120       PMem64Node,
1121       TRUE
1122       );
1123   } else {
1124     //
1125     // if the bridge does not support MEM64, degrade MEM64 to MEM32
1126     //
1127     if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {
1128         MergeResourceTree (
1129           Mem32Node,
1130           Mem64Node,
1131           TRUE
1132           );
1133     }
1134 
1135     //
1136     // if the bridge does not support PMEM64, degrade PMEM64 to PMEM32
1137     //
1138     if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {
1139       MergeResourceTree (
1140         PMem32Node,
1141         PMem64Node,
1142         TRUE
1143         );
1144     }
1145 
1146     //
1147     // if both PMEM64 and PMEM32 requests from child devices, which can not be satisfied
1148     // by a P2P bridge simultaneously, keep PMEM64 and degrade PMEM32 to MEM32.
1149     //
1150     if (!IsListEmpty (&PMem64Node->ChildList) && Bridge->Parent != NULL) {
1151       MergeResourceTree (
1152         Mem32Node,
1153         PMem32Node,
1154         TRUE
1155         );
1156     }
1157   }
1158 
1159   //
1160   // If bridge doesn't support Pmem32
1161   // degrade it to mem32
1162   //
1163   if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {
1164     MergeResourceTree (
1165       Mem32Node,
1166       PMem32Node,
1167       TRUE
1168       );
1169   }
1170 
1171   //
1172   // if root bridge supports combined Pmem Mem decoding
1173   // merge these two type of resource
1174   //
1175   if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {
1176     MergeResourceTree (
1177       Mem32Node,
1178       PMem32Node,
1179       FALSE
1180       );
1181 
1182     //
1183     // No need to check if to degrade MEM64 after merge, because
1184     // if there are PMEM64 still here, 64-bit decode should be supported
1185     // by the root bride.
1186     //
1187     MergeResourceTree (
1188       Mem64Node,
1189       PMem64Node,
1190       FALSE
1191       );
1192   }
1193 }
1194 
1195 /**
1196   Test whether bridge device support decode resource.
1197 
1198   @param Bridge    Bridge device instance.
1199   @param Decode    Decode type according to resource type.
1200 
1201   @return TRUE     The bridge device support decode resource.
1202   @return FALSE    The bridge device don't support decode resource.
1203 
1204 **/
1205 BOOLEAN
BridgeSupportResourceDecode(IN PCI_IO_DEVICE * Bridge,IN UINT32 Decode)1206 BridgeSupportResourceDecode (
1207   IN PCI_IO_DEVICE *Bridge,
1208   IN UINT32        Decode
1209   )
1210 {
1211   if (((Bridge->Decodes) & Decode) != 0) {
1212     return TRUE;
1213   }
1214 
1215   return FALSE;
1216 }
1217 
1218 /**
1219   This function is used to program the resource allocated
1220   for each resource node under specified bridge.
1221 
1222   @param Base     Base address of resource to be progammed.
1223   @param Bridge   PCI resource node for the bridge device.
1224 
1225   @retval EFI_SUCCESS            Successfully to program all resouces
1226                                  on given PCI bridge device.
1227   @retval EFI_OUT_OF_RESOURCES   Base is all one.
1228 
1229 **/
1230 EFI_STATUS
ProgramResource(IN UINT64 Base,IN PCI_RESOURCE_NODE * Bridge)1231 ProgramResource (
1232   IN UINT64            Base,
1233   IN PCI_RESOURCE_NODE *Bridge
1234   )
1235 {
1236   LIST_ENTRY        *CurrentLink;
1237   PCI_RESOURCE_NODE *Node;
1238   EFI_STATUS        Status;
1239 
1240   if (Base == gAllOne) {
1241     return EFI_OUT_OF_RESOURCES;
1242   }
1243 
1244   CurrentLink = Bridge->ChildList.ForwardLink;
1245 
1246   while (CurrentLink != &Bridge->ChildList) {
1247 
1248     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
1249 
1250     if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {
1251 
1252       if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
1253         //
1254         // Program the PCI Card Bus device
1255         //
1256         ProgramP2C (Base, Node);
1257       } else {
1258         //
1259         // Program the PCI device BAR
1260         //
1261         ProgramBar (Base, Node);
1262       }
1263     } else {
1264       //
1265       // Program the PCI devices under this bridge
1266       //
1267       Status = ProgramResource (Base + Node->Offset, Node);
1268       if (EFI_ERROR (Status)) {
1269         return Status;
1270       }
1271 
1272       ProgramPpbApperture (Base, Node);
1273     }
1274 
1275     CurrentLink = CurrentLink->ForwardLink;
1276   }
1277 
1278   return EFI_SUCCESS;
1279 }
1280 
1281 /**
1282   Program Bar register for PCI device.
1283 
1284   @param Base  Base address for PCI device resource to be progammed.
1285   @param Node  Point to resoure node structure.
1286 
1287 **/
1288 VOID
ProgramBar(IN UINT64 Base,IN PCI_RESOURCE_NODE * Node)1289 ProgramBar (
1290   IN UINT64            Base,
1291   IN PCI_RESOURCE_NODE *Node
1292   )
1293 {
1294   EFI_PCI_IO_PROTOCOL *PciIo;
1295   UINT64              Address;
1296   UINT32              Address32;
1297 
1298   ASSERT (Node->Bar < PCI_MAX_BAR);
1299 
1300   //
1301   // Check VF BAR
1302   //
1303   if (Node->Virtual) {
1304     ProgramVfBar (Base, Node);
1305     return;
1306   }
1307 
1308   Address = 0;
1309   PciIo   = &(Node->PciDev->PciIo);
1310 
1311   Address = Base + Node->Offset;
1312 
1313   //
1314   // Indicate pci bus driver has allocated
1315   // resource for this device
1316   // It might be a temporary solution here since
1317   // pci device could have multiple bar
1318   //
1319   Node->PciDev->Allocated = TRUE;
1320 
1321   switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
1322 
1323   case PciBarTypeIo16:
1324   case PciBarTypeIo32:
1325   case PciBarTypeMem32:
1326   case PciBarTypePMem32:
1327 
1328     PciIo->Pci.Write (
1329                  PciIo,
1330                  EfiPciIoWidthUint32,
1331                  (Node->PciDev->PciBar[Node->Bar]).Offset,
1332                  1,
1333                  &Address
1334                  );
1335 
1336     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1337 
1338     break;
1339 
1340   case PciBarTypeMem64:
1341   case PciBarTypePMem64:
1342 
1343     Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1344 
1345     PciIo->Pci.Write (
1346                  PciIo,
1347                  EfiPciIoWidthUint32,
1348                  (Node->PciDev->PciBar[Node->Bar]).Offset,
1349                  1,
1350                  &Address32
1351                  );
1352 
1353     Address32 = (UINT32) RShiftU64 (Address, 32);
1354 
1355     PciIo->Pci.Write (
1356                  PciIo,
1357                  EfiPciIoWidthUint32,
1358                  (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
1359                  1,
1360                  &Address32
1361                  );
1362 
1363     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1364 
1365     break;
1366 
1367   default:
1368     break;
1369   }
1370 }
1371 
1372 /**
1373   Program IOV VF Bar register for PCI device.
1374 
1375   @param Base  Base address for PCI device resource to be progammed.
1376   @param Node  Point to resoure node structure.
1377 
1378 **/
1379 EFI_STATUS
ProgramVfBar(IN UINT64 Base,IN PCI_RESOURCE_NODE * Node)1380 ProgramVfBar (
1381   IN UINT64            Base,
1382   IN PCI_RESOURCE_NODE *Node
1383   )
1384 {
1385   EFI_PCI_IO_PROTOCOL *PciIo;
1386   UINT64              Address;
1387   UINT32              Address32;
1388 
1389   ASSERT (Node->Bar < PCI_MAX_BAR);
1390   ASSERT (Node->Virtual);
1391 
1392   Address = 0;
1393   PciIo   = &(Node->PciDev->PciIo);
1394 
1395   Address = Base + Node->Offset;
1396 
1397   //
1398   // Indicate pci bus driver has allocated
1399   // resource for this device
1400   // It might be a temporary solution here since
1401   // pci device could have multiple bar
1402   //
1403   Node->PciDev->Allocated = TRUE;
1404 
1405   switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {
1406 
1407   case PciBarTypeMem32:
1408   case PciBarTypePMem32:
1409 
1410     PciIo->Pci.Write (
1411                 PciIo,
1412                 EfiPciIoWidthUint32,
1413                 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
1414                 1,
1415                 &Address
1416                 );
1417 
1418     Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
1419     break;
1420 
1421   case PciBarTypeMem64:
1422   case PciBarTypePMem64:
1423 
1424     Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1425 
1426     PciIo->Pci.Write (
1427                 PciIo,
1428                 EfiPciIoWidthUint32,
1429                 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
1430                 1,
1431                 &Address32
1432                 );
1433 
1434     Address32 = (UINT32) RShiftU64 (Address, 32);
1435 
1436     PciIo->Pci.Write (
1437                 PciIo,
1438                 EfiPciIoWidthUint32,
1439                 ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),
1440                 1,
1441                 &Address32
1442                 );
1443 
1444     Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
1445     break;
1446 
1447   case PciBarTypeIo16:
1448   case PciBarTypeIo32:
1449     break;
1450 
1451   default:
1452     break;
1453   }
1454 
1455   return EFI_SUCCESS;
1456 }
1457 
1458 /**
1459   Program PCI-PCI bridge apperture.
1460 
1461   @param Base  Base address for resource.
1462   @param Node  Point to resoure node structure.
1463 
1464 **/
1465 VOID
ProgramPpbApperture(IN UINT64 Base,IN PCI_RESOURCE_NODE * Node)1466 ProgramPpbApperture (
1467   IN UINT64            Base,
1468   IN PCI_RESOURCE_NODE *Node
1469   )
1470 {
1471   EFI_PCI_IO_PROTOCOL *PciIo;
1472   UINT64              Address;
1473   UINT32              Address32;
1474 
1475   Address = 0;
1476   //
1477   // If no device resource of this PPB, return anyway
1478   // Apperture is set default in the initialization code
1479   //
1480   if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {
1481     //
1482     // For padding resource node, just ignore when programming
1483     //
1484     return ;
1485   }
1486 
1487   PciIo   = &(Node->PciDev->PciIo);
1488   Address = Base + Node->Offset;
1489 
1490   //
1491   // Indicate the PPB resource has been allocated
1492   //
1493   Node->PciDev->Allocated = TRUE;
1494 
1495   switch (Node->Bar) {
1496 
1497   case PPB_BAR_0:
1498   case PPB_BAR_1:
1499     switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
1500 
1501       case PciBarTypeIo16:
1502       case PciBarTypeIo32:
1503       case PciBarTypeMem32:
1504       case PciBarTypePMem32:
1505 
1506         PciIo->Pci.Write (
1507                  PciIo,
1508                  EfiPciIoWidthUint32,
1509                  (Node->PciDev->PciBar[Node->Bar]).Offset,
1510                  1,
1511                  &Address
1512                  );
1513 
1514         Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1515         Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1516         break;
1517 
1518       case PciBarTypeMem64:
1519       case PciBarTypePMem64:
1520 
1521         Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1522 
1523         PciIo->Pci.Write (
1524                  PciIo,
1525                  EfiPciIoWidthUint32,
1526                  (Node->PciDev->PciBar[Node->Bar]).Offset,
1527                  1,
1528                  &Address32
1529                  );
1530 
1531         Address32 = (UINT32) RShiftU64 (Address, 32);
1532 
1533         PciIo->Pci.Write (
1534                  PciIo,
1535                  EfiPciIoWidthUint32,
1536                  (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
1537                  1,
1538                  &Address32
1539                  );
1540 
1541         Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1542         Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1543         break;
1544 
1545       default:
1546         break;
1547     }
1548     break;
1549 
1550   case PPB_IO_RANGE:
1551 
1552     Address32 = ((UINT32) (Address)) >> 8;
1553     PciIo->Pci.Write (
1554                  PciIo,
1555                  EfiPciIoWidthUint8,
1556                  0x1C,
1557                  1,
1558                  &Address32
1559                  );
1560 
1561     Address32 >>= 8;
1562     PciIo->Pci.Write (
1563                  PciIo,
1564                  EfiPciIoWidthUint16,
1565                  0x30,
1566                  1,
1567                  &Address32
1568                  );
1569 
1570     Address32 = (UINT32) (Address + Node->Length - 1);
1571     Address32 = ((UINT32) (Address32)) >> 8;
1572     PciIo->Pci.Write (
1573                  PciIo,
1574                  EfiPciIoWidthUint8,
1575                  0x1D,
1576                  1,
1577                  &Address32
1578                  );
1579 
1580     Address32 >>= 8;
1581     PciIo->Pci.Write (
1582                  PciIo,
1583                  EfiPciIoWidthUint16,
1584                  0x32,
1585                  1,
1586                  &Address32
1587                  );
1588 
1589     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1590     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1591     break;
1592 
1593   case PPB_MEM32_RANGE:
1594 
1595     Address32 = ((UINT32) (Address)) >> 16;
1596     PciIo->Pci.Write (
1597                  PciIo,
1598                  EfiPciIoWidthUint16,
1599                  0x20,
1600                  1,
1601                  &Address32
1602                  );
1603 
1604     Address32 = (UINT32) (Address + Node->Length - 1);
1605     Address32 = ((UINT32) (Address32)) >> 16;
1606     PciIo->Pci.Write (
1607                  PciIo,
1608                  EfiPciIoWidthUint16,
1609                  0x22,
1610                  1,
1611                  &Address32
1612                  );
1613 
1614     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1615     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1616     break;
1617 
1618   case PPB_PMEM32_RANGE:
1619   case PPB_PMEM64_RANGE:
1620 
1621     Address32 = ((UINT32) (Address)) >> 16;
1622     PciIo->Pci.Write (
1623                  PciIo,
1624                  EfiPciIoWidthUint16,
1625                  0x24,
1626                  1,
1627                  &Address32
1628                  );
1629 
1630     Address32 = (UINT32) (Address + Node->Length - 1);
1631     Address32 = ((UINT32) (Address32)) >> 16;
1632     PciIo->Pci.Write (
1633                  PciIo,
1634                  EfiPciIoWidthUint16,
1635                  0x26,
1636                  1,
1637                  &Address32
1638                  );
1639 
1640     Address32 = (UINT32) RShiftU64 (Address, 32);
1641     PciIo->Pci.Write (
1642                  PciIo,
1643                  EfiPciIoWidthUint32,
1644                  0x28,
1645                  1,
1646                  &Address32
1647                  );
1648 
1649     Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);
1650     PciIo->Pci.Write (
1651                  PciIo,
1652                  EfiPciIoWidthUint32,
1653                  0x2C,
1654                  1,
1655                  &Address32
1656                  );
1657 
1658     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1659     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1660     break;
1661 
1662   default:
1663     break;
1664   }
1665 }
1666 
1667 /**
1668   Program parent bridge for Option Rom.
1669 
1670   @param PciDevice      Pci deivce instance.
1671   @param OptionRomBase  Base address for Optiona Rom.
1672   @param Enable         Enable or disable PCI memory.
1673 
1674 **/
1675 VOID
ProgrameUpstreamBridgeForRom(IN PCI_IO_DEVICE * PciDevice,IN UINT32 OptionRomBase,IN BOOLEAN Enable)1676 ProgrameUpstreamBridgeForRom (
1677   IN PCI_IO_DEVICE   *PciDevice,
1678   IN UINT32          OptionRomBase,
1679   IN BOOLEAN         Enable
1680   )
1681 {
1682   PCI_IO_DEVICE     *Parent;
1683   PCI_RESOURCE_NODE Node;
1684   //
1685   // For root bridge, just return.
1686   //
1687   Parent = PciDevice->Parent;
1688   ZeroMem (&Node, sizeof (Node));
1689   while (Parent != NULL) {
1690     if (!IS_PCI_BRIDGE (&Parent->Pci)) {
1691       break;
1692     }
1693 
1694     Node.PciDev     = Parent;
1695     Node.Length     = PciDevice->RomSize;
1696     Node.Alignment  = 0;
1697     Node.Bar        = PPB_MEM32_RANGE;
1698     Node.ResType    = PciBarTypeMem32;
1699     Node.Offset     = 0;
1700 
1701     //
1702     // Program PPB to only open a single <= 16MB apperture
1703     //
1704     if (Enable) {
1705       ProgramPpbApperture (OptionRomBase, &Node);
1706       PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1707     } else {
1708       InitializePpb (Parent);
1709       PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1710     }
1711 
1712     Parent = Parent->Parent;
1713   }
1714 }
1715 
1716 /**
1717   Test whether resource exists for a bridge.
1718 
1719   @param Bridge  Point to resource node for a bridge.
1720 
1721   @retval TRUE   There is resource on the given bridge.
1722   @retval FALSE  There isn't resource on the given bridge.
1723 
1724 **/
1725 BOOLEAN
ResourceRequestExisted(IN PCI_RESOURCE_NODE * Bridge)1726 ResourceRequestExisted (
1727   IN PCI_RESOURCE_NODE    *Bridge
1728   )
1729 {
1730   if (Bridge != NULL) {
1731     if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {
1732       return TRUE;
1733     }
1734   }
1735 
1736   return FALSE;
1737 }
1738 
1739 /**
1740   Initialize resource pool structure.
1741 
1742   @param ResourcePool Point to resource pool structure. This pool
1743                       is reset to all zero when returned.
1744   @param ResourceType Type of resource.
1745 
1746 **/
1747 VOID
InitializeResourcePool(IN OUT PCI_RESOURCE_NODE * ResourcePool,IN PCI_BAR_TYPE ResourceType)1748 InitializeResourcePool (
1749   IN OUT PCI_RESOURCE_NODE   *ResourcePool,
1750   IN     PCI_BAR_TYPE        ResourceType
1751   )
1752 {
1753   ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
1754   ResourcePool->ResType   = ResourceType;
1755   ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
1756   InitializeListHead (&ResourcePool->ChildList);
1757 }
1758 
1759 /**
1760   Destory given resource tree.
1761 
1762   @param Bridge  PCI resource root node of resource tree.
1763 
1764 **/
1765 VOID
DestroyResourceTree(IN PCI_RESOURCE_NODE * Bridge)1766 DestroyResourceTree (
1767   IN PCI_RESOURCE_NODE *Bridge
1768   )
1769 {
1770   PCI_RESOURCE_NODE *Temp;
1771   LIST_ENTRY        *CurrentLink;
1772 
1773   while (!IsListEmpty (&Bridge->ChildList)) {
1774 
1775     CurrentLink = Bridge->ChildList.ForwardLink;
1776 
1777     Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);
1778     ASSERT (Temp);
1779 
1780     RemoveEntryList (CurrentLink);
1781 
1782     if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
1783       DestroyResourceTree (Temp);
1784     }
1785 
1786     FreePool (Temp);
1787   }
1788 }
1789 
1790 /**
1791   Insert resource padding for P2C.
1792 
1793   @param PciDev     Pci device instance.
1794   @param IoNode     Resource info node for IO.
1795   @param Mem32Node  Resource info node for 32-bit memory.
1796   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1797   @param Mem64Node  Resource info node for 64-bit memory.
1798   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1799 
1800 **/
1801 VOID
ResourcePaddingForCardBusBridge(IN PCI_IO_DEVICE * PciDev,IN PCI_RESOURCE_NODE * IoNode,IN PCI_RESOURCE_NODE * Mem32Node,IN PCI_RESOURCE_NODE * PMem32Node,IN PCI_RESOURCE_NODE * Mem64Node,IN PCI_RESOURCE_NODE * PMem64Node)1802 ResourcePaddingForCardBusBridge (
1803   IN PCI_IO_DEVICE        *PciDev,
1804   IN PCI_RESOURCE_NODE    *IoNode,
1805   IN PCI_RESOURCE_NODE    *Mem32Node,
1806   IN PCI_RESOURCE_NODE    *PMem32Node,
1807   IN PCI_RESOURCE_NODE    *Mem64Node,
1808   IN PCI_RESOURCE_NODE    *PMem64Node
1809   )
1810 {
1811   PCI_RESOURCE_NODE *Node;
1812 
1813   Node = NULL;
1814 
1815   //
1816   // Memory Base/Limit Register 0
1817   // Bar 1 denodes memory range 0
1818   //
1819   Node = CreateResourceNode (
1820            PciDev,
1821            0x2000000,
1822            0x1ffffff,
1823            1,
1824            PciBarTypeMem32,
1825            PciResUsagePadding
1826            );
1827 
1828   InsertResourceNode (
1829     Mem32Node,
1830     Node
1831     );
1832 
1833   //
1834   // Memory Base/Limit Register 1
1835   // Bar 2 denodes memory range1
1836   //
1837   Node = CreateResourceNode (
1838            PciDev,
1839            0x2000000,
1840            0x1ffffff,
1841            2,
1842            PciBarTypePMem32,
1843            PciResUsagePadding
1844            );
1845 
1846   InsertResourceNode (
1847     PMem32Node,
1848     Node
1849     );
1850 
1851   //
1852   // Io Base/Limit
1853   // Bar 3 denodes io range 0
1854   //
1855   Node = CreateResourceNode (
1856            PciDev,
1857            0x100,
1858            0xff,
1859            3,
1860            PciBarTypeIo16,
1861            PciResUsagePadding
1862            );
1863 
1864   InsertResourceNode (
1865     IoNode,
1866     Node
1867     );
1868 
1869   //
1870   // Io Base/Limit
1871   // Bar 4 denodes io range 0
1872   //
1873   Node = CreateResourceNode (
1874            PciDev,
1875            0x100,
1876            0xff,
1877            4,
1878            PciBarTypeIo16,
1879            PciResUsagePadding
1880            );
1881 
1882   InsertResourceNode (
1883     IoNode,
1884     Node
1885     );
1886 }
1887 
1888 /**
1889   Program PCI Card device register for given resource node.
1890 
1891   @param Base    Base address of PCI Card device to be programmed.
1892   @param Node    Given resource node.
1893 
1894 **/
1895 VOID
ProgramP2C(IN UINT64 Base,IN PCI_RESOURCE_NODE * Node)1896 ProgramP2C (
1897   IN UINT64            Base,
1898   IN PCI_RESOURCE_NODE *Node
1899   )
1900 {
1901   EFI_PCI_IO_PROTOCOL *PciIo;
1902   UINT64              Address;
1903   UINT64              TempAddress;
1904   UINT16              BridgeControl;
1905 
1906   Address = 0;
1907   PciIo   = &(Node->PciDev->PciIo);
1908 
1909   Address = Base + Node->Offset;
1910 
1911   //
1912   // Indicate pci bus driver has allocated
1913   // resource for this device
1914   // It might be a temporary solution here since
1915   // pci device could have multiple bar
1916   //
1917   Node->PciDev->Allocated = TRUE;
1918 
1919   switch (Node->Bar) {
1920 
1921   case P2C_BAR_0:
1922     PciIo->Pci.Write (
1923                  PciIo,
1924                  EfiPciIoWidthUint32,
1925                  (Node->PciDev->PciBar[Node->Bar]).Offset,
1926                  1,
1927                  &Address
1928                  );
1929 
1930     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1931     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1932     break;
1933 
1934   case P2C_MEM_1:
1935     PciIo->Pci.Write (
1936                  PciIo,
1937                  EfiPciIoWidthUint32,
1938                  PCI_CARD_MEMORY_BASE_0,
1939                  1,
1940                  &Address
1941                  );
1942 
1943     TempAddress = Address + Node->Length - 1;
1944     PciIo->Pci.Write (
1945                  PciIo,
1946                  EfiPciIoWidthUint32,
1947                  PCI_CARD_MEMORY_LIMIT_0,
1948                  1,
1949                  &TempAddress
1950                  );
1951 
1952     if (Node->ResType == PciBarTypeMem32) {
1953       //
1954       // Set non-prefetchable bit
1955       //
1956       PciIo->Pci.Read (
1957                    PciIo,
1958                    EfiPciIoWidthUint16,
1959                    PCI_CARD_BRIDGE_CONTROL,
1960                    1,
1961                    &BridgeControl
1962                    );
1963 
1964       BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
1965       PciIo->Pci.Write (
1966                    PciIo,
1967                    EfiPciIoWidthUint16,
1968                    PCI_CARD_BRIDGE_CONTROL,
1969                    1,
1970                    &BridgeControl
1971                    );
1972 
1973     } else {
1974       //
1975       // Set pre-fetchable bit
1976       //
1977       PciIo->Pci.Read (
1978                    PciIo,
1979                    EfiPciIoWidthUint16,
1980                    PCI_CARD_BRIDGE_CONTROL,
1981                    1,
1982                    &BridgeControl
1983                    );
1984 
1985       BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
1986       PciIo->Pci.Write (
1987                    PciIo,
1988                    EfiPciIoWidthUint16,
1989                    PCI_CARD_BRIDGE_CONTROL,
1990                    1,
1991                    &BridgeControl
1992                    );
1993     }
1994 
1995     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1996     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1997     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
1998 
1999     break;
2000 
2001   case P2C_MEM_2:
2002     PciIo->Pci.Write (
2003                  PciIo,
2004                  EfiPciIoWidthUint32,
2005                  PCI_CARD_MEMORY_BASE_1,
2006                  1,
2007                  &Address
2008                  );
2009 
2010     TempAddress = Address + Node->Length - 1;
2011 
2012     PciIo->Pci.Write (
2013                  PciIo,
2014                  EfiPciIoWidthUint32,
2015                  PCI_CARD_MEMORY_LIMIT_1,
2016                  1,
2017                  &TempAddress
2018                  );
2019 
2020     if (Node->ResType == PciBarTypeMem32) {
2021 
2022       //
2023       // Set non-prefetchable bit
2024       //
2025       PciIo->Pci.Read (
2026                    PciIo,
2027                    EfiPciIoWidthUint16,
2028                    PCI_CARD_BRIDGE_CONTROL,
2029                    1,
2030                    &BridgeControl
2031                    );
2032 
2033       BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);
2034       PciIo->Pci.Write (
2035                    PciIo,
2036                    EfiPciIoWidthUint16,
2037                    PCI_CARD_BRIDGE_CONTROL,
2038                    1,
2039                    &BridgeControl
2040                    );
2041 
2042     } else {
2043 
2044       //
2045       // Set pre-fetchable bit
2046       //
2047       PciIo->Pci.Read (
2048                    PciIo,
2049                    EfiPciIoWidthUint16,
2050                    PCI_CARD_BRIDGE_CONTROL,
2051                    1,
2052                    &BridgeControl
2053                    );
2054 
2055       BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;
2056       PciIo->Pci.Write (
2057                    PciIo,
2058                    EfiPciIoWidthUint16,
2059                    PCI_CARD_BRIDGE_CONTROL,
2060                    1,
2061                    &BridgeControl
2062                    );
2063     }
2064 
2065     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2066     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
2067     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
2068     break;
2069 
2070   case P2C_IO_1:
2071     PciIo->Pci.Write (
2072                  PciIo,
2073                  EfiPciIoWidthUint32,
2074                  PCI_CARD_IO_BASE_0_LOWER,
2075                  1,
2076                  &Address
2077                  );
2078 
2079     TempAddress = Address + Node->Length - 1;
2080     PciIo->Pci.Write (
2081                  PciIo,
2082                  EfiPciIoWidthUint32,
2083                  PCI_CARD_IO_LIMIT_0_LOWER,
2084                  1,
2085                  &TempAddress
2086                  );
2087 
2088     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2089     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
2090     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
2091 
2092     break;
2093 
2094   case P2C_IO_2:
2095     PciIo->Pci.Write (
2096                  PciIo,
2097                  EfiPciIoWidthUint32,
2098                  PCI_CARD_IO_BASE_1_LOWER,
2099                  1,
2100                  &Address
2101                  );
2102 
2103     TempAddress = Address + Node->Length - 1;
2104     PciIo->Pci.Write (
2105                  PciIo,
2106                  EfiPciIoWidthUint32,
2107                  PCI_CARD_IO_LIMIT_1_LOWER,
2108                  1,
2109                  &TempAddress
2110                  );
2111 
2112     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2113     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
2114     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
2115     break;
2116 
2117   default:
2118     break;
2119   }
2120 }
2121 
2122 /**
2123   Create padding resource node.
2124 
2125   @param PciDev     Pci device instance.
2126   @param IoNode     Resource info node for IO.
2127   @param Mem32Node  Resource info node for 32-bit memory.
2128   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
2129   @param Mem64Node  Resource info node for 64-bit memory.
2130   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
2131 
2132 **/
2133 VOID
ApplyResourcePadding(IN PCI_IO_DEVICE * PciDev,IN PCI_RESOURCE_NODE * IoNode,IN PCI_RESOURCE_NODE * Mem32Node,IN PCI_RESOURCE_NODE * PMem32Node,IN PCI_RESOURCE_NODE * Mem64Node,IN PCI_RESOURCE_NODE * PMem64Node)2134 ApplyResourcePadding (
2135   IN PCI_IO_DEVICE         *PciDev,
2136   IN PCI_RESOURCE_NODE     *IoNode,
2137   IN PCI_RESOURCE_NODE     *Mem32Node,
2138   IN PCI_RESOURCE_NODE     *PMem32Node,
2139   IN PCI_RESOURCE_NODE     *Mem64Node,
2140   IN PCI_RESOURCE_NODE     *PMem64Node
2141   )
2142 {
2143   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
2144   PCI_RESOURCE_NODE                 *Node;
2145   UINT8                             DummyBarIndex;
2146 
2147   DummyBarIndex = 0;
2148   Ptr           = PciDev->ResourcePaddingDescriptors;
2149 
2150   while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
2151 
2152     if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
2153       if (Ptr->AddrLen != 0) {
2154 
2155         Node = CreateResourceNode (
2156                 PciDev,
2157                 Ptr->AddrLen,
2158                 Ptr->AddrRangeMax,
2159                 DummyBarIndex,
2160                 PciBarTypeIo16,
2161                 PciResUsagePadding
2162                 );
2163         InsertResourceNode (
2164           IoNode,
2165           Node
2166           );
2167       }
2168 
2169       Ptr++;
2170       continue;
2171     }
2172 
2173     if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
2174 
2175       if (Ptr->AddrSpaceGranularity == 32) {
2176 
2177         //
2178         // prefechable
2179         //
2180         if (Ptr->SpecificFlag == 0x6) {
2181           if (Ptr->AddrLen != 0) {
2182             Node = CreateResourceNode (
2183                     PciDev,
2184                     Ptr->AddrLen,
2185                     Ptr->AddrRangeMax,
2186                     DummyBarIndex,
2187                     PciBarTypePMem32,
2188                     PciResUsagePadding
2189                     );
2190             InsertResourceNode (
2191               PMem32Node,
2192               Node
2193               );
2194           }
2195 
2196           Ptr++;
2197           continue;
2198         }
2199 
2200         //
2201         // Non-prefechable
2202         //
2203         if (Ptr->SpecificFlag == 0) {
2204           if (Ptr->AddrLen != 0) {
2205             Node = CreateResourceNode (
2206                     PciDev,
2207                     Ptr->AddrLen,
2208                     Ptr->AddrRangeMax,
2209                     DummyBarIndex,
2210                     PciBarTypeMem32,
2211                     PciResUsagePadding
2212                     );
2213             InsertResourceNode (
2214               Mem32Node,
2215               Node
2216               );
2217           }
2218 
2219           Ptr++;
2220           continue;
2221         }
2222       }
2223 
2224       if (Ptr->AddrSpaceGranularity == 64) {
2225 
2226         //
2227         // prefechable
2228         //
2229         if (Ptr->SpecificFlag == 0x6) {
2230           if (Ptr->AddrLen != 0) {
2231             Node = CreateResourceNode (
2232                     PciDev,
2233                     Ptr->AddrLen,
2234                     Ptr->AddrRangeMax,
2235                     DummyBarIndex,
2236                     PciBarTypePMem64,
2237                     PciResUsagePadding
2238                     );
2239             InsertResourceNode (
2240               PMem64Node,
2241               Node
2242               );
2243           }
2244 
2245           Ptr++;
2246           continue;
2247         }
2248 
2249         //
2250         // Non-prefechable
2251         //
2252         if (Ptr->SpecificFlag == 0) {
2253           if (Ptr->AddrLen != 0) {
2254             Node = CreateResourceNode (
2255                     PciDev,
2256                     Ptr->AddrLen,
2257                     Ptr->AddrRangeMax,
2258                     DummyBarIndex,
2259                     PciBarTypeMem64,
2260                     PciResUsagePadding
2261                     );
2262             InsertResourceNode (
2263               Mem64Node,
2264               Node
2265               );
2266           }
2267 
2268           Ptr++;
2269           continue;
2270         }
2271       }
2272     }
2273 
2274     Ptr++;
2275   }
2276 }
2277 
2278 /**
2279   Get padding resource for PCI-PCI bridge.
2280 
2281   @param  PciIoDevice     PCI-PCI bridge device instance.
2282 
2283   @note   Feature flag PcdPciBusHotplugDeviceSupport determines
2284           whether need to pad resource for them.
2285 **/
2286 VOID
GetResourcePaddingPpb(IN PCI_IO_DEVICE * PciIoDevice)2287 GetResourcePaddingPpb (
2288   IN  PCI_IO_DEVICE                  *PciIoDevice
2289   )
2290 {
2291   if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
2292     if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
2293       GetResourcePaddingForHpb (PciIoDevice);
2294     }
2295   }
2296 }
2297 
2298