2 Internal library implementation for PCI Bus module.
4 Copyright (c) 2006 - 2016, 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 PCI Card device BAR information via PciIo interface.
35 @param PciIoDevice PCI Card device instance.
40 IN PCI_IO_DEVICE
*PciIoDevice
45 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
50 // Read PciBar information from the bar register
52 if (!gFullEnumeration
) {
54 PciIoDevice
->PciIo
.Pci
.Read (
55 &(PciIoDevice
->PciIo
),
57 PCI_CARD_MEMORY_BASE_0
,
62 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
63 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
64 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
67 PciIoDevice
->PciIo
.Pci
.Read (
68 &(PciIoDevice
->PciIo
),
70 PCI_CARD_MEMORY_BASE_1
,
74 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
75 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
76 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
79 PciIoDevice
->PciIo
.Pci
.Read (
80 &(PciIoDevice
->PciIo
),
82 PCI_CARD_IO_BASE_0_LOWER
,
86 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
87 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
88 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
91 PciIoDevice
->PciIo
.Pci
.Read (
92 &(PciIoDevice
->PciIo
),
94 PCI_CARD_IO_BASE_1_LOWER
,
98 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
99 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
100 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
104 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
105 GetResourcePaddingForHpb (PciIoDevice
);
110 Remove rejected pci device from specific root bridge
113 @param RootBridgeHandle Specific parent root bridge handle.
114 @param Bridge Bridge device instance.
118 RemoveRejectedPciDevices (
119 IN EFI_HANDLE RootBridgeHandle
,
120 IN PCI_IO_DEVICE
*Bridge
124 LIST_ENTRY
*CurrentLink
;
125 LIST_ENTRY
*LastLink
;
127 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
131 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
133 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
135 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
137 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
139 // Remove rejected devices recusively
141 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
144 // Skip rejection for all PPBs, while detect rejection for others
146 if (IsPciDeviceRejected (Temp
)) {
149 // For P2C, remove all devices on it
151 if (!IsListEmpty (&Temp
->ChildList
)) {
152 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
156 // Finally remove itself
158 LastLink
= CurrentLink
->BackLink
;
159 RemoveEntryList (CurrentLink
);
160 FreePciDevice (Temp
);
162 CurrentLink
= LastLink
;
166 CurrentLink
= CurrentLink
->ForwardLink
;
171 Dump the resourc map of the bridge device.
173 @param[in] BridgeResource Resource descriptor of the bridge device.
177 IN PCI_RESOURCE_NODE
*BridgeResource
181 PCI_RESOURCE_NODE
*Resource
;
184 if ((BridgeResource
!= NULL
) && (BridgeResource
->Length
!= 0)) {
186 EFI_D_INFO
, "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",
187 mBarTypeStr
[MIN (BridgeResource
->ResType
, PciBarTypeMaxType
)],
188 BridgeResource
->PciDev
->PciBar
[BridgeResource
->Bar
].BaseAddress
,
189 BridgeResource
->Length
, BridgeResource
->Alignment
191 for ( Link
= GetFirstNode (&BridgeResource
->ChildList
)
192 ; !IsNull (&BridgeResource
->ChildList
, Link
)
193 ; Link
= GetNextNode (&BridgeResource
->ChildList
, Link
)
195 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
196 if (Resource
->ResourceUsage
== PciResUsageTypical
) {
197 Bar
= Resource
->Virtual
? Resource
->PciDev
->VfPciBar
: Resource
->PciDev
->PciBar
;
199 EFI_D_INFO
, " Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s [%02x|%02x|%02x:",
200 Bar
[Resource
->Bar
].BaseAddress
, Resource
->Length
, Resource
->Alignment
,
201 IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"PPB" :
202 IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"P2C" :
204 Resource
->PciDev
->BusNumber
, Resource
->PciDev
->DeviceNumber
,
205 Resource
->PciDev
->FunctionNumber
208 if ((!IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && !IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
)) ||
209 (IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< PPB_IO_RANGE
)) ||
210 (IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< P2C_MEM_1
))
213 // The resource requirement comes from the device itself.
215 DEBUG ((EFI_D_INFO
, "%02x]", Bar
[Resource
->Bar
].Offset
));
218 // The resource requirement comes from the subordinate devices.
220 DEBUG ((EFI_D_INFO
, "**]"));
223 DEBUG ((EFI_D_INFO
, " Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource
->Length
, Resource
->Alignment
));
225 if (BridgeResource
->ResType
!= Resource
->ResType
) {
226 DEBUG ((EFI_D_INFO
, "; Type = %s", mBarTypeStr
[MIN (Resource
->ResType
, PciBarTypeMaxType
)]));
228 DEBUG ((EFI_D_INFO
, "\n"));
234 Find the corresponding resource node for the Device in child list of BridgeResource.
236 @param[in] Device Pointer to PCI_IO_DEVICE.
237 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.
238 @param[out] DeviceResources Pointer to a buffer to receive resources for the Device.
240 @return Count of the resource descriptors returned.
244 IN PCI_IO_DEVICE
*Device
,
245 IN PCI_RESOURCE_NODE
*BridgeResource
,
246 OUT PCI_RESOURCE_NODE
**DeviceResources OPTIONAL
250 PCI_RESOURCE_NODE
*Resource
;
254 for ( Link
= BridgeResource
->ChildList
.ForwardLink
255 ; Link
!= &BridgeResource
->ChildList
256 ; Link
= Link
->ForwardLink
258 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
259 if (Resource
->PciDev
== Device
) {
260 if (DeviceResources
!= NULL
) {
261 DeviceResources
[Count
] = Resource
;
271 Dump the resource map of all the devices under Bridge.
273 @param[in] Bridge Bridge device instance.
274 @param[in] Resources Resource descriptors for the bridge device.
275 @param[in] ResourceCount Count of resource descriptors.
279 IN PCI_IO_DEVICE
*Bridge
,
280 IN PCI_RESOURCE_NODE
**Resources
,
281 IN UINTN ResourceCount
286 PCI_IO_DEVICE
*Device
;
289 PCI_RESOURCE_NODE
**ChildResources
;
290 UINTN ChildResourceCount
;
292 DEBUG ((EFI_D_INFO
, "PciBus: Resource Map for "));
294 Status
= gBS
->OpenProtocol (
296 &gEfiPciRootBridgeIoProtocolGuid
,
300 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
302 if (EFI_ERROR (Status
)) {
304 EFI_D_INFO
, "Bridge [%02x|%02x|%02x]\n",
305 Bridge
->BusNumber
, Bridge
->DeviceNumber
, Bridge
->FunctionNumber
308 Str
= ConvertDevicePathToText (
309 DevicePathFromHandle (Bridge
->Handle
),
313 DEBUG ((EFI_D_INFO
, "Root Bridge %s\n", Str
!= NULL
? Str
: L
""));
319 for (Index
= 0; Index
< ResourceCount
; Index
++) {
320 DumpBridgeResource (Resources
[Index
]);
322 DEBUG ((EFI_D_INFO
, "\n"));
324 for ( Link
= Bridge
->ChildList
.ForwardLink
325 ; Link
!= &Bridge
->ChildList
326 ; Link
= Link
->ForwardLink
328 Device
= PCI_IO_DEVICE_FROM_LINK (Link
);
329 if (IS_PCI_BRIDGE (&Device
->Pci
)) {
331 ChildResourceCount
= 0;
332 for (Index
= 0; Index
< ResourceCount
; Index
++) {
333 ChildResourceCount
+= FindResourceNode (Device
, Resources
[Index
], NULL
);
335 ChildResources
= AllocatePool (sizeof (PCI_RESOURCE_NODE
*) * ChildResourceCount
);
336 ASSERT (ChildResources
!= NULL
);
337 ChildResourceCount
= 0;
338 for (Index
= 0; Index
< ResourceCount
; Index
++) {
339 ChildResourceCount
+= FindResourceNode (Device
, Resources
[Index
], &ChildResources
[ChildResourceCount
]);
342 DumpResourceMap (Device
, ChildResources
, ChildResourceCount
);
343 FreePool (ChildResources
);
349 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
351 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
353 @retval EFI_SUCCESS Successfully finished resource allocation.
354 @retval EFI_NOT_FOUND Cannot get root bridge instance.
355 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.
356 @retval other Some error occurred when allocating resources for the PCI Host Bridge.
358 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
362 PciHostBridgeResourceAllocator (
363 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
366 PCI_IO_DEVICE
*RootBridgeDev
;
367 EFI_HANDLE RootBridgeHandle
;
376 UINT64 Mem32ResStatus
;
377 UINT64 PMem32ResStatus
;
378 UINT64 Mem64ResStatus
;
379 UINT64 PMem64ResStatus
;
380 UINT64 MaxOptionRomSize
;
381 PCI_RESOURCE_NODE
*IoBridge
;
382 PCI_RESOURCE_NODE
*Mem32Bridge
;
383 PCI_RESOURCE_NODE
*PMem32Bridge
;
384 PCI_RESOURCE_NODE
*Mem64Bridge
;
385 PCI_RESOURCE_NODE
*PMem64Bridge
;
386 PCI_RESOURCE_NODE IoPool
;
387 PCI_RESOURCE_NODE Mem32Pool
;
388 PCI_RESOURCE_NODE PMem32Pool
;
389 PCI_RESOURCE_NODE Mem64Pool
;
390 PCI_RESOURCE_NODE PMem64Pool
;
392 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
393 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
401 // It may try several times if the resource allocation fails
405 // Initialize resource pool
407 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
408 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
409 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
410 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
411 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
413 RootBridgeDev
= NULL
;
414 RootBridgeHandle
= 0;
416 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
418 // Get Root Bridge Device by handle
420 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
422 if (RootBridgeDev
== NULL
) {
423 return EFI_NOT_FOUND
;
427 // Create the entire system resource map from the information collected by
428 // enumerator. Several resource tree was created
432 // If non-standard PCI Bridge I/O window alignment is supported,
433 // set I/O aligment to minimum possible alignment for root bridge.
435 IoBridge
= CreateResourceNode (
438 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
) ? 0x1FF: 0xFFF,
444 Mem32Bridge
= CreateResourceNode (
453 PMem32Bridge
= CreateResourceNode (
462 Mem64Bridge
= CreateResourceNode (
471 PMem64Bridge
= CreateResourceNode (
481 // Create resourcemap by going through all the devices subject to this root bridge
493 // Get the max ROM size that the root bridge can process
495 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
498 // Skip to enlarge the resource request during realloction
502 // Get Max Option Rom size for current root bridge
504 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
507 // Enlarger the mem32 resource to accomdate the option rom
508 // if the mem32 resource is not enough to hold the rom
510 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
512 Mem32Bridge
->Length
= MaxOptionRomSize
;
513 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
516 // Alignment should be adjusted as well
518 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
519 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
525 // Based on the all the resource tree, construct ACPI resource node to
526 // submit the resource aperture to pci host bridge protocol
528 Status
= ConstructAcpiResourceRequestor (
539 // Insert these resource nodes into the database
541 InsertResourceNode (&IoPool
, IoBridge
);
542 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
543 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
544 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
545 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
547 if (Status
== EFI_SUCCESS
) {
549 // Submit the resource requirement
551 Status
= PciResAlloc
->SubmitResources (
553 RootBridgeDev
->Handle
,
557 // If SubmitResources returns error, PciBus isn't able to start.
558 // It's a fatal error so assertion is added.
560 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->SubmitResources() - %r\n", Status
));
561 ASSERT_EFI_ERROR (Status
);
565 // Free acpi resource node
567 if (AcpiConfig
!= NULL
) {
568 FreePool (AcpiConfig
);
571 if (EFI_ERROR (Status
)) {
573 // Destroy all the resource tree
575 DestroyResourceTree (&IoPool
);
576 DestroyResourceTree (&Mem32Pool
);
577 DestroyResourceTree (&PMem32Pool
);
578 DestroyResourceTree (&Mem64Pool
);
579 DestroyResourceTree (&PMem64Pool
);
584 // End while, at least one Root Bridge should be found.
586 ASSERT (RootBridgeDev
!= NULL
);
589 // Notify platform to start to program the resource
591 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
592 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status
));
593 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
595 // If Hot Plug is not supported
597 if (EFI_ERROR (Status
)) {
599 // Allocation failed, then return
601 return EFI_OUT_OF_RESOURCES
;
604 // Allocation succeed.
605 // Get host bridge handle for status report, and then skip the main while
607 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
613 // If Hot Plug is supported
615 if (!EFI_ERROR (Status
)) {
617 // Allocation succeed, then continue the following
623 // If the resource allocation is unsuccessful, free resources on bridge
626 RootBridgeDev
= NULL
;
627 RootBridgeHandle
= 0;
629 IoResStatus
= EFI_RESOURCE_SATISFIED
;
630 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
631 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
632 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
633 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
635 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
637 // Get RootBridg Device by handle
639 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
640 if (RootBridgeDev
== NULL
) {
641 return EFI_NOT_FOUND
;
645 // Get host bridge handle for status report
647 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
650 // Get acpi resource node for all the resource types
654 Status
= PciResAlloc
->GetProposedResources (
656 RootBridgeDev
->Handle
,
660 if (EFI_ERROR (Status
)) {
664 if (AcpiConfig
!= NULL
) {
666 // Adjust resource allocation policy for each RB
668 GetResourceAllocationStatus (
676 FreePool (AcpiConfig
);
684 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
687 // It is very difficult to follow the spec here
688 // Device path , Bar index can not be get here
690 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
692 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
694 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
695 (VOID
*) &AllocFailExtendedData
,
696 sizeof (AllocFailExtendedData
)
699 Status
= PciHostBridgeAdjustAllocation (
713 // Destroy all the resource tree
715 DestroyResourceTree (&IoPool
);
716 DestroyResourceTree (&Mem32Pool
);
717 DestroyResourceTree (&PMem32Pool
);
718 DestroyResourceTree (&Mem64Pool
);
719 DestroyResourceTree (&PMem64Pool
);
721 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
723 if (EFI_ERROR (Status
)) {
735 // Raise the EFI_IOB_PCI_RES_ALLOC status code
737 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
739 EFI_IO_BUS_PCI
| EFI_IOB_PCI_RES_ALLOC
,
740 (VOID
*) &HandleExtendedData
,
741 sizeof (HandleExtendedData
)
745 // Notify pci bus driver starts to program the resource
747 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
749 if (EFI_ERROR (Status
)) {
753 RootBridgeDev
= NULL
;
755 RootBridgeHandle
= 0;
757 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
759 // Get RootBridg Device by handle
761 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
763 if (RootBridgeDev
== NULL
) {
764 return EFI_NOT_FOUND
;
768 // Get acpi resource node for all the resource types
771 Status
= PciResAlloc
->GetProposedResources (
773 RootBridgeDev
->Handle
,
777 if (EFI_ERROR (Status
)) {
782 // Get the resource base by interpreting acpi resource node
795 // Process option rom for this root bridge
797 ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
800 // Create the entire system resource map from the information collected by
801 // enumerator. Several resource tree was created
803 FindResourceNode (RootBridgeDev
, &IoPool
, &IoBridge
);
804 FindResourceNode (RootBridgeDev
, &Mem32Pool
, &Mem32Bridge
);
805 FindResourceNode (RootBridgeDev
, &PMem32Pool
, &PMem32Bridge
);
806 FindResourceNode (RootBridgeDev
, &Mem64Pool
, &Mem64Bridge
);
807 FindResourceNode (RootBridgeDev
, &PMem64Pool
, &PMem64Bridge
);
809 ASSERT (IoBridge
!= NULL
);
810 ASSERT (Mem32Bridge
!= NULL
);
811 ASSERT (PMem32Bridge
!= NULL
);
812 ASSERT (Mem64Bridge
!= NULL
);
813 ASSERT (PMem64Bridge
!= NULL
);
816 // Program IO resources
824 // Program Mem32 resources
832 // Program PMem32 resources
840 // Program Mem64 resources
848 // Program PMem64 resources
855 IoBridge
->PciDev
->PciBar
[IoBridge
->Bar
].BaseAddress
= IoBase
;
856 Mem32Bridge
->PciDev
->PciBar
[Mem32Bridge
->Bar
].BaseAddress
= Mem32Base
;
857 PMem32Bridge
->PciDev
->PciBar
[PMem32Bridge
->Bar
].BaseAddress
= PMem32Base
;
858 Mem64Bridge
->PciDev
->PciBar
[Mem64Bridge
->Bar
].BaseAddress
= Mem64Base
;
859 PMem64Bridge
->PciDev
->PciBar
[PMem64Bridge
->Bar
].BaseAddress
= PMem64Base
;
862 // Dump the resource map for current root bridge
865 PCI_RESOURCE_NODE
*Resources
[5];
866 Resources
[0] = IoBridge
;
867 Resources
[1] = Mem32Bridge
;
868 Resources
[2] = PMem32Bridge
;
869 Resources
[3] = Mem64Bridge
;
870 Resources
[4] = PMem64Bridge
;
871 DumpResourceMap (RootBridgeDev
, Resources
, ARRAY_SIZE (Resources
));
874 FreePool (AcpiConfig
);
878 // Destroy all the resource tree
880 DestroyResourceTree (&IoPool
);
881 DestroyResourceTree (&Mem32Pool
);
882 DestroyResourceTree (&PMem32Pool
);
883 DestroyResourceTree (&Mem64Pool
);
884 DestroyResourceTree (&PMem64Pool
);
887 // Notify the resource allocation phase is to end
889 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
895 Allocate NumberOfBuses buses and return the next available PCI bus number.
897 @param Bridge Bridge device instance.
898 @param StartBusNumber Current available PCI bus number.
899 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.
900 @param NextBusNumber Next available PCI bus number.
902 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number
903 is returned in NextBusNumber.
904 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.
908 PciAllocateBusNumber (
909 IN PCI_IO_DEVICE
*Bridge
,
910 IN UINT8 StartBusNumber
,
911 IN UINT8 NumberOfBuses
,
912 OUT UINT8
*NextBusNumber
915 PCI_IO_DEVICE
*RootBridge
;
916 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BusNumberRanges
;
918 UINT64 MaxNumberInRange
;
921 // Get PCI Root Bridge device
924 while (RootBridge
->Parent
!= NULL
) {
925 RootBridge
= RootBridge
->Parent
;
929 // Get next available PCI bus number
931 BusNumberRanges
= RootBridge
->BusNumberRanges
;
932 while (BusNumberRanges
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
933 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
934 if (StartBusNumber
>= BusNumberRanges
->AddrRangeMin
&& StartBusNumber
<= MaxNumberInRange
) {
935 NextNumber
= (UINT8
)(StartBusNumber
+ NumberOfBuses
);
936 while (NextNumber
> MaxNumberInRange
) {
938 if (BusNumberRanges
->Desc
== ACPI_END_TAG_DESCRIPTOR
) {
939 return EFI_OUT_OF_RESOURCES
;
941 NextNumber
= (UINT8
)(NextNumber
+ (BusNumberRanges
->AddrRangeMin
- (MaxNumberInRange
+ 1)));
942 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
944 *NextBusNumber
= NextNumber
;
949 return EFI_OUT_OF_RESOURCES
;
953 Scan pci bus and assign bus number to the given PCI bus system.
955 @param Bridge Bridge device instance.
956 @param StartBusNumber start point.
957 @param SubBusNumber Point to sub bus number.
958 @param PaddedBusRange Customized bus number.
960 @retval EFI_SUCCESS Successfully scanned and assigned bus number.
961 @retval other Some error occurred when scanning pci bus.
963 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
968 IN PCI_IO_DEVICE
*Bridge
,
969 IN UINT8 StartBusNumber
,
970 OUT UINT8
*SubBusNumber
,
971 OUT UINT8
*PaddedBusRange
983 PCI_IO_DEVICE
*PciDevice
;
987 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
988 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
990 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
992 UINT32 TempReservedBusNum
;
994 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
998 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
1004 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1005 TempReservedBusNum
= 0;
1006 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1009 // Check to see whether a pci device is present
1011 Status
= PciDevicePresent (
1019 if (EFI_ERROR (Status
) && Func
== 0) {
1021 // go to next device if there is no Function 0
1026 if (EFI_ERROR (Status
)) {
1031 // Get the PCI device information
1033 Status
= PciSearchDevice (
1042 ASSERT (!EFI_ERROR (Status
));
1044 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1046 if (!IS_PCI_BRIDGE (&Pci
)) {
1048 // PCI bridges will be called later
1049 // Here just need for PCI device or PCI to cardbus controller
1050 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1052 PreprocessController (
1054 PciDevice
->BusNumber
,
1055 PciDevice
->DeviceNumber
,
1056 PciDevice
->FunctionNumber
,
1057 EfiPciBeforeChildBusEnumeration
1061 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1063 // For Pci Hotplug controller devcie only
1065 if (gPciHotPlugInit
!= NULL
) {
1067 // Check if it is a Hotplug PCI controller
1069 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1070 gPciRootHpcData
[HpIndex
].Found
= TRUE
;
1072 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1074 Status
= CreateEventForHpc (HpIndex
, &Event
);
1076 ASSERT (!EFI_ERROR (Status
));
1078 Status
= gPciHotPlugInit
->InitializeRootHpc (
1080 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1086 PreprocessController (
1088 PciDevice
->BusNumber
,
1089 PciDevice
->DeviceNumber
,
1090 PciDevice
->FunctionNumber
,
1091 EfiPciBeforeChildBusEnumeration
1098 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1102 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1104 // If Hot Plug is not supported,
1105 // get the bridge information
1107 Status
= PciSearchDevice (
1116 if (EFI_ERROR (Status
)) {
1121 // If Hot Plug is supported,
1122 // Get the bridge information
1125 if (gPciHotPlugInit
!= NULL
) {
1127 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
1130 // If it is initialized, get the padded bus range
1132 Status
= gPciHotPlugInit
->GetResourcePadding (
1134 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
1137 (VOID
**) &Descriptors
,
1141 if (EFI_ERROR (Status
)) {
1146 Status
= PciGetBusRange (
1153 FreePool (Descriptors
);
1155 if (EFI_ERROR (Status
)) {
1164 Status
= PciAllocateBusNumber (Bridge
, *SubBusNumber
, 1, SubBusNumber
);
1165 if (EFI_ERROR (Status
)) {
1168 SecondBus
= *SubBusNumber
;
1170 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1171 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET
);
1173 Status
= PciRootBridgeIo
->Pci
.Write (
1183 // If it is PPB, resursively search down this bridge
1185 if (IS_PCI_BRIDGE (&Pci
)) {
1188 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1189 // PCI configuration transaction to go through any PPB
1192 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1193 Status
= PciRootBridgeIo
->Pci
.Write (
1202 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1204 PreprocessController (
1206 PciDevice
->BusNumber
,
1207 PciDevice
->DeviceNumber
,
1208 PciDevice
->FunctionNumber
,
1209 EfiPciBeforeChildBusEnumeration
1212 Status
= PciScanBus (
1218 if (EFI_ERROR (Status
)) {
1223 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
) && BusPadding
) {
1225 // Ensure the device is enabled and initialized
1227 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1228 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
1229 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
1230 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) + *PaddedBusRange
);
1233 // Reserve the larger one between the actual occupied bus number and padded bus number
1235 Status
= PciAllocateBusNumber (PciDevice
, SecondBus
, (UINT8
) (BusRange
), &PaddedSubBus
);
1236 if (EFI_ERROR (Status
)) {
1239 *SubBusNumber
= MAX (PaddedSubBus
, *SubBusNumber
);
1244 // Set the current maximum bus number under the PPB
1246 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1248 Status
= PciRootBridgeIo
->Pci
.Write (
1257 // It is device. Check PCI IOV for Bus reservation
1258 // Go through each function, just reserve the MAX ReservedBusNum for one device
1260 if (PcdGetBool (PcdSrIovSupport
) && PciDevice
->SrIovCapabilityOffset
!= 0) {
1261 if (TempReservedBusNum
< PciDevice
->ReservedBusNum
) {
1263 Status
= PciAllocateBusNumber (PciDevice
, *SubBusNumber
, (UINT8
) (PciDevice
->ReservedBusNum
- TempReservedBusNum
), SubBusNumber
);
1264 if (EFI_ERROR (Status
)) {
1267 TempReservedBusNum
= PciDevice
->ReservedBusNum
;
1270 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber
));
1272 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber
));
1278 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1281 // Skip sub functions, this is not a multi function device
1284 Func
= PCI_MAX_FUNC
;
1293 Process Option Rom on the specified root bridge.
1295 @param Bridge Pci root bridge device instance.
1297 @retval EFI_SUCCESS Success process.
1298 @retval other Some error occurred when processing Option Rom on the root bridge.
1302 PciRootBridgeP2CProcess (
1303 IN PCI_IO_DEVICE
*Bridge
1306 LIST_ENTRY
*CurrentLink
;
1307 PCI_IO_DEVICE
*Temp
;
1308 EFI_HPC_STATE State
;
1312 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1314 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1316 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1318 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1320 if (gPciHotPlugInit
!= NULL
&& Temp
->Allocated
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1323 // Raise the EFI_IOB_PCI_HPC_INIT status code
1325 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1327 EFI_IO_BUS_PCI
| EFI_IOB_PCI_HPC_INIT
,
1331 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1332 Status
= gPciHotPlugInit
->InitializeRootHpc (
1340 if (!EFI_ERROR (Status
)) {
1341 Status
= PciBridgeEnumerator (Temp
);
1343 if (EFI_ERROR (Status
)) {
1348 CurrentLink
= CurrentLink
->ForwardLink
;
1354 if (!IsListEmpty (&Temp
->ChildList
)) {
1355 Status
= PciRootBridgeP2CProcess (Temp
);
1358 CurrentLink
= CurrentLink
->ForwardLink
;
1365 Process Option Rom on the specified host bridge.
1367 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1369 @retval EFI_SUCCESS Success process.
1370 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1371 @retval other Some error occurred when processing Option Rom on the host bridge.
1375 PciHostBridgeP2CProcess (
1376 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1379 EFI_HANDLE RootBridgeHandle
;
1380 PCI_IO_DEVICE
*RootBridgeDev
;
1383 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1387 RootBridgeHandle
= NULL
;
1389 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1392 // Get RootBridg Device by handle
1394 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1396 if (RootBridgeDev
== NULL
) {
1397 return EFI_NOT_FOUND
;
1400 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1401 if (EFI_ERROR (Status
)) {
1411 This function is used to enumerate the entire host bridge
1412 in a given platform.
1414 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1416 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1417 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1418 @retval other Some error occurred when enumerating the host bridge.
1422 PciHostBridgeEnumerator (
1423 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1426 EFI_HANDLE RootBridgeHandle
;
1427 PCI_IO_DEVICE
*RootBridgeDev
;
1429 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1431 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1432 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1433 UINT8 StartBusNumber
;
1434 LIST_ENTRY RootBridgeList
;
1437 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1438 InitializeHotPlugSupport ();
1441 InitializeListHead (&RootBridgeList
);
1444 // Notify the bus allocation phase is about to start
1446 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1448 if (EFI_ERROR (Status
)) {
1452 DEBUG((EFI_D_INFO
, "PCI Bus First Scanning\n"));
1453 RootBridgeHandle
= NULL
;
1454 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1457 // if a root bridge instance is found, create root bridge device for it
1460 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1462 if (RootBridgeDev
== NULL
) {
1463 return EFI_OUT_OF_RESOURCES
;
1467 // Enumerate all the buses under this root bridge
1469 Status
= PciRootBridgeEnumerator (
1474 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1475 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1477 DestroyRootBridge (RootBridgeDev
);
1479 if (EFI_ERROR (Status
)) {
1485 // Notify the bus allocation phase is finished for the first time
1487 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1489 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1491 // Reset all assigned PCI bus number in all PPB
1493 RootBridgeHandle
= NULL
;
1494 Link
= GetFirstNode (&RootBridgeList
);
1495 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1496 (!IsNull (&RootBridgeList
, Link
))) {
1497 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1499 // Get the Bus information
1501 Status
= PciResAlloc
->StartBusEnumeration (
1504 (VOID
**) &Configuration
1506 if (EFI_ERROR (Status
)) {
1511 // Get the bus number to start with
1513 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1515 ResetAllPpbBusNumber (
1520 FreePool (Configuration
);
1521 Link
= RemoveEntryList (Link
);
1522 DestroyRootBridge (RootBridgeDev
);
1526 // Wait for all HPC initialized
1528 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1530 if (EFI_ERROR (Status
)) {
1531 DEBUG ((EFI_D_ERROR
, "Some root HPC failed to initialize\n"));
1536 // Notify the bus allocation phase is about to start for the 2nd time
1538 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1540 if (EFI_ERROR (Status
)) {
1544 DEBUG((EFI_D_INFO
, "PCI Bus Second Scanning\n"));
1545 RootBridgeHandle
= NULL
;
1546 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1549 // if a root bridge instance is found, create root bridge device for it
1551 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1553 if (RootBridgeDev
== NULL
) {
1554 return EFI_OUT_OF_RESOURCES
;
1558 // Enumerate all the buses under this root bridge
1560 Status
= PciRootBridgeEnumerator (
1565 DestroyRootBridge (RootBridgeDev
);
1566 if (EFI_ERROR (Status
)) {
1572 // Notify the bus allocation phase is to end for the 2nd time
1574 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1578 // Notify the resource allocation phase is to start
1580 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1582 if (EFI_ERROR (Status
)) {
1586 RootBridgeHandle
= NULL
;
1587 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1590 // if a root bridge instance is found, create root bridge device for it
1592 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1594 if (RootBridgeDev
== NULL
) {
1595 return EFI_OUT_OF_RESOURCES
;
1598 Status
= StartManagingRootBridge (RootBridgeDev
);
1600 if (EFI_ERROR (Status
)) {
1604 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1605 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1607 if (EFI_ERROR (Status
)) {
1611 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1613 if (EFI_ERROR (Status
)) {
1618 // Determine root bridge attribute by calling interface of Pcihostbridge
1621 DetermineRootBridgeAttributes (
1627 // Collect all the resource information under this root bridge
1628 // A database that records all the information about pci device subject to this
1629 // root bridge will then be created
1631 Status
= PciPciDeviceInfoCollector (
1636 if (EFI_ERROR (Status
)) {
1640 InsertRootBridge (RootBridgeDev
);
1643 // Record the hostbridge handle
1645 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);