2 Internal library implementation for PCI Bus module.
4 Copyright (c) 2006 - 2010, 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.
19 Retrieve the PCI Card device BAR information via PciIo interface.
21 @param PciIoDevice PCI Card device instance.
26 IN PCI_IO_DEVICE
*PciIoDevice
31 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
36 // Read PciBar information from the bar register
38 if (!gFullEnumeration
) {
40 PciIoDevice
->PciIo
.Pci
.Read (
41 &(PciIoDevice
->PciIo
),
43 PCI_CARD_MEMORY_BASE_0
,
48 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
49 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
50 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
53 PciIoDevice
->PciIo
.Pci
.Read (
54 &(PciIoDevice
->PciIo
),
56 PCI_CARD_MEMORY_BASE_1
,
60 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
61 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
62 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
65 PciIoDevice
->PciIo
.Pci
.Read (
66 &(PciIoDevice
->PciIo
),
68 PCI_CARD_IO_BASE_0_LOWER
,
72 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
73 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
74 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
77 PciIoDevice
->PciIo
.Pci
.Read (
78 &(PciIoDevice
->PciIo
),
80 PCI_CARD_IO_BASE_1_LOWER
,
84 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
85 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
86 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
90 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
91 GetResourcePaddingForHpb (PciIoDevice
);
96 Remove rejected pci device from specific root bridge
99 @param RootBridgeHandle Specific parent root bridge handle.
100 @param Bridge Bridge device instance.
104 RemoveRejectedPciDevices (
105 IN EFI_HANDLE RootBridgeHandle
,
106 IN PCI_IO_DEVICE
*Bridge
110 LIST_ENTRY
*CurrentLink
;
111 LIST_ENTRY
*LastLink
;
113 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
117 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
119 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
121 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
123 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
125 // Remove rejected devices recusively
127 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
130 // Skip rejection for all PPBs, while detect rejection for others
132 if (IsPciDeviceRejected (Temp
)) {
135 // For P2C, remove all devices on it
137 if (!IsListEmpty (&Temp
->ChildList
)) {
138 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
142 // Finally remove itself
144 LastLink
= CurrentLink
->BackLink
;
145 RemoveEntryList (CurrentLink
);
146 FreePciDevice (Temp
);
148 CurrentLink
= LastLink
;
152 CurrentLink
= CurrentLink
->ForwardLink
;
157 Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
159 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
161 @retval EFI_SUCCESS Successfully finished resource allocation.
162 @retval EFI_NOT_FOUND Cannot get root bridge instance.
163 @retval EFI_OUT_OF_RESOURCES Platform failed to program the resources if no hot plug supported.
164 @retval other Some error occurred when allocating resources for the PCI Host Bridge.
166 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
170 PciHostBridgeResourceAllocator (
171 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
174 PCI_IO_DEVICE
*RootBridgeDev
;
175 EFI_HANDLE RootBridgeHandle
;
184 UINT64 Mem32ResStatus
;
185 UINT64 PMem32ResStatus
;
186 UINT64 Mem64ResStatus
;
187 UINT64 PMem64ResStatus
;
188 UINT64 MaxOptionRomSize
;
189 PCI_RESOURCE_NODE
*IoBridge
;
190 PCI_RESOURCE_NODE
*Mem32Bridge
;
191 PCI_RESOURCE_NODE
*PMem32Bridge
;
192 PCI_RESOURCE_NODE
*Mem64Bridge
;
193 PCI_RESOURCE_NODE
*PMem64Bridge
;
194 PCI_RESOURCE_NODE IoPool
;
195 PCI_RESOURCE_NODE Mem32Pool
;
196 PCI_RESOURCE_NODE PMem32Pool
;
197 PCI_RESOURCE_NODE Mem64Pool
;
198 PCI_RESOURCE_NODE PMem64Pool
;
200 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
201 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
209 // It may try several times if the resource allocation fails
213 // Initialize resource pool
215 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
216 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
217 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
218 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
219 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
221 RootBridgeDev
= NULL
;
222 RootBridgeHandle
= 0;
224 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
226 // Get Root Bridge Device by handle
228 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
230 if (RootBridgeDev
== NULL
) {
231 return EFI_NOT_FOUND
;
235 // Create the entire system resource map from the information collected by
236 // enumerator. Several resource tree was created
240 // If non-stardard PCI Bridge I/O window alignment is supported,
241 // set I/O aligment to minimum possible alignment for root bridge.
243 IoBridge
= CreateResourceNode (
246 FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
) ? 0x1FF: 0xFFF,
252 Mem32Bridge
= CreateResourceNode (
261 PMem32Bridge
= CreateResourceNode (
270 Mem64Bridge
= CreateResourceNode (
279 PMem64Bridge
= CreateResourceNode (
289 // Create resourcemap by going through all the devices subject to this root bridge
301 // Get the max ROM size that the root bridge can process
303 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
306 // Skip to enlarge the resource request during realloction
310 // Get Max Option Rom size for current root bridge
312 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
315 // Enlarger the mem32 resource to accomdate the option rom
316 // if the mem32 resource is not enough to hold the rom
318 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
320 Mem32Bridge
->Length
= MaxOptionRomSize
;
321 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
324 // Alignment should be adjusted as well
326 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
327 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
333 // Based on the all the resource tree, contruct ACPI resource node to
334 // submit the resource aperture to pci host bridge protocol
336 Status
= ConstructAcpiResourceRequestor (
347 // Insert these resource nodes into the database
349 InsertResourceNode (&IoPool
, IoBridge
);
350 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
351 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
352 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
353 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
355 if (Status
== EFI_SUCCESS
) {
357 // Submit the resource requirement
359 Status
= PciResAlloc
->SubmitResources (
361 RootBridgeDev
->Handle
,
367 // Free acpi resource node
369 if (AcpiConfig
!= NULL
) {
370 FreePool (AcpiConfig
);
373 if (EFI_ERROR (Status
)) {
375 // Destroy all the resource tree
377 DestroyResourceTree (&IoPool
);
378 DestroyResourceTree (&Mem32Pool
);
379 DestroyResourceTree (&PMem32Pool
);
380 DestroyResourceTree (&Mem64Pool
);
381 DestroyResourceTree (&PMem64Pool
);
386 // End while, at least one Root Bridge should be found.
388 ASSERT (RootBridgeDev
!= NULL
);
391 // Notify platform to start to program the resource
393 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
394 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
396 // If Hot Plug is not supported
398 if (EFI_ERROR (Status
)) {
400 // Allocation failed, then return
402 return EFI_OUT_OF_RESOURCES
;
405 // Allocation succeed.
406 // Get host bridge handle for status report, and then skip the main while
408 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
414 // If Hot Plug is supported
416 if (!EFI_ERROR (Status
)) {
418 // Allocation succeed, then continue the following
424 // If the resource allocation is unsuccessful, free resources on bridge
427 RootBridgeDev
= NULL
;
428 RootBridgeHandle
= 0;
430 IoResStatus
= EFI_RESOURCE_SATISFIED
;
431 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
432 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
433 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
434 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
436 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
438 // Get RootBridg Device by handle
440 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
441 if (RootBridgeDev
== NULL
) {
442 return EFI_NOT_FOUND
;
446 // Get host bridge handle for status report
448 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
451 // Get acpi resource node for all the resource types
455 Status
= PciResAlloc
->GetProposedResources (
457 RootBridgeDev
->Handle
,
461 if (EFI_ERROR (Status
)) {
465 if (AcpiConfig
!= NULL
) {
467 // Adjust resource allocation policy for each RB
469 GetResourceAllocationStatus (
477 FreePool (AcpiConfig
);
485 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
488 // It is very difficult to follow the spec here
489 // Device path , Bar index can not be get here
491 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
493 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
495 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
496 (VOID
*) &AllocFailExtendedData
,
497 sizeof (AllocFailExtendedData
)
500 Status
= PciHostBridgeAdjustAllocation (
514 // Destroy all the resource tree
516 DestroyResourceTree (&IoPool
);
517 DestroyResourceTree (&Mem32Pool
);
518 DestroyResourceTree (&PMem32Pool
);
519 DestroyResourceTree (&Mem64Pool
);
520 DestroyResourceTree (&PMem64Pool
);
522 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
524 if (EFI_ERROR (Status
)) {
536 // Raise the EFI_IOB_PCI_RES_ALLOC status code
538 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
540 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
541 (VOID
*) &HandleExtendedData
,
542 sizeof (HandleExtendedData
)
546 // Notify pci bus driver starts to program the resource
548 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
550 RootBridgeDev
= NULL
;
552 RootBridgeHandle
= 0;
554 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
556 // Get RootBridg Device by handle
558 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
560 if (RootBridgeDev
== NULL
) {
561 return EFI_NOT_FOUND
;
565 // Get acpi resource node for all the resource types
568 Status
= PciResAlloc
->GetProposedResources (
570 RootBridgeDev
->Handle
,
574 if (EFI_ERROR (Status
)) {
579 // Get the resource base by interpreting acpi resource node
592 // Process option rom for this root bridge
594 ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
597 // Create the entire system resource map from the information collected by
598 // enumerator. Several resource tree was created
615 // Program IO resources
623 // Program Mem32 resources
631 // Program PMem32 resources
639 // Program Mem64 resources
647 // Program PMem64 resources
654 FreePool (AcpiConfig
);
658 // Destroy all the resource tree
660 DestroyResourceTree (&IoPool
);
661 DestroyResourceTree (&Mem32Pool
);
662 DestroyResourceTree (&PMem32Pool
);
663 DestroyResourceTree (&Mem64Pool
);
664 DestroyResourceTree (&PMem64Pool
);
667 // Notify the resource allocation phase is to end
669 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
675 Scan pci bus and assign bus number to the given PCI bus system.
677 @param Bridge Bridge device instance.
678 @param StartBusNumber start point.
679 @param SubBusNumber Point to sub bus number.
680 @param PaddedBusRange Customized bus number.
682 @retval EFI_SUCCESS Successfully scanned and assigned bus number.
683 @retval other Some error occurred when scanning pci bus.
685 @note Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
690 IN PCI_IO_DEVICE
*Bridge
,
691 IN UINT8 StartBusNumber
,
692 OUT UINT8
*SubBusNumber
,
693 OUT UINT8
*PaddedBusRange
704 PCI_IO_DEVICE
*PciDevice
;
708 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
709 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
711 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
713 UINT32 TempReservedBusNum
;
715 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
719 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
725 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
726 TempReservedBusNum
= 0;
727 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
730 // Check to see whether a pci device is present
732 Status
= PciDevicePresent (
740 if (EFI_ERROR (Status
)) {
744 DEBUG((EFI_D_INFO
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
747 // Get the PCI device information
749 Status
= PciSearchDevice (
758 ASSERT (!EFI_ERROR (Status
));
760 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
762 if (!IS_PCI_BRIDGE (&Pci
)) {
764 // PCI bridges will be called later
765 // Here just need for PCI device or PCI to cardbus controller
766 // EfiPciBeforeChildBusEnumeration for PCI Device Node
768 PreprocessController (
770 PciDevice
->BusNumber
,
771 PciDevice
->DeviceNumber
,
772 PciDevice
->FunctionNumber
,
773 EfiPciBeforeChildBusEnumeration
777 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
779 // For Pci Hotplug controller devcie only
781 if (gPciHotPlugInit
!= NULL
) {
783 // Check if it is a Hotplug PCI controller
785 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
786 gPciRootHpcData
[HpIndex
].Found
= TRUE
;
788 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
790 Status
= CreateEventForHpc (HpIndex
, &Event
);
792 ASSERT (!EFI_ERROR (Status
));
794 Status
= gPciHotPlugInit
->InitializeRootHpc (
796 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
802 PreprocessController (
804 PciDevice
->BusNumber
,
805 PciDevice
->DeviceNumber
,
806 PciDevice
->FunctionNumber
,
807 EfiPciBeforeChildBusEnumeration
814 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
818 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
820 // If Hot Plug is not supported,
821 // get the bridge information
823 Status
= PciSearchDevice (
832 if (EFI_ERROR (Status
)) {
837 // If Hot Plug is supported,
838 // Get the bridge information
841 if (gPciHotPlugInit
!= NULL
) {
843 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
846 // If it is initialized, get the padded bus range
848 Status
= gPciHotPlugInit
->GetResourcePadding (
850 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
853 (VOID
**) &Descriptors
,
857 if (EFI_ERROR (Status
)) {
862 Status
= PciGetBusRange (
869 FreePool (Descriptors
);
871 if (EFI_ERROR (Status
)) {
881 // Add feature to support customized secondary bus number
883 if (*SubBusNumber
== 0) {
884 *SubBusNumber
= *PaddedBusRange
;
889 SecondBus
= *SubBusNumber
;
891 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
892 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET
);
894 Status
= PciRootBridgeIo
->Pci
.Write (
904 // If it is PPB, resursively search down this bridge
906 if (IS_PCI_BRIDGE (&Pci
)) {
909 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
910 // PCI configuration transaction to go through any PPB
913 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
914 Status
= PciRootBridgeIo
->Pci
.Write (
923 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
925 PreprocessController (
927 PciDevice
->BusNumber
,
928 PciDevice
->DeviceNumber
,
929 PciDevice
->FunctionNumber
,
930 EfiPciBeforeChildBusEnumeration
933 DEBUG((EFI_D_INFO
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
934 Status
= PciScanBus (
940 if (EFI_ERROR (Status
)) {
945 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
) && BusPadding
) {
947 // Ensure the device is enabled and initialized
949 if ((Attributes
== EfiPaddingPciRootBridge
) &&
950 (State
& EFI_HPC_STATE_ENABLED
) != 0 &&
951 (State
& EFI_HPC_STATE_INITIALIZED
) != 0) {
952 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
954 *SubBusNumber
= (UINT8
) ((UINT8
) (BusRange
) +*SubBusNumber
);
959 // Set the current maximum bus number under the PPB
961 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET
);
963 Status
= PciRootBridgeIo
->Pci
.Write (
972 // It is device. Check PCI IOV for Bus reservation
973 // Go through each function, just reserve the MAX ReservedBusNum for one device
975 if (PcdGetBool (PcdSrIovSupport
) && PciDevice
->SrIovCapabilityOffset
!= 0) {
976 if (TempReservedBusNum
< PciDevice
->ReservedBusNum
) {
978 (*SubBusNumber
) = (UINT8
)((*SubBusNumber
) + PciDevice
->ReservedBusNum
- TempReservedBusNum
);
979 TempReservedBusNum
= PciDevice
->ReservedBusNum
;
982 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber
));
984 DEBUG ((EFI_D_INFO
, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber
));
990 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
993 // Skip sub functions, this is not a multi function device
1005 Process Option Rom on the specified root bridge.
1007 @param Bridge Pci root bridge device instance.
1009 @retval EFI_SUCCESS Success process.
1010 @retval other Some error occurred when processing Option Rom on the root bridge.
1014 PciRootBridgeP2CProcess (
1015 IN PCI_IO_DEVICE
*Bridge
1018 LIST_ENTRY
*CurrentLink
;
1019 PCI_IO_DEVICE
*Temp
;
1020 EFI_HPC_STATE State
;
1024 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1026 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
1028 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1030 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1032 if (gPciHotPlugInit
!= NULL
&& Temp
->Allocated
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1035 // Raise the EFI_IOB_PCI_HPC_INIT status code
1037 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1039 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_HPC_INIT
,
1043 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1044 Status
= gPciHotPlugInit
->InitializeRootHpc (
1052 if (!EFI_ERROR (Status
)) {
1053 Status
= PciBridgeEnumerator (Temp
);
1055 if (EFI_ERROR (Status
)) {
1060 CurrentLink
= CurrentLink
->ForwardLink
;
1066 if (!IsListEmpty (&Temp
->ChildList
)) {
1067 Status
= PciRootBridgeP2CProcess (Temp
);
1070 CurrentLink
= CurrentLink
->ForwardLink
;
1077 Process Option Rom on the specified host bridge.
1079 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1081 @retval EFI_SUCCESS Success process.
1082 @retval EFI_NOT_FOUND Can not find the root bridge instance.
1083 @retval other Some error occurred when processing Option Rom on the host bridge.
1087 PciHostBridgeP2CProcess (
1088 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1091 EFI_HANDLE RootBridgeHandle
;
1092 PCI_IO_DEVICE
*RootBridgeDev
;
1095 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1099 RootBridgeHandle
= NULL
;
1101 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1104 // Get RootBridg Device by handle
1106 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1108 if (RootBridgeDev
== NULL
) {
1109 return EFI_NOT_FOUND
;
1112 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1113 if (EFI_ERROR (Status
)) {
1123 This function is used to enumerate the entire host bridge
1124 in a given platform.
1126 @param PciResAlloc A pointer to the PCI Host Resource Allocation protocol.
1128 @retval EFI_SUCCESS Successfully enumerated the host bridge.
1129 @retval EFI_OUT_OF_RESOURCES No enough memory available.
1130 @retval other Some error occurred when enumerating the host bridge.
1134 PciHostBridgeEnumerator (
1135 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1138 EFI_HANDLE RootBridgeHandle
;
1139 PCI_IO_DEVICE
*RootBridgeDev
;
1141 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1143 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1144 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
1145 UINT8 StartBusNumber
;
1146 LIST_ENTRY RootBridgeList
;
1149 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1150 InitializeHotPlugSupport ();
1153 InitializeListHead (&RootBridgeList
);
1156 // Notify the bus allocation phase is about to start
1158 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1160 DEBUG((EFI_D_INFO
, "PCI Bus First Scanning\n"));
1161 RootBridgeHandle
= NULL
;
1162 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1165 // if a root bridge instance is found, create root bridge device for it
1168 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1170 if (RootBridgeDev
== NULL
) {
1171 return EFI_OUT_OF_RESOURCES
;
1175 // Enumerate all the buses under this root bridge
1177 Status
= PciRootBridgeEnumerator (
1182 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1183 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1185 DestroyRootBridge (RootBridgeDev
);
1187 if (EFI_ERROR (Status
)) {
1193 // Notify the bus allocation phase is finished for the first time
1195 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1197 if (gPciHotPlugInit
!= NULL
&& FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1199 // Reset all assigned PCI bus number in all PPB
1201 RootBridgeHandle
= NULL
;
1202 Link
= GetFirstNode (&RootBridgeList
);
1203 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1204 (!IsNull (&RootBridgeList
, Link
))) {
1205 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1207 // Get the Bus information
1209 Status
= PciResAlloc
->StartBusEnumeration (
1212 (VOID
**) &Configuration
1214 if (EFI_ERROR (Status
)) {
1219 // Get the bus number to start with
1221 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
1223 ResetAllPpbBusNumber (
1228 FreePool (Configuration
);
1229 Link
= RemoveEntryList (Link
);
1230 DestroyRootBridge (RootBridgeDev
);
1234 // Wait for all HPC initialized
1236 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1238 if (EFI_ERROR (Status
)) {
1239 DEBUG ((EFI_D_ERROR
, "Some root HPC failed to initialize\n"));
1244 // Notify the bus allocation phase is about to start for the 2nd time
1246 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1248 DEBUG((EFI_D_INFO
, "PCI Bus Second Scanning\n"));
1249 RootBridgeHandle
= NULL
;
1250 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1253 // if a root bridge instance is found, create root bridge device for it
1255 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1257 if (RootBridgeDev
== NULL
) {
1258 return EFI_OUT_OF_RESOURCES
;
1262 // Enumerate all the buses under this root bridge
1264 Status
= PciRootBridgeEnumerator (
1269 DestroyRootBridge (RootBridgeDev
);
1270 if (EFI_ERROR (Status
)) {
1276 // Notify the bus allocation phase is to end for the 2nd time
1278 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1282 // Notify the resource allocation phase is to start
1284 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1286 RootBridgeHandle
= NULL
;
1287 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1290 // if a root bridge instance is found, create root bridge device for it
1292 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1294 if (RootBridgeDev
== NULL
) {
1295 return EFI_OUT_OF_RESOURCES
;
1298 Status
= StartManagingRootBridge (RootBridgeDev
);
1300 if (EFI_ERROR (Status
)) {
1304 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1305 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1307 if (EFI_ERROR (Status
)) {
1311 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1313 if (EFI_ERROR (Status
)) {
1318 // Determine root bridge attribute by calling interface of Pcihostbridge
1321 DetermineRootBridgeAttributes (
1327 // Collect all the resource information under this root bridge
1328 // A database that records all the information about pci device subject to this
1329 // root bridge will then be created
1331 Status
= PciPciDeviceInfoCollector (
1336 if (EFI_ERROR (Status
)) {
1340 InsertRootBridge (RootBridgeDev
);
1343 // Record the hostbridge handle
1345 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);