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