2 PCI eunmeration implementation on entire PCI bus system 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.
18 This routine is used to enumerate entire pci bus system
21 @param Controller Parent controller handle.
23 @retval EFI_SUCCESS PCI enumeration finished successfully.
24 @retval other Some error occurred when enumerating the pci bus system.
29 IN EFI_HANDLE Controller
32 EFI_HANDLE HostBridgeHandle
;
34 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
35 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
38 // If PCI bus has already done the full enumeration, never do it again
40 if (!gFullEnumeration
) {
41 return PciEnumeratorLight (Controller
);
45 // Get the rootbridge Io protocol to find the host bridge handle
47 Status
= gBS
->OpenProtocol (
49 &gEfiPciRootBridgeIoProtocolGuid
,
50 (VOID
**) &PciRootBridgeIo
,
51 gPciBusDriverBinding
.DriverBindingHandle
,
53 EFI_OPEN_PROTOCOL_GET_PROTOCOL
56 if (EFI_ERROR (Status
)) {
61 // Get the host bridge handle
63 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
66 // Get the pci host bridge resource allocation protocol
68 Status
= gBS
->OpenProtocol (
70 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
71 (VOID
**) &PciResAlloc
,
72 gPciBusDriverBinding
.DriverBindingHandle
,
74 EFI_OPEN_PROTOCOL_GET_PROTOCOL
77 if (EFI_ERROR (Status
)) {
82 // Notify the pci bus enumeration is about to begin
84 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginEnumeration
);
86 if (EFI_ERROR (Status
)) {
91 // Start the bus allocation phase
93 Status
= PciHostBridgeEnumerator (PciResAlloc
);
95 if (EFI_ERROR (Status
)) {
100 // Submit the resource request
102 Status
= PciHostBridgeResourceAllocator (PciResAlloc
);
104 if (EFI_ERROR (Status
)) {
109 // Notify the pci bus enumeration is about to complete
111 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndEnumeration
);
113 if (EFI_ERROR (Status
)) {
120 Status
= PciHostBridgeP2CProcess (PciResAlloc
);
122 if (EFI_ERROR (Status
)) {
127 // Process attributes for devices on this host bridge
129 Status
= PciHostBridgeDeviceAttribute (PciResAlloc
);
130 if (EFI_ERROR (Status
)) {
134 gFullEnumeration
= FALSE
;
136 Status
= gBS
->InstallProtocolInterface (
138 &gEfiPciEnumerationCompleteProtocolGuid
,
139 EFI_NATIVE_INTERFACE
,
142 if (EFI_ERROR (Status
)) {
150 Enumerate PCI root bridge.
152 @param PciResAlloc Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
153 @param RootBridgeDev Instance of root bridge device.
155 @retval EFI_SUCCESS Successfully enumerated root bridge.
156 @retval other Failed to enumerate root bridge.
160 PciRootBridgeEnumerator (
161 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
162 IN PCI_IO_DEVICE
*RootBridgeDev
166 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
167 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration1
;
168 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration2
;
169 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration3
;
171 UINT8 StartBusNumber
;
172 UINT8 PaddedBusRange
;
173 EFI_HANDLE RootBridgeHandle
;
183 // Get the root bridge handle
185 RootBridgeHandle
= RootBridgeDev
->Handle
;
187 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
189 EFI_IO_BUS_PCI
| EFI_IOB_PCI_BUS_ENUM
,
190 RootBridgeDev
->DevicePath
194 // Get the Bus information
196 Status
= PciResAlloc
->StartBusEnumeration (
199 (VOID
**) &Configuration
202 if (EFI_ERROR (Status
)) {
206 if (Configuration
== NULL
|| Configuration
->Desc
== ACPI_END_TAG_DESCRIPTOR
) {
207 return EFI_INVALID_PARAMETER
;
209 RootBridgeDev
->BusNumberRanges
= Configuration
;
212 // Sort the descriptors in ascending order
214 for (Configuration1
= Configuration
; Configuration1
->Desc
!= ACPI_END_TAG_DESCRIPTOR
; Configuration1
++) {
215 Configuration2
= Configuration1
;
216 for (Configuration3
= Configuration1
+ 1; Configuration3
->Desc
!= ACPI_END_TAG_DESCRIPTOR
; Configuration3
++) {
217 if (Configuration2
->AddrRangeMin
> Configuration3
->AddrRangeMin
) {
218 Configuration2
= Configuration3
;
222 // All other fields other than AddrRangeMin and AddrLen are ignored in a descriptor,
223 // so only need to swap these two fields.
225 if (Configuration2
!= Configuration1
) {
226 AddrRangeMin
= Configuration1
->AddrRangeMin
;
227 Configuration1
->AddrRangeMin
= Configuration2
->AddrRangeMin
;
228 Configuration2
->AddrRangeMin
= AddrRangeMin
;
230 AddrLen
= Configuration1
->AddrLen
;
231 Configuration1
->AddrLen
= Configuration2
->AddrLen
;
232 Configuration2
->AddrLen
= AddrLen
;
237 // Get the bus number to start with
239 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
242 // Initialize the subordinate bus number
244 SubBusNumber
= StartBusNumber
;
247 // Reset all assigned PCI bus number
249 ResetAllPpbBusNumber (
257 Status
= PciScanBus (
264 if (EFI_ERROR (Status
)) {
270 // Assign max bus number scanned
273 Status
= PciAllocateBusNumber (RootBridgeDev
, SubBusNumber
, PaddedBusRange
, &SubBusNumber
);
274 if (EFI_ERROR (Status
)) {
279 // Find the bus range which contains the higest bus number, then returns the number of buses
280 // that should be decoded.
282 while (Configuration
->AddrRangeMin
+ Configuration
->AddrLen
- 1 < SubBusNumber
) {
285 AddrLen
= Configuration
->AddrLen
;
286 Configuration
->AddrLen
= SubBusNumber
- Configuration
->AddrRangeMin
+ 1;
289 // Save the Desc field of the next descriptor. Mark the next descriptor as an END descriptor.
292 Desc
= Configuration
->Desc
;
293 Configuration
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
298 Status
= PciResAlloc
->SetBusNumbers (
301 RootBridgeDev
->BusNumberRanges
305 // Restore changed fields
307 Configuration
->Desc
= Desc
;
308 (Configuration
- 1)->AddrLen
= AddrLen
;
314 This routine is used to process all PCI devices' Option Rom
315 on a certain root bridge.
317 @param Bridge Given parent's root bridge.
318 @param RomBase Base address of ROM driver loaded from.
319 @param MaxLength Maximum rom size.
324 IN PCI_IO_DEVICE
*Bridge
,
329 LIST_ENTRY
*CurrentLink
;
333 // Go through bridges to reach all devices
335 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
336 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
337 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
338 if (!IsListEmpty (&Temp
->ChildList
)) {
341 // Go further to process the option rom under this bridge
343 ProcessOptionRom (Temp
, RomBase
, MaxLength
);
346 if (Temp
->RomSize
!= 0 && Temp
->RomSize
<= MaxLength
) {
349 // Load and process the option rom
351 LoadOpRomImage (Temp
, RomBase
);
354 CurrentLink
= CurrentLink
->ForwardLink
;
359 This routine is used to assign bus number to the given PCI bus system
361 @param Bridge Parent root bridge instance.
362 @param StartBusNumber Number of beginning.
363 @param SubBusNumber The number of sub bus.
365 @retval EFI_SUCCESS Successfully assigned bus number.
366 @retval EFI_DEVICE_ERROR Failed to assign bus number.
371 IN PCI_IO_DEVICE
*Bridge
,
372 IN UINT8 StartBusNumber
,
373 OUT UINT8
*SubBusNumber
384 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
386 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
391 *SubBusNumber
= StartBusNumber
;
394 // First check to see whether the parent is ppb
396 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
397 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
400 // Check to see whether a pci device is present
402 Status
= PciDevicePresent (
410 if (!EFI_ERROR (Status
) &&
411 (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
414 // Reserved one bus for cardbus bridge
416 Status
= PciAllocateBusNumber (Bridge
, *SubBusNumber
, 1, SubBusNumber
);
417 if (EFI_ERROR (Status
)) {
420 SecondBus
= *SubBusNumber
;
422 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
424 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
426 Status
= PciRootBridgeIo
->Pci
.Write (
435 // Initialize SubBusNumber to SecondBus
437 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
438 Status
= PciRootBridgeIo
->Pci
.Write (
446 // If it is PPB, resursively search down this bridge
448 if (IS_PCI_BRIDGE (&Pci
)) {
451 Status
= PciRootBridgeIo
->Pci
.Write (
459 Status
= PciAssignBusNumber (
465 if (EFI_ERROR (Status
)) {
466 return EFI_DEVICE_ERROR
;
471 // Set the current maximum bus number under the PPB
473 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
475 Status
= PciRootBridgeIo
->Pci
.Write (
485 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
488 // Skip sub functions, this is not a multi function device
499 This routine is used to determine the root bridge attribute by interfacing
500 the host bridge resource allocation protocol.
502 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
503 @param RootBridgeDev Root bridge instance
505 @retval EFI_SUCCESS Successfully got root bridge's attribute.
506 @retval other Failed to get attribute.
510 DetermineRootBridgeAttributes (
511 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
512 IN PCI_IO_DEVICE
*RootBridgeDev
517 EFI_HANDLE RootBridgeHandle
;
520 RootBridgeHandle
= RootBridgeDev
->Handle
;
523 // Get root bridge attribute by calling into pci host bridge resource allocation protocol
525 Status
= PciResAlloc
->GetAllocAttributes (
531 if (EFI_ERROR (Status
)) {
536 // Here is the point where PCI bus driver calls HOST bridge allocation protocol
537 // Currently we hardcoded for ea815
539 if ((Attributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) {
540 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
;
543 if ((Attributes
& EFI_PCI_HOST_BRIDGE_MEM64_DECODE
) != 0) {
544 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM64_DECODE_SUPPORTED
;
545 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
548 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
549 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
550 RootBridgeDev
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
556 Get Max Option Rom size on specified bridge.
558 @param Bridge Given bridge device instance.
560 @return Max size of option rom needed.
564 GetMaxOptionRomSize (
565 IN PCI_IO_DEVICE
*Bridge
568 LIST_ENTRY
*CurrentLink
;
570 UINT64 MaxOptionRomSize
;
571 UINT64 TempOptionRomSize
;
573 MaxOptionRomSize
= 0;
576 // Go through bridges to reach all devices
578 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
579 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
580 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
581 if (!IsListEmpty (&Temp
->ChildList
)) {
584 // Get max option rom size under this bridge
586 TempOptionRomSize
= GetMaxOptionRomSize (Temp
);
589 // Compare with the option rom size of the bridge
590 // Get the larger one
592 if (Temp
->RomSize
> TempOptionRomSize
) {
593 TempOptionRomSize
= Temp
->RomSize
;
599 // For devices get the rom size directly
601 TempOptionRomSize
= Temp
->RomSize
;
605 // Get the largest rom size on this bridge
607 if (TempOptionRomSize
> MaxOptionRomSize
) {
608 MaxOptionRomSize
= TempOptionRomSize
;
611 CurrentLink
= CurrentLink
->ForwardLink
;
614 return MaxOptionRomSize
;
618 Process attributes of devices on this host bridge
620 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
622 @retval EFI_SUCCESS Successfully process attribute.
623 @retval EFI_NOT_FOUND Can not find the specific root bridge device.
624 @retval other Failed to determine the root bridge device's attribute.
628 PciHostBridgeDeviceAttribute (
629 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
632 EFI_HANDLE RootBridgeHandle
;
633 PCI_IO_DEVICE
*RootBridgeDev
;
636 RootBridgeHandle
= NULL
;
638 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
641 // Get RootBridg Device by handle
643 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
645 if (RootBridgeDev
== NULL
) {
646 return EFI_NOT_FOUND
;
650 // Set the attributes for devcies behind the Root Bridge
652 Status
= DetermineDeviceAttribute (RootBridgeDev
);
653 if (EFI_ERROR (Status
)) {
663 Get resource allocation status from the ACPI resource descriptor.
665 @param AcpiConfig Point to Acpi configuration table.
666 @param IoResStatus Return the status of I/O resource.
667 @param Mem32ResStatus Return the status of 32-bit Memory resource.
668 @param PMem32ResStatus Return the status of 32-bit Prefetchable Memory resource.
669 @param Mem64ResStatus Return the status of 64-bit Memory resource.
670 @param PMem64ResStatus Return the status of 64-bit Prefetchable Memory resource.
674 GetResourceAllocationStatus (
676 OUT UINT64
*IoResStatus
,
677 OUT UINT64
*Mem32ResStatus
,
678 OUT UINT64
*PMem32ResStatus
,
679 OUT UINT64
*Mem64ResStatus
,
680 OUT UINT64
*PMem64ResStatus
685 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*ACPIAddressDesc
;
687 Temp
= (UINT8
*) AcpiConfig
;
689 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
691 ACPIAddressDesc
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
692 ResStatus
= ACPIAddressDesc
->AddrTranslationOffset
;
694 switch (ACPIAddressDesc
->ResType
) {
696 if (ACPIAddressDesc
->AddrSpaceGranularity
== 32) {
697 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
701 *PMem32ResStatus
= ResStatus
;
706 *Mem32ResStatus
= ResStatus
;
710 if (ACPIAddressDesc
->AddrSpaceGranularity
== 64) {
711 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
715 *PMem64ResStatus
= ResStatus
;
720 *Mem64ResStatus
= ResStatus
;
730 *IoResStatus
= ResStatus
;
737 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
742 Remove a PCI device from device pool and mark its bar.
744 @param PciDevice Instance of Pci device.
746 @retval EFI_SUCCESS Successfully remove the PCI device.
747 @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
752 IN PCI_IO_DEVICE
*PciDevice
755 PCI_IO_DEVICE
*Bridge
;
757 LIST_ENTRY
*CurrentLink
;
760 // Remove the padding resource from a bridge
762 if ( IS_PCI_BRIDGE(&PciDevice
->Pci
) &&
763 PciDevice
->ResourcePaddingDescriptors
!= NULL
) {
764 FreePool (PciDevice
->ResourcePaddingDescriptors
);
765 PciDevice
->ResourcePaddingDescriptors
= NULL
;
772 if (IS_PCI_BRIDGE (&PciDevice
->Pci
) || (PciDevice
->Parent
== NULL
)) {
776 if (IS_CARDBUS_BRIDGE (&PciDevice
->Pci
)) {
778 // Get the root bridge device
781 while (Bridge
->Parent
!= NULL
) {
782 Bridge
= Bridge
->Parent
;
785 RemoveAllPciDeviceOnBridge (Bridge
->Handle
, PciDevice
);
790 InitializeP2C (PciDevice
);
796 Bridge
= PciDevice
->Parent
;
797 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
798 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
799 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
800 if (Temp
== PciDevice
) {
801 InitializePciDevice (Temp
);
802 RemoveEntryList (CurrentLink
);
806 CurrentLink
= CurrentLink
->ForwardLink
;
813 Determine whethter a PCI device can be rejected.
815 @param PciResNode Pointer to Pci resource node instance.
817 @retval TRUE The PCI device can be rejected.
818 @retval TRUE The PCI device cannot be rejected.
823 IN PCI_RESOURCE_NODE
*PciResNode
828 Temp
= PciResNode
->PciDev
;
831 // Ensure the device is present
838 // PPB and RB should go ahead
840 if (IS_PCI_BRIDGE (&Temp
->Pci
) || (Temp
->Parent
== NULL
)) {
845 // Skip device on Bus0
847 if ((Temp
->Parent
!= NULL
) && (Temp
->BusNumber
== 0)) {
854 if (IS_PCI_VGA (&Temp
->Pci
)) {
862 Compare two resource nodes and get the larger resource consumer.
864 @param PciResNode1 resource node 1 want to be compared
865 @param PciResNode2 resource node 2 want to be compared
867 @return Larger resource node.
871 GetLargerConsumerDevice (
872 IN PCI_RESOURCE_NODE
*PciResNode1
,
873 IN PCI_RESOURCE_NODE
*PciResNode2
876 if (PciResNode2
== NULL
) {
880 if ((IS_PCI_BRIDGE(&(PciResNode2
->PciDev
->Pci
)) || (PciResNode2
->PciDev
->Parent
== NULL
)) \
881 && (PciResNode2
->ResourceUsage
!= PciResUsagePadding
) )
886 if (PciResNode1
== NULL
) {
890 if ((PciResNode1
->Length
) > (PciResNode2
->Length
)) {
899 Get the max resource consumer in the host resource pool.
901 @param ResPool Pointer to resource pool node.
903 @return The max resource consumer in the host resource pool.
907 GetMaxResourceConsumerDevice (
908 IN PCI_RESOURCE_NODE
*ResPool
911 PCI_RESOURCE_NODE
*Temp
;
912 LIST_ENTRY
*CurrentLink
;
913 PCI_RESOURCE_NODE
*PciResNode
;
914 PCI_RESOURCE_NODE
*PPBResNode
;
918 CurrentLink
= ResPool
->ChildList
.ForwardLink
;
919 while (CurrentLink
!= NULL
&& CurrentLink
!= &ResPool
->ChildList
) {
921 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
923 if (!IsRejectiveDevice (Temp
)) {
924 CurrentLink
= CurrentLink
->ForwardLink
;
928 if ((IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
)) || (Temp
->PciDev
->Parent
== NULL
)) \
929 && (Temp
->ResourceUsage
!= PciResUsagePadding
))
931 PPBResNode
= GetMaxResourceConsumerDevice (Temp
);
932 PciResNode
= GetLargerConsumerDevice (PciResNode
, PPBResNode
);
934 PciResNode
= GetLargerConsumerDevice (PciResNode
, Temp
);
937 CurrentLink
= CurrentLink
->ForwardLink
;
944 Adjust host bridge allocation so as to reduce resource requirement
946 @param IoPool Pointer to instance of I/O resource Node.
947 @param Mem32Pool Pointer to instance of 32-bit memory resource Node.
948 @param PMem32Pool Pointer to instance of 32-bit Prefetchable memory resource node.
949 @param Mem64Pool Pointer to instance of 64-bit memory resource node.
950 @param PMem64Pool Pointer to instance of 64-bit Prefetchable memory resource node.
951 @param IoResStatus Status of I/O resource Node.
952 @param Mem32ResStatus Status of 32-bit memory resource Node.
953 @param PMem32ResStatus Status of 32-bit Prefetchable memory resource node.
954 @param Mem64ResStatus Status of 64-bit memory resource node.
955 @param PMem64ResStatus Status of 64-bit Prefetchable memory resource node.
957 @retval EFI_SUCCESS Successfully adjusted resoruce on host bridge.
958 @retval EFI_ABORTED Host bridge hasn't this resource type or no resource be adjusted.
962 PciHostBridgeAdjustAllocation (
963 IN PCI_RESOURCE_NODE
*IoPool
,
964 IN PCI_RESOURCE_NODE
*Mem32Pool
,
965 IN PCI_RESOURCE_NODE
*PMem32Pool
,
966 IN PCI_RESOURCE_NODE
*Mem64Pool
,
967 IN PCI_RESOURCE_NODE
*PMem64Pool
,
968 IN UINT64 IoResStatus
,
969 IN UINT64 Mem32ResStatus
,
970 IN UINT64 PMem32ResStatus
,
971 IN UINT64 Mem64ResStatus
,
972 IN UINT64 PMem64ResStatus
975 BOOLEAN AllocationAjusted
;
976 PCI_RESOURCE_NODE
*PciResNode
;
977 PCI_RESOURCE_NODE
*ResPool
[5];
978 PCI_IO_DEVICE
*RemovedPciDev
[5];
980 UINTN RemovedPciDevNum
;
984 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
987 ZeroMem (RemovedPciDev
, 5 * sizeof (PCI_IO_DEVICE
*));
988 RemovedPciDevNum
= 0;
991 ResPool
[1] = Mem32Pool
;
992 ResPool
[2] = PMem32Pool
;
993 ResPool
[3] = Mem64Pool
;
994 ResPool
[4] = PMem64Pool
;
996 ResStatus
[0] = IoResStatus
;
997 ResStatus
[1] = Mem32ResStatus
;
998 ResStatus
[2] = PMem32ResStatus
;
999 ResStatus
[3] = Mem64ResStatus
;
1000 ResStatus
[4] = PMem64ResStatus
;
1002 AllocationAjusted
= FALSE
;
1004 for (ResType
= 0; ResType
< 5; ResType
++) {
1006 if (ResStatus
[ResType
] == EFI_RESOURCE_SATISFIED
) {
1010 if (ResStatus
[ResType
] == EFI_RESOURCE_NOT_SATISFIED
) {
1012 // Host bridge hasn't this resource type
1018 // Hostbridge hasn't enough resource
1020 PciResNode
= GetMaxResourceConsumerDevice (ResPool
[ResType
]);
1021 if (PciResNode
== NULL
) {
1026 // Check if the device has been removed before
1028 for (DevIndex
= 0; DevIndex
< RemovedPciDevNum
; DevIndex
++) {
1029 if (PciResNode
->PciDev
== RemovedPciDev
[DevIndex
]) {
1034 if (DevIndex
!= RemovedPciDevNum
) {
1039 // Remove the device if it isn't in the array
1041 Status
= RejectPciDevice (PciResNode
->PciDev
);
1042 if (Status
== EFI_SUCCESS
) {
1045 "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",
1046 PciResNode
->PciDev
->BusNumber
, PciResNode
->PciDev
->DeviceNumber
, PciResNode
->PciDev
->FunctionNumber
1050 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
1053 // Have no way to get ReqRes, AllocRes & Bar here
1055 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
1056 AllocFailExtendedData
.DevicePathSize
= (UINT16
) sizeof (EFI_DEVICE_PATH_PROTOCOL
);
1057 AllocFailExtendedData
.DevicePath
= (UINT8
*) PciResNode
->PciDev
->DevicePath
;
1058 AllocFailExtendedData
.Bar
= PciResNode
->Bar
;
1060 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1062 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
1063 (VOID
*) &AllocFailExtendedData
,
1064 sizeof (AllocFailExtendedData
)
1068 // Add it to the array and indicate at least a device has been rejected
1070 RemovedPciDev
[RemovedPciDevNum
++] = PciResNode
->PciDev
;
1071 AllocationAjusted
= TRUE
;
1078 if (AllocationAjusted
) {
1086 Summary requests for all resource type, and contruct ACPI resource
1089 @param Bridge detecting bridge
1090 @param IoNode Pointer to instance of I/O resource Node
1091 @param Mem32Node Pointer to instance of 32-bit memory resource Node
1092 @param PMem32Node Pointer to instance of 32-bit Pmemory resource node
1093 @param Mem64Node Pointer to instance of 64-bit memory resource node
1094 @param PMem64Node Pointer to instance of 64-bit Pmemory resource node
1095 @param Config Output buffer holding new constructed APCI resource requestor
1097 @retval EFI_SUCCESS Successfully constructed ACPI resource.
1098 @retval EFI_OUT_OF_RESOURCES No memory availabe.
1102 ConstructAcpiResourceRequestor (
1103 IN PCI_IO_DEVICE
*Bridge
,
1104 IN PCI_RESOURCE_NODE
*IoNode
,
1105 IN PCI_RESOURCE_NODE
*Mem32Node
,
1106 IN PCI_RESOURCE_NODE
*PMem32Node
,
1107 IN PCI_RESOURCE_NODE
*Mem64Node
,
1108 IN PCI_RESOURCE_NODE
*PMem64Node
,
1114 UINT8
*Configuration
;
1115 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1116 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
1124 // if there is io request, add to the io aperture
1126 if (ResourceRequestExisted (IoNode
)) {
1132 // if there is mem32 request, add to the mem32 aperture
1134 if (ResourceRequestExisted (Mem32Node
)) {
1140 // if there is pmem32 request, add to the pmem32 aperture
1142 if (ResourceRequestExisted (PMem32Node
)) {
1148 // if there is mem64 request, add to the mem64 aperture
1150 if (ResourceRequestExisted (Mem64Node
)) {
1156 // if there is pmem64 request, add to the pmem64 aperture
1158 if (ResourceRequestExisted (PMem64Node
)) {
1163 if (NumConfig
!= 0) {
1166 // If there is at least one type of resource request,
1167 // allocate a acpi resource node
1169 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1170 if (Configuration
== NULL
) {
1171 return EFI_OUT_OF_RESOURCES
;
1174 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1177 // Deal with io aperture
1179 if ((Aperture
& 0x01) != 0) {
1180 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1181 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1185 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1189 Ptr
->SpecificFlag
= 1;
1190 Ptr
->AddrLen
= IoNode
->Length
;
1191 Ptr
->AddrRangeMax
= IoNode
->Alignment
;
1196 // Deal with mem32 aperture
1198 if ((Aperture
& 0x02) != 0) {
1199 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1200 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1204 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1208 Ptr
->SpecificFlag
= 0;
1212 Ptr
->AddrSpaceGranularity
= 32;
1213 Ptr
->AddrLen
= Mem32Node
->Length
;
1214 Ptr
->AddrRangeMax
= Mem32Node
->Alignment
;
1220 // Deal with Pmem32 aperture
1222 if ((Aperture
& 0x04) != 0) {
1223 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1224 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1228 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1232 Ptr
->SpecificFlag
= 0x6;
1236 Ptr
->AddrSpaceGranularity
= 32;
1237 Ptr
->AddrLen
= PMem32Node
->Length
;
1238 Ptr
->AddrRangeMax
= PMem32Node
->Alignment
;
1243 // Deal with mem64 aperture
1245 if ((Aperture
& 0x08) != 0) {
1246 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1247 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1251 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1255 Ptr
->SpecificFlag
= 0;
1259 Ptr
->AddrSpaceGranularity
= 64;
1260 Ptr
->AddrLen
= Mem64Node
->Length
;
1261 Ptr
->AddrRangeMax
= Mem64Node
->Alignment
;
1266 // Deal with Pmem64 aperture
1268 if ((Aperture
& 0x10) != 0) {
1269 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1270 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1274 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1278 Ptr
->SpecificFlag
= 0x06;
1282 Ptr
->AddrSpaceGranularity
= 64;
1283 Ptr
->AddrLen
= PMem64Node
->Length
;
1284 Ptr
->AddrRangeMax
= PMem64Node
->Alignment
;
1292 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
;
1294 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1295 PtrEnd
->Checksum
= 0;
1300 // If there is no resource request
1302 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1303 if (Configuration
== NULL
) {
1304 return EFI_OUT_OF_RESOURCES
;
1307 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (Configuration
);
1308 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1310 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Ptr
+ 1);
1311 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1312 PtrEnd
->Checksum
= 0;
1315 *Config
= Configuration
;
1321 Get resource base from an acpi configuration descriptor.
1323 @param Config An acpi configuration descriptor.
1324 @param IoBase Output of I/O resource base address.
1325 @param Mem32Base Output of 32-bit memory base address.
1326 @param PMem32Base Output of 32-bit prefetchable memory base address.
1327 @param Mem64Base Output of 64-bit memory base address.
1328 @param PMem64Base Output of 64-bit prefetchable memory base address.
1335 OUT UINT64
*Mem32Base
,
1336 OUT UINT64
*PMem32Base
,
1337 OUT UINT64
*Mem64Base
,
1338 OUT UINT64
*PMem64Base
1342 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1345 ASSERT (Config
!= NULL
);
1347 *IoBase
= 0xFFFFFFFFFFFFFFFFULL
;
1348 *Mem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1349 *PMem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1350 *Mem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1351 *PMem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1353 Temp
= (UINT8
*) Config
;
1355 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1357 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1358 ResStatus
= Ptr
->AddrTranslationOffset
;
1360 if (ResStatus
== EFI_RESOURCE_SATISFIED
) {
1362 switch (Ptr
->ResType
) {
1365 // Memory type aperture
1370 // Check to see the granularity
1372 if (Ptr
->AddrSpaceGranularity
== 32) {
1373 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1374 *PMem32Base
= Ptr
->AddrRangeMin
;
1376 *Mem32Base
= Ptr
->AddrRangeMin
;
1380 if (Ptr
->AddrSpaceGranularity
== 64) {
1381 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1382 *PMem64Base
= Ptr
->AddrRangeMin
;
1384 *Mem64Base
= Ptr
->AddrRangeMin
;
1394 *IoBase
= Ptr
->AddrRangeMin
;
1408 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1413 Enumerate pci bridge, allocate resource and determine attribute
1414 for devices on this bridge.
1416 @param BridgeDev Pointer to instance of bridge device.
1418 @retval EFI_SUCCESS Successfully enumerated PCI bridge.
1419 @retval other Failed to enumerate.
1423 PciBridgeEnumerator (
1424 IN PCI_IO_DEVICE
*BridgeDev
1428 UINT8 StartBusNumber
;
1429 EFI_PCI_IO_PROTOCOL
*PciIo
;
1434 PciIo
= &(BridgeDev
->PciIo
);
1435 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x19, 1, &StartBusNumber
);
1437 if (EFI_ERROR (Status
)) {
1441 Status
= PciAssignBusNumber (
1447 if (EFI_ERROR (Status
)) {
1451 Status
= PciPciDeviceInfoCollector (BridgeDev
, StartBusNumber
);
1453 if (EFI_ERROR (Status
)) {
1457 Status
= PciBridgeResourceAllocator (BridgeDev
);
1459 if (EFI_ERROR (Status
)) {
1463 Status
= DetermineDeviceAttribute (BridgeDev
);
1465 if (EFI_ERROR (Status
)) {
1474 Allocate all kinds of resource for PCI bridge.
1476 @param Bridge Pointer to bridge instance.
1478 @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
1479 @retval other Failed to allocate resource for bridge.
1483 PciBridgeResourceAllocator (
1484 IN PCI_IO_DEVICE
*Bridge
1487 PCI_RESOURCE_NODE
*IoBridge
;
1488 PCI_RESOURCE_NODE
*Mem32Bridge
;
1489 PCI_RESOURCE_NODE
*PMem32Bridge
;
1490 PCI_RESOURCE_NODE
*Mem64Bridge
;
1491 PCI_RESOURCE_NODE
*PMem64Bridge
;
1499 IoBridge
= CreateResourceNode (
1502 Bridge
->BridgeIoAlignment
,
1508 Mem32Bridge
= CreateResourceNode (
1517 PMem32Bridge
= CreateResourceNode (
1526 Mem64Bridge
= CreateResourceNode (
1535 PMem64Bridge
= CreateResourceNode (
1545 // Create resourcemap by going through all the devices subject to this root bridge
1556 Status
= GetResourceBaseFromBridge (
1565 if (EFI_ERROR (Status
)) {
1570 // Program IO resources
1578 // Program Mem32 resources
1586 // Program PMem32 resources
1594 // Program Mem64 resources
1602 // Program PMem64 resources
1609 DestroyResourceTree (IoBridge
);
1610 DestroyResourceTree (Mem32Bridge
);
1611 DestroyResourceTree (PMem32Bridge
);
1612 DestroyResourceTree (PMem64Bridge
);
1613 DestroyResourceTree (Mem64Bridge
);
1615 gBS
->FreePool (IoBridge
);
1616 gBS
->FreePool (Mem32Bridge
);
1617 gBS
->FreePool (PMem32Bridge
);
1618 gBS
->FreePool (PMem64Bridge
);
1619 gBS
->FreePool (Mem64Bridge
);
1625 Get resource base address for a pci bridge device.
1627 @param Bridge Given Pci driver instance.
1628 @param IoBase Output for base address of I/O type resource.
1629 @param Mem32Base Output for base address of 32-bit memory type resource.
1630 @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
1631 @param Mem64Base Output for base address of 64-bit memory type resource.
1632 @param PMem64Base Output for base address of 64-bit Pmemory type resource.
1634 @retval EFI_SUCCESS Successfully got resource base address.
1635 @retval EFI_OUT_OF_RESOURCES PCI bridge is not available.
1639 GetResourceBaseFromBridge (
1640 IN PCI_IO_DEVICE
*Bridge
,
1642 OUT UINT64
*Mem32Base
,
1643 OUT UINT64
*PMem32Base
,
1644 OUT UINT64
*Mem64Base
,
1645 OUT UINT64
*PMem64Base
1648 if (!Bridge
->Allocated
) {
1649 return EFI_OUT_OF_RESOURCES
;
1653 *Mem32Base
= gAllOne
;
1654 *PMem32Base
= gAllOne
;
1655 *Mem64Base
= gAllOne
;
1656 *PMem64Base
= gAllOne
;
1658 if (IS_PCI_BRIDGE (&Bridge
->Pci
)) {
1660 if (Bridge
->PciBar
[PPB_IO_RANGE
].Length
> 0) {
1661 *IoBase
= Bridge
->PciBar
[PPB_IO_RANGE
].BaseAddress
;
1664 if (Bridge
->PciBar
[PPB_MEM32_RANGE
].Length
> 0) {
1665 *Mem32Base
= Bridge
->PciBar
[PPB_MEM32_RANGE
].BaseAddress
;
1668 if (Bridge
->PciBar
[PPB_PMEM32_RANGE
].Length
> 0) {
1669 *PMem32Base
= Bridge
->PciBar
[PPB_PMEM32_RANGE
].BaseAddress
;
1672 if (Bridge
->PciBar
[PPB_PMEM64_RANGE
].Length
> 0) {
1673 *PMem64Base
= Bridge
->PciBar
[PPB_PMEM64_RANGE
].BaseAddress
;
1675 *PMem64Base
= gAllOne
;
1680 if (IS_CARDBUS_BRIDGE (&Bridge
->Pci
)) {
1681 if (Bridge
->PciBar
[P2C_IO_1
].Length
> 0) {
1682 *IoBase
= Bridge
->PciBar
[P2C_IO_1
].BaseAddress
;
1684 if (Bridge
->PciBar
[P2C_IO_2
].Length
> 0) {
1685 *IoBase
= Bridge
->PciBar
[P2C_IO_2
].BaseAddress
;
1689 if (Bridge
->PciBar
[P2C_MEM_1
].Length
> 0) {
1690 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypePMem32
) {
1691 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1694 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypeMem32
) {
1695 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1699 if (Bridge
->PciBar
[P2C_MEM_2
].Length
> 0) {
1700 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypePMem32
) {
1701 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1704 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypeMem32
) {
1705 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1714 These are the notifications from the PCI bus driver that it is about to enter a certain
1715 phase of the PCI enumeration process.
1717 This member function can be used to notify the host bridge driver to perform specific actions,
1718 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1719 Eight notification points are defined at this time. See belows:
1720 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
1721 structures. The PCI enumerator should issue this notification
1722 before starting a fresh enumeration process. Enumeration cannot
1723 be restarted after sending any other notification such as
1724 EfiPciHostBridgeBeginBusAllocation.
1725 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
1726 required here. This notification can be used to perform any
1727 chipset-specific programming.
1728 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
1729 specific action is required here. This notification can be used to
1730 perform any chipset-specific programming.
1731 EfiPciHostBridgeBeginResourceAllocation
1732 The resource allocation phase is about to begin. No specific
1733 action is required here. This notification can be used to perform
1734 any chipset-specific programming.
1735 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
1736 root bridges. These resource settings are returned on the next call to
1737 GetProposedResources(). Before calling NotifyPhase() with a Phase of
1738 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
1739 for gathering I/O and memory requests for
1740 all the PCI root bridges and submitting these requests using
1741 SubmitResources(). This function pads the resource amount
1742 to suit the root bridge hardware, takes care of dependencies between
1743 the PCI root bridges, and calls the Global Coherency Domain (GCD)
1744 with the allocation request. In the case of padding, the allocated range
1745 could be bigger than what was requested.
1746 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
1747 resources (proposed resources) for all the PCI root bridges. After the
1748 hardware is programmed, reassigning resources will not be supported.
1749 The bus settings are not affected.
1750 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
1751 root bridges and resets the I/O and memory apertures to their initial
1752 state. The bus settings are not affected. If the request to allocate
1753 resources fails, the PCI enumerator can use this notification to
1754 deallocate previous resources, adjust the requests, and retry
1756 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
1757 required here. This notification can be used to perform any chipsetspecific
1760 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1761 @param[in] Phase The phase during enumeration
1763 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
1764 is valid for a Phase of EfiPciHostBridgeAllocateResources if
1765 SubmitResources() has not been called for one or more
1766 PCI root bridges before this call
1767 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
1768 for a Phase of EfiPciHostBridgeSetResources.
1769 @retval EFI_INVALID_PARAMETER Invalid phase parameter
1770 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1771 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1772 previously submitted resource requests cannot be fulfilled or
1773 were only partially fulfilled.
1774 @retval EFI_SUCCESS The notification was accepted without any errors.
1779 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
1780 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1783 EFI_HANDLE HostBridgeHandle
;
1784 EFI_HANDLE RootBridgeHandle
;
1785 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1788 HostBridgeHandle
= NULL
;
1789 RootBridgeHandle
= NULL
;
1790 if (gPciPlatformProtocol
!= NULL
) {
1792 // Get Host Bridge Handle.
1794 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1797 // Get the rootbridge Io protocol to find the host bridge handle
1799 Status
= gBS
->HandleProtocol (
1801 &gEfiPciRootBridgeIoProtocolGuid
,
1802 (VOID
**) &PciRootBridgeIo
1805 if (EFI_ERROR (Status
)) {
1806 return EFI_NOT_FOUND
;
1809 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1812 // Call PlatformPci::PlatformNotify() if the protocol is present.
1814 gPciPlatformProtocol
->PlatformNotify (
1815 gPciPlatformProtocol
,
1820 } else if (gPciOverrideProtocol
!= NULL
){
1822 // Get Host Bridge Handle.
1824 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1827 // Get the rootbridge Io protocol to find the host bridge handle
1829 Status
= gBS
->HandleProtocol (
1831 &gEfiPciRootBridgeIoProtocolGuid
,
1832 (VOID
**) &PciRootBridgeIo
1835 if (EFI_ERROR (Status
)) {
1836 return EFI_NOT_FOUND
;
1839 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1842 // Call PlatformPci::PhaseNotify() if the protocol is present.
1844 gPciOverrideProtocol
->PlatformNotify (
1845 gPciOverrideProtocol
,
1852 Status
= PciResAlloc
->NotifyPhase (
1857 if (gPciPlatformProtocol
!= NULL
) {
1859 // Call PlatformPci::PlatformNotify() if the protocol is present.
1861 gPciPlatformProtocol
->PlatformNotify (
1862 gPciPlatformProtocol
,
1868 } else if (gPciOverrideProtocol
!= NULL
) {
1870 // Call PlatformPci::PhaseNotify() if the protocol is present.
1872 gPciOverrideProtocol
->PlatformNotify (
1873 gPciOverrideProtocol
,
1884 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1885 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1886 PCI controllers before enumeration.
1888 This function is called during the PCI enumeration process. No specific action is expected from this
1889 member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1892 @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1893 @param Bus The bus number of the pci device.
1894 @param Device The device number of the pci device.
1895 @param Func The function number of the pci device.
1896 @param Phase The phase of the PCI device enumeration.
1898 @retval EFI_SUCCESS The requested parameters were returned.
1899 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
1900 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
1901 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1902 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
1903 not enumerate this device, including its child devices if it is a PCI-to-PCI
1908 PreprocessController (
1909 IN PCI_IO_DEVICE
*Bridge
,
1913 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1916 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress
;
1917 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
1918 EFI_HANDLE RootBridgeHandle
;
1919 EFI_HANDLE HostBridgeHandle
;
1923 // Get the host bridge handle
1925 HostBridgeHandle
= Bridge
->PciRootBridgeIo
->ParentHandle
;
1928 // Get the pci host bridge resource allocation protocol
1930 Status
= gBS
->OpenProtocol (
1932 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
1933 (VOID
**) &PciResAlloc
,
1936 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1939 if (EFI_ERROR (Status
)) {
1940 return EFI_UNSUPPORTED
;
1944 // Get Root Brige Handle
1946 while (Bridge
->Parent
!= NULL
) {
1947 Bridge
= Bridge
->Parent
;
1950 RootBridgeHandle
= Bridge
->Handle
;
1952 RootBridgePciAddress
.Register
= 0;
1953 RootBridgePciAddress
.Function
= Func
;
1954 RootBridgePciAddress
.Device
= Device
;
1955 RootBridgePciAddress
.Bus
= Bus
;
1956 RootBridgePciAddress
.ExtendedRegister
= 0;
1958 if (gPciPlatformProtocol
!= NULL
) {
1960 // Call PlatformPci::PrepController() if the protocol is present.
1962 gPciPlatformProtocol
->PlatformPrepController (
1963 gPciPlatformProtocol
,
1966 RootBridgePciAddress
,
1970 } else if (gPciOverrideProtocol
!= NULL
) {
1972 // Call PlatformPci::PrepController() if the protocol is present.
1974 gPciOverrideProtocol
->PlatformPrepController (
1975 gPciOverrideProtocol
,
1978 RootBridgePciAddress
,
1984 Status
= PciResAlloc
->PreprocessController (
1987 RootBridgePciAddress
,
1991 if (gPciPlatformProtocol
!= NULL
) {
1993 // Call PlatformPci::PrepController() if the protocol is present.
1995 gPciPlatformProtocol
->PlatformPrepController (
1996 gPciPlatformProtocol
,
1999 RootBridgePciAddress
,
2003 } else if (gPciOverrideProtocol
!= NULL
) {
2005 // Call PlatformPci::PrepController() if the protocol is present.
2007 gPciOverrideProtocol
->PlatformPrepController (
2008 gPciOverrideProtocol
,
2011 RootBridgePciAddress
,
2021 This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
2022 happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
2024 @param This A pointer to the hot plug request protocol.
2025 @param Operation The operation the PCI bus driver is requested to make.
2026 @param Controller The handle of the hot-plug controller.
2027 @param RemainingDevicePath The remaining device path for the PCI-like hot-plug device.
2028 @param NumberOfChildren The number of child handles.
2029 For a add operation, it is an output parameter.
2030 For a remove operation, it's an input parameter.
2031 @param ChildHandleBuffer The buffer which contains the child handles.
2033 @retval EFI_INVALID_PARAMETER Operation is not a legal value.
2034 Controller is NULL or not a valid handle.
2035 NumberOfChildren is NULL.
2036 ChildHandleBuffer is NULL while Operation is add.
2037 @retval EFI_OUT_OF_RESOURCES There are no enough resources to start the devices.
2038 @retval EFI_NOT_FOUND Can not find bridge according to controller handle.
2039 @retval EFI_SUCCESS The handles for the specified device have been created or destroyed
2040 as requested, and for an add operation, the new handles are
2041 returned in ChildHandleBuffer.
2045 PciHotPlugRequestNotify (
2046 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL
* This
,
2047 IN EFI_PCI_HOTPLUG_OPERATION Operation
,
2048 IN EFI_HANDLE Controller
,
2049 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
,
2050 IN OUT UINT8
*NumberOfChildren
,
2051 IN OUT EFI_HANDLE
* ChildHandleBuffer
2054 PCI_IO_DEVICE
*Bridge
;
2055 PCI_IO_DEVICE
*Temp
;
2056 EFI_PCI_IO_PROTOCOL
*PciIo
;
2058 EFI_HANDLE RootBridgeHandle
;
2062 // Check input parameter validity
2064 if ((Controller
== NULL
) || (NumberOfChildren
== NULL
)){
2065 return EFI_INVALID_PARAMETER
;
2068 if ((Operation
!= EfiPciHotPlugRequestAdd
) && (Operation
!= EfiPciHotplugRequestRemove
)) {
2069 return EFI_INVALID_PARAMETER
;
2072 if (Operation
== EfiPciHotPlugRequestAdd
){
2073 if (ChildHandleBuffer
== NULL
) {
2074 return EFI_INVALID_PARAMETER
;
2076 } else if ((Operation
== EfiPciHotplugRequestRemove
) && (*NumberOfChildren
!= 0)) {
2077 if (ChildHandleBuffer
== NULL
) {
2078 return EFI_INVALID_PARAMETER
;
2082 Status
= gBS
->OpenProtocol (
2084 &gEfiPciIoProtocolGuid
,
2086 gPciBusDriverBinding
.DriverBindingHandle
,
2088 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2091 if (EFI_ERROR (Status
)) {
2092 return EFI_NOT_FOUND
;
2095 Bridge
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
2098 // Get root bridge handle
2101 while (Temp
->Parent
!= NULL
) {
2102 Temp
= Temp
->Parent
;
2105 RootBridgeHandle
= Temp
->Handle
;
2107 if (Operation
== EfiPciHotPlugRequestAdd
) {
2109 // Report Status Code to indicate hot plug happens
2111 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
2113 (EFI_IO_BUS_PCI
| EFI_IOB_PC_HOTPLUG
),
2117 if (NumberOfChildren
!= NULL
) {
2118 *NumberOfChildren
= 0;
2121 if (IsListEmpty (&Bridge
->ChildList
)) {
2123 Status
= PciBridgeEnumerator (Bridge
);
2125 if (EFI_ERROR (Status
)) {
2130 Status
= StartPciDevicesOnBridge (
2133 RemainingDevicePath
,
2141 if (Operation
== EfiPciHotplugRequestRemove
) {
2143 if (*NumberOfChildren
== 0) {
2145 // Remove all devices on the bridge
2147 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Bridge
);
2152 for (Index
= 0; Index
< *NumberOfChildren
; Index
++) {
2154 // De register all the pci device
2156 Status
= DeRegisterPciDevice (RootBridgeHandle
, ChildHandleBuffer
[Index
]);
2158 if (EFI_ERROR (Status
)) {
2173 Search hostbridge according to given handle
2175 @param RootBridgeHandle Host bridge handle.
2177 @retval TRUE Found host bridge handle.
2178 @retval FALSE Not found hot bridge handle.
2182 SearchHostBridgeHandle (
2183 IN EFI_HANDLE RootBridgeHandle
2186 EFI_HANDLE HostBridgeHandle
;
2187 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2192 // Get the rootbridge Io protocol to find the host bridge handle
2194 Status
= gBS
->OpenProtocol (
2196 &gEfiPciRootBridgeIoProtocolGuid
,
2197 (VOID
**) &PciRootBridgeIo
,
2198 gPciBusDriverBinding
.DriverBindingHandle
,
2200 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2203 if (EFI_ERROR (Status
)) {
2207 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
2208 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2209 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2218 Add host bridge handle to global variable for enumerating.
2220 @param HostBridgeHandle Host bridge handle.
2222 @retval EFI_SUCCESS Successfully added host bridge.
2223 @retval EFI_ABORTED Host bridge is NULL, or given host bridge
2224 has been in host bridge list.
2228 AddHostBridgeEnumerator (
2229 IN EFI_HANDLE HostBridgeHandle
2234 if (HostBridgeHandle
== NULL
) {
2238 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2239 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2244 if (Index
< PCI_MAX_HOST_BRIDGE_NUM
) {
2245 gPciHostBrigeHandles
[Index
] = HostBridgeHandle
;
2246 gPciHostBridgeNumber
++;