MdeModulePkg/PciBus: Fix a bug PPB MEM32 BAR isn't restored sometimes
[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   EFI_PCI_IO_PROTOCOL *PciIo;\r
1666   UINT16              Base;\r
1667   UINT16              Limit;\r
1668   //\r
1669   // For root bridge, just return.\r
1670   //\r
1671   Parent = PciDevice->Parent;\r
1672   while (Parent != NULL) {\r
1673     if (!IS_PCI_BRIDGE (&Parent->Pci)) {\r
1674       break;\r
1675     }\r
1676 \r
1677     PciIo = &Parent->PciIo;\r
1678 \r
1679     //\r
1680     // Program PPB to only open a single <= 16MB aperture\r
1681     //\r
1682     if (Enable) {\r
1683       //\r
1684       // Only cover MMIO for Option ROM.\r
1685       //\r
1686       Base  = (UINT16) (OptionRomBase >> 16);\r
1687       Limit = (UINT16) ((OptionRomBase + PciDevice->RomSize - 1) >> 16);\r
1688       PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase),  1, &Base);\r
1689       PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);\r
1690 \r
1691       PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
1692     } else {\r
1693       //\r
1694       // Cover 32bit MMIO for devices below the bridge.\r
1695       //\r
1696       if (Parent->PciBar[PPB_MEM32_RANGE].Length == 0) {\r
1697         //\r
1698         // When devices under the bridge contains Option ROM and doesn't require 32bit MMIO.\r
1699         //\r
1700         Base  = (UINT16) gAllOne;\r
1701         Limit = (UINT16) gAllZero;\r
1702       } else {\r
1703         Base  = (UINT16) ((UINT32) Parent->PciBar[PPB_MEM32_RANGE].BaseAddress >> 16);\r
1704         Limit = (UINT16) ((UINT32) (Parent->PciBar[PPB_MEM32_RANGE].BaseAddress\r
1705                                     + Parent->PciBar[PPB_MEM32_RANGE].Length - 1) >> 16);\r
1706       }\r
1707       PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase),  1, &Base);\r
1708       PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);\r
1709 \r
1710       PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
1711     }\r
1712 \r
1713     Parent = Parent->Parent;\r
1714   }\r
1715 }\r
1716 \r
1717 /**\r
1718   Test whether resource exists for a bridge.\r
1719 \r
1720   @param Bridge  Point to resource node for a bridge.\r
1721 \r
1722   @retval TRUE   There is resource on the given bridge.\r
1723   @retval FALSE  There isn't resource on the given bridge.\r
1724 \r
1725 **/\r
1726 BOOLEAN\r
1727 ResourceRequestExisted (\r
1728   IN PCI_RESOURCE_NODE    *Bridge\r
1729   )\r
1730 {\r
1731   if (Bridge != NULL) {\r
1732     if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {\r
1733       return TRUE;\r
1734     }\r
1735   }\r
1736 \r
1737   return FALSE;\r
1738 }\r
1739 \r
1740 /**\r
1741   Initialize resource pool structure.\r
1742 \r
1743   @param ResourcePool Point to resource pool structure. This pool\r
1744                       is reset to all zero when returned.\r
1745   @param ResourceType Type of resource.\r
1746 \r
1747 **/\r
1748 VOID\r
1749 InitializeResourcePool (\r
1750   IN OUT PCI_RESOURCE_NODE   *ResourcePool,\r
1751   IN     PCI_BAR_TYPE        ResourceType\r
1752   )\r
1753 {\r
1754   ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));\r
1755   ResourcePool->ResType   = ResourceType;\r
1756   ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;\r
1757   InitializeListHead (&ResourcePool->ChildList);\r
1758 }\r
1759 \r
1760 /**\r
1761   Destroy given resource tree.\r
1762 \r
1763   @param Bridge  PCI resource root node of resource tree.\r
1764 \r
1765 **/\r
1766 VOID\r
1767 DestroyResourceTree (\r
1768   IN PCI_RESOURCE_NODE *Bridge\r
1769   )\r
1770 {\r
1771   PCI_RESOURCE_NODE *Temp;\r
1772   LIST_ENTRY        *CurrentLink;\r
1773 \r
1774   while (!IsListEmpty (&Bridge->ChildList)) {\r
1775 \r
1776     CurrentLink = Bridge->ChildList.ForwardLink;\r
1777 \r
1778     Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1779     ASSERT (Temp);\r
1780 \r
1781     RemoveEntryList (CurrentLink);\r
1782 \r
1783     if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {\r
1784       DestroyResourceTree (Temp);\r
1785     }\r
1786 \r
1787     FreePool (Temp);\r
1788   }\r
1789 }\r
1790 \r
1791 /**\r
1792   Insert resource padding for P2C.\r
1793 \r
1794   @param PciDev     Pci device instance.\r
1795   @param IoNode     Resource info node for IO.\r
1796   @param Mem32Node  Resource info node for 32-bit memory.\r
1797   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
1798   @param Mem64Node  Resource info node for 64-bit memory.\r
1799   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
1800 \r
1801 **/\r
1802 VOID\r
1803 ResourcePaddingForCardBusBridge (\r
1804   IN PCI_IO_DEVICE        *PciDev,\r
1805   IN PCI_RESOURCE_NODE    *IoNode,\r
1806   IN PCI_RESOURCE_NODE    *Mem32Node,\r
1807   IN PCI_RESOURCE_NODE    *PMem32Node,\r
1808   IN PCI_RESOURCE_NODE    *Mem64Node,\r
1809   IN PCI_RESOURCE_NODE    *PMem64Node\r
1810   )\r
1811 {\r
1812   PCI_RESOURCE_NODE *Node;\r
1813 \r
1814   Node = NULL;\r
1815 \r
1816   //\r
1817   // Memory Base/Limit Register 0\r
1818   // Bar 1 decodes memory range 0\r
1819   //\r
1820   Node = CreateResourceNode (\r
1821            PciDev,\r
1822            0x2000000,\r
1823            0x1ffffff,\r
1824            1,\r
1825            PciBarTypeMem32,\r
1826            PciResUsagePadding\r
1827            );\r
1828 \r
1829   InsertResourceNode (\r
1830     Mem32Node,\r
1831     Node\r
1832     );\r
1833 \r
1834   //\r
1835   // Memory Base/Limit Register 1\r
1836   // Bar 2 decodes memory range1\r
1837   //\r
1838   Node = CreateResourceNode (\r
1839            PciDev,\r
1840            0x2000000,\r
1841            0x1ffffff,\r
1842            2,\r
1843            PciBarTypePMem32,\r
1844            PciResUsagePadding\r
1845            );\r
1846 \r
1847   InsertResourceNode (\r
1848     PMem32Node,\r
1849     Node\r
1850     );\r
1851 \r
1852   //\r
1853   // Io Base/Limit\r
1854   // Bar 3 decodes io range 0\r
1855   //\r
1856   Node = CreateResourceNode (\r
1857            PciDev,\r
1858            0x100,\r
1859            0xff,\r
1860            3,\r
1861            PciBarTypeIo16,\r
1862            PciResUsagePadding\r
1863            );\r
1864 \r
1865   InsertResourceNode (\r
1866     IoNode,\r
1867     Node\r
1868     );\r
1869 \r
1870   //\r
1871   // Io Base/Limit\r
1872   // Bar 4 decodes io range 0\r
1873   //\r
1874   Node = CreateResourceNode (\r
1875            PciDev,\r
1876            0x100,\r
1877            0xff,\r
1878            4,\r
1879            PciBarTypeIo16,\r
1880            PciResUsagePadding\r
1881            );\r
1882 \r
1883   InsertResourceNode (\r
1884     IoNode,\r
1885     Node\r
1886     );\r
1887 }\r
1888 \r
1889 /**\r
1890   Program PCI Card device register for given resource node.\r
1891 \r
1892   @param Base    Base address of PCI Card device to be programmed.\r
1893   @param Node    Given resource node.\r
1894 \r
1895 **/\r
1896 VOID\r
1897 ProgramP2C (\r
1898   IN UINT64            Base,\r
1899   IN PCI_RESOURCE_NODE *Node\r
1900   )\r
1901 {\r
1902   EFI_PCI_IO_PROTOCOL *PciIo;\r
1903   UINT64              Address;\r
1904   UINT64              TempAddress;\r
1905   UINT16              BridgeControl;\r
1906 \r
1907   Address = 0;\r
1908   PciIo   = &(Node->PciDev->PciIo);\r
1909 \r
1910   Address = Base + Node->Offset;\r
1911 \r
1912   //\r
1913   // Indicate pci bus driver has allocated\r
1914   // resource for this device\r
1915   // It might be a temporary solution here since\r
1916   // pci device could have multiple bar\r
1917   //\r
1918   Node->PciDev->Allocated = TRUE;\r
1919 \r
1920   switch (Node->Bar) {\r
1921 \r
1922   case P2C_BAR_0:\r
1923     PciIo->Pci.Write (\r
1924                  PciIo,\r
1925                  EfiPciIoWidthUint32,\r
1926                  (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1927                  1,\r
1928                  &Address\r
1929                  );\r
1930 \r
1931     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1932     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
1933     break;\r
1934 \r
1935   case P2C_MEM_1:\r
1936     PciIo->Pci.Write (\r
1937                  PciIo,\r
1938                  EfiPciIoWidthUint32,\r
1939                  PCI_CARD_MEMORY_BASE_0,\r
1940                  1,\r
1941                  &Address\r
1942                  );\r
1943 \r
1944     TempAddress = Address + Node->Length - 1;\r
1945     PciIo->Pci.Write (\r
1946                  PciIo,\r
1947                  EfiPciIoWidthUint32,\r
1948                  PCI_CARD_MEMORY_LIMIT_0,\r
1949                  1,\r
1950                  &TempAddress\r
1951                  );\r
1952 \r
1953     if (Node->ResType == PciBarTypeMem32) {\r
1954       //\r
1955       // Set non-prefetchable bit\r
1956       //\r
1957       PciIo->Pci.Read (\r
1958                    PciIo,\r
1959                    EfiPciIoWidthUint16,\r
1960                    PCI_CARD_BRIDGE_CONTROL,\r
1961                    1,\r
1962                    &BridgeControl\r
1963                    );\r
1964 \r
1965       BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
1966       PciIo->Pci.Write (\r
1967                    PciIo,\r
1968                    EfiPciIoWidthUint16,\r
1969                    PCI_CARD_BRIDGE_CONTROL,\r
1970                    1,\r
1971                    &BridgeControl\r
1972                    );\r
1973 \r
1974     } else {\r
1975       //\r
1976       // Set prefetchable bit\r
1977       //\r
1978       PciIo->Pci.Read (\r
1979                    PciIo,\r
1980                    EfiPciIoWidthUint16,\r
1981                    PCI_CARD_BRIDGE_CONTROL,\r
1982                    1,\r
1983                    &BridgeControl\r
1984                    );\r
1985 \r
1986       BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
1987       PciIo->Pci.Write (\r
1988                    PciIo,\r
1989                    EfiPciIoWidthUint16,\r
1990                    PCI_CARD_BRIDGE_CONTROL,\r
1991                    1,\r
1992                    &BridgeControl\r
1993                    );\r
1994     }\r
1995 \r
1996     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1997     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
1998     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
1999 \r
2000     break;\r
2001 \r
2002   case P2C_MEM_2:\r
2003     PciIo->Pci.Write (\r
2004                  PciIo,\r
2005                  EfiPciIoWidthUint32,\r
2006                  PCI_CARD_MEMORY_BASE_1,\r
2007                  1,\r
2008                  &Address\r
2009                  );\r
2010 \r
2011     TempAddress = Address + Node->Length - 1;\r
2012 \r
2013     PciIo->Pci.Write (\r
2014                  PciIo,\r
2015                  EfiPciIoWidthUint32,\r
2016                  PCI_CARD_MEMORY_LIMIT_1,\r
2017                  1,\r
2018                  &TempAddress\r
2019                  );\r
2020 \r
2021     if (Node->ResType == PciBarTypeMem32) {\r
2022 \r
2023       //\r
2024       // Set non-prefetchable bit\r
2025       //\r
2026       PciIo->Pci.Read (\r
2027                    PciIo,\r
2028                    EfiPciIoWidthUint16,\r
2029                    PCI_CARD_BRIDGE_CONTROL,\r
2030                    1,\r
2031                    &BridgeControl\r
2032                    );\r
2033 \r
2034       BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);\r
2035       PciIo->Pci.Write (\r
2036                    PciIo,\r
2037                    EfiPciIoWidthUint16,\r
2038                    PCI_CARD_BRIDGE_CONTROL,\r
2039                    1,\r
2040                    &BridgeControl\r
2041                    );\r
2042 \r
2043     } else {\r
2044 \r
2045       //\r
2046       // Set prefetchable bit\r
2047       //\r
2048       PciIo->Pci.Read (\r
2049                    PciIo,\r
2050                    EfiPciIoWidthUint16,\r
2051                    PCI_CARD_BRIDGE_CONTROL,\r
2052                    1,\r
2053                    &BridgeControl\r
2054                    );\r
2055 \r
2056       BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;\r
2057       PciIo->Pci.Write (\r
2058                    PciIo,\r
2059                    EfiPciIoWidthUint16,\r
2060                    PCI_CARD_BRIDGE_CONTROL,\r
2061                    1,\r
2062                    &BridgeControl\r
2063                    );\r
2064     }\r
2065 \r
2066     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
2067     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
2068     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
2069     break;\r
2070 \r
2071   case P2C_IO_1:\r
2072     PciIo->Pci.Write (\r
2073                  PciIo,\r
2074                  EfiPciIoWidthUint32,\r
2075                  PCI_CARD_IO_BASE_0_LOWER,\r
2076                  1,\r
2077                  &Address\r
2078                  );\r
2079 \r
2080     TempAddress = Address + Node->Length - 1;\r
2081     PciIo->Pci.Write (\r
2082                  PciIo,\r
2083                  EfiPciIoWidthUint32,\r
2084                  PCI_CARD_IO_LIMIT_0_LOWER,\r
2085                  1,\r
2086                  &TempAddress\r
2087                  );\r
2088 \r
2089     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
2090     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
2091     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
2092 \r
2093     break;\r
2094 \r
2095   case P2C_IO_2:\r
2096     PciIo->Pci.Write (\r
2097                  PciIo,\r
2098                  EfiPciIoWidthUint32,\r
2099                  PCI_CARD_IO_BASE_1_LOWER,\r
2100                  1,\r
2101                  &Address\r
2102                  );\r
2103 \r
2104     TempAddress = Address + Node->Length - 1;\r
2105     PciIo->Pci.Write (\r
2106                  PciIo,\r
2107                  EfiPciIoWidthUint32,\r
2108                  PCI_CARD_IO_LIMIT_1_LOWER,\r
2109                  1,\r
2110                  &TempAddress\r
2111                  );\r
2112 \r
2113     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
2114     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;\r
2115     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;\r
2116     break;\r
2117 \r
2118   default:\r
2119     break;\r
2120   }\r
2121 }\r
2122 \r
2123 /**\r
2124   Create padding resource node.\r
2125 \r
2126   @param PciDev     Pci device instance.\r
2127   @param IoNode     Resource info node for IO.\r
2128   @param Mem32Node  Resource info node for 32-bit memory.\r
2129   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
2130   @param Mem64Node  Resource info node for 64-bit memory.\r
2131   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
2132 \r
2133 **/\r
2134 VOID\r
2135 ApplyResourcePadding (\r
2136   IN PCI_IO_DEVICE         *PciDev,\r
2137   IN PCI_RESOURCE_NODE     *IoNode,\r
2138   IN PCI_RESOURCE_NODE     *Mem32Node,\r
2139   IN PCI_RESOURCE_NODE     *PMem32Node,\r
2140   IN PCI_RESOURCE_NODE     *Mem64Node,\r
2141   IN PCI_RESOURCE_NODE     *PMem64Node\r
2142   )\r
2143 {\r
2144   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
2145   PCI_RESOURCE_NODE                 *Node;\r
2146   UINT8                             DummyBarIndex;\r
2147 \r
2148   DummyBarIndex = 0;\r
2149   Ptr           = PciDev->ResourcePaddingDescriptors;\r
2150 \r
2151   while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
2152 \r
2153     if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
2154       if (Ptr->AddrLen != 0) {\r
2155 \r
2156         Node = CreateResourceNode (\r
2157                 PciDev,\r
2158                 Ptr->AddrLen,\r
2159                 Ptr->AddrRangeMax,\r
2160                 DummyBarIndex,\r
2161                 PciBarTypeIo16,\r
2162                 PciResUsagePadding\r
2163                 );\r
2164         InsertResourceNode (\r
2165           IoNode,\r
2166           Node\r
2167           );\r
2168       }\r
2169 \r
2170       Ptr++;\r
2171       continue;\r
2172     }\r
2173 \r
2174     if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
2175 \r
2176       if (Ptr->AddrSpaceGranularity == 32) {\r
2177 \r
2178         //\r
2179         // prefetchable\r
2180         //\r
2181         if (Ptr->SpecificFlag == 0x6) {\r
2182           if (Ptr->AddrLen != 0) {\r
2183             Node = CreateResourceNode (\r
2184                     PciDev,\r
2185                     Ptr->AddrLen,\r
2186                     Ptr->AddrRangeMax,\r
2187                     DummyBarIndex,\r
2188                     PciBarTypePMem32,\r
2189                     PciResUsagePadding\r
2190                     );\r
2191             InsertResourceNode (\r
2192               PMem32Node,\r
2193               Node\r
2194               );\r
2195           }\r
2196 \r
2197           Ptr++;\r
2198           continue;\r
2199         }\r
2200 \r
2201         //\r
2202         // Non-prefetchable\r
2203         //\r
2204         if (Ptr->SpecificFlag == 0) {\r
2205           if (Ptr->AddrLen != 0) {\r
2206             Node = CreateResourceNode (\r
2207                     PciDev,\r
2208                     Ptr->AddrLen,\r
2209                     Ptr->AddrRangeMax,\r
2210                     DummyBarIndex,\r
2211                     PciBarTypeMem32,\r
2212                     PciResUsagePadding\r
2213                     );\r
2214             InsertResourceNode (\r
2215               Mem32Node,\r
2216               Node\r
2217               );\r
2218           }\r
2219 \r
2220           Ptr++;\r
2221           continue;\r
2222         }\r
2223       }\r
2224 \r
2225       if (Ptr->AddrSpaceGranularity == 64) {\r
2226 \r
2227         //\r
2228         // prefetchable\r
2229         //\r
2230         if (Ptr->SpecificFlag == 0x6) {\r
2231           if (Ptr->AddrLen != 0) {\r
2232             Node = CreateResourceNode (\r
2233                     PciDev,\r
2234                     Ptr->AddrLen,\r
2235                     Ptr->AddrRangeMax,\r
2236                     DummyBarIndex,\r
2237                     PciBarTypePMem64,\r
2238                     PciResUsagePadding\r
2239                     );\r
2240             InsertResourceNode (\r
2241               PMem64Node,\r
2242               Node\r
2243               );\r
2244           }\r
2245 \r
2246           Ptr++;\r
2247           continue;\r
2248         }\r
2249 \r
2250         //\r
2251         // Non-prefetchable\r
2252         //\r
2253         if (Ptr->SpecificFlag == 0) {\r
2254           if (Ptr->AddrLen != 0) {\r
2255             Node = CreateResourceNode (\r
2256                     PciDev,\r
2257                     Ptr->AddrLen,\r
2258                     Ptr->AddrRangeMax,\r
2259                     DummyBarIndex,\r
2260                     PciBarTypeMem64,\r
2261                     PciResUsagePadding\r
2262                     );\r
2263             InsertResourceNode (\r
2264               Mem64Node,\r
2265               Node\r
2266               );\r
2267           }\r
2268 \r
2269           Ptr++;\r
2270           continue;\r
2271         }\r
2272       }\r
2273     }\r
2274 \r
2275     Ptr++;\r
2276   }\r
2277 }\r
2278 \r
2279 /**\r
2280   Get padding resource for PCI-PCI bridge.\r
2281 \r
2282   @param  PciIoDevice     PCI-PCI bridge device instance.\r
2283 \r
2284   @note   Feature flag PcdPciBusHotplugDeviceSupport determines\r
2285           whether need to pad resource for them.\r
2286 **/\r
2287 VOID\r
2288 GetResourcePaddingPpb (\r
2289   IN  PCI_IO_DEVICE                  *PciIoDevice\r
2290   )\r
2291 {\r
2292   if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
2293     if (PciIoDevice->ResourcePaddingDescriptors == NULL) {\r
2294       GetResourcePaddingForHpb (PciIoDevice);\r
2295     }\r
2296   }\r
2297 }\r
2298 \r