add SR-IOV support in EDK II.
[edk2.git] / IntelFrameworkModulePkg / Bus / Pci / PciBusDxe / PciResourceSupport.c
blob17c864029b3d1eec88e95b347993fd3f75a040ca
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;
1233 // Check VF BAR
1235 if (Node->Virtual) {
1236 ProgramVfBar (Base, Node);
1239 Address = 0;
1240 PciIo = &(Node->PciDev->PciIo);
1242 Address = Base + Node->Offset;
1245 // Indicate pci bus driver has allocated
1246 // resource for this device
1247 // It might be a temporary solution here since
1248 // pci device could have multiple bar
1250 Node->PciDev->Allocated = TRUE;
1252 ASSERT (Node->Bar < PCI_MAX_BAR);
1253 switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
1255 case PciBarTypeIo16:
1256 case PciBarTypeIo32:
1257 case PciBarTypeMem32:
1258 case PciBarTypePMem32:
1260 PciIo->Pci.Write (
1261 PciIo,
1262 EfiPciIoWidthUint32,
1263 (Node->PciDev->PciBar[Node->Bar]).Offset,
1265 &Address
1268 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1270 break;
1272 case PciBarTypeMem64:
1273 case PciBarTypePMem64:
1275 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1277 PciIo->Pci.Write (
1278 PciIo,
1279 EfiPciIoWidthUint32,
1280 (Node->PciDev->PciBar[Node->Bar]).Offset,
1282 &Address32
1285 Address32 = (UINT32) RShiftU64 (Address, 32);
1287 PciIo->Pci.Write (
1288 PciIo,
1289 EfiPciIoWidthUint32,
1290 (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
1292 &Address32
1295 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1297 break;
1299 default:
1300 break;
1305 Program IOV VF Bar register for PCI device.
1307 @param Base Base address for PCI device resource to be progammed.
1308 @param Node Point to resoure node structure.
1311 EFI_STATUS
1312 ProgramVfBar (
1313 IN UINT64 Base,
1314 IN PCI_RESOURCE_NODE *Node
1317 EFI_PCI_IO_PROTOCOL *PciIo;
1318 UINT64 Address;
1319 UINT32 Address32;
1321 ASSERT (Node->Virtual);
1322 if (!Node->Virtual) {
1323 return EFI_UNSUPPORTED;
1326 Address = 0;
1327 PciIo = &(Node->PciDev->PciIo);
1329 Address = Base + Node->Offset;
1332 // Indicate pci bus driver has allocated
1333 // resource for this device
1334 // It might be a temporary solution here since
1335 // pci device could have multiple bar
1337 Node->PciDev->Allocated = TRUE;
1339 switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {
1341 case PciBarTypeMem32:
1342 case PciBarTypePMem32:
1344 PciIo->Pci.Write (
1345 PciIo,
1346 EfiPciIoWidthUint32,
1347 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
1349 &Address
1352 Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
1354 DEBUG ((
1355 EFI_D_INFO,
1356 "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 32Mem (Address - 0x%x)\n",
1357 (UINTN)Node->PciDev->BusNumber,
1358 (UINTN)Node->PciDev->DeviceNumber,
1359 (UINTN)Node->PciDev->FunctionNumber,
1360 (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,
1361 (UINTN)Address
1364 break;
1366 case PciBarTypeMem64:
1367 case PciBarTypePMem64:
1369 Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1371 PciIo->Pci.Write (
1372 PciIo,
1373 EfiPciIoWidthUint32,
1374 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
1376 &Address32
1379 Address32 = (UINT32) RShiftU64 (Address, 32);
1381 PciIo->Pci.Write (
1382 PciIo,
1383 EfiPciIoWidthUint32,
1384 ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),
1386 &Address32
1389 Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
1391 DEBUG ((
1392 EFI_D_INFO,
1393 "PCI-IOV B%x.D%x.F%x - VF Bar (Offset - 0x%x) 64Mem (Address - 0x%lx)\n",
1394 (UINTN)Node->PciDev->BusNumber,
1395 (UINTN)Node->PciDev->DeviceNumber,
1396 (UINTN)Node->PciDev->FunctionNumber,
1397 (UINTN)(Node->PciDev->VfPciBar[Node->Bar]).Offset,
1398 (UINT64)Address
1401 break;
1403 case PciBarTypeIo16:
1404 case PciBarTypeIo32:
1405 break;
1407 default:
1408 break;
1411 return EFI_SUCCESS;
1415 Program PCI-PCI bridge apperture.
1417 @param Base Base address for resource.
1418 @param Node Point to resoure node structure.
1421 VOID
1422 ProgramPpbApperture (
1423 IN UINT64 Base,
1424 IN PCI_RESOURCE_NODE *Node
1427 EFI_PCI_IO_PROTOCOL *PciIo;
1428 UINT64 Address;
1429 UINT32 Address32;
1431 Address = 0;
1433 // If no device resource of this PPB, return anyway
1434 // Apperture is set default in the initialization code
1436 if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {
1438 // For padding resource node, just ignore when programming
1440 return ;
1443 PciIo = &(Node->PciDev->PciIo);
1444 Address = Base + Node->Offset;
1447 // Indicate the PPB resource has been allocated
1449 Node->PciDev->Allocated = TRUE;
1451 switch (Node->Bar) {
1453 case PPB_BAR_0:
1454 case PPB_BAR_1:
1455 PciIo->Pci.Write (
1456 PciIo,
1457 EfiPciIoWidthUint32,
1458 (Node->PciDev->PciBar[Node->Bar]).Offset,
1460 &Address
1463 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1464 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1466 break;
1468 case PPB_IO_RANGE:
1470 Address32 = ((UINT32) (Address)) >> 8;
1471 PciIo->Pci.Write (
1472 PciIo,
1473 EfiPciIoWidthUint8,
1474 0x1C,
1476 &Address32
1479 Address32 >>= 8;
1480 PciIo->Pci.Write (
1481 PciIo,
1482 EfiPciIoWidthUint16,
1483 0x30,
1485 &Address32
1488 Address32 = (UINT32) (Address + Node->Length - 1);
1489 Address32 = ((UINT32) (Address32)) >> 8;
1490 PciIo->Pci.Write (
1491 PciIo,
1492 EfiPciIoWidthUint8,
1493 0x1D,
1495 &Address32
1498 Address32 >>= 8;
1499 PciIo->Pci.Write (
1500 PciIo,
1501 EfiPciIoWidthUint16,
1502 0x32,
1504 &Address32
1507 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1508 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1509 break;
1511 case PPB_MEM32_RANGE:
1513 Address32 = ((UINT32) (Address)) >> 16;
1514 PciIo->Pci.Write (
1515 PciIo,
1516 EfiPciIoWidthUint16,
1517 0x20,
1519 &Address32
1522 Address32 = (UINT32) (Address + Node->Length - 1);
1523 Address32 = ((UINT32) (Address32)) >> 16;
1524 PciIo->Pci.Write (
1525 PciIo,
1526 EfiPciIoWidthUint16,
1527 0x22,
1529 &Address32
1532 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1533 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1534 break;
1536 case PPB_PMEM32_RANGE:
1537 case PPB_PMEM64_RANGE:
1539 Address32 = ((UINT32) (Address)) >> 16;
1540 PciIo->Pci.Write (
1541 PciIo,
1542 EfiPciIoWidthUint16,
1543 0x24,
1545 &Address32
1548 Address32 = (UINT32) (Address + Node->Length - 1);
1549 Address32 = ((UINT32) (Address32)) >> 16;
1550 PciIo->Pci.Write (
1551 PciIo,
1552 EfiPciIoWidthUint16,
1553 0x26,
1555 &Address32
1558 Address32 = (UINT32) RShiftU64 (Address, 32);
1559 PciIo->Pci.Write (
1560 PciIo,
1561 EfiPciIoWidthUint32,
1562 0x28,
1564 &Address32
1567 Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);
1568 PciIo->Pci.Write (
1569 PciIo,
1570 EfiPciIoWidthUint32,
1571 0x2C,
1573 &Address32
1576 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1577 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1578 break;
1580 default:
1581 break;
1586 Program parent bridge for Option Rom.
1588 @param PciDevice Pci deivce instance.
1589 @param OptionRomBase Base address for Optiona Rom.
1590 @param Enable Enable or disable PCI memory.
1593 VOID
1594 ProgrameUpstreamBridgeForRom (
1595 IN PCI_IO_DEVICE *PciDevice,
1596 IN UINT32 OptionRomBase,
1597 IN BOOLEAN Enable
1600 PCI_IO_DEVICE *Parent;
1601 PCI_RESOURCE_NODE Node;
1603 // For root bridge, just return.
1605 Parent = PciDevice->Parent;
1606 ZeroMem (&Node, sizeof (Node));
1607 while (Parent != NULL) {
1608 if (!IS_PCI_BRIDGE (&Parent->Pci)) {
1609 break;
1612 Node.PciDev = Parent;
1613 Node.Length = PciDevice->RomSize;
1614 Node.Alignment = 0;
1615 Node.Bar = PPB_MEM32_RANGE;
1616 Node.ResType = PciBarTypeMem32;
1617 Node.Offset = 0;
1620 // Program PPB to only open a single <= 16MB apperture
1622 if (Enable) {
1623 ProgramPpbApperture (OptionRomBase, &Node);
1624 PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1625 } else {
1626 InitializePpb (Parent);
1627 PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1630 Parent = Parent->Parent;
1635 Test whether resource exists for a bridge.
1637 @param Bridge Point to resource node for a bridge.
1639 @retval TRUE There is resource on the given bridge.
1640 @retval FALSE There isn't resource on the given bridge.
1643 BOOLEAN
1644 ResourceRequestExisted (
1645 IN PCI_RESOURCE_NODE *Bridge
1648 if (Bridge != NULL) {
1649 if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {
1650 return TRUE;
1654 return FALSE;
1658 Initialize resource pool structure.
1660 @param ResourcePool Point to resource pool structure. This pool
1661 is reset to all zero when returned.
1662 @param ResourceType Type of resource.
1665 VOID
1666 InitializeResourcePool (
1667 IN OUT PCI_RESOURCE_NODE *ResourcePool,
1668 IN PCI_BAR_TYPE ResourceType
1671 ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
1672 ResourcePool->ResType = ResourceType;
1673 ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
1674 InitializeListHead (&ResourcePool->ChildList);
1679 Get all resource information for given Pci device.
1681 @param PciDev Pci device instance.
1682 @param IoBridge Io resource node.
1683 @param Mem32Bridge 32-bit memory node.
1684 @param PMem32Bridge 32-bit Pmemory node.
1685 @param Mem64Bridge 64-bit memory node.
1686 @param PMem64Bridge 64-bit PMemory node.
1687 @param IoPool Link list header for Io resource.
1688 @param Mem32Pool Link list header for 32-bit memory.
1689 @param PMem32Pool Link list header for 32-bit Prefetchable memory.
1690 @param Mem64Pool Link list header for 64-bit memory.
1691 @param PMem64Pool Link list header for 64-bit Prefetchable memory.
1694 VOID
1695 GetResourceMap (
1696 IN PCI_IO_DEVICE *PciDev,
1697 IN PCI_RESOURCE_NODE **IoBridge,
1698 IN PCI_RESOURCE_NODE **Mem32Bridge,
1699 IN PCI_RESOURCE_NODE **PMem32Bridge,
1700 IN PCI_RESOURCE_NODE **Mem64Bridge,
1701 IN PCI_RESOURCE_NODE **PMem64Bridge,
1702 IN PCI_RESOURCE_NODE *IoPool,
1703 IN PCI_RESOURCE_NODE *Mem32Pool,
1704 IN PCI_RESOURCE_NODE *PMem32Pool,
1705 IN PCI_RESOURCE_NODE *Mem64Pool,
1706 IN PCI_RESOURCE_NODE *PMem64Pool
1710 PCI_RESOURCE_NODE *Temp;
1711 LIST_ENTRY *CurrentLink;
1713 CurrentLink = IoPool->ChildList.ForwardLink;
1716 // Get Io resource map
1718 while (CurrentLink != &IoPool->ChildList) {
1720 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1722 if (Temp->PciDev == PciDev) {
1723 *IoBridge = Temp;
1726 CurrentLink = CurrentLink->ForwardLink;
1730 // Get Mem32 resource map
1732 CurrentLink = Mem32Pool->ChildList.ForwardLink;
1734 while (CurrentLink != &Mem32Pool->ChildList) {
1736 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1738 if (Temp->PciDev == PciDev) {
1739 *Mem32Bridge = Temp;
1742 CurrentLink = CurrentLink->ForwardLink;
1746 // Get Pmem32 resource map
1748 CurrentLink = PMem32Pool->ChildList.ForwardLink;
1750 while (CurrentLink != &PMem32Pool->ChildList) {
1752 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1754 if (Temp->PciDev == PciDev) {
1755 *PMem32Bridge = Temp;
1758 CurrentLink = CurrentLink->ForwardLink;
1762 // Get Mem64 resource map
1764 CurrentLink = Mem64Pool->ChildList.ForwardLink;
1766 while (CurrentLink != &Mem64Pool->ChildList) {
1768 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1770 if (Temp->PciDev == PciDev) {
1771 *Mem64Bridge = Temp;
1774 CurrentLink = CurrentLink->ForwardLink;
1778 // Get Pmem64 resource map
1780 CurrentLink = PMem64Pool->ChildList.ForwardLink;
1782 while (CurrentLink != &PMem64Pool->ChildList) {
1784 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1786 if (Temp->PciDev == PciDev) {
1787 *PMem64Bridge = Temp;
1790 CurrentLink = CurrentLink->ForwardLink;
1795 Destory given resource tree.
1797 @param Bridge PCI resource root node of resource tree.
1800 VOID
1801 DestroyResourceTree (
1802 IN PCI_RESOURCE_NODE *Bridge
1805 PCI_RESOURCE_NODE *Temp;
1806 LIST_ENTRY *CurrentLink;
1808 while (!IsListEmpty (&Bridge->ChildList)) {
1810 CurrentLink = Bridge->ChildList.ForwardLink;
1812 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
1813 ASSERT (Temp);
1815 RemoveEntryList (CurrentLink);
1817 if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
1818 DestroyResourceTree (Temp);
1821 FreePool (Temp);
1826 Insert resource padding for P2C.
1828 @param PciDev Pci device instance.
1829 @param IoNode Resource info node for IO.
1830 @param Mem32Node Resource info node for 32-bit memory.
1831 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1832 @param Mem64Node Resource info node for 64-bit memory.
1833 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1836 VOID
1837 ResourcePaddingForCardBusBridge (
1838 IN PCI_IO_DEVICE *PciDev,
1839 IN PCI_RESOURCE_NODE *IoNode,
1840 IN PCI_RESOURCE_NODE *Mem32Node,
1841 IN PCI_RESOURCE_NODE *PMem32Node,
1842 IN PCI_RESOURCE_NODE *Mem64Node,
1843 IN PCI_RESOURCE_NODE *PMem64Node
1846 PCI_RESOURCE_NODE *Node;
1848 Node = NULL;
1851 // Memory Base/Limit Register 0
1852 // Bar 1 denodes memory range 0
1854 Node = CreateResourceNode (
1855 PciDev,
1856 0x2000000,
1857 0x1ffffff,
1859 PciBarTypeMem32,
1860 PciResUsagePadding
1863 InsertResourceNode (
1864 Mem32Node,
1865 Node
1869 // Memory Base/Limit Register 1
1870 // Bar 2 denodes memory range1
1872 Node = CreateResourceNode (
1873 PciDev,
1874 0x2000000,
1875 0x1ffffff,
1877 PciBarTypePMem32,
1878 PciResUsagePadding
1881 InsertResourceNode (
1882 PMem32Node,
1883 Node
1887 // Io Base/Limit
1888 // Bar 3 denodes io range 0
1890 Node = CreateResourceNode (
1891 PciDev,
1892 0x100,
1893 0xff,
1895 PciBarTypeIo16,
1896 PciResUsagePadding
1899 InsertResourceNode (
1900 IoNode,
1901 Node
1905 // Io Base/Limit
1906 // Bar 4 denodes io range 0
1908 Node = CreateResourceNode (
1909 PciDev,
1910 0x100,
1911 0xff,
1913 PciBarTypeIo16,
1914 PciResUsagePadding
1917 InsertResourceNode (
1918 IoNode,
1919 Node
1924 Program PCI Card device register for given resource node.
1926 @param Base Base address of PCI Card device to be programmed.
1927 @param Node Given resource node.
1930 VOID
1931 ProgramP2C (
1932 IN UINT64 Base,
1933 IN PCI_RESOURCE_NODE *Node
1936 EFI_PCI_IO_PROTOCOL *PciIo;
1937 UINT64 Address;
1938 UINT64 TempAddress;
1939 UINT16 BridgeControl;
1941 Address = 0;
1942 PciIo = &(Node->PciDev->PciIo);
1944 Address = Base + Node->Offset;
1947 // Indicate pci bus driver has allocated
1948 // resource for this device
1949 // It might be a temporary solution here since
1950 // pci device could have multiple bar
1952 Node->PciDev->Allocated = TRUE;
1954 switch (Node->Bar) {
1956 case P2C_BAR_0:
1957 PciIo->Pci.Write (
1958 PciIo,
1959 EfiPciIoWidthUint32,
1960 (Node->PciDev->PciBar[Node->Bar]).Offset,
1962 &Address
1965 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1966 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
1967 break;
1969 case P2C_MEM_1:
1970 PciIo->Pci.Write (
1971 PciIo,
1972 EfiPciIoWidthUint32,
1973 PCI_CARD_MEMORY_BASE_0,
1975 &Address
1978 TempAddress = Address + Node->Length - 1;
1979 PciIo->Pci.Write (
1980 PciIo,
1981 EfiPciIoWidthUint32,
1982 PCI_CARD_MEMORY_LIMIT_0,
1984 &TempAddress
1987 if (Node->ResType == PciBarTypeMem32) {
1989 // Set non-prefetchable bit
1991 PciIo->Pci.Read (
1992 PciIo,
1993 EfiPciIoWidthUint16,
1994 PCI_CARD_BRIDGE_CONTROL,
1996 &BridgeControl
1999 BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
2000 PciIo->Pci.Write (
2001 PciIo,
2002 EfiPciIoWidthUint16,
2003 PCI_CARD_BRIDGE_CONTROL,
2005 &BridgeControl
2008 } else {
2010 // Set pre-fetchable bit
2012 PciIo->Pci.Read (
2013 PciIo,
2014 EfiPciIoWidthUint16,
2015 PCI_CARD_BRIDGE_CONTROL,
2017 &BridgeControl
2020 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
2021 PciIo->Pci.Write (
2022 PciIo,
2023 EfiPciIoWidthUint16,
2024 PCI_CARD_BRIDGE_CONTROL,
2026 &BridgeControl
2030 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2031 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2032 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2034 break;
2036 case P2C_MEM_2:
2037 PciIo->Pci.Write (
2038 PciIo,
2039 EfiPciIoWidthUint32,
2040 PCI_CARD_MEMORY_BASE_1,
2042 &Address
2045 TempAddress = Address + Node->Length - 1;
2047 PciIo->Pci.Write (
2048 PciIo,
2049 EfiPciIoWidthUint32,
2050 PCI_CARD_MEMORY_LIMIT_1,
2052 &TempAddress
2055 if (Node->ResType == PciBarTypeMem32) {
2058 // Set non-prefetchable bit
2060 PciIo->Pci.Read (
2061 PciIo,
2062 EfiPciIoWidthUint16,
2063 PCI_CARD_BRIDGE_CONTROL,
2065 &BridgeControl
2068 BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);
2069 PciIo->Pci.Write (
2070 PciIo,
2071 EfiPciIoWidthUint16,
2072 PCI_CARD_BRIDGE_CONTROL,
2074 &BridgeControl
2077 } else {
2080 // Set pre-fetchable bit
2082 PciIo->Pci.Read (
2083 PciIo,
2084 EfiPciIoWidthUint16,
2085 PCI_CARD_BRIDGE_CONTROL,
2087 &BridgeControl
2090 BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;
2091 PciIo->Pci.Write (
2092 PciIo,
2093 EfiPciIoWidthUint16,
2094 PCI_CARD_BRIDGE_CONTROL,
2096 &BridgeControl
2100 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2101 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2102 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2103 break;
2105 case P2C_IO_1:
2106 PciIo->Pci.Write (
2107 PciIo,
2108 EfiPciIoWidthUint32,
2109 PCI_CARD_IO_BASE_0_LOWER,
2111 &Address
2114 TempAddress = Address + Node->Length - 1;
2115 PciIo->Pci.Write (
2116 PciIo,
2117 EfiPciIoWidthUint32,
2118 PCI_CARD_IO_LIMIT_0_LOWER,
2120 &TempAddress
2123 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2124 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2125 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2127 break;
2129 case P2C_IO_2:
2130 PciIo->Pci.Write (
2131 PciIo,
2132 EfiPciIoWidthUint32,
2133 PCI_CARD_IO_BASE_1_LOWER,
2135 &Address
2138 TempAddress = Address + Node->Length - 1;
2139 PciIo->Pci.Write (
2140 PciIo,
2141 EfiPciIoWidthUint32,
2142 PCI_CARD_IO_LIMIT_1_LOWER,
2144 &TempAddress
2147 Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2148 Node->PciDev->PciBar[Node->Bar].Length = Node->Length;
2149 Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType;
2150 break;
2152 default:
2153 break;
2158 Create padding resource node.
2160 @param PciDev Pci device instance.
2161 @param IoNode Resource info node for IO.
2162 @param Mem32Node Resource info node for 32-bit memory.
2163 @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
2164 @param Mem64Node Resource info node for 64-bit memory.
2165 @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
2168 VOID
2169 ApplyResourcePadding (
2170 IN PCI_IO_DEVICE *PciDev,
2171 IN PCI_RESOURCE_NODE *IoNode,
2172 IN PCI_RESOURCE_NODE *Mem32Node,
2173 IN PCI_RESOURCE_NODE *PMem32Node,
2174 IN PCI_RESOURCE_NODE *Mem64Node,
2175 IN PCI_RESOURCE_NODE *PMem64Node
2178 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
2179 PCI_RESOURCE_NODE *Node;
2180 UINT8 DummyBarIndex;
2182 DummyBarIndex = 0;
2183 Ptr = PciDev->ResourcePaddingDescriptors;
2185 while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
2187 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
2188 if (Ptr->AddrLen != 0) {
2190 Node = CreateResourceNode (
2191 PciDev,
2192 Ptr->AddrLen,
2193 Ptr->AddrRangeMax,
2194 DummyBarIndex,
2195 PciBarTypeIo16,
2196 PciResUsagePadding
2198 InsertResourceNode (
2199 IoNode,
2200 Node
2204 Ptr++;
2205 continue;
2208 if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
2210 if (Ptr->AddrSpaceGranularity == 32) {
2213 // prefechable
2215 if (Ptr->SpecificFlag == 0x6) {
2216 if (Ptr->AddrLen != 0) {
2217 Node = CreateResourceNode (
2218 PciDev,
2219 Ptr->AddrLen,
2220 Ptr->AddrRangeMax,
2221 DummyBarIndex,
2222 PciBarTypePMem32,
2223 PciResUsagePadding
2225 InsertResourceNode (
2226 PMem32Node,
2227 Node
2231 Ptr++;
2232 continue;
2236 // Non-prefechable
2238 if (Ptr->SpecificFlag == 0) {
2239 if (Ptr->AddrLen != 0) {
2240 Node = CreateResourceNode (
2241 PciDev,
2242 Ptr->AddrLen,
2243 Ptr->AddrRangeMax,
2244 DummyBarIndex,
2245 PciBarTypeMem32,
2246 PciResUsagePadding
2248 InsertResourceNode (
2249 Mem32Node,
2250 Node
2254 Ptr++;
2255 continue;
2259 if (Ptr->AddrSpaceGranularity == 64) {
2262 // prefechable
2264 if (Ptr->SpecificFlag == 0x6) {
2265 if (Ptr->AddrLen != 0) {
2266 Node = CreateResourceNode (
2267 PciDev,
2268 Ptr->AddrLen,
2269 Ptr->AddrRangeMax,
2270 DummyBarIndex,
2271 PciBarTypePMem64,
2272 PciResUsagePadding
2274 InsertResourceNode (
2275 PMem64Node,
2276 Node
2280 Ptr++;
2281 continue;
2285 // Non-prefechable
2287 if (Ptr->SpecificFlag == 0) {
2288 if (Ptr->AddrLen != 0) {
2289 Node = CreateResourceNode (
2290 PciDev,
2291 Ptr->AddrLen,
2292 Ptr->AddrRangeMax,
2293 DummyBarIndex,
2294 PciBarTypeMem64,
2295 PciResUsagePadding
2297 InsertResourceNode (
2298 Mem64Node,
2299 Node
2303 Ptr++;
2304 continue;
2309 Ptr++;
2314 Get padding resource for PCI-PCI bridge.
2316 @param PciIoDevice PCI-PCI bridge device instance.
2318 @note Feature flag PcdPciBusHotplugDeviceSupport determines
2319 whether need to pad resource for them.
2321 VOID
2322 GetResourcePaddingPpb (
2323 IN PCI_IO_DEVICE *PciIoDevice
2326 if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
2327 if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
2328 GetResourcePaddingForHpb (PciIoDevice);