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