2 Internal library implementation for PCI Bus module.
4 Copyright (c) 2006 - 2013, 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
= BridgeResource
->ChildList
.ForwardLink
192 ; Link
!= &BridgeResource
->ChildList
193 ; Link
= Link
->ForwardLink
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 ",
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" :
206 if ((!IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && !IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
)) ||
207 (IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< PPB_IO_RANGE
)) ||
208 (IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< P2C_MEM_1
))
211 // The resource requirement comes from the device itself.
214 EFI_D_INFO
, " [%02x|%02x|%02x:%02x]\n",
215 Resource
->PciDev
->BusNumber
, Resource
->PciDev
->DeviceNumber
,
216 Resource
->PciDev
->FunctionNumber
, Bar
[Resource
->Bar
].Offset
220 // The resource requirement comes from the subordinate devices.
223 EFI_D_INFO
, " [%02x|%02x|%02x:**]\n",
224 Resource
->PciDev
->BusNumber
, Resource
->PciDev
->DeviceNumber
,
225 Resource
->PciDev
->FunctionNumber
229 DEBUG ((EFI_D_INFO
, " Padding:Length = 0x%lx;\tAlignment = 0x%lx\n", Resource
->Length
, Resource
->Alignment
));
236 Find the corresponding resource node for the Device in child list of BridgeResource.
238 @param[in] Device Pointer to PCI_IO_DEVICE.
239 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.
241 @return !NULL The corresponding resource node for the Device.
242 @return NULL No corresponding resource node for the Device.
246 IN PCI_IO_DEVICE
*Device
,
247 IN PCI_RESOURCE_NODE
*BridgeResource
251 PCI_RESOURCE_NODE
*Resource
;
253 for ( Link
= BridgeResource
->ChildList
.ForwardLink
254 ; Link
!= &BridgeResource
->ChildList
255 ; Link
= Link
->ForwardLink
257 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
258 if (Resource
->PciDev
== Device
) {
267 Dump the resource map of all the devices under Bridge.
269 @param[in] Bridge Bridge device instance.
270 @param[in] IoNode IO resource descriptor for the bridge device.
271 @param[in] Mem32Node Mem32 resource descriptor for the bridge device.
272 @param[in] PMem32Node PMem32 resource descriptor for the bridge device.
273 @param[in] Mem64Node Mem64 resource descriptor for the bridge device.
274 @param[in] PMem64Node PMem64 resource descriptor for the bridge device.
278 IN PCI_IO_DEVICE
*Bridge
,
279 IN PCI_RESOURCE_NODE
*IoNode
,
280 IN PCI_RESOURCE_NODE
*Mem32Node
,
281 IN PCI_RESOURCE_NODE
*PMem32Node
,
282 IN PCI_RESOURCE_NODE
*Mem64Node
,
283 IN PCI_RESOURCE_NODE
*PMem64Node
288 PCI_IO_DEVICE
*Device
;
289 PCI_RESOURCE_NODE
*ChildIoNode
;
290 PCI_RESOURCE_NODE
*ChildMem32Node
;
291 PCI_RESOURCE_NODE
*ChildPMem32Node
;
292 PCI_RESOURCE_NODE
*ChildMem64Node
;
293 PCI_RESOURCE_NODE
*ChildPMem64Node
;
296 DEBUG ((EFI_D_INFO
, "PciBus: Resource Map for "));
298 Status
= gBS
->OpenProtocol (
300 &gEfiPciRootBridgeIoProtocolGuid
,
304 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
306 if (EFI_ERROR (Status
)) {
308 EFI_D_INFO
, "Bridge [%02x|%02x|%02x]\n",
309 Bridge
->BusNumber
, Bridge
->DeviceNumber
, Bridge
->FunctionNumber
312 Str
= ConvertDevicePathToText (
313 DevicePathFromHandle (Bridge
->Handle
),
317 DEBUG ((EFI_D_INFO
, "Root Bridge %s\n", Str
!= NULL
? Str
: L
""));
323 DumpBridgeResource (IoNode
);
324 DumpBridgeResource (Mem32Node
);
325 DumpBridgeResource (PMem32Node
);
326 DumpBridgeResource (Mem64Node
);
327 DumpBridgeResource (PMem64Node
);
328 DEBUG ((EFI_D_INFO
, "\n"));
330 for ( Link
= Bridge
->ChildList
.ForwardLink
331 ; Link
!= &Bridge
->ChildList
332 ; Link
= Link
->ForwardLink
334 Device
= PCI_IO_DEVICE_FROM_LINK (Link
);
335 if (IS_PCI_BRIDGE (&Device
->Pci
)) {
337 ChildIoNode
= (IoNode
== NULL
? NULL
: FindResourceNode (Device
, IoNode
));
338 ChildMem32Node
= (Mem32Node
== NULL
? NULL
: FindResourceNode (Device
, Mem32Node
));
339 ChildPMem32Node
= (PMem32Node
== NULL
? NULL
: FindResourceNode (Device
, PMem32Node
));
340 ChildMem64Node
= (Mem64Node
== NULL
? NULL
: FindResourceNode (Device
, Mem64Node
));
341 ChildPMem64Node
= (PMem64Node
== NULL
? NULL
: FindResourceNode (Device
, PMem64Node
));
356 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
358 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
360 @retval EFI_SUCCESS Successfully finished resource allocation.
361 @retval EFI_NOT_FOUND Cannot get root bridge instance.
362 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.
363 @retval other Some error occurred when allocating resources for the PCI Host Bridge.
365 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
369 PciHostBridgeResourceAllocator (
370 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
373 PCI_IO_DEVICE
*RootBridgeDev
;
374 EFI_HANDLE RootBridgeHandle
;
383 UINT64 Mem32ResStatus
;
384 UINT64 PMem32ResStatus
;
385 UINT64 Mem64ResStatus
;
386 UINT64 PMem64ResStatus
;
387 UINT64 MaxOptionRomSize
;
388 PCI_RESOURCE_NODE
*IoBridge
;
389 PCI_RESOURCE_NODE
*Mem32Bridge
;
390 PCI_RESOURCE_NODE
*PMem32Bridge
;
391 PCI_RESOURCE_NODE
*Mem64Bridge
;
392 PCI_RESOURCE_NODE
*PMem64Bridge
;
393 PCI_RESOURCE_NODE IoPool
;
394 PCI_RESOURCE_NODE Mem32Pool
;
395 PCI_RESOURCE_NODE PMem32Pool
;
396 PCI_RESOURCE_NODE Mem64Pool
;
397 PCI_RESOURCE_NODE PMem64Pool
;
399 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
400 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
408 // It may try several times if the resource allocation fails
412 // Initialize resource pool
414 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
415 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
416 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
417 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
418 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
420 RootBridgeDev
= NULL
;
421 RootBridgeHandle
= 0;
423 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
425 // Get Root Bridge Device by handle
427 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
429 if (RootBridgeDev
== NULL
) {
430 return EFI_NOT_FOUND
;
434 // Create the entire system resource map from the information collected by
435 // enumerator. Several resource tree was created
439 // If non-stardard PCI Bridge I/O window alignment is supported,
440 // set I/O aligment to minimum possible alignment for root bridge.
442 IoBridge
= CreateResourceNode (
445 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
) ? 0x1FF: 0xFFF,
451 Mem32Bridge
= CreateResourceNode (
460 PMem32Bridge
= CreateResourceNode (
469 Mem64Bridge
= CreateResourceNode (
478 PMem64Bridge
= CreateResourceNode (
488 // Create resourcemap by going through all the devices subject to this root bridge
500 // Get the max ROM size that the root bridge can process
502 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
505 // Skip to enlarge the resource request during realloction
509 // Get Max Option Rom size for current root bridge
511 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
514 // Enlarger the mem32 resource to accomdate the option rom
515 // if the mem32 resource is not enough to hold the rom
517 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
519 Mem32Bridge
->Length
= MaxOptionRomSize
;
520 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
523 // Alignment should be adjusted as well
525 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
526 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
532 // Based on the all the resource tree, contruct ACPI resource node to
533 // submit the resource aperture to pci host bridge protocol
535 Status
= ConstructAcpiResourceRequestor (
546 // Insert these resource nodes into the database
548 InsertResourceNode (&IoPool
, IoBridge
);
549 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
550 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
551 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
552 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
554 if (Status
== EFI_SUCCESS
) {
556 // Submit the resource requirement
558 Status
= PciResAlloc
->SubmitResources (
560 RootBridgeDev
->Handle
,
564 // If SubmitResources returns error, PciBus isn't able to start.
565 // It's a fatal error so assertion is added.
567 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->SubmitResources() - %r\n", Status
));
568 ASSERT_EFI_ERROR (Status
);
572 // Free acpi resource node
574 if (AcpiConfig
!= NULL
) {
575 FreePool (AcpiConfig
);
578 if (EFI_ERROR (Status
)) {
580 // Destroy all the resource tree
582 DestroyResourceTree (&IoPool
);
583 DestroyResourceTree (&Mem32Pool
);
584 DestroyResourceTree (&PMem32Pool
);
585 DestroyResourceTree (&Mem64Pool
);
586 DestroyResourceTree (&PMem64Pool
);
591 // End while, at least one Root Bridge should be found.
593 ASSERT (RootBridgeDev
!= NULL
);
596 // Notify platform to start to program the resource
598 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
599 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status
));
600 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
602 // If Hot Plug is not supported
604 if (EFI_ERROR (Status
)) {
606 // Allocation failed, then return
608 return EFI_OUT_OF_RESOURCES
;
611 // Allocation succeed.
612 // Get host bridge handle for status report, and then skip the main while
614 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
620 // If Hot Plug is supported
622 if (!EFI_ERROR (Status
)) {
624 // Allocation succeed, then continue the following
630 // If the resource allocation is unsuccessful, free resources on bridge
633 RootBridgeDev
= NULL
;
634 RootBridgeHandle
= 0;
636 IoResStatus
= EFI_RESOURCE_SATISFIED
;
637 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
638 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
639 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
640 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
642 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
644 // Get RootBridg Device by handle
646 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
647 if (RootBridgeDev
== NULL
) {
648 return EFI_NOT_FOUND
;
652 // Get host bridge handle for status report
654 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
657 // Get acpi resource node for all the resource types
661 Status
= PciResAlloc
->GetProposedResources (
663 RootBridgeDev
->Handle
,
667 if (EFI_ERROR (Status
)) {
671 if (AcpiConfig
!= NULL
) {
673 // Adjust resource allocation policy for each RB
675 GetResourceAllocationStatus (
683 FreePool (AcpiConfig
);
691 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
694 // It is very difficult to follow the spec here
695 // Device path , Bar index can not be get here
697 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
699 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
701 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
702 (VOID
*) &AllocFailExtendedData
,
703 sizeof (AllocFailExtendedData
)
706 Status
= PciHostBridgeAdjustAllocation (
720 // Destroy all the resource tree
722 DestroyResourceTree (&IoPool
);
723 DestroyResourceTree (&Mem32Pool
);
724 DestroyResourceTree (&PMem32Pool
);
725 DestroyResourceTree (&Mem64Pool
);
726 DestroyResourceTree (&PMem64Pool
);
728 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
730 if (EFI_ERROR (Status
)) {
742 // Raise the EFI_IOB_PCI_RES_ALLOC status code
744 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
746 EFI_IO_BUS_PCI
| EFI_IOB_PCI_RES_ALLOC
,
747 (VOID
*) &HandleExtendedData
,
748 sizeof (HandleExtendedData
)
752 // Notify pci bus driver starts to program the resource
754 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
756 if (EFI_ERROR (Status
)) {
760 RootBridgeDev
= NULL
;
762 RootBridgeHandle
= 0;
764 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
766 // Get RootBridg Device by handle
768 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
770 if (RootBridgeDev
== NULL
) {
771 return EFI_NOT_FOUND
;
775 // Get acpi resource node for all the resource types
778 Status
= PciResAlloc
->GetProposedResources (
780 RootBridgeDev
->Handle
,
784 if (EFI_ERROR (Status
)) {
789 // Get the resource base by interpreting acpi resource node
802 // Process option rom for this root bridge
804 ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
807 // Create the entire system resource map from the information collected by
808 // enumerator. Several resource tree was created
810 IoBridge
= FindResourceNode (RootBridgeDev
, &IoPool
);
811 Mem32Bridge
= FindResourceNode (RootBridgeDev
, &Mem32Pool
);
812 PMem32Bridge
= FindResourceNode (RootBridgeDev
, &PMem32Pool
);
813 Mem64Bridge
= FindResourceNode (RootBridgeDev
, &Mem64Pool
);
814 PMem64Bridge
= FindResourceNode (RootBridgeDev
, &PMem64Pool
);
816 ASSERT (IoBridge
!= NULL
);
817 ASSERT (Mem32Bridge
!= NULL
);
818 ASSERT (PMem32Bridge
!= NULL
);
819 ASSERT (Mem64Bridge
!= NULL
);
820 ASSERT (PMem64Bridge
!= NULL
);
823 // Program IO resources
831 // Program Mem32 resources
839 // Program PMem32 resources
847 // Program Mem64 resources
855 // Program PMem64 resources
862 IoBridge
->PciDev
->PciBar
[IoBridge
->Bar
].BaseAddress
= IoBase
;
863 Mem32Bridge
->PciDev
->PciBar
[Mem32Bridge
->Bar
].BaseAddress
= Mem32Base
;
864 PMem32Bridge
->PciDev
->PciBar
[PMem32Bridge
->Bar
].BaseAddress
= PMem32Base
;
865 Mem64Bridge
->PciDev
->PciBar
[Mem64Bridge
->Bar
].BaseAddress
= Mem64Base
;
866 PMem64Bridge
->PciDev
->PciBar
[PMem64Bridge
->Bar
].BaseAddress
= PMem64Base
;
869 // Dump the resource map for current root bridge
882 FreePool (AcpiConfig
);
886 // Destroy all the resource tree
888 DestroyResourceTree (&IoPool
);
889 DestroyResourceTree (&Mem32Pool
);
890 DestroyResourceTree (&PMem32Pool
);
891 DestroyResourceTree (&Mem64Pool
);
892 DestroyResourceTree (&PMem64Pool
);
895 // Notify the resource allocation phase is to end
897 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
903 Allocate NumberOfBuses buses and return the next available PCI bus number.
905 @param Bridge Bridge device instance.
906 @param StartBusNumber Current available PCI bus number.
907 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.
908 @param NextBusNumber Next available PCI bus number.
910 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number
911 is returned in NextBusNumber.
912 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.
916 PciAllocateBusNumber (
917 IN PCI_IO_DEVICE
*Bridge
,
918 IN UINT8 StartBusNumber
,
919 IN UINT8 NumberOfBuses
,
920 OUT UINT8
*NextBusNumber
923 PCI_IO_DEVICE
*RootBridge
;
924 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BusNumberRanges
;
926 UINT64 MaxNumberInRange
;
929 // Get PCI Root Bridge device
932 while (RootBridge
->Parent
!= NULL
) {
933 RootBridge
= RootBridge
->Parent
;
937 // Get next available PCI bus number
939 BusNumberRanges
= RootBridge
->BusNumberRanges
;
940 while (BusNumberRanges
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
941 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
942 if (StartBusNumber
>= BusNumberRanges
->AddrRangeMin
&& StartBusNumber
<= MaxNumberInRange
) {
943 NextNumber
= (UINT8
)(StartBusNumber
+ NumberOfBuses
);
944 while (NextNumber
> MaxNumberInRange
) {
946 if (BusNumberRanges
->Desc
== ACPI_END_TAG_DESCRIPTOR
) {
947 return EFI_OUT_OF_RESOURCES
;
949 NextNumber
= (UINT8
)(NextNumber
+ (BusNumberRanges
->AddrRangeMin
- (MaxNumberInRange
+ 1)));
950 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
952 *NextBusNumber
= NextNumber
;
957 return EFI_OUT_OF_RESOURCES
;
961 Scan pci bus and assign bus number to the given PCI bus system.
963 @param Bridge Bridge device instance.
964 @param StartBusNumber start point.
965 @param SubBusNumber Point to sub bus number.
966 @param PaddedBusRange Customized bus number.
968 @retval EFI_SUCCESS Successfully scanned and assigned bus number.
969 @retval other Some error occurred when scanning pci bus.
971 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
976 IN PCI_IO_DEVICE
*Bridge
,
977 IN UINT8 StartBusNumber
,
978 OUT UINT8
*SubBusNumber
,
979 OUT UINT8
*PaddedBusRange
990 PCI_IO_DEVICE
*PciDevice
;
994 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
995 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
997 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
999 UINT32 TempReservedBusNum
;
1001 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1005 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
1011 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1012 TempReservedBusNum
= 0;
1013 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1016 // Check to see whether a pci device is present
1018 Status
= PciDevicePresent (
1026 if (EFI_ERROR (Status
) && Func
== 0) {
1028 // go to next device if there is no Function 0
1033 if (EFI_ERROR (Status
)) {
1038 // Get the PCI device information
1040 Status
= PciSearchDevice (
1049 ASSERT (!EFI_ERROR (Status
));
1051 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1053 if (!IS_PCI_BRIDGE (&Pci
)) {
1055 // PCI bridges will be called later
1056 // Here just need for PCI device or PCI to cardbus controller
1057 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1059 PreprocessController (
1061 PciDevice
->BusNumber
,
1062 PciDevice
->DeviceNumber
,
1063 PciDevice
->FunctionNumber
,
1064 EfiPciBeforeChildBusEnumeration
1068 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1070 // For Pci Hotplug controller devcie only
1072 if (gPciHotPlugInit
!= NULL
) {
1074 // Check if it is a Hotplug PCI controller
1076 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1077 gPciRootHpcData
[HpIndex
].Found
= TRUE
;
1079 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1081 Status
= CreateEventForHpc (HpIndex
, &Event
);
1083 ASSERT (!EFI_ERROR (Status
));
1085 Status
= gPciHotPlugInit
->InitializeRootHpc (
1087 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1093 PreprocessController (
1095 PciDevice
->BusNumber
,
1096 PciDevice
->DeviceNumber
,
1097 PciDevice
->FunctionNumber
,
1098 EfiPciBeforeChildBusEnumeration
1105 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1109 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1111 // If Hot Plug is not supported,
1112 // get the bridge information
1114 Status
= PciSearchDevice (
1123 if (EFI_ERROR (Status
)) {
1128 // If Hot Plug is supported,
1129 // Get the bridge information
1132 if (gPciHotPlugInit
!= NULL
) {
1134 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
1137 // If it is initialized, get the padded bus range
1139 Status
= gPciHotPlugInit
->GetResourcePadding (
1141 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
1144 (VOID
**) &Descriptors
,
1148 if (EFI_ERROR (Status
)) {
1153 Status
= PciGetBusRange (
1160 FreePool (Descriptors
);
1162 if (EFI_ERROR (Status
)) {
1171 Status
= PciAllocateBusNumber (Bridge
, *SubBusNumber
, 1, SubBusNumber
);
1172 if (EFI_ERROR (Status
)) {
1175 SecondBus
= *SubBusNumber
;
1177 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1178 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET
);
1180 Status
= PciRootBridgeIo
->Pci
.Write (
1190 // If it is PPB, resursively search down this bridge
1192 if (IS_PCI_BRIDGE (&Pci
)) {
1195 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1196 // PCI configuration transaction to go through any PPB
1199 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1200 Status
= PciRootBridgeIo
->Pci
.Write (
1209 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1211 PreprocessController (
1213 PciDevice
->BusNumber
,
1214 PciDevice
->DeviceNumber
,
1215 PciDevice
->FunctionNumber
,
1216 EfiPciBeforeChildBusEnumeration
1219 Status
= PciScanBus (
1221 (UINT8
) (SecondBus
),
1225 if (EFI_ERROR (Status
)) {
1230 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
) && BusPadding
) {
1232 // Ensure the device is enabled and initialized
1234 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1235 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
1236 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
1237 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
1239 Status
= PciAllocateBusNumber (PciDevice
, *SubBusNumber
, (UINT8
) (BusRange
), SubBusNumber
);
1240 if (EFI_ERROR (Status
)) {
1247 // Set the current maximum bus number under the PPB
1249 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1251 Status
= PciRootBridgeIo
->Pci
.Write (
1260 // It is device. Check PCI IOV for Bus reservation
1261 // Go through each function, just reserve the MAX ReservedBusNum for one device
1263 if (PcdGetBool (PcdSrIovSupport
) && PciDevice
->SrIovCapabilityOffset
!= 0) {
1264 if (TempReservedBusNum
< PciDevice
->ReservedBusNum
) {
1266 Status
= PciAllocateBusNumber (PciDevice
, *SubBusNumber
, (UINT8
) (PciDevice
->ReservedBusNum
- TempReservedBusNum
), SubBusNumber
);
1267 if (EFI_ERROR (Status
)) {
1270 TempReservedBusNum
= PciDevice
->ReservedBusNum
;
1273 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber
));
1275 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber
));
1281 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1284 // Skip sub functions, this is not a multi function device
1287 Func
= PCI_MAX_FUNC
;
1296 Process Option Rom on the specified root bridge.
1298 @param Bridge Pci root bridge device instance.
1300 @retval EFI_SUCCESS Success process.
1301 @retval other Some error occurred when processing Option Rom on the root bridge.
1305 PciRootBridgeP2CProcess (
1306 IN PCI_IO_DEVICE
*Bridge
1309 LIST_ENTRY
*CurrentLink
;
1310 PCI_IO_DEVICE
*Temp
;
1311 EFI_HPC_STATE State
;
1315 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1317 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1319 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1321 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1323 if (gPciHotPlugInit
!= NULL
&& Temp
->Allocated
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1326 // Raise the EFI_IOB_PCI_HPC_INIT status code
1328 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1330 EFI_IO_BUS_PCI
| EFI_IOB_PCI_HPC_INIT
,
1334 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1335 Status
= gPciHotPlugInit
->InitializeRootHpc (
1343 if (!EFI_ERROR (Status
)) {
1344 Status
= PciBridgeEnumerator (Temp
);
1346 if (EFI_ERROR (Status
)) {
1351 CurrentLink
= CurrentLink
->ForwardLink
;
1357 if (!IsListEmpty (&Temp
->ChildList
)) {
1358 Status
= PciRootBridgeP2CProcess (Temp
);
1361 CurrentLink
= CurrentLink
->ForwardLink
;
1368 Process Option Rom on the specified host bridge.
1370 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1372 @retval EFI_SUCCESS Success process.
1373 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1374 @retval other Some error occurred when processing Option Rom on the host bridge.
1378 PciHostBridgeP2CProcess (
1379 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1382 EFI_HANDLE RootBridgeHandle
;
1383 PCI_IO_DEVICE
*RootBridgeDev
;
1386 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1390 RootBridgeHandle
= NULL
;
1392 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1395 // Get RootBridg Device by handle
1397 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1399 if (RootBridgeDev
== NULL
) {
1400 return EFI_NOT_FOUND
;
1403 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1404 if (EFI_ERROR (Status
)) {
1414 This function is used to enumerate the entire host bridge
1415 in a given platform.
1417 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1419 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1420 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1421 @retval other Some error occurred when enumerating the host bridge.
1425 PciHostBridgeEnumerator (
1426 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1429 EFI_HANDLE RootBridgeHandle
;
1430 PCI_IO_DEVICE
*RootBridgeDev
;
1432 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1434 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1435 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1436 UINT8 StartBusNumber
;
1437 LIST_ENTRY RootBridgeList
;
1440 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1441 InitializeHotPlugSupport ();
1444 InitializeListHead (&RootBridgeList
);
1447 // Notify the bus allocation phase is about to start
1449 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1451 if (EFI_ERROR (Status
)) {
1455 DEBUG((EFI_D_INFO
, "PCI Bus First Scanning\n"));
1456 RootBridgeHandle
= NULL
;
1457 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1460 // if a root bridge instance is found, create root bridge device for it
1463 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1465 if (RootBridgeDev
== NULL
) {
1466 return EFI_OUT_OF_RESOURCES
;
1470 // Enumerate all the buses under this root bridge
1472 Status
= PciRootBridgeEnumerator (
1477 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1478 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1480 DestroyRootBridge (RootBridgeDev
);
1482 if (EFI_ERROR (Status
)) {
1488 // Notify the bus allocation phase is finished for the first time
1490 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1492 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1494 // Reset all assigned PCI bus number in all PPB
1496 RootBridgeHandle
= NULL
;
1497 Link
= GetFirstNode (&RootBridgeList
);
1498 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1499 (!IsNull (&RootBridgeList
, Link
))) {
1500 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1502 // Get the Bus information
1504 Status
= PciResAlloc
->StartBusEnumeration (
1507 (VOID
**) &Configuration
1509 if (EFI_ERROR (Status
)) {
1514 // Get the bus number to start with
1516 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1518 ResetAllPpbBusNumber (
1523 FreePool (Configuration
);
1524 Link
= RemoveEntryList (Link
);
1525 DestroyRootBridge (RootBridgeDev
);
1529 // Wait for all HPC initialized
1531 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1533 if (EFI_ERROR (Status
)) {
1534 DEBUG ((EFI_D_ERROR
, "Some root HPC failed to initialize\n"));
1539 // Notify the bus allocation phase is about to start for the 2nd time
1541 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1543 if (EFI_ERROR (Status
)) {
1547 DEBUG((EFI_D_INFO
, "PCI Bus Second Scanning\n"));
1548 RootBridgeHandle
= NULL
;
1549 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1552 // if a root bridge instance is found, create root bridge device for it
1554 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1556 if (RootBridgeDev
== NULL
) {
1557 return EFI_OUT_OF_RESOURCES
;
1561 // Enumerate all the buses under this root bridge
1563 Status
= PciRootBridgeEnumerator (
1568 DestroyRootBridge (RootBridgeDev
);
1569 if (EFI_ERROR (Status
)) {
1575 // Notify the bus allocation phase is to end for the 2nd time
1577 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1581 // Notify the resource allocation phase is to start
1583 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1585 if (EFI_ERROR (Status
)) {
1589 RootBridgeHandle
= NULL
;
1590 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1593 // if a root bridge instance is found, create root bridge device for it
1595 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1597 if (RootBridgeDev
== NULL
) {
1598 return EFI_OUT_OF_RESOURCES
;
1601 Status
= StartManagingRootBridge (RootBridgeDev
);
1603 if (EFI_ERROR (Status
)) {
1607 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1608 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1610 if (EFI_ERROR (Status
)) {
1614 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1616 if (EFI_ERROR (Status
)) {
1621 // Determine root bridge attribute by calling interface of Pcihostbridge
1624 DetermineRootBridgeAttributes (
1630 // Collect all the resource information under this root bridge
1631 // A database that records all the information about pci device subject to this
1632 // root bridge will then be created
1634 Status
= PciPciDeviceInfoCollector (
1639 if (EFI_ERROR (Status
)) {
1643 InsertRootBridge (RootBridgeDev
);
1646 // Record the hostbridge handle
1648 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);