2 Internal library implementation for PCI Bus module.
4 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 GLOBAL_REMOVE_IF_UNREFERENCED
18 CHAR16
*mBarTypeStr
[] = {
32 Retrieve the PCI Card device BAR information via PciIo interface.
34 @param PciIoDevice PCI Card device instance.
39 IN PCI_IO_DEVICE
*PciIoDevice
44 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
49 // Read PciBar information from the bar register
51 if (!gFullEnumeration
) {
53 PciIoDevice
->PciIo
.Pci
.Read (
54 &(PciIoDevice
->PciIo
),
56 PCI_CARD_MEMORY_BASE_0
,
61 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
62 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
63 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
66 PciIoDevice
->PciIo
.Pci
.Read (
67 &(PciIoDevice
->PciIo
),
69 PCI_CARD_MEMORY_BASE_1
,
73 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
74 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
75 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
78 PciIoDevice
->PciIo
.Pci
.Read (
79 &(PciIoDevice
->PciIo
),
81 PCI_CARD_IO_BASE_0_LOWER
,
85 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
86 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
87 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
90 PciIoDevice
->PciIo
.Pci
.Read (
91 &(PciIoDevice
->PciIo
),
93 PCI_CARD_IO_BASE_1_LOWER
,
97 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
98 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
99 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
103 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
104 GetResourcePaddingForHpb (PciIoDevice
);
109 Remove rejected pci device from specific root bridge
112 @param RootBridgeHandle Specific parent root bridge handle.
113 @param Bridge Bridge device instance.
117 RemoveRejectedPciDevices (
118 IN EFI_HANDLE RootBridgeHandle
,
119 IN PCI_IO_DEVICE
*Bridge
123 LIST_ENTRY
*CurrentLink
;
124 LIST_ENTRY
*LastLink
;
126 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
130 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
132 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
134 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
136 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
138 // Remove rejected devices recusively
140 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
143 // Skip rejection for all PPBs, while detect rejection for others
145 if (IsPciDeviceRejected (Temp
)) {
148 // For P2C, remove all devices on it
150 if (!IsListEmpty (&Temp
->ChildList
)) {
151 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
155 // Finally remove itself
157 LastLink
= CurrentLink
->BackLink
;
158 RemoveEntryList (CurrentLink
);
159 FreePciDevice (Temp
);
161 CurrentLink
= LastLink
;
165 CurrentLink
= CurrentLink
->ForwardLink
;
170 Dump the resourc map of the bridge device.
172 @param[in] BridgeResource Resource descriptor of the bridge device.
176 IN PCI_RESOURCE_NODE
*BridgeResource
180 PCI_RESOURCE_NODE
*Resource
;
183 if ((BridgeResource
!= NULL
) && (BridgeResource
->Length
!= 0)) {
185 EFI_D_INFO
, "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",
186 mBarTypeStr
[MIN (BridgeResource
->ResType
, PciBarTypeMaxType
)],
187 BridgeResource
->PciDev
->PciBar
[BridgeResource
->Bar
].BaseAddress
,
188 BridgeResource
->Length
, BridgeResource
->Alignment
190 for ( Link
= BridgeResource
->ChildList
.ForwardLink
191 ; Link
!= &BridgeResource
->ChildList
192 ; Link
= Link
->ForwardLink
194 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
195 if (Resource
->ResourceUsage
== PciResUsageTypical
) {
196 Bar
= Resource
->Virtual
? Resource
->PciDev
->VfPciBar
: Resource
->PciDev
->PciBar
;
198 EFI_D_INFO
, " Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s ",
199 Bar
[Resource
->Bar
].BaseAddress
, Resource
->Length
, Resource
->Alignment
,
200 IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"PPB" :
201 IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) ? L
"P2C" :
205 if ((!IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && !IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
)) ||
206 (IS_PCI_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< PPB_IO_RANGE
)) ||
207 (IS_CARDBUS_BRIDGE (&Resource
->PciDev
->Pci
) && (Resource
->Bar
< P2C_MEM_1
))
210 // The resource requirement comes from the device itself.
213 EFI_D_INFO
, " [%02x|%02x|%02x:%02x]\n",
214 Resource
->PciDev
->BusNumber
, Resource
->PciDev
->DeviceNumber
,
215 Resource
->PciDev
->FunctionNumber
, Bar
[Resource
->Bar
].Offset
219 // The resource requirement comes from the subordinate devices.
222 EFI_D_INFO
, " [%02x|%02x|%02x:**]\n",
223 Resource
->PciDev
->BusNumber
, Resource
->PciDev
->DeviceNumber
,
224 Resource
->PciDev
->FunctionNumber
228 DEBUG ((EFI_D_INFO
, " Padding:Length = 0x%lx;\tAlignment = 0x%lx\n", Resource
->Length
, Resource
->Alignment
));
235 Find the corresponding resource node for the Device in child list of BridgeResource.
237 @param[in] Device Pointer to PCI_IO_DEVICE.
238 @param[in] BridgeResource Pointer to PCI_RESOURCE_NODE.
240 @return !NULL The corresponding resource node for the Device.
241 @return NULL No corresponding resource node for the Device.
245 IN PCI_IO_DEVICE
*Device
,
246 IN PCI_RESOURCE_NODE
*BridgeResource
250 PCI_RESOURCE_NODE
*Resource
;
252 for ( Link
= BridgeResource
->ChildList
.ForwardLink
253 ; Link
!= &BridgeResource
->ChildList
254 ; Link
= Link
->ForwardLink
256 Resource
= RESOURCE_NODE_FROM_LINK (Link
);
257 if (Resource
->PciDev
== Device
) {
266 Dump the resource map of all the devices under Bridge.
268 @param[in] Bridge Bridge device instance.
269 @param[in] IoNode IO resource descriptor for the bridge device.
270 @param[in] Mem32Node Mem32 resource descriptor for the bridge device.
271 @param[in] PMem32Node PMem32 resource descriptor for the bridge device.
272 @param[in] Mem64Node Mem64 resource descriptor for the bridge device.
273 @param[in] PMem64Node PMem64 resource descriptor for the bridge device.
277 IN PCI_IO_DEVICE
*Bridge
,
278 IN PCI_RESOURCE_NODE
*IoNode
,
279 IN PCI_RESOURCE_NODE
*Mem32Node
,
280 IN PCI_RESOURCE_NODE
*PMem32Node
,
281 IN PCI_RESOURCE_NODE
*Mem64Node
,
282 IN PCI_RESOURCE_NODE
*PMem64Node
287 PCI_IO_DEVICE
*Device
;
288 PCI_RESOURCE_NODE
*ChildIoNode
;
289 PCI_RESOURCE_NODE
*ChildMem32Node
;
290 PCI_RESOURCE_NODE
*ChildPMem32Node
;
291 PCI_RESOURCE_NODE
*ChildMem64Node
;
292 PCI_RESOURCE_NODE
*ChildPMem64Node
;
293 EFI_DEVICE_PATH_TO_TEXT_PROTOCOL
*ToText
;
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 Status
= gBS
->LocateProtocol (
313 &gEfiDevicePathToTextProtocolGuid
,
318 if (!EFI_ERROR (Status
)) {
319 Str
= ToText
->ConvertDevicePathToText (
320 DevicePathFromHandle (Bridge
->Handle
),
325 DEBUG ((EFI_D_INFO
, "Root Bridge %s\n", Str
!= NULL
? Str
: L
""));
331 DumpBridgeResource (IoNode
);
332 DumpBridgeResource (Mem32Node
);
333 DumpBridgeResource (PMem32Node
);
334 DumpBridgeResource (Mem64Node
);
335 DumpBridgeResource (PMem64Node
);
336 DEBUG ((EFI_D_INFO
, "\n"));
338 for ( Link
= Bridge
->ChildList
.ForwardLink
339 ; Link
!= &Bridge
->ChildList
340 ; Link
= Link
->ForwardLink
342 Device
= PCI_IO_DEVICE_FROM_LINK (Link
);
343 if (IS_PCI_BRIDGE (&Device
->Pci
)) {
345 ChildIoNode
= (IoNode
== NULL
? NULL
: FindResourceNode (Device
, IoNode
));
346 ChildMem32Node
= (Mem32Node
== NULL
? NULL
: FindResourceNode (Device
, Mem32Node
));
347 ChildPMem32Node
= (PMem32Node
== NULL
? NULL
: FindResourceNode (Device
, PMem32Node
));
348 ChildMem64Node
= (Mem64Node
== NULL
? NULL
: FindResourceNode (Device
, Mem64Node
));
349 ChildPMem64Node
= (PMem64Node
== NULL
? NULL
: FindResourceNode (Device
, PMem64Node
));
364 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
366 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
368 @retval EFI_SUCCESS Successfully finished resource allocation.
369 @retval EFI_NOT_FOUND Cannot get root bridge instance.
370 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.
371 @retval other Some error occurred when allocating resources for the PCI Host Bridge.
373 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
377 PciHostBridgeResourceAllocator (
378 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
381 PCI_IO_DEVICE
*RootBridgeDev
;
382 EFI_HANDLE RootBridgeHandle
;
391 UINT64 Mem32ResStatus
;
392 UINT64 PMem32ResStatus
;
393 UINT64 Mem64ResStatus
;
394 UINT64 PMem64ResStatus
;
395 UINT64 MaxOptionRomSize
;
396 PCI_RESOURCE_NODE
*IoBridge
;
397 PCI_RESOURCE_NODE
*Mem32Bridge
;
398 PCI_RESOURCE_NODE
*PMem32Bridge
;
399 PCI_RESOURCE_NODE
*Mem64Bridge
;
400 PCI_RESOURCE_NODE
*PMem64Bridge
;
401 PCI_RESOURCE_NODE IoPool
;
402 PCI_RESOURCE_NODE Mem32Pool
;
403 PCI_RESOURCE_NODE PMem32Pool
;
404 PCI_RESOURCE_NODE Mem64Pool
;
405 PCI_RESOURCE_NODE PMem64Pool
;
407 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
408 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
416 // It may try several times if the resource allocation fails
420 // Initialize resource pool
422 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
423 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
424 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
425 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
426 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
428 RootBridgeDev
= NULL
;
429 RootBridgeHandle
= 0;
431 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
433 // Get Root Bridge Device by handle
435 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
437 if (RootBridgeDev
== NULL
) {
438 return EFI_NOT_FOUND
;
442 // Create the entire system resource map from the information collected by
443 // enumerator. Several resource tree was created
447 // If non-stardard PCI Bridge I/O window alignment is supported,
448 // set I/O aligment to minimum possible alignment for root bridge.
450 IoBridge
= CreateResourceNode (
453 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
) ? 0x1FF: 0xFFF,
459 Mem32Bridge
= CreateResourceNode (
468 PMem32Bridge
= CreateResourceNode (
477 Mem64Bridge
= CreateResourceNode (
486 PMem64Bridge
= CreateResourceNode (
496 // Create resourcemap by going through all the devices subject to this root bridge
508 // Get the max ROM size that the root bridge can process
510 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
513 // Skip to enlarge the resource request during realloction
517 // Get Max Option Rom size for current root bridge
519 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
522 // Enlarger the mem32 resource to accomdate the option rom
523 // if the mem32 resource is not enough to hold the rom
525 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
527 Mem32Bridge
->Length
= MaxOptionRomSize
;
528 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
531 // Alignment should be adjusted as well
533 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
534 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
540 // Based on the all the resource tree, contruct ACPI resource node to
541 // submit the resource aperture to pci host bridge protocol
543 Status
= ConstructAcpiResourceRequestor (
554 // Insert these resource nodes into the database
556 InsertResourceNode (&IoPool
, IoBridge
);
557 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
558 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
559 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
560 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
562 if (Status
== EFI_SUCCESS
) {
564 // Submit the resource requirement
566 Status
= PciResAlloc
->SubmitResources (
568 RootBridgeDev
->Handle
,
572 // If SubmitResources returns error, PciBus isn't able to start.
573 // It's a fatal error so assertion is added.
575 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->SubmitResources() - %r\n", Status
));
576 ASSERT_EFI_ERROR (Status
);
580 // Free acpi resource node
582 if (AcpiConfig
!= NULL
) {
583 FreePool (AcpiConfig
);
586 if (EFI_ERROR (Status
)) {
588 // Destroy all the resource tree
590 DestroyResourceTree (&IoPool
);
591 DestroyResourceTree (&Mem32Pool
);
592 DestroyResourceTree (&PMem32Pool
);
593 DestroyResourceTree (&Mem64Pool
);
594 DestroyResourceTree (&PMem64Pool
);
599 // End while, at least one Root Bridge should be found.
601 ASSERT (RootBridgeDev
!= NULL
);
604 // Notify platform to start to program the resource
606 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
607 DEBUG ((EFI_D_INFO
, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status
));
608 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
610 // If Hot Plug is not supported
612 if (EFI_ERROR (Status
)) {
614 // Allocation failed, then return
616 return EFI_OUT_OF_RESOURCES
;
619 // Allocation succeed.
620 // Get host bridge handle for status report, and then skip the main while
622 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
628 // If Hot Plug is supported
630 if (!EFI_ERROR (Status
)) {
632 // Allocation succeed, then continue the following
638 // If the resource allocation is unsuccessful, free resources on bridge
641 RootBridgeDev
= NULL
;
642 RootBridgeHandle
= 0;
644 IoResStatus
= EFI_RESOURCE_SATISFIED
;
645 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
646 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
647 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
648 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
650 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
652 // Get RootBridg Device by handle
654 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
655 if (RootBridgeDev
== NULL
) {
656 return EFI_NOT_FOUND
;
660 // Get host bridge handle for status report
662 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
665 // Get acpi resource node for all the resource types
669 Status
= PciResAlloc
->GetProposedResources (
671 RootBridgeDev
->Handle
,
675 if (EFI_ERROR (Status
)) {
679 if (AcpiConfig
!= NULL
) {
681 // Adjust resource allocation policy for each RB
683 GetResourceAllocationStatus (
691 FreePool (AcpiConfig
);
699 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
702 // It is very difficult to follow the spec here
703 // Device path , Bar index can not be get here
705 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
707 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
709 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
710 (VOID
*) &AllocFailExtendedData
,
711 sizeof (AllocFailExtendedData
)
714 Status
= PciHostBridgeAdjustAllocation (
728 // Destroy all the resource tree
730 DestroyResourceTree (&IoPool
);
731 DestroyResourceTree (&Mem32Pool
);
732 DestroyResourceTree (&PMem32Pool
);
733 DestroyResourceTree (&Mem64Pool
);
734 DestroyResourceTree (&PMem64Pool
);
736 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
738 if (EFI_ERROR (Status
)) {
750 // Raise the EFI_IOB_PCI_RES_ALLOC status code
752 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
754 EFI_IO_BUS_PCI
| EFI_IOB_PCI_RES_ALLOC
,
755 (VOID
*) &HandleExtendedData
,
756 sizeof (HandleExtendedData
)
760 // Notify pci bus driver starts to program the resource
762 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
764 RootBridgeDev
= NULL
;
766 RootBridgeHandle
= 0;
768 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
770 // Get RootBridg Device by handle
772 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
774 if (RootBridgeDev
== NULL
) {
775 return EFI_NOT_FOUND
;
779 // Get acpi resource node for all the resource types
782 Status
= PciResAlloc
->GetProposedResources (
784 RootBridgeDev
->Handle
,
788 if (EFI_ERROR (Status
)) {
793 // Get the resource base by interpreting acpi resource node
806 // Process option rom for this root bridge
808 ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
811 // Create the entire system resource map from the information collected by
812 // enumerator. Several resource tree was created
814 IoBridge
= FindResourceNode (RootBridgeDev
, &IoPool
);
815 Mem32Bridge
= FindResourceNode (RootBridgeDev
, &Mem32Pool
);
816 PMem32Bridge
= FindResourceNode (RootBridgeDev
, &PMem32Pool
);
817 Mem64Bridge
= FindResourceNode (RootBridgeDev
, &Mem64Pool
);
818 PMem64Bridge
= FindResourceNode (RootBridgeDev
, &PMem64Pool
);
820 ASSERT (IoBridge
!= NULL
);
821 ASSERT (Mem32Bridge
!= NULL
);
822 ASSERT (PMem32Bridge
!= NULL
);
823 ASSERT (Mem64Bridge
!= NULL
);
824 ASSERT (PMem64Bridge
!= NULL
);
827 // Program IO resources
835 // Program Mem32 resources
843 // Program PMem32 resources
851 // Program Mem64 resources
859 // Program PMem64 resources
866 IoBridge
->PciDev
->PciBar
[IoBridge
->Bar
].BaseAddress
= IoBase
;
867 Mem32Bridge
->PciDev
->PciBar
[Mem32Bridge
->Bar
].BaseAddress
= Mem32Base
;
868 PMem32Bridge
->PciDev
->PciBar
[PMem32Bridge
->Bar
].BaseAddress
= PMem32Base
;
869 Mem64Bridge
->PciDev
->PciBar
[Mem64Bridge
->Bar
].BaseAddress
= Mem64Base
;
870 PMem64Bridge
->PciDev
->PciBar
[PMem64Bridge
->Bar
].BaseAddress
= PMem64Base
;
873 // Dump the resource map for current root bridge
886 FreePool (AcpiConfig
);
890 // Destroy all the resource tree
892 DestroyResourceTree (&IoPool
);
893 DestroyResourceTree (&Mem32Pool
);
894 DestroyResourceTree (&PMem32Pool
);
895 DestroyResourceTree (&Mem64Pool
);
896 DestroyResourceTree (&PMem64Pool
);
899 // Notify the resource allocation phase is to end
901 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
907 Allocate NumberOfBuses buses and return the next available PCI bus number.
909 @param Bridge Bridge device instance.
910 @param StartBusNumber Current available PCI bus number.
911 @param NumberOfBuses Number of buses enumerated below the StartBusNumber.
912 @param NextBusNumber Next available PCI bus number.
914 @retval EFI_SUCCESS Available bus number resource is enough. Next available PCI bus number
915 is returned in NextBusNumber.
916 @retval EFI_OUT_OF_RESOURCES Available bus number resource is not enough for allocation.
920 PciAllocateBusNumber (
921 IN PCI_IO_DEVICE
*Bridge
,
922 IN UINT8 StartBusNumber
,
923 IN UINT8 NumberOfBuses
,
924 OUT UINT8
*NextBusNumber
927 PCI_IO_DEVICE
*RootBridge
;
928 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BusNumberRanges
;
930 UINT64 MaxNumberInRange
;
933 // Get PCI Root Bridge device
936 while (RootBridge
->Parent
!= NULL
) {
937 RootBridge
= RootBridge
->Parent
;
941 // Get next available PCI bus number
943 BusNumberRanges
= RootBridge
->BusNumberRanges
;
944 while (BusNumberRanges
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
945 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
946 if (StartBusNumber
>= BusNumberRanges
->AddrRangeMin
&& StartBusNumber
<= MaxNumberInRange
) {
947 NextNumber
= (UINT8
)(StartBusNumber
+ NumberOfBuses
);
948 while (NextNumber
> MaxNumberInRange
) {
950 if (BusNumberRanges
->Desc
== ACPI_END_TAG_DESCRIPTOR
) {
951 return EFI_OUT_OF_RESOURCES
;
953 NextNumber
= (UINT8
)(NextNumber
+ (BusNumberRanges
->AddrRangeMin
- (MaxNumberInRange
+ 1)));
954 MaxNumberInRange
= BusNumberRanges
->AddrRangeMin
+ BusNumberRanges
->AddrLen
- 1;
956 *NextBusNumber
= NextNumber
;
961 return EFI_OUT_OF_RESOURCES
;
965 Scan pci bus and assign bus number to the given PCI bus system.
967 @param Bridge Bridge device instance.
968 @param StartBusNumber start point.
969 @param SubBusNumber Point to sub bus number.
970 @param PaddedBusRange Customized bus number.
972 @retval EFI_SUCCESS Successfully scanned and assigned bus number.
973 @retval other Some error occurred when scanning pci bus.
975 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
980 IN PCI_IO_DEVICE
*Bridge
,
981 IN UINT8 StartBusNumber
,
982 OUT UINT8
*SubBusNumber
,
983 OUT UINT8
*PaddedBusRange
994 PCI_IO_DEVICE
*PciDevice
;
998 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
999 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1001 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1003 UINT32 TempReservedBusNum
;
1005 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1009 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
1015 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1016 TempReservedBusNum
= 0;
1017 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1020 // Check to see whether a pci device is present
1022 Status
= PciDevicePresent (
1030 if (EFI_ERROR (Status
)) {
1035 // Get the PCI device information
1037 Status
= PciSearchDevice (
1046 ASSERT (!EFI_ERROR (Status
));
1048 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1050 if (!IS_PCI_BRIDGE (&Pci
)) {
1052 // PCI bridges will be called later
1053 // Here just need for PCI device or PCI to cardbus controller
1054 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1056 PreprocessController (
1058 PciDevice
->BusNumber
,
1059 PciDevice
->DeviceNumber
,
1060 PciDevice
->FunctionNumber
,
1061 EfiPciBeforeChildBusEnumeration
1065 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1067 // For Pci Hotplug controller devcie only
1069 if (gPciHotPlugInit
!= NULL
) {
1071 // Check if it is a Hotplug PCI controller
1073 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1074 gPciRootHpcData
[HpIndex
].Found
= TRUE
;
1076 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1078 Status
= CreateEventForHpc (HpIndex
, &Event
);
1080 ASSERT (!EFI_ERROR (Status
));
1082 Status
= gPciHotPlugInit
->InitializeRootHpc (
1084 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1090 PreprocessController (
1092 PciDevice
->BusNumber
,
1093 PciDevice
->DeviceNumber
,
1094 PciDevice
->FunctionNumber
,
1095 EfiPciBeforeChildBusEnumeration
1102 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1106 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1108 // If Hot Plug is not supported,
1109 // get the bridge information
1111 Status
= PciSearchDevice (
1120 if (EFI_ERROR (Status
)) {
1125 // If Hot Plug is supported,
1126 // Get the bridge information
1129 if (gPciHotPlugInit
!= NULL
) {
1131 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
1134 // If it is initialized, get the padded bus range
1136 Status
= gPciHotPlugInit
->GetResourcePadding (
1138 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
1141 (VOID
**) &Descriptors
,
1145 if (EFI_ERROR (Status
)) {
1150 Status
= PciGetBusRange (
1157 FreePool (Descriptors
);
1159 if (EFI_ERROR (Status
)) {
1168 Status
= PciAllocateBusNumber (Bridge
, *SubBusNumber
, 1, SubBusNumber
);
1169 if (EFI_ERROR (Status
)) {
1172 SecondBus
= *SubBusNumber
;
1174 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1175 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET
);
1177 Status
= PciRootBridgeIo
->Pci
.Write (
1187 // If it is PPB, resursively search down this bridge
1189 if (IS_PCI_BRIDGE (&Pci
)) {
1192 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1193 // PCI configuration transaction to go through any PPB
1196 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
1197 Status
= PciRootBridgeIo
->Pci
.Write (
1206 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1208 PreprocessController (
1210 PciDevice
->BusNumber
,
1211 PciDevice
->DeviceNumber
,
1212 PciDevice
->FunctionNumber
,
1213 EfiPciBeforeChildBusEnumeration
1216 Status
= PciScanBus (
1218 (UINT8
) (SecondBus
),
1222 if (EFI_ERROR (Status
)) {
1227 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
) && BusPadding
) {
1229 // Ensure the device is enabled and initialized
1231 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1232 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
1233 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
1234 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
1236 Status
= PciAllocateBusNumber (PciDevice
, *SubBusNumber
, (UINT8
) (BusRange
), SubBusNumber
);
1237 if (EFI_ERROR (Status
)) {
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 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1448 DEBUG((EFI_D_INFO
, "PCI Bus First Scanning\n"));
1449 RootBridgeHandle
= NULL
;
1450 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1453 // if a root bridge instance is found, create root bridge device for it
1456 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1458 if (RootBridgeDev
== NULL
) {
1459 return EFI_OUT_OF_RESOURCES
;
1463 // Enumerate all the buses under this root bridge
1465 Status
= PciRootBridgeEnumerator (
1470 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1471 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1473 DestroyRootBridge (RootBridgeDev
);
1475 if (EFI_ERROR (Status
)) {
1481 // Notify the bus allocation phase is finished for the first time
1483 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1485 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1487 // Reset all assigned PCI bus number in all PPB
1489 RootBridgeHandle
= NULL
;
1490 Link
= GetFirstNode (&RootBridgeList
);
1491 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1492 (!IsNull (&RootBridgeList
, Link
))) {
1493 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1495 // Get the Bus information
1497 Status
= PciResAlloc
->StartBusEnumeration (
1500 (VOID
**) &Configuration
1502 if (EFI_ERROR (Status
)) {
1507 // Get the bus number to start with
1509 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1511 ResetAllPpbBusNumber (
1516 FreePool (Configuration
);
1517 Link
= RemoveEntryList (Link
);
1518 DestroyRootBridge (RootBridgeDev
);
1522 // Wait for all HPC initialized
1524 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1526 if (EFI_ERROR (Status
)) {
1527 DEBUG ((EFI_D_ERROR
, "Some root HPC failed to initialize\n"));
1532 // Notify the bus allocation phase is about to start for the 2nd time
1534 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1536 DEBUG((EFI_D_INFO
, "PCI Bus Second Scanning\n"));
1537 RootBridgeHandle
= NULL
;
1538 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1541 // if a root bridge instance is found, create root bridge device for it
1543 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1545 if (RootBridgeDev
== NULL
) {
1546 return EFI_OUT_OF_RESOURCES
;
1550 // Enumerate all the buses under this root bridge
1552 Status
= PciRootBridgeEnumerator (
1557 DestroyRootBridge (RootBridgeDev
);
1558 if (EFI_ERROR (Status
)) {
1564 // Notify the bus allocation phase is to end for the 2nd time
1566 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1570 // Notify the resource allocation phase is to start
1572 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1574 RootBridgeHandle
= NULL
;
1575 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1578 // if a root bridge instance is found, create root bridge device for it
1580 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1582 if (RootBridgeDev
== NULL
) {
1583 return EFI_OUT_OF_RESOURCES
;
1586 Status
= StartManagingRootBridge (RootBridgeDev
);
1588 if (EFI_ERROR (Status
)) {
1592 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1593 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1595 if (EFI_ERROR (Status
)) {
1599 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1601 if (EFI_ERROR (Status
)) {
1606 // Determine root bridge attribute by calling interface of Pcihostbridge
1609 DetermineRootBridgeAttributes (
1615 // Collect all the resource information under this root bridge
1616 // A database that records all the information about pci device subject to this
1617 // root bridge will then be created
1619 Status
= PciPciDeviceInfoCollector (
1624 if (EFI_ERROR (Status
)) {
1628 InsertRootBridge (RootBridgeDev
);
1631 // Record the hostbridge handle
1633 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);