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