]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
MdePkg: Follow PI1.4a to fix artificial limitation of SkuId range
[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
c7e7613e 4Copyright (c) 2006 - 2015, 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
9060e3ec 1055 PCI_IO_DEVICE *Temp;\r
de028a62 1056 LIST_ENTRY *ChildDeviceLink;\r
1057 LIST_ENTRY *ChildNodeLink;\r
4661d5df 1058 LIST_ENTRY *NextChildNodeLink;\r
60516202 1059 PCI_RESOURCE_NODE *TempNode;\r
9060e3ec 1060\r
1061 //\r
60516202 1062 // If any child device has both option ROM and 64-bit BAR, degrade its PMEM64/MEM64\r
1063 // requests in case that if a legacy option ROM image can not access 64-bit resources.\r
9060e3ec 1064 //\r
de028a62 1065 ChildDeviceLink = Bridge->ChildList.ForwardLink;\r
1066 while (ChildDeviceLink != NULL && ChildDeviceLink != &Bridge->ChildList) {\r
1067 Temp = PCI_IO_DEVICE_FROM_LINK (ChildDeviceLink);\r
9060e3ec 1068 if (Temp->RomSize != 0) {\r
60516202 1069 if (!IsListEmpty (&Mem64Node->ChildList)) { \r
de028a62 1070 ChildNodeLink = Mem64Node->ChildList.ForwardLink;\r
1071 while (ChildNodeLink != &Mem64Node->ChildList) {\r
1072 TempNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);\r
4661d5df 1073 NextChildNodeLink = ChildNodeLink->ForwardLink;\r
60516202 1074\r
1075 if (TempNode->PciDev == Temp) {\r
de028a62 1076 RemoveEntryList (ChildNodeLink);\r
60516202 1077 InsertResourceNode (Mem32Node, TempNode);\r
1078 }\r
4661d5df 1079 ChildNodeLink = NextChildNodeLink;\r
60516202 1080 } \r
1081 }\r
1082\r
1083 if (!IsListEmpty (&PMem64Node->ChildList)) { \r
de028a62 1084 ChildNodeLink = PMem64Node->ChildList.ForwardLink;\r
1085 while (ChildNodeLink != &PMem64Node->ChildList) {\r
1086 TempNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);\r
4661d5df 1087 NextChildNodeLink = ChildNodeLink->ForwardLink;\r
60516202 1088\r
1089 if (TempNode->PciDev == Temp) {\r
de028a62 1090 RemoveEntryList (ChildNodeLink);\r
60516202 1091 InsertResourceNode (PMem32Node, TempNode);\r
1092 }\r
4661d5df 1093 ChildNodeLink = NextChildNodeLink;\r
60516202 1094 } \r
1095 }\r
1096\r
9060e3ec 1097 }\r
de028a62 1098 ChildDeviceLink = ChildDeviceLink->ForwardLink;\r
9060e3ec 1099 }\r
1100\r
1101 //\r
60516202 1102 // If firmware is in 32-bit mode,\r
1103 // then degrade PMEM64/MEM64 requests\r
9060e3ec 1104 //\r
60516202 1105 if (sizeof (UINTN) <= 4) {\r
1106 MergeResourceTree (\r
1107 Mem32Node,\r
1108 Mem64Node,\r
1109 TRUE\r
1110 );\r
1111\r
9060e3ec 1112 MergeResourceTree (\r
1113 PMem32Node,\r
1114 PMem64Node,\r
1115 TRUE\r
1116 );\r
1117 } else {\r
1118 //\r
60516202 1119 // if the bridge does not support MEM64, degrade MEM64 to MEM32\r
9060e3ec 1120 //\r
60516202 1121 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {\r
1122 MergeResourceTree (\r
1123 Mem32Node,\r
1124 Mem64Node,\r
1125 TRUE\r
1126 );\r
1127 }\r
1128\r
1129 //\r
1130 // if the bridge does not support PMEM64, degrade PMEM64 to PMEM32\r
1131 //\r
1132 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {\r
9060e3ec 1133 MergeResourceTree (\r
1134 PMem32Node,\r
1135 PMem64Node,\r
1136 TRUE\r
1137 );\r
60516202 1138 } \r
9060e3ec 1139\r
60516202 1140 //\r
1141 // if both PMEM64 and PMEM32 requests from child devices, which can not be satisfied\r
1142 // by a P2P bridge simultaneously, keep PMEM64 and degrade PMEM32 to MEM32.\r
1143 //\r
1144 if (!IsListEmpty (&PMem64Node->ChildList) && Bridge->Parent != NULL) {\r
1145 MergeResourceTree (\r
1146 Mem32Node,\r
1147 PMem32Node,\r
1148 TRUE\r
1149 );\r
1150 }\r
9060e3ec 1151 }\r
1152\r
1153 //\r
1154 // If bridge doesn't support Pmem32\r
1155 // degrade it to mem32\r
1156 //\r
1157 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {\r
1158 MergeResourceTree (\r
1159 Mem32Node,\r
1160 PMem32Node,\r
1161 TRUE\r
1162 );\r
1163 }\r
1164\r
1165 //\r
60516202 1166 // if root bridge supports combined Pmem Mem decoding\r
9060e3ec 1167 // merge these two type of resource\r
1168 //\r
1169 if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {\r
1170 MergeResourceTree (\r
1171 Mem32Node,\r
1172 PMem32Node,\r
1173 FALSE\r
1174 );\r
1175\r
60516202 1176 //\r
1177 // No need to check if to degrade MEM64 after merge, because\r
1178 // if there are PMEM64 still here, 64-bit decode should be supported\r
1179 // by the root bride.\r
1180 //\r
9060e3ec 1181 MergeResourceTree (\r
1182 Mem64Node,\r
1183 PMem64Node,\r
1184 FALSE\r
1185 );\r
1186 }\r
1187}\r
1188\r
1189/**\r
1190 Test whether bridge device support decode resource.\r
1191\r
1192 @param Bridge Bridge device instance.\r
1193 @param Decode Decode type according to resource type.\r
1194\r
1195 @return TRUE The bridge device support decode resource.\r
1196 @return FALSE The bridge device don't support decode resource.\r
1197\r
1198**/\r
1199BOOLEAN\r
1200BridgeSupportResourceDecode (\r
1201 IN PCI_IO_DEVICE *Bridge,\r
1202 IN UINT32 Decode\r
1203 )\r
1204{\r
1205 if (((Bridge->Decodes) & Decode) != 0) {\r
1206 return TRUE;\r
1207 }\r
1208\r
1209 return FALSE;\r
1210}\r
1211\r
1212/**\r
1213 This function is used to program the resource allocated\r
1214 for each resource node under specified bridge.\r
1215\r
1216 @param Base Base address of resource to be progammed.\r
1217 @param Bridge PCI resource node for the bridge device.\r
1218\r
1219 @retval EFI_SUCCESS Successfully to program all resouces\r
1220 on given PCI bridge device.\r
1221 @retval EFI_OUT_OF_RESOURCES Base is all one.\r
1222\r
1223**/\r
1224EFI_STATUS\r
1225ProgramResource (\r
1226 IN UINT64 Base,\r
1227 IN PCI_RESOURCE_NODE *Bridge\r
1228 )\r
1229{\r
1230 LIST_ENTRY *CurrentLink;\r
1231 PCI_RESOURCE_NODE *Node;\r
1232 EFI_STATUS Status;\r
1233\r
1234 if (Base == gAllOne) {\r
1235 return EFI_OUT_OF_RESOURCES;\r
1236 }\r
1237\r
1238 CurrentLink = Bridge->ChildList.ForwardLink;\r
1239\r
1240 while (CurrentLink != &Bridge->ChildList) {\r
1241\r
1242 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1243\r
1244 if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {\r
1245\r
1246 if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
1247 //\r
1248 // Program the PCI Card Bus device\r
1249 //\r
1250 ProgramP2C (Base, Node);\r
1251 } else {\r
1252 //\r
1253 // Program the PCI device BAR\r
1254 //\r
1255 ProgramBar (Base, Node);\r
1256 }\r
1257 } else {\r
1258 //\r
1259 // Program the PCI devices under this bridge\r
1260 //\r
1261 Status = ProgramResource (Base + Node->Offset, Node);\r
1262 if (EFI_ERROR (Status)) {\r
1263 return Status;\r
1264 }\r
1265\r
1266 ProgramPpbApperture (Base, Node);\r
1267 }\r
1268\r
1269 CurrentLink = CurrentLink->ForwardLink;\r
1270 }\r
1271\r
1272 return EFI_SUCCESS;\r
1273}\r
1274\r
1275/**\r
1276 Program Bar register for PCI device.\r
1277\r
1278 @param Base Base address for PCI device resource to be progammed.\r
1279 @param Node Point to resoure node structure.\r
1280\r
1281**/\r
1282VOID\r
1283ProgramBar (\r
1284 IN UINT64 Base,\r
1285 IN PCI_RESOURCE_NODE *Node\r
1286 )\r
1287{\r
1288 EFI_PCI_IO_PROTOCOL *PciIo;\r
1289 UINT64 Address;\r
1290 UINT32 Address32;\r
1291\r
1292 ASSERT (Node->Bar < PCI_MAX_BAR);\r
1293\r
1294 //\r
1295 // Check VF BAR\r
1296 //\r
1297 if (Node->Virtual) {\r
1298 ProgramVfBar (Base, Node);\r
05399810 1299 return;\r
9060e3ec 1300 }\r
1301\r
1302 Address = 0;\r
1303 PciIo = &(Node->PciDev->PciIo);\r
1304\r
1305 Address = Base + Node->Offset;\r
1306\r
1307 //\r
1308 // Indicate pci bus driver has allocated\r
1309 // resource for this device\r
1310 // It might be a temporary solution here since\r
1311 // pci device could have multiple bar\r
1312 //\r
1313 Node->PciDev->Allocated = TRUE;\r
1314\r
1315 switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {\r
1316\r
1317 case PciBarTypeIo16:\r
1318 case PciBarTypeIo32:\r
1319 case PciBarTypeMem32:\r
1320 case PciBarTypePMem32:\r
1321\r
1322 PciIo->Pci.Write (\r
1323 PciIo,\r
1324 EfiPciIoWidthUint32,\r
1325 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1326 1,\r
1327 &Address\r
1328 );\r
1329\r
1330 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1331\r
1332 break;\r
1333\r
1334 case PciBarTypeMem64:\r
1335 case PciBarTypePMem64:\r
1336\r
1337 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
1338\r
1339 PciIo->Pci.Write (\r
1340 PciIo,\r
1341 EfiPciIoWidthUint32,\r
1342 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1343 1,\r
1344 &Address32\r
1345 );\r
1346\r
1347 Address32 = (UINT32) RShiftU64 (Address, 32);\r
1348\r
1349 PciIo->Pci.Write (\r
1350 PciIo,\r
1351 EfiPciIoWidthUint32,\r
1352 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),\r
1353 1,\r
1354 &Address32\r
1355 );\r
1356\r
1357 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1358\r
1359 break;\r
1360\r
1361 default:\r
1362 break;\r
1363 }\r
1364}\r
1365\r
1366/**\r
1367 Program IOV VF Bar register for PCI device.\r
1368\r
1369 @param Base Base address for PCI device resource to be progammed.\r
1370 @param Node Point to resoure node structure.\r
1371\r
1372**/\r
1373EFI_STATUS\r
1374ProgramVfBar (\r
1375 IN UINT64 Base,\r
1376 IN PCI_RESOURCE_NODE *Node\r
1377 )\r
1378{\r
1379 EFI_PCI_IO_PROTOCOL *PciIo;\r
1380 UINT64 Address;\r
1381 UINT32 Address32;\r
1382\r
1383 ASSERT (Node->Bar < PCI_MAX_BAR);\r
1384 ASSERT (Node->Virtual);\r
1385\r
1386 Address = 0;\r
1387 PciIo = &(Node->PciDev->PciIo);\r
1388\r
1389 Address = Base + Node->Offset;\r
1390\r
1391 //\r
1392 // Indicate pci bus driver has allocated\r
1393 // resource for this device\r
1394 // It might be a temporary solution here since\r
1395 // pci device could have multiple bar\r
1396 //\r
1397 Node->PciDev->Allocated = TRUE;\r
1398\r
1399 switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {\r
1400\r
1401 case PciBarTypeMem32:\r
1402 case PciBarTypePMem32:\r
1403\r
1404 PciIo->Pci.Write (\r
1405 PciIo,\r
1406 EfiPciIoWidthUint32,\r
1407 (Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
1408 1,\r
1409 &Address\r
1410 );\r
1411\r
1412 Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
9060e3ec 1413 break;\r
1414\r
1415 case PciBarTypeMem64:\r
1416 case PciBarTypePMem64:\r
1417\r
1418 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
1419\r
1420 PciIo->Pci.Write (\r
1421 PciIo,\r
1422 EfiPciIoWidthUint32,\r
1423 (Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
1424 1,\r
1425 &Address32\r
1426 );\r
1427\r
1428 Address32 = (UINT32) RShiftU64 (Address, 32);\r
1429\r
1430 PciIo->Pci.Write (\r
1431 PciIo,\r
1432 EfiPciIoWidthUint32,\r
1433 ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),\r
1434 1,\r
1435 &Address32\r
1436 );\r
1437\r
1438 Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
9060e3ec 1439 break;\r
1440\r
1441 case PciBarTypeIo16:\r
1442 case PciBarTypeIo32:\r
1443 break;\r
1444\r
1445 default:\r
1446 break;\r
1447 }\r
1448\r
1449 return EFI_SUCCESS;\r
1450}\r
1451\r
1452/**\r
1453 Program PCI-PCI bridge apperture.\r
1454\r
1455 @param Base Base address for resource.\r
1456 @param Node Point to resoure node structure.\r
1457\r
1458**/\r
1459VOID\r
1460ProgramPpbApperture (\r
1461 IN UINT64 Base,\r
1462 IN PCI_RESOURCE_NODE *Node\r
1463 )\r
1464{\r
1465 EFI_PCI_IO_PROTOCOL *PciIo;\r
1466 UINT64 Address;\r
1467 UINT32 Address32;\r
1468\r
1469 Address = 0;\r
1470 //\r
1471 // If no device resource of this PPB, return anyway\r
1472 // Apperture is set default in the initialization code\r
1473 //\r
1474 if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {\r
1475 //\r
1476 // For padding resource node, just ignore when programming\r
1477 //\r
1478 return ;\r
1479 }\r
1480\r
1481 PciIo = &(Node->PciDev->PciIo);\r
1482 Address = Base + Node->Offset;\r
1483\r
1484 //\r
1485 // Indicate the PPB resource has been allocated\r
1486 //\r
1487 Node->PciDev->Allocated = TRUE;\r
1488\r
1489 switch (Node->Bar) {\r
1490\r
1491 case PPB_BAR_0:\r
1492 case PPB_BAR_1:\r
41f39898
RN
1493 switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {\r
1494\r
1495 case PciBarTypeIo16:\r
1496 case PciBarTypeIo32:\r
1497 case PciBarTypeMem32:\r
1498 case PciBarTypePMem32:\r
1499\r
1500 PciIo->Pci.Write (\r
9060e3ec 1501 PciIo,\r
1502 EfiPciIoWidthUint32,\r
1503 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1504 1,\r
1505 &Address\r
1506 );\r
1507\r
41f39898
RN
1508 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1509 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1510 break;\r
1511\r
1512 case PciBarTypeMem64:\r
1513 case PciBarTypePMem64:\r
1514\r
1515 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
1516\r
1517 PciIo->Pci.Write (\r
1518 PciIo,\r
1519 EfiPciIoWidthUint32,\r
1520 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1521 1,\r
1522 &Address32\r
1523 );\r
1524\r
1525 Address32 = (UINT32) RShiftU64 (Address, 32);\r
9060e3ec 1526\r
41f39898
RN
1527 PciIo->Pci.Write (\r
1528 PciIo,\r
1529 EfiPciIoWidthUint32,\r
1530 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),\r
1531 1,\r
1532 &Address32\r
1533 );\r
1534\r
1535 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1536 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1537 break;\r
1538\r
1539 default:\r
1540 break;\r
1541 }\r
9060e3ec 1542 break;\r
1543\r
1544 case PPB_IO_RANGE:\r
1545\r
1546 Address32 = ((UINT32) (Address)) >> 8;\r
1547 PciIo->Pci.Write (\r
1548 PciIo,\r
1549 EfiPciIoWidthUint8,\r
1550 0x1C,\r
1551 1,\r
1552 &Address32\r
1553 );\r
1554\r
1555 Address32 >>= 8;\r
1556 PciIo->Pci.Write (\r
1557 PciIo,\r
1558 EfiPciIoWidthUint16,\r
1559 0x30,\r
1560 1,\r
1561 &Address32\r
1562 );\r
1563\r
1564 Address32 = (UINT32) (Address + Node->Length - 1);\r
1565 Address32 = ((UINT32) (Address32)) >> 8;\r
1566 PciIo->Pci.Write (\r
1567 PciIo,\r
1568 EfiPciIoWidthUint8,\r
1569 0x1D,\r
1570 1,\r
1571 &Address32\r
1572 );\r
1573\r
1574 Address32 >>= 8;\r
1575 PciIo->Pci.Write (\r
1576 PciIo,\r
1577 EfiPciIoWidthUint16,\r
1578 0x32,\r
1579 1,\r
1580 &Address32\r
1581 );\r
1582\r
1583 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1584 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1585 break;\r
1586\r
1587 case PPB_MEM32_RANGE:\r
1588\r
1589 Address32 = ((UINT32) (Address)) >> 16;\r
1590 PciIo->Pci.Write (\r
1591 PciIo,\r
1592 EfiPciIoWidthUint16,\r
1593 0x20,\r
1594 1,\r
1595 &Address32\r
1596 );\r
1597\r
1598 Address32 = (UINT32) (Address + Node->Length - 1);\r
1599 Address32 = ((UINT32) (Address32)) >> 16;\r
1600 PciIo->Pci.Write (\r
1601 PciIo,\r
1602 EfiPciIoWidthUint16,\r
1603 0x22,\r
1604 1,\r
1605 &Address32\r
1606 );\r
1607\r
1608 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1609 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1610 break;\r
1611\r
1612 case PPB_PMEM32_RANGE:\r
1613 case PPB_PMEM64_RANGE:\r
1614\r
1615 Address32 = ((UINT32) (Address)) >> 16;\r
1616 PciIo->Pci.Write (\r
1617 PciIo,\r
1618 EfiPciIoWidthUint16,\r
1619 0x24,\r
1620 1,\r
1621 &Address32\r
1622 );\r
1623\r
1624 Address32 = (UINT32) (Address + Node->Length - 1);\r
1625 Address32 = ((UINT32) (Address32)) >> 16;\r
1626 PciIo->Pci.Write (\r
1627 PciIo,\r
1628 EfiPciIoWidthUint16,\r
1629 0x26,\r
1630 1,\r
1631 &Address32\r
1632 );\r
1633\r
1634 Address32 = (UINT32) RShiftU64 (Address, 32);\r
1635 PciIo->Pci.Write (\r
1636 PciIo,\r
1637 EfiPciIoWidthUint32,\r
1638 0x28,\r
1639 1,\r
1640 &Address32\r
1641 );\r
1642\r
1643 Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);\r
1644 PciIo->Pci.Write (\r
1645 PciIo,\r
1646 EfiPciIoWidthUint32,\r
1647 0x2C,\r
1648 1,\r
1649 &Address32\r
1650 );\r
1651\r
1652 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1653 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1654 break;\r
1655\r
1656 default:\r
1657 break;\r
1658 }\r
1659}\r
1660\r
1661/**\r
1662 Program parent bridge for Option Rom.\r
1663\r
1664 @param PciDevice Pci deivce instance.\r
1665 @param OptionRomBase Base address for Optiona Rom.\r
1666 @param Enable Enable or disable PCI memory.\r
1667\r
1668**/\r
1669VOID\r
1670ProgrameUpstreamBridgeForRom (\r
1671 IN PCI_IO_DEVICE *PciDevice,\r
1672 IN UINT32 OptionRomBase,\r
1673 IN BOOLEAN Enable\r
1674 )\r
1675{\r
1676 PCI_IO_DEVICE *Parent;\r
1677 PCI_RESOURCE_NODE Node;\r
1678 //\r
1679 // For root bridge, just return.\r
1680 //\r
1681 Parent = PciDevice->Parent;\r
1682 ZeroMem (&Node, sizeof (Node));\r
1683 while (Parent != NULL) {\r
1684 if (!IS_PCI_BRIDGE (&Parent->Pci)) {\r
1685 break;\r
1686 }\r
1687\r
1688 Node.PciDev = Parent;\r
1689 Node.Length = PciDevice->RomSize;\r
1690 Node.Alignment = 0;\r
1691 Node.Bar = PPB_MEM32_RANGE;\r
1692 Node.ResType = PciBarTypeMem32;\r
1693 Node.Offset = 0;\r
1694\r
1695 //\r
1696 // Program PPB to only open a single <= 16MB apperture\r
1697 //\r
1698 if (Enable) {\r
1699 ProgramPpbApperture (OptionRomBase, &Node);\r
1700 PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
1701 } else {\r
1702 InitializePpb (Parent);\r
1703 PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
1704 }\r
1705\r
1706 Parent = Parent->Parent;\r
1707 }\r
1708}\r
1709\r
1710/**\r
1711 Test whether resource exists for a bridge.\r
1712\r
1713 @param Bridge Point to resource node for a bridge.\r
1714\r
1715 @retval TRUE There is resource on the given bridge.\r
1716 @retval FALSE There isn't resource on the given bridge.\r
1717\r
1718**/\r
1719BOOLEAN\r
1720ResourceRequestExisted (\r
1721 IN PCI_RESOURCE_NODE *Bridge\r
1722 )\r
1723{\r
1724 if (Bridge != NULL) {\r
1725 if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {\r
1726 return TRUE;\r
1727 }\r
1728 }\r
1729\r
1730 return FALSE;\r
1731}\r
1732\r
1733/**\r
1734 Initialize resource pool structure.\r
1735\r
1736 @param ResourcePool Point to resource pool structure. This pool\r
1737 is reset to all zero when returned.\r
1738 @param ResourceType Type of resource.\r
1739\r
1740**/\r
1741VOID\r
1742InitializeResourcePool (\r
1743 IN OUT PCI_RESOURCE_NODE *ResourcePool,\r
1744 IN PCI_BAR_TYPE ResourceType\r
1745 )\r
1746{\r
1747 ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));\r
1748 ResourcePool->ResType = ResourceType;\r
1749 ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;\r
1750 InitializeListHead (&ResourcePool->ChildList);\r
1751}\r
1752\r
9060e3ec 1753/**\r
1754 Destory given resource tree.\r
1755\r
1756 @param Bridge PCI resource root node of resource tree.\r
1757\r
1758**/\r
1759VOID\r
1760DestroyResourceTree (\r
1761 IN PCI_RESOURCE_NODE *Bridge\r
1762 )\r
1763{\r
1764 PCI_RESOURCE_NODE *Temp;\r
1765 LIST_ENTRY *CurrentLink;\r
1766\r
1767 while (!IsListEmpty (&Bridge->ChildList)) {\r
1768\r
1769 CurrentLink = Bridge->ChildList.ForwardLink;\r
1770\r
1771 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1772 ASSERT (Temp);\r
1773\r
1774 RemoveEntryList (CurrentLink);\r
1775\r
1776 if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {\r
1777 DestroyResourceTree (Temp);\r
1778 }\r
1779\r
1780 FreePool (Temp);\r
1781 }\r
1782}\r
1783\r
1784/**\r
1785 Insert resource padding for P2C.\r
1786\r
1787 @param PciDev Pci device instance.\r
1788 @param IoNode Resource info node for IO.\r
1789 @param Mem32Node Resource info node for 32-bit memory.\r
1790 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
1791 @param Mem64Node Resource info node for 64-bit memory.\r
1792 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
1793\r
1794**/\r
1795VOID\r
1796ResourcePaddingForCardBusBridge (\r
1797 IN PCI_IO_DEVICE *PciDev,\r
1798 IN PCI_RESOURCE_NODE *IoNode,\r
1799 IN PCI_RESOURCE_NODE *Mem32Node,\r
1800 IN PCI_RESOURCE_NODE *PMem32Node,\r
1801 IN PCI_RESOURCE_NODE *Mem64Node,\r
1802 IN PCI_RESOURCE_NODE *PMem64Node\r
1803 )\r
1804{\r
1805 PCI_RESOURCE_NODE *Node;\r
1806\r
1807 Node = NULL;\r
1808\r
1809 //\r
1810 // Memory Base/Limit Register 0\r
1811 // Bar 1 denodes memory range 0\r
1812 //\r
1813 Node = CreateResourceNode (\r
1814 PciDev,\r
1815 0x2000000,\r
1816 0x1ffffff,\r
1817 1,\r
1818 PciBarTypeMem32,\r
1819 PciResUsagePadding\r
1820 );\r
1821\r
1822 InsertResourceNode (\r
1823 Mem32Node,\r
1824 Node\r
1825 );\r
1826\r
1827 //\r
1828 // Memory Base/Limit Register 1\r
1829 // Bar 2 denodes memory range1\r
1830 //\r
1831 Node = CreateResourceNode (\r
1832 PciDev,\r
1833 0x2000000,\r
1834 0x1ffffff,\r
1835 2,\r
1836 PciBarTypePMem32,\r
1837 PciResUsagePadding\r
1838 );\r
1839\r
1840 InsertResourceNode (\r
1841 PMem32Node,\r
1842 Node\r
1843 );\r
1844\r
1845 //\r
1846 // Io Base/Limit\r
1847 // Bar 3 denodes io range 0\r
1848 //\r
1849 Node = CreateResourceNode (\r
1850 PciDev,\r
1851 0x100,\r
1852 0xff,\r
1853 3,\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 // Io Base/Limit\r
1865 // Bar 4 denodes io range 0\r
1866 //\r
1867 Node = CreateResourceNode (\r
1868 PciDev,\r
1869 0x100,\r
1870 0xff,\r
1871 4,\r
1872 PciBarTypeIo16,\r
1873 PciResUsagePadding\r
1874 );\r
1875\r
1876 InsertResourceNode (\r
1877 IoNode,\r
1878 Node\r
1879 );\r
1880}\r
1881\r
1882/**\r
1883 Program PCI Card device register for given resource node.\r
1884\r
1885 @param Base Base address of PCI Card device to be programmed.\r
1886 @param Node Given resource node.\r
1887\r
1888**/\r
1889VOID\r
1890ProgramP2C (\r
1891 IN UINT64 Base,\r
1892 IN PCI_RESOURCE_NODE *Node\r
1893 )\r
1894{\r
1895 EFI_PCI_IO_PROTOCOL *PciIo;\r
1896 UINT64 Address;\r
1897 UINT64 TempAddress;\r
1898 UINT16 BridgeControl;\r
1899\r
1900 Address = 0;\r
1901 PciIo = &(Node->PciDev->PciIo);\r
1902\r
1903 Address = Base + Node->Offset;\r
1904\r
1905 //\r
1906 // Indicate pci bus driver has allocated\r
1907 // resource for this device\r
1908 // It might be a temporary solution here since\r
1909 // pci device could have multiple bar\r
1910 //\r
1911 Node->PciDev->Allocated = TRUE;\r
1912\r
1913 switch (Node->Bar) {\r
1914\r
1915 case P2C_BAR_0:\r
1916 PciIo->Pci.Write (\r
1917 PciIo,\r
1918 EfiPciIoWidthUint32,\r
1919 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1920 1,\r
1921 &Address\r
1922 );\r
1923\r
1924 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1925 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1926 break;\r
1927\r
1928 case P2C_MEM_1:\r
1929 PciIo->Pci.Write (\r
1930 PciIo,\r
1931 EfiPciIoWidthUint32,\r
1932 PCI_CARD_MEMORY_BASE_0,\r
1933 1,\r
1934 &Address\r
1935 );\r
1936\r
1937 TempAddress = Address + Node->Length - 1;\r
1938 PciIo->Pci.Write (\r
1939 PciIo,\r
1940 EfiPciIoWidthUint32,\r
1941 PCI_CARD_MEMORY_LIMIT_0,\r
1942 1,\r
1943 &TempAddress\r
1944 );\r
1945\r
1946 if (Node->ResType == PciBarTypeMem32) {\r
1947 //\r
1948 // Set non-prefetchable bit\r
1949 //\r
1950 PciIo->Pci.Read (\r
1951 PciIo,\r
1952 EfiPciIoWidthUint16,\r
1953 PCI_CARD_BRIDGE_CONTROL,\r
1954 1,\r
1955 &BridgeControl\r
1956 );\r
1957\r
1958 BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
1959 PciIo->Pci.Write (\r
1960 PciIo,\r
1961 EfiPciIoWidthUint16,\r
1962 PCI_CARD_BRIDGE_CONTROL,\r
1963 1,\r
1964 &BridgeControl\r
1965 );\r
1966\r
1967 } else {\r
1968 //\r
1969 // Set pre-fetchable bit\r
1970 //\r
1971 PciIo->Pci.Read (\r
1972 PciIo,\r
1973 EfiPciIoWidthUint16,\r
1974 PCI_CARD_BRIDGE_CONTROL,\r
1975 1,\r
1976 &BridgeControl\r
1977 );\r
1978\r
1979 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
1980 PciIo->Pci.Write (\r
1981 PciIo,\r
1982 EfiPciIoWidthUint16,\r
1983 PCI_CARD_BRIDGE_CONTROL,\r
1984 1,\r
1985 &BridgeControl\r
1986 );\r
1987 }\r
1988\r
1989 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1990 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1991 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
1992\r
1993 break;\r
1994\r
1995 case P2C_MEM_2:\r
1996 PciIo->Pci.Write (\r
1997 PciIo,\r
1998 EfiPciIoWidthUint32,\r
1999 PCI_CARD_MEMORY_BASE_1,\r
2000 1,\r
2001 &Address\r
2002 );\r
2003\r
2004 TempAddress = Address + Node->Length - 1;\r
2005\r
2006 PciIo->Pci.Write (\r
2007 PciIo,\r
2008 EfiPciIoWidthUint32,\r
2009 PCI_CARD_MEMORY_LIMIT_1,\r
2010 1,\r
2011 &TempAddress\r
2012 );\r
2013\r
2014 if (Node->ResType == PciBarTypeMem32) {\r
2015\r
2016 //\r
2017 // Set non-prefetchable bit\r
2018 //\r
2019 PciIo->Pci.Read (\r
2020 PciIo,\r
2021 EfiPciIoWidthUint16,\r
2022 PCI_CARD_BRIDGE_CONTROL,\r
2023 1,\r
2024 &BridgeControl\r
2025 );\r
2026\r
2027 BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);\r
2028 PciIo->Pci.Write (\r
2029 PciIo,\r
2030 EfiPciIoWidthUint16,\r
2031 PCI_CARD_BRIDGE_CONTROL,\r
2032 1,\r
2033 &BridgeControl\r
2034 );\r
2035\r
2036 } else {\r
2037\r
2038 //\r
2039 // Set pre-fetchable bit\r
2040 //\r
2041 PciIo->Pci.Read (\r
2042 PciIo,\r
2043 EfiPciIoWidthUint16,\r
2044 PCI_CARD_BRIDGE_CONTROL,\r
2045 1,\r
2046 &BridgeControl\r
2047 );\r
2048\r
2049 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;\r
2050 PciIo->Pci.Write (\r
2051 PciIo,\r
2052 EfiPciIoWidthUint16,\r
2053 PCI_CARD_BRIDGE_CONTROL,\r
2054 1,\r
2055 &BridgeControl\r
2056 );\r
2057 }\r
2058\r
2059 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
2060 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
2061 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
2062 break;\r
2063\r
2064 case P2C_IO_1:\r
2065 PciIo->Pci.Write (\r
2066 PciIo,\r
2067 EfiPciIoWidthUint32,\r
2068 PCI_CARD_IO_BASE_0_LOWER,\r
2069 1,\r
2070 &Address\r
2071 );\r
2072\r
2073 TempAddress = Address + Node->Length - 1;\r
2074 PciIo->Pci.Write (\r
2075 PciIo,\r
2076 EfiPciIoWidthUint32,\r
2077 PCI_CARD_IO_LIMIT_0_LOWER,\r
2078 1,\r
2079 &TempAddress\r
2080 );\r
2081\r
2082 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
2083 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
2084 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
2085\r
2086 break;\r
2087\r
2088 case P2C_IO_2:\r
2089 PciIo->Pci.Write (\r
2090 PciIo,\r
2091 EfiPciIoWidthUint32,\r
2092 PCI_CARD_IO_BASE_1_LOWER,\r
2093 1,\r
2094 &Address\r
2095 );\r
2096\r
2097 TempAddress = Address + Node->Length - 1;\r
2098 PciIo->Pci.Write (\r
2099 PciIo,\r
2100 EfiPciIoWidthUint32,\r
2101 PCI_CARD_IO_LIMIT_1_LOWER,\r
2102 1,\r
2103 &TempAddress\r
2104 );\r
2105\r
2106 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
2107 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
2108 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
2109 break;\r
2110\r
2111 default:\r
2112 break;\r
2113 }\r
2114}\r
2115\r
2116/**\r
2117 Create padding resource node.\r
2118\r
2119 @param PciDev Pci device instance.\r
2120 @param IoNode Resource info node for IO.\r
2121 @param Mem32Node Resource info node for 32-bit memory.\r
2122 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
2123 @param Mem64Node Resource info node for 64-bit memory.\r
2124 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
2125\r
2126**/\r
2127VOID\r
2128ApplyResourcePadding (\r
2129 IN PCI_IO_DEVICE *PciDev,\r
2130 IN PCI_RESOURCE_NODE *IoNode,\r
2131 IN PCI_RESOURCE_NODE *Mem32Node,\r
2132 IN PCI_RESOURCE_NODE *PMem32Node,\r
2133 IN PCI_RESOURCE_NODE *Mem64Node,\r
2134 IN PCI_RESOURCE_NODE *PMem64Node\r
2135 )\r
2136{\r
2137 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
2138 PCI_RESOURCE_NODE *Node;\r
2139 UINT8 DummyBarIndex;\r
2140\r
2141 DummyBarIndex = 0;\r
2142 Ptr = PciDev->ResourcePaddingDescriptors;\r
2143\r
2144 while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
2145\r
2146 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
2147 if (Ptr->AddrLen != 0) {\r
2148\r
2149 Node = CreateResourceNode (\r
2150 PciDev,\r
2151 Ptr->AddrLen,\r
2152 Ptr->AddrRangeMax,\r
2153 DummyBarIndex,\r
2154 PciBarTypeIo16,\r
2155 PciResUsagePadding\r
2156 );\r
2157 InsertResourceNode (\r
2158 IoNode,\r
2159 Node\r
2160 );\r
2161 }\r
2162\r
2163 Ptr++;\r
2164 continue;\r
2165 }\r
2166\r
2167 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
2168\r
2169 if (Ptr->AddrSpaceGranularity == 32) {\r
2170\r
2171 //\r
2172 // prefechable\r
2173 //\r
2174 if (Ptr->SpecificFlag == 0x6) {\r
2175 if (Ptr->AddrLen != 0) {\r
2176 Node = CreateResourceNode (\r
2177 PciDev,\r
2178 Ptr->AddrLen,\r
2179 Ptr->AddrRangeMax,\r
2180 DummyBarIndex,\r
2181 PciBarTypePMem32,\r
2182 PciResUsagePadding\r
2183 );\r
2184 InsertResourceNode (\r
2185 PMem32Node,\r
2186 Node\r
2187 );\r
2188 }\r
2189\r
2190 Ptr++;\r
2191 continue;\r
2192 }\r
2193\r
2194 //\r
2195 // Non-prefechable\r
2196 //\r
2197 if (Ptr->SpecificFlag == 0) {\r
2198 if (Ptr->AddrLen != 0) {\r
2199 Node = CreateResourceNode (\r
2200 PciDev,\r
2201 Ptr->AddrLen,\r
2202 Ptr->AddrRangeMax,\r
2203 DummyBarIndex,\r
2204 PciBarTypeMem32,\r
2205 PciResUsagePadding\r
2206 );\r
2207 InsertResourceNode (\r
2208 Mem32Node,\r
2209 Node\r
2210 );\r
2211 }\r
2212\r
2213 Ptr++;\r
2214 continue;\r
2215 }\r
2216 }\r
2217\r
2218 if (Ptr->AddrSpaceGranularity == 64) {\r
2219\r
2220 //\r
2221 // prefechable\r
2222 //\r
2223 if (Ptr->SpecificFlag == 0x6) {\r
2224 if (Ptr->AddrLen != 0) {\r
2225 Node = CreateResourceNode (\r
2226 PciDev,\r
2227 Ptr->AddrLen,\r
2228 Ptr->AddrRangeMax,\r
2229 DummyBarIndex,\r
2230 PciBarTypePMem64,\r
2231 PciResUsagePadding\r
2232 );\r
2233 InsertResourceNode (\r
2234 PMem64Node,\r
2235 Node\r
2236 );\r
2237 }\r
2238\r
2239 Ptr++;\r
2240 continue;\r
2241 }\r
2242\r
2243 //\r
2244 // Non-prefechable\r
2245 //\r
2246 if (Ptr->SpecificFlag == 0) {\r
2247 if (Ptr->AddrLen != 0) {\r
2248 Node = CreateResourceNode (\r
2249 PciDev,\r
2250 Ptr->AddrLen,\r
2251 Ptr->AddrRangeMax,\r
2252 DummyBarIndex,\r
2253 PciBarTypeMem64,\r
2254 PciResUsagePadding\r
2255 );\r
2256 InsertResourceNode (\r
2257 Mem64Node,\r
2258 Node\r
2259 );\r
2260 }\r
2261\r
2262 Ptr++;\r
2263 continue;\r
2264 }\r
2265 }\r
2266 }\r
2267\r
2268 Ptr++;\r
2269 }\r
2270}\r
2271\r
2272/**\r
2273 Get padding resource for PCI-PCI bridge.\r
2274\r
2275 @param PciIoDevice PCI-PCI bridge device instance.\r
2276\r
2277 @note Feature flag PcdPciBusHotplugDeviceSupport determines\r
2278 whether need to pad resource for them.\r
2279**/\r
2280VOID\r
2281GetResourcePaddingPpb (\r
2282 IN PCI_IO_DEVICE *PciIoDevice\r
2283 )\r
2284{\r
2285 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
2286 if (PciIoDevice->ResourcePaddingDescriptors == NULL) {\r
2287 GetResourcePaddingForHpb (PciIoDevice);\r
2288 }\r
2289 }\r
2290}\r
2291\r