add security check
[edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciResourceSupport.c
blob4fea0306872e2cf33614335fb2436c96df681815
1 /** @file
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.
13 **/
15 #include "PciBus.h"
17 /**
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.
23 **/
24 VOID
25 SkipVGAAperture (
26 OUT UINT64 *Start,
27 IN UINT64 Length
30 UINT64 Original;
31 UINT64 Mask;
32 UINT64 StartOffset;
33 UINT64 LimitOffset;
35 ASSERT (Start != NULL);
37 // For legacy VGA, bit 10 to bit 15 is not decoded
39 Mask = 0x3FF;
41 Original = *Start;
42 StartOffset = Original & Mask;
43 LimitOffset = ((*Start) + Length - 1) & Mask;
44 if (LimitOffset >= VGABASE1) {
45 *Start = *Start - StartOffset + VGALIMIT2 + 1;
49 /**
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.
55 **/
56 VOID
57 SkipIsaAliasAperture (
58 OUT UINT64 *Start,
59 IN UINT64 Length
63 UINT64 Original;
64 UINT64 Mask;
65 UINT64 StartOffset;
66 UINT64 LimitOffset;
68 ASSERT (Start != NULL);
71 // For legacy ISA, bit 10 to bit 15 is not decoded
73 Mask = 0x3FF;
75 Original = *Start;
76 StartOffset = Original & Mask;
77 LimitOffset = ((*Start) + Length - 1) & Mask;
79 if (LimitOffset >= ISABASE) {
80 *Start = *Start - StartOffset + ISALIMIT + 1;
84 /**
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.
91 **/
92 VOID
93 InsertResourceNode (
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) {
113 break;
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)) {
118 break;
122 SwapListEntries (&ResNode->Link, CurrentLink);
124 CurrentLink = ResNode->Link.ForwardLink;
129 This routine is used to merge two different resource trees in need of
130 resoure degradation.
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
137 type.
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.
146 VOID
147 MergeResourceTree (
148 IN PCI_RESOURCE_NODE *Dst,
149 IN PCI_RESOURCE_NODE *Res,
150 IN BOOLEAN TypeMerge
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);
165 if (TypeMerge) {
166 Temp->ResType = Dst->ResType;
169 RemoveEntryList (CurrentLink);
170 InsertResourceNode (Dst, Temp);
175 This function is used to calculate the IO16 aperture
176 for a bridge.
178 @param Bridge PCI resource node for bridge.
181 VOID
182 CalculateApertureIo16 (
183 IN PCI_RESOURCE_NODE *Bridge
186 EFI_STATUS Status;
187 UINT64 Aperture;
188 LIST_ENTRY *CurrentLink;
189 PCI_RESOURCE_NODE *Node;
190 UINT64 Offset;
191 BOOLEAN IsaEnable;
192 BOOLEAN VGAEnable;
193 EFI_PCI_PLATFORM_POLICY PciPolicy;
196 // Always assume there is ISA device and VGA device on the platform
197 // will be customized later
199 IsaEnable = FALSE;
200 VGAEnable = FALSE;
203 // Check PciPlatform policy
205 if (gPciPlatformProtocol != NULL) {
206 Status = gPciPlatformProtocol->GetPlatformPolicy (
207 gPciPlatformProtocol,
208 &PciPolicy
210 if (!EFI_ERROR (Status)) {
211 if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
212 IsaEnable = TRUE;
214 if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {
215 VGAEnable = TRUE;
220 Aperture = 0;
222 if (Bridge == NULL) {
223 return ;
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);
240 if (Offset != 0) {
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
257 if (IsaEnable) {
258 SkipIsaAliasAperture (
259 &Aperture,
260 Node->Length
262 Offset = Aperture & (Node->Alignment);
263 if (Offset != 0) {
264 Aperture = Aperture + (Node->Alignment + 1) - Offset;
266 } else if (VGAEnable) {
267 SkipVGAAperture (
268 &Aperture,
269 Node->Length
271 Offset = Aperture & (Node->Alignment);
272 if (Offset != 0) {
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
291 // alignment
293 Offset = Aperture & (Bridge->Alignment);
295 if (Offset != 0) {
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.
320 VOID
321 CalculateResourceAperture (
322 IN PCI_RESOURCE_NODE *Bridge
325 UINT64 Aperture;
326 LIST_ENTRY *CurrentLink;
327 PCI_RESOURCE_NODE *Node;
329 UINT64 Offset;
331 Aperture = 0;
333 if (Bridge == NULL) {
334 return ;
337 if (Bridge->ResType == PciBarTypeIo16) {
339 CalculateApertureIo16 (Bridge);
340 return ;
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);
357 if (Offset != 0) {
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
382 // alignment
384 Offset = Aperture & (Bridge->Alignment);
385 if (Offset != 0) {
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
392 // padded resource
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.
422 VOID
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
433 UINT8 Index;
434 PCI_RESOURCE_NODE *Node;
435 BOOLEAN ResourceRequested;
437 Node = NULL;
438 ResourceRequested = FALSE;
440 for (Index = 0; Index < PCI_MAX_BAR; Index++) {
442 switch ((PciDev->PciBar)[Index].BarType) {
444 case PciBarTypeMem32:
446 Node = CreateResourceNode (
447 PciDev,
448 (PciDev->PciBar)[Index].Length,
449 (PciDev->PciBar)[Index].Alignment,
450 Index,
451 PciBarTypeMem32,
452 PciResUsageTypical
455 InsertResourceNode (
456 Mem32Node,
457 Node
460 ResourceRequested = TRUE;
461 break;
463 case PciBarTypeMem64:
465 Node = CreateResourceNode (
466 PciDev,
467 (PciDev->PciBar)[Index].Length,
468 (PciDev->PciBar)[Index].Alignment,
469 Index,
470 PciBarTypeMem64,
471 PciResUsageTypical
474 InsertResourceNode (
475 Mem64Node,
476 Node
479 ResourceRequested = TRUE;
480 break;
482 case PciBarTypePMem64:
484 Node = CreateResourceNode (
485 PciDev,
486 (PciDev->PciBar)[Index].Length,
487 (PciDev->PciBar)[Index].Alignment,
488 Index,
489 PciBarTypePMem64,
490 PciResUsageTypical
493 InsertResourceNode (
494 PMem64Node,
495 Node
498 ResourceRequested = TRUE;
499 break;
501 case PciBarTypePMem32:
503 Node = CreateResourceNode (
504 PciDev,
505 (PciDev->PciBar)[Index].Length,
506 (PciDev->PciBar)[Index].Alignment,
507 Index,
508 PciBarTypePMem32,
509 PciResUsageTypical
512 InsertResourceNode (
513 PMem32Node,
514 Node
516 ResourceRequested = TRUE;
517 break;
519 case PciBarTypeIo16:
520 case PciBarTypeIo32:
522 Node = CreateResourceNode (
523 PciDev,
524 (PciDev->PciBar)[Index].Length,
525 (PciDev->PciBar)[Index].Alignment,
526 Index,
527 PciBarTypeIo16,
528 PciResUsageTypical
531 InsertResourceNode (
532 IoNode,
533 Node
535 ResourceRequested = TRUE;
536 break;
538 case PciBarTypeUnknown:
539 break;
541 default:
542 break;
547 // Add VF resource
549 for (Index = 0; Index < PCI_MAX_BAR; Index++) {
551 switch ((PciDev->VfPciBar)[Index].BarType) {
553 case PciBarTypeMem32:
555 Node = CreateVfResourceNode (
556 PciDev,
557 (PciDev->VfPciBar)[Index].Length,
558 (PciDev->VfPciBar)[Index].Alignment,
559 Index,
560 PciBarTypeMem32,
561 PciResUsageTypical
564 InsertResourceNode (
565 Mem32Node,
566 Node
569 break;
571 case PciBarTypeMem64:
573 Node = CreateVfResourceNode (
574 PciDev,
575 (PciDev->VfPciBar)[Index].Length,
576 (PciDev->VfPciBar)[Index].Alignment,
577 Index,
578 PciBarTypeMem64,
579 PciResUsageTypical
582 InsertResourceNode (
583 Mem64Node,
584 Node
587 break;
589 case PciBarTypePMem64:
591 Node = CreateVfResourceNode (
592 PciDev,
593 (PciDev->VfPciBar)[Index].Length,
594 (PciDev->VfPciBar)[Index].Alignment,
595 Index,
596 PciBarTypePMem64,
597 PciResUsageTypical
600 InsertResourceNode (
601 PMem64Node,
602 Node
605 break;
607 case PciBarTypePMem32:
609 Node = CreateVfResourceNode (
610 PciDev,
611 (PciDev->VfPciBar)[Index].Length,
612 (PciDev->VfPciBar)[Index].Alignment,
613 Index,
614 PciBarTypePMem32,
615 PciResUsageTypical
618 InsertResourceNode (
619 PMem32Node,
620 Node
622 break;
624 case PciBarTypeIo16:
625 case PciBarTypeIo32:
626 break;
628 case PciBarTypeUnknown:
629 break;
631 default:
632 break;
635 // If there is no resource requested from this device,
636 // then we indicate this device has been allocated naturally.
638 if (!ResourceRequested) {
639 PciDev->Allocated = TRUE;
644 This function is used to create a resource node.
646 @param PciDev Pci device instance.
647 @param Length Length of Io/Memory resource.
648 @param Alignment Alignment of resource.
649 @param Bar Bar index.
650 @param ResType Type of resource: IO/Memory.
651 @param ResUsage Resource usage.
653 @return PCI resource node created for given PCI device.
654 NULL means PCI resource node is not created.
657 PCI_RESOURCE_NODE *
658 CreateResourceNode (
659 IN PCI_IO_DEVICE *PciDev,
660 IN UINT64 Length,
661 IN UINT64 Alignment,
662 IN UINT8 Bar,
663 IN PCI_BAR_TYPE ResType,
664 IN PCI_RESOURCE_USAGE ResUsage
667 PCI_RESOURCE_NODE *Node;
669 Node = NULL;
671 Node = AllocateZeroPool (sizeof (PCI_RESOURCE_NODE));
672 ASSERT (Node != NULL);
673 if (Node == NULL) {
674 return NULL;
677 Node->Signature = PCI_RESOURCE_SIGNATURE;
678 Node->PciDev = PciDev;
679 Node->Length = Length;
680 Node->Alignment = Alignment;
681 Node->Bar = Bar;
682 Node->ResType = ResType;
683 Node->Reserved = FALSE;
684 Node->ResourceUsage = ResUsage;
685 InitializeListHead (&Node->ChildList);
687 return Node;
691 This function is used to create a IOV VF resource node.
693 @param PciDev Pci device instance.
694 @param Length Length of Io/Memory resource.
695 @param Alignment Alignment of resource.
696 @param Bar Bar index.
697 @param ResType Type of resource: IO/Memory.
698 @param ResUsage Resource usage.
700 @return PCI resource node created for given VF PCI device.
701 NULL means PCI resource node is not created.
704 PCI_RESOURCE_NODE *
705 CreateVfResourceNode (
706 IN PCI_IO_DEVICE *PciDev,
707 IN UINT64 Length,
708 IN UINT64 Alignment,
709 IN UINT8 Bar,
710 IN PCI_BAR_TYPE ResType,
711 IN PCI_RESOURCE_USAGE ResUsage
714 PCI_RESOURCE_NODE *Node;
716 DEBUG ((
717 EFI_D_INFO,
718 "PCI-IOV B%x.D%x.F%x - VfResource (Bar - 0x%x) (Type - 0x%x) (Length - 0x%x)\n",
719 (UINTN)PciDev->BusNumber,
720 (UINTN)PciDev->DeviceNumber,
721 (UINTN)PciDev->FunctionNumber,
722 (UINTN)Bar,
723 (UINTN)ResType,
724 (UINTN)Length
727 Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);
728 if (Node == NULL) {
729 return Node;
732 Node->Virtual = TRUE;
734 return Node;
738 This function is used to extract resource request from
739 device node list.
741 @param Bridge Pci device instance.
742 @param IoNode Resource info node for IO.
743 @param Mem32Node Resource info node for 32-bit memory.
744 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
745 @param Mem64Node Resource info node for 64-bit memory.
746 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
749 VOID
750 CreateResourceMap (
751 IN PCI_IO_DEVICE *Bridge,
752 IN OUT PCI_RESOURCE_NODE *IoNode,
753 IN OUT PCI_RESOURCE_NODE *Mem32Node,
754 IN OUT PCI_RESOURCE_NODE *PMem32Node,
755 IN OUT PCI_RESOURCE_NODE *Mem64Node,
756 IN OUT PCI_RESOURCE_NODE *PMem64Node
759 PCI_IO_DEVICE *Temp;
760 PCI_RESOURCE_NODE *IoBridge;
761 PCI_RESOURCE_NODE *Mem32Bridge;
762 PCI_RESOURCE_NODE *PMem32Bridge;
763 PCI_RESOURCE_NODE *Mem64Bridge;
764 PCI_RESOURCE_NODE *PMem64Bridge;
765 LIST_ENTRY *CurrentLink;
767 CurrentLink = Bridge->ChildList.ForwardLink;
769 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
771 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
774 // Create resource nodes for this device by scanning the
775 // Bar array in the device private data
776 // If the upstream bridge doesn't support this device,
777 // no any resource node will be created for this device
779 GetResourceFromDevice (
780 Temp,
781 IoNode,
782 Mem32Node,
783 PMem32Node,
784 Mem64Node,
785 PMem64Node
788 if (IS_PCI_BRIDGE (&Temp->Pci)) {
791 // If the device has children, create a bridge resource node for this PPB
792 // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
793 // is aligned with 4KB
794 // This device is typically a bridge device like PPB and P2C
795 // Note: 0x1000 aligned
797 IoBridge = CreateResourceNode (
798 Temp,
800 0xFFF,
801 PPB_IO_RANGE,
802 PciBarTypeIo16,
803 PciResUsageTypical
806 Mem32Bridge = CreateResourceNode (
807 Temp,
809 0xFFFFF,
810 PPB_MEM32_RANGE,
811 PciBarTypeMem32,
812 PciResUsageTypical
815 PMem32Bridge = CreateResourceNode (
816 Temp,
818 0xFFFFF,
819 PPB_PMEM32_RANGE,
820 PciBarTypePMem32,
821 PciResUsageTypical
824 Mem64Bridge = CreateResourceNode (
825 Temp,
827 0xFFFFF,
828 PPB_MEM64_RANGE,
829 PciBarTypeMem64,
830 PciResUsageTypical
833 PMem64Bridge = CreateResourceNode (
834 Temp,
836 0xFFFFF,
837 PPB_PMEM64_RANGE,
838 PciBarTypePMem64,
839 PciResUsageTypical
843 // Recursively create resouce map on this bridge
845 CreateResourceMap (
846 Temp,
847 IoBridge,
848 Mem32Bridge,
849 PMem32Bridge,
850 Mem64Bridge,
851 PMem64Bridge
854 if (ResourceRequestExisted (IoBridge)) {
855 InsertResourceNode (
856 IoNode,
857 IoBridge
859 } else {
860 FreePool (IoBridge);
861 IoBridge = NULL;
865 // If there is node under this resource bridge,
866 // then calculate bridge's aperture of this type
867 // and insert it into the respective resource tree.
868 // If no, delete this resource bridge
870 if (ResourceRequestExisted (Mem32Bridge)) {
871 InsertResourceNode (
872 Mem32Node,
873 Mem32Bridge
875 } else {
876 FreePool (Mem32Bridge);
877 Mem32Bridge = NULL;
881 // If there is node under this resource bridge,
882 // then calculate bridge's aperture of this type
883 // and insert it into the respective resource tree.
884 // If no, delete this resource bridge
886 if (ResourceRequestExisted (PMem32Bridge)) {
887 InsertResourceNode (
888 PMem32Node,
889 PMem32Bridge
891 } else {
892 FreePool (PMem32Bridge);
893 PMem32Bridge = NULL;
897 // If there is node under this resource bridge,
898 // then calculate bridge's aperture of this type
899 // and insert it into the respective resource tree.
900 // If no, delete this resource bridge
902 if (ResourceRequestExisted (Mem64Bridge)) {
903 InsertResourceNode (
904 Mem64Node,
905 Mem64Bridge
907 } else {
908 FreePool (Mem64Bridge);
909 Mem64Bridge = NULL;
913 // If there is node under this resource bridge,
914 // then calculate bridge's aperture of this type
915 // and insert it into the respective resource tree.
916 // If no, delete this resource bridge
918 if (ResourceRequestExisted (PMem64Bridge)) {
919 InsertResourceNode (
920 PMem64Node,
921 PMem64Bridge
923 } else {
924 FreePool (PMem64Bridge);
925 PMem64Bridge = NULL;
931 // If it is P2C, apply hard coded resource padding
933 if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
934 ResourcePaddingForCardBusBridge (
935 Temp,
936 IoNode,
937 Mem32Node,
938 PMem32Node,
939 Mem64Node,
940 PMem64Node
944 CurrentLink = CurrentLink->ForwardLink;
948 // To do some platform specific resource padding ...
950 ResourcePaddingPolicy (
951 Bridge,
952 IoNode,
953 Mem32Node,
954 PMem32Node,
955 Mem64Node,
956 PMem64Node
960 // Degrade resource if necessary
962 DegradeResource (
963 Bridge,
964 Mem32Node,
965 PMem32Node,
966 Mem64Node,
967 PMem64Node
971 // Calculate resource aperture for this bridge device
973 CalculateResourceAperture (Mem32Node);
974 CalculateResourceAperture (PMem32Node);
975 CalculateResourceAperture (Mem64Node);
976 CalculateResourceAperture (PMem64Node);
977 CalculateResourceAperture (IoNode);
981 This function is used to do the resource padding for a specific platform.
983 @param PciDev Pci device instance.
984 @param IoNode Resource info node for IO.
985 @param Mem32Node Resource info node for 32-bit memory.
986 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
987 @param Mem64Node Resource info node for 64-bit memory.
988 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
991 VOID
992 ResourcePaddingPolicy (
993 IN PCI_IO_DEVICE *PciDev,
994 IN PCI_RESOURCE_NODE *IoNode,
995 IN PCI_RESOURCE_NODE *Mem32Node,
996 IN PCI_RESOURCE_NODE *PMem32Node,
997 IN PCI_RESOURCE_NODE *Mem64Node,
998 IN PCI_RESOURCE_NODE *PMem64Node
1002 // Create padding resource node
1004 if (PciDev->ResourcePaddingDescriptors != NULL) {
1005 ApplyResourcePadding (
1006 PciDev,
1007 IoNode,
1008 Mem32Node,
1009 PMem32Node,
1010 Mem64Node,
1011 PMem64Node
1017 This function is used to degrade resource if the upstream bridge
1018 doesn't support certain resource. Degradation path is
1019 PMEM64 -> MEM64 -> MEM32
1020 PMEM64 -> PMEM32 -> MEM32
1021 IO32 -> IO16.
1023 @param Bridge Pci device instance.
1024 @param Mem32Node Resource info node for 32-bit memory.
1025 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1026 @param Mem64Node Resource info node for 64-bit memory.
1027 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1030 VOID
1031 DegradeResource (
1032 IN PCI_IO_DEVICE *Bridge,
1033 IN PCI_RESOURCE_NODE *Mem32Node,
1034 IN PCI_RESOURCE_NODE *PMem32Node,
1035 IN PCI_RESOURCE_NODE *Mem64Node,
1036 IN PCI_RESOURCE_NODE *PMem64Node
1039 BOOLEAN HasOprom;
1040 PCI_IO_DEVICE *Temp;
1041 LIST_ENTRY *CurrentLink;
1044 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1045 // to find if this bridge and downstream has OptionRom.
1047 HasOprom = FALSE;
1048 CurrentLink = Bridge->ChildList.ForwardLink;
1049 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
1051 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1052 if (Temp->RomSize != 0) {
1053 HasOprom = TRUE;
1054 break;
1056 CurrentLink = CurrentLink->ForwardLink;
1060 // If bridge doesn't support Prefetchable
1061 // memory64, degrade it to Prefetchable memory32
1063 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {
1064 MergeResourceTree (
1065 PMem32Node,
1066 PMem64Node,
1067 TRUE
1069 } else {
1071 // if no PMem32 request and no OptionRom request, still keep PMem64. Otherwise degrade to PMem32
1073 if ((PMem32Node != NULL && (PMem32Node->Length != 0 && Bridge->Parent != NULL)) || HasOprom) {
1075 // Fixed the issue that there is no resource for 64-bit (above 4G)
1077 MergeResourceTree (
1078 PMem32Node,
1079 PMem64Node,
1080 TRUE
1087 // If bridge doesn't support Mem64
1088 // degrade it to mem32
1090 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {
1091 MergeResourceTree (
1092 Mem32Node,
1093 Mem64Node,
1094 TRUE
1099 // If bridge doesn't support Pmem32
1100 // degrade it to mem32
1102 if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {
1103 MergeResourceTree (
1104 Mem32Node,
1105 PMem32Node,
1106 TRUE
1111 // if bridge supports combined Pmem Mem decoding
1112 // merge these two type of resource
1114 if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {
1115 MergeResourceTree (
1116 Mem32Node,
1117 PMem32Node,
1118 FALSE
1121 MergeResourceTree (
1122 Mem64Node,
1123 PMem64Node,
1124 FALSE
1130 Test whether bridge device support decode resource.
1132 @param Bridge Bridge device instance.
1133 @param Decode Decode type according to resource type.
1135 @return TRUE The bridge device support decode resource.
1136 @return FALSE The bridge device don't support decode resource.
1139 BOOLEAN
1140 BridgeSupportResourceDecode (
1141 IN PCI_IO_DEVICE *Bridge,
1142 IN UINT32 Decode
1145 if (((Bridge->Decodes) & Decode) != 0) {
1146 return TRUE;
1149 return FALSE;
1153 This function is used to program the resource allocated
1154 for each resource node under specified bridge.
1156 @param Base Base address of resource to be progammed.
1157 @param Bridge PCI resource node for the bridge device.
1159 @retval EFI_SUCCESS Successfully to program all resouces
1160 on given PCI bridge device.
1161 @retval EFI_OUT_OF_RESOURCES Base is all one.
1164 EFI_STATUS
1165 ProgramResource (
1166 IN UINT64 Base,
1167 IN PCI_RESOURCE_NODE *Bridge
1170 LIST_ENTRY *CurrentLink;
1171 PCI_RESOURCE_NODE *Node;
1172 EFI_STATUS Status;
1174 if (Base == gAllOne) {
1175 return EFI_OUT_OF_RESOURCES;
1178 CurrentLink = Bridge->ChildList.ForwardLink;
1180 while (CurrentLink != &Bridge->ChildList) {
1182 Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
1184 if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {
1186 if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
1188 // Program the PCI Card Bus device
1190 ProgramP2C (Base, Node);
1191 } else {
1193 // Program the PCI device BAR
1195 ProgramBar (Base, Node);
1197 } else {
1199 // Program the PCI devices under this bridge
1201 Status = ProgramResource (Base + Node->Offset, Node);
1202 if (EFI_ERROR (Status)) {
1203 return Status;
1206 ProgramPpbApperture (Base, Node);
1209 CurrentLink = CurrentLink->ForwardLink;
1212 return EFI_SUCCESS;
1216 Program Bar register for PCI device.
1218 @param Base Base address for PCI device resource to be progammed.
1219 @param Node Point to resoure node structure.
1222 VOID
1223 ProgramBar (
1224 IN UINT64 Base,
1225 IN PCI_RESOURCE_NODE *Node
1228 EFI_PCI_IO_PROTOCOL *PciIo;
1229 UINT64 Address;
1230 UINT32 Address32;
1232 ASSERT (Node->Bar < PCI_MAX_BAR);
1235 // Check VF BAR
1237 if (Node->Virtual) {
1238 ProgramVfBar (Base, Node);
1241 Address = 0;
1242 PciIo = &(Node->PciDev->PciIo);
1244 Address = Base + Node->Offset;
1247 // Indicate pci bus driver has allocated
1248 // resource for this device
1249 // It might be a temporary solution here since
1250 // pci device could have multiple bar
1252 Node->PciDev->Allocated = TRUE;
1254 switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
1256 case PciBarTypeIo16:
1257 case PciBarTypeIo32:
1258 case PciBarTypeMem32:
1259 case PciBarTypePMem32:
1261 PciIo->Pci.Write (
1262 PciIo,
1263 EfiPciIoWidthUint32,
1264 (Node->PciDev->PciBar[Node->Bar]).Offset,
1266 &Address
1269 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1271 break;
1273 case PciBarTypeMem64:
1274 case PciBarTypePMem64:
1276 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1278 PciIo->Pci.Write (
1279 PciIo,
1280 EfiPciIoWidthUint32,
1281 (Node->PciDev->PciBar[Node->Bar]).Offset,
1283 &Address32
1286 Address32 = (UINT32) RShiftU64 (Address, 32);
1288 PciIo->Pci.Write (
1289 PciIo,
1290 EfiPciIoWidthUint32,
1291 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
1293 &Address32
1296 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1298 break;
1300 default:
1301 break;
1306 Program IOV VF Bar register for PCI device.
1308 @param Base Base address for PCI device resource to be progammed.
1309 @param Node Point to resoure node structure.
1312 EFI_STATUS
1313 ProgramVfBar (
1314 IN UINT64 Base,
1315 IN PCI_RESOURCE_NODE *Node
1318 EFI_PCI_IO_PROTOCOL *PciIo;
1319 UINT64 Address;
1320 UINT32 Address32;
1322 ASSERT (Node->Virtual);
1323 if (!Node->Virtual) {
1324 return EFI_UNSUPPORTED;
1327 Address = 0;
1328 PciIo = &(Node->PciDev->PciIo);
1330 Address = Base + Node->Offset;
1333 // Indicate pci bus driver has allocated
1334 // resource for this device
1335 // It might be a temporary solution here since
1336 // pci device could have multiple bar
1338 Node->PciDev->Allocated = TRUE;
1340 switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {
1342 case PciBarTypeMem32:
1343 case PciBarTypePMem32:
1345 PciIo->Pci.Write (
1346 PciIo,
1347 EfiPciIoWidthUint32,
1348 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
1350 &Address
1353 Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
1355 DEBUG ((
1356 EFI_D_INFO,
1357 "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 32Mem (Address - 0x%x)\n",
1358 (UINTN)Node->PciDev->BusNumber,
1359 (UINTN)Node->PciDev->DeviceNumber,
1360 (UINTN)Node->PciDev->FunctionNumber,
1361 (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,
1362 (UINTN)Address
1365 break;
1367 case PciBarTypeMem64:
1368 case PciBarTypePMem64:
1370 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1372 PciIo->Pci.Write (
1373 PciIo,
1374 EfiPciIoWidthUint32,
1375 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
1377 &Address32
1380 Address32 = (UINT32) RShiftU64 (Address, 32);
1382 PciIo->Pci.Write (
1383 PciIo,
1384 EfiPciIoWidthUint32,
1385 ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),
1387 &Address32
1390 Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
1392 DEBUG ((
1393 EFI_D_INFO,
1394 "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 64Mem (Address - 0x%lx)\n",
1395 (UINTN)Node->PciDev->BusNumber,
1396 (UINTN)Node->PciDev->DeviceNumber,
1397 (UINTN)Node->PciDev->FunctionNumber,
1398 (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,
1399 (UINT64)Address
1402 break;
1404 case PciBarTypeIo16:
1405 case PciBarTypeIo32:
1406 break;
1408 default:
1409 break;
1412 return EFI_SUCCESS;
1416 Program PCI-PCI bridge apperture.
1418 @param Base Base address for resource.
1419 @param Node Point to resoure node structure.
1422 VOID
1423 ProgramPpbApperture (
1424 IN UINT64 Base,
1425 IN PCI_RESOURCE_NODE *Node
1428 EFI_PCI_IO_PROTOCOL *PciIo;
1429 UINT64 Address;
1430 UINT32 Address32;
1432 Address = 0;
1434 // If no device resource of this PPB, return anyway
1435 // Apperture is set default in the initialization code
1437 if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {
1439 // For padding resource node, just ignore when programming
1441 return ;
1444 PciIo = &(Node->PciDev->PciIo);
1445 Address = Base + Node->Offset;
1448 // Indicate the PPB resource has been allocated
1450 Node->PciDev->Allocated = TRUE;
1452 switch (Node->Bar) {
1454 case PPB_BAR_0:
1455 case PPB_BAR_1:
1456 PciIo->Pci.Write (
1457 PciIo,
1458 EfiPciIoWidthUint32,
1459 (Node->PciDev->PciBar[Node->Bar]).Offset,
1461 &Address
1464 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1465 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1467 break;
1469 case PPB_IO_RANGE:
1471 Address32 = ((UINT32) (Address)) >> 8;
1472 PciIo->Pci.Write (
1473 PciIo,
1474 EfiPciIoWidthUint8,
1475 0x1C,
1477 &Address32
1480 Address32 >>= 8;
1481 PciIo->Pci.Write (
1482 PciIo,
1483 EfiPciIoWidthUint16,
1484 0x30,
1486 &Address32
1489 Address32 = (UINT32) (Address + Node->Length - 1);
1490 Address32 = ((UINT32) (Address32)) >> 8;
1491 PciIo->Pci.Write (
1492 PciIo,
1493 EfiPciIoWidthUint8,
1494 0x1D,
1496 &Address32
1499 Address32 >>= 8;
1500 PciIo->Pci.Write (
1501 PciIo,
1502 EfiPciIoWidthUint16,
1503 0x32,
1505 &Address32
1508 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1509 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1510 break;
1512 case PPB_MEM32_RANGE:
1514 Address32 = ((UINT32) (Address)) >> 16;
1515 PciIo->Pci.Write (
1516 PciIo,
1517 EfiPciIoWidthUint16,
1518 0x20,
1520 &Address32
1523 Address32 = (UINT32) (Address + Node->Length - 1);
1524 Address32 = ((UINT32) (Address32)) >> 16;
1525 PciIo->Pci.Write (
1526 PciIo,
1527 EfiPciIoWidthUint16,
1528 0x22,
1530 &Address32
1533 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1534 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1535 break;
1537 case PPB_PMEM32_RANGE:
1538 case PPB_PMEM64_RANGE:
1540 Address32 = ((UINT32) (Address)) >> 16;
1541 PciIo->Pci.Write (
1542 PciIo,
1543 EfiPciIoWidthUint16,
1544 0x24,
1546 &Address32
1549 Address32 = (UINT32) (Address + Node->Length - 1);
1550 Address32 = ((UINT32) (Address32)) >> 16;
1551 PciIo->Pci.Write (
1552 PciIo,
1553 EfiPciIoWidthUint16,
1554 0x26,
1556 &Address32
1559 Address32 = (UINT32) RShiftU64 (Address, 32);
1560 PciIo->Pci.Write (
1561 PciIo,
1562 EfiPciIoWidthUint32,
1563 0x28,
1565 &Address32
1568 Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);
1569 PciIo->Pci.Write (
1570 PciIo,
1571 EfiPciIoWidthUint32,
1572 0x2C,
1574 &Address32
1577 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1578 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1579 break;
1581 default:
1582 break;
1587 Program parent bridge for Option Rom.
1589 @param PciDevice Pci deivce instance.
1590 @param OptionRomBase Base address for Optiona Rom.
1591 @param Enable Enable or disable PCI memory.
1594 VOID
1595 ProgrameUpstreamBridgeForRom (
1596 IN PCI_IO_DEVICE *PciDevice,
1597 IN UINT32 OptionRomBase,
1598 IN BOOLEAN Enable
1601 PCI_IO_DEVICE *Parent;
1602 PCI_RESOURCE_NODE Node;
1604 // For root bridge, just return.
1606 Parent = PciDevice->Parent;
1607 ZeroMem (&Node, sizeof (Node));
1608 while (Parent != NULL) {
1609 if (!IS_PCI_BRIDGE (&Parent->Pci)) {
1610 break;
1613 Node.PciDev = Parent;
1614 Node.Length = PciDevice->RomSize;
1615 Node.Alignment = 0;
1616 Node.Bar = PPB_MEM32_RANGE;
1617 Node.ResType = PciBarTypeMem32;
1618 Node.Offset = 0;
1621 // Program PPB to only open a single <= 16MB apperture
1623 if (Enable) {
1624 ProgramPpbApperture (OptionRomBase, &Node);
1625 PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1626 } else {
1627 InitializePpb (Parent);
1628 PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1631 Parent = Parent->Parent;
1636 Test whether resource exists for a bridge.
1638 @param Bridge Point to resource node for a bridge.
1640 @retval TRUE There is resource on the given bridge.
1641 @retval FALSE There isn't resource on the given bridge.
1644 BOOLEAN
1645 ResourceRequestExisted (
1646 IN PCI_RESOURCE_NODE *Bridge
1649 if (Bridge != NULL) {
1650 if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {
1651 return TRUE;
1655 return FALSE;
1659 Initialize resource pool structure.
1661 @param ResourcePool Point to resource pool structure. This pool
1662 is reset to all zero when returned.
1663 @param ResourceType Type of resource.
1666 VOID
1667 InitializeResourcePool (
1668 IN OUT PCI_RESOURCE_NODE *ResourcePool,
1669 IN PCI_BAR_TYPE ResourceType
1672 ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
1673 ResourcePool->ResType = ResourceType;
1674 ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
1675 InitializeListHead (&ResourcePool->ChildList);
1680 Get all resource information for given Pci device.
1682 @param PciDev Pci device instance.
1683 @param IoBridge Io resource node.
1684 @param Mem32Bridge 32-bit memory node.
1685 @param PMem32Bridge 32-bit Pmemory node.
1686 @param Mem64Bridge 64-bit memory node.
1687 @param PMem64Bridge 64-bit PMemory node.
1688 @param IoPool Link list header for Io resource.
1689 @param Mem32Pool Link list header for 32-bit memory.
1690 @param PMem32Pool Link list header for 32-bit Prefetchable memory.
1691 @param Mem64Pool Link list header for 64-bit memory.
1692 @param PMem64Pool Link list header for 64-bit Prefetchable memory.
1695 VOID
1696 GetResourceMap (
1697 IN PCI_IO_DEVICE *PciDev,
1698 IN PCI_RESOURCE_NODE **IoBridge,
1699 IN PCI_RESOURCE_NODE **Mem32Bridge,
1700 IN PCI_RESOURCE_NODE **PMem32Bridge,
1701 IN PCI_RESOURCE_NODE **Mem64Bridge,
1702 IN PCI_RESOURCE_NODE **PMem64Bridge,
1703 IN PCI_RESOURCE_NODE *IoPool,
1704 IN PCI_RESOURCE_NODE *Mem32Pool,
1705 IN PCI_RESOURCE_NODE *PMem32Pool,
1706 IN PCI_RESOURCE_NODE *Mem64Pool,
1707 IN PCI_RESOURCE_NODE *PMem64Pool
1711 PCI_RESOURCE_NODE *Temp;
1712 LIST_ENTRY *CurrentLink;
1714 CurrentLink = IoPool->ChildList.ForwardLink;
1717 // Get Io resource map
1719 while (CurrentLink != &IoPool->ChildList) {
1721 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1723 if (Temp->PciDev == PciDev) {
1724 *IoBridge = Temp;
1727 CurrentLink = CurrentLink->ForwardLink;
1731 // Get Mem32 resource map
1733 CurrentLink = Mem32Pool->ChildList.ForwardLink;
1735 while (CurrentLink != &Mem32Pool->ChildList) {
1737 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1739 if (Temp->PciDev == PciDev) {
1740 *Mem32Bridge = Temp;
1743 CurrentLink = CurrentLink->ForwardLink;
1747 // Get Pmem32 resource map
1749 CurrentLink = PMem32Pool->ChildList.ForwardLink;
1751 while (CurrentLink != &PMem32Pool->ChildList) {
1753 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1755 if (Temp->PciDev == PciDev) {
1756 *PMem32Bridge = Temp;
1759 CurrentLink = CurrentLink->ForwardLink;
1763 // Get Mem64 resource map
1765 CurrentLink = Mem64Pool->ChildList.ForwardLink;
1767 while (CurrentLink != &Mem64Pool->ChildList) {
1769 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1771 if (Temp->PciDev == PciDev) {
1772 *Mem64Bridge = Temp;
1775 CurrentLink = CurrentLink->ForwardLink;
1779 // Get Pmem64 resource map
1781 CurrentLink = PMem64Pool->ChildList.ForwardLink;
1783 while (CurrentLink != &PMem64Pool->ChildList) {
1785 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1787 if (Temp->PciDev == PciDev) {
1788 *PMem64Bridge = Temp;
1791 CurrentLink = CurrentLink->ForwardLink;
1796 Destory given resource tree.
1798 @param Bridge PCI resource root node of resource tree.
1801 VOID
1802 DestroyResourceTree (
1803 IN PCI_RESOURCE_NODE *Bridge
1806 PCI_RESOURCE_NODE *Temp;
1807 LIST_ENTRY *CurrentLink;
1809 while (!IsListEmpty (&Bridge->ChildList)) {
1811 CurrentLink = Bridge->ChildList.ForwardLink;
1813 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1814 ASSERT (Temp);
1816 RemoveEntryList (CurrentLink);
1818 if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
1819 DestroyResourceTree (Temp);
1822 FreePool (Temp);
1827 Insert resource padding for P2C.
1829 @param PciDev Pci device instance.
1830 @param IoNode Resource info node for IO.
1831 @param Mem32Node Resource info node for 32-bit memory.
1832 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1833 @param Mem64Node Resource info node for 64-bit memory.
1834 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1837 VOID
1838 ResourcePaddingForCardBusBridge (
1839 IN PCI_IO_DEVICE *PciDev,
1840 IN PCI_RESOURCE_NODE *IoNode,
1841 IN PCI_RESOURCE_NODE *Mem32Node,
1842 IN PCI_RESOURCE_NODE *PMem32Node,
1843 IN PCI_RESOURCE_NODE *Mem64Node,
1844 IN PCI_RESOURCE_NODE *PMem64Node
1847 PCI_RESOURCE_NODE *Node;
1849 Node = NULL;
1852 // Memory Base/Limit Register 0
1853 // Bar 1 denodes memory range 0
1855 Node = CreateResourceNode (
1856 PciDev,
1857 0x2000000,
1858 0x1ffffff,
1860 PciBarTypeMem32,
1861 PciResUsagePadding
1864 InsertResourceNode (
1865 Mem32Node,
1866 Node
1870 // Memory Base/Limit Register 1
1871 // Bar 2 denodes memory range1
1873 Node = CreateResourceNode (
1874 PciDev,
1875 0x2000000,
1876 0x1ffffff,
1878 PciBarTypePMem32,
1879 PciResUsagePadding
1882 InsertResourceNode (
1883 PMem32Node,
1884 Node
1888 // Io Base/Limit
1889 // Bar 3 denodes io range 0
1891 Node = CreateResourceNode (
1892 PciDev,
1893 0x100,
1894 0xff,
1896 PciBarTypeIo16,
1897 PciResUsagePadding
1900 InsertResourceNode (
1901 IoNode,
1902 Node
1906 // Io Base/Limit
1907 // Bar 4 denodes io range 0
1909 Node = CreateResourceNode (
1910 PciDev,
1911 0x100,
1912 0xff,
1914 PciBarTypeIo16,
1915 PciResUsagePadding
1918 InsertResourceNode (
1919 IoNode,
1920 Node
1925 Program PCI Card device register for given resource node.
1927 @param Base Base address of PCI Card device to be programmed.
1928 @param Node Given resource node.
1931 VOID
1932 ProgramP2C (
1933 IN UINT64 Base,
1934 IN PCI_RESOURCE_NODE *Node
1937 EFI_PCI_IO_PROTOCOL *PciIo;
1938 UINT64 Address;
1939 UINT64 TempAddress;
1940 UINT16 BridgeControl;
1942 Address = 0;
1943 PciIo = &(Node->PciDev->PciIo);
1945 Address = Base + Node->Offset;
1948 // Indicate pci bus driver has allocated
1949 // resource for this device
1950 // It might be a temporary solution here since
1951 // pci device could have multiple bar
1953 Node->PciDev->Allocated = TRUE;
1955 switch (Node->Bar) {
1957 case P2C_BAR_0:
1958 PciIo->Pci.Write (
1959 PciIo,
1960 EfiPciIoWidthUint32,
1961 (Node->PciDev->PciBar[Node->Bar]).Offset,
1963 &Address
1966 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1967 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1968 break;
1970 case P2C_MEM_1:
1971 PciIo->Pci.Write (
1972 PciIo,
1973 EfiPciIoWidthUint32,
1974 PCI_CARD_MEMORY_BASE_0,
1976 &Address
1979 TempAddress = Address + Node->Length - 1;
1980 PciIo->Pci.Write (
1981 PciIo,
1982 EfiPciIoWidthUint32,
1983 PCI_CARD_MEMORY_LIMIT_0,
1985 &TempAddress
1988 if (Node->ResType == PciBarTypeMem32) {
1990 // Set non-prefetchable bit
1992 PciIo->Pci.Read (
1993 PciIo,
1994 EfiPciIoWidthUint16,
1995 PCI_CARD_BRIDGE_CONTROL,
1997 &BridgeControl
2000 BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
2001 PciIo->Pci.Write (
2002 PciIo,
2003 EfiPciIoWidthUint16,
2004 PCI_CARD_BRIDGE_CONTROL,
2006 &BridgeControl
2009 } else {
2011 // Set pre-fetchable bit
2013 PciIo->Pci.Read (
2014 PciIo,
2015 EfiPciIoWidthUint16,
2016 PCI_CARD_BRIDGE_CONTROL,
2018 &BridgeControl
2021 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
2022 PciIo->Pci.Write (
2023 PciIo,
2024 EfiPciIoWidthUint16,
2025 PCI_CARD_BRIDGE_CONTROL,
2027 &BridgeControl
2031 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2032 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2033 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2035 break;
2037 case P2C_MEM_2:
2038 PciIo->Pci.Write (
2039 PciIo,
2040 EfiPciIoWidthUint32,
2041 PCI_CARD_MEMORY_BASE_1,
2043 &Address
2046 TempAddress = Address + Node->Length - 1;
2048 PciIo->Pci.Write (
2049 PciIo,
2050 EfiPciIoWidthUint32,
2051 PCI_CARD_MEMORY_LIMIT_1,
2053 &TempAddress
2056 if (Node->ResType == PciBarTypeMem32) {
2059 // Set non-prefetchable bit
2061 PciIo->Pci.Read (
2062 PciIo,
2063 EfiPciIoWidthUint16,
2064 PCI_CARD_BRIDGE_CONTROL,
2066 &BridgeControl
2069 BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);
2070 PciIo->Pci.Write (
2071 PciIo,
2072 EfiPciIoWidthUint16,
2073 PCI_CARD_BRIDGE_CONTROL,
2075 &BridgeControl
2078 } else {
2081 // Set pre-fetchable bit
2083 PciIo->Pci.Read (
2084 PciIo,
2085 EfiPciIoWidthUint16,
2086 PCI_CARD_BRIDGE_CONTROL,
2088 &BridgeControl
2091 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;
2092 PciIo->Pci.Write (
2093 PciIo,
2094 EfiPciIoWidthUint16,
2095 PCI_CARD_BRIDGE_CONTROL,
2097 &BridgeControl
2101 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2102 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2103 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2104 break;
2106 case P2C_IO_1:
2107 PciIo->Pci.Write (
2108 PciIo,
2109 EfiPciIoWidthUint32,
2110 PCI_CARD_IO_BASE_0_LOWER,
2112 &Address
2115 TempAddress = Address + Node->Length - 1;
2116 PciIo->Pci.Write (
2117 PciIo,
2118 EfiPciIoWidthUint32,
2119 PCI_CARD_IO_LIMIT_0_LOWER,
2121 &TempAddress
2124 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2125 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2126 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2128 break;
2130 case P2C_IO_2:
2131 PciIo->Pci.Write (
2132 PciIo,
2133 EfiPciIoWidthUint32,
2134 PCI_CARD_IO_BASE_1_LOWER,
2136 &Address
2139 TempAddress = Address + Node->Length - 1;
2140 PciIo->Pci.Write (
2141 PciIo,
2142 EfiPciIoWidthUint32,
2143 PCI_CARD_IO_LIMIT_1_LOWER,
2145 &TempAddress
2148 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2149 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2150 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2151 break;
2153 default:
2154 break;
2159 Create padding resource node.
2161 @param PciDev Pci device instance.
2162 @param IoNode Resource info node for IO.
2163 @param Mem32Node Resource info node for 32-bit memory.
2164 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
2165 @param Mem64Node Resource info node for 64-bit memory.
2166 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
2169 VOID
2170 ApplyResourcePadding (
2171 IN PCI_IO_DEVICE *PciDev,
2172 IN PCI_RESOURCE_NODE *IoNode,
2173 IN PCI_RESOURCE_NODE *Mem32Node,
2174 IN PCI_RESOURCE_NODE *PMem32Node,
2175 IN PCI_RESOURCE_NODE *Mem64Node,
2176 IN PCI_RESOURCE_NODE *PMem64Node
2179 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
2180 PCI_RESOURCE_NODE *Node;
2181 UINT8 DummyBarIndex;
2183 DummyBarIndex = 0;
2184 Ptr = PciDev->ResourcePaddingDescriptors;
2186 while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
2188 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
2189 if (Ptr->AddrLen != 0) {
2191 Node = CreateResourceNode (
2192 PciDev,
2193 Ptr->AddrLen,
2194 Ptr->AddrRangeMax,
2195 DummyBarIndex,
2196 PciBarTypeIo16,
2197 PciResUsagePadding
2199 InsertResourceNode (
2200 IoNode,
2201 Node
2205 Ptr++;
2206 continue;
2209 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
2211 if (Ptr->AddrSpaceGranularity == 32) {
2214 // prefechable
2216 if (Ptr->SpecificFlag == 0x6) {
2217 if (Ptr->AddrLen != 0) {
2218 Node = CreateResourceNode (
2219 PciDev,
2220 Ptr->AddrLen,
2221 Ptr->AddrRangeMax,
2222 DummyBarIndex,
2223 PciBarTypePMem32,
2224 PciResUsagePadding
2226 InsertResourceNode (
2227 PMem32Node,
2228 Node
2232 Ptr++;
2233 continue;
2237 // Non-prefechable
2239 if (Ptr->SpecificFlag == 0) {
2240 if (Ptr->AddrLen != 0) {
2241 Node = CreateResourceNode (
2242 PciDev,
2243 Ptr->AddrLen,
2244 Ptr->AddrRangeMax,
2245 DummyBarIndex,
2246 PciBarTypeMem32,
2247 PciResUsagePadding
2249 InsertResourceNode (
2250 Mem32Node,
2251 Node
2255 Ptr++;
2256 continue;
2260 if (Ptr->AddrSpaceGranularity == 64) {
2263 // prefechable
2265 if (Ptr->SpecificFlag == 0x6) {
2266 if (Ptr->AddrLen != 0) {
2267 Node = CreateResourceNode (
2268 PciDev,
2269 Ptr->AddrLen,
2270 Ptr->AddrRangeMax,
2271 DummyBarIndex,
2272 PciBarTypePMem64,
2273 PciResUsagePadding
2275 InsertResourceNode (
2276 PMem64Node,
2277 Node
2281 Ptr++;
2282 continue;
2286 // Non-prefechable
2288 if (Ptr->SpecificFlag == 0) {
2289 if (Ptr->AddrLen != 0) {
2290 Node = CreateResourceNode (
2291 PciDev,
2292 Ptr->AddrLen,
2293 Ptr->AddrRangeMax,
2294 DummyBarIndex,
2295 PciBarTypeMem64,
2296 PciResUsagePadding
2298 InsertResourceNode (
2299 Mem64Node,
2300 Node
2304 Ptr++;
2305 continue;
2310 Ptr++;
2315 Get padding resource for PCI-PCI bridge.
2317 @param PciIoDevice PCI-PCI bridge device instance.
2319 @note Feature flag PcdPciBusHotplugDeviceSupport determines
2320 whether need to pad resource for them.
2322 VOID
2323 GetResourcePaddingPpb (
2324 IN PCI_IO_DEVICE *PciIoDevice
2327 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
2328 if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
2329 GetResourcePaddingForHpb (PciIoDevice);