1. used PciPlatfromProtocolGuid to get VgaIo and IsaIo supported capability.
[edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciResourceSupport.c
blobda0cfa0cae86121ce5282d044a6cf87a51dde964
1 /** @file
3 Copyright (c) 2006 - 2009, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 **/
14 #include "PciBus.h"
15 #include "PciResourceSupport.h"
16 #include "PciCommand.h"
18 /**
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.
25 **/
26 EFI_STATUS
27 SkipVGAAperture (
28 OUT UINT64 *Start,
29 IN UINT64 Length
32 UINT64 Original;
33 UINT64 Mask;
34 UINT64 StartOffset;
35 UINT64 LimitOffset;
38 // For legacy VGA, bit 10 to bit 15 is not decoded
40 Mask = 0x3FF;
42 Original = *Start;
43 StartOffset = Original & Mask;
44 LimitOffset = ((*Start) + Length - 1) & Mask;
45 if (LimitOffset >= VGABASE1) {
46 *Start = *Start - StartOffset + VGALIMIT2 + 1;
49 return EFI_SUCCESS;
52 /**
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.
59 **/
60 EFI_STATUS
61 SkipIsaAliasAperture (
62 OUT UINT64 *Start,
63 IN UINT64 Length
67 UINT64 Original;
68 UINT64 Mask;
69 UINT64 StartOffset;
70 UINT64 LimitOffset;
73 // For legacy ISA, bit 10 to bit 15 is not decoded
75 Mask = 0x3FF;
77 Original = *Start;
78 StartOffset = Original & Mask;
79 LimitOffset = ((*Start) + Length - 1) & Mask;
81 if (LimitOffset >= ISABASE) {
82 *Start = *Start - StartOffset + ISALIMIT + 1;
85 return EFI_SUCCESS;
88 /**
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.
96 **/
97 EFI_STATUS
98 InsertResourceNode (
99 PCI_RESOURCE_NODE *Bridge,
100 PCI_RESOURCE_NODE *ResNode
103 LIST_ENTRY *CurrentLink;
104 PCI_RESOURCE_NODE *Temp;
105 UINT64 ResNodeAlignRest;
106 UINT64 TempAlignRest;
108 ASSERT (Bridge != NULL);
109 ASSERT (ResNode != NULL);
111 InsertHeadList (&Bridge->ChildList, &ResNode->Link);
113 CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;
114 while (CurrentLink != &Bridge->ChildList) {
115 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
117 if (ResNode->Alignment > Temp->Alignment) {
118 break;
119 } else if (ResNode->Alignment == Temp->Alignment) {
120 ResNodeAlignRest = ResNode->Length & ResNode->Alignment;
121 TempAlignRest = Temp->Length & Temp->Alignment;
122 if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {
123 break;
127 SwapListEntries (&ResNode->Link, CurrentLink);
129 CurrentLink = ResNode->Link.ForwardLink;
132 return EFI_SUCCESS;
137 Routine Description:
139 This routine is used to merge two different resource tree in need of
140 resoure degradation. For example, if a upstream PPB doesn't support,
141 prefetchable memory decoding, the PCI bus driver will choose to call this function
142 to merge prefectchable memory resource list into normal memory list.
144 If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
145 type.
147 @param Dst Point to destination resource tree.
148 @param Res Point to source resource tree.
149 @param TypeMerge If the TypeMerge is TRUE, Res resource type is changed to the type of
150 destination resource type.
153 @retval EFI_SUCCESS Success.
155 EFI_STATUS
156 MergeResourceTree (
157 PCI_RESOURCE_NODE *Dst,
158 PCI_RESOURCE_NODE *Res,
159 BOOLEAN TypeMerge
163 LIST_ENTRY *CurrentLink;
164 PCI_RESOURCE_NODE *Temp;
166 ASSERT (Dst != NULL);
167 ASSERT (Res != NULL);
169 while (!IsListEmpty (&Res->ChildList)) {
170 CurrentLink = Res->ChildList.ForwardLink;
172 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
174 if (TypeMerge) {
175 Temp->ResType = Dst->ResType;
178 RemoveEntryList (CurrentLink);
179 InsertResourceNode (Dst, Temp);
183 return EFI_SUCCESS;
187 This function is used to calculate the IO16 aperture
188 for a bridge.
190 @param Bridge PCI resource node for bridge.
192 @retval EFI_SUCCESS Success.
194 EFI_STATUS
195 CalculateApertureIo16 (
196 IN PCI_RESOURCE_NODE *Bridge
199 EFI_STATUS Status;
200 UINT64 Aperture;
201 LIST_ENTRY *CurrentLink;
202 PCI_RESOURCE_NODE *Node;
203 UINT64 Offset;
204 BOOLEAN IsaEnable;
205 BOOLEAN VGAEnable;
206 EFI_PCI_PLATFORM_POLICY PciPolicy;
210 // Always assume there is ISA device and VGA device on the platform
211 // will be customized later
213 IsaEnable = FALSE;
214 VGAEnable = FALSE;
217 // Check PciPlatform policy
219 if (gPciPlatformProtocol != NULL) {
220 Status = gPciPlatformProtocol->GetPlatformPolicy (
221 gPciPlatformProtocol,
222 &PciPolicy
224 if (!EFI_ERROR (Status)) {
225 if (PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) {
226 IsaEnable = TRUE;
228 if (PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) {
229 VGAEnable = TRUE;
234 Aperture = 0;
236 if (Bridge == NULL) {
237 return EFI_SUCCESS;
240 CurrentLink = Bridge->ChildList.ForwardLink;
243 // Assume the bridge is aligned
245 while (CurrentLink != &Bridge->ChildList) {
247 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
250 // Consider the aperture alignment
252 Offset = Aperture & (Node->Alignment);
254 if (Offset != 0) {
256 Aperture = Aperture + (Node->Alignment + 1) - Offset;
261 // IsaEnable and VGAEnable can not be implemented now.
262 // If both of them are enabled, then the IO resource would
263 // become too limited to meet the requirement of most of devices.
266 if (IsaEnable || VGAEnable) {
267 if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
269 // Check if there is need to support ISA/VGA decoding
270 // If so, we need to avoid isa/vga aliasing range
272 if (IsaEnable) {
273 SkipIsaAliasAperture (
274 &Aperture,
275 Node->Length
277 Offset = Aperture & (Node->Alignment);
278 if (Offset != 0) {
279 Aperture = Aperture + (Node->Alignment + 1) - Offset;
281 } else if (VGAEnable) {
282 SkipVGAAperture (
283 &Aperture,
284 Node->Length
286 Offset = Aperture & (Node->Alignment);
287 if (Offset != 0) {
288 Aperture = Aperture + (Node->Alignment + 1) - Offset;
294 Node->Offset = Aperture;
297 // Increment aperture by the length of node
299 Aperture += Node->Length;
301 CurrentLink = CurrentLink->ForwardLink;
305 // At last, adjust the aperture with the bridge's
306 // alignment
308 Offset = Aperture & (Bridge->Alignment);
310 if (Offset != 0) {
311 Aperture = Aperture + (Bridge->Alignment + 1) - Offset;
314 Bridge->Length = Aperture;
316 // At last, adjust the bridge's alignment to the first child's alignment
317 // if the bridge has at least one child
319 CurrentLink = Bridge->ChildList.ForwardLink;
320 if (CurrentLink != &Bridge->ChildList) {
321 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
322 if (Node->Alignment > Bridge->Alignment) {
323 Bridge->Alignment = Node->Alignment;
327 return EFI_SUCCESS;
331 This function is used to calculate the resource aperture
332 for a given bridge device.
334 @param Bridge Give bridge device.
336 @retval EFI_SUCCESS Success.
338 EFI_STATUS
339 CalculateResourceAperture (
340 IN PCI_RESOURCE_NODE *Bridge
343 UINT64 Aperture;
344 LIST_ENTRY *CurrentLink;
345 PCI_RESOURCE_NODE *Node;
347 UINT64 Offset;
349 Aperture = 0;
351 if (Bridge == NULL) {
352 return EFI_SUCCESS;
355 if (Bridge->ResType == PciBarTypeIo16) {
356 return CalculateApertureIo16 (Bridge);
359 CurrentLink = Bridge->ChildList.ForwardLink;
362 // Assume the bridge is aligned
364 while (CurrentLink != &Bridge->ChildList) {
366 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
369 // Apply padding resource if available
372 Offset = Aperture & (Node->Alignment);
374 if (Offset != 0) {
376 Aperture = Aperture + (Node->Alignment + 1) - Offset;
381 // Recode current aperture as a offset
382 // this offset will be used in future real allocation
384 Node->Offset = Aperture;
387 // Increment aperture by the length of node
389 Aperture += Node->Length;
392 // Consider the aperture alignment
395 CurrentLink = CurrentLink->ForwardLink;
399 // At last, adjust the aperture with the bridge's
400 // alignment
402 Offset = Aperture & (Bridge->Alignment);
403 if (Offset != 0) {
404 Aperture = Aperture + (Bridge->Alignment + 1) - Offset;
408 // If the bridge has already padded the resource and the
409 // amount of padded resource is larger, then keep the
410 // padded resource
412 if (Bridge->Length < Aperture) {
413 Bridge->Length = Aperture;
417 // At last, adjust the bridge's alignment to the first child's alignment
418 // if the bridge has at least one child
420 CurrentLink = Bridge->ChildList.ForwardLink;
421 if (CurrentLink != &Bridge->ChildList) {
422 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
423 if (Node->Alignment > Bridge->Alignment) {
424 Bridge->Alignment = Node->Alignment;
428 return EFI_SUCCESS;
432 Get IO/Memory resource infor for given PCI device.
434 @param PciDev Pci device instance.
435 @param IoNode Resource info node for IO .
436 @param Mem32Node Resource info node for 32-bit memory.
437 @param PMem32Node Resource info node for 32-bit PMemory.
438 @param Mem64Node Resource info node for 64-bit memory.
439 @param PMem64Node Resource info node for 64-bit PMemory.
441 @retval EFI_SUCCESS Success.
443 EFI_STATUS
444 GetResourceFromDevice (
445 PCI_IO_DEVICE *PciDev,
446 PCI_RESOURCE_NODE *IoNode,
447 PCI_RESOURCE_NODE *Mem32Node,
448 PCI_RESOURCE_NODE *PMem32Node,
449 PCI_RESOURCE_NODE *Mem64Node,
450 PCI_RESOURCE_NODE *PMem64Node
454 UINT8 Index;
455 PCI_RESOURCE_NODE *Node;
456 BOOLEAN ResourceRequested;
458 Node = NULL;
459 ResourceRequested = FALSE;
461 for (Index = 0; Index < PCI_MAX_BAR; Index++) {
463 switch ((PciDev->PciBar)[Index].BarType) {
465 case PciBarTypeMem32:
467 Node = CreateResourceNode (
468 PciDev,
469 (PciDev->PciBar)[Index].Length,
470 (PciDev->PciBar)[Index].Alignment,
471 Index,
472 PciBarTypeMem32,
473 PciResUsageTypical
476 InsertResourceNode (
477 Mem32Node,
478 Node
481 ResourceRequested = TRUE;
482 break;
484 case PciBarTypeMem64:
486 Node = CreateResourceNode (
487 PciDev,
488 (PciDev->PciBar)[Index].Length,
489 (PciDev->PciBar)[Index].Alignment,
490 Index,
491 PciBarTypeMem64,
492 PciResUsageTypical
495 InsertResourceNode (
496 Mem64Node,
497 Node
500 ResourceRequested = TRUE;
501 break;
503 case PciBarTypePMem64:
505 Node = CreateResourceNode (
506 PciDev,
507 (PciDev->PciBar)[Index].Length,
508 (PciDev->PciBar)[Index].Alignment,
509 Index,
510 PciBarTypePMem64,
511 PciResUsageTypical
514 InsertResourceNode (
515 PMem64Node,
516 Node
519 ResourceRequested = TRUE;
520 break;
522 case PciBarTypePMem32:
524 Node = CreateResourceNode (
525 PciDev,
526 (PciDev->PciBar)[Index].Length,
527 (PciDev->PciBar)[Index].Alignment,
528 Index,
529 PciBarTypePMem32,
530 PciResUsageTypical
533 InsertResourceNode (
534 PMem32Node,
535 Node
537 ResourceRequested = TRUE;
538 break;
540 case PciBarTypeIo16:
541 case PciBarTypeIo32:
543 Node = CreateResourceNode (
544 PciDev,
545 (PciDev->PciBar)[Index].Length,
546 (PciDev->PciBar)[Index].Alignment,
547 Index,
548 PciBarTypeIo16,
549 PciResUsageTypical
552 InsertResourceNode (
553 IoNode,
554 Node
556 ResourceRequested = TRUE;
557 break;
559 case PciBarTypeUnknown:
560 break;
562 default:
563 break;
568 // If there is no resource requested from this device,
569 // then we indicate this device has been allocated naturally.
571 if (!ResourceRequested) {
572 PciDev->Allocated = TRUE;
575 return EFI_SUCCESS;
579 This function is used to create a resource node.
581 @param PciDev Pci device instance.
582 @param Length Length of Io/Memory resource.
583 @param Alignment Alignment of resource.
584 @param Bar Bar index.
585 @param ResType Type of resource: IO/Memory.
586 @param ResUsage Resource usage.
588 PCI_RESOURCE_NODE *
589 CreateResourceNode (
590 IN PCI_IO_DEVICE *PciDev,
591 IN UINT64 Length,
592 IN UINT64 Alignment,
593 IN UINT8 Bar,
594 IN PCI_BAR_TYPE ResType,
595 IN PCI_RESOURCE_USAGE ResUsage
598 PCI_RESOURCE_NODE *Node;
600 Node = NULL;
602 Node = AllocatePool (sizeof (PCI_RESOURCE_NODE));
603 ASSERT (Node != NULL);
604 if (Node == NULL) {
605 return NULL;
608 ZeroMem (Node, sizeof (PCI_RESOURCE_NODE));
610 Node->Signature = PCI_RESOURCE_SIGNATURE;
611 Node->PciDev = PciDev;
612 Node->Length = Length;
613 Node->Alignment = Alignment;
614 Node->Bar = Bar;
615 Node->ResType = ResType;
616 Node->Reserved = FALSE;
617 Node->ResourceUsage = ResUsage;
618 InitializeListHead (&Node->ChildList);
619 return Node;
623 This routine is used to extract resource request from
624 device node list.
626 @param Bridge Pci device instance.
627 @param IoNode Resource info node for IO.
628 @param Mem32Node Resource info node for 32-bit memory.
629 @param PMem32Node Resource info node for 32-bit PMemory.
630 @param Mem64Node Resource info node for 64-bit memory.
631 @param PMem64Node Resource info node for 64-bit PMemory.
633 @retval EFI_SUCCESS Success.
635 EFI_STATUS
636 CreateResourceMap (
637 IN PCI_IO_DEVICE *Bridge,
638 IN PCI_RESOURCE_NODE *IoNode,
639 IN PCI_RESOURCE_NODE *Mem32Node,
640 IN PCI_RESOURCE_NODE *PMem32Node,
641 IN PCI_RESOURCE_NODE *Mem64Node,
642 IN PCI_RESOURCE_NODE *PMem64Node
645 PCI_IO_DEVICE *Temp;
646 PCI_RESOURCE_NODE *IoBridge;
647 PCI_RESOURCE_NODE *Mem32Bridge;
648 PCI_RESOURCE_NODE *PMem32Bridge;
649 PCI_RESOURCE_NODE *Mem64Bridge;
650 PCI_RESOURCE_NODE *PMem64Bridge;
651 LIST_ENTRY *CurrentLink;
653 CurrentLink = Bridge->ChildList.ForwardLink;
655 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
657 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
660 // Create resource nodes for this device by scanning the
661 // Bar array in the device private data
662 // If the upstream bridge doesn't support this device,
663 // no any resource node will be created for this device
665 GetResourceFromDevice (
666 Temp,
667 IoNode,
668 Mem32Node,
669 PMem32Node,
670 Mem64Node,
671 PMem64Node
674 if (IS_PCI_BRIDGE (&Temp->Pci)) {
677 // If the device has children, create a bridge resource node for this PPB
678 // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
679 // is aligned with 4KB
680 // This device is typically a bridge device like PPB and P2C
682 IoBridge = CreateResourceNode (
683 Temp,
685 0xFFF,
686 PPB_IO_RANGE,
687 PciBarTypeIo16,
688 PciResUsageTypical
689 ); //0x1000 aligned
691 Mem32Bridge = CreateResourceNode (
692 Temp,
694 0xFFFFF,
695 PPB_MEM32_RANGE,
696 PciBarTypeMem32,
697 PciResUsageTypical
700 PMem32Bridge = CreateResourceNode (
701 Temp,
703 0xFFFFF,
704 PPB_PMEM32_RANGE,
705 PciBarTypePMem32,
706 PciResUsageTypical
709 Mem64Bridge = CreateResourceNode (
710 Temp,
712 0xFFFFF,
713 PPB_MEM64_RANGE,
714 PciBarTypeMem64,
715 PciResUsageTypical
718 PMem64Bridge = CreateResourceNode (
719 Temp,
721 0xFFFFF,
722 PPB_PMEM64_RANGE,
723 PciBarTypePMem64,
724 PciResUsageTypical
728 // Recursively create resouce map on this bridge
730 CreateResourceMap (
731 Temp,
732 IoBridge,
733 Mem32Bridge,
734 PMem32Bridge,
735 Mem64Bridge,
736 PMem64Bridge
739 if (ResourceRequestExisted (IoBridge)) {
740 InsertResourceNode (
741 IoNode,
742 IoBridge
744 } else {
745 gBS->FreePool (IoBridge);
746 IoBridge = NULL;
750 // If there is node under this resource bridge,
751 // then calculate bridge's aperture of this type
752 // and insert it into the respective resource tree.
753 // If no, delete this resource bridge
755 if (ResourceRequestExisted (Mem32Bridge)) {
756 InsertResourceNode (
757 Mem32Node,
758 Mem32Bridge
760 } else {
761 gBS->FreePool (Mem32Bridge);
762 Mem32Bridge = NULL;
766 // If there is node under this resource bridge,
767 // then calculate bridge's aperture of this type
768 // and insert it into the respective resource tree.
769 // If no, delete this resource bridge
771 if (ResourceRequestExisted (PMem32Bridge)) {
772 InsertResourceNode (
773 PMem32Node,
774 PMem32Bridge
776 } else {
777 gBS->FreePool (PMem32Bridge);
778 PMem32Bridge = NULL;
782 // If there is node under this resource bridge,
783 // then calculate bridge's aperture of this type
784 // and insert it into the respective resource tree.
785 // If no, delete this resource bridge
787 if (ResourceRequestExisted (Mem64Bridge)) {
788 InsertResourceNode (
789 Mem64Node,
790 Mem64Bridge
792 } else {
793 gBS->FreePool (Mem64Bridge);
794 Mem64Bridge = NULL;
798 // If there is node under this resource bridge,
799 // then calculate bridge's aperture of this type
800 // and insert it into the respective resource tree.
801 // If no, delete this resource bridge
803 if (ResourceRequestExisted (PMem64Bridge)) {
804 InsertResourceNode (
805 PMem64Node,
806 PMem64Bridge
808 } else {
809 gBS->FreePool (PMem64Bridge);
810 PMem64Bridge = NULL;
816 // If it is P2C, apply hard coded resource padding
819 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
820 ResourcePaddingForCardBusBridge (
821 Temp,
822 IoNode,
823 Mem32Node,
824 PMem32Node,
825 Mem64Node,
826 PMem64Node
830 CurrentLink = CurrentLink->ForwardLink;
834 // To do some platform specific resource padding ...
836 ResourcePaddingPolicy (
837 Bridge,
838 IoNode,
839 Mem32Node,
840 PMem32Node,
841 Mem64Node,
842 PMem64Node
846 // Degrade resource if necessary
848 DegradeResource (
849 Bridge,
850 Mem32Node,
851 PMem32Node,
852 Mem64Node,
853 PMem64Node
857 // Calculate resource aperture for this bridge device
859 CalculateResourceAperture (Mem32Node);
860 CalculateResourceAperture (PMem32Node);
861 CalculateResourceAperture (Mem64Node);
862 CalculateResourceAperture (PMem64Node);
863 CalculateResourceAperture (IoNode);
865 return EFI_SUCCESS;
870 This function is used to do the resource padding for a specific platform.
872 @param PciDev Pci device instance.
873 @param IoNode Resource info node for IO.
874 @param Mem32Node Resource info node for 32-bit memory.
875 @param PMem32Node Resource info node for 32-bit PMemory.
876 @param Mem64Node Resource info node for 64-bit memory.
877 @param PMem64Node Resource info node for 64-bit PMemory.
879 @retval EFI_SUCCESS Success.
881 EFI_STATUS
882 ResourcePaddingPolicy (
883 PCI_IO_DEVICE *PciDev,
884 PCI_RESOURCE_NODE *IoNode,
885 PCI_RESOURCE_NODE *Mem32Node,
886 PCI_RESOURCE_NODE *PMem32Node,
887 PCI_RESOURCE_NODE *Mem64Node,
888 PCI_RESOURCE_NODE *PMem64Node
892 // Create padding resource node
894 if (PciDev->ResourcePaddingDescriptors != NULL) {
895 ApplyResourcePadding (
896 PciDev,
897 IoNode,
898 Mem32Node,
899 PMem32Node,
900 Mem64Node,
901 PMem64Node
905 return EFI_SUCCESS;
910 This function is used to degrade resource if the upstream bridge
911 doesn't support certain resource. Degradation path is
912 PMEM64 -> MEM64 -> MEM32
913 PMEM64 -> PMEM32 -> MEM32
914 IO32 -> IO16.
916 @param Bridge Pci device instance.
917 @param Mem32Node Resource info node for 32-bit memory.
918 @param PMem32Node Resource info node for 32-bit PMemory.
919 @param Mem64Node Resource info node for 64-bit memory.
920 @param PMem64Node Resource info node for 64-bit PMemory.
922 @retval EFI_SUCCESS Success.
924 EFI_STATUS
925 DegradeResource (
926 IN PCI_IO_DEVICE *Bridge,
927 IN PCI_RESOURCE_NODE *Mem32Node,
928 IN PCI_RESOURCE_NODE *PMem32Node,
929 IN PCI_RESOURCE_NODE *Mem64Node,
930 IN PCI_RESOURCE_NODE *PMem64Node
933 BOOLEAN HasOprom;
934 PCI_IO_DEVICE *Temp;
935 LIST_ENTRY *CurrentLink;
938 // For RootBridge, PPB , P2C, go recursively to traverse all its children
939 // to find if this bridge and downstream has OptionRom.
941 HasOprom = FALSE;
942 CurrentLink = Bridge->ChildList.ForwardLink;
943 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
945 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
946 if (Temp->RomSize != 0) {
947 HasOprom = TRUE;
948 break;
950 CurrentLink = CurrentLink->ForwardLink;
954 // If bridge doesn't support Prefetchable
955 // memory64, degrade it to Prefetchable memory32
957 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {
958 MergeResourceTree (
959 PMem32Node,
960 PMem64Node,
961 TRUE
963 } else {
965 // if no PMem32 request and no OptionRom request, still keep PMem64. Otherwise degrade to PMem32
967 if ((PMem32Node != NULL && (PMem32Node->Length != 0 && Bridge->Parent != NULL)) || HasOprom) {
969 // Fixed the issue that there is no resource for 64-bit (above 4G)
971 MergeResourceTree (
972 PMem32Node,
973 PMem64Node,
974 TRUE
981 // If bridge doesn't support Mem64
982 // degrade it to mem32
984 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {
985 MergeResourceTree (
986 Mem32Node,
987 Mem64Node,
988 TRUE
993 // If bridge doesn't support Pmem32
994 // degrade it to mem32
996 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {
997 MergeResourceTree (
998 Mem32Node,
999 PMem32Node,
1000 TRUE
1005 // if bridge supports combined Pmem Mem decoding
1006 // merge these two type of resource
1008 if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {
1009 MergeResourceTree (
1010 Mem32Node,
1011 PMem32Node,
1012 FALSE
1015 MergeResourceTree (
1016 Mem64Node,
1017 PMem64Node,
1018 FALSE
1022 return EFI_SUCCESS;
1026 Test whether bridge device support decode resource
1028 @param Bridge Bridge device instance.
1029 @param Decode Decode type according to resource type.
1031 @return TRUE bridge device support decode resource.
1032 @return FALSE bridge device don't support decode resource.
1035 BOOLEAN
1036 BridgeSupportResourceDecode (
1037 IN PCI_IO_DEVICE *Bridge,
1038 IN UINT32 Decode
1042 if (((Bridge->Decodes) & Decode) != 0) {
1043 return TRUE;
1046 return FALSE;
1050 This function is used to program the resource allocated
1051 for each resource node.
1054 @param Base Base address of resource.
1055 @param Bridge Bridge device instance.
1057 @retval EFI_SUCCESS Success.
1059 EFI_STATUS
1060 ProgramResource (
1061 IN UINT64 Base,
1062 IN PCI_RESOURCE_NODE *Bridge
1065 LIST_ENTRY *CurrentLink;
1066 PCI_RESOURCE_NODE *Node;
1067 EFI_STATUS Status;
1069 if (Base == gAllOne) {
1070 return EFI_OUT_OF_RESOURCES;
1073 CurrentLink = Bridge->ChildList.ForwardLink;
1075 while (CurrentLink != &Bridge->ChildList) {
1077 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
1079 if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {
1081 if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
1082 ProgramP2C (Base, Node);
1083 } else {
1084 ProgramBar (Base, Node);
1086 } else {
1087 Status = ProgramResource (Base + Node->Offset, Node);
1089 if (EFI_ERROR (Status)) {
1090 return Status;
1093 ProgramPpbApperture (Base, Node);
1096 CurrentLink = CurrentLink->ForwardLink;
1099 return EFI_SUCCESS;
1103 Program Bar register.
1105 @param Base Base address for resource.
1106 @param Node Point to resoure node structure.
1108 @retval EFI_SUCCESS Success.
1110 EFI_STATUS
1111 ProgramBar (
1112 IN UINT64 Base,
1113 IN PCI_RESOURCE_NODE *Node
1116 EFI_PCI_IO_PROTOCOL *PciIo;
1117 UINT64 Address;
1118 UINT32 Address32;
1120 Address = 0;
1121 PciIo = &(Node->PciDev->PciIo);
1123 Address = Base + Node->Offset;
1126 // Indicate pci bus driver has allocated
1127 // resource for this device
1128 // It might be a temporary solution here since
1129 // pci device could have multiple bar
1131 Node->PciDev->Allocated = TRUE;
1133 ASSERT (Node->Bar < PCI_MAX_BAR);
1134 switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
1136 case PciBarTypeIo16:
1137 case PciBarTypeIo32:
1138 case PciBarTypeMem32:
1139 case PciBarTypePMem32:
1141 PciIoWrite (
1142 PciIo,
1143 EfiPciIoWidthUint32,
1144 (Node->PciDev->PciBar[Node->Bar]).Offset,
1146 &Address
1149 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1151 break;
1153 case PciBarTypeMem64:
1154 case PciBarTypePMem64:
1156 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1158 PciIoWrite (
1159 PciIo,
1160 EfiPciIoWidthUint32,
1161 (Node->PciDev->PciBar[Node->Bar]).Offset,
1163 &Address32
1166 Address32 = (UINT32) RShiftU64 (Address, 32);
1168 PciIoWrite (
1169 PciIo,
1170 EfiPciIoWidthUint32,
1171 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
1173 &Address32
1176 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1178 break;
1180 default:
1181 break;
1184 return EFI_SUCCESS;
1188 Program PPB apperture.
1190 @param Base Base address for resource.
1191 @param Node Point to resoure node structure.
1193 @retval EFI_SUCCESS Success.
1195 EFI_STATUS
1196 ProgramPpbApperture (
1197 IN UINT64 Base,
1198 IN PCI_RESOURCE_NODE *Node
1201 EFI_PCI_IO_PROTOCOL *PciIo;
1202 UINT64 Address;
1203 UINT32 Address32;
1205 Address = 0;
1207 // if no device south of this PPB, return anyway
1208 // Apperture is set default in the initialization code
1210 if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {
1212 // For padding resource node, just ignore when programming
1214 return EFI_SUCCESS;
1217 PciIo = &(Node->PciDev->PciIo);
1218 Address = Base + Node->Offset;
1221 // Indicate the PPB resource has been allocated
1223 Node->PciDev->Allocated = TRUE;
1225 switch (Node->Bar) {
1227 case PPB_BAR_0:
1228 case PPB_BAR_1:
1229 PciIoWrite (
1230 PciIo,
1231 EfiPciIoWidthUint32,
1232 (Node->PciDev->PciBar[Node->Bar]).Offset,
1234 &Address
1237 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1238 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1240 break;
1242 case PPB_IO_RANGE:
1244 Address32 = ((UINT32) (Address)) >> 8;
1245 PciIoWrite (
1246 PciIo,
1247 EfiPciIoWidthUint8,
1248 0x1C,
1250 &Address32
1253 Address32 >>= 8;
1254 PciIoWrite (
1255 PciIo,
1256 EfiPciIoWidthUint16,
1257 0x30,
1259 &Address32
1262 Address32 = (UINT32) (Address + Node->Length - 1);
1263 Address32 = ((UINT32) (Address32)) >> 8;
1264 PciIoWrite (
1265 PciIo,
1266 EfiPciIoWidthUint8,
1267 0x1D,
1269 &Address32
1272 Address32 >>= 8;
1273 PciIoWrite (
1274 PciIo,
1275 EfiPciIoWidthUint16,
1276 0x32,
1278 &Address32
1281 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1282 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1283 break;
1285 case PPB_MEM32_RANGE:
1287 Address32 = ((UINT32) (Address)) >> 16;
1288 PciIoWrite (
1289 PciIo,
1290 EfiPciIoWidthUint16,
1291 0x20,
1293 &Address32
1296 Address32 = (UINT32) (Address + Node->Length - 1);
1297 Address32 = ((UINT32) (Address32)) >> 16;
1298 PciIoWrite (
1299 PciIo,
1300 EfiPciIoWidthUint16,
1301 0x22,
1303 &Address32
1306 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1307 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1308 break;
1310 case PPB_PMEM32_RANGE:
1311 case PPB_PMEM64_RANGE:
1313 Address32 = ((UINT32) (Address)) >> 16;
1314 PciIoWrite (
1315 PciIo,
1316 EfiPciIoWidthUint16,
1317 0x24,
1319 &Address32
1322 Address32 = (UINT32) (Address + Node->Length - 1);
1323 Address32 = ((UINT32) (Address32)) >> 16;
1324 PciIoWrite (
1325 PciIo,
1326 EfiPciIoWidthUint16,
1327 0x26,
1329 &Address32
1332 Address32 = (UINT32) RShiftU64 (Address, 32);
1333 PciIoWrite (
1334 PciIo,
1335 EfiPciIoWidthUint32,
1336 0x28,
1338 &Address32
1341 Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);
1342 PciIoWrite (
1343 PciIo,
1344 EfiPciIoWidthUint32,
1345 0x2C,
1347 &Address32
1350 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1351 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1352 break;
1354 default:
1355 break;
1358 return EFI_SUCCESS;
1362 Program parent bridge for oprom.
1364 @param PciDevice Pci deivce instance.
1365 @param OptionRomBase Base address for oprom.
1366 @param Enable Enable/Disable.
1368 @retval EFI_SUCCESS Success.
1370 EFI_STATUS
1371 ProgrameUpstreamBridgeForRom (
1372 IN PCI_IO_DEVICE *PciDevice,
1373 IN UINT32 OptionRomBase,
1374 IN BOOLEAN Enable
1377 PCI_IO_DEVICE *Parent;
1378 PCI_RESOURCE_NODE Node;
1380 // For root bridge, just return.
1382 Parent = PciDevice->Parent;
1383 ZeroMem (&Node, sizeof (Node));
1384 while (Parent != NULL) {
1385 if (!IS_PCI_BRIDGE (&Parent->Pci)) {
1386 break;
1389 Node.PciDev = Parent;
1390 Node.Length = PciDevice->RomSize;
1391 Node.Alignment = 0;
1392 Node.Bar = PPB_MEM32_RANGE;
1393 Node.ResType = PciBarTypeMem32;
1394 Node.Offset = 0;
1397 // Program PPB to only open a single <= 16<MB apperture
1399 if (Enable) {
1400 ProgramPpbApperture (OptionRomBase, &Node);
1401 PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1402 } else {
1403 InitializePpb (Parent);
1404 PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1407 Parent = Parent->Parent;
1410 return EFI_SUCCESS;
1414 Test whether resource exists for a bridge.
1416 @param Bridge Point to resource node for a bridge.
1418 @return whether resource exists.
1420 BOOLEAN
1421 ResourceRequestExisted (
1422 IN PCI_RESOURCE_NODE *Bridge
1425 if (Bridge != NULL) {
1426 if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {
1427 return TRUE;
1431 return FALSE;
1435 Initialize resource pool structure.
1437 @param ResourcePool Point to resource pool structure.
1438 @param ResourceType Type of resource.
1440 EFI_STATUS
1441 InitializeResourcePool (
1442 PCI_RESOURCE_NODE *ResourcePool,
1443 PCI_BAR_TYPE ResourceType
1447 ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
1448 ResourcePool->ResType = ResourceType;
1449 ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
1450 InitializeListHead (&ResourcePool->ChildList);
1452 return EFI_SUCCESS;
1456 Get all resource information for given Pci device.
1458 @param PciDev Pci device instance.
1459 @param IoBridge Io resource node.
1460 @param Mem32Bridge 32-bit memory node.
1461 @param PMem32Bridge 32-bit Pmemory node.
1462 @param Mem64Bridge 64-bit memory node.
1463 @param PMem64Bridge 64-bit PMemory node.
1464 @param IoPool Link list header for Io resource.
1465 @param Mem32Pool Link list header for 32-bit memory.
1466 @param PMem32Pool Link list header for 32-bit Pmemory.
1467 @param Mem64Pool Link list header for 64-bit memory.
1468 @param PMem64Pool Link list header for 64-bit Pmemory.
1470 @retval EFI_SUCCESS Success.
1472 EFI_STATUS
1473 GetResourceMap (
1474 PCI_IO_DEVICE *PciDev,
1475 PCI_RESOURCE_NODE **IoBridge,
1476 PCI_RESOURCE_NODE **Mem32Bridge,
1477 PCI_RESOURCE_NODE **PMem32Bridge,
1478 PCI_RESOURCE_NODE **Mem64Bridge,
1479 PCI_RESOURCE_NODE **PMem64Bridge,
1480 PCI_RESOURCE_NODE *IoPool,
1481 PCI_RESOURCE_NODE *Mem32Pool,
1482 PCI_RESOURCE_NODE *PMem32Pool,
1483 PCI_RESOURCE_NODE *Mem64Pool,
1484 PCI_RESOURCE_NODE *PMem64Pool
1488 PCI_RESOURCE_NODE *Temp;
1489 LIST_ENTRY *CurrentLink;
1491 CurrentLink = IoPool->ChildList.ForwardLink;
1494 // Get Io resource map
1496 while (CurrentLink != &IoPool->ChildList) {
1498 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1500 if (Temp->PciDev == PciDev) {
1501 *IoBridge = Temp;
1504 CurrentLink = CurrentLink->ForwardLink;
1508 // Get Mem32 resource map
1510 CurrentLink = Mem32Pool->ChildList.ForwardLink;
1512 while (CurrentLink != &Mem32Pool->ChildList) {
1514 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1516 if (Temp->PciDev == PciDev) {
1517 *Mem32Bridge = Temp;
1520 CurrentLink = CurrentLink->ForwardLink;
1524 // Get Pmem32 resource map
1526 CurrentLink = PMem32Pool->ChildList.ForwardLink;
1528 while (CurrentLink != &PMem32Pool->ChildList) {
1530 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1532 if (Temp->PciDev == PciDev) {
1533 *PMem32Bridge = Temp;
1536 CurrentLink = CurrentLink->ForwardLink;
1540 // Get Mem64 resource map
1542 CurrentLink = Mem64Pool->ChildList.ForwardLink;
1544 while (CurrentLink != &Mem64Pool->ChildList) {
1546 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1548 if (Temp->PciDev == PciDev) {
1549 *Mem64Bridge = Temp;
1552 CurrentLink = CurrentLink->ForwardLink;
1556 // Get Pmem64 resource map
1558 CurrentLink = PMem64Pool->ChildList.ForwardLink;
1560 while (CurrentLink != &PMem64Pool->ChildList) {
1562 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1564 if (Temp->PciDev == PciDev) {
1565 *PMem64Bridge = Temp;
1568 CurrentLink = CurrentLink->ForwardLink;
1571 return EFI_SUCCESS;
1575 Destory given resource tree.
1577 @param Bridge root node of resource tree.
1579 @retval EFI_SUCCESS Success.
1581 EFI_STATUS
1582 DestroyResourceTree (
1583 IN PCI_RESOURCE_NODE *Bridge
1586 PCI_RESOURCE_NODE *Temp;
1587 LIST_ENTRY *CurrentLink;
1589 while (!IsListEmpty (&Bridge->ChildList)) {
1591 CurrentLink = Bridge->ChildList.ForwardLink;
1593 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1595 RemoveEntryList (CurrentLink);
1597 if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
1598 DestroyResourceTree (Temp);
1601 gBS->FreePool (Temp);
1604 return EFI_SUCCESS;
1608 Record the reserved resource and insert to reserved list.
1610 @param Base Base address of reserved resourse.
1611 @param Length Length of reserved resource.
1612 @param ResType Resource type.
1613 @param Bridge Pci device instance.
1615 EFI_STATUS
1616 RecordReservedResource (
1617 IN UINT64 Base,
1618 IN UINT64 Length,
1619 IN PCI_BAR_TYPE ResType,
1620 IN PCI_IO_DEVICE *Bridge
1623 PCI_RESERVED_RESOURCE_LIST *ReservedNode;
1625 ReservedNode = AllocatePool (sizeof (PCI_RESERVED_RESOURCE_LIST));
1626 if (ReservedNode == NULL) {
1627 return EFI_OUT_OF_RESOURCES;
1630 ReservedNode->Signature = RESERVED_RESOURCE_SIGNATURE;
1631 ReservedNode->Node.Base = Base;
1632 ReservedNode->Node.Length = Length;
1633 ReservedNode->Node.ResType = ResType;
1635 InsertTailList (&Bridge->ReservedResourceList, &(ReservedNode->Link));
1637 return EFI_SUCCESS;
1641 Insert resource padding for P2C.
1643 @param PciDev Pci device instance.
1644 @param IoNode Resource info node for IO.
1645 @param Mem32Node Resource info node for 32-bit memory.
1646 @param PMem32Node Resource info node for 32-bit PMemory.
1647 @param Mem64Node Resource info node for 64-bit memory.
1648 @param PMem64Node Resource info node for 64-bit PMemory.
1650 @retval EFI_SUCCESS Success.
1652 EFI_STATUS
1653 ResourcePaddingForCardBusBridge (
1654 PCI_IO_DEVICE *PciDev,
1655 PCI_RESOURCE_NODE *IoNode,
1656 PCI_RESOURCE_NODE *Mem32Node,
1657 PCI_RESOURCE_NODE *PMem32Node,
1658 PCI_RESOURCE_NODE *Mem64Node,
1659 PCI_RESOURCE_NODE *PMem64Node
1662 PCI_RESOURCE_NODE *Node;
1664 Node = NULL;
1667 // Memory Base/Limit Register 0
1668 // Bar 1 denodes memory range 0
1670 Node = CreateResourceNode (
1671 PciDev,
1672 0x2000000,
1673 0x1ffffff,
1675 PciBarTypeMem32,
1676 PciResUsagePadding
1679 InsertResourceNode (
1680 Mem32Node,
1681 Node
1685 // Memory Base/Limit Register 1
1686 // Bar 2 denodes memory range1
1688 Node = CreateResourceNode (
1689 PciDev,
1690 0x2000000,
1691 0x1ffffff,
1693 PciBarTypePMem32,
1694 PciResUsagePadding
1697 InsertResourceNode (
1698 PMem32Node,
1699 Node
1703 // Io Base/Limit
1704 // Bar 3 denodes io range 0
1706 Node = CreateResourceNode (
1707 PciDev,
1708 0x100,
1709 0xff,
1711 PciBarTypeIo16,
1712 PciResUsagePadding
1715 InsertResourceNode (
1716 IoNode,
1717 Node
1721 // Io Base/Limit
1722 // Bar 4 denodes io range 0
1724 Node = CreateResourceNode (
1725 PciDev,
1726 0x100,
1727 0xff,
1729 PciBarTypeIo16,
1730 PciResUsagePadding
1733 InsertResourceNode (
1734 IoNode,
1735 Node
1738 return EFI_SUCCESS;
1742 Program P2C register for given resource node
1744 @param Base Base address of P2C device
1745 @param Node Given resource node.
1747 @retval EFI_SUCCESS Success
1749 EFI_STATUS
1750 ProgramP2C (
1751 IN UINT64 Base,
1752 IN PCI_RESOURCE_NODE *Node
1755 EFI_PCI_IO_PROTOCOL *PciIo;
1756 UINT64 Address;
1757 UINT64 TempAddress;
1758 UINT16 BridgeControl;
1760 Address = 0;
1761 PciIo = &(Node->PciDev->PciIo);
1763 Address = Base + Node->Offset;
1766 // Indicate pci bus driver has allocated
1767 // resource for this device
1768 // It might be a temporary solution here since
1769 // pci device could have multiple bar
1771 Node->PciDev->Allocated = TRUE;
1773 switch (Node->Bar) {
1775 case P2C_BAR_0:
1776 PciIoWrite (
1777 PciIo,
1778 EfiPciIoWidthUint32,
1779 (Node->PciDev->PciBar[Node->Bar]).Offset,
1781 &Address
1784 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1785 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1786 break;
1788 case P2C_MEM_1:
1789 PciIoWrite (
1790 PciIo,
1791 EfiPciIoWidthUint32,
1792 0x1c,
1794 &Address
1797 TempAddress = Address + Node->Length - 1;
1798 PciIoWrite (
1799 PciIo,
1800 EfiPciIoWidthUint32,
1801 0x20,
1803 &TempAddress
1806 if (Node->ResType == PciBarTypeMem32) {
1809 // Set non-prefetchable bit
1811 PciIoRead (
1812 PciIo,
1813 EfiPciIoWidthUint16,
1814 0x3e,
1816 &BridgeControl
1819 BridgeControl &= 0xfeff;
1820 PciIoWrite (
1821 PciIo,
1822 EfiPciIoWidthUint16,
1823 0x3e,
1825 &BridgeControl
1828 } else {
1831 // Set pre-fetchable bit
1833 PciIoRead (
1834 PciIo,
1835 EfiPciIoWidthUint16,
1836 0x3e,
1838 &BridgeControl
1841 BridgeControl |= 0x0100;
1842 PciIoWrite (
1843 PciIo,
1844 EfiPciIoWidthUint16,
1845 0x3e,
1847 &BridgeControl
1851 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1852 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1853 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
1855 break;
1857 case P2C_MEM_2:
1858 PciIoWrite (
1859 PciIo,
1860 EfiPciIoWidthUint32,
1861 0x24,
1863 &Address
1866 TempAddress = Address + Node->Length - 1;
1868 PciIoWrite (
1869 PciIo,
1870 EfiPciIoWidthUint32,
1871 0x28,
1873 &TempAddress
1876 if (Node->ResType == PciBarTypeMem32) {
1879 // Set non-prefetchable bit
1881 PciIoRead (
1882 PciIo,
1883 EfiPciIoWidthUint16,
1884 0x3e,
1886 &BridgeControl
1889 BridgeControl &= 0xfdff;
1890 PciIoWrite (
1891 PciIo,
1892 EfiPciIoWidthUint16,
1893 0x3e,
1895 &BridgeControl
1897 } else {
1900 // Set pre-fetchable bit
1902 PciIoRead (
1903 PciIo,
1904 EfiPciIoWidthUint16,
1905 0x3e,
1907 &BridgeControl
1910 BridgeControl |= 0x0200;
1911 PciIoWrite (
1912 PciIo,
1913 EfiPciIoWidthUint16,
1914 0x3e,
1916 &BridgeControl
1920 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1921 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1922 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
1923 break;
1925 case P2C_IO_1:
1926 PciIoWrite (
1927 PciIo,
1928 EfiPciIoWidthUint32,
1929 0x2c,
1931 &Address
1933 TempAddress = Address + Node->Length - 1;
1934 PciIoWrite (
1935 PciIo,
1936 EfiPciIoWidthUint32,
1937 0x30,
1939 &TempAddress
1942 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1943 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1944 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
1946 break;
1948 case P2C_IO_2:
1949 PciIoWrite (
1950 PciIo,
1951 EfiPciIoWidthUint32,
1952 0x34,
1954 &Address
1957 TempAddress = Address + Node->Length - 1;
1958 PciIoWrite (
1959 PciIo,
1960 EfiPciIoWidthUint32,
1961 0x38,
1963 &TempAddress
1966 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1967 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1968 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
1969 break;
1971 default:
1972 break;
1975 return EFI_SUCCESS;
1979 Create padding resource node.
1981 @param PciDev Pci device instance.
1982 @param IoNode Resource info node for IO.
1983 @param Mem32Node Resource info node for 32-bit memory.
1984 @param PMem32Node Resource info node for 32-bit PMemory.
1985 @param Mem64Node Resource info node for 64-bit memory.
1986 @param PMem64Node Resource info node for 64-bit PMemory.
1988 @retval EFI_SUCCESS Success.
1991 EFI_STATUS
1992 ApplyResourcePadding (
1993 PCI_IO_DEVICE *PciDev,
1994 PCI_RESOURCE_NODE *IoNode,
1995 PCI_RESOURCE_NODE *Mem32Node,
1996 PCI_RESOURCE_NODE *PMem32Node,
1997 PCI_RESOURCE_NODE *Mem64Node,
1998 PCI_RESOURCE_NODE *PMem64Node
2001 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
2002 PCI_RESOURCE_NODE *Node;
2003 UINT8 DummyBarIndex;
2005 DummyBarIndex = 0;
2006 Ptr = PciDev->ResourcePaddingDescriptors;
2008 while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
2010 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
2011 if (Ptr->AddrLen != 0) {
2013 Node = CreateResourceNode (
2014 PciDev,
2015 Ptr->AddrLen,
2016 Ptr->AddrRangeMax,
2017 DummyBarIndex,
2018 PciBarTypeIo16,
2019 PciResUsagePadding
2021 InsertResourceNode (
2022 IoNode,
2023 Node
2027 Ptr++;
2028 continue;
2031 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
2033 if (Ptr->AddrSpaceGranularity == 32) {
2036 // prefechable
2038 if (Ptr->SpecificFlag == 0x6) {
2039 if (Ptr->AddrLen != 0) {
2040 Node = CreateResourceNode (
2041 PciDev,
2042 Ptr->AddrLen,
2043 Ptr->AddrRangeMax,
2044 DummyBarIndex,
2045 PciBarTypePMem32,
2046 PciResUsagePadding
2048 InsertResourceNode (
2049 PMem32Node,
2050 Node
2054 Ptr++;
2055 continue;
2059 // Non-prefechable
2061 if (Ptr->SpecificFlag == 0) {
2062 if (Ptr->AddrLen != 0) {
2063 Node = CreateResourceNode (
2064 PciDev,
2065 Ptr->AddrLen,
2066 Ptr->AddrRangeMax,
2067 DummyBarIndex,
2068 PciBarTypeMem32,
2069 PciResUsagePadding
2071 InsertResourceNode (
2072 Mem32Node,
2073 Node
2077 Ptr++;
2078 continue;
2082 if (Ptr->AddrSpaceGranularity == 64) {
2085 // prefechable
2087 if (Ptr->SpecificFlag == 0x6) {
2088 if (Ptr->AddrLen != 0) {
2089 Node = CreateResourceNode (
2090 PciDev,
2091 Ptr->AddrLen,
2092 Ptr->AddrRangeMax,
2093 DummyBarIndex,
2094 PciBarTypePMem64,
2095 PciResUsagePadding
2097 InsertResourceNode (
2098 PMem64Node,
2099 Node
2103 Ptr++;
2104 continue;
2108 // Non-prefechable
2110 if (Ptr->SpecificFlag == 0) {
2111 if (Ptr->AddrLen != 0) {
2112 Node = CreateResourceNode (
2113 PciDev,
2114 Ptr->AddrLen,
2115 Ptr->AddrRangeMax,
2116 DummyBarIndex,
2117 PciBarTypeMem64,
2118 PciResUsagePadding
2120 InsertResourceNode (
2121 Mem64Node,
2122 Node
2126 Ptr++;
2127 continue;
2132 Ptr++;
2135 return EFI_SUCCESS;
2139 Get padding resource for PPB.
2140 Light PCI bus driver woundn't support hotplug root device
2141 So no need to pad resource for them.
2143 @param PciIoDevice Pci device instance.
2145 VOID
2146 GetResourcePaddingPpb (
2147 IN PCI_IO_DEVICE *PciIoDevice
2150 if (gPciHotPlugInit != NULL) {
2151 if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
2152 GetResourcePaddingForHpb (PciIoDevice);