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
1010VOID
1012 IN PCI_IO_DEVICE *Bridge,
1013 IN PCI_RESOURCE_NODE *Mem32Node,
1014 IN PCI_RESOURCE_NODE *PMem32Node,
1015 IN PCI_RESOURCE_NODE *Mem64Node,
1016 IN PCI_RESOURCE_NODE *PMem64Node
1017 )
1018{
1019 PCI_IO_DEVICE *PciIoDevice;
1020 LIST_ENTRY *ChildDeviceLink;
1021 LIST_ENTRY *ChildNodeLink;
1022 LIST_ENTRY *NextChildNodeLink;
1023 PCI_RESOURCE_NODE *ResourceNode;
1024
1025 if (FeaturePcdGet (PcdPciDegradeResourceForOptionRom)) {
1026 //
1027 // If any child device has both option ROM and 64-bit BAR, degrade its PMEM64/MEM64
1028 // requests in case that if a legacy option ROM image can not access 64-bit resources.
1029 //
1030 ChildDeviceLink = Bridge->ChildList.ForwardLink;
1031 while (ChildDeviceLink != NULL && ChildDeviceLink != &Bridge->ChildList) {
1032 PciIoDevice = PCI_IO_DEVICE_FROM_LINK (ChildDeviceLink);
1033 if (PciIoDevice->RomSize != 0) {
1034 if (!IsListEmpty (&Mem64Node->ChildList)) {
1035 ChildNodeLink = Mem64Node->ChildList.ForwardLink;
1036 while (ChildNodeLink != &Mem64Node->ChildList) {
1037 ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);
1038 NextChildNodeLink = ChildNodeLink->ForwardLink;
1039
1040 if ((ResourceNode->PciDev == PciIoDevice) &&
1041 (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)
1042 )
1043 {
1044 RemoveEntryList (ChildNodeLink);
1045 InsertResourceNode (Mem32Node, ResourceNode);
1046 }
1047
1048 ChildNodeLink = NextChildNodeLink;
1049 }
1050 }
1051
1052 if (!IsListEmpty (&PMem64Node->ChildList)) {
1053 ChildNodeLink = PMem64Node->ChildList.ForwardLink;
1054 while (ChildNodeLink != &PMem64Node->ChildList) {
1055 ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);
1056 NextChildNodeLink = ChildNodeLink->ForwardLink;
1057
1058 if ((ResourceNode->PciDev == PciIoDevice) &&
1059 (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)
1060 )
1061 {
1062 RemoveEntryList (ChildNodeLink);
1063 InsertResourceNode (PMem32Node, ResourceNode);
1064 }
1065
1066 ChildNodeLink = NextChildNodeLink;
1067 }
1068 }
1069 }
1070
1071 ChildDeviceLink = ChildDeviceLink->ForwardLink;
1072 }
1073 }
1074
1075 //
1076 // If firmware is in 32-bit mode,
1077 // then degrade PMEM64/MEM64 requests
1078 //
1079 if (sizeof (UINTN) <= 4) {
1081 Mem32Node,
1082 Mem64Node,
1083 TRUE
1084 );
1085
1087 PMem32Node,
1088 PMem64Node,
1089 TRUE
1090 );
1091 } else {
1092 //
1093 // if the bridge does not support MEM64, degrade MEM64 to MEM32
1094 //
1095 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {
1097 Mem32Node,
1098 Mem64Node,
1099 TRUE
1100 );
1101 }
1102
1103 //
1104 // if the bridge does not support PMEM64, degrade PMEM64 to PMEM32
1105 //
1106 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {
1108 PMem32Node,
1109 PMem64Node,
1110 TRUE
1111 );
1112 }
1113
1114 //
1115 // if both PMEM64 and PMEM32 requests from child devices, which can not be satisfied
1116 // by a P2P bridge simultaneously, keep PMEM64 and degrade PMEM32 to MEM32.
1117 //
1118 if (!IsListEmpty (&PMem64Node->ChildList) && (Bridge->Parent != NULL)) {
1120 Mem32Node,
1121 PMem32Node,
1122 TRUE
1123 );
1124 }
1125 }
1126
1127 //
1128 // If bridge doesn't support Pmem32
1129 // degrade it to mem32
1130 //
1131 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {
1133 Mem32Node,
1134 PMem32Node,
1135 TRUE
1136 );
1137 }
1138
1139 //
1140 // if root bridge supports combined Pmem Mem decoding
1141 // merge these two type of resource
1142 //
1143 if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {
1145 Mem32Node,
1146 PMem32Node,
1147 FALSE
1148 );
1149
1150 //
1151 // No need to check if to degrade MEM64 after merge, because
1152 // if there are PMEM64 still here, 64-bit decode should be supported
1153 // by the root bride.
1154 //
1156 Mem64Node,
1157 PMem64Node,
1158 FALSE
1159 );
1160 }
1161}
1162
1173BOOLEAN
1175 IN PCI_IO_DEVICE *Bridge,
1176 IN UINT32 Decode
1177 )
1178{
1179 if (((Bridge->Decodes) & Decode) != 0) {
1180 return TRUE;
1181 }
1182
1183 return FALSE;
1184}
1185
1200 IN UINT64 Base,
1201 IN PCI_RESOURCE_NODE *Bridge
1202 )
1203{
1204 LIST_ENTRY *CurrentLink;
1205 PCI_RESOURCE_NODE *Node;
1206 EFI_STATUS Status;
1207
1208 if (Base == gAllOne) {
1209 return EFI_OUT_OF_RESOURCES;
1210 }
1211
1212 CurrentLink = Bridge->ChildList.ForwardLink;
1213
1214 while (CurrentLink != &Bridge->ChildList) {
1215 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
1216
1217 if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {
1218 if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
1219 //
1220 // Program the PCI Card Bus device
1221 //
1222 ProgramP2C (Base, Node);
1223 } else {
1224 //
1225 // Program the PCI device BAR
1226 //
1227 ProgramBar (Base, Node);
1228 }
1229 } else {
1230 //
1231 // Program the PCI devices under this bridge
1232 //
1233 Status = ProgramResource (Base + Node->Offset, Node);
1234 if (EFI_ERROR (Status)) {
1235 return Status;
1236 }
1237
1238 ProgramPpbApperture (Base, Node);
1239 }
1240
1241 CurrentLink = CurrentLink->ForwardLink;
1242 }
1243
1244 return EFI_SUCCESS;
1245}
1246
1254VOID
1256 IN UINT64 Base,
1257 IN PCI_RESOURCE_NODE *Node
1258 )
1259{
1260 EFI_PCI_IO_PROTOCOL *PciIo;
1261 UINT64 Address;
1262 UINT32 Address32;
1263
1264 ASSERT (Node->Bar < PCI_MAX_BAR);
1265
1266 //
1267 // Check VF BAR
1268 //
1269 if (Node->Virtual) {
1270 ProgramVfBar (Base, Node);
1271 return;
1272 }
1273
1274 Address = 0;
1275 PciIo = &(Node->PciDev->PciIo);
1276
1277 Address = Base + Node->Offset;
1278
1279 //
1280 // Indicate pci bus driver has allocated
1281 // resource for this device
1282 // It might be a temporary solution here since
1283 // pci device could have multiple bar
1284 //
1285 Node->PciDev->Allocated = TRUE;
1286
1287 switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
1288 case PciBarTypeIo16:
1289 case PciBarTypeIo32:
1290 case PciBarTypeMem32:
1291 case PciBarTypePMem32:
1292
1293 PciIo->Pci.Write (
1294 PciIo,
1295 EfiPciIoWidthUint32,
1296 (Node->PciDev->PciBar[Node->Bar]).Offset,
1297 1,
1298 &Address
1299 );
1300 //
1301 // Continue to the case PciBarTypeOpRom to set the BaseAddress.
1302 // PciBarTypeOpRom is a virtual BAR only in root bridge, to capture
1303 // the MEM32 resource requirement for Option ROM shadow.
1304 //
1305
1306 case PciBarTypeOpRom:
1307 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1308
1309 break;
1310
1311 case PciBarTypeMem64:
1312 case PciBarTypePMem64:
1313
1314 Address32 = (UINT32)(Address & 0x00000000FFFFFFFF);
1315
1316 PciIo->Pci.Write (
1317 PciIo,
1318 EfiPciIoWidthUint32,
1319 (Node->PciDev->PciBar[Node->Bar]).Offset,
1320 1,
1321 &Address32
1322 );
1323
1324 Address32 = (UINT32)RShiftU64 (Address, 32);
1325
1326 PciIo->Pci.Write (
1327 PciIo,
1328 EfiPciIoWidthUint32,
1329 (UINT8)((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
1330 1,
1331 &Address32
1332 );
1333
1334 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1335
1336 break;
1337
1338 default:
1339 break;
1340 }
1341}
1342
1352 IN UINT64 Base,
1353 IN PCI_RESOURCE_NODE *Node
1354 )
1355{
1356 EFI_PCI_IO_PROTOCOL *PciIo;
1357 UINT64 Address;
1358 UINT32 Address32;
1359
1360 ASSERT (Node->Bar < PCI_MAX_BAR);
1361 ASSERT (Node->Virtual);
1362
1363 Address = 0;
1364 PciIo = &(Node->PciDev->PciIo);
1365
1366 Address = Base + Node->Offset;
1367
1368 //
1369 // Indicate pci bus driver has allocated
1370 // resource for this device
1371 // It might be a temporary solution here since
1372 // pci device could have multiple bar
1373 //
1374 Node->PciDev->Allocated = TRUE;
1375
1376 switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {
1377 case PciBarTypeMem32:
1378 case PciBarTypePMem32:
1379
1380 PciIo->Pci.Write (
1381 PciIo,
1382 EfiPciIoWidthUint32,
1383 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
1384 1,
1385 &Address
1386 );
1387
1388 Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
1389 break;
1390
1391 case PciBarTypeMem64:
1392 case PciBarTypePMem64:
1393
1394 Address32 = (UINT32)(Address & 0x00000000FFFFFFFF);
1395
1396 PciIo->Pci.Write (
1397 PciIo,
1398 EfiPciIoWidthUint32,
1399 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
1400 1,
1401 &Address32
1402 );
1403
1404 Address32 = (UINT32)RShiftU64 (Address, 32);
1405
1406 PciIo->Pci.Write (
1407 PciIo,
1408 EfiPciIoWidthUint32,
1409 ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),
1410 1,
1411 &Address32
1412 );
1413
1414 Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
1415 break;
1416
1417 case PciBarTypeIo16:
1418 case PciBarTypeIo32:
1419 break;
1420
1421 default:
1422 break;
1423 }
1424
1425 return EFI_SUCCESS;
1426}
1427
1435VOID
1437 IN UINT64 Base,
1438 IN PCI_RESOURCE_NODE *Node
1439 )
1440{
1441 EFI_PCI_IO_PROTOCOL *PciIo;
1442 UINT64 Address;
1443 UINT32 Address32;
1444
1445 Address = 0;
1446 //
1447 // If no device resource of this PPB, return anyway
1448 // Aperture is set default in the initialization code
1449 //
1450 if ((Node->Length == 0) || (Node->ResourceUsage == PciResUsagePadding)) {
1451 //
1452 // For padding resource node, just ignore when programming
1453 //
1454 return;
1455 }
1456
1457 PciIo = &(Node->PciDev->PciIo);
1458 Address = Base + Node->Offset;
1459
1460 //
1461 // Indicate the PPB resource has been allocated
1462 //
1463 Node->PciDev->Allocated = TRUE;
1464
1465 switch (Node->Bar) {
1466 case PPB_BAR_0:
1467 case PPB_BAR_1:
1468 switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
1469 case PciBarTypeIo16:
1470 case PciBarTypeIo32:
1471 case PciBarTypeMem32:
1472 case PciBarTypePMem32:
1473
1474 PciIo->Pci.Write (
1475 PciIo,
1476 EfiPciIoWidthUint32,
1477 (Node->PciDev->PciBar[Node->Bar]).Offset,
1478 1,
1479 &Address
1480 );
1481
1482 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1483 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1484 break;
1485
1486 case PciBarTypeMem64:
1487 case PciBarTypePMem64:
1488
1489 Address32 = (UINT32)(Address & 0x00000000FFFFFFFF);
1490
1491 PciIo->Pci.Write (
1492 PciIo,
1493 EfiPciIoWidthUint32,
1494 (Node->PciDev->PciBar[Node->Bar]).Offset,
1495 1,
1496 &Address32
1497 );
1498
1499 Address32 = (UINT32)RShiftU64 (Address, 32);
1500
1501 PciIo->Pci.Write (
1502 PciIo,
1503 EfiPciIoWidthUint32,
1504 (UINT8)((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
1505 1,
1506 &Address32
1507 );
1508
1509 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1510 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1511 break;
1512
1513 default:
1514 break;
1515 }
1516
1517 break;
1518
1519 case PPB_IO_RANGE:
1520
1521 Address32 = ((UINT32)(Address)) >> 8;
1522 PciIo->Pci.Write (
1523 PciIo,
1524 EfiPciIoWidthUint8,
1525 0x1C,
1526 1,
1527 &Address32
1528 );
1529
1530 Address32 >>= 8;
1531 PciIo->Pci.Write (
1532 PciIo,
1533 EfiPciIoWidthUint16,
1534 0x30,
1535 1,
1536 &Address32
1537 );
1538
1539 Address32 = (UINT32)(Address + Node->Length - 1);
1540 Address32 = ((UINT32)(Address32)) >> 8;
1541 PciIo->Pci.Write (
1542 PciIo,
1543 EfiPciIoWidthUint8,
1544 0x1D,
1545 1,
1546 &Address32
1547 );
1548
1549 Address32 >>= 8;
1550 PciIo->Pci.Write (
1551 PciIo,
1552 EfiPciIoWidthUint16,
1553 0x32,
1554 1,
1555 &Address32
1556 );
1557
1558 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1559 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1560 break;
1561
1562 case PPB_MEM32_RANGE:
1563
1564 Address32 = ((UINT32)(Address)) >> 16;
1565 PciIo->Pci.Write (
1566 PciIo,
1567 EfiPciIoWidthUint16,
1568 0x20,
1569 1,
1570 &Address32
1571 );
1572
1573 Address32 = (UINT32)(Address + Node->Length - 1);
1574 Address32 = ((UINT32)(Address32)) >> 16;
1575 PciIo->Pci.Write (
1576 PciIo,
1577 EfiPciIoWidthUint16,
1578 0x22,
1579 1,
1580 &Address32
1581 );
1582
1583 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1584 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1585 break;
1586
1587 case PPB_PMEM32_RANGE:
1588 case PPB_PMEM64_RANGE:
1589
1590 Address32 = ((UINT32)(Address)) >> 16;
1591 PciIo->Pci.Write (
1592 PciIo,
1593 EfiPciIoWidthUint16,
1594 0x24,
1595 1,
1596 &Address32
1597 );
1598
1599 Address32 = (UINT32)(Address + Node->Length - 1);
1600 Address32 = ((UINT32)(Address32)) >> 16;
1601 PciIo->Pci.Write (
1602 PciIo,
1603 EfiPciIoWidthUint16,
1604 0x26,
1605 1,
1606 &Address32
1607 );
1608
1609 Address32 = (UINT32)RShiftU64 (Address, 32);
1610 PciIo->Pci.Write (
1611 PciIo,
1612 EfiPciIoWidthUint32,
1613 0x28,
1614 1,
1615 &Address32
1616 );
1617
1618 Address32 = (UINT32)RShiftU64 ((Address + Node->Length - 1), 32);
1619 PciIo->Pci.Write (
1620 PciIo,
1621 EfiPciIoWidthUint32,
1622 0x2C,
1623 1,
1624 &Address32
1625 );
1626
1627 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1628 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1629 break;
1630
1631 default:
1632 break;
1633 }
1634}
1635
1644VOID
1646 IN PCI_IO_DEVICE *PciDevice,
1647 IN UINT32 OptionRomBase,
1648 IN BOOLEAN Enable
1649 )
1650{
1651 PCI_IO_DEVICE *Parent;
1652 EFI_PCI_IO_PROTOCOL *PciIo;
1653 UINT16 Base;
1654 UINT16 Limit;
1655
1656 //
1657 // For root bridge, just return.
1658 //
1659 Parent = PciDevice->Parent;
1660 while (Parent != NULL) {
1661 if (!IS_PCI_BRIDGE (&Parent->Pci)) {
1662 break;
1663 }
1664
1665 PciIo = &Parent->PciIo;
1666
1667 //
1668 // Program PPB to only open a single <= 16MB aperture
1669 //
1670 if (Enable) {
1671 //
1672 // Only cover MMIO for Option ROM.
1673 //
1674 Base = (UINT16)(OptionRomBase >> 16);
1675 Limit = (UINT16)((OptionRomBase + PciDevice->RomSize - 1) >> 16);
1676 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), 1, &Base);
1677 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);
1678
1680 } else {
1681 //
1682 // Cover 32bit MMIO for devices below the bridge.
1683 //
1684 if (Parent->PciBar[PPB_MEM32_RANGE].Length == 0) {
1685 //
1686 // When devices under the bridge contains Option ROM and doesn't require 32bit MMIO.
1687 //
1688 Base = (UINT16)gAllOne;
1689 Limit = (UINT16)gAllZero;
1690 } else {
1691 Base = (UINT16)((UINT32)Parent->PciBar[PPB_MEM32_RANGE].BaseAddress >> 16);
1692 Limit = (UINT16)((UINT32)(Parent->PciBar[PPB_MEM32_RANGE].BaseAddress
1693 + Parent->PciBar[PPB_MEM32_RANGE].Length - 1) >> 16);
1694 }
1695
1696 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase), 1, &Base);
1697 PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);
1698
1700 }
1701
1702 Parent = Parent->Parent;
1703 }
1704}
1705
1715BOOLEAN
1717 IN PCI_RESOURCE_NODE *Bridge
1718 )
1719{
1720 if (Bridge != NULL) {
1721 if (!IsListEmpty (&Bridge->ChildList) || (Bridge->Length != 0)) {
1722 return TRUE;
1723 }
1724 }
1725
1726 return FALSE;
1727}
1728
1737VOID
1739 IN OUT PCI_RESOURCE_NODE *ResourcePool,
1740 IN PCI_BAR_TYPE ResourceType
1741 )
1742{
1743 ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
1744 ResourcePool->ResType = ResourceType;
1745 ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
1746 InitializeListHead (&ResourcePool->ChildList);
1747}
1748
1755VOID
1757 IN PCI_RESOURCE_NODE *Bridge
1758 )
1759{
1760 PCI_RESOURCE_NODE *Temp;
1761 LIST_ENTRY *CurrentLink;
1762
1763 while (!IsListEmpty (&Bridge->ChildList)) {
1764 CurrentLink = Bridge->ChildList.ForwardLink;
1765
1766 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1767 ASSERT (Temp);
1768
1769 RemoveEntryList (CurrentLink);
1770
1771 if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
1772 DestroyResourceTree (Temp);
1773 }
1774
1775 FreePool (Temp);
1776 }
1777}
1778
1790VOID
1792 IN PCI_IO_DEVICE *PciDev,
1793 IN PCI_RESOURCE_NODE *IoNode,
1794 IN PCI_RESOURCE_NODE *Mem32Node,
1795 IN PCI_RESOURCE_NODE *PMem32Node,
1796 IN PCI_RESOURCE_NODE *Mem64Node,
1797 IN PCI_RESOURCE_NODE *PMem64Node
1798 )
1799{
1800 PCI_RESOURCE_NODE *Node;
1801
1802 Node = NULL;
1803
1804 //
1805 // Memory Base/Limit Register 0
1806 // Bar 1 decodes memory range 0
1807 //
1808 Node = CreateResourceNode (
1809 PciDev,
1810 0x2000000,
1811 0x1ffffff,
1812 1,
1813 PciBarTypeMem32,
1814 PciResUsagePadding
1815 );
1816
1818 Mem32Node,
1819 Node
1820 );
1821
1822 //
1823 // Memory Base/Limit Register 1
1824 // Bar 2 decodes memory range1
1825 //
1826 Node = CreateResourceNode (
1827 PciDev,
1828 0x2000000,
1829 0x1ffffff,
1830 2,
1831 PciBarTypePMem32,
1832 PciResUsagePadding
1833 );
1834
1836 PMem32Node,
1837 Node
1838 );
1839
1840 //
1841 // Io Base/Limit
1842 // Bar 3 decodes io range 0
1843 //
1844 Node = CreateResourceNode (
1845 PciDev,
1846 0x100,
1847 0xff,
1848 3,
1849 PciBarTypeIo16,
1850 PciResUsagePadding
1851 );
1852
1854 IoNode,
1855 Node
1856 );
1857
1858 //
1859 // Io Base/Limit
1860 // Bar 4 decodes io range 0
1861 //
1862 Node = CreateResourceNode (
1863 PciDev,
1864 0x100,
1865 0xff,
1866 4,
1867 PciBarTypeIo16,
1868 PciResUsagePadding
1869 );
1870
1872 IoNode,
1873 Node
1874 );
1875}
1876
1884VOID
1886 IN UINT64 Base,
1887 IN PCI_RESOURCE_NODE *Node
1888 )
1889{
1890 EFI_PCI_IO_PROTOCOL *PciIo;
1891 UINT64 Address;
1892 UINT64 TempAddress;
1893 UINT16 BridgeControl;
1894
1895 Address = 0;
1896 PciIo = &(Node->PciDev->PciIo);
1897
1898 Address = Base + Node->Offset;
1899
1900 //
1901 // Indicate pci bus driver has allocated
1902 // resource for this device
1903 // It might be a temporary solution here since
1904 // pci device could have multiple bar
1905 //
1906 Node->PciDev->Allocated = TRUE;
1907
1908 switch (Node->Bar) {
1909 case P2C_BAR_0:
1910 PciIo->Pci.Write (
1911 PciIo,
1912 EfiPciIoWidthUint32,
1913 (Node->PciDev->PciBar[Node->Bar]).Offset,
1914 1,
1915 &Address
1916 );
1917
1918 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1919 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1920 break;
1921
1922 case P2C_MEM_1:
1923 PciIo->Pci.Write (
1924 PciIo,
1925 EfiPciIoWidthUint32,
1926 PCI_CARD_MEMORY_BASE_0,
1927 1,
1928 &Address
1929 );
1930
1931 TempAddress = Address + Node->Length - 1;
1932 PciIo->Pci.Write (
1933 PciIo,
1934 EfiPciIoWidthUint32,
1935 PCI_CARD_MEMORY_LIMIT_0,
1936 1,
1937 &TempAddress
1938 );
1939
1940 if (Node->ResType == PciBarTypeMem32) {
1941 //
1942 // Set non-prefetchable bit
1943 //
1944 PciIo->Pci.Read (
1945 PciIo,
1946 EfiPciIoWidthUint16,
1947 PCI_CARD_BRIDGE_CONTROL,
1948 1,
1949 &BridgeControl
1950 );
1951
1952 BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
1953 PciIo->Pci.Write (
1954 PciIo,
1955 EfiPciIoWidthUint16,
1956 PCI_CARD_BRIDGE_CONTROL,
1957 1,
1958 &BridgeControl
1959 );
1960 } else {
1961 //
1962 // Set prefetchable bit
1963 //
1964 PciIo->Pci.Read (
1965 PciIo,
1966 EfiPciIoWidthUint16,
1967 PCI_CARD_BRIDGE_CONTROL,
1968 1,
1969 &BridgeControl
1970 );
1971
1972 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
1973 PciIo->Pci.Write (
1974 PciIo,
1975 EfiPciIoWidthUint16,
1976 PCI_CARD_BRIDGE_CONTROL,
1977 1,
1978 &BridgeControl
1979 );
1980 }
1981
1982 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1983 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1984 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
1985
1986 break;
1987
1988 case P2C_MEM_2:
1989 PciIo->Pci.Write (
1990 PciIo,
1991 EfiPciIoWidthUint32,
1992 PCI_CARD_MEMORY_BASE_1,
1993 1,
1994 &Address
1995 );
1996
1997 TempAddress = Address + Node->Length - 1;
1998
1999 PciIo->Pci.Write (
2000 PciIo,
2001 EfiPciIoWidthUint32,
2002 PCI_CARD_MEMORY_LIMIT_1,
2003 1,
2004 &TempAddress
2005 );
2006
2007 if (Node->ResType == PciBarTypeMem32) {
2008 //
2009 // Set non-prefetchable bit
2010 //
2011 PciIo->Pci.Read (
2012 PciIo,
2013 EfiPciIoWidthUint16,
2014 PCI_CARD_BRIDGE_CONTROL,
2015 1,
2016 &BridgeControl
2017 );
2018
2019 BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);
2020 PciIo->Pci.Write (
2021 PciIo,
2022 EfiPciIoWidthUint16,
2023 PCI_CARD_BRIDGE_CONTROL,
2024 1,
2025 &BridgeControl
2026 );
2027 } else {
2028 //
2029 // Set prefetchable bit
2030 //
2031 PciIo->Pci.Read (
2032 PciIo,
2033 EfiPciIoWidthUint16,
2034 PCI_CARD_BRIDGE_CONTROL,
2035 1,
2036 &BridgeControl
2037 );
2038
2039 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;
2040 PciIo->Pci.Write (
2041 PciIo,
2042 EfiPciIoWidthUint16,
2043 PCI_CARD_BRIDGE_CONTROL,
2044 1,
2045 &BridgeControl
2046 );
2047 }
2048
2049 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2050 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2051 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2052 break;
2053
2054 case P2C_IO_1:
2055 PciIo->Pci.Write (
2056 PciIo,
2057 EfiPciIoWidthUint32,
2058 PCI_CARD_IO_BASE_0_LOWER,
2059 1,
2060 &Address
2061 );
2062
2063 TempAddress = Address + Node->Length - 1;
2064 PciIo->Pci.Write (
2065 PciIo,
2066 EfiPciIoWidthUint32,
2067 PCI_CARD_IO_LIMIT_0_LOWER,
2068 1,
2069 &TempAddress
2070 );
2071
2072 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2073 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2074 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2075
2076 break;
2077
2078 case P2C_IO_2:
2079 PciIo->Pci.Write (
2080 PciIo,
2081 EfiPciIoWidthUint32,
2082 PCI_CARD_IO_BASE_1_LOWER,
2083 1,
2084 &Address
2085 );
2086
2087 TempAddress = Address + Node->Length - 1;
2088 PciIo->Pci.Write (
2089 PciIo,
2090 EfiPciIoWidthUint32,
2091 PCI_CARD_IO_LIMIT_1_LOWER,
2092 1,
2093 &TempAddress
2094 );
2095
2096 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2097 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2098 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2099 break;
2100
2101 default:
2102 break;
2103 }
2104}
2105
2117VOID
2119 IN PCI_IO_DEVICE *PciDev,
2120 IN PCI_RESOURCE_NODE *IoNode,
2121 IN PCI_RESOURCE_NODE *Mem32Node,
2122 IN PCI_RESOURCE_NODE *PMem32Node,
2123 IN PCI_RESOURCE_NODE *Mem64Node,
2124 IN PCI_RESOURCE_NODE *PMem64Node
2125 )
2126{
2128 PCI_RESOURCE_NODE *Node;
2129 UINT8 DummyBarIndex;
2130
2131 DummyBarIndex = 0;
2132 Ptr = PciDev->ResourcePaddingDescriptors;
2133
2134 while (((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
2135 if ((Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && (Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO)) {
2136 if (Ptr->AddrLen != 0) {
2137 Node = CreateResourceNode (
2138 PciDev,
2139 Ptr->AddrLen,
2140 Ptr->AddrRangeMax,
2141 DummyBarIndex,
2142 PciBarTypeIo16,
2143 PciResUsagePadding
2144 );
2146 IoNode,
2147 Node
2148 );
2149 }
2150
2151 Ptr++;
2152 continue;
2153 }
2154
2155 if ((Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) && (Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM)) {
2156 if (Ptr->AddrSpaceGranularity == 32) {
2157 //
2158 // prefetchable
2159 //
2160 if (Ptr->SpecificFlag == 0x6) {
2161 if (Ptr->AddrLen != 0) {
2162 Node = CreateResourceNode (
2163 PciDev,
2164 Ptr->AddrLen,
2165 Ptr->AddrRangeMax,
2166 DummyBarIndex,
2167 PciBarTypePMem32,
2168 PciResUsagePadding
2169 );
2171 PMem32Node,
2172 Node
2173 );
2174 }
2175
2176 Ptr++;
2177 continue;
2178 }
2179
2180 //
2181 // Non-prefetchable
2182 //
2183 if (Ptr->SpecificFlag == 0) {
2184 if (Ptr->AddrLen != 0) {
2185 Node = CreateResourceNode (
2186 PciDev,
2187 Ptr->AddrLen,
2188 Ptr->AddrRangeMax,
2189 DummyBarIndex,
2190 PciBarTypeMem32,
2191 PciResUsagePadding
2192 );
2194 Mem32Node,
2195 Node
2196 );
2197 }
2198
2199 Ptr++;
2200 continue;
2201 }
2202 }
2203
2204 if (Ptr->AddrSpaceGranularity == 64) {
2205 //
2206 // prefetchable
2207 //
2208 if (Ptr->SpecificFlag == 0x6) {
2209 if (Ptr->AddrLen != 0) {
2210 Node = CreateResourceNode (
2211 PciDev,
2212 Ptr->AddrLen,
2213 Ptr->AddrRangeMax,
2214 DummyBarIndex,
2215 PciBarTypePMem64,
2216 PciResUsagePadding
2217 );
2219 PMem64Node,
2220 Node
2221 );
2222 }
2223
2224 Ptr++;
2225 continue;
2226 }
2227
2228 //
2229 // Non-prefetchable
2230 //
2231 if (Ptr->SpecificFlag == 0) {
2232 if (Ptr->AddrLen != 0) {
2233 Node = CreateResourceNode (
2234 PciDev,
2235 Ptr->AddrLen,
2236 Ptr->AddrRangeMax,
2237 DummyBarIndex,
2238 PciBarTypeMem64,
2239 PciResUsagePadding
2240 );
2242 Mem64Node,
2243 Node
2244 );
2245 }
2246
2247 Ptr++;
2248 continue;
2249 }
2250 }
2251 }
2252
2253 Ptr++;
2254 }
2255}
2256
2265VOID
2267 IN PCI_IO_DEVICE *PciIoDevice
2268 )
2269{
2270 if ((gPciHotPlugInit != NULL) && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
2271 if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
2272 GetResourcePaddingForHpb (PciIoDevice);
2273 }
2274 }
2275}
UINT64 UINTN
PACKED struct @89 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 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