2 PCI resouces support functions implemntation for PCI Bus module.
4 Copyright (c) 2006 - 2009, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 The function is used to skip VGA range.
20 @param Start Returned start address including VGA range.
21 @param Length The length of VGA range.
35 ASSERT (Start
!= NULL
);
37 // For legacy VGA, bit 10 to bit 15 is not decoded
42 StartOffset
= Original
& Mask
;
43 LimitOffset
= ((*Start
) + Length
- 1) & Mask
;
44 if (LimitOffset
>= VGABASE1
) {
45 *Start
= *Start
- StartOffset
+ VGALIMIT2
+ 1;
50 This function is used to skip ISA aliasing aperture.
52 @param Start Returned start address including ISA aliasing aperture.
53 @param Length The length of ISA aliasing aperture.
57 SkipIsaAliasAperture (
68 ASSERT (Start
!= NULL
);
71 // For legacy ISA, bit 10 to bit 15 is not decoded
76 StartOffset
= Original
& Mask
;
77 LimitOffset
= ((*Start
) + Length
- 1) & Mask
;
79 if (LimitOffset
>= ISABASE
) {
80 *Start
= *Start
- StartOffset
+ ISALIMIT
+ 1;
85 This function inserts a resource node into the resource list.
86 The resource list is sorted in descend order.
88 @param Bridge PCI resource node for bridge.
89 @param ResNode Resource node want to be inserted.
94 IN PCI_RESOURCE_NODE
*Bridge
,
95 IN PCI_RESOURCE_NODE
*ResNode
98 LIST_ENTRY
*CurrentLink
;
99 PCI_RESOURCE_NODE
*Temp
;
100 UINT64 ResNodeAlignRest
;
101 UINT64 TempAlignRest
;
103 ASSERT (Bridge
!= NULL
);
104 ASSERT (ResNode
!= NULL
);
106 InsertHeadList (&Bridge
->ChildList
, &ResNode
->Link
);
108 CurrentLink
= Bridge
->ChildList
.ForwardLink
->ForwardLink
;
109 while (CurrentLink
!= &Bridge
->ChildList
) {
110 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
112 if (ResNode
->Alignment
> Temp
->Alignment
) {
114 } else if (ResNode
->Alignment
== Temp
->Alignment
) {
115 ResNodeAlignRest
= ResNode
->Length
& ResNode
->Alignment
;
116 TempAlignRest
= Temp
->Length
& Temp
->Alignment
;
117 if ((ResNodeAlignRest
== 0) || (ResNodeAlignRest
>= TempAlignRest
)) {
122 SwapListEntries (&ResNode
->Link
, CurrentLink
);
124 CurrentLink
= ResNode
->Link
.ForwardLink
;
129 This routine is used to merge two different resource trees in need of
132 For example, if an upstream PPB doesn't support,
133 prefetchable memory decoding, the PCI bus driver will choose to call this function
134 to merge prefectchable memory resource list into normal memory list.
136 If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
138 If Dst is NULL or Res is NULL, ASSERT ().
140 @param Dst Point to destination resource tree.
141 @param Res Point to source resource tree.
142 @param TypeMerge If the TypeMerge is TRUE, Res resource type is changed to the type of
143 destination resource type.
148 IN PCI_RESOURCE_NODE
*Dst
,
149 IN PCI_RESOURCE_NODE
*Res
,
154 LIST_ENTRY
*CurrentLink
;
155 PCI_RESOURCE_NODE
*Temp
;
157 ASSERT (Dst
!= NULL
);
158 ASSERT (Res
!= NULL
);
160 while (!IsListEmpty (&Res
->ChildList
)) {
161 CurrentLink
= Res
->ChildList
.ForwardLink
;
163 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
166 Temp
->ResType
= Dst
->ResType
;
169 RemoveEntryList (CurrentLink
);
170 InsertResourceNode (Dst
, Temp
);
175 This function is used to calculate the IO16 aperture
178 @param Bridge PCI resource node for bridge.
182 CalculateApertureIo16 (
183 IN PCI_RESOURCE_NODE
*Bridge
188 LIST_ENTRY
*CurrentLink
;
189 PCI_RESOURCE_NODE
*Node
;
193 EFI_PCI_PLATFORM_POLICY PciPolicy
;
196 // Always assume there is ISA device and VGA device on the platform
197 // will be customized later
203 // Check PciPlatform policy
205 if (gPciPlatformProtocol
!= NULL
) {
206 Status
= gPciPlatformProtocol
->GetPlatformPolicy (
207 gPciPlatformProtocol
,
210 if (!EFI_ERROR (Status
)) {
211 if ((PciPolicy
& EFI_RESERVE_ISA_IO_ALIAS
) != 0) {
214 if ((PciPolicy
& EFI_RESERVE_VGA_IO_ALIAS
) != 0) {
222 if (Bridge
== NULL
) {
226 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
229 // Assume the bridge is aligned
231 while (CurrentLink
!= &Bridge
->ChildList
) {
233 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
236 // Consider the aperture alignment
238 Offset
= Aperture
& (Node
->Alignment
);
242 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - Offset
;
247 // IsaEnable and VGAEnable can not be implemented now.
248 // If both of them are enabled, then the IO resource would
249 // become too limited to meet the requirement of most of devices.
251 if (IsaEnable
|| VGAEnable
) {
252 if (!IS_PCI_BRIDGE (&(Node
->PciDev
->Pci
)) && !IS_CARDBUS_BRIDGE (&(Node
->PciDev
->Pci
))) {
254 // Check if there is need to support ISA/VGA decoding
255 // If so, we need to avoid isa/vga aliasing range
258 SkipIsaAliasAperture (
262 Offset
= Aperture
& (Node
->Alignment
);
264 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - Offset
;
266 } else if (VGAEnable
) {
271 Offset
= Aperture
& (Node
->Alignment
);
273 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - Offset
;
279 Node
->Offset
= Aperture
;
282 // Increment aperture by the length of node
284 Aperture
+= Node
->Length
;
286 CurrentLink
= CurrentLink
->ForwardLink
;
290 // At last, adjust the aperture with the bridge's
293 Offset
= Aperture
& (Bridge
->Alignment
);
296 Aperture
= Aperture
+ (Bridge
->Alignment
+ 1) - Offset
;
299 Bridge
->Length
= Aperture
;
301 // At last, adjust the bridge's alignment to the first child's alignment
302 // if the bridge has at least one child
304 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
305 if (CurrentLink
!= &Bridge
->ChildList
) {
306 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
307 if (Node
->Alignment
> Bridge
->Alignment
) {
308 Bridge
->Alignment
= Node
->Alignment
;
314 This function is used to calculate the resource aperture
315 for a given bridge device.
317 @param Bridge PCI resouce node for given bridge device.
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
) {
339 CalculateApertureIo16 (Bridge
);
343 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
346 // Assume the bridge is aligned
348 while (CurrentLink
!= &Bridge
->ChildList
) {
350 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
353 // Apply padding resource if available
356 Offset
= Aperture
& (Node
->Alignment
);
360 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - Offset
;
365 // Recode current aperture as a offset
366 // this offset will be used in future real allocation
368 Node
->Offset
= Aperture
;
371 // Increment aperture by the length of node
373 Aperture
+= Node
->Length
;
376 // Consider the aperture alignment
379 CurrentLink
= CurrentLink
->ForwardLink
;
383 // At last, adjust the aperture with the bridge's
386 Offset
= Aperture
& (Bridge
->Alignment
);
388 Aperture
= Aperture
+ (Bridge
->Alignment
+ 1) - Offset
;
392 // If the bridge has already padded the resource and the
393 // amount of padded resource is larger, then keep the
396 if (Bridge
->Length
< Aperture
) {
397 Bridge
->Length
= Aperture
;
401 // At last, adjust the bridge's alignment to the first child's alignment
402 // if the bridge has at least one child
404 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
405 if (CurrentLink
!= &Bridge
->ChildList
) {
406 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
407 if (Node
->Alignment
> Bridge
->Alignment
) {
408 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 Prefetchable Memory.
420 @param Mem64Node Resource info node for 64-bit memory.
421 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
425 GetResourceFromDevice (
426 IN PCI_IO_DEVICE
*PciDev
,
427 IN PCI_RESOURCE_NODE
*IoNode
,
428 IN PCI_RESOURCE_NODE
*Mem32Node
,
429 IN PCI_RESOURCE_NODE
*PMem32Node
,
430 IN PCI_RESOURCE_NODE
*Mem64Node
,
431 IN PCI_RESOURCE_NODE
*PMem64Node
436 PCI_RESOURCE_NODE
*Node
;
437 BOOLEAN ResourceRequested
;
440 ResourceRequested
= FALSE
;
442 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
444 switch ((PciDev
->PciBar
)[Index
].BarType
) {
446 case PciBarTypeMem32
:
448 Node
= CreateResourceNode (
450 (PciDev
->PciBar
)[Index
].Length
,
451 (PciDev
->PciBar
)[Index
].Alignment
,
462 ResourceRequested
= TRUE
;
465 case PciBarTypeMem64
:
467 Node
= CreateResourceNode (
469 (PciDev
->PciBar
)[Index
].Length
,
470 (PciDev
->PciBar
)[Index
].Alignment
,
481 ResourceRequested
= TRUE
;
484 case PciBarTypePMem64
:
486 Node
= CreateResourceNode (
488 (PciDev
->PciBar
)[Index
].Length
,
489 (PciDev
->PciBar
)[Index
].Alignment
,
500 ResourceRequested
= TRUE
;
503 case PciBarTypePMem32
:
505 Node
= CreateResourceNode (
507 (PciDev
->PciBar
)[Index
].Length
,
508 (PciDev
->PciBar
)[Index
].Alignment
,
518 ResourceRequested
= TRUE
;
524 Node
= CreateResourceNode (
526 (PciDev
->PciBar
)[Index
].Length
,
527 (PciDev
->PciBar
)[Index
].Alignment
,
537 ResourceRequested
= TRUE
;
540 case PciBarTypeUnknown
:
549 // If there is no resource requested from this device,
550 // then we indicate this device has been allocated naturally.
552 if (!ResourceRequested
) {
553 PciDev
->Allocated
= TRUE
;
558 This function is used to create a resource node.
560 @param PciDev Pci device instance.
561 @param Length Length of Io/Memory resource.
562 @param Alignment Alignment of resource.
563 @param Bar Bar index.
564 @param ResType Type of resource: IO/Memory.
565 @param ResUsage Resource usage.
567 @return PCI resource node created for given PCI device.
568 NULL means PCI resource node is not created.
573 IN PCI_IO_DEVICE
*PciDev
,
577 IN PCI_BAR_TYPE ResType
,
578 IN PCI_RESOURCE_USAGE ResUsage
581 PCI_RESOURCE_NODE
*Node
;
585 Node
= AllocatePool (sizeof (PCI_RESOURCE_NODE
));
586 ASSERT (Node
!= NULL
);
591 ZeroMem (Node
, sizeof (PCI_RESOURCE_NODE
));
593 Node
->Signature
= PCI_RESOURCE_SIGNATURE
;
594 Node
->PciDev
= PciDev
;
595 Node
->Length
= Length
;
596 Node
->Alignment
= Alignment
;
598 Node
->ResType
= ResType
;
599 Node
->Reserved
= FALSE
;
600 Node
->ResourceUsage
= ResUsage
;
601 InitializeListHead (&Node
->ChildList
);
607 This function is used to extract resource request from
610 @param Bridge Pci device instance.
611 @param IoNode Resource info node for IO.
612 @param Mem32Node Resource info node for 32-bit memory.
613 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
614 @param Mem64Node Resource info node for 64-bit memory.
615 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
620 IN PCI_IO_DEVICE
*Bridge
,
621 IN PCI_RESOURCE_NODE
*IoNode
,
622 IN PCI_RESOURCE_NODE
*Mem32Node
,
623 IN PCI_RESOURCE_NODE
*PMem32Node
,
624 IN PCI_RESOURCE_NODE
*Mem64Node
,
625 IN PCI_RESOURCE_NODE
*PMem64Node
629 PCI_RESOURCE_NODE
*IoBridge
;
630 PCI_RESOURCE_NODE
*Mem32Bridge
;
631 PCI_RESOURCE_NODE
*PMem32Bridge
;
632 PCI_RESOURCE_NODE
*Mem64Bridge
;
633 PCI_RESOURCE_NODE
*PMem64Bridge
;
634 LIST_ENTRY
*CurrentLink
;
636 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
638 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
640 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
643 // Create resource nodes for this device by scanning the
644 // Bar array in the device private data
645 // If the upstream bridge doesn't support this device,
646 // no any resource node will be created for this device
648 GetResourceFromDevice (
657 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
660 // If the device has children, create a bridge resource node for this PPB
661 // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
662 // is aligned with 4KB
663 // This device is typically a bridge device like PPB and P2C
664 // Note: 0x1000 aligned
666 IoBridge
= CreateResourceNode (
675 Mem32Bridge
= CreateResourceNode (
684 PMem32Bridge
= CreateResourceNode (
693 Mem64Bridge
= CreateResourceNode (
702 PMem64Bridge
= CreateResourceNode (
712 // Recursively create resouce map on this bridge
723 if (ResourceRequestExisted (IoBridge
)) {
729 gBS
->FreePool (IoBridge
);
734 // If there is node under this resource bridge,
735 // then calculate bridge's aperture of this type
736 // and insert it into the respective resource tree.
737 // If no, delete this resource bridge
739 if (ResourceRequestExisted (Mem32Bridge
)) {
745 gBS
->FreePool (Mem32Bridge
);
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 (PMem32Bridge
)) {
761 gBS
->FreePool (PMem32Bridge
);
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 (Mem64Bridge
)) {
777 gBS
->FreePool (Mem64Bridge
);
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 (PMem64Bridge
)) {
793 gBS
->FreePool (PMem64Bridge
);
800 // If it is P2C, apply hard coded resource padding
803 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
804 ResourcePaddingForCardBusBridge (
814 CurrentLink
= CurrentLink
->ForwardLink
;
818 // To do some platform specific resource padding ...
820 ResourcePaddingPolicy (
830 // Degrade resource if necessary
841 // Calculate resource aperture for this bridge device
843 CalculateResourceAperture (Mem32Node
);
844 CalculateResourceAperture (PMem32Node
);
845 CalculateResourceAperture (Mem64Node
);
846 CalculateResourceAperture (PMem64Node
);
847 CalculateResourceAperture (IoNode
);
851 This function is used to do the resource padding for a specific platform.
853 @param PciDev Pci device instance.
854 @param IoNode Resource info node for IO.
855 @param Mem32Node Resource info node for 32-bit memory.
856 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
857 @param Mem64Node Resource info node for 64-bit memory.
858 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
862 ResourcePaddingPolicy (
863 IN PCI_IO_DEVICE
*PciDev
,
864 IN PCI_RESOURCE_NODE
*IoNode
,
865 IN PCI_RESOURCE_NODE
*Mem32Node
,
866 IN PCI_RESOURCE_NODE
*PMem32Node
,
867 IN PCI_RESOURCE_NODE
*Mem64Node
,
868 IN PCI_RESOURCE_NODE
*PMem64Node
872 // Create padding resource node
874 if (PciDev
->ResourcePaddingDescriptors
!= NULL
) {
875 ApplyResourcePadding (
887 This function is used to degrade resource if the upstream bridge
888 doesn't support certain resource. Degradation path is
889 PMEM64 -> MEM64 -> MEM32
890 PMEM64 -> PMEM32 -> MEM32
893 @param Bridge Pci device instance.
894 @param Mem32Node Resource info node for 32-bit memory.
895 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
896 @param Mem64Node Resource info node for 64-bit memory.
897 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
902 IN PCI_IO_DEVICE
*Bridge
,
903 IN PCI_RESOURCE_NODE
*Mem32Node
,
904 IN PCI_RESOURCE_NODE
*PMem32Node
,
905 IN PCI_RESOURCE_NODE
*Mem64Node
,
906 IN PCI_RESOURCE_NODE
*PMem64Node
911 LIST_ENTRY
*CurrentLink
;
914 // For RootBridge, PPB , P2C, go recursively to traverse all its children
915 // to find if this bridge and downstream has OptionRom.
918 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
919 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
921 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
922 if (Temp
->RomSize
!= 0) {
926 CurrentLink
= CurrentLink
->ForwardLink
;
930 // If bridge doesn't support Prefetchable
931 // memory64, degrade it to Prefetchable memory32
933 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
)) {
941 // if no PMem32 request and no OptionRom request, still keep PMem64. Otherwise degrade to PMem32
943 if ((PMem32Node
!= NULL
&& (PMem32Node
->Length
!= 0 && Bridge
->Parent
!= NULL
)) || HasOprom
) {
945 // Fixed the issue that there is no resource for 64-bit (above 4G)
957 // If bridge doesn't support Mem64
958 // degrade it to mem32
960 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_MEM64_DECODE_SUPPORTED
)) {
969 // If bridge doesn't support Pmem32
970 // degrade it to mem32
972 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
)) {
981 // if bridge supports combined Pmem Mem decoding
982 // merge these two type of resource
984 if (BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
)) {
1000 Test whether bridge device support decode resource.
1002 @param Bridge Bridge device instance.
1003 @param Decode Decode type according to resource type.
1005 @return TRUE The bridge device support decode resource.
1006 @return FALSE The bridge device don't support decode resource.
1010 BridgeSupportResourceDecode (
1011 IN PCI_IO_DEVICE
*Bridge
,
1015 if (((Bridge
->Decodes
) & Decode
) != 0) {
1023 This function is used to program the resource allocated
1024 for each resource node under specified bridge.
1026 @param Base Base address of resource to be progammed.
1027 @param Bridge PCI resource node for the bridge device.
1029 @retval EFI_SUCCESS Successfully to program all resouces
1030 on given PCI bridge device.
1031 @retval EFI_OUT_OF_RESOURCES Base is all one.
1037 IN PCI_RESOURCE_NODE
*Bridge
1040 LIST_ENTRY
*CurrentLink
;
1041 PCI_RESOURCE_NODE
*Node
;
1044 if (Base
== gAllOne
) {
1045 return EFI_OUT_OF_RESOURCES
;
1048 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1050 while (CurrentLink
!= &Bridge
->ChildList
) {
1052 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1054 if (!IS_PCI_BRIDGE (&(Node
->PciDev
->Pci
))) {
1056 if (IS_CARDBUS_BRIDGE (&(Node
->PciDev
->Pci
))) {
1058 // Program the PCI Card Bus device
1060 ProgramP2C (Base
, Node
);
1063 // Program the PCI device BAR
1065 ProgramBar (Base
, Node
);
1069 // Program the PCI devices under this bridge
1071 Status
= ProgramResource (Base
+ Node
->Offset
, Node
);
1072 if (EFI_ERROR (Status
)) {
1076 ProgramPpbApperture (Base
, Node
);
1079 CurrentLink
= CurrentLink
->ForwardLink
;
1086 Program Bar register for PCI device.
1088 @param Base Base address for PCI device resource to be progammed.
1089 @param Node Point to resoure node structure.
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 ASSERT (Node
->Bar
< PCI_MAX_BAR
);
1116 switch ((Node
->PciDev
->PciBar
[Node
->Bar
]).BarType
) {
1118 case PciBarTypeIo16
:
1119 case PciBarTypeIo32
:
1120 case PciBarTypeMem32
:
1121 case PciBarTypePMem32
:
1125 EfiPciIoWidthUint32
,
1126 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1131 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1135 case PciBarTypeMem64
:
1136 case PciBarTypePMem64
:
1138 Address32
= (UINT32
) (Address
& 0x00000000FFFFFFFF);
1142 EfiPciIoWidthUint32
,
1143 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1148 Address32
= (UINT32
) RShiftU64 (Address
, 32);
1152 EfiPciIoWidthUint32
,
1153 (UINT8
) ((Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
+ 4),
1158 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1168 Program PCI-PCI bridge apperture.
1170 @param Base Base address for resource.
1171 @param Node Point to resoure node structure.
1175 ProgramPpbApperture (
1177 IN PCI_RESOURCE_NODE
*Node
1180 EFI_PCI_IO_PROTOCOL
*PciIo
;
1186 // If no device resource of this PPB, return anyway
1187 // Apperture is set default in the initialization code
1189 if (Node
->Length
== 0 || Node
->ResourceUsage
== PciResUsagePadding
) {
1191 // For padding resource node, just ignore when programming
1196 PciIo
= &(Node
->PciDev
->PciIo
);
1197 Address
= Base
+ Node
->Offset
;
1200 // Indicate the PPB resource has been allocated
1202 Node
->PciDev
->Allocated
= TRUE
;
1204 switch (Node
->Bar
) {
1210 EfiPciIoWidthUint32
,
1211 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1216 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1217 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1223 Address32
= ((UINT32
) (Address
)) >> 8;
1235 EfiPciIoWidthUint16
,
1241 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1242 Address32
= ((UINT32
) (Address32
)) >> 8;
1254 EfiPciIoWidthUint16
,
1260 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1261 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1264 case PPB_MEM32_RANGE
:
1266 Address32
= ((UINT32
) (Address
)) >> 16;
1269 EfiPciIoWidthUint16
,
1275 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1276 Address32
= ((UINT32
) (Address32
)) >> 16;
1279 EfiPciIoWidthUint16
,
1285 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1286 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1289 case PPB_PMEM32_RANGE
:
1290 case PPB_PMEM64_RANGE
:
1292 Address32
= ((UINT32
) (Address
)) >> 16;
1295 EfiPciIoWidthUint16
,
1301 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1302 Address32
= ((UINT32
) (Address32
)) >> 16;
1305 EfiPciIoWidthUint16
,
1311 Address32
= (UINT32
) RShiftU64 (Address
, 32);
1314 EfiPciIoWidthUint32
,
1320 Address32
= (UINT32
) RShiftU64 ((Address
+ Node
->Length
- 1), 32);
1323 EfiPciIoWidthUint32
,
1329 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1330 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1339 Program parent bridge for Option Rom.
1341 @param PciDevice Pci deivce instance.
1342 @param OptionRomBase Base address for Optiona Rom.
1343 @param Enable Enable or disable PCI memory.
1347 ProgrameUpstreamBridgeForRom (
1348 IN PCI_IO_DEVICE
*PciDevice
,
1349 IN UINT32 OptionRomBase
,
1353 PCI_IO_DEVICE
*Parent
;
1354 PCI_RESOURCE_NODE Node
;
1356 // For root bridge, just return.
1358 Parent
= PciDevice
->Parent
;
1359 ZeroMem (&Node
, sizeof (Node
));
1360 while (Parent
!= NULL
) {
1361 if (!IS_PCI_BRIDGE (&Parent
->Pci
)) {
1365 Node
.PciDev
= Parent
;
1366 Node
.Length
= PciDevice
->RomSize
;
1368 Node
.Bar
= PPB_MEM32_RANGE
;
1369 Node
.ResType
= PciBarTypeMem32
;
1373 // Program PPB to only open a single <= 16MB apperture
1376 ProgramPpbApperture (OptionRomBase
, &Node
);
1377 PCI_ENABLE_COMMAND_REGISTER (Parent
, EFI_PCI_COMMAND_MEMORY_SPACE
);
1379 InitializePpb (Parent
);
1380 PCI_DISABLE_COMMAND_REGISTER (Parent
, EFI_PCI_COMMAND_MEMORY_SPACE
);
1383 Parent
= Parent
->Parent
;
1388 Test whether resource exists for a bridge.
1390 @param Bridge Point to resource node for a bridge.
1392 @retval TRUE There is resource on the given bridge.
1393 @retval FALSE There isn't resource on the given bridge.
1397 ResourceRequestExisted (
1398 IN PCI_RESOURCE_NODE
*Bridge
1401 if (Bridge
!= NULL
) {
1402 if (!IsListEmpty (&Bridge
->ChildList
) || Bridge
->Length
!= 0) {
1411 Initialize resource pool structure.
1413 @param ResourcePool Point to resource pool structure. This pool
1414 is reset to all zero when returned.
1415 @param ResourceType Type of resource.
1419 InitializeResourcePool (
1420 IN OUT PCI_RESOURCE_NODE
*ResourcePool
,
1421 IN PCI_BAR_TYPE ResourceType
1424 ZeroMem (ResourcePool
, sizeof (PCI_RESOURCE_NODE
));
1425 ResourcePool
->ResType
= ResourceType
;
1426 ResourcePool
->Signature
= PCI_RESOURCE_SIGNATURE
;
1427 InitializeListHead (&ResourcePool
->ChildList
);
1432 Get all resource information for given Pci device.
1434 @param PciDev Pci device instance.
1435 @param IoBridge Io resource node.
1436 @param Mem32Bridge 32-bit memory node.
1437 @param PMem32Bridge 32-bit Pmemory node.
1438 @param Mem64Bridge 64-bit memory node.
1439 @param PMem64Bridge 64-bit PMemory node.
1440 @param IoPool Link list header for Io resource.
1441 @param Mem32Pool Link list header for 32-bit memory.
1442 @param PMem32Pool Link list header for 32-bit Prefetchable memory.
1443 @param Mem64Pool Link list header for 64-bit memory.
1444 @param PMem64Pool Link list header for 64-bit Prefetchable memory.
1449 IN PCI_IO_DEVICE
*PciDev
,
1450 IN PCI_RESOURCE_NODE
**IoBridge
,
1451 IN PCI_RESOURCE_NODE
**Mem32Bridge
,
1452 IN PCI_RESOURCE_NODE
**PMem32Bridge
,
1453 IN PCI_RESOURCE_NODE
**Mem64Bridge
,
1454 IN PCI_RESOURCE_NODE
**PMem64Bridge
,
1455 IN PCI_RESOURCE_NODE
*IoPool
,
1456 IN PCI_RESOURCE_NODE
*Mem32Pool
,
1457 IN PCI_RESOURCE_NODE
*PMem32Pool
,
1458 IN PCI_RESOURCE_NODE
*Mem64Pool
,
1459 IN PCI_RESOURCE_NODE
*PMem64Pool
1463 PCI_RESOURCE_NODE
*Temp
;
1464 LIST_ENTRY
*CurrentLink
;
1466 CurrentLink
= IoPool
->ChildList
.ForwardLink
;
1469 // Get Io resource map
1471 while (CurrentLink
!= &IoPool
->ChildList
) {
1473 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1475 if (Temp
->PciDev
== PciDev
) {
1479 CurrentLink
= CurrentLink
->ForwardLink
;
1483 // Get Mem32 resource map
1485 CurrentLink
= Mem32Pool
->ChildList
.ForwardLink
;
1487 while (CurrentLink
!= &Mem32Pool
->ChildList
) {
1489 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1491 if (Temp
->PciDev
== PciDev
) {
1492 *Mem32Bridge
= Temp
;
1495 CurrentLink
= CurrentLink
->ForwardLink
;
1499 // Get Pmem32 resource map
1501 CurrentLink
= PMem32Pool
->ChildList
.ForwardLink
;
1503 while (CurrentLink
!= &PMem32Pool
->ChildList
) {
1505 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1507 if (Temp
->PciDev
== PciDev
) {
1508 *PMem32Bridge
= Temp
;
1511 CurrentLink
= CurrentLink
->ForwardLink
;
1515 // Get Mem64 resource map
1517 CurrentLink
= Mem64Pool
->ChildList
.ForwardLink
;
1519 while (CurrentLink
!= &Mem64Pool
->ChildList
) {
1521 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1523 if (Temp
->PciDev
== PciDev
) {
1524 *Mem64Bridge
= Temp
;
1527 CurrentLink
= CurrentLink
->ForwardLink
;
1531 // Get Pmem64 resource map
1533 CurrentLink
= PMem64Pool
->ChildList
.ForwardLink
;
1535 while (CurrentLink
!= &PMem64Pool
->ChildList
) {
1537 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1539 if (Temp
->PciDev
== PciDev
) {
1540 *PMem64Bridge
= Temp
;
1543 CurrentLink
= CurrentLink
->ForwardLink
;
1548 Destory given resource tree.
1550 @param Bridge PCI resource root node of resource tree.
1554 DestroyResourceTree (
1555 IN PCI_RESOURCE_NODE
*Bridge
1558 PCI_RESOURCE_NODE
*Temp
;
1559 LIST_ENTRY
*CurrentLink
;
1561 while (!IsListEmpty (&Bridge
->ChildList
)) {
1563 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1565 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1568 RemoveEntryList (CurrentLink
);
1570 if (IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
))) {
1571 DestroyResourceTree (Temp
);
1579 Insert resource padding for P2C.
1581 @param PciDev Pci device instance.
1582 @param IoNode Resource info node for IO.
1583 @param Mem32Node Resource info node for 32-bit memory.
1584 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1585 @param Mem64Node Resource info node for 64-bit memory.
1586 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1590 ResourcePaddingForCardBusBridge (
1591 IN PCI_IO_DEVICE
*PciDev
,
1592 IN PCI_RESOURCE_NODE
*IoNode
,
1593 IN PCI_RESOURCE_NODE
*Mem32Node
,
1594 IN PCI_RESOURCE_NODE
*PMem32Node
,
1595 IN PCI_RESOURCE_NODE
*Mem64Node
,
1596 IN PCI_RESOURCE_NODE
*PMem64Node
1599 PCI_RESOURCE_NODE
*Node
;
1604 // Memory Base/Limit Register 0
1605 // Bar 1 denodes memory range 0
1607 Node
= CreateResourceNode (
1616 InsertResourceNode (
1622 // Memory Base/Limit Register 1
1623 // Bar 2 denodes memory range1
1625 Node
= CreateResourceNode (
1634 InsertResourceNode (
1641 // Bar 3 denodes io range 0
1643 Node
= CreateResourceNode (
1652 InsertResourceNode (
1659 // Bar 4 denodes io range 0
1661 Node
= CreateResourceNode (
1670 InsertResourceNode (
1677 Program PCI Card device register for given resource node.
1679 @param Base Base address of PCI Card device to be programmed.
1680 @param Node Given resource node.
1686 IN PCI_RESOURCE_NODE
*Node
1689 EFI_PCI_IO_PROTOCOL
*PciIo
;
1692 UINT16 BridgeControl
;
1695 PciIo
= &(Node
->PciDev
->PciIo
);
1697 Address
= Base
+ Node
->Offset
;
1700 // Indicate pci bus driver has allocated
1701 // resource for this device
1702 // It might be a temporary solution here since
1703 // pci device could have multiple bar
1705 Node
->PciDev
->Allocated
= TRUE
;
1707 switch (Node
->Bar
) {
1712 EfiPciIoWidthUint32
,
1713 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1718 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1719 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1725 EfiPciIoWidthUint32
,
1726 PCI_CARD_MEMORY_BASE_0
,
1731 TempAddress
= Address
+ Node
->Length
- 1;
1734 EfiPciIoWidthUint32
,
1735 PCI_CARD_MEMORY_LIMIT_0
,
1740 if (Node
->ResType
== PciBarTypeMem32
) {
1742 // Set non-prefetchable bit
1746 EfiPciIoWidthUint16
,
1747 PCI_CARD_BRIDGE_CONTROL
,
1752 BridgeControl
&= (UINT16
) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE
;
1755 EfiPciIoWidthUint16
,
1756 PCI_CARD_BRIDGE_CONTROL
,
1763 // Set pre-fetchable bit
1767 EfiPciIoWidthUint16
,
1768 PCI_CARD_BRIDGE_CONTROL
,
1773 BridgeControl
|= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE
;
1776 EfiPciIoWidthUint16
,
1777 PCI_CARD_BRIDGE_CONTROL
,
1783 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1784 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1785 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1792 EfiPciIoWidthUint32
,
1793 PCI_CARD_MEMORY_BASE_1
,
1798 TempAddress
= Address
+ Node
->Length
- 1;
1802 EfiPciIoWidthUint32
,
1803 PCI_CARD_MEMORY_LIMIT_1
,
1808 if (Node
->ResType
== PciBarTypeMem32
) {
1811 // Set non-prefetchable bit
1815 EfiPciIoWidthUint16
,
1816 PCI_CARD_BRIDGE_CONTROL
,
1821 BridgeControl
&= (UINT16
) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE
);
1824 EfiPciIoWidthUint16
,
1825 PCI_CARD_BRIDGE_CONTROL
,
1833 // Set pre-fetchable bit
1837 EfiPciIoWidthUint16
,
1838 PCI_CARD_BRIDGE_CONTROL
,
1843 BridgeControl
|= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE
;
1846 EfiPciIoWidthUint16
,
1847 PCI_CARD_BRIDGE_CONTROL
,
1853 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1854 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1855 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1861 EfiPciIoWidthUint32
,
1862 PCI_CARD_IO_BASE_0_LOWER
,
1867 TempAddress
= Address
+ Node
->Length
- 1;
1870 EfiPciIoWidthUint32
,
1871 PCI_CARD_IO_LIMIT_0_LOWER
,
1876 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1877 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1878 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1885 EfiPciIoWidthUint32
,
1886 PCI_CARD_IO_BASE_1_LOWER
,
1891 TempAddress
= Address
+ Node
->Length
- 1;
1894 EfiPciIoWidthUint32
,
1895 PCI_CARD_IO_LIMIT_1_LOWER
,
1900 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1901 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1902 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1911 Create padding resource node.
1913 @param PciDev Pci device instance.
1914 @param IoNode Resource info node for IO.
1915 @param Mem32Node Resource info node for 32-bit memory.
1916 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1917 @param Mem64Node Resource info node for 64-bit memory.
1918 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1922 ApplyResourcePadding (
1923 IN PCI_IO_DEVICE
*PciDev
,
1924 IN PCI_RESOURCE_NODE
*IoNode
,
1925 IN PCI_RESOURCE_NODE
*Mem32Node
,
1926 IN PCI_RESOURCE_NODE
*PMem32Node
,
1927 IN PCI_RESOURCE_NODE
*Mem64Node
,
1928 IN PCI_RESOURCE_NODE
*PMem64Node
1931 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1932 PCI_RESOURCE_NODE
*Node
;
1933 UINT8 DummyBarIndex
;
1936 Ptr
= PciDev
->ResourcePaddingDescriptors
;
1938 while (((EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1940 if (Ptr
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Ptr
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
) {
1941 if (Ptr
->AddrLen
!= 0) {
1943 Node
= CreateResourceNode (
1951 InsertResourceNode (
1961 if (Ptr
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Ptr
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
1963 if (Ptr
->AddrSpaceGranularity
== 32) {
1968 if (Ptr
->SpecificFlag
== 0x6) {
1969 if (Ptr
->AddrLen
!= 0) {
1970 Node
= CreateResourceNode (
1978 InsertResourceNode (
1991 if (Ptr
->SpecificFlag
== 0) {
1992 if (Ptr
->AddrLen
!= 0) {
1993 Node
= CreateResourceNode (
2001 InsertResourceNode (
2012 if (Ptr
->AddrSpaceGranularity
== 64) {
2017 if (Ptr
->SpecificFlag
== 0x6) {
2018 if (Ptr
->AddrLen
!= 0) {
2019 Node
= CreateResourceNode (
2027 InsertResourceNode (
2040 if (Ptr
->SpecificFlag
== 0) {
2041 if (Ptr
->AddrLen
!= 0) {
2042 Node
= CreateResourceNode (
2050 InsertResourceNode (
2067 Get padding resource for PCI-PCI bridge.
2069 @param PciIoDevice PCI-PCI bridge device instance.
2071 @note Feature flag PcdPciBusHotplugDeviceSupport determines
2072 whether need to pad resource for them.
2075 GetResourcePaddingPpb (
2076 IN PCI_IO_DEVICE
*PciIoDevice
2079 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
2080 if (PciIoDevice
->ResourcePaddingDescriptors
== NULL
) {
2081 GetResourcePaddingForHpb (PciIoDevice
);