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