3 Copyright (c) 2006 - 2009, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "PciResourceSupport.h"
16 #include "PciCommand.h"
19 The function is used to skip VGA range
21 @param Start address including VGA range
22 @param Length length of VGA range.
24 @retval EFI_SUCCESS success.
38 // For legacy VGA, bit 10 to bit 15 is not decoded
43 StartOffset
= Original
& Mask
;
44 LimitOffset
= ((*Start
) + Length
- 1) & Mask
;
45 if (LimitOffset
>= VGABASE1
) {
46 *Start
= *Start
- StartOffset
+ VGALIMIT2
+ 1;
53 This function is used to skip ISA aliasing aperture.
55 @param Start address including ISA aliasing aperture.
56 @param Length length of ISA aliasing aperture.
58 @retval EFI_SUCCESS success.
61 SkipIsaAliasAperture (
73 // For legacy ISA, bit 10 to bit 15 is not decoded
78 StartOffset
= Original
& Mask
;
79 LimitOffset
= ((*Start
) + Length
- 1) & Mask
;
81 if (LimitOffset
>= ISABASE
) {
82 *Start
= *Start
- StartOffset
+ ISALIMIT
+ 1;
89 This function inserts a resource node into the resource list.
90 The resource list is sorted in descend order.
92 @param Bridge PCI resource node for bridge.
93 @param ResNode Resource node want to be inserted.
95 @retval EFI_SUCCESS Success.
99 PCI_RESOURCE_NODE
*Bridge
,
100 PCI_RESOURCE_NODE
*ResNode
103 LIST_ENTRY
*CurrentLink
;
104 PCI_RESOURCE_NODE
*Temp
;
105 UINT64 ResNodeAlignRest
;
106 UINT64 TempAlignRest
;
108 ASSERT (Bridge
!= NULL
);
109 ASSERT (ResNode
!= NULL
);
111 InsertHeadList (&Bridge
->ChildList
, &ResNode
->Link
);
113 CurrentLink
= Bridge
->ChildList
.ForwardLink
->ForwardLink
;
114 while (CurrentLink
!= &Bridge
->ChildList
) {
115 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
117 if (ResNode
->Alignment
> Temp
->Alignment
) {
119 } else if (ResNode
->Alignment
== Temp
->Alignment
) {
120 ResNodeAlignRest
= ResNode
->Length
& ResNode
->Alignment
;
121 TempAlignRest
= Temp
->Length
& Temp
->Alignment
;
122 if ((ResNodeAlignRest
== 0) || (ResNodeAlignRest
>= TempAlignRest
)) {
127 SwapListEntries (&ResNode
->Link
, CurrentLink
);
129 CurrentLink
= ResNode
->Link
.ForwardLink
;
139 This routine is used to merge two different resource tree in need of
140 resoure degradation. For example, if a upstream PPB doesn't support,
141 prefetchable memory decoding, the PCI bus driver will choose to call this function
142 to merge prefectchable memory resource list into normal memory list.
144 If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
147 @param Dst Point to destination resource tree.
148 @param Res Point to source resource tree.
149 @param TypeMerge If the TypeMerge is TRUE, Res resource type is changed to the type of
150 destination resource type.
153 @retval EFI_SUCCESS Success.
157 PCI_RESOURCE_NODE
*Dst
,
158 PCI_RESOURCE_NODE
*Res
,
163 LIST_ENTRY
*CurrentLink
;
164 PCI_RESOURCE_NODE
*Temp
;
166 ASSERT (Dst
!= NULL
);
167 ASSERT (Res
!= NULL
);
169 while (!IsListEmpty (&Res
->ChildList
)) {
170 CurrentLink
= Res
->ChildList
.ForwardLink
;
172 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
175 Temp
->ResType
= Dst
->ResType
;
178 RemoveEntryList (CurrentLink
);
179 InsertResourceNode (Dst
, Temp
);
187 This function is used to calculate the IO16 aperture
190 @param Bridge PCI resource node for bridge.
192 @retval EFI_SUCCESS Success.
195 CalculateApertureIo16 (
196 IN PCI_RESOURCE_NODE
*Bridge
201 LIST_ENTRY
*CurrentLink
;
202 PCI_RESOURCE_NODE
*Node
;
206 EFI_PCI_PLATFORM_POLICY PciPolicy
;
210 // Always assume there is ISA device and VGA device on the platform
211 // will be customized later
217 // Check PciPlatform policy
219 if (gPciPlatformProtocol
!= NULL
) {
220 Status
= gPciPlatformProtocol
->GetPlatformPolicy (
221 gPciPlatformProtocol
,
224 if (!EFI_ERROR (Status
)) {
225 if (PciPolicy
& EFI_RESERVE_ISA_IO_ALIAS
) {
228 if (PciPolicy
& EFI_RESERVE_VGA_IO_ALIAS
) {
236 if (Bridge
== NULL
) {
240 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
243 // Assume the bridge is aligned
245 while (CurrentLink
!= &Bridge
->ChildList
) {
247 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
250 // Consider the aperture alignment
252 Offset
= Aperture
& (Node
->Alignment
);
256 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - Offset
;
261 // IsaEnable and VGAEnable can not be implemented now.
262 // If both of them are enabled, then the IO resource would
263 // become too limited to meet the requirement of most of devices.
266 if (IsaEnable
|| VGAEnable
) {
267 if (!IS_PCI_BRIDGE (&(Node
->PciDev
->Pci
)) && !IS_CARDBUS_BRIDGE (&(Node
->PciDev
->Pci
))) {
269 // Check if there is need to support ISA/VGA decoding
270 // If so, we need to avoid isa/vga aliasing range
273 SkipIsaAliasAperture (
277 Offset
= Aperture
& (Node
->Alignment
);
279 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - Offset
;
281 } else if (VGAEnable
) {
286 Offset
= Aperture
& (Node
->Alignment
);
288 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - Offset
;
294 Node
->Offset
= Aperture
;
297 // Increment aperture by the length of node
299 Aperture
+= Node
->Length
;
301 CurrentLink
= CurrentLink
->ForwardLink
;
305 // At last, adjust the aperture with the bridge's
308 Offset
= Aperture
& (Bridge
->Alignment
);
311 Aperture
= Aperture
+ (Bridge
->Alignment
+ 1) - Offset
;
314 Bridge
->Length
= Aperture
;
316 // At last, adjust the bridge's alignment to the first child's alignment
317 // if the bridge has at least one child
319 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
320 if (CurrentLink
!= &Bridge
->ChildList
) {
321 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
322 if (Node
->Alignment
> Bridge
->Alignment
) {
323 Bridge
->Alignment
= Node
->Alignment
;
331 This function is used to calculate the resource aperture
332 for a given bridge device.
334 @param Bridge Give bridge device.
336 @retval EFI_SUCCESS Success.
339 CalculateResourceAperture (
340 IN PCI_RESOURCE_NODE
*Bridge
344 LIST_ENTRY
*CurrentLink
;
345 PCI_RESOURCE_NODE
*Node
;
351 if (Bridge
== NULL
) {
355 if (Bridge
->ResType
== PciBarTypeIo16
) {
356 return CalculateApertureIo16 (Bridge
);
359 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
362 // Assume the bridge is aligned
364 while (CurrentLink
!= &Bridge
->ChildList
) {
366 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
369 // Apply padding resource if available
372 Offset
= Aperture
& (Node
->Alignment
);
376 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - Offset
;
381 // Recode current aperture as a offset
382 // this offset will be used in future real allocation
384 Node
->Offset
= Aperture
;
387 // Increment aperture by the length of node
389 Aperture
+= Node
->Length
;
392 // Consider the aperture alignment
395 CurrentLink
= CurrentLink
->ForwardLink
;
399 // At last, adjust the aperture with the bridge's
402 Offset
= Aperture
& (Bridge
->Alignment
);
404 Aperture
= Aperture
+ (Bridge
->Alignment
+ 1) - Offset
;
408 // If the bridge has already padded the resource and the
409 // amount of padded resource is larger, then keep the
412 if (Bridge
->Length
< Aperture
) {
413 Bridge
->Length
= Aperture
;
417 // At last, adjust the bridge's alignment to the first child's alignment
418 // if the bridge has at least one child
420 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
421 if (CurrentLink
!= &Bridge
->ChildList
) {
422 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
423 if (Node
->Alignment
> Bridge
->Alignment
) {
424 Bridge
->Alignment
= Node
->Alignment
;
432 Get IO/Memory resource infor for given PCI device.
434 @param PciDev Pci device instance.
435 @param IoNode Resource info node for IO .
436 @param Mem32Node Resource info node for 32-bit memory.
437 @param PMem32Node Resource info node for 32-bit PMemory.
438 @param Mem64Node Resource info node for 64-bit memory.
439 @param PMem64Node Resource info node for 64-bit PMemory.
441 @retval EFI_SUCCESS Success.
444 GetResourceFromDevice (
445 PCI_IO_DEVICE
*PciDev
,
446 PCI_RESOURCE_NODE
*IoNode
,
447 PCI_RESOURCE_NODE
*Mem32Node
,
448 PCI_RESOURCE_NODE
*PMem32Node
,
449 PCI_RESOURCE_NODE
*Mem64Node
,
450 PCI_RESOURCE_NODE
*PMem64Node
455 PCI_RESOURCE_NODE
*Node
;
456 BOOLEAN ResourceRequested
;
459 ResourceRequested
= FALSE
;
461 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
463 switch ((PciDev
->PciBar
)[Index
].BarType
) {
465 case PciBarTypeMem32
:
467 Node
= CreateResourceNode (
469 (PciDev
->PciBar
)[Index
].Length
,
470 (PciDev
->PciBar
)[Index
].Alignment
,
481 ResourceRequested
= TRUE
;
484 case PciBarTypeMem64
:
486 Node
= CreateResourceNode (
488 (PciDev
->PciBar
)[Index
].Length
,
489 (PciDev
->PciBar
)[Index
].Alignment
,
500 ResourceRequested
= TRUE
;
503 case PciBarTypePMem64
:
505 Node
= CreateResourceNode (
507 (PciDev
->PciBar
)[Index
].Length
,
508 (PciDev
->PciBar
)[Index
].Alignment
,
519 ResourceRequested
= TRUE
;
522 case PciBarTypePMem32
:
524 Node
= CreateResourceNode (
526 (PciDev
->PciBar
)[Index
].Length
,
527 (PciDev
->PciBar
)[Index
].Alignment
,
537 ResourceRequested
= TRUE
;
543 Node
= CreateResourceNode (
545 (PciDev
->PciBar
)[Index
].Length
,
546 (PciDev
->PciBar
)[Index
].Alignment
,
556 ResourceRequested
= TRUE
;
559 case PciBarTypeUnknown
:
568 // If there is no resource requested from this device,
569 // then we indicate this device has been allocated naturally.
571 if (!ResourceRequested
) {
572 PciDev
->Allocated
= TRUE
;
579 This function is used to create a resource node.
581 @param PciDev Pci device instance.
582 @param Length Length of Io/Memory resource.
583 @param Alignment Alignment of resource.
584 @param Bar Bar index.
585 @param ResType Type of resource: IO/Memory.
586 @param ResUsage Resource usage.
590 IN PCI_IO_DEVICE
*PciDev
,
594 IN PCI_BAR_TYPE ResType
,
595 IN PCI_RESOURCE_USAGE ResUsage
598 PCI_RESOURCE_NODE
*Node
;
602 Node
= AllocatePool (sizeof (PCI_RESOURCE_NODE
));
603 ASSERT (Node
!= NULL
);
608 ZeroMem (Node
, sizeof (PCI_RESOURCE_NODE
));
610 Node
->Signature
= PCI_RESOURCE_SIGNATURE
;
611 Node
->PciDev
= PciDev
;
612 Node
->Length
= Length
;
613 Node
->Alignment
= Alignment
;
615 Node
->ResType
= ResType
;
616 Node
->Reserved
= FALSE
;
617 Node
->ResourceUsage
= ResUsage
;
618 InitializeListHead (&Node
->ChildList
);
623 This routine is used to extract resource request from
626 @param Bridge Pci device instance.
627 @param IoNode Resource info node for IO.
628 @param Mem32Node Resource info node for 32-bit memory.
629 @param PMem32Node Resource info node for 32-bit PMemory.
630 @param Mem64Node Resource info node for 64-bit memory.
631 @param PMem64Node Resource info node for 64-bit PMemory.
633 @retval EFI_SUCCESS Success.
637 IN PCI_IO_DEVICE
*Bridge
,
638 IN PCI_RESOURCE_NODE
*IoNode
,
639 IN PCI_RESOURCE_NODE
*Mem32Node
,
640 IN PCI_RESOURCE_NODE
*PMem32Node
,
641 IN PCI_RESOURCE_NODE
*Mem64Node
,
642 IN PCI_RESOURCE_NODE
*PMem64Node
646 PCI_RESOURCE_NODE
*IoBridge
;
647 PCI_RESOURCE_NODE
*Mem32Bridge
;
648 PCI_RESOURCE_NODE
*PMem32Bridge
;
649 PCI_RESOURCE_NODE
*Mem64Bridge
;
650 PCI_RESOURCE_NODE
*PMem64Bridge
;
651 LIST_ENTRY
*CurrentLink
;
653 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
655 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
657 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
660 // Create resource nodes for this device by scanning the
661 // Bar array in the device private data
662 // If the upstream bridge doesn't support this device,
663 // no any resource node will be created for this device
665 GetResourceFromDevice (
674 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
677 // If the device has children, create a bridge resource node for this PPB
678 // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
679 // is aligned with 4KB
680 // This device is typically a bridge device like PPB and P2C
682 IoBridge
= CreateResourceNode (
691 Mem32Bridge
= CreateResourceNode (
700 PMem32Bridge
= CreateResourceNode (
709 Mem64Bridge
= CreateResourceNode (
718 PMem64Bridge
= CreateResourceNode (
728 // Recursively create resouce map on this bridge
739 if (ResourceRequestExisted (IoBridge
)) {
745 gBS
->FreePool (IoBridge
);
750 // If there is node under this resource bridge,
751 // then calculate bridge's aperture of this type
752 // and insert it into the respective resource tree.
753 // If no, delete this resource bridge
755 if (ResourceRequestExisted (Mem32Bridge
)) {
761 gBS
->FreePool (Mem32Bridge
);
766 // If there is node under this resource bridge,
767 // then calculate bridge's aperture of this type
768 // and insert it into the respective resource tree.
769 // If no, delete this resource bridge
771 if (ResourceRequestExisted (PMem32Bridge
)) {
777 gBS
->FreePool (PMem32Bridge
);
782 // If there is node under this resource bridge,
783 // then calculate bridge's aperture of this type
784 // and insert it into the respective resource tree.
785 // If no, delete this resource bridge
787 if (ResourceRequestExisted (Mem64Bridge
)) {
793 gBS
->FreePool (Mem64Bridge
);
798 // If there is node under this resource bridge,
799 // then calculate bridge's aperture of this type
800 // and insert it into the respective resource tree.
801 // If no, delete this resource bridge
803 if (ResourceRequestExisted (PMem64Bridge
)) {
809 gBS
->FreePool (PMem64Bridge
);
816 // If it is P2C, apply hard coded resource padding
819 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
820 ResourcePaddingForCardBusBridge (
830 CurrentLink
= CurrentLink
->ForwardLink
;
834 // To do some platform specific resource padding ...
836 ResourcePaddingPolicy (
846 // Degrade resource if necessary
857 // Calculate resource aperture for this bridge device
859 CalculateResourceAperture (Mem32Node
);
860 CalculateResourceAperture (PMem32Node
);
861 CalculateResourceAperture (Mem64Node
);
862 CalculateResourceAperture (PMem64Node
);
863 CalculateResourceAperture (IoNode
);
870 This function is used to do the resource padding for a specific platform.
872 @param PciDev Pci device instance.
873 @param IoNode Resource info node for IO.
874 @param Mem32Node Resource info node for 32-bit memory.
875 @param PMem32Node Resource info node for 32-bit PMemory.
876 @param Mem64Node Resource info node for 64-bit memory.
877 @param PMem64Node Resource info node for 64-bit PMemory.
879 @retval EFI_SUCCESS Success.
882 ResourcePaddingPolicy (
883 PCI_IO_DEVICE
*PciDev
,
884 PCI_RESOURCE_NODE
*IoNode
,
885 PCI_RESOURCE_NODE
*Mem32Node
,
886 PCI_RESOURCE_NODE
*PMem32Node
,
887 PCI_RESOURCE_NODE
*Mem64Node
,
888 PCI_RESOURCE_NODE
*PMem64Node
892 // Create padding resource node
894 if (PciDev
->ResourcePaddingDescriptors
!= NULL
) {
895 ApplyResourcePadding (
910 This function is used to degrade resource if the upstream bridge
911 doesn't support certain resource. Degradation path is
912 PMEM64 -> MEM64 -> MEM32
913 PMEM64 -> PMEM32 -> MEM32
916 @param Bridge Pci device instance.
917 @param Mem32Node Resource info node for 32-bit memory.
918 @param PMem32Node Resource info node for 32-bit PMemory.
919 @param Mem64Node Resource info node for 64-bit memory.
920 @param PMem64Node Resource info node for 64-bit PMemory.
922 @retval EFI_SUCCESS Success.
926 IN PCI_IO_DEVICE
*Bridge
,
927 IN PCI_RESOURCE_NODE
*Mem32Node
,
928 IN PCI_RESOURCE_NODE
*PMem32Node
,
929 IN PCI_RESOURCE_NODE
*Mem64Node
,
930 IN PCI_RESOURCE_NODE
*PMem64Node
935 LIST_ENTRY
*CurrentLink
;
938 // For RootBridge, PPB , P2C, go recursively to traverse all its children
939 // to find if this bridge and downstream has OptionRom.
942 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
943 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
945 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
946 if (Temp
->RomSize
!= 0) {
950 CurrentLink
= CurrentLink
->ForwardLink
;
954 // If bridge doesn't support Prefetchable
955 // memory64, degrade it to Prefetchable memory32
957 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
)) {
965 // if no PMem32 request and no OptionRom request, still keep PMem64. Otherwise degrade to PMem32
967 if ((PMem32Node
!= NULL
&& (PMem32Node
->Length
!= 0 && Bridge
->Parent
!= NULL
)) || HasOprom
) {
969 // Fixed the issue that there is no resource for 64-bit (above 4G)
981 // If bridge doesn't support Mem64
982 // degrade it to mem32
984 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_MEM64_DECODE_SUPPORTED
)) {
993 // If bridge doesn't support Pmem32
994 // degrade it to mem32
996 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
)) {
1005 // if bridge supports combined Pmem Mem decoding
1006 // merge these two type of resource
1008 if (BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
)) {
1026 Test whether bridge device support decode resource
1028 @param Bridge Bridge device instance.
1029 @param Decode Decode type according to resource type.
1031 @return TRUE bridge device support decode resource.
1032 @return FALSE bridge device don't support decode resource.
1036 BridgeSupportResourceDecode (
1037 IN PCI_IO_DEVICE
*Bridge
,
1042 if (((Bridge
->Decodes
) & Decode
) != 0) {
1050 This function is used to program the resource allocated
1051 for each resource node.
1054 @param Base Base address of resource.
1055 @param Bridge Bridge device instance.
1057 @retval EFI_SUCCESS Success.
1062 IN PCI_RESOURCE_NODE
*Bridge
1065 LIST_ENTRY
*CurrentLink
;
1066 PCI_RESOURCE_NODE
*Node
;
1069 if (Base
== gAllOne
) {
1070 return EFI_OUT_OF_RESOURCES
;
1073 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1075 while (CurrentLink
!= &Bridge
->ChildList
) {
1077 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1079 if (!IS_PCI_BRIDGE (&(Node
->PciDev
->Pci
))) {
1081 if (IS_CARDBUS_BRIDGE (&(Node
->PciDev
->Pci
))) {
1082 ProgramP2C (Base
, Node
);
1084 ProgramBar (Base
, Node
);
1087 Status
= ProgramResource (Base
+ Node
->Offset
, Node
);
1089 if (EFI_ERROR (Status
)) {
1093 ProgramPpbApperture (Base
, Node
);
1096 CurrentLink
= CurrentLink
->ForwardLink
;
1103 Program Bar register.
1105 @param Base Base address for resource.
1106 @param Node Point to resoure node structure.
1108 @retval EFI_SUCCESS Success.
1113 IN PCI_RESOURCE_NODE
*Node
1116 EFI_PCI_IO_PROTOCOL
*PciIo
;
1121 PciIo
= &(Node
->PciDev
->PciIo
);
1123 Address
= Base
+ Node
->Offset
;
1126 // Indicate pci bus driver has allocated
1127 // resource for this device
1128 // It might be a temporary solution here since
1129 // pci device could have multiple bar
1131 Node
->PciDev
->Allocated
= TRUE
;
1133 ASSERT (Node
->Bar
< PCI_MAX_BAR
);
1134 switch ((Node
->PciDev
->PciBar
[Node
->Bar
]).BarType
) {
1136 case PciBarTypeIo16
:
1137 case PciBarTypeIo32
:
1138 case PciBarTypeMem32
:
1139 case PciBarTypePMem32
:
1143 EfiPciIoWidthUint32
,
1144 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1149 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1153 case PciBarTypeMem64
:
1154 case PciBarTypePMem64
:
1156 Address32
= (UINT32
) (Address
& 0x00000000FFFFFFFF);
1160 EfiPciIoWidthUint32
,
1161 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1166 Address32
= (UINT32
) RShiftU64 (Address
, 32);
1170 EfiPciIoWidthUint32
,
1171 (UINT8
) ((Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
+ 4),
1176 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1188 Program PPB apperture.
1190 @param Base Base address for resource.
1191 @param Node Point to resoure node structure.
1193 @retval EFI_SUCCESS Success.
1196 ProgramPpbApperture (
1198 IN PCI_RESOURCE_NODE
*Node
1201 EFI_PCI_IO_PROTOCOL
*PciIo
;
1207 // if no device south of this PPB, return anyway
1208 // Apperture is set default in the initialization code
1210 if (Node
->Length
== 0 || Node
->ResourceUsage
== PciResUsagePadding
) {
1212 // For padding resource node, just ignore when programming
1217 PciIo
= &(Node
->PciDev
->PciIo
);
1218 Address
= Base
+ Node
->Offset
;
1221 // Indicate the PPB resource has been allocated
1223 Node
->PciDev
->Allocated
= TRUE
;
1225 switch (Node
->Bar
) {
1231 EfiPciIoWidthUint32
,
1232 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1237 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1238 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1244 Address32
= ((UINT32
) (Address
)) >> 8;
1256 EfiPciIoWidthUint16
,
1262 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1263 Address32
= ((UINT32
) (Address32
)) >> 8;
1275 EfiPciIoWidthUint16
,
1281 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1282 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1285 case PPB_MEM32_RANGE
:
1287 Address32
= ((UINT32
) (Address
)) >> 16;
1290 EfiPciIoWidthUint16
,
1296 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1297 Address32
= ((UINT32
) (Address32
)) >> 16;
1300 EfiPciIoWidthUint16
,
1306 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1307 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1310 case PPB_PMEM32_RANGE
:
1311 case PPB_PMEM64_RANGE
:
1313 Address32
= ((UINT32
) (Address
)) >> 16;
1316 EfiPciIoWidthUint16
,
1322 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1323 Address32
= ((UINT32
) (Address32
)) >> 16;
1326 EfiPciIoWidthUint16
,
1332 Address32
= (UINT32
) RShiftU64 (Address
, 32);
1335 EfiPciIoWidthUint32
,
1341 Address32
= (UINT32
) RShiftU64 ((Address
+ Node
->Length
- 1), 32);
1344 EfiPciIoWidthUint32
,
1350 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1351 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1362 Program parent bridge for oprom.
1364 @param PciDevice Pci deivce instance.
1365 @param OptionRomBase Base address for oprom.
1366 @param Enable Enable/Disable.
1368 @retval EFI_SUCCESS Success.
1371 ProgrameUpstreamBridgeForRom (
1372 IN PCI_IO_DEVICE
*PciDevice
,
1373 IN UINT32 OptionRomBase
,
1377 PCI_IO_DEVICE
*Parent
;
1378 PCI_RESOURCE_NODE Node
;
1380 // For root bridge, just return.
1382 Parent
= PciDevice
->Parent
;
1383 ZeroMem (&Node
, sizeof (Node
));
1384 while (Parent
!= NULL
) {
1385 if (!IS_PCI_BRIDGE (&Parent
->Pci
)) {
1389 Node
.PciDev
= Parent
;
1390 Node
.Length
= PciDevice
->RomSize
;
1392 Node
.Bar
= PPB_MEM32_RANGE
;
1393 Node
.ResType
= PciBarTypeMem32
;
1397 // Program PPB to only open a single <= 16<MB apperture
1400 ProgramPpbApperture (OptionRomBase
, &Node
);
1401 PCI_ENABLE_COMMAND_REGISTER (Parent
, EFI_PCI_COMMAND_MEMORY_SPACE
);
1403 InitializePpb (Parent
);
1404 PCI_DISABLE_COMMAND_REGISTER (Parent
, EFI_PCI_COMMAND_MEMORY_SPACE
);
1407 Parent
= Parent
->Parent
;
1414 Test whether resource exists for a bridge.
1416 @param Bridge Point to resource node for a bridge.
1418 @return whether resource exists.
1421 ResourceRequestExisted (
1422 IN PCI_RESOURCE_NODE
*Bridge
1425 if (Bridge
!= NULL
) {
1426 if (!IsListEmpty (&Bridge
->ChildList
) || Bridge
->Length
!= 0) {
1435 Initialize resource pool structure.
1437 @param ResourcePool Point to resource pool structure.
1438 @param ResourceType Type of resource.
1441 InitializeResourcePool (
1442 PCI_RESOURCE_NODE
*ResourcePool
,
1443 PCI_BAR_TYPE ResourceType
1447 ZeroMem (ResourcePool
, sizeof (PCI_RESOURCE_NODE
));
1448 ResourcePool
->ResType
= ResourceType
;
1449 ResourcePool
->Signature
= PCI_RESOURCE_SIGNATURE
;
1450 InitializeListHead (&ResourcePool
->ChildList
);
1456 Get all resource information for given Pci device.
1458 @param PciDev Pci device instance.
1459 @param IoBridge Io resource node.
1460 @param Mem32Bridge 32-bit memory node.
1461 @param PMem32Bridge 32-bit Pmemory node.
1462 @param Mem64Bridge 64-bit memory node.
1463 @param PMem64Bridge 64-bit PMemory node.
1464 @param IoPool Link list header for Io resource.
1465 @param Mem32Pool Link list header for 32-bit memory.
1466 @param PMem32Pool Link list header for 32-bit Pmemory.
1467 @param Mem64Pool Link list header for 64-bit memory.
1468 @param PMem64Pool Link list header for 64-bit Pmemory.
1470 @retval EFI_SUCCESS Success.
1474 PCI_IO_DEVICE
*PciDev
,
1475 PCI_RESOURCE_NODE
**IoBridge
,
1476 PCI_RESOURCE_NODE
**Mem32Bridge
,
1477 PCI_RESOURCE_NODE
**PMem32Bridge
,
1478 PCI_RESOURCE_NODE
**Mem64Bridge
,
1479 PCI_RESOURCE_NODE
**PMem64Bridge
,
1480 PCI_RESOURCE_NODE
*IoPool
,
1481 PCI_RESOURCE_NODE
*Mem32Pool
,
1482 PCI_RESOURCE_NODE
*PMem32Pool
,
1483 PCI_RESOURCE_NODE
*Mem64Pool
,
1484 PCI_RESOURCE_NODE
*PMem64Pool
1488 PCI_RESOURCE_NODE
*Temp
;
1489 LIST_ENTRY
*CurrentLink
;
1491 CurrentLink
= IoPool
->ChildList
.ForwardLink
;
1494 // Get Io resource map
1496 while (CurrentLink
!= &IoPool
->ChildList
) {
1498 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1500 if (Temp
->PciDev
== PciDev
) {
1504 CurrentLink
= CurrentLink
->ForwardLink
;
1508 // Get Mem32 resource map
1510 CurrentLink
= Mem32Pool
->ChildList
.ForwardLink
;
1512 while (CurrentLink
!= &Mem32Pool
->ChildList
) {
1514 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1516 if (Temp
->PciDev
== PciDev
) {
1517 *Mem32Bridge
= Temp
;
1520 CurrentLink
= CurrentLink
->ForwardLink
;
1524 // Get Pmem32 resource map
1526 CurrentLink
= PMem32Pool
->ChildList
.ForwardLink
;
1528 while (CurrentLink
!= &PMem32Pool
->ChildList
) {
1530 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1532 if (Temp
->PciDev
== PciDev
) {
1533 *PMem32Bridge
= Temp
;
1536 CurrentLink
= CurrentLink
->ForwardLink
;
1540 // Get Mem64 resource map
1542 CurrentLink
= Mem64Pool
->ChildList
.ForwardLink
;
1544 while (CurrentLink
!= &Mem64Pool
->ChildList
) {
1546 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1548 if (Temp
->PciDev
== PciDev
) {
1549 *Mem64Bridge
= Temp
;
1552 CurrentLink
= CurrentLink
->ForwardLink
;
1556 // Get Pmem64 resource map
1558 CurrentLink
= PMem64Pool
->ChildList
.ForwardLink
;
1560 while (CurrentLink
!= &PMem64Pool
->ChildList
) {
1562 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1564 if (Temp
->PciDev
== PciDev
) {
1565 *PMem64Bridge
= Temp
;
1568 CurrentLink
= CurrentLink
->ForwardLink
;
1575 Destory given resource tree.
1577 @param Bridge root node of resource tree.
1579 @retval EFI_SUCCESS Success.
1582 DestroyResourceTree (
1583 IN PCI_RESOURCE_NODE
*Bridge
1586 PCI_RESOURCE_NODE
*Temp
;
1587 LIST_ENTRY
*CurrentLink
;
1589 while (!IsListEmpty (&Bridge
->ChildList
)) {
1591 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1593 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1595 RemoveEntryList (CurrentLink
);
1597 if (IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
))) {
1598 DestroyResourceTree (Temp
);
1601 gBS
->FreePool (Temp
);
1608 Record the reserved resource and insert to reserved list.
1610 @param Base Base address of reserved resourse.
1611 @param Length Length of reserved resource.
1612 @param ResType Resource type.
1613 @param Bridge Pci device instance.
1616 RecordReservedResource (
1619 IN PCI_BAR_TYPE ResType
,
1620 IN PCI_IO_DEVICE
*Bridge
1623 PCI_RESERVED_RESOURCE_LIST
*ReservedNode
;
1625 ReservedNode
= AllocatePool (sizeof (PCI_RESERVED_RESOURCE_LIST
));
1626 if (ReservedNode
== NULL
) {
1627 return EFI_OUT_OF_RESOURCES
;
1630 ReservedNode
->Signature
= RESERVED_RESOURCE_SIGNATURE
;
1631 ReservedNode
->Node
.Base
= Base
;
1632 ReservedNode
->Node
.Length
= Length
;
1633 ReservedNode
->Node
.ResType
= ResType
;
1635 InsertTailList (&Bridge
->ReservedResourceList
, &(ReservedNode
->Link
));
1641 Insert resource padding for P2C.
1643 @param PciDev Pci device instance.
1644 @param IoNode Resource info node for IO.
1645 @param Mem32Node Resource info node for 32-bit memory.
1646 @param PMem32Node Resource info node for 32-bit PMemory.
1647 @param Mem64Node Resource info node for 64-bit memory.
1648 @param PMem64Node Resource info node for 64-bit PMemory.
1650 @retval EFI_SUCCESS Success.
1653 ResourcePaddingForCardBusBridge (
1654 PCI_IO_DEVICE
*PciDev
,
1655 PCI_RESOURCE_NODE
*IoNode
,
1656 PCI_RESOURCE_NODE
*Mem32Node
,
1657 PCI_RESOURCE_NODE
*PMem32Node
,
1658 PCI_RESOURCE_NODE
*Mem64Node
,
1659 PCI_RESOURCE_NODE
*PMem64Node
1662 PCI_RESOURCE_NODE
*Node
;
1667 // Memory Base/Limit Register 0
1668 // Bar 1 denodes memory range 0
1670 Node
= CreateResourceNode (
1679 InsertResourceNode (
1685 // Memory Base/Limit Register 1
1686 // Bar 2 denodes memory range1
1688 Node
= CreateResourceNode (
1697 InsertResourceNode (
1704 // Bar 3 denodes io range 0
1706 Node
= CreateResourceNode (
1715 InsertResourceNode (
1722 // Bar 4 denodes io range 0
1724 Node
= CreateResourceNode (
1733 InsertResourceNode (
1742 Program P2C register for given resource node
1744 @param Base Base address of P2C device
1745 @param Node Given resource node.
1747 @retval EFI_SUCCESS Success
1752 IN PCI_RESOURCE_NODE
*Node
1755 EFI_PCI_IO_PROTOCOL
*PciIo
;
1758 UINT16 BridgeControl
;
1761 PciIo
= &(Node
->PciDev
->PciIo
);
1763 Address
= Base
+ Node
->Offset
;
1766 // Indicate pci bus driver has allocated
1767 // resource for this device
1768 // It might be a temporary solution here since
1769 // pci device could have multiple bar
1771 Node
->PciDev
->Allocated
= TRUE
;
1773 switch (Node
->Bar
) {
1778 EfiPciIoWidthUint32
,
1779 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1784 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1785 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1791 EfiPciIoWidthUint32
,
1797 TempAddress
= Address
+ Node
->Length
- 1;
1800 EfiPciIoWidthUint32
,
1806 if (Node
->ResType
== PciBarTypeMem32
) {
1809 // Set non-prefetchable bit
1813 EfiPciIoWidthUint16
,
1819 BridgeControl
&= 0xfeff;
1822 EfiPciIoWidthUint16
,
1831 // Set pre-fetchable bit
1835 EfiPciIoWidthUint16
,
1841 BridgeControl
|= 0x0100;
1844 EfiPciIoWidthUint16
,
1851 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1852 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1853 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1860 EfiPciIoWidthUint32
,
1866 TempAddress
= Address
+ Node
->Length
- 1;
1870 EfiPciIoWidthUint32
,
1876 if (Node
->ResType
== PciBarTypeMem32
) {
1879 // Set non-prefetchable bit
1883 EfiPciIoWidthUint16
,
1889 BridgeControl
&= 0xfdff;
1892 EfiPciIoWidthUint16
,
1900 // Set pre-fetchable bit
1904 EfiPciIoWidthUint16
,
1910 BridgeControl
|= 0x0200;
1913 EfiPciIoWidthUint16
,
1920 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1921 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1922 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1928 EfiPciIoWidthUint32
,
1933 TempAddress
= Address
+ Node
->Length
- 1;
1936 EfiPciIoWidthUint32
,
1942 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1943 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1944 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1951 EfiPciIoWidthUint32
,
1957 TempAddress
= Address
+ Node
->Length
- 1;
1960 EfiPciIoWidthUint32
,
1966 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1967 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1968 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1979 Create padding resource node.
1981 @param PciDev Pci device instance.
1982 @param IoNode Resource info node for IO.
1983 @param Mem32Node Resource info node for 32-bit memory.
1984 @param PMem32Node Resource info node for 32-bit PMemory.
1985 @param Mem64Node Resource info node for 64-bit memory.
1986 @param PMem64Node Resource info node for 64-bit PMemory.
1988 @retval EFI_SUCCESS Success.
1992 ApplyResourcePadding (
1993 PCI_IO_DEVICE
*PciDev
,
1994 PCI_RESOURCE_NODE
*IoNode
,
1995 PCI_RESOURCE_NODE
*Mem32Node
,
1996 PCI_RESOURCE_NODE
*PMem32Node
,
1997 PCI_RESOURCE_NODE
*Mem64Node
,
1998 PCI_RESOURCE_NODE
*PMem64Node
2001 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
2002 PCI_RESOURCE_NODE
*Node
;
2003 UINT8 DummyBarIndex
;
2006 Ptr
= PciDev
->ResourcePaddingDescriptors
;
2008 while (((EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
2010 if (Ptr
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Ptr
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
) {
2011 if (Ptr
->AddrLen
!= 0) {
2013 Node
= CreateResourceNode (
2021 InsertResourceNode (
2031 if (Ptr
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Ptr
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
2033 if (Ptr
->AddrSpaceGranularity
== 32) {
2038 if (Ptr
->SpecificFlag
== 0x6) {
2039 if (Ptr
->AddrLen
!= 0) {
2040 Node
= CreateResourceNode (
2048 InsertResourceNode (
2061 if (Ptr
->SpecificFlag
== 0) {
2062 if (Ptr
->AddrLen
!= 0) {
2063 Node
= CreateResourceNode (
2071 InsertResourceNode (
2082 if (Ptr
->AddrSpaceGranularity
== 64) {
2087 if (Ptr
->SpecificFlag
== 0x6) {
2088 if (Ptr
->AddrLen
!= 0) {
2089 Node
= CreateResourceNode (
2097 InsertResourceNode (
2110 if (Ptr
->SpecificFlag
== 0) {
2111 if (Ptr
->AddrLen
!= 0) {
2112 Node
= CreateResourceNode (
2120 InsertResourceNode (
2139 Get padding resource for PPB.
2140 Light PCI bus driver woundn't support hotplug root device
2141 So no need to pad resource for them.
2143 @param PciIoDevice Pci device instance.
2146 GetResourcePaddingPpb (
2147 IN PCI_IO_DEVICE
*PciIoDevice
2150 if (gPciHotPlugInit
!= NULL
) {
2151 if (PciIoDevice
->ResourcePaddingDescriptors
== NULL
) {
2152 GetResourcePaddingForHpb (PciIoDevice
);