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 OUT 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
355 Offset
= Aperture
& (Node
->Alignment
);
359 Aperture
= Aperture
+ (Node
->Alignment
+ 1) - Offset
;
364 // Recode current aperture as a offset
365 // this offset will be used in future real allocation
367 Node
->Offset
= Aperture
;
370 // Increment aperture by the length of node
372 Aperture
+= Node
->Length
;
375 // 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
;
412 Get IO/Memory resource infor for given PCI device.
414 @param PciDev Pci device instance.
415 @param IoNode Resource info node for IO .
416 @param Mem32Node Resource info node for 32-bit memory.
417 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
418 @param Mem64Node Resource info node for 64-bit memory.
419 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
423 GetResourceFromDevice (
424 IN PCI_IO_DEVICE
*PciDev
,
425 IN OUT PCI_RESOURCE_NODE
*IoNode
,
426 IN OUT PCI_RESOURCE_NODE
*Mem32Node
,
427 IN OUT PCI_RESOURCE_NODE
*PMem32Node
,
428 IN OUT PCI_RESOURCE_NODE
*Mem64Node
,
429 IN OUT PCI_RESOURCE_NODE
*PMem64Node
434 PCI_RESOURCE_NODE
*Node
;
435 BOOLEAN ResourceRequested
;
438 ResourceRequested
= FALSE
;
440 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
442 switch ((PciDev
->PciBar
)[Index
].BarType
) {
444 case PciBarTypeMem32
:
446 Node
= CreateResourceNode (
448 (PciDev
->PciBar
)[Index
].Length
,
449 (PciDev
->PciBar
)[Index
].Alignment
,
460 ResourceRequested
= TRUE
;
463 case PciBarTypeMem64
:
465 Node
= CreateResourceNode (
467 (PciDev
->PciBar
)[Index
].Length
,
468 (PciDev
->PciBar
)[Index
].Alignment
,
479 ResourceRequested
= TRUE
;
482 case PciBarTypePMem64
:
484 Node
= CreateResourceNode (
486 (PciDev
->PciBar
)[Index
].Length
,
487 (PciDev
->PciBar
)[Index
].Alignment
,
498 ResourceRequested
= TRUE
;
501 case PciBarTypePMem32
:
503 Node
= CreateResourceNode (
505 (PciDev
->PciBar
)[Index
].Length
,
506 (PciDev
->PciBar
)[Index
].Alignment
,
516 ResourceRequested
= TRUE
;
522 Node
= CreateResourceNode (
524 (PciDev
->PciBar
)[Index
].Length
,
525 (PciDev
->PciBar
)[Index
].Alignment
,
535 ResourceRequested
= TRUE
;
538 case PciBarTypeUnknown
:
547 // If there is no resource requested from this device,
548 // then we indicate this device has been allocated naturally.
550 if (!ResourceRequested
) {
551 PciDev
->Allocated
= TRUE
;
556 This function is used to create a resource node.
558 @param PciDev Pci device instance.
559 @param Length Length of Io/Memory resource.
560 @param Alignment Alignment of resource.
561 @param Bar Bar index.
562 @param ResType Type of resource: IO/Memory.
563 @param ResUsage Resource usage.
565 @return PCI resource node created for given PCI device.
566 NULL means PCI resource node is not created.
571 IN PCI_IO_DEVICE
*PciDev
,
575 IN PCI_BAR_TYPE ResType
,
576 IN PCI_RESOURCE_USAGE ResUsage
579 PCI_RESOURCE_NODE
*Node
;
583 Node
= AllocateZeroPool (sizeof (PCI_RESOURCE_NODE
));
584 ASSERT (Node
!= NULL
);
589 Node
->Signature
= PCI_RESOURCE_SIGNATURE
;
590 Node
->PciDev
= PciDev
;
591 Node
->Length
= Length
;
592 Node
->Alignment
= Alignment
;
594 Node
->ResType
= ResType
;
595 Node
->Reserved
= FALSE
;
596 Node
->ResourceUsage
= ResUsage
;
597 InitializeListHead (&Node
->ChildList
);
603 This function is used to extract resource request from
606 @param Bridge Pci device instance.
607 @param IoNode Resource info node for IO.
608 @param Mem32Node Resource info node for 32-bit memory.
609 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
610 @param Mem64Node Resource info node for 64-bit memory.
611 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
616 IN PCI_IO_DEVICE
*Bridge
,
617 IN OUT PCI_RESOURCE_NODE
*IoNode
,
618 IN OUT PCI_RESOURCE_NODE
*Mem32Node
,
619 IN OUT PCI_RESOURCE_NODE
*PMem32Node
,
620 IN OUT PCI_RESOURCE_NODE
*Mem64Node
,
621 IN OUT PCI_RESOURCE_NODE
*PMem64Node
625 PCI_RESOURCE_NODE
*IoBridge
;
626 PCI_RESOURCE_NODE
*Mem32Bridge
;
627 PCI_RESOURCE_NODE
*PMem32Bridge
;
628 PCI_RESOURCE_NODE
*Mem64Bridge
;
629 PCI_RESOURCE_NODE
*PMem64Bridge
;
630 LIST_ENTRY
*CurrentLink
;
632 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
634 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
636 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
639 // Create resource nodes for this device by scanning the
640 // Bar array in the device private data
641 // If the upstream bridge doesn't support this device,
642 // no any resource node will be created for this device
644 GetResourceFromDevice (
653 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
656 // If the device has children, create a bridge resource node for this PPB
657 // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
658 // is aligned with 4KB
659 // This device is typically a bridge device like PPB and P2C
660 // Note: 0x1000 aligned
662 IoBridge
= CreateResourceNode (
671 Mem32Bridge
= CreateResourceNode (
680 PMem32Bridge
= CreateResourceNode (
689 Mem64Bridge
= CreateResourceNode (
698 PMem64Bridge
= CreateResourceNode (
708 // Recursively create resouce map on this bridge
719 if (ResourceRequestExisted (IoBridge
)) {
730 // If there is node under this resource bridge,
731 // then calculate bridge's aperture of this type
732 // and insert it into the respective resource tree.
733 // If no, delete this resource bridge
735 if (ResourceRequestExisted (Mem32Bridge
)) {
741 FreePool (Mem32Bridge
);
746 // If there is node under this resource bridge,
747 // then calculate bridge's aperture of this type
748 // and insert it into the respective resource tree.
749 // If no, delete this resource bridge
751 if (ResourceRequestExisted (PMem32Bridge
)) {
757 FreePool (PMem32Bridge
);
762 // If there is node under this resource bridge,
763 // then calculate bridge's aperture of this type
764 // and insert it into the respective resource tree.
765 // If no, delete this resource bridge
767 if (ResourceRequestExisted (Mem64Bridge
)) {
773 FreePool (Mem64Bridge
);
778 // If there is node under this resource bridge,
779 // then calculate bridge's aperture of this type
780 // and insert it into the respective resource tree.
781 // If no, delete this resource bridge
783 if (ResourceRequestExisted (PMem64Bridge
)) {
789 FreePool (PMem64Bridge
);
796 // If it is P2C, apply hard coded resource padding
798 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
799 ResourcePaddingForCardBusBridge (
809 CurrentLink
= CurrentLink
->ForwardLink
;
813 // To do some platform specific resource padding ...
815 ResourcePaddingPolicy (
825 // Degrade resource if necessary
836 // Calculate resource aperture for this bridge device
838 CalculateResourceAperture (Mem32Node
);
839 CalculateResourceAperture (PMem32Node
);
840 CalculateResourceAperture (Mem64Node
);
841 CalculateResourceAperture (PMem64Node
);
842 CalculateResourceAperture (IoNode
);
846 This function is used to do the resource padding for a specific platform.
848 @param PciDev Pci device instance.
849 @param IoNode Resource info node for IO.
850 @param Mem32Node Resource info node for 32-bit memory.
851 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
852 @param Mem64Node Resource info node for 64-bit memory.
853 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
857 ResourcePaddingPolicy (
858 IN PCI_IO_DEVICE
*PciDev
,
859 IN PCI_RESOURCE_NODE
*IoNode
,
860 IN PCI_RESOURCE_NODE
*Mem32Node
,
861 IN PCI_RESOURCE_NODE
*PMem32Node
,
862 IN PCI_RESOURCE_NODE
*Mem64Node
,
863 IN PCI_RESOURCE_NODE
*PMem64Node
867 // Create padding resource node
869 if (PciDev
->ResourcePaddingDescriptors
!= NULL
) {
870 ApplyResourcePadding (
882 This function is used to degrade resource if the upstream bridge
883 doesn't support certain resource. Degradation path is
884 PMEM64 -> MEM64 -> MEM32
885 PMEM64 -> PMEM32 -> MEM32
888 @param Bridge Pci device instance.
889 @param Mem32Node Resource info node for 32-bit memory.
890 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
891 @param Mem64Node Resource info node for 64-bit memory.
892 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
897 IN PCI_IO_DEVICE
*Bridge
,
898 IN PCI_RESOURCE_NODE
*Mem32Node
,
899 IN PCI_RESOURCE_NODE
*PMem32Node
,
900 IN PCI_RESOURCE_NODE
*Mem64Node
,
901 IN PCI_RESOURCE_NODE
*PMem64Node
906 LIST_ENTRY
*CurrentLink
;
909 // For RootBridge, PPB , P2C, go recursively to traverse all its children
910 // to find if this bridge and downstream has OptionRom.
913 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
914 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
916 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
917 if (Temp
->RomSize
!= 0) {
921 CurrentLink
= CurrentLink
->ForwardLink
;
925 // If bridge doesn't support Prefetchable
926 // memory64, degrade it to Prefetchable memory32
928 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
)) {
936 // if no PMem32 request and no OptionRom request, still keep PMem64. Otherwise degrade to PMem32
938 if ((PMem32Node
!= NULL
&& (PMem32Node
->Length
!= 0 && Bridge
->Parent
!= NULL
)) || HasOprom
) {
940 // Fixed the issue that there is no resource for 64-bit (above 4G)
952 // If bridge doesn't support Mem64
953 // degrade it to mem32
955 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_MEM64_DECODE_SUPPORTED
)) {
964 // If bridge doesn't support Pmem32
965 // degrade it to mem32
967 if (!BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
)) {
976 // if bridge supports combined Pmem Mem decoding
977 // merge these two type of resource
979 if (BridgeSupportResourceDecode (Bridge
, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
)) {
995 Test whether bridge device support decode resource.
997 @param Bridge Bridge device instance.
998 @param Decode Decode type according to resource type.
1000 @return TRUE The bridge device support decode resource.
1001 @return FALSE The bridge device don't support decode resource.
1005 BridgeSupportResourceDecode (
1006 IN PCI_IO_DEVICE
*Bridge
,
1010 if (((Bridge
->Decodes
) & Decode
) != 0) {
1018 This function is used to program the resource allocated
1019 for each resource node under specified bridge.
1021 @param Base Base address of resource to be progammed.
1022 @param Bridge PCI resource node for the bridge device.
1024 @retval EFI_SUCCESS Successfully to program all resouces
1025 on given PCI bridge device.
1026 @retval EFI_OUT_OF_RESOURCES Base is all one.
1032 IN PCI_RESOURCE_NODE
*Bridge
1035 LIST_ENTRY
*CurrentLink
;
1036 PCI_RESOURCE_NODE
*Node
;
1039 if (Base
== gAllOne
) {
1040 return EFI_OUT_OF_RESOURCES
;
1043 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1045 while (CurrentLink
!= &Bridge
->ChildList
) {
1047 Node
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1049 if (!IS_PCI_BRIDGE (&(Node
->PciDev
->Pci
))) {
1051 if (IS_CARDBUS_BRIDGE (&(Node
->PciDev
->Pci
))) {
1053 // Program the PCI Card Bus device
1055 ProgramP2C (Base
, Node
);
1058 // Program the PCI device BAR
1060 ProgramBar (Base
, Node
);
1064 // Program the PCI devices under this bridge
1066 Status
= ProgramResource (Base
+ Node
->Offset
, Node
);
1067 if (EFI_ERROR (Status
)) {
1071 ProgramPpbApperture (Base
, Node
);
1074 CurrentLink
= CurrentLink
->ForwardLink
;
1081 Program Bar register for PCI device.
1083 @param Base Base address for PCI device resource to be progammed.
1084 @param Node Point to resoure node structure.
1090 IN PCI_RESOURCE_NODE
*Node
1093 EFI_PCI_IO_PROTOCOL
*PciIo
;
1098 PciIo
= &(Node
->PciDev
->PciIo
);
1100 Address
= Base
+ Node
->Offset
;
1103 // Indicate pci bus driver has allocated
1104 // resource for this device
1105 // It might be a temporary solution here since
1106 // pci device could have multiple bar
1108 Node
->PciDev
->Allocated
= TRUE
;
1110 ASSERT (Node
->Bar
< PCI_MAX_BAR
);
1111 switch ((Node
->PciDev
->PciBar
[Node
->Bar
]).BarType
) {
1113 case PciBarTypeIo16
:
1114 case PciBarTypeIo32
:
1115 case PciBarTypeMem32
:
1116 case PciBarTypePMem32
:
1120 EfiPciIoWidthUint32
,
1121 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1126 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1130 case PciBarTypeMem64
:
1131 case PciBarTypePMem64
:
1133 Address32
= (UINT32
) (Address
& 0x00000000FFFFFFFF);
1137 EfiPciIoWidthUint32
,
1138 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1143 Address32
= (UINT32
) RShiftU64 (Address
, 32);
1147 EfiPciIoWidthUint32
,
1148 (UINT8
) ((Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
+ 4),
1153 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1163 Program PCI-PCI bridge apperture.
1165 @param Base Base address for resource.
1166 @param Node Point to resoure node structure.
1170 ProgramPpbApperture (
1172 IN PCI_RESOURCE_NODE
*Node
1175 EFI_PCI_IO_PROTOCOL
*PciIo
;
1181 // If no device resource of this PPB, return anyway
1182 // Apperture is set default in the initialization code
1184 if (Node
->Length
== 0 || Node
->ResourceUsage
== PciResUsagePadding
) {
1186 // For padding resource node, just ignore when programming
1191 PciIo
= &(Node
->PciDev
->PciIo
);
1192 Address
= Base
+ Node
->Offset
;
1195 // Indicate the PPB resource has been allocated
1197 Node
->PciDev
->Allocated
= TRUE
;
1199 switch (Node
->Bar
) {
1205 EfiPciIoWidthUint32
,
1206 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1211 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1212 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1218 Address32
= ((UINT32
) (Address
)) >> 8;
1230 EfiPciIoWidthUint16
,
1236 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1237 Address32
= ((UINT32
) (Address32
)) >> 8;
1249 EfiPciIoWidthUint16
,
1255 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1256 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1259 case PPB_MEM32_RANGE
:
1261 Address32
= ((UINT32
) (Address
)) >> 16;
1264 EfiPciIoWidthUint16
,
1270 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1271 Address32
= ((UINT32
) (Address32
)) >> 16;
1274 EfiPciIoWidthUint16
,
1280 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1281 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1284 case PPB_PMEM32_RANGE
:
1285 case PPB_PMEM64_RANGE
:
1287 Address32
= ((UINT32
) (Address
)) >> 16;
1290 EfiPciIoWidthUint16
,
1296 Address32
= (UINT32
) (Address
+ Node
->Length
- 1);
1297 Address32
= ((UINT32
) (Address32
)) >> 16;
1300 EfiPciIoWidthUint16
,
1306 Address32
= (UINT32
) RShiftU64 (Address
, 32);
1309 EfiPciIoWidthUint32
,
1315 Address32
= (UINT32
) RShiftU64 ((Address
+ Node
->Length
- 1), 32);
1318 EfiPciIoWidthUint32
,
1324 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1325 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1334 Program parent bridge for Option Rom.
1336 @param PciDevice Pci deivce instance.
1337 @param OptionRomBase Base address for Optiona Rom.
1338 @param Enable Enable or disable PCI memory.
1342 ProgrameUpstreamBridgeForRom (
1343 IN PCI_IO_DEVICE
*PciDevice
,
1344 IN UINT32 OptionRomBase
,
1348 PCI_IO_DEVICE
*Parent
;
1349 PCI_RESOURCE_NODE Node
;
1351 // For root bridge, just return.
1353 Parent
= PciDevice
->Parent
;
1354 ZeroMem (&Node
, sizeof (Node
));
1355 while (Parent
!= NULL
) {
1356 if (!IS_PCI_BRIDGE (&Parent
->Pci
)) {
1360 Node
.PciDev
= Parent
;
1361 Node
.Length
= PciDevice
->RomSize
;
1363 Node
.Bar
= PPB_MEM32_RANGE
;
1364 Node
.ResType
= PciBarTypeMem32
;
1368 // Program PPB to only open a single <= 16MB apperture
1371 ProgramPpbApperture (OptionRomBase
, &Node
);
1372 PCI_ENABLE_COMMAND_REGISTER (Parent
, EFI_PCI_COMMAND_MEMORY_SPACE
);
1374 InitializePpb (Parent
);
1375 PCI_DISABLE_COMMAND_REGISTER (Parent
, EFI_PCI_COMMAND_MEMORY_SPACE
);
1378 Parent
= Parent
->Parent
;
1383 Test whether resource exists for a bridge.
1385 @param Bridge Point to resource node for a bridge.
1387 @retval TRUE There is resource on the given bridge.
1388 @retval FALSE There isn't resource on the given bridge.
1392 ResourceRequestExisted (
1393 IN PCI_RESOURCE_NODE
*Bridge
1396 if (Bridge
!= NULL
) {
1397 if (!IsListEmpty (&Bridge
->ChildList
) || Bridge
->Length
!= 0) {
1406 Initialize resource pool structure.
1408 @param ResourcePool Point to resource pool structure. This pool
1409 is reset to all zero when returned.
1410 @param ResourceType Type of resource.
1414 InitializeResourcePool (
1415 IN OUT PCI_RESOURCE_NODE
*ResourcePool
,
1416 IN PCI_BAR_TYPE ResourceType
1419 ZeroMem (ResourcePool
, sizeof (PCI_RESOURCE_NODE
));
1420 ResourcePool
->ResType
= ResourceType
;
1421 ResourcePool
->Signature
= PCI_RESOURCE_SIGNATURE
;
1422 InitializeListHead (&ResourcePool
->ChildList
);
1427 Get all resource information for given Pci device.
1429 @param PciDev Pci device instance.
1430 @param IoBridge Io resource node.
1431 @param Mem32Bridge 32-bit memory node.
1432 @param PMem32Bridge 32-bit Pmemory node.
1433 @param Mem64Bridge 64-bit memory node.
1434 @param PMem64Bridge 64-bit PMemory node.
1435 @param IoPool Link list header for Io resource.
1436 @param Mem32Pool Link list header for 32-bit memory.
1437 @param PMem32Pool Link list header for 32-bit Prefetchable memory.
1438 @param Mem64Pool Link list header for 64-bit memory.
1439 @param PMem64Pool Link list header for 64-bit Prefetchable memory.
1444 IN PCI_IO_DEVICE
*PciDev
,
1445 IN PCI_RESOURCE_NODE
**IoBridge
,
1446 IN PCI_RESOURCE_NODE
**Mem32Bridge
,
1447 IN PCI_RESOURCE_NODE
**PMem32Bridge
,
1448 IN PCI_RESOURCE_NODE
**Mem64Bridge
,
1449 IN PCI_RESOURCE_NODE
**PMem64Bridge
,
1450 IN PCI_RESOURCE_NODE
*IoPool
,
1451 IN PCI_RESOURCE_NODE
*Mem32Pool
,
1452 IN PCI_RESOURCE_NODE
*PMem32Pool
,
1453 IN PCI_RESOURCE_NODE
*Mem64Pool
,
1454 IN PCI_RESOURCE_NODE
*PMem64Pool
1458 PCI_RESOURCE_NODE
*Temp
;
1459 LIST_ENTRY
*CurrentLink
;
1461 CurrentLink
= IoPool
->ChildList
.ForwardLink
;
1464 // Get Io resource map
1466 while (CurrentLink
!= &IoPool
->ChildList
) {
1468 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1470 if (Temp
->PciDev
== PciDev
) {
1474 CurrentLink
= CurrentLink
->ForwardLink
;
1478 // Get Mem32 resource map
1480 CurrentLink
= Mem32Pool
->ChildList
.ForwardLink
;
1482 while (CurrentLink
!= &Mem32Pool
->ChildList
) {
1484 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1486 if (Temp
->PciDev
== PciDev
) {
1487 *Mem32Bridge
= Temp
;
1490 CurrentLink
= CurrentLink
->ForwardLink
;
1494 // Get Pmem32 resource map
1496 CurrentLink
= PMem32Pool
->ChildList
.ForwardLink
;
1498 while (CurrentLink
!= &PMem32Pool
->ChildList
) {
1500 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1502 if (Temp
->PciDev
== PciDev
) {
1503 *PMem32Bridge
= Temp
;
1506 CurrentLink
= CurrentLink
->ForwardLink
;
1510 // Get Mem64 resource map
1512 CurrentLink
= Mem64Pool
->ChildList
.ForwardLink
;
1514 while (CurrentLink
!= &Mem64Pool
->ChildList
) {
1516 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1518 if (Temp
->PciDev
== PciDev
) {
1519 *Mem64Bridge
= Temp
;
1522 CurrentLink
= CurrentLink
->ForwardLink
;
1526 // Get Pmem64 resource map
1528 CurrentLink
= PMem64Pool
->ChildList
.ForwardLink
;
1530 while (CurrentLink
!= &PMem64Pool
->ChildList
) {
1532 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1534 if (Temp
->PciDev
== PciDev
) {
1535 *PMem64Bridge
= Temp
;
1538 CurrentLink
= CurrentLink
->ForwardLink
;
1543 Destory given resource tree.
1545 @param Bridge PCI resource root node of resource tree.
1549 DestroyResourceTree (
1550 IN PCI_RESOURCE_NODE
*Bridge
1553 PCI_RESOURCE_NODE
*Temp
;
1554 LIST_ENTRY
*CurrentLink
;
1556 while (!IsListEmpty (&Bridge
->ChildList
)) {
1558 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1560 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
1563 RemoveEntryList (CurrentLink
);
1565 if (IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
))) {
1566 DestroyResourceTree (Temp
);
1574 Insert resource padding for P2C.
1576 @param PciDev Pci device instance.
1577 @param IoNode Resource info node for IO.
1578 @param Mem32Node Resource info node for 32-bit memory.
1579 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1580 @param Mem64Node Resource info node for 64-bit memory.
1581 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1585 ResourcePaddingForCardBusBridge (
1586 IN PCI_IO_DEVICE
*PciDev
,
1587 IN PCI_RESOURCE_NODE
*IoNode
,
1588 IN PCI_RESOURCE_NODE
*Mem32Node
,
1589 IN PCI_RESOURCE_NODE
*PMem32Node
,
1590 IN PCI_RESOURCE_NODE
*Mem64Node
,
1591 IN PCI_RESOURCE_NODE
*PMem64Node
1594 PCI_RESOURCE_NODE
*Node
;
1599 // Memory Base/Limit Register 0
1600 // Bar 1 denodes memory range 0
1602 Node
= CreateResourceNode (
1611 InsertResourceNode (
1617 // Memory Base/Limit Register 1
1618 // Bar 2 denodes memory range1
1620 Node
= CreateResourceNode (
1629 InsertResourceNode (
1636 // Bar 3 denodes io range 0
1638 Node
= CreateResourceNode (
1647 InsertResourceNode (
1654 // Bar 4 denodes io range 0
1656 Node
= CreateResourceNode (
1665 InsertResourceNode (
1672 Program PCI Card device register for given resource node.
1674 @param Base Base address of PCI Card device to be programmed.
1675 @param Node Given resource node.
1681 IN PCI_RESOURCE_NODE
*Node
1684 EFI_PCI_IO_PROTOCOL
*PciIo
;
1687 UINT16 BridgeControl
;
1690 PciIo
= &(Node
->PciDev
->PciIo
);
1692 Address
= Base
+ Node
->Offset
;
1695 // Indicate pci bus driver has allocated
1696 // resource for this device
1697 // It might be a temporary solution here since
1698 // pci device could have multiple bar
1700 Node
->PciDev
->Allocated
= TRUE
;
1702 switch (Node
->Bar
) {
1707 EfiPciIoWidthUint32
,
1708 (Node
->PciDev
->PciBar
[Node
->Bar
]).Offset
,
1713 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1714 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1720 EfiPciIoWidthUint32
,
1721 PCI_CARD_MEMORY_BASE_0
,
1726 TempAddress
= Address
+ Node
->Length
- 1;
1729 EfiPciIoWidthUint32
,
1730 PCI_CARD_MEMORY_LIMIT_0
,
1735 if (Node
->ResType
== PciBarTypeMem32
) {
1737 // Set non-prefetchable bit
1741 EfiPciIoWidthUint16
,
1742 PCI_CARD_BRIDGE_CONTROL
,
1747 BridgeControl
&= (UINT16
) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE
;
1750 EfiPciIoWidthUint16
,
1751 PCI_CARD_BRIDGE_CONTROL
,
1758 // Set pre-fetchable bit
1762 EfiPciIoWidthUint16
,
1763 PCI_CARD_BRIDGE_CONTROL
,
1768 BridgeControl
|= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE
;
1771 EfiPciIoWidthUint16
,
1772 PCI_CARD_BRIDGE_CONTROL
,
1778 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1779 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1780 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1787 EfiPciIoWidthUint32
,
1788 PCI_CARD_MEMORY_BASE_1
,
1793 TempAddress
= Address
+ Node
->Length
- 1;
1797 EfiPciIoWidthUint32
,
1798 PCI_CARD_MEMORY_LIMIT_1
,
1803 if (Node
->ResType
== PciBarTypeMem32
) {
1806 // Set non-prefetchable bit
1810 EfiPciIoWidthUint16
,
1811 PCI_CARD_BRIDGE_CONTROL
,
1816 BridgeControl
&= (UINT16
) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE
);
1819 EfiPciIoWidthUint16
,
1820 PCI_CARD_BRIDGE_CONTROL
,
1828 // Set pre-fetchable bit
1832 EfiPciIoWidthUint16
,
1833 PCI_CARD_BRIDGE_CONTROL
,
1838 BridgeControl
|= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE
;
1841 EfiPciIoWidthUint16
,
1842 PCI_CARD_BRIDGE_CONTROL
,
1848 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1849 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1850 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1856 EfiPciIoWidthUint32
,
1857 PCI_CARD_IO_BASE_0_LOWER
,
1862 TempAddress
= Address
+ Node
->Length
- 1;
1865 EfiPciIoWidthUint32
,
1866 PCI_CARD_IO_LIMIT_0_LOWER
,
1871 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1872 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1873 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1880 EfiPciIoWidthUint32
,
1881 PCI_CARD_IO_BASE_1_LOWER
,
1886 TempAddress
= Address
+ Node
->Length
- 1;
1889 EfiPciIoWidthUint32
,
1890 PCI_CARD_IO_LIMIT_1_LOWER
,
1895 Node
->PciDev
->PciBar
[Node
->Bar
].BaseAddress
= Address
;
1896 Node
->PciDev
->PciBar
[Node
->Bar
].Length
= Node
->Length
;
1897 Node
->PciDev
->PciBar
[Node
->Bar
].BarType
= Node
->ResType
;
1906 Create padding resource node.
1908 @param PciDev Pci device instance.
1909 @param IoNode Resource info node for IO.
1910 @param Mem32Node Resource info node for 32-bit memory.
1911 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1912 @param Mem64Node Resource info node for 64-bit memory.
1913 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1917 ApplyResourcePadding (
1918 IN PCI_IO_DEVICE
*PciDev
,
1919 IN PCI_RESOURCE_NODE
*IoNode
,
1920 IN PCI_RESOURCE_NODE
*Mem32Node
,
1921 IN PCI_RESOURCE_NODE
*PMem32Node
,
1922 IN PCI_RESOURCE_NODE
*Mem64Node
,
1923 IN PCI_RESOURCE_NODE
*PMem64Node
1926 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1927 PCI_RESOURCE_NODE
*Node
;
1928 UINT8 DummyBarIndex
;
1931 Ptr
= PciDev
->ResourcePaddingDescriptors
;
1933 while (((EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1935 if (Ptr
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Ptr
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
) {
1936 if (Ptr
->AddrLen
!= 0) {
1938 Node
= CreateResourceNode (
1946 InsertResourceNode (
1956 if (Ptr
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Ptr
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
1958 if (Ptr
->AddrSpaceGranularity
== 32) {
1963 if (Ptr
->SpecificFlag
== 0x6) {
1964 if (Ptr
->AddrLen
!= 0) {
1965 Node
= CreateResourceNode (
1973 InsertResourceNode (
1986 if (Ptr
->SpecificFlag
== 0) {
1987 if (Ptr
->AddrLen
!= 0) {
1988 Node
= CreateResourceNode (
1996 InsertResourceNode (
2007 if (Ptr
->AddrSpaceGranularity
== 64) {
2012 if (Ptr
->SpecificFlag
== 0x6) {
2013 if (Ptr
->AddrLen
!= 0) {
2014 Node
= CreateResourceNode (
2022 InsertResourceNode (
2035 if (Ptr
->SpecificFlag
== 0) {
2036 if (Ptr
->AddrLen
!= 0) {
2037 Node
= CreateResourceNode (
2045 InsertResourceNode (
2062 Get padding resource for PCI-PCI bridge.
2064 @param PciIoDevice PCI-PCI bridge device instance.
2066 @note Feature flag PcdPciBusHotplugDeviceSupport determines
2067 whether need to pad resource for them.
2070 GetResourcePaddingPpb (
2071 IN PCI_IO_DEVICE
*PciIoDevice
2074 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
2075 if (PciIoDevice
->ResourcePaddingDescriptors
== NULL
) {
2076 GetResourcePaddingForHpb (PciIoDevice
);