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