]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
Retired PciIncompatibleDeviceSupportLib from IntelFrameworkModulePkg.
[mirror_edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciResourceSupport.c
CommitLineData
eeefcb9d 1/** @file\r
8e8227d1 2 PCI resouces support functions implemntation for PCI Bus module.\r
ead42efc 3\r
c72216a6 4Copyright (c) 2006 - 2009, Intel Corporation\r
ead42efc 5All rights reserved. This program and the accompanying materials\r
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
3db51098 13**/\r
ead42efc 14\r
03417d8d 15#include "PciBus.h"\r
ead42efc 16\r
57076f45 17/**\r
8e8227d1 18 The function is used to skip VGA range.\r
19\r
20 @param Start Returned start address including VGA range.\r
21 @param Length The length of VGA range.\r
22\r
57076f45 23**/\r
8e8227d1 24VOID\r
ead42efc 25SkipVGAAperture (\r
26 OUT UINT64 *Start,\r
27 IN UINT64 Length\r
28 )\r
ead42efc 29{\r
30 UINT64 Original;\r
31 UINT64 Mask;\r
32 UINT64 StartOffset;\r
33 UINT64 LimitOffset;\r
34\r
8e8227d1 35 ASSERT (Start != NULL);\r
ead42efc 36 //\r
37 // For legacy VGA, bit 10 to bit 15 is not decoded\r
38 //\r
39 Mask = 0x3FF;\r
40\r
41 Original = *Start;\r
42 StartOffset = Original & Mask;\r
43 LimitOffset = ((*Start) + Length - 1) & Mask;\r
44 if (LimitOffset >= VGABASE1) {\r
45 *Start = *Start - StartOffset + VGALIMIT2 + 1;\r
46 }\r
ead42efc 47}\r
48\r
57076f45 49/**\r
eeefcb9d 50 This function is used to skip ISA aliasing aperture.\r
8e8227d1 51\r
52 @param Start Returned start address including ISA aliasing aperture.\r
53 @param Length The length of ISA aliasing aperture.\r
54\r
57076f45 55**/\r
8e8227d1 56VOID\r
ead42efc 57SkipIsaAliasAperture (\r
58 OUT UINT64 *Start,\r
59 IN UINT64 Length\r
60 )\r
ead42efc 61{\r
62\r
63 UINT64 Original;\r
64 UINT64 Mask;\r
65 UINT64 StartOffset;\r
66 UINT64 LimitOffset;\r
67\r
8e8227d1 68 ASSERT (Start != NULL);\r
69\r
ead42efc 70 //\r
71 // For legacy ISA, bit 10 to bit 15 is not decoded\r
72 //\r
73 Mask = 0x3FF;\r
74\r
75 Original = *Start;\r
76 StartOffset = Original & Mask;\r
77 LimitOffset = ((*Start) + Length - 1) & Mask;\r
78\r
79 if (LimitOffset >= ISABASE) {\r
80 *Start = *Start - StartOffset + ISALIMIT + 1;\r
81 }\r
ead42efc 82}\r
83\r
bcd70414 84/**\r
ead42efc 85 This function inserts a resource node into the resource list.\r
86 The resource list is sorted in descend order.\r
87\r
eeefcb9d 88 @param Bridge PCI resource node for bridge.\r
89 @param ResNode Resource node want to be inserted.\r
8e8227d1 90\r
bcd70414 91**/\r
8e8227d1 92VOID\r
57076f45 93InsertResourceNode (\r
9eb130ff 94 IN OUT PCI_RESOURCE_NODE *Bridge,\r
95 IN PCI_RESOURCE_NODE *ResNode\r
57076f45 96 )\r
ead42efc 97{\r
98 LIST_ENTRY *CurrentLink;\r
99 PCI_RESOURCE_NODE *Temp;\r
100 UINT64 ResNodeAlignRest;\r
101 UINT64 TempAlignRest;\r
102\r
c72216a6 103 ASSERT (Bridge != NULL);\r
104 ASSERT (ResNode != NULL);\r
105\r
ead42efc 106 InsertHeadList (&Bridge->ChildList, &ResNode->Link);\r
107\r
108 CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;\r
109 while (CurrentLink != &Bridge->ChildList) {\r
110 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
111\r
112 if (ResNode->Alignment > Temp->Alignment) {\r
113 break;\r
114 } else if (ResNode->Alignment == Temp->Alignment) {\r
115 ResNodeAlignRest = ResNode->Length & ResNode->Alignment;\r
116 TempAlignRest = Temp->Length & Temp->Alignment;\r
117 if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {\r
118 break;\r
119 }\r
120 }\r
121\r
122 SwapListEntries (&ResNode->Link, CurrentLink);\r
123\r
124 CurrentLink = ResNode->Link.ForwardLink;\r
125 }\r
ead42efc 126}\r
127\r
bcd70414 128/**\r
8e8227d1 129 This routine is used to merge two different resource trees in need of\r
130 resoure degradation.\r
ead42efc 131\r
8e8227d1 132 For example, if an upstream PPB doesn't support,\r
ead42efc 133 prefetchable memory decoding, the PCI bus driver will choose to call this function\r
134 to merge prefectchable memory resource list into normal memory list.\r
135\r
136 If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource\r
137 type.\r
8e8227d1 138 If Dst is NULL or Res is NULL, ASSERT ().\r
ead42efc 139\r
eeefcb9d 140 @param Dst Point to destination resource tree.\r
141 @param Res Point to source resource tree.\r
8e8227d1 142 @param TypeMerge If the TypeMerge is TRUE, Res resource type is changed to the type of\r
57076f45 143 destination resource type.\r
8e8227d1 144\r
bcd70414 145**/\r
8e8227d1 146VOID\r
57076f45 147MergeResourceTree (\r
8e8227d1 148 IN PCI_RESOURCE_NODE *Dst,\r
149 IN PCI_RESOURCE_NODE *Res,\r
150 IN BOOLEAN TypeMerge\r
57076f45 151 )\r
ead42efc 152{\r
153\r
154 LIST_ENTRY *CurrentLink;\r
155 PCI_RESOURCE_NODE *Temp;\r
156\r
c72216a6 157 ASSERT (Dst != NULL);\r
158 ASSERT (Res != NULL);\r
159\r
ead42efc 160 while (!IsListEmpty (&Res->ChildList)) {\r
161 CurrentLink = Res->ChildList.ForwardLink;\r
162\r
163 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
164\r
165 if (TypeMerge) {\r
166 Temp->ResType = Dst->ResType;\r
167 }\r
168\r
169 RemoveEntryList (CurrentLink);\r
170 InsertResourceNode (Dst, Temp);\r
ead42efc 171 }\r
ead42efc 172}\r
173\r
bcd70414 174/**\r
ead42efc 175 This function is used to calculate the IO16 aperture\r
176 for a bridge.\r
177\r
8e8227d1 178 @param Bridge PCI resource node for bridge.\r
179\r
bcd70414 180**/\r
8e8227d1 181VOID\r
57076f45 182CalculateApertureIo16 (\r
8e8227d1 183 IN PCI_RESOURCE_NODE *Bridge\r
57076f45 184 )\r
ead42efc 185{\r
94b9d5c6 186 EFI_STATUS Status;\r
187 UINT64 Aperture;\r
188 LIST_ENTRY *CurrentLink;\r
189 PCI_RESOURCE_NODE *Node;\r
190 UINT64 Offset;\r
191 BOOLEAN IsaEnable;\r
192 BOOLEAN VGAEnable;\r
193 EFI_PCI_PLATFORM_POLICY PciPolicy;\r
ead42efc 194\r
195 //\r
196 // Always assume there is ISA device and VGA device on the platform\r
197 // will be customized later\r
198 //\r
199 IsaEnable = FALSE;\r
200 VGAEnable = FALSE;\r
201\r
94b9d5c6 202 //\r
203 // Check PciPlatform policy\r
204 //\r
205 if (gPciPlatformProtocol != NULL) {\r
206 Status = gPciPlatformProtocol->GetPlatformPolicy (\r
207 gPciPlatformProtocol,\r
208 &PciPolicy\r
209 );\r
210 if (!EFI_ERROR (Status)) {\r
8e8227d1 211 if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {\r
94b9d5c6 212 IsaEnable = TRUE;\r
213 }\r
8e8227d1 214 if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {\r
94b9d5c6 215 VGAEnable = TRUE;\r
216 }\r
217 }\r
ead42efc 218 }\r
219\r
220 Aperture = 0;\r
221\r
97404058 222 if (Bridge == NULL) {\r
8e8227d1 223 return ;\r
ead42efc 224 }\r
225\r
226 CurrentLink = Bridge->ChildList.ForwardLink;\r
227\r
228 //\r
229 // Assume the bridge is aligned\r
230 //\r
231 while (CurrentLink != &Bridge->ChildList) {\r
232\r
233 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
234\r
235 //\r
236 // Consider the aperture alignment\r
237 //\r
5326528b 238 Offset = Aperture & (Node->Alignment);\r
ead42efc 239\r
5326528b 240 if (Offset != 0) {\r
ead42efc 241\r
5326528b 242 Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
ead42efc 243\r
244 }\r
245\r
246 //\r
247 // IsaEnable and VGAEnable can not be implemented now.\r
248 // If both of them are enabled, then the IO resource would\r
249 // become too limited to meet the requirement of most of devices.\r
250 //\r
ead42efc 251 if (IsaEnable || VGAEnable) {\r
252 if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
253 //\r
254 // Check if there is need to support ISA/VGA decoding\r
255 // If so, we need to avoid isa/vga aliasing range\r
256 //\r
257 if (IsaEnable) {\r
258 SkipIsaAliasAperture (\r
259 &Aperture,\r
8e8227d1 260 Node->Length\r
ead42efc 261 );\r
5326528b 262 Offset = Aperture & (Node->Alignment);\r
263 if (Offset != 0) {\r
264 Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
ead42efc 265 }\r
266 } else if (VGAEnable) {\r
267 SkipVGAAperture (\r
268 &Aperture,\r
269 Node->Length\r
270 );\r
5326528b 271 Offset = Aperture & (Node->Alignment);\r
272 if (Offset != 0) {\r
273 Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
ead42efc 274 }\r
275 }\r
276 }\r
277 }\r
278\r
279 Node->Offset = Aperture;\r
280\r
281 //\r
282 // Increment aperture by the length of node\r
283 //\r
284 Aperture += Node->Length;\r
285\r
286 CurrentLink = CurrentLink->ForwardLink;\r
287 }\r
288\r
289 //\r
290 // At last, adjust the aperture with the bridge's\r
291 // alignment\r
292 //\r
5326528b 293 Offset = Aperture & (Bridge->Alignment);\r
ead42efc 294\r
5326528b 295 if (Offset != 0) {\r
296 Aperture = Aperture + (Bridge->Alignment + 1) - Offset;\r
ead42efc 297 }\r
298\r
299 Bridge->Length = Aperture;\r
300 //\r
301 // At last, adjust the bridge's alignment to the first child's alignment\r
302 // if the bridge has at least one child\r
303 //\r
304 CurrentLink = Bridge->ChildList.ForwardLink;\r
305 if (CurrentLink != &Bridge->ChildList) {\r
306 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
307 if (Node->Alignment > Bridge->Alignment) {\r
308 Bridge->Alignment = Node->Alignment;\r
309 }\r
310 }\r
ead42efc 311}\r
312\r
bcd70414 313/**\r
ead42efc 314 This function is used to calculate the resource aperture\r
eeefcb9d 315 for a given bridge device.\r
ead42efc 316\r
8e8227d1 317 @param Bridge PCI resouce node for given bridge device.\r
318\r
bcd70414 319**/\r
8e8227d1 320VOID\r
57076f45 321CalculateResourceAperture (\r
8e8227d1 322 IN PCI_RESOURCE_NODE *Bridge\r
57076f45 323 )\r
ead42efc 324{\r
325 UINT64 Aperture;\r
326 LIST_ENTRY *CurrentLink;\r
327 PCI_RESOURCE_NODE *Node;\r
328\r
5326528b 329 UINT64 Offset;\r
ead42efc 330\r
331 Aperture = 0;\r
332\r
97404058 333 if (Bridge == NULL) {\r
8e8227d1 334 return ;\r
ead42efc 335 }\r
336\r
337 if (Bridge->ResType == PciBarTypeIo16) {\r
8e8227d1 338\r
339 CalculateApertureIo16 (Bridge);\r
340 return ;\r
ead42efc 341 }\r
342\r
343 CurrentLink = Bridge->ChildList.ForwardLink;\r
344\r
345 //\r
346 // Assume the bridge is aligned\r
347 //\r
348 while (CurrentLink != &Bridge->ChildList) {\r
349\r
350 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
351\r
352 //\r
353 // Apply padding resource if available\r
354 //\r
5326528b 355 Offset = Aperture & (Node->Alignment);\r
ead42efc 356\r
5326528b 357 if (Offset != 0) {\r
ead42efc 358\r
5326528b 359 Aperture = Aperture + (Node->Alignment + 1) - Offset;\r
ead42efc 360\r
361 }\r
362\r
363 //\r
364 // Recode current aperture as a offset\r
365 // this offset will be used in future real allocation\r
366 //\r
367 Node->Offset = Aperture;\r
368\r
369 //\r
370 // Increment aperture by the length of node\r
371 //\r
372 Aperture += Node->Length;\r
373\r
374 //\r
375 // Consider the aperture alignment\r
376 //\r
ead42efc 377 CurrentLink = CurrentLink->ForwardLink;\r
378 }\r
379\r
380 //\r
381 // At last, adjust the aperture with the bridge's\r
382 // alignment\r
383 //\r
5326528b 384 Offset = Aperture & (Bridge->Alignment);\r
385 if (Offset != 0) {\r
386 Aperture = Aperture + (Bridge->Alignment + 1) - Offset;\r
ead42efc 387 }\r
388\r
389 //\r
390 // If the bridge has already padded the resource and the\r
391 // amount of padded resource is larger, then keep the\r
392 // padded resource\r
393 //\r
394 if (Bridge->Length < Aperture) {\r
395 Bridge->Length = Aperture;\r
396 }\r
8e8227d1 397\r
ead42efc 398 //\r
399 // At last, adjust the bridge's alignment to the first child's alignment\r
400 // if the bridge has at least one child\r
401 //\r
402 CurrentLink = Bridge->ChildList.ForwardLink;\r
403 if (CurrentLink != &Bridge->ChildList) {\r
404 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
405 if (Node->Alignment > Bridge->Alignment) {\r
406 Bridge->Alignment = Node->Alignment;\r
407 }\r
408 }\r
ead42efc 409}\r
410\r
57076f45 411/**\r
eeefcb9d 412 Get IO/Memory resource infor for given PCI device.\r
8e8227d1 413\r
eeefcb9d 414 @param PciDev Pci device instance.\r
415 @param IoNode Resource info node for IO .\r
416 @param Mem32Node Resource info node for 32-bit memory.\r
8e8227d1 417 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
eeefcb9d 418 @param Mem64Node Resource info node for 64-bit memory.\r
8e8227d1 419 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
420\r
57076f45 421**/\r
8e8227d1 422VOID\r
ead42efc 423GetResourceFromDevice (\r
9eb130ff 424 IN PCI_IO_DEVICE *PciDev,\r
425 IN OUT PCI_RESOURCE_NODE *IoNode,\r
426 IN OUT PCI_RESOURCE_NODE *Mem32Node,\r
427 IN OUT PCI_RESOURCE_NODE *PMem32Node,\r
428 IN OUT PCI_RESOURCE_NODE *Mem64Node,\r
429 IN OUT PCI_RESOURCE_NODE *PMem64Node\r
ead42efc 430 )\r
ead42efc 431{\r
432\r
433 UINT8 Index;\r
434 PCI_RESOURCE_NODE *Node;\r
435 BOOLEAN ResourceRequested;\r
436\r
437 Node = NULL;\r
438 ResourceRequested = FALSE;\r
439\r
440 for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
441\r
442 switch ((PciDev->PciBar)[Index].BarType) {\r
443\r
444 case PciBarTypeMem32:\r
445\r
446 Node = CreateResourceNode (\r
447 PciDev,\r
448 (PciDev->PciBar)[Index].Length,\r
449 (PciDev->PciBar)[Index].Alignment,\r
450 Index,\r
451 PciBarTypeMem32,\r
452 PciResUsageTypical\r
453 );\r
454\r
455 InsertResourceNode (\r
456 Mem32Node,\r
457 Node\r
458 );\r
459\r
460 ResourceRequested = TRUE;\r
461 break;\r
462\r
463 case PciBarTypeMem64:\r
464\r
465 Node = CreateResourceNode (\r
466 PciDev,\r
467 (PciDev->PciBar)[Index].Length,\r
468 (PciDev->PciBar)[Index].Alignment,\r
469 Index,\r
470 PciBarTypeMem64,\r
471 PciResUsageTypical\r
472 );\r
473\r
474 InsertResourceNode (\r
475 Mem64Node,\r
476 Node\r
477 );\r
478\r
479 ResourceRequested = TRUE;\r
480 break;\r
481\r
482 case PciBarTypePMem64:\r
483\r
484 Node = CreateResourceNode (\r
485 PciDev,\r
486 (PciDev->PciBar)[Index].Length,\r
487 (PciDev->PciBar)[Index].Alignment,\r
488 Index,\r
489 PciBarTypePMem64,\r
490 PciResUsageTypical\r
491 );\r
492\r
493 InsertResourceNode (\r
494 PMem64Node,\r
495 Node\r
496 );\r
497\r
498 ResourceRequested = TRUE;\r
499 break;\r
500\r
501 case PciBarTypePMem32:\r
502\r
503 Node = CreateResourceNode (\r
504 PciDev,\r
505 (PciDev->PciBar)[Index].Length,\r
506 (PciDev->PciBar)[Index].Alignment,\r
507 Index,\r
508 PciBarTypePMem32,\r
509 PciResUsageTypical\r
510 );\r
511\r
512 InsertResourceNode (\r
513 PMem32Node,\r
514 Node\r
515 );\r
516 ResourceRequested = TRUE;\r
517 break;\r
518\r
519 case PciBarTypeIo16:\r
520 case PciBarTypeIo32:\r
521\r
522 Node = CreateResourceNode (\r
523 PciDev,\r
524 (PciDev->PciBar)[Index].Length,\r
525 (PciDev->PciBar)[Index].Alignment,\r
526 Index,\r
527 PciBarTypeIo16,\r
528 PciResUsageTypical\r
529 );\r
530\r
531 InsertResourceNode (\r
532 IoNode,\r
533 Node\r
534 );\r
535 ResourceRequested = TRUE;\r
536 break;\r
537\r
538 case PciBarTypeUnknown:\r
539 break;\r
540\r
541 default:\r
542 break;\r
543 }\r
544 }\r
545\r
546 //\r
547 // If there is no resource requested from this device,\r
548 // then we indicate this device has been allocated naturally.\r
549 //\r
550 if (!ResourceRequested) {\r
551 PciDev->Allocated = TRUE;\r
552 }\r
ead42efc 553}\r
554\r
57076f45 555/**\r
eeefcb9d 556 This function is used to create a resource node.\r
557\r
558 @param PciDev Pci device instance.\r
559 @param Length Length of Io/Memory resource.\r
560 @param Alignment Alignment of resource.\r
561 @param Bar Bar index.\r
562 @param ResType Type of resource: IO/Memory.\r
563 @param ResUsage Resource usage.\r
8e8227d1 564\r
565 @return PCI resource node created for given PCI device.\r
566 NULL means PCI resource node is not created.\r
567\r
57076f45 568**/\r
ead42efc 569PCI_RESOURCE_NODE *\r
570CreateResourceNode (\r
571 IN PCI_IO_DEVICE *PciDev,\r
572 IN UINT64 Length,\r
573 IN UINT64 Alignment,\r
574 IN UINT8 Bar,\r
575 IN PCI_BAR_TYPE ResType,\r
576 IN PCI_RESOURCE_USAGE ResUsage\r
577 )\r
ead42efc 578{\r
579 PCI_RESOURCE_NODE *Node;\r
580\r
581 Node = NULL;\r
582\r
9eb130ff 583 Node = AllocateZeroPool (sizeof (PCI_RESOURCE_NODE));\r
7f0f1b8f 584 ASSERT (Node != NULL);\r
ead42efc 585 if (Node == NULL) {\r
586 return NULL;\r
587 }\r
588\r
ead42efc 589 Node->Signature = PCI_RESOURCE_SIGNATURE;\r
590 Node->PciDev = PciDev;\r
591 Node->Length = Length;\r
592 Node->Alignment = Alignment;\r
593 Node->Bar = Bar;\r
594 Node->ResType = ResType;\r
595 Node->Reserved = FALSE;\r
596 Node->ResourceUsage = ResUsage;\r
597 InitializeListHead (&Node->ChildList);\r
8e8227d1 598\r
ead42efc 599 return Node;\r
600}\r
601\r
57076f45 602/**\r
8e8227d1 603 This function is used to extract resource request from\r
57076f45 604 device node list.\r
605\r
eeefcb9d 606 @param Bridge Pci device instance.\r
607 @param IoNode Resource info node for IO.\r
608 @param Mem32Node Resource info node for 32-bit memory.\r
8e8227d1 609 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
eeefcb9d 610 @param Mem64Node Resource info node for 64-bit memory.\r
8e8227d1 611 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
57076f45 612\r
57076f45 613**/\r
8e8227d1 614VOID\r
ead42efc 615CreateResourceMap (\r
9eb130ff 616 IN PCI_IO_DEVICE *Bridge,\r
617 IN OUT PCI_RESOURCE_NODE *IoNode,\r
618 IN OUT PCI_RESOURCE_NODE *Mem32Node,\r
619 IN OUT PCI_RESOURCE_NODE *PMem32Node,\r
620 IN OUT PCI_RESOURCE_NODE *Mem64Node,\r
621 IN OUT PCI_RESOURCE_NODE *PMem64Node\r
ead42efc 622 )\r
ead42efc 623{\r
624 PCI_IO_DEVICE *Temp;\r
625 PCI_RESOURCE_NODE *IoBridge;\r
626 PCI_RESOURCE_NODE *Mem32Bridge;\r
627 PCI_RESOURCE_NODE *PMem32Bridge;\r
628 PCI_RESOURCE_NODE *Mem64Bridge;\r
629 PCI_RESOURCE_NODE *PMem64Bridge;\r
630 LIST_ENTRY *CurrentLink;\r
631\r
632 CurrentLink = Bridge->ChildList.ForwardLink;\r
633\r
97404058 634 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
ead42efc 635\r
636 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
637\r
638 //\r
639 // Create resource nodes for this device by scanning the\r
640 // Bar array in the device private data\r
641 // If the upstream bridge doesn't support this device,\r
642 // no any resource node will be created for this device\r
643 //\r
644 GetResourceFromDevice (\r
645 Temp,\r
646 IoNode,\r
647 Mem32Node,\r
648 PMem32Node,\r
649 Mem64Node,\r
650 PMem64Node\r
651 );\r
652\r
653 if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
654\r
655 //\r
656 // If the device has children, create a bridge resource node for this PPB\r
657 // Note: For PPB, memory aperture is aligned with 1MB and IO aperture\r
658 // is aligned with 4KB\r
659 // This device is typically a bridge device like PPB and P2C\r
8e8227d1 660 // Note: 0x1000 aligned\r
ead42efc 661 //\r
662 IoBridge = CreateResourceNode (\r
8e8227d1 663 Temp,\r
664 0,\r
665 0xFFF,\r
666 PPB_IO_RANGE,\r
667 PciBarTypeIo16,\r
668 PciResUsageTypical\r
669 );\r
670\r
ead42efc 671 Mem32Bridge = CreateResourceNode (\r
672 Temp,\r
673 0,\r
674 0xFFFFF,\r
675 PPB_MEM32_RANGE,\r
676 PciBarTypeMem32,\r
677 PciResUsageTypical\r
678 );\r
679\r
680 PMem32Bridge = CreateResourceNode (\r
8e8227d1 681 Temp,\r
682 0,\r
683 0xFFFFF,\r
684 PPB_PMEM32_RANGE,\r
685 PciBarTypePMem32,\r
686 PciResUsageTypical\r
687 );\r
ead42efc 688\r
689 Mem64Bridge = CreateResourceNode (\r
690 Temp,\r
691 0,\r
692 0xFFFFF,\r
693 PPB_MEM64_RANGE,\r
694 PciBarTypeMem64,\r
695 PciResUsageTypical\r
696 );\r
697\r
698 PMem64Bridge = CreateResourceNode (\r
8e8227d1 699 Temp,\r
700 0,\r
701 0xFFFFF,\r
702 PPB_PMEM64_RANGE,\r
703 PciBarTypePMem64,\r
704 PciResUsageTypical\r
705 );\r
ead42efc 706\r
707 //\r
708 // Recursively create resouce map on this bridge\r
709 //\r
710 CreateResourceMap (\r
711 Temp,\r
712 IoBridge,\r
713 Mem32Bridge,\r
714 PMem32Bridge,\r
715 Mem64Bridge,\r
716 PMem64Bridge\r
717 );\r
718\r
719 if (ResourceRequestExisted (IoBridge)) {\r
720 InsertResourceNode (\r
721 IoNode,\r
722 IoBridge\r
723 );\r
724 } else {\r
9eb130ff 725 FreePool (IoBridge);\r
ead42efc 726 IoBridge = NULL;\r
727 }\r
728\r
729 //\r
730 // If there is node under this resource bridge,\r
731 // then calculate bridge's aperture of this type\r
732 // and insert it into the respective resource tree.\r
733 // If no, delete this resource bridge\r
734 //\r
735 if (ResourceRequestExisted (Mem32Bridge)) {\r
736 InsertResourceNode (\r
737 Mem32Node,\r
738 Mem32Bridge\r
739 );\r
740 } else {\r
9eb130ff 741 FreePool (Mem32Bridge);\r
ead42efc 742 Mem32Bridge = NULL;\r
743 }\r
744\r
745 //\r
746 // If there is node under this resource bridge,\r
747 // then calculate bridge's aperture of this type\r
748 // and insert it into the respective resource tree.\r
749 // If no, delete this resource bridge\r
750 //\r
751 if (ResourceRequestExisted (PMem32Bridge)) {\r
752 InsertResourceNode (\r
753 PMem32Node,\r
754 PMem32Bridge\r
755 );\r
756 } else {\r
9eb130ff 757 FreePool (PMem32Bridge);\r
ead42efc 758 PMem32Bridge = NULL;\r
759 }\r
760\r
761 //\r
762 // If there is node under this resource bridge,\r
763 // then calculate bridge's aperture of this type\r
764 // and insert it into the respective resource tree.\r
765 // If no, delete this resource bridge\r
766 //\r
767 if (ResourceRequestExisted (Mem64Bridge)) {\r
768 InsertResourceNode (\r
769 Mem64Node,\r
770 Mem64Bridge\r
771 );\r
772 } else {\r
9eb130ff 773 FreePool (Mem64Bridge);\r
ead42efc 774 Mem64Bridge = NULL;\r
775 }\r
776\r
777 //\r
778 // If there is node under this resource bridge,\r
779 // then calculate bridge's aperture of this type\r
780 // and insert it into the respective resource tree.\r
781 // If no, delete this resource bridge\r
782 //\r
783 if (ResourceRequestExisted (PMem64Bridge)) {\r
784 InsertResourceNode (\r
785 PMem64Node,\r
786 PMem64Bridge\r
787 );\r
788 } else {\r
9eb130ff 789 FreePool (PMem64Bridge);\r
ead42efc 790 PMem64Bridge = NULL;\r
791 }\r
792\r
793 }\r
794\r
795 //\r
796 // If it is P2C, apply hard coded resource padding\r
797 //\r
ead42efc 798 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
799 ResourcePaddingForCardBusBridge (\r
800 Temp,\r
801 IoNode,\r
802 Mem32Node,\r
803 PMem32Node,\r
804 Mem64Node,\r
805 PMem64Node\r
806 );\r
807 }\r
808\r
809 CurrentLink = CurrentLink->ForwardLink;\r
810 }\r
9eb130ff 811\r
ead42efc 812 //\r
813 // To do some platform specific resource padding ...\r
814 //\r
815 ResourcePaddingPolicy (\r
816 Bridge,\r
817 IoNode,\r
818 Mem32Node,\r
819 PMem32Node,\r
820 Mem64Node,\r
821 PMem64Node\r
822 );\r
823\r
824 //\r
825 // Degrade resource if necessary\r
826 //\r
827 DegradeResource (\r
828 Bridge,\r
829 Mem32Node,\r
830 PMem32Node,\r
831 Mem64Node,\r
832 PMem64Node\r
833 );\r
834\r
835 //\r
836 // Calculate resource aperture for this bridge device\r
837 //\r
838 CalculateResourceAperture (Mem32Node);\r
839 CalculateResourceAperture (PMem32Node);\r
840 CalculateResourceAperture (Mem64Node);\r
841 CalculateResourceAperture (PMem64Node);\r
842 CalculateResourceAperture (IoNode);\r
ead42efc 843}\r
844\r
57076f45 845/**\r
eeefcb9d 846 This function is used to do the resource padding for a specific platform.\r
57076f45 847\r
eeefcb9d 848 @param PciDev Pci device instance.\r
849 @param IoNode Resource info node for IO.\r
850 @param Mem32Node Resource info node for 32-bit memory.\r
8e8227d1 851 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
eeefcb9d 852 @param Mem64Node Resource info node for 64-bit memory.\r
8e8227d1 853 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
57076f45 854\r
57076f45 855**/\r
8e8227d1 856VOID\r
ead42efc 857ResourcePaddingPolicy (\r
8e8227d1 858 IN PCI_IO_DEVICE *PciDev,\r
859 IN PCI_RESOURCE_NODE *IoNode,\r
860 IN PCI_RESOURCE_NODE *Mem32Node,\r
861 IN PCI_RESOURCE_NODE *PMem32Node,\r
862 IN PCI_RESOURCE_NODE *Mem64Node,\r
863 IN PCI_RESOURCE_NODE *PMem64Node\r
ead42efc 864 )\r
ead42efc 865{\r
866 //\r
867 // Create padding resource node\r
868 //\r
869 if (PciDev->ResourcePaddingDescriptors != NULL) {\r
870 ApplyResourcePadding (\r
871 PciDev,\r
872 IoNode,\r
873 Mem32Node,\r
874 PMem32Node,\r
875 Mem64Node,\r
876 PMem64Node\r
877 );\r
878 }\r
ead42efc 879}\r
880\r
bcd70414 881/**\r
8e8227d1 882 This function is used to degrade resource if the upstream bridge\r
883 doesn't support certain resource. Degradation path is\r
ead42efc 884 PMEM64 -> MEM64 -> MEM32\r
885 PMEM64 -> PMEM32 -> MEM32\r
eeefcb9d 886 IO32 -> IO16.\r
ead42efc 887\r
eeefcb9d 888 @param Bridge Pci device instance.\r
889 @param Mem32Node Resource info node for 32-bit memory.\r
8e8227d1 890 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
eeefcb9d 891 @param Mem64Node Resource info node for 64-bit memory.\r
8e8227d1 892 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
ead42efc 893\r
bcd70414 894**/\r
8e8227d1 895VOID\r
57076f45 896DegradeResource (\r
897 IN PCI_IO_DEVICE *Bridge,\r
898 IN PCI_RESOURCE_NODE *Mem32Node,\r
899 IN PCI_RESOURCE_NODE *PMem32Node,\r
900 IN PCI_RESOURCE_NODE *Mem64Node,\r
901 IN PCI_RESOURCE_NODE *PMem64Node\r
902 )\r
ead42efc 903{\r
68077ae3 904 BOOLEAN HasOprom;\r
905 PCI_IO_DEVICE *Temp;\r
906 LIST_ENTRY *CurrentLink;\r
907\r
908 //\r
909 // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
910 // to find if this bridge and downstream has OptionRom.\r
8e8227d1 911 //\r
68077ae3 912 HasOprom = FALSE;\r
913 CurrentLink = Bridge->ChildList.ForwardLink;\r
97404058 914 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
68077ae3 915\r
916 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
917 if (Temp->RomSize != 0) {\r
918 HasOprom = TRUE;\r
919 break;\r
8e8227d1 920 }\r
68077ae3 921 CurrentLink = CurrentLink->ForwardLink;\r
8e8227d1 922 }\r
ead42efc 923\r
924 //\r
925 // If bridge doesn't support Prefetchable\r
926 // memory64, degrade it to Prefetchable memory32\r
927 //\r
928 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {\r
929 MergeResourceTree (\r
930 PMem32Node,\r
931 PMem64Node,\r
932 TRUE\r
933 );\r
934 } else {\r
935 //\r
68077ae3 936 // if no PMem32 request and no OptionRom request, still keep PMem64. Otherwise degrade to PMem32\r
ead42efc 937 //\r
8e8227d1 938 if ((PMem32Node != NULL && (PMem32Node->Length != 0 && Bridge->Parent != NULL)) || HasOprom) {\r
31bbf49f 939 //\r
940 // Fixed the issue that there is no resource for 64-bit (above 4G)\r
941 //\r
ead42efc 942 MergeResourceTree (\r
943 PMem32Node,\r
944 PMem64Node,\r
945 TRUE\r
946 );\r
947 }\r
948 }\r
949\r
950\r
951 //\r
952 // If bridge doesn't support Mem64\r
953 // degrade it to mem32\r
954 //\r
955 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {\r
956 MergeResourceTree (\r
957 Mem32Node,\r
958 Mem64Node,\r
959 TRUE\r
960 );\r
961 }\r
962\r
963 //\r
964 // If bridge doesn't support Pmem32\r
965 // degrade it to mem32\r
966 //\r
967 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {\r
968 MergeResourceTree (\r
969 Mem32Node,\r
970 PMem32Node,\r
971 TRUE\r
972 );\r
973 }\r
974\r
975 //\r
976 // if bridge supports combined Pmem Mem decoding\r
977 // merge these two type of resource\r
978 //\r
979 if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {\r
980 MergeResourceTree (\r
981 Mem32Node,\r
982 PMem32Node,\r
983 FALSE\r
984 );\r
985\r
986 MergeResourceTree (\r
987 Mem64Node,\r
988 PMem64Node,\r
989 FALSE\r
990 );\r
991 }\r
ead42efc 992}\r
993\r
57076f45 994/**\r
8e8227d1 995 Test whether bridge device support decode resource.\r
996\r
eeefcb9d 997 @param Bridge Bridge device instance.\r
998 @param Decode Decode type according to resource type.\r
8e8227d1 999\r
1000 @return TRUE The bridge device support decode resource.\r
1001 @return FALSE The bridge device don't support decode resource.\r
1002\r
57076f45 1003**/\r
ead42efc 1004BOOLEAN\r
1005BridgeSupportResourceDecode (\r
1006 IN PCI_IO_DEVICE *Bridge,\r
1007 IN UINT32 Decode\r
1008 )\r
ead42efc 1009{\r
97404058 1010 if (((Bridge->Decodes) & Decode) != 0) {\r
ead42efc 1011 return TRUE;\r
1012 }\r
1013\r
1014 return FALSE;\r
1015}\r
1016\r
bcd70414 1017/**\r
8e8227d1 1018 This function is used to program the resource allocated\r
1019 for each resource node under specified bridge.\r
1020\r
1021 @param Base Base address of resource to be progammed.\r
1022 @param Bridge PCI resource node for the bridge device.\r
1023\r
1024 @retval EFI_SUCCESS Successfully to program all resouces\r
1025 on given PCI bridge device.\r
1026 @retval EFI_OUT_OF_RESOURCES Base is all one.\r
1027\r
bcd70414 1028**/\r
57076f45 1029EFI_STATUS\r
1030ProgramResource (\r
1031 IN UINT64 Base,\r
1032 IN PCI_RESOURCE_NODE *Bridge\r
1033 )\r
ead42efc 1034{\r
1035 LIST_ENTRY *CurrentLink;\r
1036 PCI_RESOURCE_NODE *Node;\r
1037 EFI_STATUS Status;\r
1038\r
1039 if (Base == gAllOne) {\r
1040 return EFI_OUT_OF_RESOURCES;\r
1041 }\r
1042\r
1043 CurrentLink = Bridge->ChildList.ForwardLink;\r
1044\r
1045 while (CurrentLink != &Bridge->ChildList) {\r
1046\r
1047 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1048\r
1049 if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {\r
1050\r
1051 if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
8e8227d1 1052 //\r
1053 // Program the PCI Card Bus device\r
1054 //\r
ead42efc 1055 ProgramP2C (Base, Node);\r
1056 } else {\r
8e8227d1 1057 //\r
1058 // Program the PCI device BAR\r
1059 //\r
ead42efc 1060 ProgramBar (Base, Node);\r
1061 }\r
1062 } else {\r
8e8227d1 1063 //\r
1064 // Program the PCI devices under this bridge\r
1065 //\r
ead42efc 1066 Status = ProgramResource (Base + Node->Offset, Node);\r
ead42efc 1067 if (EFI_ERROR (Status)) {\r
1068 return Status;\r
1069 }\r
1070\r
1071 ProgramPpbApperture (Base, Node);\r
1072 }\r
1073\r
1074 CurrentLink = CurrentLink->ForwardLink;\r
1075 }\r
1076\r
1077 return EFI_SUCCESS;\r
1078}\r
1079\r
57076f45 1080/**\r
8e8227d1 1081 Program Bar register for PCI device.\r
1082\r
1083 @param Base Base address for PCI device resource to be progammed.\r
eeefcb9d 1084 @param Node Point to resoure node structure.\r
8e8227d1 1085\r
57076f45 1086**/\r
8e8227d1 1087VOID\r
ead42efc 1088ProgramBar (\r
1089 IN UINT64 Base,\r
1090 IN PCI_RESOURCE_NODE *Node\r
1091 )\r
ead42efc 1092{\r
1093 EFI_PCI_IO_PROTOCOL *PciIo;\r
1094 UINT64 Address;\r
1095 UINT32 Address32;\r
1096\r
1097 Address = 0;\r
1098 PciIo = &(Node->PciDev->PciIo);\r
1099\r
1100 Address = Base + Node->Offset;\r
1101\r
1102 //\r
1103 // Indicate pci bus driver has allocated\r
1104 // resource for this device\r
1105 // It might be a temporary solution here since\r
1106 // pci device could have multiple bar\r
1107 //\r
1108 Node->PciDev->Allocated = TRUE;\r
1109\r
c72216a6 1110 ASSERT (Node->Bar < PCI_MAX_BAR);\r
ead42efc 1111 switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {\r
1112\r
1113 case PciBarTypeIo16:\r
1114 case PciBarTypeIo32:\r
1115 case PciBarTypeMem32:\r
1116 case PciBarTypePMem32:\r
1117\r
9eb130ff 1118 PciIo->Pci.Write (\r
1119 PciIo,\r
1120 EfiPciIoWidthUint32,\r
1121 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1122 1,\r
1123 &Address\r
1124 );\r
ead42efc 1125\r
1126 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1127\r
1128 break;\r
1129\r
1130 case PciBarTypeMem64:\r
1131 case PciBarTypePMem64:\r
1132\r
1133 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
1134\r
9eb130ff 1135 PciIo->Pci.Write (\r
1136 PciIo,\r
1137 EfiPciIoWidthUint32,\r
1138 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1139 1,\r
1140 &Address32\r
1141 );\r
ead42efc 1142\r
1143 Address32 = (UINT32) RShiftU64 (Address, 32);\r
1144\r
9eb130ff 1145 PciIo->Pci.Write (\r
1146 PciIo,\r
1147 EfiPciIoWidthUint32,\r
1148 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),\r
1149 1,\r
1150 &Address32\r
1151 );\r
ead42efc 1152\r
1153 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1154\r
1155 break;\r
1156\r
1157 default:\r
1158 break;\r
1159 }\r
ead42efc 1160}\r
1161\r
57076f45 1162/**\r
8e8227d1 1163 Program PCI-PCI bridge apperture.\r
1164\r
eeefcb9d 1165 @param Base Base address for resource.\r
1166 @param Node Point to resoure node structure.\r
8e8227d1 1167\r
57076f45 1168**/\r
8e8227d1 1169VOID\r
ead42efc 1170ProgramPpbApperture (\r
1171 IN UINT64 Base,\r
1172 IN PCI_RESOURCE_NODE *Node\r
1173 )\r
ead42efc 1174{\r
1175 EFI_PCI_IO_PROTOCOL *PciIo;\r
1176 UINT64 Address;\r
1177 UINT32 Address32;\r
1178\r
1179 Address = 0;\r
1180 //\r
8e8227d1 1181 // If no device resource of this PPB, return anyway\r
ead42efc 1182 // Apperture is set default in the initialization code\r
1183 //\r
1184 if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {\r
1185 //\r
1186 // For padding resource node, just ignore when programming\r
1187 //\r
8e8227d1 1188 return ;\r
ead42efc 1189 }\r
1190\r
1191 PciIo = &(Node->PciDev->PciIo);\r
1192 Address = Base + Node->Offset;\r
1193\r
1194 //\r
1195 // Indicate the PPB resource has been allocated\r
1196 //\r
1197 Node->PciDev->Allocated = TRUE;\r
1198\r
1199 switch (Node->Bar) {\r
1200\r
1201 case PPB_BAR_0:\r
1202 case PPB_BAR_1:\r
9eb130ff 1203 PciIo->Pci.Write (\r
1204 PciIo,\r
1205 EfiPciIoWidthUint32,\r
1206 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1207 1,\r
1208 &Address\r
1209 );\r
ead42efc 1210\r
1211 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1212 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1213\r
1214 break;\r
1215\r
1216 case PPB_IO_RANGE:\r
1217\r
1218 Address32 = ((UINT32) (Address)) >> 8;\r
9eb130ff 1219 PciIo->Pci.Write (\r
1220 PciIo,\r
1221 EfiPciIoWidthUint8,\r
1222 0x1C,\r
1223 1,\r
1224 &Address32\r
1225 );\r
ead42efc 1226\r
1227 Address32 >>= 8;\r
9eb130ff 1228 PciIo->Pci.Write (\r
1229 PciIo,\r
1230 EfiPciIoWidthUint16,\r
1231 0x30,\r
1232 1,\r
1233 &Address32\r
1234 );\r
ead42efc 1235\r
1236 Address32 = (UINT32) (Address + Node->Length - 1);\r
1237 Address32 = ((UINT32) (Address32)) >> 8;\r
9eb130ff 1238 PciIo->Pci.Write (\r
1239 PciIo,\r
1240 EfiPciIoWidthUint8,\r
1241 0x1D,\r
1242 1,\r
1243 &Address32\r
1244 );\r
ead42efc 1245\r
1246 Address32 >>= 8;\r
9eb130ff 1247 PciIo->Pci.Write (\r
1248 PciIo,\r
1249 EfiPciIoWidthUint16,\r
1250 0x32,\r
1251 1,\r
1252 &Address32\r
1253 );\r
ead42efc 1254\r
1255 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1256 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1257 break;\r
1258\r
1259 case PPB_MEM32_RANGE:\r
1260\r
1261 Address32 = ((UINT32) (Address)) >> 16;\r
9eb130ff 1262 PciIo->Pci.Write (\r
1263 PciIo,\r
1264 EfiPciIoWidthUint16,\r
1265 0x20,\r
1266 1,\r
1267 &Address32\r
1268 );\r
ead42efc 1269\r
1270 Address32 = (UINT32) (Address + Node->Length - 1);\r
1271 Address32 = ((UINT32) (Address32)) >> 16;\r
9eb130ff 1272 PciIo->Pci.Write (\r
1273 PciIo,\r
1274 EfiPciIoWidthUint16,\r
1275 0x22,\r
1276 1,\r
1277 &Address32\r
1278 );\r
ead42efc 1279\r
1280 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1281 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1282 break;\r
1283\r
1284 case PPB_PMEM32_RANGE:\r
1285 case PPB_PMEM64_RANGE:\r
1286\r
1287 Address32 = ((UINT32) (Address)) >> 16;\r
9eb130ff 1288 PciIo->Pci.Write (\r
1289 PciIo,\r
1290 EfiPciIoWidthUint16,\r
1291 0x24,\r
1292 1,\r
1293 &Address32\r
1294 );\r
ead42efc 1295\r
1296 Address32 = (UINT32) (Address + Node->Length - 1);\r
1297 Address32 = ((UINT32) (Address32)) >> 16;\r
9eb130ff 1298 PciIo->Pci.Write (\r
1299 PciIo,\r
1300 EfiPciIoWidthUint16,\r
1301 0x26,\r
1302 1,\r
1303 &Address32\r
1304 );\r
ead42efc 1305\r
1306 Address32 = (UINT32) RShiftU64 (Address, 32);\r
9eb130ff 1307 PciIo->Pci.Write (\r
1308 PciIo,\r
1309 EfiPciIoWidthUint32,\r
1310 0x28,\r
1311 1,\r
1312 &Address32\r
1313 );\r
ead42efc 1314\r
1315 Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);\r
9eb130ff 1316 PciIo->Pci.Write (\r
1317 PciIo,\r
1318 EfiPciIoWidthUint32,\r
1319 0x2C,\r
1320 1,\r
1321 &Address32\r
1322 );\r
ead42efc 1323\r
1324 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1325 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1326 break;\r
1327\r
1328 default:\r
1329 break;\r
1330 }\r
ead42efc 1331}\r
1332\r
57076f45 1333/**\r
8e8227d1 1334 Program parent bridge for Option Rom.\r
1335\r
eeefcb9d 1336 @param PciDevice Pci deivce instance.\r
8e8227d1 1337 @param OptionRomBase Base address for Optiona Rom.\r
1338 @param Enable Enable or disable PCI memory.\r
1339\r
57076f45 1340**/\r
8e8227d1 1341VOID\r
ead42efc 1342ProgrameUpstreamBridgeForRom (\r
1343 IN PCI_IO_DEVICE *PciDevice,\r
1344 IN UINT32 OptionRomBase,\r
1345 IN BOOLEAN Enable\r
1346 )\r
ead42efc 1347{\r
1348 PCI_IO_DEVICE *Parent;\r
1349 PCI_RESOURCE_NODE Node;\r
1350 //\r
1351 // For root bridge, just return.\r
1352 //\r
1353 Parent = PciDevice->Parent;\r
1354 ZeroMem (&Node, sizeof (Node));\r
97404058 1355 while (Parent != NULL) {\r
ead42efc 1356 if (!IS_PCI_BRIDGE (&Parent->Pci)) {\r
1357 break;\r
1358 }\r
1359\r
1360 Node.PciDev = Parent;\r
1361 Node.Length = PciDevice->RomSize;\r
1362 Node.Alignment = 0;\r
1363 Node.Bar = PPB_MEM32_RANGE;\r
1364 Node.ResType = PciBarTypeMem32;\r
1365 Node.Offset = 0;\r
1366\r
1367 //\r
8e8227d1 1368 // Program PPB to only open a single <= 16MB apperture\r
ead42efc 1369 //\r
1370 if (Enable) {\r
1371 ProgramPpbApperture (OptionRomBase, &Node);\r
94b9d5c6 1372 PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
ead42efc 1373 } else {\r
1374 InitializePpb (Parent);\r
94b9d5c6 1375 PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
ead42efc 1376 }\r
1377\r
1378 Parent = Parent->Parent;\r
1379 }\r
ead42efc 1380}\r
1381\r
57076f45 1382/**\r
eeefcb9d 1383 Test whether resource exists for a bridge.\r
8e8227d1 1384\r
eeefcb9d 1385 @param Bridge Point to resource node for a bridge.\r
8e8227d1 1386\r
1387 @retval TRUE There is resource on the given bridge.\r
1388 @retval FALSE There isn't resource on the given bridge.\r
1389\r
57076f45 1390**/\r
ead42efc 1391BOOLEAN\r
1392ResourceRequestExisted (\r
8e8227d1 1393 IN PCI_RESOURCE_NODE *Bridge\r
ead42efc 1394 )\r
ead42efc 1395{\r
1396 if (Bridge != NULL) {\r
1397 if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {\r
1398 return TRUE;\r
1399 }\r
1400 }\r
1401\r
1402 return FALSE;\r
1403}\r
1404\r
57076f45 1405/**\r
1406 Initialize resource pool structure.\r
8e8227d1 1407\r
1408 @param ResourcePool Point to resource pool structure. This pool\r
1409 is reset to all zero when returned.\r
eeefcb9d 1410 @param ResourceType Type of resource.\r
8e8227d1 1411\r
57076f45 1412**/\r
8e8227d1 1413VOID\r
ead42efc 1414InitializeResourcePool (\r
8e8227d1 1415 IN OUT PCI_RESOURCE_NODE *ResourcePool,\r
1416 IN PCI_BAR_TYPE ResourceType\r
ead42efc 1417 )\r
ead42efc 1418{\r
ead42efc 1419 ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));\r
1420 ResourcePool->ResType = ResourceType;\r
1421 ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;\r
1422 InitializeListHead (&ResourcePool->ChildList);\r
ead42efc 1423}\r
1424\r
8e8227d1 1425\r
57076f45 1426/**\r
eeefcb9d 1427 Get all resource information for given Pci device.\r
8e8227d1 1428\r
eeefcb9d 1429 @param PciDev Pci device instance.\r
1430 @param IoBridge Io resource node.\r
1431 @param Mem32Bridge 32-bit memory node.\r
1432 @param PMem32Bridge 32-bit Pmemory node.\r
1433 @param Mem64Bridge 64-bit memory node.\r
1434 @param PMem64Bridge 64-bit PMemory node.\r
1435 @param IoPool Link list header for Io resource.\r
1436 @param Mem32Pool Link list header for 32-bit memory.\r
8e8227d1 1437 @param PMem32Pool Link list header for 32-bit Prefetchable memory.\r
eeefcb9d 1438 @param Mem64Pool Link list header for 64-bit memory.\r
8e8227d1 1439 @param PMem64Pool Link list header for 64-bit Prefetchable memory.\r
1440\r
57076f45 1441**/\r
8e8227d1 1442VOID\r
ead42efc 1443GetResourceMap (\r
8e8227d1 1444 IN PCI_IO_DEVICE *PciDev,\r
1445 IN PCI_RESOURCE_NODE **IoBridge,\r
1446 IN PCI_RESOURCE_NODE **Mem32Bridge,\r
1447 IN PCI_RESOURCE_NODE **PMem32Bridge,\r
1448 IN PCI_RESOURCE_NODE **Mem64Bridge,\r
1449 IN PCI_RESOURCE_NODE **PMem64Bridge,\r
1450 IN PCI_RESOURCE_NODE *IoPool,\r
1451 IN PCI_RESOURCE_NODE *Mem32Pool,\r
1452 IN PCI_RESOURCE_NODE *PMem32Pool,\r
1453 IN PCI_RESOURCE_NODE *Mem64Pool,\r
1454 IN PCI_RESOURCE_NODE *PMem64Pool\r
ead42efc 1455 )\r
ead42efc 1456{\r
1457\r
1458 PCI_RESOURCE_NODE *Temp;\r
1459 LIST_ENTRY *CurrentLink;\r
1460\r
1461 CurrentLink = IoPool->ChildList.ForwardLink;\r
1462\r
1463 //\r
1464 // Get Io resource map\r
1465 //\r
1466 while (CurrentLink != &IoPool->ChildList) {\r
1467\r
1468 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1469\r
1470 if (Temp->PciDev == PciDev) {\r
1471 *IoBridge = Temp;\r
1472 }\r
1473\r
1474 CurrentLink = CurrentLink->ForwardLink;\r
1475 }\r
1476\r
1477 //\r
1478 // Get Mem32 resource map\r
1479 //\r
1480 CurrentLink = Mem32Pool->ChildList.ForwardLink;\r
1481\r
1482 while (CurrentLink != &Mem32Pool->ChildList) {\r
1483\r
1484 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1485\r
1486 if (Temp->PciDev == PciDev) {\r
1487 *Mem32Bridge = Temp;\r
1488 }\r
1489\r
1490 CurrentLink = CurrentLink->ForwardLink;\r
1491 }\r
1492\r
1493 //\r
1494 // Get Pmem32 resource map\r
1495 //\r
1496 CurrentLink = PMem32Pool->ChildList.ForwardLink;\r
1497\r
1498 while (CurrentLink != &PMem32Pool->ChildList) {\r
1499\r
1500 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1501\r
1502 if (Temp->PciDev == PciDev) {\r
1503 *PMem32Bridge = Temp;\r
1504 }\r
1505\r
1506 CurrentLink = CurrentLink->ForwardLink;\r
1507 }\r
1508\r
1509 //\r
1510 // Get Mem64 resource map\r
1511 //\r
1512 CurrentLink = Mem64Pool->ChildList.ForwardLink;\r
1513\r
1514 while (CurrentLink != &Mem64Pool->ChildList) {\r
1515\r
1516 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1517\r
1518 if (Temp->PciDev == PciDev) {\r
1519 *Mem64Bridge = Temp;\r
1520 }\r
1521\r
1522 CurrentLink = CurrentLink->ForwardLink;\r
1523 }\r
1524\r
1525 //\r
1526 // Get Pmem64 resource map\r
1527 //\r
1528 CurrentLink = PMem64Pool->ChildList.ForwardLink;\r
1529\r
1530 while (CurrentLink != &PMem64Pool->ChildList) {\r
1531\r
1532 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1533\r
1534 if (Temp->PciDev == PciDev) {\r
1535 *PMem64Bridge = Temp;\r
1536 }\r
1537\r
1538 CurrentLink = CurrentLink->ForwardLink;\r
1539 }\r
ead42efc 1540}\r
1541\r
57076f45 1542/**\r
eeefcb9d 1543 Destory given resource tree.\r
8e8227d1 1544\r
1545 @param Bridge PCI resource root node of resource tree.\r
1546\r
57076f45 1547**/\r
8e8227d1 1548VOID\r
ead42efc 1549DestroyResourceTree (\r
1550 IN PCI_RESOURCE_NODE *Bridge\r
1551 )\r
ead42efc 1552{\r
1553 PCI_RESOURCE_NODE *Temp;\r
1554 LIST_ENTRY *CurrentLink;\r
1555\r
1556 while (!IsListEmpty (&Bridge->ChildList)) {\r
1557\r
1558 CurrentLink = Bridge->ChildList.ForwardLink;\r
1559\r
1560 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
8e8227d1 1561 ASSERT (Temp);\r
ead42efc 1562\r
1563 RemoveEntryList (CurrentLink);\r
1564\r
1565 if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {\r
1566 DestroyResourceTree (Temp);\r
1567 }\r
1568\r
8e8227d1 1569 FreePool (Temp);\r
ead42efc 1570 }\r
ead42efc 1571}\r
1572\r
57076f45 1573/**\r
eeefcb9d 1574 Insert resource padding for P2C.\r
8e8227d1 1575\r
eeefcb9d 1576 @param PciDev Pci device instance.\r
8e8227d1 1577 @param IoNode Resource info node for IO.\r
eeefcb9d 1578 @param Mem32Node Resource info node for 32-bit memory.\r
8e8227d1 1579 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
eeefcb9d 1580 @param Mem64Node Resource info node for 64-bit memory.\r
8e8227d1 1581 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
1582\r
57076f45 1583**/\r
8e8227d1 1584VOID\r
ead42efc 1585ResourcePaddingForCardBusBridge (\r
8e8227d1 1586 IN PCI_IO_DEVICE *PciDev,\r
1587 IN PCI_RESOURCE_NODE *IoNode,\r
1588 IN PCI_RESOURCE_NODE *Mem32Node,\r
1589 IN PCI_RESOURCE_NODE *PMem32Node,\r
1590 IN PCI_RESOURCE_NODE *Mem64Node,\r
1591 IN PCI_RESOURCE_NODE *PMem64Node\r
ead42efc 1592 )\r
ead42efc 1593{\r
1594 PCI_RESOURCE_NODE *Node;\r
1595\r
1596 Node = NULL;\r
1597\r
1598 //\r
1599 // Memory Base/Limit Register 0\r
1600 // Bar 1 denodes memory range 0\r
1601 //\r
1602 Node = CreateResourceNode (\r
8e8227d1 1603 PciDev,\r
1604 0x2000000,\r
1605 0x1ffffff,\r
1606 1,\r
1607 PciBarTypeMem32,\r
1608 PciResUsagePadding\r
1609 );\r
ead42efc 1610\r
1611 InsertResourceNode (\r
1612 Mem32Node,\r
1613 Node\r
1614 );\r
1615\r
1616 //\r
1617 // Memory Base/Limit Register 1\r
1618 // Bar 2 denodes memory range1\r
1619 //\r
1620 Node = CreateResourceNode (\r
8e8227d1 1621 PciDev,\r
1622 0x2000000,\r
1623 0x1ffffff,\r
1624 2,\r
1625 PciBarTypePMem32,\r
1626 PciResUsagePadding\r
1627 );\r
ead42efc 1628\r
1629 InsertResourceNode (\r
1630 PMem32Node,\r
1631 Node\r
1632 );\r
1633\r
1634 //\r
1635 // Io Base/Limit\r
1636 // Bar 3 denodes io range 0\r
1637 //\r
1638 Node = CreateResourceNode (\r
8e8227d1 1639 PciDev,\r
1640 0x100,\r
1641 0xff,\r
1642 3,\r
1643 PciBarTypeIo16,\r
1644 PciResUsagePadding\r
1645 );\r
ead42efc 1646\r
1647 InsertResourceNode (\r
1648 IoNode,\r
1649 Node\r
1650 );\r
1651\r
1652 //\r
1653 // Io Base/Limit\r
1654 // Bar 4 denodes io range 0\r
1655 //\r
1656 Node = CreateResourceNode (\r
8e8227d1 1657 PciDev,\r
1658 0x100,\r
1659 0xff,\r
1660 4,\r
1661 PciBarTypeIo16,\r
1662 PciResUsagePadding\r
1663 );\r
ead42efc 1664\r
1665 InsertResourceNode (\r
1666 IoNode,\r
1667 Node\r
1668 );\r
ead42efc 1669}\r
1670\r
57076f45 1671/**\r
8e8227d1 1672 Program PCI Card device register for given resource node.\r
1673\r
1674 @param Base Base address of PCI Card device to be programmed.\r
57076f45 1675 @param Node Given resource node.\r
8e8227d1 1676\r
57076f45 1677**/\r
8e8227d1 1678VOID\r
ead42efc 1679ProgramP2C (\r
1680 IN UINT64 Base,\r
1681 IN PCI_RESOURCE_NODE *Node\r
1682 )\r
ead42efc 1683{\r
1684 EFI_PCI_IO_PROTOCOL *PciIo;\r
1685 UINT64 Address;\r
1686 UINT64 TempAddress;\r
1687 UINT16 BridgeControl;\r
1688\r
1689 Address = 0;\r
1690 PciIo = &(Node->PciDev->PciIo);\r
1691\r
1692 Address = Base + Node->Offset;\r
1693\r
1694 //\r
1695 // Indicate pci bus driver has allocated\r
1696 // resource for this device\r
1697 // It might be a temporary solution here since\r
1698 // pci device could have multiple bar\r
1699 //\r
1700 Node->PciDev->Allocated = TRUE;\r
1701\r
1702 switch (Node->Bar) {\r
1703\r
1704 case P2C_BAR_0:\r
9eb130ff 1705 PciIo->Pci.Write (\r
1706 PciIo,\r
1707 EfiPciIoWidthUint32,\r
1708 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1709 1,\r
1710 &Address\r
1711 );\r
ead42efc 1712\r
1713 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1714 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1715 break;\r
1716\r
1717 case P2C_MEM_1:\r
9eb130ff 1718 PciIo->Pci.Write (\r
1719 PciIo,\r
1720 EfiPciIoWidthUint32,\r
1721 PCI_CARD_MEMORY_BASE_0,\r
1722 1,\r
1723 &Address\r
1724 );\r
ead42efc 1725\r
1726 TempAddress = Address + Node->Length - 1;\r
9eb130ff 1727 PciIo->Pci.Write (\r
1728 PciIo,\r
1729 EfiPciIoWidthUint32,\r
1730 PCI_CARD_MEMORY_LIMIT_0,\r
1731 1,\r
1732 &TempAddress\r
1733 );\r
ead42efc 1734\r
1735 if (Node->ResType == PciBarTypeMem32) {\r
ead42efc 1736 //\r
1737 // Set non-prefetchable bit\r
1738 //\r
9eb130ff 1739 PciIo->Pci.Read (\r
1740 PciIo,\r
1741 EfiPciIoWidthUint16,\r
1742 PCI_CARD_BRIDGE_CONTROL,\r
1743 1,\r
1744 &BridgeControl\r
1745 );\r
8e8227d1 1746\r
1747 BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
9eb130ff 1748 PciIo->Pci.Write (\r
1749 PciIo,\r
1750 EfiPciIoWidthUint16,\r
1751 PCI_CARD_BRIDGE_CONTROL,\r
1752 1,\r
1753 &BridgeControl\r
1754 );\r
ead42efc 1755\r
1756 } else {\r
ead42efc 1757 //\r
1758 // Set pre-fetchable bit\r
1759 //\r
9eb130ff 1760 PciIo->Pci.Read (\r
1761 PciIo,\r
1762 EfiPciIoWidthUint16,\r
1763 PCI_CARD_BRIDGE_CONTROL,\r
1764 1,\r
1765 &BridgeControl\r
1766 );\r
8e8227d1 1767\r
1768 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
9eb130ff 1769 PciIo->Pci.Write (\r
1770 PciIo,\r
1771 EfiPciIoWidthUint16,\r
1772 PCI_CARD_BRIDGE_CONTROL,\r
1773 1,\r
1774 &BridgeControl\r
1775 );\r
ead42efc 1776 }\r
1777\r
1778 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1779 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1780 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
1781\r
1782 break;\r
1783\r
1784 case P2C_MEM_2:\r
9eb130ff 1785 PciIo->Pci.Write (\r
1786 PciIo,\r
1787 EfiPciIoWidthUint32,\r
1788 PCI_CARD_MEMORY_BASE_1,\r
1789 1,\r
1790 &Address\r
1791 );\r
ead42efc 1792\r
1793 TempAddress = Address + Node->Length - 1;\r
1794\r
9eb130ff 1795 PciIo->Pci.Write (\r
1796 PciIo,\r
1797 EfiPciIoWidthUint32,\r
1798 PCI_CARD_MEMORY_LIMIT_1,\r
1799 1,\r
1800 &TempAddress\r
1801 );\r
ead42efc 1802\r
1803 if (Node->ResType == PciBarTypeMem32) {\r
1804\r
1805 //\r
1806 // Set non-prefetchable bit\r
1807 //\r
9eb130ff 1808 PciIo->Pci.Read (\r
1809 PciIo,\r
1810 EfiPciIoWidthUint16,\r
1811 PCI_CARD_BRIDGE_CONTROL,\r
1812 1,\r
1813 &BridgeControl\r
1814 );\r
8e8227d1 1815\r
1816 BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);\r
9eb130ff 1817 PciIo->Pci.Write (\r
1818 PciIo,\r
1819 EfiPciIoWidthUint16,\r
1820 PCI_CARD_BRIDGE_CONTROL,\r
1821 1,\r
1822 &BridgeControl\r
1823 );\r
8e8227d1 1824\r
ead42efc 1825 } else {\r
1826\r
1827 //\r
1828 // Set pre-fetchable bit\r
1829 //\r
9eb130ff 1830 PciIo->Pci.Read (\r
1831 PciIo,\r
1832 EfiPciIoWidthUint16,\r
1833 PCI_CARD_BRIDGE_CONTROL,\r
1834 1,\r
1835 &BridgeControl\r
1836 );\r
8e8227d1 1837\r
1838 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;\r
9eb130ff 1839 PciIo->Pci.Write (\r
1840 PciIo,\r
1841 EfiPciIoWidthUint16,\r
1842 PCI_CARD_BRIDGE_CONTROL,\r
1843 1,\r
1844 &BridgeControl\r
1845 );\r
ead42efc 1846 }\r
1847\r
1848 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1849 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1850 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
1851 break;\r
1852\r
1853 case P2C_IO_1:\r
9eb130ff 1854 PciIo->Pci.Write (\r
1855 PciIo,\r
1856 EfiPciIoWidthUint32,\r
1857 PCI_CARD_IO_BASE_0_LOWER,\r
1858 1,\r
1859 &Address\r
1860 );\r
8e8227d1 1861\r
ead42efc 1862 TempAddress = Address + Node->Length - 1;\r
9eb130ff 1863 PciIo->Pci.Write (\r
1864 PciIo,\r
1865 EfiPciIoWidthUint32,\r
1866 PCI_CARD_IO_LIMIT_0_LOWER,\r
1867 1,\r
1868 &TempAddress\r
1869 );\r
ead42efc 1870\r
1871 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1872 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1873 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
1874\r
1875 break;\r
1876\r
1877 case P2C_IO_2:\r
9eb130ff 1878 PciIo->Pci.Write (\r
1879 PciIo,\r
1880 EfiPciIoWidthUint32,\r
1881 PCI_CARD_IO_BASE_1_LOWER,\r
1882 1,\r
1883 &Address\r
1884 );\r
ead42efc 1885\r
1886 TempAddress = Address + Node->Length - 1;\r
9eb130ff 1887 PciIo->Pci.Write (\r
1888 PciIo,\r
1889 EfiPciIoWidthUint32,\r
1890 PCI_CARD_IO_LIMIT_1_LOWER,\r
1891 1,\r
1892 &TempAddress\r
1893 );\r
ead42efc 1894\r
1895 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1896 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1897 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
1898 break;\r
1899\r
1900 default:\r
1901 break;\r
1902 }\r
ead42efc 1903}\r
1904\r
57076f45 1905/**\r
1906 Create padding resource node.\r
8e8227d1 1907\r
eeefcb9d 1908 @param PciDev Pci device instance.\r
8e8227d1 1909 @param IoNode Resource info node for IO.\r
eeefcb9d 1910 @param Mem32Node Resource info node for 32-bit memory.\r
8e8227d1 1911 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
eeefcb9d 1912 @param Mem64Node Resource info node for 64-bit memory.\r
8e8227d1 1913 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
57076f45 1914\r
1915**/\r
8e8227d1 1916VOID\r
ead42efc 1917ApplyResourcePadding (\r
8e8227d1 1918 IN PCI_IO_DEVICE *PciDev,\r
1919 IN PCI_RESOURCE_NODE *IoNode,\r
1920 IN PCI_RESOURCE_NODE *Mem32Node,\r
1921 IN PCI_RESOURCE_NODE *PMem32Node,\r
1922 IN PCI_RESOURCE_NODE *Mem64Node,\r
1923 IN PCI_RESOURCE_NODE *PMem64Node\r
ead42efc 1924 )\r
ead42efc 1925{\r
1926 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
1927 PCI_RESOURCE_NODE *Node;\r
1928 UINT8 DummyBarIndex;\r
1929\r
1930 DummyBarIndex = 0;\r
1931 Ptr = PciDev->ResourcePaddingDescriptors;\r
1932\r
1933 while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
1934\r
1935 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
1936 if (Ptr->AddrLen != 0) {\r
1937\r
1938 Node = CreateResourceNode (\r
1939 PciDev,\r
1940 Ptr->AddrLen,\r
1941 Ptr->AddrRangeMax,\r
1942 DummyBarIndex,\r
1943 PciBarTypeIo16,\r
1944 PciResUsagePadding\r
1945 );\r
1946 InsertResourceNode (\r
1947 IoNode,\r
1948 Node\r
1949 );\r
1950 }\r
1951\r
1952 Ptr++;\r
1953 continue;\r
1954 }\r
1955\r
1956 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
1957\r
1958 if (Ptr->AddrSpaceGranularity == 32) {\r
1959\r
1960 //\r
1961 // prefechable\r
1962 //\r
1963 if (Ptr->SpecificFlag == 0x6) {\r
5326528b 1964 if (Ptr->AddrLen != 0) {\r
ead42efc 1965 Node = CreateResourceNode (\r
1966 PciDev,\r
1967 Ptr->AddrLen,\r
1968 Ptr->AddrRangeMax,\r
1969 DummyBarIndex,\r
1970 PciBarTypePMem32,\r
1971 PciResUsagePadding\r
1972 );\r
1973 InsertResourceNode (\r
1974 PMem32Node,\r
1975 Node\r
1976 );\r
1977 }\r
1978\r
1979 Ptr++;\r
1980 continue;\r
1981 }\r
1982\r
1983 //\r
1984 // Non-prefechable\r
1985 //\r
1986 if (Ptr->SpecificFlag == 0) {\r
5326528b 1987 if (Ptr->AddrLen != 0) {\r
ead42efc 1988 Node = CreateResourceNode (\r
1989 PciDev,\r
1990 Ptr->AddrLen,\r
1991 Ptr->AddrRangeMax,\r
1992 DummyBarIndex,\r
1993 PciBarTypeMem32,\r
1994 PciResUsagePadding\r
1995 );\r
1996 InsertResourceNode (\r
1997 Mem32Node,\r
1998 Node\r
1999 );\r
2000 }\r
2001\r
2002 Ptr++;\r
2003 continue;\r
2004 }\r
2005 }\r
2006\r
2007 if (Ptr->AddrSpaceGranularity == 64) {\r
2008\r
2009 //\r
2010 // prefechable\r
2011 //\r
2012 if (Ptr->SpecificFlag == 0x6) {\r
5326528b 2013 if (Ptr->AddrLen != 0) {\r
ead42efc 2014 Node = CreateResourceNode (\r
2015 PciDev,\r
2016 Ptr->AddrLen,\r
2017 Ptr->AddrRangeMax,\r
2018 DummyBarIndex,\r
2019 PciBarTypePMem64,\r
2020 PciResUsagePadding\r
2021 );\r
2022 InsertResourceNode (\r
2023 PMem64Node,\r
2024 Node\r
2025 );\r
2026 }\r
2027\r
2028 Ptr++;\r
2029 continue;\r
2030 }\r
2031\r
2032 //\r
2033 // Non-prefechable\r
2034 //\r
2035 if (Ptr->SpecificFlag == 0) {\r
5326528b 2036 if (Ptr->AddrLen != 0) {\r
ead42efc 2037 Node = CreateResourceNode (\r
2038 PciDev,\r
2039 Ptr->AddrLen,\r
2040 Ptr->AddrRangeMax,\r
2041 DummyBarIndex,\r
2042 PciBarTypeMem64,\r
2043 PciResUsagePadding\r
2044 );\r
2045 InsertResourceNode (\r
2046 Mem64Node,\r
2047 Node\r
2048 );\r
2049 }\r
2050\r
2051 Ptr++;\r
2052 continue;\r
2053 }\r
2054 }\r
2055 }\r
2056\r
2057 Ptr++;\r
2058 }\r
ead42efc 2059}\r
2060\r
57076f45 2061/**\r
8e8227d1 2062 Get padding resource for PCI-PCI bridge.\r
2063\r
2064 @param PciIoDevice PCI-PCI bridge device instance.\r
57076f45 2065\r
8e8227d1 2066 @note Feature flag PcdPciBusHotplugDeviceSupport determines\r
2067 whether need to pad resource for them.\r
57076f45 2068**/\r
ead42efc 2069VOID\r
2070GetResourcePaddingPpb (\r
2071 IN PCI_IO_DEVICE *PciIoDevice\r
2072 )\r
ead42efc 2073{\r
8e8227d1 2074 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
ead42efc 2075 if (PciIoDevice->ResourcePaddingDescriptors == NULL) {\r
2076 GetResourcePaddingForHpb (PciIoDevice);\r
2077 }\r
2078 }\r
2079}\r
57076f45 2080\r