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