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