3 Copyright (c) 2006 - 2007, 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 InsertHeadList (&Bridge
->ChildList
, &ResNode
->Link
);
110 CurrentLink
= Bridge
->ChildList
.ForwardLink
->ForwardLink
;
111 while (CurrentLink
!= &Bridge
->ChildList
) {
112 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
114 if (ResNode
->Alignment
> Temp
->Alignment
) {
116 } else if (ResNode
->Alignment
== Temp
->Alignment
) {
117 ResNodeAlignRest
= ResNode
->Length
& ResNode
->Alignment
;
118 TempAlignRest
= Temp
->Length
& Temp
->Alignment
;
119 if ((ResNodeAlignRest
== 0) || (ResNodeAlignRest
>= TempAlignRest
)) {
124 SwapListEntries (&ResNode
->Link
, CurrentLink
);
126 CurrentLink
= ResNode
->Link
.ForwardLink
;
136 This routine is used to merge two different resource tree in need of
137 resoure degradation. For example, if a upstream PPB doesn't support,
138 prefetchable memory decoding, the PCI bus driver will choose to call this function
139 to merge prefectchable memory resource list into normal memory list.
141 If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
144 @param Dst Point to destination resource tree
145 @param Res Point to source resource tree
146 @param TypeMerge If the TypeMerge is TRUE, Res resource type is changed to the type of
147 destination resource type.
150 @retval EFI_SUCCESS Success
154 PCI_RESOURCE_NODE
*Dst
,
155 PCI_RESOURCE_NODE
*Res
,
160 LIST_ENTRY
*CurrentLink
;
161 PCI_RESOURCE_NODE
*Temp
;
163 while (!IsListEmpty (&Res
->ChildList
)) {
164 CurrentLink
= Res
->ChildList
.ForwardLink
;
166 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
169 Temp
->ResType
= Dst
->ResType
;
172 RemoveEntryList (CurrentLink
);
173 InsertResourceNode (Dst
, Temp
);
181 This function is used to calculate the IO16 aperture
184 @param Bridge PCI resource node for bridge.
186 @retval EFI_SUCCESS Success
189 CalculateApertureIo16 (
190 IN PCI_RESOURCE_NODE
*Bridge
195 LIST_ENTRY
*CurrentLink
;
196 PCI_RESOURCE_NODE
*Node
;
202 // Always assume there is ISA device and VGA device on the platform
203 // will be customized later
208 if (FeaturePcdGet (PcdPciIsaEnable
)){
212 if (FeaturePcdGet (PcdPciVgaEnable
)){
222 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
225 // Assume the bridge is aligned
227 while (CurrentLink
!= &Bridge
->ChildList
) {
229 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
232 // Consider the aperture alignment
234 offset
= Aperture
& (Node
->Alignment
);
238 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - offset
;
243 // IsaEnable and VGAEnable can not be implemented now.
244 // If both of them are enabled, then the IO resource would
245 // become too limited to meet the requirement of most of devices.
248 if (IsaEnable
|| VGAEnable
) {
249 if (!IS_PCI_BRIDGE (&(Node
->PciDev
->Pci
)) && !IS_CARDBUS_BRIDGE (&(Node
->PciDev
->Pci
))) {
251 // Check if there is need to support ISA/VGA decoding
252 // If so, we need to avoid isa/vga aliasing range
255 SkipIsaAliasAperture (
259 offset
= Aperture
& (Node
->Alignment
);
261 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - offset
;
263 } else if (VGAEnable
) {
268 offset
= Aperture
& (Node
->Alignment
);
270 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - offset
;
276 Node
->Offset
= Aperture
;
279 // Increment aperture by the length of node
281 Aperture
+= Node
->Length
;
283 CurrentLink
= CurrentLink
->ForwardLink
;
287 // At last, adjust the aperture with the bridge's
290 offset
= Aperture
& (Bridge
->Alignment
);
293 Aperture
= Aperture
+ (Bridge
->Alignment
+ 1) - offset
;
296 Bridge
->Length
= Aperture
;
298 // At last, adjust the bridge's alignment to the first child's alignment
299 // if the bridge has at least one child
301 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
302 if (CurrentLink
!= &Bridge
->ChildList
) {
303 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
304 if (Node
->Alignment
> Bridge
->Alignment
) {
305 Bridge
->Alignment
= Node
->Alignment
;
313 This function is used to calculate the resource aperture
314 for a given bridge device
316 @param Bridge Give bridge device
318 @retval EFI_SUCCESS Success
321 CalculateResourceAperture (
322 IN PCI_RESOURCE_NODE
*Bridge
326 LIST_ENTRY
*CurrentLink
;
327 PCI_RESOURCE_NODE
*Node
;
337 if (Bridge
->ResType
== PciBarTypeIo16
) {
338 return CalculateApertureIo16 (Bridge
);
341 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
344 // Assume the bridge is aligned
346 while (CurrentLink
!= &Bridge
->ChildList
) {
348 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
351 // Apply padding resource if available
354 offset
= Aperture
& (Node
->Alignment
);
358 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - offset
;
363 // Recode current aperture as a offset
364 // this offset will be used in future real allocation
366 Node
->Offset
= Aperture
;
369 // Increment aperture by the length of node
371 Aperture
+= Node
->Length
;
374 // Consider the aperture alignment
377 CurrentLink
= CurrentLink
->ForwardLink
;
381 // At last, adjust the aperture with the bridge's
384 offset
= Aperture
& (Bridge
->Alignment
);
386 Aperture
= Aperture
+ (Bridge
->Alignment
+ 1) - offset
;
390 // If the bridge has already padded the resource and the
391 // amount of padded resource is larger, then keep the
394 if (Bridge
->Length
< Aperture
) {
395 Bridge
->Length
= Aperture
;
399 // At last, adjust the bridge's alignment to the first child's alignment
400 // if the bridge has at least one child
402 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
403 if (CurrentLink
!= &Bridge
->ChildList
) {
404 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
405 if (Node
->Alignment
> Bridge
->Alignment
) {
406 Bridge
->Alignment
= Node
->Alignment
;
414 Get IO/Memory resource infor for given PCI device
416 @param PciDev Pci device instance
417 @param IoNode Resource info node for IO
418 @param Mem32Node Resource info node for 32-bit memory
419 @param PMem32Node Resource info node for 32-bit PMemory
420 @param Mem64Node Resource info node for 64-bit memory
421 @param PMem64Node Resource info node for 64-bit PMemory
423 @retval EFI_SUCCESS Success
426 GetResourceFromDevice (
427 PCI_IO_DEVICE
*PciDev
,
428 PCI_RESOURCE_NODE
*IoNode
,
429 PCI_RESOURCE_NODE
*Mem32Node
,
430 PCI_RESOURCE_NODE
*PMem32Node
,
431 PCI_RESOURCE_NODE
*Mem64Node
,
432 PCI_RESOURCE_NODE
*PMem64Node
437 PCI_RESOURCE_NODE
*Node
;
438 BOOLEAN ResourceRequested
;
441 ResourceRequested
= FALSE
;
443 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
445 switch ((PciDev
->PciBar
)[Index
].BarType
) {
447 case PciBarTypeMem32
:
449 Node
= CreateResourceNode (
451 (PciDev
->PciBar
)[Index
].Length
,
452 (PciDev
->PciBar
)[Index
].Alignment
,
463 ResourceRequested
= TRUE
;
466 case PciBarTypeMem64
:
468 Node
= CreateResourceNode (
470 (PciDev
->PciBar
)[Index
].Length
,
471 (PciDev
->PciBar
)[Index
].Alignment
,
482 ResourceRequested
= TRUE
;
485 case PciBarTypePMem64
:
487 Node
= CreateResourceNode (
489 (PciDev
->PciBar
)[Index
].Length
,
490 (PciDev
->PciBar
)[Index
].Alignment
,
501 ResourceRequested
= TRUE
;
504 case PciBarTypePMem32
:
506 Node
= CreateResourceNode (
508 (PciDev
->PciBar
)[Index
].Length
,
509 (PciDev
->PciBar
)[Index
].Alignment
,
519 ResourceRequested
= TRUE
;
525 Node
= CreateResourceNode (
527 (PciDev
->PciBar
)[Index
].Length
,
528 (PciDev
->PciBar
)[Index
].Alignment
,
538 ResourceRequested
= TRUE
;
541 case PciBarTypeUnknown
:
550 // If there is no resource requested from this device,
551 // then we indicate this device has been allocated naturally.
553 if (!ResourceRequested
) {
554 PciDev
->Allocated
= TRUE
;
561 This function is used to create a resource node
563 @param PciDev Pci device instance
564 @param Length Length of Io/Memory resource
565 @param Alignment Alignment of resource
567 @param ResType Type of resource: IO/Memory
568 @param ResUage Resource usage
572 IN PCI_IO_DEVICE
*PciDev
,
576 IN PCI_BAR_TYPE ResType
,
577 IN PCI_RESOURCE_USAGE ResUsage
580 PCI_RESOURCE_NODE
*Node
;
584 Node
= AllocatePool (sizeof (PCI_RESOURCE_NODE
));
585 ASSERT (Node
!= NULL
);
590 ZeroMem (Node
, sizeof (PCI_RESOURCE_NODE
));
592 Node
->Signature
= PCI_RESOURCE_SIGNATURE
;
593 Node
->PciDev
= PciDev
;
594 Node
->Length
= Length
;
595 Node
->Alignment
= Alignment
;
597 Node
->ResType
= ResType
;
598 Node
->Reserved
= FALSE
;
599 Node
->ResourceUsage
= ResUsage
;
600 InitializeListHead (&Node
->ChildList
);
605 This routine is used to extract resource request from
608 @param Bridge Pci device instance
609 @param IoNode Resource info node for IO
610 @param Mem32Node Resource info node for 32-bit memory
611 @param PMem32Node Resource info node for 32-bit PMemory
612 @param Mem64Node Resource info node for 64-bit memory
613 @param PMem64Node Resource info node for 64-bit PMemory
615 @retval EFI_SUCCESS Success
619 IN PCI_IO_DEVICE
*Bridge
,
620 IN PCI_RESOURCE_NODE
*IoNode
,
621 IN PCI_RESOURCE_NODE
*Mem32Node
,
622 IN PCI_RESOURCE_NODE
*PMem32Node
,
623 IN PCI_RESOURCE_NODE
*Mem64Node
,
624 IN PCI_RESOURCE_NODE
*PMem64Node
628 PCI_RESOURCE_NODE
*IoBridge
;
629 PCI_RESOURCE_NODE
*Mem32Bridge
;
630 PCI_RESOURCE_NODE
*PMem32Bridge
;
631 PCI_RESOURCE_NODE
*Mem64Bridge
;
632 PCI_RESOURCE_NODE
*PMem64Bridge
;
633 LIST_ENTRY
*CurrentLink
;
635 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
637 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
639 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
642 // Create resource nodes for this device by scanning the
643 // Bar array in the device private data
644 // If the upstream bridge doesn't support this device,
645 // no any resource node will be created for this device
647 GetResourceFromDevice (
656 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
659 // If the device has children, create a bridge resource node for this PPB
660 // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
661 // is aligned with 4KB
662 // This device is typically a bridge device like PPB and P2C
664 IoBridge
= CreateResourceNode (
673 Mem32Bridge
= CreateResourceNode (
682 PMem32Bridge
= CreateResourceNode (
691 Mem64Bridge
= CreateResourceNode (
700 PMem64Bridge
= CreateResourceNode (
710 // Recursively create resouce map on this bridge
721 if (ResourceRequestExisted (IoBridge
)) {
727 gBS
->FreePool (IoBridge
);
732 // If there is node under this resource bridge,
733 // then calculate bridge's aperture of this type
734 // and insert it into the respective resource tree.
735 // If no, delete this resource bridge
737 if (ResourceRequestExisted (Mem32Bridge
)) {
743 gBS
->FreePool (Mem32Bridge
);
748 // If there is node under this resource bridge,
749 // then calculate bridge's aperture of this type
750 // and insert it into the respective resource tree.
751 // If no, delete this resource bridge
753 if (ResourceRequestExisted (PMem32Bridge
)) {
759 gBS
->FreePool (PMem32Bridge
);
764 // If there is node under this resource bridge,
765 // then calculate bridge's aperture of this type
766 // and insert it into the respective resource tree.
767 // If no, delete this resource bridge
769 if (ResourceRequestExisted (Mem64Bridge
)) {
775 gBS
->FreePool (Mem64Bridge
);
780 // If there is node under this resource bridge,
781 // then calculate bridge's aperture of this type
782 // and insert it into the respective resource tree.
783 // If no, delete this resource bridge
785 if (ResourceRequestExisted (PMem64Bridge
)) {
791 gBS
->FreePool (PMem64Bridge
);
798 // If it is P2C, apply hard coded resource padding
801 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
802 ResourcePaddingForCardBusBridge (
812 CurrentLink
= CurrentLink
->ForwardLink
;
816 // To do some platform specific resource padding ...
818 ResourcePaddingPolicy (
828 // Degrade resource if necessary
839 // Calculate resource aperture for this bridge device
841 CalculateResourceAperture (Mem32Node
);
842 CalculateResourceAperture (PMem32Node
);
843 CalculateResourceAperture (Mem64Node
);
844 CalculateResourceAperture (PMem64Node
);
845 CalculateResourceAperture (IoNode
);
852 This function is used to do the resource padding for a specific platform
854 @param Bridge Pci device instance
855 @param IoNode Resource info node for IO
856 @param Mem32Node Resource info node for 32-bit memory
857 @param PMem32Node Resource info node for 32-bit PMemory
858 @param Mem64Node Resource info node for 64-bit memory
859 @param PMem64Node Resource info node for 64-bit PMemory
861 @retval EFI_SUCCESS Success
864 ResourcePaddingPolicy (
865 PCI_IO_DEVICE
*PciDev
,
866 PCI_RESOURCE_NODE
*IoNode
,
867 PCI_RESOURCE_NODE
*Mem32Node
,
868 PCI_RESOURCE_NODE
*PMem32Node
,
869 PCI_RESOURCE_NODE
*Mem64Node
,
870 PCI_RESOURCE_NODE
*PMem64Node
874 // Create padding resource node
876 if (PciDev
->ResourcePaddingDescriptors
!= NULL
) {
877 ApplyResourcePadding (
892 This function is used to degrade resource if the upstream bridge
893 doesn't support certain resource. Degradation path is
894 PMEM64 -> MEM64 -> MEM32
895 PMEM64 -> PMEM32 -> MEM32
898 @param Bridge Pci device instance
899 @param IoNode Resource info node for IO
900 @param Mem32Node Resource info node for 32-bit memory
901 @param PMem32Node Resource info node for 32-bit PMemory
902 @param Mem64Node Resource info node for 64-bit memory
903 @param PMem64Node Resource info node for 64-bit PMemory
905 @retval EFI_SUCCESS Success
909 IN PCI_IO_DEVICE
*Bridge
,
910 IN PCI_RESOURCE_NODE
*Mem32Node
,
911 IN PCI_RESOURCE_NODE
*PMem32Node
,
912 IN PCI_RESOURCE_NODE
*Mem64Node
,
913 IN PCI_RESOURCE_NODE
*PMem64Node
918 // If bridge doesn't support Prefetchable
919 // memory64, degrade it to Prefetchable memory32
921 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
)) {
929 // if no PMem32 request, still keep PMem64. Otherwise degrade to PMem32
931 if (PMem32Node
!= NULL
&& PMem32Node
->Length
!= 0 && Bridge
->Parent
!= NULL
) {
933 // Fixed the issue that there is no resource for 64-bit (above 4G)
945 // If bridge doesn't support Mem64
946 // degrade it to mem32
948 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_MEM64_DECODE_SUPPORTED
)) {
957 // If bridge doesn't support Pmem32
958 // degrade it to mem32
960 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
)) {
969 // if bridge supports combined Pmem Mem decoding
970 // merge these two type of resource
972 if (BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
)) {
990 Test whether bridge device support decode resource
992 @param Bridge Bridge device instance
993 @param Decode Decode type according to resource type
995 @return whether bridge device support decode resource
999 BridgeSupportResourceDecode (
1000 IN PCI_IO_DEVICE
*Bridge
,
1005 if ((Bridge
->Decodes
) & Decode
) {
1013 This function is used to program the resource allocated
1014 for each resource node
1017 @param Base Base address of resource
1018 @param Bridge Bridge device instance
1020 @retval EFI_SUCCESS Success
1025 IN PCI_RESOURCE_NODE
*Bridge
1028 LIST_ENTRY
*CurrentLink
;
1029 PCI_RESOURCE_NODE
*Node
;
1032 if (Base
== gAllOne
) {
1033 return EFI_OUT_OF_RESOURCES
;
1036 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1038 while (CurrentLink
!= &Bridge
->ChildList
) {
1040 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1042 if (!IS_PCI_BRIDGE (&(Node
->PciDev
->Pci
))) {
1044 if (IS_CARDBUS_BRIDGE (&(Node
->PciDev
->Pci
))) {
1045 ProgramP2C (Base
, Node
);
1047 ProgramBar (Base
, Node
);
1050 Status
= ProgramResource (Base
+ Node
->Offset
, Node
);
1052 if (EFI_ERROR (Status
)) {
1056 ProgramPpbApperture (Base
, Node
);
1059 CurrentLink
= CurrentLink
->ForwardLink
;
1066 Program Bar register.
1068 @param Base Base address for resource
1069 @param Node Point to resoure node structure
1071 @retval EFI_SUCCESS Success
1076 IN PCI_RESOURCE_NODE
*Node
1079 EFI_PCI_IO_PROTOCOL
*PciIo
;
1084 PciIo
= &(Node
->PciDev
->PciIo
);
1086 Address
= Base
+ Node
->Offset
;
1089 // Indicate pci bus driver has allocated
1090 // resource for this device
1091 // It might be a temporary solution here since
1092 // pci device could have multiple bar
1094 Node
->PciDev
->Allocated
= TRUE
;
1096 switch ((Node
->PciDev
->PciBar
[Node
->Bar
]).BarType
) {
1098 case PciBarTypeIo16
:
1099 case PciBarTypeIo32
:
1100 case PciBarTypeMem32
:
1101 case PciBarTypePMem32
:
1105 EfiPciIoWidthUint32
,
1106 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1111 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1115 case PciBarTypeMem64
:
1116 case PciBarTypePMem64
:
1118 Address32
= (UINT32
) (Address
& 0x00000000FFFFFFFF);
1122 EfiPciIoWidthUint32
,
1123 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1128 Address32
= (UINT32
) RShiftU64 (Address
, 32);
1132 EfiPciIoWidthUint32
,
1133 (UINT8
) ((Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
+ 4),
1138 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1150 Program PPB apperture
1152 @param Base Base address for resource
1153 @param Node Point to resoure node structure
1155 @retval EFI_SUCCESS Success
1158 ProgramPpbApperture (
1160 IN PCI_RESOURCE_NODE
*Node
1163 EFI_PCI_IO_PROTOCOL
*PciIo
;
1169 // if no device south of this PPB, return anyway
1170 // Apperture is set default in the initialization code
1172 if (Node
->Length
== 0 || Node
->ResourceUsage
== PciResUsagePadding
) {
1174 // For padding resource node, just ignore when programming
1179 PciIo
= &(Node
->PciDev
->PciIo
);
1180 Address
= Base
+ Node
->Offset
;
1183 // Indicate the PPB resource has been allocated
1185 Node
->PciDev
->Allocated
= TRUE
;
1187 switch (Node
->Bar
) {
1193 EfiPciIoWidthUint32
,
1194 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1199 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1200 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1206 Address32
= ((UINT32
) (Address
)) >> 8;
1218 EfiPciIoWidthUint16
,
1224 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1225 Address32
= ((UINT32
) (Address32
)) >> 8;
1237 EfiPciIoWidthUint16
,
1243 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1244 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1247 case PPB_MEM32_RANGE
:
1249 Address32
= ((UINT32
) (Address
)) >> 16;
1252 EfiPciIoWidthUint16
,
1258 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1259 Address32
= ((UINT32
) (Address32
)) >> 16;
1262 EfiPciIoWidthUint16
,
1268 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1269 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1272 case PPB_PMEM32_RANGE
:
1273 case PPB_PMEM64_RANGE
:
1275 Address32
= ((UINT32
) (Address
)) >> 16;
1278 EfiPciIoWidthUint16
,
1284 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1285 Address32
= ((UINT32
) (Address32
)) >> 16;
1288 EfiPciIoWidthUint16
,
1294 Address32
= (UINT32
) RShiftU64 (Address
, 32);
1297 EfiPciIoWidthUint32
,
1303 Address32
= (UINT32
) RShiftU64 ((Address
+ Node
->Length
- 1), 32);
1306 EfiPciIoWidthUint32
,
1312 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1313 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1324 Program parent bridge for oprom
1326 @param PciDevice Pci deivce instance
1327 @param OptionRomBase Base address for oprom
1328 @param Enable Enable/Disable
1330 @retval EFI_SUCCESS Success
1333 ProgrameUpstreamBridgeForRom (
1334 IN PCI_IO_DEVICE
*PciDevice
,
1335 IN UINT32 OptionRomBase
,
1339 PCI_IO_DEVICE
*Parent
;
1340 PCI_RESOURCE_NODE Node
;
1342 // For root bridge, just return.
1344 Parent
= PciDevice
->Parent
;
1345 ZeroMem (&Node
, sizeof (Node
));
1347 if (!IS_PCI_BRIDGE (&Parent
->Pci
)) {
1351 Node
.PciDev
= Parent
;
1352 Node
.Length
= PciDevice
->RomSize
;
1354 Node
.Bar
= PPB_MEM32_RANGE
;
1355 Node
.ResType
= PciBarTypeMem32
;
1359 // Program PPB to only open a single <= 16<MB apperture
1362 ProgramPpbApperture (OptionRomBase
, &Node
);
1363 PciEnableCommandRegister (Parent
, EFI_PCI_COMMAND_MEMORY_SPACE
);
1365 InitializePpb (Parent
);
1366 PciDisableCommandRegister (Parent
, EFI_PCI_COMMAND_MEMORY_SPACE
);
1369 Parent
= Parent
->Parent
;
1376 Test whether resource exists for a bridge
1378 @param Bridge Point to resource node for a bridge
1380 @return whether resource exists
1383 ResourceRequestExisted (
1384 IN PCI_RESOURCE_NODE
*Bridge
1387 if (Bridge
!= NULL
) {
1388 if (!IsListEmpty (&Bridge
->ChildList
) || Bridge
->Length
!= 0) {
1397 Initialize resource pool structure.
1399 @param ResourcePool Point to resource pool structure
1400 @param ResourceType Type of resource
1403 InitializeResourcePool (
1404 PCI_RESOURCE_NODE
*ResourcePool
,
1405 PCI_BAR_TYPE ResourceType
1409 ZeroMem (ResourcePool
, sizeof (PCI_RESOURCE_NODE
));
1410 ResourcePool
->ResType
= ResourceType
;
1411 ResourcePool
->Signature
= PCI_RESOURCE_SIGNATURE
;
1412 InitializeListHead (&ResourcePool
->ChildList
);
1418 Get all resource information for given Pci device
1420 @param PciDev Pci device instance
1421 @param IoBridge Io resource node
1422 @param Mem32Bridge 32-bit memory node
1423 @param PMem32Bridge 32-bit Pmemory node
1424 @param Mem64Bridge 64-bit memory node
1425 @param PMem64Bridge 64-bit PMemory node
1426 @param IoPool Link list header for Io resource
1427 @param Mem32Pool Link list header for 32-bit memory
1428 @param PMem32Pool Link list header for 32-bit Pmemory
1429 @param Mem64Pool Link list header for 64-bit memory
1430 @param PMem64Pool Link list header for 64-bit Pmemory
1432 @retval EFI_SUCCESS Success
1436 PCI_IO_DEVICE
*PciDev
,
1437 PCI_RESOURCE_NODE
**IoBridge
,
1438 PCI_RESOURCE_NODE
**Mem32Bridge
,
1439 PCI_RESOURCE_NODE
**PMem32Bridge
,
1440 PCI_RESOURCE_NODE
**Mem64Bridge
,
1441 PCI_RESOURCE_NODE
**PMem64Bridge
,
1442 PCI_RESOURCE_NODE
*IoPool
,
1443 PCI_RESOURCE_NODE
*Mem32Pool
,
1444 PCI_RESOURCE_NODE
*PMem32Pool
,
1445 PCI_RESOURCE_NODE
*Mem64Pool
,
1446 PCI_RESOURCE_NODE
*PMem64Pool
1450 PCI_RESOURCE_NODE
*Temp
;
1451 LIST_ENTRY
*CurrentLink
;
1453 CurrentLink
= IoPool
->ChildList
.ForwardLink
;
1456 // Get Io resource map
1458 while (CurrentLink
!= &IoPool
->ChildList
) {
1460 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1462 if (Temp
->PciDev
== PciDev
) {
1466 CurrentLink
= CurrentLink
->ForwardLink
;
1470 // Get Mem32 resource map
1472 CurrentLink
= Mem32Pool
->ChildList
.ForwardLink
;
1474 while (CurrentLink
!= &Mem32Pool
->ChildList
) {
1476 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1478 if (Temp
->PciDev
== PciDev
) {
1479 *Mem32Bridge
= Temp
;
1482 CurrentLink
= CurrentLink
->ForwardLink
;
1486 // Get Pmem32 resource map
1488 CurrentLink
= PMem32Pool
->ChildList
.ForwardLink
;
1490 while (CurrentLink
!= &PMem32Pool
->ChildList
) {
1492 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1494 if (Temp
->PciDev
== PciDev
) {
1495 *PMem32Bridge
= Temp
;
1498 CurrentLink
= CurrentLink
->ForwardLink
;
1502 // Get Mem64 resource map
1504 CurrentLink
= Mem64Pool
->ChildList
.ForwardLink
;
1506 while (CurrentLink
!= &Mem64Pool
->ChildList
) {
1508 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1510 if (Temp
->PciDev
== PciDev
) {
1511 *Mem64Bridge
= Temp
;
1514 CurrentLink
= CurrentLink
->ForwardLink
;
1518 // Get Pmem64 resource map
1520 CurrentLink
= PMem64Pool
->ChildList
.ForwardLink
;
1522 while (CurrentLink
!= &PMem64Pool
->ChildList
) {
1524 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1526 if (Temp
->PciDev
== PciDev
) {
1527 *PMem64Bridge
= Temp
;
1530 CurrentLink
= CurrentLink
->ForwardLink
;
1537 Destory given resource tree
1539 @param Bridge root node of resource tree
1541 @retval EFI_SUCCESS Success
1544 DestroyResourceTree (
1545 IN PCI_RESOURCE_NODE
*Bridge
1548 PCI_RESOURCE_NODE
*Temp
;
1549 LIST_ENTRY
*CurrentLink
;
1551 while (!IsListEmpty (&Bridge
->ChildList
)) {
1553 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1555 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1557 RemoveEntryList (CurrentLink
);
1559 if (IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
))) {
1560 DestroyResourceTree (Temp
);
1563 gBS
->FreePool (Temp
);
1570 Record the reserved resource and insert to reserved list.
1572 @param Base Base address of reserved resourse
1573 @param Length Length of reserved resource
1574 @param ResType Resource type
1575 @param Bridge Pci device instance
1578 RecordReservedResource (
1581 IN PCI_BAR_TYPE ResType
,
1582 IN PCI_IO_DEVICE
*Bridge
1585 PCI_RESERVED_RESOURCE_LIST
*ReservedNode
;
1587 ReservedNode
= AllocatePool (sizeof (PCI_RESERVED_RESOURCE_LIST
));
1588 if (ReservedNode
== NULL
) {
1589 return EFI_OUT_OF_RESOURCES
;
1592 ReservedNode
->Signature
= RESERVED_RESOURCE_SIGNATURE
;
1593 ReservedNode
->Node
.Base
= Base
;
1594 ReservedNode
->Node
.Length
= Length
;
1595 ReservedNode
->Node
.ResType
= ResType
;
1597 InsertTailList (&Bridge
->ReservedResourceList
, &(ReservedNode
->Link
));
1603 Insert resource padding for P2C
1605 @param PciDev Pci device instance
1606 @param IoNode Resource info node for IO
1607 @param Mem32Node Resource info node for 32-bit memory
1608 @param PMem32Node Resource info node for 32-bit PMemory
1609 @param Mem64Node Resource info node for 64-bit memory
1610 @param PMem64Node Resource info node for 64-bit PMemory
1612 @retval EFI_SUCCESS Success
1615 ResourcePaddingForCardBusBridge (
1616 PCI_IO_DEVICE
*PciDev
,
1617 PCI_RESOURCE_NODE
*IoNode
,
1618 PCI_RESOURCE_NODE
*Mem32Node
,
1619 PCI_RESOURCE_NODE
*PMem32Node
,
1620 PCI_RESOURCE_NODE
*Mem64Node
,
1621 PCI_RESOURCE_NODE
*PMem64Node
1624 PCI_RESOURCE_NODE
*Node
;
1629 // Memory Base/Limit Register 0
1630 // Bar 1 denodes memory range 0
1632 Node
= CreateResourceNode (
1641 InsertResourceNode (
1647 // Memory Base/Limit Register 1
1648 // Bar 2 denodes memory range1
1650 Node
= CreateResourceNode (
1659 InsertResourceNode (
1666 // Bar 3 denodes io range 0
1668 Node
= CreateResourceNode (
1677 InsertResourceNode (
1684 // Bar 4 denodes io range 0
1686 Node
= CreateResourceNode (
1695 InsertResourceNode (
1704 Program P2C register for given resource node
1706 @param Base Base address of P2C device
1707 @param Node Given resource node.
1709 @retval EFI_SUCCESS Success
1714 IN PCI_RESOURCE_NODE
*Node
1717 EFI_PCI_IO_PROTOCOL
*PciIo
;
1720 UINT16 BridgeControl
;
1723 PciIo
= &(Node
->PciDev
->PciIo
);
1725 Address
= Base
+ Node
->Offset
;
1728 // Indicate pci bus driver has allocated
1729 // resource for this device
1730 // It might be a temporary solution here since
1731 // pci device could have multiple bar
1733 Node
->PciDev
->Allocated
= TRUE
;
1735 switch (Node
->Bar
) {
1740 EfiPciIoWidthUint32
,
1741 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1746 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1747 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1753 EfiPciIoWidthUint32
,
1759 TempAddress
= Address
+ Node
->Length
- 1;
1762 EfiPciIoWidthUint32
,
1768 if (Node
->ResType
== PciBarTypeMem32
) {
1771 // Set non-prefetchable bit
1775 EfiPciIoWidthUint16
,
1781 BridgeControl
&= 0xfeff;
1784 EfiPciIoWidthUint16
,
1793 // Set pre-fetchable bit
1797 EfiPciIoWidthUint16
,
1803 BridgeControl
|= 0x0100;
1806 EfiPciIoWidthUint16
,
1813 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1814 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1815 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1822 EfiPciIoWidthUint32
,
1828 TempAddress
= Address
+ Node
->Length
- 1;
1832 EfiPciIoWidthUint32
,
1838 if (Node
->ResType
== PciBarTypeMem32
) {
1841 // Set non-prefetchable bit
1845 EfiPciIoWidthUint16
,
1851 BridgeControl
&= 0xfdff;
1854 EfiPciIoWidthUint16
,
1862 // Set pre-fetchable bit
1866 EfiPciIoWidthUint16
,
1872 BridgeControl
|= 0x0200;
1875 EfiPciIoWidthUint16
,
1882 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1883 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1884 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1890 EfiPciIoWidthUint32
,
1895 TempAddress
= Address
+ Node
->Length
- 1;
1898 EfiPciIoWidthUint32
,
1904 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1905 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1906 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1913 EfiPciIoWidthUint32
,
1919 TempAddress
= Address
+ Node
->Length
- 1;
1922 EfiPciIoWidthUint32
,
1928 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1929 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1930 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1941 Create padding resource node.
1943 @param PciDev Pci device instance
1944 @param IoNode Resource info node for IO
1945 @param Mem32Node Resource info node for 32-bit memory
1946 @param PMem32Node Resource info node for 32-bit PMemory
1947 @param Mem64Node Resource info node for 64-bit memory
1948 @param PMem64Node Resource info node for 64-bit PMemory
1950 @retval EFI_SUCCESS Success
1954 ApplyResourcePadding (
1955 PCI_IO_DEVICE
*PciDev
,
1956 PCI_RESOURCE_NODE
*IoNode
,
1957 PCI_RESOURCE_NODE
*Mem32Node
,
1958 PCI_RESOURCE_NODE
*PMem32Node
,
1959 PCI_RESOURCE_NODE
*Mem64Node
,
1960 PCI_RESOURCE_NODE
*PMem64Node
1963 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1964 PCI_RESOURCE_NODE
*Node
;
1965 UINT8 DummyBarIndex
;
1968 Ptr
= PciDev
->ResourcePaddingDescriptors
;
1970 while (((EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1972 if (Ptr
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Ptr
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
) {
1973 if (Ptr
->AddrLen
!= 0) {
1975 Node
= CreateResourceNode (
1983 InsertResourceNode (
1993 if (Ptr
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Ptr
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
1995 if (Ptr
->AddrSpaceGranularity
== 32) {
2000 if (Ptr
->SpecificFlag
== 0x6) {
2002 Node
= CreateResourceNode (
2010 InsertResourceNode (
2023 if (Ptr
->SpecificFlag
== 0) {
2025 Node
= CreateResourceNode (
2033 InsertResourceNode (
2044 if (Ptr
->AddrSpaceGranularity
== 64) {
2049 if (Ptr
->SpecificFlag
== 0x6) {
2051 Node
= CreateResourceNode (
2059 InsertResourceNode (
2072 if (Ptr
->SpecificFlag
== 0) {
2074 Node
= CreateResourceNode (
2082 InsertResourceNode (
2101 Get padding resource for PPB
2102 Light PCI bus driver woundn't support hotplug root device
2103 So no need to pad resource for them
2105 @param PciIoDevice Pci device instance
2108 GetResourcePaddingPpb (
2109 IN PCI_IO_DEVICE
*PciIoDevice
2112 if (gPciHotPlugInit
) {
2113 if (PciIoDevice
->ResourcePaddingDescriptors
== NULL
) {
2114 GetResourcePaddingForHpb (PciIoDevice
);