2 Internal library implementation for PCI Bus module.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 GLOBAL_REMOVE_IF_UNREFERENCED
19 CHAR16
*mBarTypeStr
[] = {
33 Retrieve the max bus number that is assigned to the Root Bridge hierarchy.
34 It can support the case that there are multiple bus ranges.
36 @param Bridge Bridge device instance.
38 @retval The max bus number that is assigned to this Root Bridge hierarchy.
43 IN PCI_IO_DEVICE
*Bridge
46 PCI_IO_DEVICE
*RootBridge
;
47 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BusNumberRanges
;
48 UINT64 MaxNumberInRange
;
51 // Get PCI Root Bridge device
54 while (RootBridge
->Parent
!= NULL
) {
55 RootBridge
= RootBridge
->Parent
;
59 // Iterate the bus number ranges to get max PCI bus number
61 BusNumberRanges
= RootBridge
->BusNumberRanges
;
62 while (BusNumberRanges
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
63 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
66 return (UINT16
) MaxNumberInRange
;
70 Retrieve the PCI Card device BAR information via PciIo interface.
72 @param PciIoDevice PCI Card device instance.
77 IN PCI_IO_DEVICE
*PciIoDevice
82 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
87 // Read PciBar information from the bar register
89 if (!gFullEnumeration
) {
91 PciIoDevice
->PciIo
.Pci
.Read (
92 &(PciIoDevice
->PciIo
),
94 PCI_CARD_MEMORY_BASE_0
,
99 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
100 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
101 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
104 PciIoDevice
->PciIo
.Pci
.Read (
105 &(PciIoDevice
->PciIo
),
107 PCI_CARD_MEMORY_BASE_1
,
111 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
112 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
113 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
116 PciIoDevice
->PciIo
.Pci
.Read (
117 &(PciIoDevice
->PciIo
),
119 PCI_CARD_IO_BASE_0_LOWER
,
123 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
124 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
125 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
128 PciIoDevice
->PciIo
.Pci
.Read (
129 &(PciIoDevice
->PciIo
),
131 PCI_CARD_IO_BASE_1_LOWER
,
135 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
136 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
137 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
141 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
142 GetResourcePaddingForHpb (PciIoDevice
);
147 Remove rejected pci device from specific root bridge
150 @param RootBridgeHandle Specific parent root bridge handle.
151 @param Bridge Bridge device instance.
155 RemoveRejectedPciDevices (
156 IN EFI_HANDLE RootBridgeHandle
,
157 IN PCI_IO_DEVICE
*Bridge
161 LIST_ENTRY
*CurrentLink
;
162 LIST_ENTRY
*LastLink
;
164 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
168 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
170 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
172 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
174 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
176 // Remove rejected devices recusively
178 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
181 // Skip rejection for all PPBs, while detect rejection for others
183 if (IsPciDeviceRejected (Temp
)) {
186 // For P2C, remove all devices on it
188 if (!IsListEmpty (&Temp
->ChildList
)) {
189 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
193 // Finally remove itself
195 LastLink
= CurrentLink
->BackLink
;
196 RemoveEntryList (CurrentLink
);
197 FreePciDevice (Temp
);
199 CurrentLink
= LastLink
;
203 CurrentLink
= CurrentLink
->ForwardLink
;
208 Dump the resourc map of the bridge device.
210 @param[in] BridgeResource Resource descriptor of the bridge device.
214 IN PCI_RESOURCE_NODE
*BridgeResource
218 PCI_RESOURCE_NODE
*Resource
;
221 if ((BridgeResource
!= NULL
) && (BridgeResource
->Length
!= 0)) {
223 EFI_D_INFO
, "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",
224 mBarTypeStr
[MIN (BridgeResource
->ResType
, PciBarTypeMaxType
)],
225 BridgeResource
->PciDev
->PciBar
[BridgeResource
->Bar
].BaseAddress
,
226 BridgeResource
->Length
, BridgeResource
->Alignment
228 for ( Link
= GetFirstNode (&BridgeResource
->ChildList
)
229 ; !IsNull (&BridgeResource
->ChildList
, Link
)
230 ; Link
= GetNextNode (&BridgeResource
->ChildList
, Link
)
232 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
233 if (Resource
->ResourceUsage
== PciResUsageTypical
) {
234 Bar
= Resource
->Virtual
? Resource
->PciDev
->VfPciBar
: Resource
->PciDev
->PciBar
;
236 EFI_D_INFO
, " Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s [%02x|%02x|%02x:",
237 Bar
[Resource
->Bar
].BaseAddress
, Resource
->Length
, Resource
->Alignment
,
238 IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"PPB" :
239 IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"P2C" :
241 Resource
->PciDev
->BusNumber
, Resource
->PciDev
->DeviceNumber
,
242 Resource
->PciDev
->FunctionNumber
245 if ((!IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && !IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
)) ||
246 (IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< PPB_IO_RANGE
)) ||
247 (IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< P2C_MEM_1
))
250 // The resource requirement comes from the device itself.
252 DEBUG ((EFI_D_INFO
, "%02x]", Bar
[Resource
->Bar
].Offset
));
255 // The resource requirement comes from the subordinate devices.
257 DEBUG ((EFI_D_INFO
, "**]"));
260 DEBUG ((EFI_D_INFO
, " Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource
->Length
, Resource
->Alignment
));
262 if (BridgeResource
->ResType
!= Resource
->ResType
) {
263 DEBUG ((EFI_D_INFO
, "; Type = %s", mBarTypeStr
[MIN (Resource
->ResType
, PciBarTypeMaxType
)]));
265 DEBUG ((EFI_D_INFO
, "\n"));
271 Find the corresponding resource node for the Device in child list of BridgeResource.
273 @param[in] Device Pointer to PCI_IO_DEVICE.
274 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.
275 @param[out] DeviceResources Pointer to a buffer to receive resources for the Device.
277 @return Count of the resource descriptors returned.
281 IN PCI_IO_DEVICE
*Device
,
282 IN PCI_RESOURCE_NODE
*BridgeResource
,
283 OUT PCI_RESOURCE_NODE
**DeviceResources OPTIONAL
287 PCI_RESOURCE_NODE
*Resource
;
291 for ( Link
= BridgeResource
->ChildList
.ForwardLink
292 ; Link
!= &BridgeResource
->ChildList
293 ; Link
= Link
->ForwardLink
295 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
296 if (Resource
->PciDev
== Device
) {
297 if (DeviceResources
!= NULL
) {
298 DeviceResources
[Count
] = Resource
;
308 Dump the resource map of all the devices under Bridge.
310 @param[in] Bridge Bridge device instance.
311 @param[in] Resources Resource descriptors for the bridge device.
312 @param[in] ResourceCount Count of resource descriptors.
316 IN PCI_IO_DEVICE
*Bridge
,
317 IN PCI_RESOURCE_NODE
**Resources
,
318 IN UINTN ResourceCount
323 PCI_IO_DEVICE
*Device
;
326 PCI_RESOURCE_NODE
**ChildResources
;
327 UINTN ChildResourceCount
;
329 DEBUG ((EFI_D_INFO
, "PciBus: Resource Map for "));
331 Status
= gBS
->OpenProtocol (
333 &gEfiPciRootBridgeIoProtocolGuid
,
337 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
339 if (EFI_ERROR (Status
)) {
341 EFI_D_INFO
, "Bridge [%02x|%02x|%02x]\n",
342 Bridge
->BusNumber
, Bridge
->DeviceNumber
, Bridge
->FunctionNumber
345 Str
= ConvertDevicePathToText (
346 DevicePathFromHandle (Bridge
->Handle
),
350 DEBUG ((EFI_D_INFO
, "Root Bridge %s\n", Str
!= NULL
? Str
: L
""));
356 for (Index
= 0; Index
< ResourceCount
; Index
++) {
357 DumpBridgeResource (Resources
[Index
]);
359 DEBUG ((EFI_D_INFO
, "\n"));
361 for ( Link
= Bridge
->ChildList
.ForwardLink
362 ; Link
!= &Bridge
->ChildList
363 ; Link
= Link
->ForwardLink
365 Device
= PCI_IO_DEVICE_FROM_LINK (Link
);
366 if (IS_PCI_BRIDGE (&Device
->Pci
)) {
368 ChildResourceCount
= 0;
369 for (Index
= 0; Index
< ResourceCount
; Index
++) {
370 ChildResourceCount
+= FindResourceNode (Device
, Resources
[Index
], NULL
);
372 ChildResources
= AllocatePool (sizeof (PCI_RESOURCE_NODE
*) * ChildResourceCount
);
373 ASSERT (ChildResources
!= NULL
);
374 ChildResourceCount
= 0;
375 for (Index
= 0; Index
< ResourceCount
; Index
++) {
376 ChildResourceCount
+= FindResourceNode (Device
, Resources
[Index
], &ChildResources
[ChildResourceCount
]);
379 DumpResourceMap (Device
, ChildResources
, ChildResourceCount
);
380 FreePool (ChildResources
);
386 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
388 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
390 @retval EFI_SUCCESS Successfully finished resource allocation.
391 @retval EFI_NOT_FOUND Cannot get root bridge instance.
392 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.
393 @retval other Some error occurred when allocating resources for the PCI Host Bridge.
395 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
399 PciHostBridgeResourceAllocator (
400 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
403 PCI_IO_DEVICE
*RootBridgeDev
;
404 EFI_HANDLE RootBridgeHandle
;
413 UINT64 Mem32ResStatus
;
414 UINT64 PMem32ResStatus
;
415 UINT64 Mem64ResStatus
;
416 UINT64 PMem64ResStatus
;
417 UINT64 MaxOptionRomSize
;
418 PCI_RESOURCE_NODE
*IoBridge
;
419 PCI_RESOURCE_NODE
*Mem32Bridge
;
420 PCI_RESOURCE_NODE
*PMem32Bridge
;
421 PCI_RESOURCE_NODE
*Mem64Bridge
;
422 PCI_RESOURCE_NODE
*PMem64Bridge
;
423 PCI_RESOURCE_NODE IoPool
;
424 PCI_RESOURCE_NODE Mem32Pool
;
425 PCI_RESOURCE_NODE PMem32Pool
;
426 PCI_RESOURCE_NODE Mem64Pool
;
427 PCI_RESOURCE_NODE PMem64Pool
;
429 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
430 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
438 // It may try several times if the resource allocation fails
442 // Initialize resource pool
444 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
445 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
446 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
447 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
448 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
450 RootBridgeDev
= NULL
;
451 RootBridgeHandle
= 0;
453 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
455 // Get Root Bridge Device by handle
457 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
459 if (RootBridgeDev
== NULL
) {
460 return EFI_NOT_FOUND
;
464 // Create the entire system resource map from the information collected by
465 // enumerator. Several resource tree was created
469 // If non-standard PCI Bridge I/O window alignment is supported,
470 // set I/O aligment to minimum possible alignment for root bridge.
472 IoBridge
= CreateResourceNode (
475 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
) ? 0x1FF: 0xFFF,
481 Mem32Bridge
= CreateResourceNode (
490 PMem32Bridge
= CreateResourceNode (
499 Mem64Bridge
= CreateResourceNode (
508 PMem64Bridge
= CreateResourceNode (
518 // Create resourcemap by going through all the devices subject to this root bridge
530 // Get the max ROM size that the root bridge can process
532 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
535 // Skip to enlarge the resource request during realloction
539 // Get Max Option Rom size for current root bridge
541 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
544 // Enlarger the mem32 resource to accomdate the option rom
545 // if the mem32 resource is not enough to hold the rom
547 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
549 Mem32Bridge
->Length
= MaxOptionRomSize
;
550 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
553 // Alignment should be adjusted as well
555 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
556 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
562 // Based on the all the resource tree, construct ACPI resource node to
563 // submit the resource aperture to pci host bridge protocol
565 Status
= ConstructAcpiResourceRequestor (
576 // Insert these resource nodes into the database
578 InsertResourceNode (&IoPool
, IoBridge
);
579 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
580 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
581 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
582 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
584 if (Status
== EFI_SUCCESS
) {
586 // Submit the resource requirement
588 Status
= PciResAlloc
->SubmitResources (
590 RootBridgeDev
->Handle
,
594 // If SubmitResources returns error, PciBus isn't able to start.
595 // It's a fatal error so assertion is added.
597 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->SubmitResources() - %r\n", Status
));
598 ASSERT_EFI_ERROR (Status
);
602 // Free acpi resource node
604 if (AcpiConfig
!= NULL
) {
605 FreePool (AcpiConfig
);
608 if (EFI_ERROR (Status
)) {
610 // Destroy all the resource tree
612 DestroyResourceTree (&IoPool
);
613 DestroyResourceTree (&Mem32Pool
);
614 DestroyResourceTree (&PMem32Pool
);
615 DestroyResourceTree (&Mem64Pool
);
616 DestroyResourceTree (&PMem64Pool
);
621 // End while, at least one Root Bridge should be found.
623 ASSERT (RootBridgeDev
!= NULL
);
626 // Notify platform to start to program the resource
628 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
629 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status
));
630 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
632 // If Hot Plug is not supported
634 if (EFI_ERROR (Status
)) {
636 // Allocation failed, then return
638 return EFI_OUT_OF_RESOURCES
;
641 // Allocation succeed.
642 // Get host bridge handle for status report, and then skip the main while
644 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
650 // If Hot Plug is supported
652 if (!EFI_ERROR (Status
)) {
654 // Allocation succeed, then continue the following
660 // If the resource allocation is unsuccessful, free resources on bridge
663 RootBridgeDev
= NULL
;
664 RootBridgeHandle
= 0;
666 IoResStatus
= EFI_RESOURCE_SATISFIED
;
667 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
668 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
669 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
670 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
672 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
674 // Get RootBridg Device by handle
676 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
677 if (RootBridgeDev
== NULL
) {
678 return EFI_NOT_FOUND
;
682 // Get host bridge handle for status report
684 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
687 // Get acpi resource node for all the resource types
691 Status
= PciResAlloc
->GetProposedResources (
693 RootBridgeDev
->Handle
,
697 if (EFI_ERROR (Status
)) {
701 if (AcpiConfig
!= NULL
) {
703 // Adjust resource allocation policy for each RB
705 GetResourceAllocationStatus (
713 FreePool (AcpiConfig
);
721 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
724 // It is very difficult to follow the spec here
725 // Device path , Bar index can not be get here
727 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
729 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
731 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
732 (VOID
*) &AllocFailExtendedData
,
733 sizeof (AllocFailExtendedData
)
736 Status
= PciHostBridgeAdjustAllocation (
750 // Destroy all the resource tree
752 DestroyResourceTree (&IoPool
);
753 DestroyResourceTree (&Mem32Pool
);
754 DestroyResourceTree (&PMem32Pool
);
755 DestroyResourceTree (&Mem64Pool
);
756 DestroyResourceTree (&PMem64Pool
);
758 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
760 if (EFI_ERROR (Status
)) {
772 // Raise the EFI_IOB_PCI_RES_ALLOC status code
774 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
776 EFI_IO_BUS_PCI
| EFI_IOB_PCI_RES_ALLOC
,
777 (VOID
*) &HandleExtendedData
,
778 sizeof (HandleExtendedData
)
782 // Notify pci bus driver starts to program the resource
784 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
786 if (EFI_ERROR (Status
)) {
790 RootBridgeDev
= NULL
;
792 RootBridgeHandle
= 0;
794 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
796 // Get RootBridg Device by handle
798 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
800 if (RootBridgeDev
== NULL
) {
801 return EFI_NOT_FOUND
;
805 // Get acpi resource node for all the resource types
808 Status
= PciResAlloc
->GetProposedResources (
810 RootBridgeDev
->Handle
,
814 if (EFI_ERROR (Status
)) {
819 // Get the resource base by interpreting acpi resource node
832 // Process option rom for this root bridge
834 ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
837 // Create the entire system resource map from the information collected by
838 // enumerator. Several resource tree was created
840 FindResourceNode (RootBridgeDev
, &IoPool
, &IoBridge
);
841 FindResourceNode (RootBridgeDev
, &Mem32Pool
, &Mem32Bridge
);
842 FindResourceNode (RootBridgeDev
, &PMem32Pool
, &PMem32Bridge
);
843 FindResourceNode (RootBridgeDev
, &Mem64Pool
, &Mem64Bridge
);
844 FindResourceNode (RootBridgeDev
, &PMem64Pool
, &PMem64Bridge
);
846 ASSERT (IoBridge
!= NULL
);
847 ASSERT (Mem32Bridge
!= NULL
);
848 ASSERT (PMem32Bridge
!= NULL
);
849 ASSERT (Mem64Bridge
!= NULL
);
850 ASSERT (PMem64Bridge
!= NULL
);
853 // Program IO resources
861 // Program Mem32 resources
869 // Program PMem32 resources
877 // Program Mem64 resources
885 // Program PMem64 resources
892 IoBridge
->PciDev
->PciBar
[IoBridge
->Bar
].BaseAddress
= IoBase
;
893 Mem32Bridge
->PciDev
->PciBar
[Mem32Bridge
->Bar
].BaseAddress
= Mem32Base
;
894 PMem32Bridge
->PciDev
->PciBar
[PMem32Bridge
->Bar
].BaseAddress
= PMem32Base
;
895 Mem64Bridge
->PciDev
->PciBar
[Mem64Bridge
->Bar
].BaseAddress
= Mem64Base
;
896 PMem64Bridge
->PciDev
->PciBar
[PMem64Bridge
->Bar
].BaseAddress
= PMem64Base
;
899 // Dump the resource map for current root bridge
902 PCI_RESOURCE_NODE
*Resources
[5];
903 Resources
[0] = IoBridge
;
904 Resources
[1] = Mem32Bridge
;
905 Resources
[2] = PMem32Bridge
;
906 Resources
[3] = Mem64Bridge
;
907 Resources
[4] = PMem64Bridge
;
908 DumpResourceMap (RootBridgeDev
, Resources
, ARRAY_SIZE (Resources
));
911 FreePool (AcpiConfig
);
915 // Destroy all the resource tree
917 DestroyResourceTree (&IoPool
);
918 DestroyResourceTree (&Mem32Pool
);
919 DestroyResourceTree (&PMem32Pool
);
920 DestroyResourceTree (&Mem64Pool
);
921 DestroyResourceTree (&PMem64Pool
);
924 // Notify the resource allocation phase is to end
926 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
932 Allocate NumberOfBuses buses and return the next available PCI bus number.
934 @param Bridge Bridge device instance.
935 @param StartBusNumber Current available PCI bus number.
936 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.
937 @param NextBusNumber Next available PCI bus number.
939 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number
940 is returned in NextBusNumber.
941 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.
945 PciAllocateBusNumber (
946 IN PCI_IO_DEVICE
*Bridge
,
947 IN UINT8 StartBusNumber
,
948 IN UINT8 NumberOfBuses
,
949 OUT UINT8
*NextBusNumber
952 PCI_IO_DEVICE
*RootBridge
;
953 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BusNumberRanges
;
955 UINT64 MaxNumberInRange
;
958 // Get PCI Root Bridge device
961 while (RootBridge
->Parent
!= NULL
) {
962 RootBridge
= RootBridge
->Parent
;
966 // Get next available PCI bus number
968 BusNumberRanges
= RootBridge
->BusNumberRanges
;
969 while (BusNumberRanges
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
970 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
971 if (StartBusNumber
>= BusNumberRanges
->AddrRangeMin
&& StartBusNumber
<= MaxNumberInRange
) {
972 NextNumber
= (UINT8
)(StartBusNumber
+ NumberOfBuses
);
973 while (NextNumber
> MaxNumberInRange
) {
975 if (BusNumberRanges
->Desc
== ACPI_END_TAG_DESCRIPTOR
) {
976 return EFI_OUT_OF_RESOURCES
;
978 NextNumber
= (UINT8
)(NextNumber
+ (BusNumberRanges
->AddrRangeMin
- (MaxNumberInRange
+ 1)));
979 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
981 *NextBusNumber
= NextNumber
;
986 return EFI_OUT_OF_RESOURCES
;
990 Scan pci bus and assign bus number to the given PCI bus system.
992 @param Bridge Bridge device instance.
993 @param StartBusNumber start point.
994 @param SubBusNumber Point to sub bus number.
995 @param PaddedBusRange Customized bus number.
997 @retval EFI_SUCCESS Successfully scanned and assigned bus number.
998 @retval other Some error occurred when scanning pci bus.
1000 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1005 IN PCI_IO_DEVICE
*Bridge
,
1006 IN UINT8 StartBusNumber
,
1007 OUT UINT8
*SubBusNumber
,
1008 OUT UINT8
*PaddedBusRange
1020 PCI_IO_DEVICE
*PciDevice
;
1022 EFI_HPC_STATE State
;
1024 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
1025 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1026 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*NextDescriptors
;
1028 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1030 UINT32 TempReservedBusNum
;
1032 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1036 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
1042 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1043 TempReservedBusNum
= 0;
1044 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1047 // Check to see whether a pci device is present
1049 Status
= PciDevicePresent (
1057 if (EFI_ERROR (Status
) && Func
== 0) {
1059 // go to next device if there is no Function 0
1064 if (EFI_ERROR (Status
)) {
1069 // Get the PCI device information
1071 Status
= PciSearchDevice (
1080 ASSERT (!EFI_ERROR (Status
));
1082 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1084 if (!IS_PCI_BRIDGE (&Pci
)) {
1086 // PCI bridges will be called later
1087 // Here just need for PCI device or PCI to cardbus controller
1088 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1090 PreprocessController (
1092 PciDevice
->BusNumber
,
1093 PciDevice
->DeviceNumber
,
1094 PciDevice
->FunctionNumber
,
1095 EfiPciBeforeChildBusEnumeration
1099 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1101 // For Pci Hotplug controller devcie only
1103 if (gPciHotPlugInit
!= NULL
) {
1105 // Check if it is a Hotplug PCI controller
1107 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1108 gPciRootHpcData
[HpIndex
].Found
= TRUE
;
1110 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1112 Status
= CreateEventForHpc (HpIndex
, &Event
);
1114 ASSERT (!EFI_ERROR (Status
));
1116 Status
= gPciHotPlugInit
->InitializeRootHpc (
1118 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1124 PreprocessController (
1126 PciDevice
->BusNumber
,
1127 PciDevice
->DeviceNumber
,
1128 PciDevice
->FunctionNumber
,
1129 EfiPciBeforeChildBusEnumeration
1136 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1140 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1142 // If Hot Plug is not supported,
1143 // get the bridge information
1145 Status
= PciSearchDevice (
1154 if (EFI_ERROR (Status
)) {
1159 // If Hot Plug is supported,
1160 // Get the bridge information
1163 if (gPciHotPlugInit
!= NULL
) {
1165 if (IsPciHotPlugBus (PciDevice
)) {
1168 // If it is initialized, get the padded bus range
1170 Status
= gPciHotPlugInit
->GetResourcePadding (
1172 PciDevice
->DevicePath
,
1175 (VOID
**) &Descriptors
,
1179 if (EFI_ERROR (Status
)) {
1184 NextDescriptors
= Descriptors
;
1185 Status
= PciGetBusRange (
1192 FreePool (Descriptors
);
1194 if (!EFI_ERROR (Status
)) {
1196 } else if (Status
!= EFI_NOT_FOUND
) {
1198 // EFI_NOT_FOUND is not a real error. It indicates no bus number padding requested.
1206 Status
= PciAllocateBusNumber (Bridge
, *SubBusNumber
, 1, SubBusNumber
);
1207 if (EFI_ERROR (Status
)) {
1210 SecondBus
= *SubBusNumber
;
1212 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1213 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET
);
1215 Status
= PciRootBridgeIo
->Pci
.Write (
1225 // If it is PPB, resursively search down this bridge
1227 if (IS_PCI_BRIDGE (&Pci
)) {
1230 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1231 // PCI configuration transaction to go through any PPB
1233 Register
= PciGetMaxBusNumber (Bridge
);
1234 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1235 Status
= PciRootBridgeIo
->Pci
.Write (
1244 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1246 PreprocessController (
1248 PciDevice
->BusNumber
,
1249 PciDevice
->DeviceNumber
,
1250 PciDevice
->FunctionNumber
,
1251 EfiPciBeforeChildBusEnumeration
1254 Status
= PciScanBus (
1260 if (EFI_ERROR (Status
)) {
1265 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
) && BusPadding
) {
1267 // Ensure the device is enabled and initialized
1269 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1270 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
1271 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
1272 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) + *PaddedBusRange
);
1275 // Reserve the larger one between the actual occupied bus number and padded bus number
1277 Status
= PciAllocateBusNumber (PciDevice
, SecondBus
, (UINT8
) (BusRange
), &PaddedSubBus
);
1278 if (EFI_ERROR (Status
)) {
1281 *SubBusNumber
= MAX (PaddedSubBus
, *SubBusNumber
);
1286 // Set the current maximum bus number under the PPB
1288 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1290 Status
= PciRootBridgeIo
->Pci
.Write (
1299 // It is device. Check PCI IOV for Bus reservation
1300 // Go through each function, just reserve the MAX ReservedBusNum for one device
1302 if (PcdGetBool (PcdSrIovSupport
) && PciDevice
->SrIovCapabilityOffset
!= 0) {
1303 if (TempReservedBusNum
< PciDevice
->ReservedBusNum
) {
1305 Status
= PciAllocateBusNumber (PciDevice
, *SubBusNumber
, (UINT8
) (PciDevice
->ReservedBusNum
- TempReservedBusNum
), SubBusNumber
);
1306 if (EFI_ERROR (Status
)) {
1309 TempReservedBusNum
= PciDevice
->ReservedBusNum
;
1312 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber
));
1314 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber
));
1320 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1323 // Skip sub functions, this is not a multi function device
1326 Func
= PCI_MAX_FUNC
;
1335 Process Option Rom on the specified root bridge.
1337 @param Bridge Pci root bridge device instance.
1339 @retval EFI_SUCCESS Success process.
1340 @retval other Some error occurred when processing Option Rom on the root bridge.
1344 PciRootBridgeP2CProcess (
1345 IN PCI_IO_DEVICE
*Bridge
1348 LIST_ENTRY
*CurrentLink
;
1349 PCI_IO_DEVICE
*Temp
;
1350 EFI_HPC_STATE State
;
1354 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1356 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1358 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1360 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1362 if (gPciHotPlugInit
!= NULL
&& Temp
->Allocated
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1365 // Raise the EFI_IOB_PCI_HPC_INIT status code
1367 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1369 EFI_IO_BUS_PCI
| EFI_IOB_PCI_HPC_INIT
,
1373 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1374 Status
= gPciHotPlugInit
->InitializeRootHpc (
1382 if (!EFI_ERROR (Status
)) {
1383 Status
= PciBridgeEnumerator (Temp
);
1385 if (EFI_ERROR (Status
)) {
1390 CurrentLink
= CurrentLink
->ForwardLink
;
1396 if (!IsListEmpty (&Temp
->ChildList
)) {
1397 Status
= PciRootBridgeP2CProcess (Temp
);
1400 CurrentLink
= CurrentLink
->ForwardLink
;
1407 Process Option Rom on the specified host bridge.
1409 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1411 @retval EFI_SUCCESS Success process.
1412 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1413 @retval other Some error occurred when processing Option Rom on the host bridge.
1417 PciHostBridgeP2CProcess (
1418 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1421 EFI_HANDLE RootBridgeHandle
;
1422 PCI_IO_DEVICE
*RootBridgeDev
;
1425 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1429 RootBridgeHandle
= NULL
;
1431 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1434 // Get RootBridg Device by handle
1436 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1438 if (RootBridgeDev
== NULL
) {
1439 return EFI_NOT_FOUND
;
1442 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1443 if (EFI_ERROR (Status
)) {
1453 This function is used to enumerate the entire host bridge
1454 in a given platform.
1456 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1458 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1459 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1460 @retval other Some error occurred when enumerating the host bridge.
1464 PciHostBridgeEnumerator (
1465 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1468 EFI_HANDLE RootBridgeHandle
;
1469 PCI_IO_DEVICE
*RootBridgeDev
;
1471 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1473 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1474 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1475 UINT8 StartBusNumber
;
1476 LIST_ENTRY RootBridgeList
;
1479 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1480 InitializeHotPlugSupport ();
1483 InitializeListHead (&RootBridgeList
);
1486 // Notify the bus allocation phase is about to start
1488 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1490 if (EFI_ERROR (Status
)) {
1494 DEBUG((EFI_D_INFO
, "PCI Bus First Scanning\n"));
1495 RootBridgeHandle
= NULL
;
1496 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1499 // if a root bridge instance is found, create root bridge device for it
1502 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1504 if (RootBridgeDev
== NULL
) {
1505 return EFI_OUT_OF_RESOURCES
;
1509 // Enumerate all the buses under this root bridge
1511 Status
= PciRootBridgeEnumerator (
1516 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1517 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1519 DestroyRootBridge (RootBridgeDev
);
1521 if (EFI_ERROR (Status
)) {
1527 // Notify the bus allocation phase is finished for the first time
1529 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1531 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1533 // Reset all assigned PCI bus number in all PPB
1535 RootBridgeHandle
= NULL
;
1536 Link
= GetFirstNode (&RootBridgeList
);
1537 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1538 (!IsNull (&RootBridgeList
, Link
))) {
1539 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1541 // Get the Bus information
1543 Status
= PciResAlloc
->StartBusEnumeration (
1546 (VOID
**) &Configuration
1548 if (EFI_ERROR (Status
)) {
1553 // Get the bus number to start with
1555 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1557 ResetAllPpbBusNumber (
1562 FreePool (Configuration
);
1563 Link
= RemoveEntryList (Link
);
1564 DestroyRootBridge (RootBridgeDev
);
1568 // Wait for all HPC initialized
1570 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1572 if (EFI_ERROR (Status
)) {
1573 DEBUG ((EFI_D_ERROR
, "Some root HPC failed to initialize\n"));
1578 // Notify the bus allocation phase is about to start for the 2nd time
1580 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1582 if (EFI_ERROR (Status
)) {
1586 DEBUG((EFI_D_INFO
, "PCI Bus Second Scanning\n"));
1587 RootBridgeHandle
= NULL
;
1588 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1591 // if a root bridge instance is found, create root bridge device for it
1593 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1595 if (RootBridgeDev
== NULL
) {
1596 return EFI_OUT_OF_RESOURCES
;
1600 // Enumerate all the buses under this root bridge
1602 Status
= PciRootBridgeEnumerator (
1607 DestroyRootBridge (RootBridgeDev
);
1608 if (EFI_ERROR (Status
)) {
1614 // Notify the bus allocation phase is to end for the 2nd time
1616 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1620 // Notify the resource allocation phase is to start
1622 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1624 if (EFI_ERROR (Status
)) {
1628 RootBridgeHandle
= NULL
;
1629 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1632 // if a root bridge instance is found, create root bridge device for it
1634 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1636 if (RootBridgeDev
== NULL
) {
1637 return EFI_OUT_OF_RESOURCES
;
1640 Status
= StartManagingRootBridge (RootBridgeDev
);
1642 if (EFI_ERROR (Status
)) {
1646 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1647 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1649 if (EFI_ERROR (Status
)) {
1653 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1655 if (EFI_ERROR (Status
)) {
1660 // Determine root bridge attribute by calling interface of Pcihostbridge
1663 DetermineRootBridgeAttributes (
1669 // Collect all the resource information under this root bridge
1670 // A database that records all the information about pci device subject to this
1671 // root bridge will then be created
1673 Status
= PciPciDeviceInfoCollector (
1678 if (EFI_ERROR (Status
)) {
1682 InsertRootBridge (RootBridgeDev
);
1685 // Record the hostbridge handle
1687 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);