3 Copyright (c) 2006 - 2008, 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
)){
218 if (Bridge
== NULL
) {
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
;
333 if (Bridge
== NULL
) {
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
!= NULL
&& 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 LIST_ENTRY
*CurrentLink
;
921 // For RootBridge, PPB , P2C, go recursively to traverse all its children
922 // to find if this bridge and downstream has OptionRom.
925 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
926 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
928 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
929 if (Temp
->RomSize
!= 0) {
933 CurrentLink
= CurrentLink
->ForwardLink
;
937 // If bridge doesn't support Prefetchable
938 // memory64, degrade it to Prefetchable memory32
940 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
)) {
948 // if no PMem32 request and no OptionRom request, still keep PMem64. Otherwise degrade to PMem32
950 if ((PMem32Node
!= NULL
&& (PMem32Node
->Length
!= 0 && Bridge
->Parent
!= NULL
)) || HasOprom
) {
952 // Fixed the issue that there is no resource for 64-bit (above 4G)
964 // If bridge doesn't support Mem64
965 // degrade it to mem32
967 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_MEM64_DECODE_SUPPORTED
)) {
976 // If bridge doesn't support Pmem32
977 // degrade it to mem32
979 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
)) {
988 // if bridge supports combined Pmem Mem decoding
989 // merge these two type of resource
991 if (BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
)) {
1009 Test whether bridge device support decode resource
1011 @param Bridge Bridge device instance
1012 @param Decode Decode type according to resource type
1014 @return whether bridge device support decode resource
1018 BridgeSupportResourceDecode (
1019 IN PCI_IO_DEVICE
*Bridge
,
1024 if (((Bridge
->Decodes
) & Decode
) != 0) {
1032 This function is used to program the resource allocated
1033 for each resource node
1036 @param Base Base address of resource
1037 @param Bridge Bridge device instance
1039 @retval EFI_SUCCESS Success
1044 IN PCI_RESOURCE_NODE
*Bridge
1047 LIST_ENTRY
*CurrentLink
;
1048 PCI_RESOURCE_NODE
*Node
;
1051 if (Base
== gAllOne
) {
1052 return EFI_OUT_OF_RESOURCES
;
1055 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1057 while (CurrentLink
!= &Bridge
->ChildList
) {
1059 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1061 if (!IS_PCI_BRIDGE (&(Node
->PciDev
->Pci
))) {
1063 if (IS_CARDBUS_BRIDGE (&(Node
->PciDev
->Pci
))) {
1064 ProgramP2C (Base
, Node
);
1066 ProgramBar (Base
, Node
);
1069 Status
= ProgramResource (Base
+ Node
->Offset
, Node
);
1071 if (EFI_ERROR (Status
)) {
1075 ProgramPpbApperture (Base
, Node
);
1078 CurrentLink
= CurrentLink
->ForwardLink
;
1085 Program Bar register.
1087 @param Base Base address for resource
1088 @param Node Point to resoure node structure
1090 @retval EFI_SUCCESS Success
1095 IN PCI_RESOURCE_NODE
*Node
1098 EFI_PCI_IO_PROTOCOL
*PciIo
;
1103 PciIo
= &(Node
->PciDev
->PciIo
);
1105 Address
= Base
+ Node
->Offset
;
1108 // Indicate pci bus driver has allocated
1109 // resource for this device
1110 // It might be a temporary solution here since
1111 // pci device could have multiple bar
1113 Node
->PciDev
->Allocated
= TRUE
;
1115 switch ((Node
->PciDev
->PciBar
[Node
->Bar
]).BarType
) {
1117 case PciBarTypeIo16
:
1118 case PciBarTypeIo32
:
1119 case PciBarTypeMem32
:
1120 case PciBarTypePMem32
:
1124 EfiPciIoWidthUint32
,
1125 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1130 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1134 case PciBarTypeMem64
:
1135 case PciBarTypePMem64
:
1137 Address32
= (UINT32
) (Address
& 0x00000000FFFFFFFF);
1141 EfiPciIoWidthUint32
,
1142 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1147 Address32
= (UINT32
) RShiftU64 (Address
, 32);
1151 EfiPciIoWidthUint32
,
1152 (UINT8
) ((Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
+ 4),
1157 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1169 Program PPB apperture
1171 @param Base Base address for resource
1172 @param Node Point to resoure node structure
1174 @retval EFI_SUCCESS Success
1177 ProgramPpbApperture (
1179 IN PCI_RESOURCE_NODE
*Node
1182 EFI_PCI_IO_PROTOCOL
*PciIo
;
1188 // if no device south of this PPB, return anyway
1189 // Apperture is set default in the initialization code
1191 if (Node
->Length
== 0 || Node
->ResourceUsage
== PciResUsagePadding
) {
1193 // For padding resource node, just ignore when programming
1198 PciIo
= &(Node
->PciDev
->PciIo
);
1199 Address
= Base
+ Node
->Offset
;
1202 // Indicate the PPB resource has been allocated
1204 Node
->PciDev
->Allocated
= TRUE
;
1206 switch (Node
->Bar
) {
1212 EfiPciIoWidthUint32
,
1213 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1218 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1219 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1225 Address32
= ((UINT32
) (Address
)) >> 8;
1237 EfiPciIoWidthUint16
,
1243 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1244 Address32
= ((UINT32
) (Address32
)) >> 8;
1256 EfiPciIoWidthUint16
,
1262 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1263 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1266 case PPB_MEM32_RANGE
:
1268 Address32
= ((UINT32
) (Address
)) >> 16;
1271 EfiPciIoWidthUint16
,
1277 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1278 Address32
= ((UINT32
) (Address32
)) >> 16;
1281 EfiPciIoWidthUint16
,
1287 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1288 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1291 case PPB_PMEM32_RANGE
:
1292 case PPB_PMEM64_RANGE
:
1294 Address32
= ((UINT32
) (Address
)) >> 16;
1297 EfiPciIoWidthUint16
,
1303 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1304 Address32
= ((UINT32
) (Address32
)) >> 16;
1307 EfiPciIoWidthUint16
,
1313 Address32
= (UINT32
) RShiftU64 (Address
, 32);
1316 EfiPciIoWidthUint32
,
1322 Address32
= (UINT32
) RShiftU64 ((Address
+ Node
->Length
- 1), 32);
1325 EfiPciIoWidthUint32
,
1331 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1332 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1343 Program parent bridge for oprom
1345 @param PciDevice Pci deivce instance
1346 @param OptionRomBase Base address for oprom
1347 @param Enable Enable/Disable
1349 @retval EFI_SUCCESS Success
1352 ProgrameUpstreamBridgeForRom (
1353 IN PCI_IO_DEVICE
*PciDevice
,
1354 IN UINT32 OptionRomBase
,
1358 PCI_IO_DEVICE
*Parent
;
1359 PCI_RESOURCE_NODE Node
;
1361 // For root bridge, just return.
1363 Parent
= PciDevice
->Parent
;
1364 ZeroMem (&Node
, sizeof (Node
));
1365 while (Parent
!= NULL
) {
1366 if (!IS_PCI_BRIDGE (&Parent
->Pci
)) {
1370 Node
.PciDev
= Parent
;
1371 Node
.Length
= PciDevice
->RomSize
;
1373 Node
.Bar
= PPB_MEM32_RANGE
;
1374 Node
.ResType
= PciBarTypeMem32
;
1378 // Program PPB to only open a single <= 16<MB apperture
1381 ProgramPpbApperture (OptionRomBase
, &Node
);
1382 PciEnableCommandRegister (Parent
, EFI_PCI_COMMAND_MEMORY_SPACE
);
1384 InitializePpb (Parent
);
1385 PciDisableCommandRegister (Parent
, EFI_PCI_COMMAND_MEMORY_SPACE
);
1388 Parent
= Parent
->Parent
;
1395 Test whether resource exists for a bridge
1397 @param Bridge Point to resource node for a bridge
1399 @return whether resource exists
1402 ResourceRequestExisted (
1403 IN PCI_RESOURCE_NODE
*Bridge
1406 if (Bridge
!= NULL
) {
1407 if (!IsListEmpty (&Bridge
->ChildList
) || Bridge
->Length
!= 0) {
1416 Initialize resource pool structure.
1418 @param ResourcePool Point to resource pool structure
1419 @param ResourceType Type of resource
1422 InitializeResourcePool (
1423 PCI_RESOURCE_NODE
*ResourcePool
,
1424 PCI_BAR_TYPE ResourceType
1428 ZeroMem (ResourcePool
, sizeof (PCI_RESOURCE_NODE
));
1429 ResourcePool
->ResType
= ResourceType
;
1430 ResourcePool
->Signature
= PCI_RESOURCE_SIGNATURE
;
1431 InitializeListHead (&ResourcePool
->ChildList
);
1437 Get all resource information for given Pci device
1439 @param PciDev Pci device instance
1440 @param IoBridge Io resource node
1441 @param Mem32Bridge 32-bit memory node
1442 @param PMem32Bridge 32-bit Pmemory node
1443 @param Mem64Bridge 64-bit memory node
1444 @param PMem64Bridge 64-bit PMemory node
1445 @param IoPool Link list header for Io resource
1446 @param Mem32Pool Link list header for 32-bit memory
1447 @param PMem32Pool Link list header for 32-bit Pmemory
1448 @param Mem64Pool Link list header for 64-bit memory
1449 @param PMem64Pool Link list header for 64-bit Pmemory
1451 @retval EFI_SUCCESS Success
1455 PCI_IO_DEVICE
*PciDev
,
1456 PCI_RESOURCE_NODE
**IoBridge
,
1457 PCI_RESOURCE_NODE
**Mem32Bridge
,
1458 PCI_RESOURCE_NODE
**PMem32Bridge
,
1459 PCI_RESOURCE_NODE
**Mem64Bridge
,
1460 PCI_RESOURCE_NODE
**PMem64Bridge
,
1461 PCI_RESOURCE_NODE
*IoPool
,
1462 PCI_RESOURCE_NODE
*Mem32Pool
,
1463 PCI_RESOURCE_NODE
*PMem32Pool
,
1464 PCI_RESOURCE_NODE
*Mem64Pool
,
1465 PCI_RESOURCE_NODE
*PMem64Pool
1469 PCI_RESOURCE_NODE
*Temp
;
1470 LIST_ENTRY
*CurrentLink
;
1472 CurrentLink
= IoPool
->ChildList
.ForwardLink
;
1475 // Get Io resource map
1477 while (CurrentLink
!= &IoPool
->ChildList
) {
1479 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1481 if (Temp
->PciDev
== PciDev
) {
1485 CurrentLink
= CurrentLink
->ForwardLink
;
1489 // Get Mem32 resource map
1491 CurrentLink
= Mem32Pool
->ChildList
.ForwardLink
;
1493 while (CurrentLink
!= &Mem32Pool
->ChildList
) {
1495 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1497 if (Temp
->PciDev
== PciDev
) {
1498 *Mem32Bridge
= Temp
;
1501 CurrentLink
= CurrentLink
->ForwardLink
;
1505 // Get Pmem32 resource map
1507 CurrentLink
= PMem32Pool
->ChildList
.ForwardLink
;
1509 while (CurrentLink
!= &PMem32Pool
->ChildList
) {
1511 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1513 if (Temp
->PciDev
== PciDev
) {
1514 *PMem32Bridge
= Temp
;
1517 CurrentLink
= CurrentLink
->ForwardLink
;
1521 // Get Mem64 resource map
1523 CurrentLink
= Mem64Pool
->ChildList
.ForwardLink
;
1525 while (CurrentLink
!= &Mem64Pool
->ChildList
) {
1527 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1529 if (Temp
->PciDev
== PciDev
) {
1530 *Mem64Bridge
= Temp
;
1533 CurrentLink
= CurrentLink
->ForwardLink
;
1537 // Get Pmem64 resource map
1539 CurrentLink
= PMem64Pool
->ChildList
.ForwardLink
;
1541 while (CurrentLink
!= &PMem64Pool
->ChildList
) {
1543 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1545 if (Temp
->PciDev
== PciDev
) {
1546 *PMem64Bridge
= Temp
;
1549 CurrentLink
= CurrentLink
->ForwardLink
;
1556 Destory given resource tree
1558 @param Bridge root node of resource tree
1560 @retval EFI_SUCCESS Success
1563 DestroyResourceTree (
1564 IN PCI_RESOURCE_NODE
*Bridge
1567 PCI_RESOURCE_NODE
*Temp
;
1568 LIST_ENTRY
*CurrentLink
;
1570 while (!IsListEmpty (&Bridge
->ChildList
)) {
1572 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1574 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1576 RemoveEntryList (CurrentLink
);
1578 if (IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
))) {
1579 DestroyResourceTree (Temp
);
1582 gBS
->FreePool (Temp
);
1589 Record the reserved resource and insert to reserved list.
1591 @param Base Base address of reserved resourse
1592 @param Length Length of reserved resource
1593 @param ResType Resource type
1594 @param Bridge Pci device instance
1597 RecordReservedResource (
1600 IN PCI_BAR_TYPE ResType
,
1601 IN PCI_IO_DEVICE
*Bridge
1604 PCI_RESERVED_RESOURCE_LIST
*ReservedNode
;
1606 ReservedNode
= AllocatePool (sizeof (PCI_RESERVED_RESOURCE_LIST
));
1607 if (ReservedNode
== NULL
) {
1608 return EFI_OUT_OF_RESOURCES
;
1611 ReservedNode
->Signature
= RESERVED_RESOURCE_SIGNATURE
;
1612 ReservedNode
->Node
.Base
= Base
;
1613 ReservedNode
->Node
.Length
= Length
;
1614 ReservedNode
->Node
.ResType
= ResType
;
1616 InsertTailList (&Bridge
->ReservedResourceList
, &(ReservedNode
->Link
));
1622 Insert resource padding for P2C
1624 @param PciDev Pci device instance
1625 @param IoNode Resource info node for IO
1626 @param Mem32Node Resource info node for 32-bit memory
1627 @param PMem32Node Resource info node for 32-bit PMemory
1628 @param Mem64Node Resource info node for 64-bit memory
1629 @param PMem64Node Resource info node for 64-bit PMemory
1631 @retval EFI_SUCCESS Success
1634 ResourcePaddingForCardBusBridge (
1635 PCI_IO_DEVICE
*PciDev
,
1636 PCI_RESOURCE_NODE
*IoNode
,
1637 PCI_RESOURCE_NODE
*Mem32Node
,
1638 PCI_RESOURCE_NODE
*PMem32Node
,
1639 PCI_RESOURCE_NODE
*Mem64Node
,
1640 PCI_RESOURCE_NODE
*PMem64Node
1643 PCI_RESOURCE_NODE
*Node
;
1648 // Memory Base/Limit Register 0
1649 // Bar 1 denodes memory range 0
1651 Node
= CreateResourceNode (
1660 InsertResourceNode (
1666 // Memory Base/Limit Register 1
1667 // Bar 2 denodes memory range1
1669 Node
= CreateResourceNode (
1678 InsertResourceNode (
1685 // Bar 3 denodes io range 0
1687 Node
= CreateResourceNode (
1696 InsertResourceNode (
1703 // Bar 4 denodes io range 0
1705 Node
= CreateResourceNode (
1714 InsertResourceNode (
1723 Program P2C register for given resource node
1725 @param Base Base address of P2C device
1726 @param Node Given resource node.
1728 @retval EFI_SUCCESS Success
1733 IN PCI_RESOURCE_NODE
*Node
1736 EFI_PCI_IO_PROTOCOL
*PciIo
;
1739 UINT16 BridgeControl
;
1742 PciIo
= &(Node
->PciDev
->PciIo
);
1744 Address
= Base
+ Node
->Offset
;
1747 // Indicate pci bus driver has allocated
1748 // resource for this device
1749 // It might be a temporary solution here since
1750 // pci device could have multiple bar
1752 Node
->PciDev
->Allocated
= TRUE
;
1754 switch (Node
->Bar
) {
1759 EfiPciIoWidthUint32
,
1760 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1765 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1766 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1772 EfiPciIoWidthUint32
,
1778 TempAddress
= Address
+ Node
->Length
- 1;
1781 EfiPciIoWidthUint32
,
1787 if (Node
->ResType
== PciBarTypeMem32
) {
1790 // Set non-prefetchable bit
1794 EfiPciIoWidthUint16
,
1800 BridgeControl
&= 0xfeff;
1803 EfiPciIoWidthUint16
,
1812 // Set pre-fetchable bit
1816 EfiPciIoWidthUint16
,
1822 BridgeControl
|= 0x0100;
1825 EfiPciIoWidthUint16
,
1832 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1833 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1834 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1841 EfiPciIoWidthUint32
,
1847 TempAddress
= Address
+ Node
->Length
- 1;
1851 EfiPciIoWidthUint32
,
1857 if (Node
->ResType
== PciBarTypeMem32
) {
1860 // Set non-prefetchable bit
1864 EfiPciIoWidthUint16
,
1870 BridgeControl
&= 0xfdff;
1873 EfiPciIoWidthUint16
,
1881 // Set pre-fetchable bit
1885 EfiPciIoWidthUint16
,
1891 BridgeControl
|= 0x0200;
1894 EfiPciIoWidthUint16
,
1901 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1902 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1903 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1909 EfiPciIoWidthUint32
,
1914 TempAddress
= Address
+ Node
->Length
- 1;
1917 EfiPciIoWidthUint32
,
1923 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1924 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1925 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1932 EfiPciIoWidthUint32
,
1938 TempAddress
= Address
+ Node
->Length
- 1;
1941 EfiPciIoWidthUint32
,
1947 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1948 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1949 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1960 Create padding resource node.
1962 @param PciDev Pci device instance
1963 @param IoNode Resource info node for IO
1964 @param Mem32Node Resource info node for 32-bit memory
1965 @param PMem32Node Resource info node for 32-bit PMemory
1966 @param Mem64Node Resource info node for 64-bit memory
1967 @param PMem64Node Resource info node for 64-bit PMemory
1969 @retval EFI_SUCCESS Success
1973 ApplyResourcePadding (
1974 PCI_IO_DEVICE
*PciDev
,
1975 PCI_RESOURCE_NODE
*IoNode
,
1976 PCI_RESOURCE_NODE
*Mem32Node
,
1977 PCI_RESOURCE_NODE
*PMem32Node
,
1978 PCI_RESOURCE_NODE
*Mem64Node
,
1979 PCI_RESOURCE_NODE
*PMem64Node
1982 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1983 PCI_RESOURCE_NODE
*Node
;
1984 UINT8 DummyBarIndex
;
1987 Ptr
= PciDev
->ResourcePaddingDescriptors
;
1989 while (((EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1991 if (Ptr
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Ptr
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
) {
1992 if (Ptr
->AddrLen
!= 0) {
1994 Node
= CreateResourceNode (
2002 InsertResourceNode (
2012 if (Ptr
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Ptr
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
2014 if (Ptr
->AddrSpaceGranularity
== 32) {
2019 if (Ptr
->SpecificFlag
== 0x6) {
2021 Node
= CreateResourceNode (
2029 InsertResourceNode (
2042 if (Ptr
->SpecificFlag
== 0) {
2044 Node
= CreateResourceNode (
2052 InsertResourceNode (
2063 if (Ptr
->AddrSpaceGranularity
== 64) {
2068 if (Ptr
->SpecificFlag
== 0x6) {
2070 Node
= CreateResourceNode (
2078 InsertResourceNode (
2091 if (Ptr
->SpecificFlag
== 0) {
2093 Node
= CreateResourceNode (
2101 InsertResourceNode (
2120 Get padding resource for PPB
2121 Light PCI bus driver woundn't support hotplug root device
2122 So no need to pad resource for them
2124 @param PciIoDevice Pci device instance
2127 GetResourcePaddingPpb (
2128 IN PCI_IO_DEVICE
*PciIoDevice
2131 if (gPciHotPlugInit
!= NULL
) {
2132 if (PciIoDevice
->ResourcePaddingDescriptors
== NULL
) {
2133 GetResourcePaddingForHpb (PciIoDevice
);