]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Bus/Pci/PciBusDxe/PciResourceSupport.c
add security check
[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
7fc72ecb 547 // Add VF resource\r
548 //\r
549 for (Index = 0; Index < PCI_MAX_BAR; Index++) {\r
550\r
551 switch ((PciDev->VfPciBar)[Index].BarType) {\r
552\r
553 case PciBarTypeMem32:\r
554\r
555 Node = CreateVfResourceNode (\r
556 PciDev,\r
557 (PciDev->VfPciBar)[Index].Length,\r
558 (PciDev->VfPciBar)[Index].Alignment,\r
559 Index,\r
560 PciBarTypeMem32,\r
561 PciResUsageTypical\r
562 );\r
563\r
564 InsertResourceNode (\r
565 Mem32Node,\r
566 Node\r
567 );\r
568\r
569 break;\r
570\r
571 case PciBarTypeMem64:\r
572\r
573 Node = CreateVfResourceNode (\r
574 PciDev,\r
575 (PciDev->VfPciBar)[Index].Length,\r
576 (PciDev->VfPciBar)[Index].Alignment,\r
577 Index,\r
578 PciBarTypeMem64,\r
579 PciResUsageTypical\r
580 );\r
581\r
582 InsertResourceNode (\r
583 Mem64Node,\r
584 Node\r
585 );\r
586\r
587 break;\r
588\r
589 case PciBarTypePMem64:\r
590\r
591 Node = CreateVfResourceNode (\r
592 PciDev,\r
593 (PciDev->VfPciBar)[Index].Length,\r
594 (PciDev->VfPciBar)[Index].Alignment,\r
595 Index,\r
596 PciBarTypePMem64,\r
597 PciResUsageTypical\r
598 );\r
599\r
600 InsertResourceNode (\r
601 PMem64Node,\r
602 Node\r
603 );\r
604\r
605 break;\r
606\r
607 case PciBarTypePMem32:\r
608\r
609 Node = CreateVfResourceNode (\r
610 PciDev,\r
611 (PciDev->VfPciBar)[Index].Length,\r
612 (PciDev->VfPciBar)[Index].Alignment,\r
613 Index,\r
614 PciBarTypePMem32,\r
615 PciResUsageTypical\r
616 );\r
617\r
618 InsertResourceNode (\r
619 PMem32Node,\r
620 Node\r
621 );\r
622 break;\r
623\r
624 case PciBarTypeIo16:\r
625 case PciBarTypeIo32:\r
626 break;\r
627\r
628 case PciBarTypeUnknown:\r
629 break;\r
630\r
631 default:\r
632 break;\r
633 }\r
634 }\r
ead42efc 635 // If there is no resource requested from this device,\r
636 // then we indicate this device has been allocated naturally.\r
637 //\r
638 if (!ResourceRequested) {\r
639 PciDev->Allocated = TRUE;\r
640 }\r
ead42efc 641}\r
642\r
57076f45 643/**\r
eeefcb9d 644 This function is used to create a resource node.\r
645\r
646 @param PciDev Pci device instance.\r
647 @param Length Length of Io/Memory resource.\r
648 @param Alignment Alignment of resource.\r
649 @param Bar Bar index.\r
650 @param ResType Type of resource: IO/Memory.\r
651 @param ResUsage Resource usage.\r
8e8227d1 652\r
653 @return PCI resource node created for given PCI device.\r
654 NULL means PCI resource node is not created.\r
655\r
57076f45 656**/\r
ead42efc 657PCI_RESOURCE_NODE *\r
658CreateResourceNode (\r
659 IN PCI_IO_DEVICE *PciDev,\r
660 IN UINT64 Length,\r
661 IN UINT64 Alignment,\r
662 IN UINT8 Bar,\r
663 IN PCI_BAR_TYPE ResType,\r
664 IN PCI_RESOURCE_USAGE ResUsage\r
665 )\r
ead42efc 666{\r
667 PCI_RESOURCE_NODE *Node;\r
668\r
669 Node = NULL;\r
670\r
9eb130ff 671 Node = AllocateZeroPool (sizeof (PCI_RESOURCE_NODE));\r
7f0f1b8f 672 ASSERT (Node != NULL);\r
ead42efc 673 if (Node == NULL) {\r
674 return NULL;\r
675 }\r
676\r
ead42efc 677 Node->Signature = PCI_RESOURCE_SIGNATURE;\r
678 Node->PciDev = PciDev;\r
679 Node->Length = Length;\r
680 Node->Alignment = Alignment;\r
681 Node->Bar = Bar;\r
682 Node->ResType = ResType;\r
683 Node->Reserved = FALSE;\r
684 Node->ResourceUsage = ResUsage;\r
685 InitializeListHead (&Node->ChildList);\r
8e8227d1 686\r
ead42efc 687 return Node;\r
688}\r
689\r
7fc72ecb 690/**\r
691 This function is used to create a IOV VF resource node.\r
692\r
693 @param PciDev Pci device instance.\r
694 @param Length Length of Io/Memory resource.\r
695 @param Alignment Alignment of resource.\r
696 @param Bar Bar index.\r
697 @param ResType Type of resource: IO/Memory.\r
698 @param ResUsage Resource usage.\r
699\r
700 @return PCI resource node created for given VF PCI device.\r
701 NULL means PCI resource node is not created.\r
702\r
703**/\r
704PCI_RESOURCE_NODE *\r
705CreateVfResourceNode (\r
706 IN PCI_IO_DEVICE *PciDev,\r
707 IN UINT64 Length,\r
708 IN UINT64 Alignment,\r
709 IN UINT8 Bar,\r
710 IN PCI_BAR_TYPE ResType,\r
711 IN PCI_RESOURCE_USAGE ResUsage\r
712 )\r
713{\r
714 PCI_RESOURCE_NODE *Node;\r
715\r
716 DEBUG ((\r
717 EFI_D_INFO,\r
718 "PCI-IOV B%x.D%x.F%x - VfResource (Bar - 0x%x) (Type - 0x%x) (Length - 0x%x)\n",\r
719 (UINTN)PciDev->BusNumber,\r
720 (UINTN)PciDev->DeviceNumber,\r
721 (UINTN)PciDev->FunctionNumber,\r
722 (UINTN)Bar,\r
723 (UINTN)ResType,\r
724 (UINTN)Length\r
725 ));\r
726\r
727 Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);\r
728 if (Node == NULL) {\r
729 return Node;\r
730 }\r
731\r
732 Node->Virtual = TRUE;\r
733\r
734 return Node;\r
735}\r
736\r
57076f45 737/**\r
8e8227d1 738 This function is used to extract resource request from\r
57076f45 739 device node list.\r
740\r
eeefcb9d 741 @param Bridge Pci device instance.\r
742 @param IoNode Resource info node for IO.\r
743 @param Mem32Node Resource info node for 32-bit memory.\r
8e8227d1 744 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
eeefcb9d 745 @param Mem64Node Resource info node for 64-bit memory.\r
8e8227d1 746 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
57076f45 747\r
57076f45 748**/\r
8e8227d1 749VOID\r
ead42efc 750CreateResourceMap (\r
9eb130ff 751 IN PCI_IO_DEVICE *Bridge,\r
752 IN OUT PCI_RESOURCE_NODE *IoNode,\r
753 IN OUT PCI_RESOURCE_NODE *Mem32Node,\r
754 IN OUT PCI_RESOURCE_NODE *PMem32Node,\r
755 IN OUT PCI_RESOURCE_NODE *Mem64Node,\r
756 IN OUT PCI_RESOURCE_NODE *PMem64Node\r
ead42efc 757 )\r
ead42efc 758{\r
759 PCI_IO_DEVICE *Temp;\r
760 PCI_RESOURCE_NODE *IoBridge;\r
761 PCI_RESOURCE_NODE *Mem32Bridge;\r
762 PCI_RESOURCE_NODE *PMem32Bridge;\r
763 PCI_RESOURCE_NODE *Mem64Bridge;\r
764 PCI_RESOURCE_NODE *PMem64Bridge;\r
765 LIST_ENTRY *CurrentLink;\r
766\r
767 CurrentLink = Bridge->ChildList.ForwardLink;\r
768\r
97404058 769 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
ead42efc 770\r
771 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
772\r
773 //\r
774 // Create resource nodes for this device by scanning the\r
775 // Bar array in the device private data\r
776 // If the upstream bridge doesn't support this device,\r
777 // no any resource node will be created for this device\r
778 //\r
779 GetResourceFromDevice (\r
780 Temp,\r
781 IoNode,\r
782 Mem32Node,\r
783 PMem32Node,\r
784 Mem64Node,\r
785 PMem64Node\r
786 );\r
787\r
788 if (IS_PCI_BRIDGE (&Temp->Pci)) {\r
789\r
790 //\r
791 // If the device has children, create a bridge resource node for this PPB\r
792 // Note: For PPB, memory aperture is aligned with 1MB and IO aperture\r
793 // is aligned with 4KB\r
794 // This device is typically a bridge device like PPB and P2C\r
8e8227d1 795 // Note: 0x1000 aligned\r
ead42efc 796 //\r
797 IoBridge = CreateResourceNode (\r
8e8227d1 798 Temp,\r
799 0,\r
800 0xFFF,\r
801 PPB_IO_RANGE,\r
802 PciBarTypeIo16,\r
803 PciResUsageTypical\r
804 );\r
805\r
ead42efc 806 Mem32Bridge = CreateResourceNode (\r
807 Temp,\r
808 0,\r
809 0xFFFFF,\r
810 PPB_MEM32_RANGE,\r
811 PciBarTypeMem32,\r
812 PciResUsageTypical\r
813 );\r
814\r
815 PMem32Bridge = CreateResourceNode (\r
8e8227d1 816 Temp,\r
817 0,\r
818 0xFFFFF,\r
819 PPB_PMEM32_RANGE,\r
820 PciBarTypePMem32,\r
821 PciResUsageTypical\r
822 );\r
ead42efc 823\r
824 Mem64Bridge = CreateResourceNode (\r
825 Temp,\r
826 0,\r
827 0xFFFFF,\r
828 PPB_MEM64_RANGE,\r
829 PciBarTypeMem64,\r
830 PciResUsageTypical\r
831 );\r
832\r
833 PMem64Bridge = CreateResourceNode (\r
8e8227d1 834 Temp,\r
835 0,\r
836 0xFFFFF,\r
837 PPB_PMEM64_RANGE,\r
838 PciBarTypePMem64,\r
839 PciResUsageTypical\r
840 );\r
ead42efc 841\r
842 //\r
843 // Recursively create resouce map on this bridge\r
844 //\r
845 CreateResourceMap (\r
846 Temp,\r
847 IoBridge,\r
848 Mem32Bridge,\r
849 PMem32Bridge,\r
850 Mem64Bridge,\r
851 PMem64Bridge\r
852 );\r
853\r
854 if (ResourceRequestExisted (IoBridge)) {\r
855 InsertResourceNode (\r
856 IoNode,\r
857 IoBridge\r
858 );\r
859 } else {\r
9eb130ff 860 FreePool (IoBridge);\r
ead42efc 861 IoBridge = NULL;\r
862 }\r
863\r
864 //\r
865 // If there is node under this resource bridge,\r
866 // then calculate bridge's aperture of this type\r
867 // and insert it into the respective resource tree.\r
868 // If no, delete this resource bridge\r
869 //\r
870 if (ResourceRequestExisted (Mem32Bridge)) {\r
871 InsertResourceNode (\r
872 Mem32Node,\r
873 Mem32Bridge\r
874 );\r
875 } else {\r
9eb130ff 876 FreePool (Mem32Bridge);\r
ead42efc 877 Mem32Bridge = 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 (PMem32Bridge)) {\r
887 InsertResourceNode (\r
888 PMem32Node,\r
889 PMem32Bridge\r
890 );\r
891 } else {\r
9eb130ff 892 FreePool (PMem32Bridge);\r
ead42efc 893 PMem32Bridge = 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 (Mem64Bridge)) {\r
903 InsertResourceNode (\r
904 Mem64Node,\r
905 Mem64Bridge\r
906 );\r
907 } else {\r
9eb130ff 908 FreePool (Mem64Bridge);\r
ead42efc 909 Mem64Bridge = 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 (PMem64Bridge)) {\r
919 InsertResourceNode (\r
920 PMem64Node,\r
921 PMem64Bridge\r
922 );\r
923 } else {\r
9eb130ff 924 FreePool (PMem64Bridge);\r
ead42efc 925 PMem64Bridge = NULL;\r
926 }\r
927\r
928 }\r
929\r
930 //\r
931 // If it is P2C, apply hard coded resource padding\r
932 //\r
ead42efc 933 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {\r
934 ResourcePaddingForCardBusBridge (\r
935 Temp,\r
936 IoNode,\r
937 Mem32Node,\r
938 PMem32Node,\r
939 Mem64Node,\r
940 PMem64Node\r
941 );\r
942 }\r
943\r
944 CurrentLink = CurrentLink->ForwardLink;\r
945 }\r
9eb130ff 946\r
ead42efc 947 //\r
948 // To do some platform specific resource padding ...\r
949 //\r
950 ResourcePaddingPolicy (\r
951 Bridge,\r
952 IoNode,\r
953 Mem32Node,\r
954 PMem32Node,\r
955 Mem64Node,\r
956 PMem64Node\r
957 );\r
958\r
959 //\r
960 // Degrade resource if necessary\r
961 //\r
962 DegradeResource (\r
963 Bridge,\r
964 Mem32Node,\r
965 PMem32Node,\r
966 Mem64Node,\r
967 PMem64Node\r
968 );\r
969\r
970 //\r
971 // Calculate resource aperture for this bridge device\r
972 //\r
973 CalculateResourceAperture (Mem32Node);\r
974 CalculateResourceAperture (PMem32Node);\r
975 CalculateResourceAperture (Mem64Node);\r
976 CalculateResourceAperture (PMem64Node);\r
977 CalculateResourceAperture (IoNode);\r
ead42efc 978}\r
979\r
57076f45 980/**\r
eeefcb9d 981 This function is used to do the resource padding for a specific platform.\r
57076f45 982\r
eeefcb9d 983 @param PciDev Pci device instance.\r
984 @param IoNode Resource info node for IO.\r
985 @param Mem32Node Resource info node for 32-bit memory.\r
8e8227d1 986 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
eeefcb9d 987 @param Mem64Node Resource info node for 64-bit memory.\r
8e8227d1 988 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
57076f45 989\r
57076f45 990**/\r
8e8227d1 991VOID\r
ead42efc 992ResourcePaddingPolicy (\r
8e8227d1 993 IN PCI_IO_DEVICE *PciDev,\r
994 IN PCI_RESOURCE_NODE *IoNode,\r
995 IN PCI_RESOURCE_NODE *Mem32Node,\r
996 IN PCI_RESOURCE_NODE *PMem32Node,\r
997 IN PCI_RESOURCE_NODE *Mem64Node,\r
998 IN PCI_RESOURCE_NODE *PMem64Node\r
ead42efc 999 )\r
ead42efc 1000{\r
1001 //\r
1002 // Create padding resource node\r
1003 //\r
1004 if (PciDev->ResourcePaddingDescriptors != NULL) {\r
1005 ApplyResourcePadding (\r
1006 PciDev,\r
1007 IoNode,\r
1008 Mem32Node,\r
1009 PMem32Node,\r
1010 Mem64Node,\r
1011 PMem64Node\r
1012 );\r
1013 }\r
ead42efc 1014}\r
1015\r
bcd70414 1016/**\r
8e8227d1 1017 This function is used to degrade resource if the upstream bridge\r
1018 doesn't support certain resource. Degradation path is\r
ead42efc 1019 PMEM64 -> MEM64 -> MEM32\r
1020 PMEM64 -> PMEM32 -> MEM32\r
eeefcb9d 1021 IO32 -> IO16.\r
ead42efc 1022\r
eeefcb9d 1023 @param Bridge Pci device instance.\r
1024 @param Mem32Node Resource info node for 32-bit memory.\r
8e8227d1 1025 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
eeefcb9d 1026 @param Mem64Node Resource info node for 64-bit memory.\r
8e8227d1 1027 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
ead42efc 1028\r
bcd70414 1029**/\r
8e8227d1 1030VOID\r
57076f45 1031DegradeResource (\r
1032 IN PCI_IO_DEVICE *Bridge,\r
1033 IN PCI_RESOURCE_NODE *Mem32Node,\r
1034 IN PCI_RESOURCE_NODE *PMem32Node,\r
1035 IN PCI_RESOURCE_NODE *Mem64Node,\r
1036 IN PCI_RESOURCE_NODE *PMem64Node\r
1037 )\r
ead42efc 1038{\r
68077ae3 1039 BOOLEAN HasOprom;\r
1040 PCI_IO_DEVICE *Temp;\r
1041 LIST_ENTRY *CurrentLink;\r
1042\r
1043 //\r
1044 // For RootBridge, PPB , P2C, go recursively to traverse all its children\r
1045 // to find if this bridge and downstream has OptionRom.\r
8e8227d1 1046 //\r
68077ae3 1047 HasOprom = FALSE;\r
1048 CurrentLink = Bridge->ChildList.ForwardLink;\r
97404058 1049 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {\r
68077ae3 1050\r
1051 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);\r
1052 if (Temp->RomSize != 0) {\r
1053 HasOprom = TRUE;\r
1054 break;\r
8e8227d1 1055 }\r
68077ae3 1056 CurrentLink = CurrentLink->ForwardLink;\r
8e8227d1 1057 }\r
ead42efc 1058\r
1059 //\r
1060 // If bridge doesn't support Prefetchable\r
1061 // memory64, degrade it to Prefetchable memory32\r
1062 //\r
1063 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {\r
1064 MergeResourceTree (\r
1065 PMem32Node,\r
1066 PMem64Node,\r
1067 TRUE\r
1068 );\r
1069 } else {\r
1070 //\r
68077ae3 1071 // if no PMem32 request and no OptionRom request, still keep PMem64. Otherwise degrade to PMem32\r
ead42efc 1072 //\r
8e8227d1 1073 if ((PMem32Node != NULL && (PMem32Node->Length != 0 && Bridge->Parent != NULL)) || HasOprom) {\r
31bbf49f 1074 //\r
1075 // Fixed the issue that there is no resource for 64-bit (above 4G)\r
1076 //\r
ead42efc 1077 MergeResourceTree (\r
1078 PMem32Node,\r
1079 PMem64Node,\r
1080 TRUE\r
1081 );\r
1082 }\r
1083 }\r
1084\r
1085\r
1086 //\r
1087 // If bridge doesn't support Mem64\r
1088 // degrade it to mem32\r
1089 //\r
1090 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {\r
1091 MergeResourceTree (\r
1092 Mem32Node,\r
1093 Mem64Node,\r
1094 TRUE\r
1095 );\r
1096 }\r
1097\r
1098 //\r
1099 // If bridge doesn't support Pmem32\r
1100 // degrade it to mem32\r
1101 //\r
1102 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {\r
1103 MergeResourceTree (\r
1104 Mem32Node,\r
1105 PMem32Node,\r
1106 TRUE\r
1107 );\r
1108 }\r
1109\r
1110 //\r
1111 // if bridge supports combined Pmem Mem decoding\r
1112 // merge these two type of resource\r
1113 //\r
1114 if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {\r
1115 MergeResourceTree (\r
1116 Mem32Node,\r
1117 PMem32Node,\r
1118 FALSE\r
1119 );\r
1120\r
1121 MergeResourceTree (\r
1122 Mem64Node,\r
1123 PMem64Node,\r
1124 FALSE\r
1125 );\r
1126 }\r
ead42efc 1127}\r
1128\r
57076f45 1129/**\r
8e8227d1 1130 Test whether bridge device support decode resource.\r
1131\r
eeefcb9d 1132 @param Bridge Bridge device instance.\r
1133 @param Decode Decode type according to resource type.\r
8e8227d1 1134\r
1135 @return TRUE The bridge device support decode resource.\r
1136 @return FALSE The bridge device don't support decode resource.\r
1137\r
57076f45 1138**/\r
ead42efc 1139BOOLEAN\r
1140BridgeSupportResourceDecode (\r
1141 IN PCI_IO_DEVICE *Bridge,\r
1142 IN UINT32 Decode\r
1143 )\r
ead42efc 1144{\r
97404058 1145 if (((Bridge->Decodes) & Decode) != 0) {\r
ead42efc 1146 return TRUE;\r
1147 }\r
1148\r
1149 return FALSE;\r
1150}\r
1151\r
bcd70414 1152/**\r
8e8227d1 1153 This function is used to program the resource allocated\r
1154 for each resource node under specified bridge.\r
1155\r
1156 @param Base Base address of resource to be progammed.\r
1157 @param Bridge PCI resource node for the bridge device.\r
1158\r
1159 @retval EFI_SUCCESS Successfully to program all resouces\r
1160 on given PCI bridge device.\r
1161 @retval EFI_OUT_OF_RESOURCES Base is all one.\r
1162\r
bcd70414 1163**/\r
57076f45 1164EFI_STATUS\r
1165ProgramResource (\r
1166 IN UINT64 Base,\r
1167 IN PCI_RESOURCE_NODE *Bridge\r
1168 )\r
ead42efc 1169{\r
1170 LIST_ENTRY *CurrentLink;\r
1171 PCI_RESOURCE_NODE *Node;\r
1172 EFI_STATUS Status;\r
1173\r
1174 if (Base == gAllOne) {\r
1175 return EFI_OUT_OF_RESOURCES;\r
1176 }\r
1177\r
1178 CurrentLink = Bridge->ChildList.ForwardLink;\r
1179\r
1180 while (CurrentLink != &Bridge->ChildList) {\r
1181\r
1182 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1183\r
1184 if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {\r
1185\r
1186 if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {\r
8e8227d1 1187 //\r
1188 // Program the PCI Card Bus device\r
1189 //\r
ead42efc 1190 ProgramP2C (Base, Node);\r
1191 } else {\r
8e8227d1 1192 //\r
1193 // Program the PCI device BAR\r
1194 //\r
ead42efc 1195 ProgramBar (Base, Node);\r
1196 }\r
1197 } else {\r
8e8227d1 1198 //\r
1199 // Program the PCI devices under this bridge\r
1200 //\r
ead42efc 1201 Status = ProgramResource (Base + Node->Offset, Node);\r
ead42efc 1202 if (EFI_ERROR (Status)) {\r
1203 return Status;\r
1204 }\r
1205\r
1206 ProgramPpbApperture (Base, Node);\r
1207 }\r
1208\r
1209 CurrentLink = CurrentLink->ForwardLink;\r
1210 }\r
1211\r
1212 return EFI_SUCCESS;\r
1213}\r
1214\r
57076f45 1215/**\r
8e8227d1 1216 Program Bar register for PCI device.\r
1217\r
1218 @param Base Base address for PCI device resource to be progammed.\r
eeefcb9d 1219 @param Node Point to resoure node structure.\r
8e8227d1 1220\r
57076f45 1221**/\r
8e8227d1 1222VOID\r
ead42efc 1223ProgramBar (\r
1224 IN UINT64 Base,\r
1225 IN PCI_RESOURCE_NODE *Node\r
1226 )\r
ead42efc 1227{\r
1228 EFI_PCI_IO_PROTOCOL *PciIo;\r
1229 UINT64 Address;\r
1230 UINT32 Address32;\r
1231\r
eb14b481 1232 ASSERT (Node->Bar < PCI_MAX_BAR);\r
1233\r
7fc72ecb 1234 //\r
1235 // Check VF BAR\r
1236 //\r
1237 if (Node->Virtual) {\r
1238 ProgramVfBar (Base, Node);\r
1239 }\r
1240\r
ead42efc 1241 Address = 0;\r
1242 PciIo = &(Node->PciDev->PciIo);\r
1243\r
1244 Address = Base + Node->Offset;\r
1245\r
1246 //\r
1247 // Indicate pci bus driver has allocated\r
1248 // resource for this device\r
1249 // It might be a temporary solution here since\r
1250 // pci device could have multiple bar\r
1251 //\r
1252 Node->PciDev->Allocated = TRUE;\r
1253\r
1254 switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {\r
1255\r
1256 case PciBarTypeIo16:\r
1257 case PciBarTypeIo32:\r
1258 case PciBarTypeMem32:\r
1259 case PciBarTypePMem32:\r
1260\r
9eb130ff 1261 PciIo->Pci.Write (\r
1262 PciIo,\r
1263 EfiPciIoWidthUint32,\r
1264 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1265 1,\r
1266 &Address\r
1267 );\r
ead42efc 1268\r
1269 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1270\r
1271 break;\r
1272\r
1273 case PciBarTypeMem64:\r
1274 case PciBarTypePMem64:\r
1275\r
1276 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
1277\r
9eb130ff 1278 PciIo->Pci.Write (\r
1279 PciIo,\r
1280 EfiPciIoWidthUint32,\r
1281 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1282 1,\r
1283 &Address32\r
1284 );\r
ead42efc 1285\r
1286 Address32 = (UINT32) RShiftU64 (Address, 32);\r
1287\r
9eb130ff 1288 PciIo->Pci.Write (\r
1289 PciIo,\r
1290 EfiPciIoWidthUint32,\r
1291 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),\r
1292 1,\r
1293 &Address32\r
1294 );\r
ead42efc 1295\r
1296 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1297\r
1298 break;\r
1299\r
1300 default:\r
1301 break;\r
1302 }\r
ead42efc 1303}\r
1304\r
7fc72ecb 1305/**\r
1306 Program IOV VF Bar register for PCI device.\r
1307\r
1308 @param Base Base address for PCI device resource to be progammed.\r
1309 @param Node Point to resoure node structure.\r
1310\r
1311**/\r
1312EFI_STATUS\r
1313ProgramVfBar (\r
1314 IN UINT64 Base,\r
1315 IN PCI_RESOURCE_NODE *Node\r
1316 )\r
1317{\r
1318 EFI_PCI_IO_PROTOCOL *PciIo;\r
1319 UINT64 Address;\r
1320 UINT32 Address32;\r
1321\r
1322 ASSERT (Node->Virtual);\r
1323 if (!Node->Virtual) {\r
1324 return EFI_UNSUPPORTED;\r
1325 }\r
1326\r
1327 Address = 0;\r
1328 PciIo = &(Node->PciDev->PciIo);\r
1329\r
1330 Address = Base + Node->Offset;\r
1331\r
1332 //\r
1333 // Indicate pci bus driver has allocated\r
1334 // resource for this device\r
1335 // It might be a temporary solution here since\r
1336 // pci device could have multiple bar\r
1337 //\r
1338 Node->PciDev->Allocated = TRUE;\r
1339\r
1340 switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {\r
1341\r
1342 case PciBarTypeMem32:\r
1343 case PciBarTypePMem32:\r
1344\r
1345 PciIo->Pci.Write (\r
1346 PciIo,\r
1347 EfiPciIoWidthUint32,\r
1348 (Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
1349 1,\r
1350 &Address\r
1351 );\r
1352\r
1353 Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
1354\r
1355 DEBUG ((\r
1356 EFI_D_INFO,\r
1357 "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 32Mem (Address - 0x%x)\n",\r
1358 (UINTN)Node->PciDev->BusNumber,\r
1359 (UINTN)Node->PciDev->DeviceNumber,\r
1360 (UINTN)Node->PciDev->FunctionNumber,\r
1361 (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
1362 (UINTN)Address\r
1363 ));\r
1364\r
1365 break;\r
1366\r
1367 case PciBarTypeMem64:\r
1368 case PciBarTypePMem64:\r
1369\r
1370 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);\r
1371\r
1372 PciIo->Pci.Write (\r
1373 PciIo,\r
1374 EfiPciIoWidthUint32,\r
1375 (Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
1376 1,\r
1377 &Address32\r
1378 );\r
1379\r
1380 Address32 = (UINT32) RShiftU64 (Address, 32);\r
1381\r
1382 PciIo->Pci.Write (\r
1383 PciIo,\r
1384 EfiPciIoWidthUint32,\r
1385 ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),\r
1386 1,\r
1387 &Address32\r
1388 );\r
1389\r
1390 Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;\r
1391\r
1392 DEBUG ((\r
1393 EFI_D_INFO,\r
1394 "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 64Mem (Address - 0x%lx)\n",\r
1395 (UINTN)Node->PciDev->BusNumber,\r
1396 (UINTN)Node->PciDev->DeviceNumber,\r
1397 (UINTN)Node->PciDev->FunctionNumber,\r
1398 (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,\r
1399 (UINT64)Address\r
1400 ));\r
1401\r
1402 break;\r
1403\r
1404 case PciBarTypeIo16:\r
1405 case PciBarTypeIo32:\r
1406 break;\r
1407\r
1408 default:\r
1409 break;\r
1410 }\r
1411\r
1412 return EFI_SUCCESS;\r
1413}\r
1414\r
57076f45 1415/**\r
8e8227d1 1416 Program PCI-PCI bridge apperture.\r
1417\r
eeefcb9d 1418 @param Base Base address for resource.\r
1419 @param Node Point to resoure node structure.\r
8e8227d1 1420\r
57076f45 1421**/\r
8e8227d1 1422VOID\r
ead42efc 1423ProgramPpbApperture (\r
1424 IN UINT64 Base,\r
1425 IN PCI_RESOURCE_NODE *Node\r
1426 )\r
ead42efc 1427{\r
1428 EFI_PCI_IO_PROTOCOL *PciIo;\r
1429 UINT64 Address;\r
1430 UINT32 Address32;\r
1431\r
1432 Address = 0;\r
1433 //\r
8e8227d1 1434 // If no device resource of this PPB, return anyway\r
ead42efc 1435 // Apperture is set default in the initialization code\r
1436 //\r
1437 if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {\r
1438 //\r
1439 // For padding resource node, just ignore when programming\r
1440 //\r
8e8227d1 1441 return ;\r
ead42efc 1442 }\r
1443\r
1444 PciIo = &(Node->PciDev->PciIo);\r
1445 Address = Base + Node->Offset;\r
1446\r
1447 //\r
1448 // Indicate the PPB resource has been allocated\r
1449 //\r
1450 Node->PciDev->Allocated = TRUE;\r
1451\r
1452 switch (Node->Bar) {\r
1453\r
1454 case PPB_BAR_0:\r
1455 case PPB_BAR_1:\r
9eb130ff 1456 PciIo->Pci.Write (\r
1457 PciIo,\r
1458 EfiPciIoWidthUint32,\r
1459 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1460 1,\r
1461 &Address\r
1462 );\r
ead42efc 1463\r
1464 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1465 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1466\r
1467 break;\r
1468\r
1469 case PPB_IO_RANGE:\r
1470\r
1471 Address32 = ((UINT32) (Address)) >> 8;\r
9eb130ff 1472 PciIo->Pci.Write (\r
1473 PciIo,\r
1474 EfiPciIoWidthUint8,\r
1475 0x1C,\r
1476 1,\r
1477 &Address32\r
1478 );\r
ead42efc 1479\r
1480 Address32 >>= 8;\r
9eb130ff 1481 PciIo->Pci.Write (\r
1482 PciIo,\r
1483 EfiPciIoWidthUint16,\r
1484 0x30,\r
1485 1,\r
1486 &Address32\r
1487 );\r
ead42efc 1488\r
1489 Address32 = (UINT32) (Address + Node->Length - 1);\r
1490 Address32 = ((UINT32) (Address32)) >> 8;\r
9eb130ff 1491 PciIo->Pci.Write (\r
1492 PciIo,\r
1493 EfiPciIoWidthUint8,\r
1494 0x1D,\r
1495 1,\r
1496 &Address32\r
1497 );\r
ead42efc 1498\r
1499 Address32 >>= 8;\r
9eb130ff 1500 PciIo->Pci.Write (\r
1501 PciIo,\r
1502 EfiPciIoWidthUint16,\r
1503 0x32,\r
1504 1,\r
1505 &Address32\r
1506 );\r
ead42efc 1507\r
1508 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1509 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1510 break;\r
1511\r
1512 case PPB_MEM32_RANGE:\r
1513\r
1514 Address32 = ((UINT32) (Address)) >> 16;\r
9eb130ff 1515 PciIo->Pci.Write (\r
1516 PciIo,\r
1517 EfiPciIoWidthUint16,\r
1518 0x20,\r
1519 1,\r
1520 &Address32\r
1521 );\r
ead42efc 1522\r
1523 Address32 = (UINT32) (Address + Node->Length - 1);\r
1524 Address32 = ((UINT32) (Address32)) >> 16;\r
9eb130ff 1525 PciIo->Pci.Write (\r
1526 PciIo,\r
1527 EfiPciIoWidthUint16,\r
1528 0x22,\r
1529 1,\r
1530 &Address32\r
1531 );\r
ead42efc 1532\r
1533 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1534 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1535 break;\r
1536\r
1537 case PPB_PMEM32_RANGE:\r
1538 case PPB_PMEM64_RANGE:\r
1539\r
1540 Address32 = ((UINT32) (Address)) >> 16;\r
9eb130ff 1541 PciIo->Pci.Write (\r
1542 PciIo,\r
1543 EfiPciIoWidthUint16,\r
1544 0x24,\r
1545 1,\r
1546 &Address32\r
1547 );\r
ead42efc 1548\r
1549 Address32 = (UINT32) (Address + Node->Length - 1);\r
1550 Address32 = ((UINT32) (Address32)) >> 16;\r
9eb130ff 1551 PciIo->Pci.Write (\r
1552 PciIo,\r
1553 EfiPciIoWidthUint16,\r
1554 0x26,\r
1555 1,\r
1556 &Address32\r
1557 );\r
ead42efc 1558\r
1559 Address32 = (UINT32) RShiftU64 (Address, 32);\r
9eb130ff 1560 PciIo->Pci.Write (\r
1561 PciIo,\r
1562 EfiPciIoWidthUint32,\r
1563 0x28,\r
1564 1,\r
1565 &Address32\r
1566 );\r
ead42efc 1567\r
1568 Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);\r
9eb130ff 1569 PciIo->Pci.Write (\r
1570 PciIo,\r
1571 EfiPciIoWidthUint32,\r
1572 0x2C,\r
1573 1,\r
1574 &Address32\r
1575 );\r
ead42efc 1576\r
1577 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1578 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1579 break;\r
1580\r
1581 default:\r
1582 break;\r
1583 }\r
ead42efc 1584}\r
1585\r
57076f45 1586/**\r
8e8227d1 1587 Program parent bridge for Option Rom.\r
1588\r
eeefcb9d 1589 @param PciDevice Pci deivce instance.\r
8e8227d1 1590 @param OptionRomBase Base address for Optiona Rom.\r
1591 @param Enable Enable or disable PCI memory.\r
1592\r
57076f45 1593**/\r
8e8227d1 1594VOID\r
ead42efc 1595ProgrameUpstreamBridgeForRom (\r
1596 IN PCI_IO_DEVICE *PciDevice,\r
1597 IN UINT32 OptionRomBase,\r
1598 IN BOOLEAN Enable\r
1599 )\r
ead42efc 1600{\r
1601 PCI_IO_DEVICE *Parent;\r
1602 PCI_RESOURCE_NODE Node;\r
1603 //\r
1604 // For root bridge, just return.\r
1605 //\r
1606 Parent = PciDevice->Parent;\r
1607 ZeroMem (&Node, sizeof (Node));\r
97404058 1608 while (Parent != NULL) {\r
ead42efc 1609 if (!IS_PCI_BRIDGE (&Parent->Pci)) {\r
1610 break;\r
1611 }\r
1612\r
1613 Node.PciDev = Parent;\r
1614 Node.Length = PciDevice->RomSize;\r
1615 Node.Alignment = 0;\r
1616 Node.Bar = PPB_MEM32_RANGE;\r
1617 Node.ResType = PciBarTypeMem32;\r
1618 Node.Offset = 0;\r
1619\r
1620 //\r
8e8227d1 1621 // Program PPB to only open a single <= 16MB apperture\r
ead42efc 1622 //\r
1623 if (Enable) {\r
1624 ProgramPpbApperture (OptionRomBase, &Node);\r
94b9d5c6 1625 PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
ead42efc 1626 } else {\r
1627 InitializePpb (Parent);\r
94b9d5c6 1628 PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);\r
ead42efc 1629 }\r
1630\r
1631 Parent = Parent->Parent;\r
1632 }\r
ead42efc 1633}\r
1634\r
57076f45 1635/**\r
eeefcb9d 1636 Test whether resource exists for a bridge.\r
8e8227d1 1637\r
eeefcb9d 1638 @param Bridge Point to resource node for a bridge.\r
8e8227d1 1639\r
1640 @retval TRUE There is resource on the given bridge.\r
1641 @retval FALSE There isn't resource on the given bridge.\r
1642\r
57076f45 1643**/\r
ead42efc 1644BOOLEAN\r
1645ResourceRequestExisted (\r
8e8227d1 1646 IN PCI_RESOURCE_NODE *Bridge\r
ead42efc 1647 )\r
ead42efc 1648{\r
1649 if (Bridge != NULL) {\r
1650 if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {\r
1651 return TRUE;\r
1652 }\r
1653 }\r
1654\r
1655 return FALSE;\r
1656}\r
1657\r
57076f45 1658/**\r
1659 Initialize resource pool structure.\r
8e8227d1 1660\r
1661 @param ResourcePool Point to resource pool structure. This pool\r
1662 is reset to all zero when returned.\r
eeefcb9d 1663 @param ResourceType Type of resource.\r
8e8227d1 1664\r
57076f45 1665**/\r
8e8227d1 1666VOID\r
ead42efc 1667InitializeResourcePool (\r
8e8227d1 1668 IN OUT PCI_RESOURCE_NODE *ResourcePool,\r
1669 IN PCI_BAR_TYPE ResourceType\r
ead42efc 1670 )\r
ead42efc 1671{\r
ead42efc 1672 ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));\r
1673 ResourcePool->ResType = ResourceType;\r
1674 ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;\r
1675 InitializeListHead (&ResourcePool->ChildList);\r
ead42efc 1676}\r
1677\r
8e8227d1 1678\r
57076f45 1679/**\r
eeefcb9d 1680 Get all resource information for given Pci device.\r
8e8227d1 1681\r
eeefcb9d 1682 @param PciDev Pci device instance.\r
1683 @param IoBridge Io resource node.\r
1684 @param Mem32Bridge 32-bit memory node.\r
1685 @param PMem32Bridge 32-bit Pmemory node.\r
1686 @param Mem64Bridge 64-bit memory node.\r
1687 @param PMem64Bridge 64-bit PMemory node.\r
1688 @param IoPool Link list header for Io resource.\r
1689 @param Mem32Pool Link list header for 32-bit memory.\r
8e8227d1 1690 @param PMem32Pool Link list header for 32-bit Prefetchable memory.\r
eeefcb9d 1691 @param Mem64Pool Link list header for 64-bit memory.\r
8e8227d1 1692 @param PMem64Pool Link list header for 64-bit Prefetchable memory.\r
1693\r
57076f45 1694**/\r
8e8227d1 1695VOID\r
ead42efc 1696GetResourceMap (\r
8e8227d1 1697 IN PCI_IO_DEVICE *PciDev,\r
1698 IN PCI_RESOURCE_NODE **IoBridge,\r
1699 IN PCI_RESOURCE_NODE **Mem32Bridge,\r
1700 IN PCI_RESOURCE_NODE **PMem32Bridge,\r
1701 IN PCI_RESOURCE_NODE **Mem64Bridge,\r
1702 IN PCI_RESOURCE_NODE **PMem64Bridge,\r
1703 IN PCI_RESOURCE_NODE *IoPool,\r
1704 IN PCI_RESOURCE_NODE *Mem32Pool,\r
1705 IN PCI_RESOURCE_NODE *PMem32Pool,\r
1706 IN PCI_RESOURCE_NODE *Mem64Pool,\r
1707 IN PCI_RESOURCE_NODE *PMem64Pool\r
ead42efc 1708 )\r
ead42efc 1709{\r
1710\r
1711 PCI_RESOURCE_NODE *Temp;\r
1712 LIST_ENTRY *CurrentLink;\r
1713\r
1714 CurrentLink = IoPool->ChildList.ForwardLink;\r
1715\r
1716 //\r
1717 // Get Io resource map\r
1718 //\r
1719 while (CurrentLink != &IoPool->ChildList) {\r
1720\r
1721 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1722\r
1723 if (Temp->PciDev == PciDev) {\r
1724 *IoBridge = Temp;\r
1725 }\r
1726\r
1727 CurrentLink = CurrentLink->ForwardLink;\r
1728 }\r
1729\r
1730 //\r
1731 // Get Mem32 resource map\r
1732 //\r
1733 CurrentLink = Mem32Pool->ChildList.ForwardLink;\r
1734\r
1735 while (CurrentLink != &Mem32Pool->ChildList) {\r
1736\r
1737 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1738\r
1739 if (Temp->PciDev == PciDev) {\r
1740 *Mem32Bridge = Temp;\r
1741 }\r
1742\r
1743 CurrentLink = CurrentLink->ForwardLink;\r
1744 }\r
1745\r
1746 //\r
1747 // Get Pmem32 resource map\r
1748 //\r
1749 CurrentLink = PMem32Pool->ChildList.ForwardLink;\r
1750\r
1751 while (CurrentLink != &PMem32Pool->ChildList) {\r
1752\r
1753 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1754\r
1755 if (Temp->PciDev == PciDev) {\r
1756 *PMem32Bridge = Temp;\r
1757 }\r
1758\r
1759 CurrentLink = CurrentLink->ForwardLink;\r
1760 }\r
1761\r
1762 //\r
1763 // Get Mem64 resource map\r
1764 //\r
1765 CurrentLink = Mem64Pool->ChildList.ForwardLink;\r
1766\r
1767 while (CurrentLink != &Mem64Pool->ChildList) {\r
1768\r
1769 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1770\r
1771 if (Temp->PciDev == PciDev) {\r
1772 *Mem64Bridge = Temp;\r
1773 }\r
1774\r
1775 CurrentLink = CurrentLink->ForwardLink;\r
1776 }\r
1777\r
1778 //\r
1779 // Get Pmem64 resource map\r
1780 //\r
1781 CurrentLink = PMem64Pool->ChildList.ForwardLink;\r
1782\r
1783 while (CurrentLink != &PMem64Pool->ChildList) {\r
1784\r
1785 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
1786\r
1787 if (Temp->PciDev == PciDev) {\r
1788 *PMem64Bridge = Temp;\r
1789 }\r
1790\r
1791 CurrentLink = CurrentLink->ForwardLink;\r
1792 }\r
ead42efc 1793}\r
1794\r
57076f45 1795/**\r
eeefcb9d 1796 Destory given resource tree.\r
8e8227d1 1797\r
1798 @param Bridge PCI resource root node of resource tree.\r
1799\r
57076f45 1800**/\r
8e8227d1 1801VOID\r
ead42efc 1802DestroyResourceTree (\r
1803 IN PCI_RESOURCE_NODE *Bridge\r
1804 )\r
ead42efc 1805{\r
1806 PCI_RESOURCE_NODE *Temp;\r
1807 LIST_ENTRY *CurrentLink;\r
1808\r
1809 while (!IsListEmpty (&Bridge->ChildList)) {\r
1810\r
1811 CurrentLink = Bridge->ChildList.ForwardLink;\r
1812\r
1813 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);\r
8e8227d1 1814 ASSERT (Temp);\r
ead42efc 1815\r
1816 RemoveEntryList (CurrentLink);\r
1817\r
1818 if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {\r
1819 DestroyResourceTree (Temp);\r
1820 }\r
1821\r
8e8227d1 1822 FreePool (Temp);\r
ead42efc 1823 }\r
ead42efc 1824}\r
1825\r
57076f45 1826/**\r
eeefcb9d 1827 Insert resource padding for P2C.\r
8e8227d1 1828\r
eeefcb9d 1829 @param PciDev Pci device instance.\r
8e8227d1 1830 @param IoNode Resource info node for IO.\r
eeefcb9d 1831 @param Mem32Node Resource info node for 32-bit memory.\r
8e8227d1 1832 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
eeefcb9d 1833 @param Mem64Node Resource info node for 64-bit memory.\r
8e8227d1 1834 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
1835\r
57076f45 1836**/\r
8e8227d1 1837VOID\r
ead42efc 1838ResourcePaddingForCardBusBridge (\r
8e8227d1 1839 IN PCI_IO_DEVICE *PciDev,\r
1840 IN PCI_RESOURCE_NODE *IoNode,\r
1841 IN PCI_RESOURCE_NODE *Mem32Node,\r
1842 IN PCI_RESOURCE_NODE *PMem32Node,\r
1843 IN PCI_RESOURCE_NODE *Mem64Node,\r
1844 IN PCI_RESOURCE_NODE *PMem64Node\r
ead42efc 1845 )\r
ead42efc 1846{\r
1847 PCI_RESOURCE_NODE *Node;\r
1848\r
1849 Node = NULL;\r
1850\r
1851 //\r
1852 // Memory Base/Limit Register 0\r
1853 // Bar 1 denodes memory range 0\r
1854 //\r
1855 Node = CreateResourceNode (\r
8e8227d1 1856 PciDev,\r
1857 0x2000000,\r
1858 0x1ffffff,\r
1859 1,\r
1860 PciBarTypeMem32,\r
1861 PciResUsagePadding\r
1862 );\r
ead42efc 1863\r
1864 InsertResourceNode (\r
1865 Mem32Node,\r
1866 Node\r
1867 );\r
1868\r
1869 //\r
1870 // Memory Base/Limit Register 1\r
1871 // Bar 2 denodes memory range1\r
1872 //\r
1873 Node = CreateResourceNode (\r
8e8227d1 1874 PciDev,\r
1875 0x2000000,\r
1876 0x1ffffff,\r
1877 2,\r
1878 PciBarTypePMem32,\r
1879 PciResUsagePadding\r
1880 );\r
ead42efc 1881\r
1882 InsertResourceNode (\r
1883 PMem32Node,\r
1884 Node\r
1885 );\r
1886\r
1887 //\r
1888 // Io Base/Limit\r
1889 // Bar 3 denodes io range 0\r
1890 //\r
1891 Node = CreateResourceNode (\r
8e8227d1 1892 PciDev,\r
1893 0x100,\r
1894 0xff,\r
1895 3,\r
1896 PciBarTypeIo16,\r
1897 PciResUsagePadding\r
1898 );\r
ead42efc 1899\r
1900 InsertResourceNode (\r
1901 IoNode,\r
1902 Node\r
1903 );\r
1904\r
1905 //\r
1906 // Io Base/Limit\r
1907 // Bar 4 denodes io range 0\r
1908 //\r
1909 Node = CreateResourceNode (\r
8e8227d1 1910 PciDev,\r
1911 0x100,\r
1912 0xff,\r
1913 4,\r
1914 PciBarTypeIo16,\r
1915 PciResUsagePadding\r
1916 );\r
ead42efc 1917\r
1918 InsertResourceNode (\r
1919 IoNode,\r
1920 Node\r
1921 );\r
ead42efc 1922}\r
1923\r
57076f45 1924/**\r
8e8227d1 1925 Program PCI Card device register for given resource node.\r
1926\r
1927 @param Base Base address of PCI Card device to be programmed.\r
57076f45 1928 @param Node Given resource node.\r
8e8227d1 1929\r
57076f45 1930**/\r
8e8227d1 1931VOID\r
ead42efc 1932ProgramP2C (\r
1933 IN UINT64 Base,\r
1934 IN PCI_RESOURCE_NODE *Node\r
1935 )\r
ead42efc 1936{\r
1937 EFI_PCI_IO_PROTOCOL *PciIo;\r
1938 UINT64 Address;\r
1939 UINT64 TempAddress;\r
1940 UINT16 BridgeControl;\r
1941\r
1942 Address = 0;\r
1943 PciIo = &(Node->PciDev->PciIo);\r
1944\r
1945 Address = Base + Node->Offset;\r
1946\r
1947 //\r
1948 // Indicate pci bus driver has allocated\r
1949 // resource for this device\r
1950 // It might be a temporary solution here since\r
1951 // pci device could have multiple bar\r
1952 //\r
1953 Node->PciDev->Allocated = TRUE;\r
1954\r
1955 switch (Node->Bar) {\r
1956\r
1957 case P2C_BAR_0:\r
9eb130ff 1958 PciIo->Pci.Write (\r
1959 PciIo,\r
1960 EfiPciIoWidthUint32,\r
1961 (Node->PciDev->PciBar[Node->Bar]).Offset,\r
1962 1,\r
1963 &Address\r
1964 );\r
ead42efc 1965\r
1966 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
1967 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
1968 break;\r
1969\r
1970 case P2C_MEM_1:\r
9eb130ff 1971 PciIo->Pci.Write (\r
1972 PciIo,\r
1973 EfiPciIoWidthUint32,\r
1974 PCI_CARD_MEMORY_BASE_0,\r
1975 1,\r
1976 &Address\r
1977 );\r
ead42efc 1978\r
1979 TempAddress = Address + Node->Length - 1;\r
9eb130ff 1980 PciIo->Pci.Write (\r
1981 PciIo,\r
1982 EfiPciIoWidthUint32,\r
1983 PCI_CARD_MEMORY_LIMIT_0,\r
1984 1,\r
1985 &TempAddress\r
1986 );\r
ead42efc 1987\r
1988 if (Node->ResType == PciBarTypeMem32) {\r
ead42efc 1989 //\r
1990 // Set non-prefetchable bit\r
1991 //\r
9eb130ff 1992 PciIo->Pci.Read (\r
1993 PciIo,\r
1994 EfiPciIoWidthUint16,\r
1995 PCI_CARD_BRIDGE_CONTROL,\r
1996 1,\r
1997 &BridgeControl\r
1998 );\r
8e8227d1 1999\r
2000 BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
9eb130ff 2001 PciIo->Pci.Write (\r
2002 PciIo,\r
2003 EfiPciIoWidthUint16,\r
2004 PCI_CARD_BRIDGE_CONTROL,\r
2005 1,\r
2006 &BridgeControl\r
2007 );\r
ead42efc 2008\r
2009 } else {\r
ead42efc 2010 //\r
2011 // Set pre-fetchable bit\r
2012 //\r
9eb130ff 2013 PciIo->Pci.Read (\r
2014 PciIo,\r
2015 EfiPciIoWidthUint16,\r
2016 PCI_CARD_BRIDGE_CONTROL,\r
2017 1,\r
2018 &BridgeControl\r
2019 );\r
8e8227d1 2020\r
2021 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;\r
9eb130ff 2022 PciIo->Pci.Write (\r
2023 PciIo,\r
2024 EfiPciIoWidthUint16,\r
2025 PCI_CARD_BRIDGE_CONTROL,\r
2026 1,\r
2027 &BridgeControl\r
2028 );\r
ead42efc 2029 }\r
2030\r
2031 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
2032 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
2033 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
2034\r
2035 break;\r
2036\r
2037 case P2C_MEM_2:\r
9eb130ff 2038 PciIo->Pci.Write (\r
2039 PciIo,\r
2040 EfiPciIoWidthUint32,\r
2041 PCI_CARD_MEMORY_BASE_1,\r
2042 1,\r
2043 &Address\r
2044 );\r
ead42efc 2045\r
2046 TempAddress = Address + Node->Length - 1;\r
2047\r
9eb130ff 2048 PciIo->Pci.Write (\r
2049 PciIo,\r
2050 EfiPciIoWidthUint32,\r
2051 PCI_CARD_MEMORY_LIMIT_1,\r
2052 1,\r
2053 &TempAddress\r
2054 );\r
ead42efc 2055\r
2056 if (Node->ResType == PciBarTypeMem32) {\r
2057\r
2058 //\r
2059 // Set non-prefetchable bit\r
2060 //\r
9eb130ff 2061 PciIo->Pci.Read (\r
2062 PciIo,\r
2063 EfiPciIoWidthUint16,\r
2064 PCI_CARD_BRIDGE_CONTROL,\r
2065 1,\r
2066 &BridgeControl\r
2067 );\r
8e8227d1 2068\r
2069 BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);\r
9eb130ff 2070 PciIo->Pci.Write (\r
2071 PciIo,\r
2072 EfiPciIoWidthUint16,\r
2073 PCI_CARD_BRIDGE_CONTROL,\r
2074 1,\r
2075 &BridgeControl\r
2076 );\r
8e8227d1 2077\r
ead42efc 2078 } else {\r
2079\r
2080 //\r
2081 // Set pre-fetchable bit\r
2082 //\r
9eb130ff 2083 PciIo->Pci.Read (\r
2084 PciIo,\r
2085 EfiPciIoWidthUint16,\r
2086 PCI_CARD_BRIDGE_CONTROL,\r
2087 1,\r
2088 &BridgeControl\r
2089 );\r
8e8227d1 2090\r
2091 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;\r
9eb130ff 2092 PciIo->Pci.Write (\r
2093 PciIo,\r
2094 EfiPciIoWidthUint16,\r
2095 PCI_CARD_BRIDGE_CONTROL,\r
2096 1,\r
2097 &BridgeControl\r
2098 );\r
ead42efc 2099 }\r
2100\r
2101 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
2102 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
2103 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
2104 break;\r
2105\r
2106 case P2C_IO_1:\r
9eb130ff 2107 PciIo->Pci.Write (\r
2108 PciIo,\r
2109 EfiPciIoWidthUint32,\r
2110 PCI_CARD_IO_BASE_0_LOWER,\r
2111 1,\r
2112 &Address\r
2113 );\r
8e8227d1 2114\r
ead42efc 2115 TempAddress = Address + Node->Length - 1;\r
9eb130ff 2116 PciIo->Pci.Write (\r
2117 PciIo,\r
2118 EfiPciIoWidthUint32,\r
2119 PCI_CARD_IO_LIMIT_0_LOWER,\r
2120 1,\r
2121 &TempAddress\r
2122 );\r
ead42efc 2123\r
2124 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
2125 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
2126 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
2127\r
2128 break;\r
2129\r
2130 case P2C_IO_2:\r
9eb130ff 2131 PciIo->Pci.Write (\r
2132 PciIo,\r
2133 EfiPciIoWidthUint32,\r
2134 PCI_CARD_IO_BASE_1_LOWER,\r
2135 1,\r
2136 &Address\r
2137 );\r
ead42efc 2138\r
2139 TempAddress = Address + Node->Length - 1;\r
9eb130ff 2140 PciIo->Pci.Write (\r
2141 PciIo,\r
2142 EfiPciIoWidthUint32,\r
2143 PCI_CARD_IO_LIMIT_1_LOWER,\r
2144 1,\r
2145 &TempAddress\r
2146 );\r
ead42efc 2147\r
2148 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;\r
2149 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;\r
2150 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;\r
2151 break;\r
2152\r
2153 default:\r
2154 break;\r
2155 }\r
ead42efc 2156}\r
2157\r
57076f45 2158/**\r
2159 Create padding resource node.\r
8e8227d1 2160\r
eeefcb9d 2161 @param PciDev Pci device instance.\r
8e8227d1 2162 @param IoNode Resource info node for IO.\r
eeefcb9d 2163 @param Mem32Node Resource info node for 32-bit memory.\r
8e8227d1 2164 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.\r
eeefcb9d 2165 @param Mem64Node Resource info node for 64-bit memory.\r
8e8227d1 2166 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.\r
57076f45 2167\r
2168**/\r
8e8227d1 2169VOID\r
ead42efc 2170ApplyResourcePadding (\r
8e8227d1 2171 IN PCI_IO_DEVICE *PciDev,\r
2172 IN PCI_RESOURCE_NODE *IoNode,\r
2173 IN PCI_RESOURCE_NODE *Mem32Node,\r
2174 IN PCI_RESOURCE_NODE *PMem32Node,\r
2175 IN PCI_RESOURCE_NODE *Mem64Node,\r
2176 IN PCI_RESOURCE_NODE *PMem64Node\r
ead42efc 2177 )\r
ead42efc 2178{\r
2179 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;\r
2180 PCI_RESOURCE_NODE *Node;\r
2181 UINT8 DummyBarIndex;\r
2182\r
2183 DummyBarIndex = 0;\r
2184 Ptr = PciDev->ResourcePaddingDescriptors;\r
2185\r
2186 while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {\r
2187\r
2188 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {\r
2189 if (Ptr->AddrLen != 0) {\r
2190\r
2191 Node = CreateResourceNode (\r
2192 PciDev,\r
2193 Ptr->AddrLen,\r
2194 Ptr->AddrRangeMax,\r
2195 DummyBarIndex,\r
2196 PciBarTypeIo16,\r
2197 PciResUsagePadding\r
2198 );\r
2199 InsertResourceNode (\r
2200 IoNode,\r
2201 Node\r
2202 );\r
2203 }\r
2204\r
2205 Ptr++;\r
2206 continue;\r
2207 }\r
2208\r
2209 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
2210\r
2211 if (Ptr->AddrSpaceGranularity == 32) {\r
2212\r
2213 //\r
2214 // prefechable\r
2215 //\r
2216 if (Ptr->SpecificFlag == 0x6) {\r
5326528b 2217 if (Ptr->AddrLen != 0) {\r
ead42efc 2218 Node = CreateResourceNode (\r
2219 PciDev,\r
2220 Ptr->AddrLen,\r
2221 Ptr->AddrRangeMax,\r
2222 DummyBarIndex,\r
2223 PciBarTypePMem32,\r
2224 PciResUsagePadding\r
2225 );\r
2226 InsertResourceNode (\r
2227 PMem32Node,\r
2228 Node\r
2229 );\r
2230 }\r
2231\r
2232 Ptr++;\r
2233 continue;\r
2234 }\r
2235\r
2236 //\r
2237 // Non-prefechable\r
2238 //\r
2239 if (Ptr->SpecificFlag == 0) {\r
5326528b 2240 if (Ptr->AddrLen != 0) {\r
ead42efc 2241 Node = CreateResourceNode (\r
2242 PciDev,\r
2243 Ptr->AddrLen,\r
2244 Ptr->AddrRangeMax,\r
2245 DummyBarIndex,\r
2246 PciBarTypeMem32,\r
2247 PciResUsagePadding\r
2248 );\r
2249 InsertResourceNode (\r
2250 Mem32Node,\r
2251 Node\r
2252 );\r
2253 }\r
2254\r
2255 Ptr++;\r
2256 continue;\r
2257 }\r
2258 }\r
2259\r
2260 if (Ptr->AddrSpaceGranularity == 64) {\r
2261\r
2262 //\r
2263 // prefechable\r
2264 //\r
2265 if (Ptr->SpecificFlag == 0x6) {\r
5326528b 2266 if (Ptr->AddrLen != 0) {\r
ead42efc 2267 Node = CreateResourceNode (\r
2268 PciDev,\r
2269 Ptr->AddrLen,\r
2270 Ptr->AddrRangeMax,\r
2271 DummyBarIndex,\r
2272 PciBarTypePMem64,\r
2273 PciResUsagePadding\r
2274 );\r
2275 InsertResourceNode (\r
2276 PMem64Node,\r
2277 Node\r
2278 );\r
2279 }\r
2280\r
2281 Ptr++;\r
2282 continue;\r
2283 }\r
2284\r
2285 //\r
2286 // Non-prefechable\r
2287 //\r
2288 if (Ptr->SpecificFlag == 0) {\r
5326528b 2289 if (Ptr->AddrLen != 0) {\r
ead42efc 2290 Node = CreateResourceNode (\r
2291 PciDev,\r
2292 Ptr->AddrLen,\r
2293 Ptr->AddrRangeMax,\r
2294 DummyBarIndex,\r
2295 PciBarTypeMem64,\r
2296 PciResUsagePadding\r
2297 );\r
2298 InsertResourceNode (\r
2299 Mem64Node,\r
2300 Node\r
2301 );\r
2302 }\r
2303\r
2304 Ptr++;\r
2305 continue;\r
2306 }\r
2307 }\r
2308 }\r
2309\r
2310 Ptr++;\r
2311 }\r
ead42efc 2312}\r
2313\r
57076f45 2314/**\r
8e8227d1 2315 Get padding resource for PCI-PCI bridge.\r
2316\r
2317 @param PciIoDevice PCI-PCI bridge device instance.\r
57076f45 2318\r
8e8227d1 2319 @note Feature flag PcdPciBusHotplugDeviceSupport determines\r
2320 whether need to pad resource for them.\r
57076f45 2321**/\r
ead42efc 2322VOID\r
2323GetResourcePaddingPpb (\r
2324 IN PCI_IO_DEVICE *PciIoDevice\r
2325 )\r
ead42efc 2326{\r
8e8227d1 2327 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {\r
ead42efc 2328 if (PciIoDevice->ResourcePaddingDescriptors == NULL) {\r
2329 GetResourcePaddingForHpb (PciIoDevice);\r
2330 }\r
2331 }\r
2332}\r
57076f45 2333\r