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