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