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