2 PCI eunmeration implementation on entire PCI bus system for PCI Bus module.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 This routine is used to enumerate entire pci bus system
22 @param Controller Parent controller handle.
23 @param HostBridgeHandle Host bridge handle.
25 @retval EFI_SUCCESS PCI enumeration finished successfully.
26 @retval other Some error occurred when enumerating the pci bus system.
31 IN EFI_HANDLE Controller
,
32 IN EFI_HANDLE HostBridgeHandle
36 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
39 // Get the pci host bridge resource allocation protocol
41 Status
= gBS
->OpenProtocol (
43 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
44 (VOID
**) &PciResAlloc
,
45 gPciBusDriverBinding
.DriverBindingHandle
,
47 EFI_OPEN_PROTOCOL_GET_PROTOCOL
50 if (EFI_ERROR (Status
)) {
55 // Notify the pci bus enumeration is about to begin
57 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginEnumeration
);
59 if (EFI_ERROR (Status
)) {
64 // Start the bus allocation phase
66 Status
= PciHostBridgeEnumerator (PciResAlloc
);
68 if (EFI_ERROR (Status
)) {
73 // Submit the resource request
75 Status
= PciHostBridgeResourceAllocator (PciResAlloc
);
77 if (EFI_ERROR (Status
)) {
82 // Notify the pci bus enumeration is about to complete
84 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndEnumeration
);
86 if (EFI_ERROR (Status
)) {
93 Status
= PciHostBridgeP2CProcess (PciResAlloc
);
95 if (EFI_ERROR (Status
)) {
100 // Process attributes for devices on this host bridge
102 Status
= PciHostBridgeDeviceAttribute (PciResAlloc
);
103 if (EFI_ERROR (Status
)) {
107 Status
= gBS
->InstallProtocolInterface (
109 &gEfiPciEnumerationCompleteProtocolGuid
,
110 EFI_NATIVE_INTERFACE
,
113 if (EFI_ERROR (Status
)) {
121 Enumerate PCI root bridge.
123 @param PciResAlloc Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
124 @param RootBridgeDev Instance of root bridge device.
126 @retval EFI_SUCCESS Successfully enumerated root bridge.
127 @retval other Failed to enumerate root bridge.
131 PciRootBridgeEnumerator (
132 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
133 IN PCI_IO_DEVICE
*RootBridgeDev
137 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
138 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration1
;
139 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration2
;
140 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration3
;
142 UINT8 StartBusNumber
;
143 UINT8 PaddedBusRange
;
144 EFI_HANDLE RootBridgeHandle
;
154 // Get the root bridge handle
156 RootBridgeHandle
= RootBridgeDev
->Handle
;
158 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
160 EFI_IO_BUS_PCI
| EFI_IOB_PCI_BUS_ENUM
,
161 RootBridgeDev
->DevicePath
165 // Get the Bus information
167 Status
= PciResAlloc
->StartBusEnumeration (
170 (VOID
**) &Configuration
173 if (EFI_ERROR (Status
)) {
177 if (Configuration
== NULL
|| Configuration
->Desc
== ACPI_END_TAG_DESCRIPTOR
) {
178 return EFI_INVALID_PARAMETER
;
180 RootBridgeDev
->BusNumberRanges
= Configuration
;
183 // Sort the descriptors in ascending order
185 for (Configuration1
= Configuration
; Configuration1
->Desc
!= ACPI_END_TAG_DESCRIPTOR
; Configuration1
++) {
186 Configuration2
= Configuration1
;
187 for (Configuration3
= Configuration1
+ 1; Configuration3
->Desc
!= ACPI_END_TAG_DESCRIPTOR
; Configuration3
++) {
188 if (Configuration2
->AddrRangeMin
> Configuration3
->AddrRangeMin
) {
189 Configuration2
= Configuration3
;
193 // All other fields other than AddrRangeMin and AddrLen are ignored in a descriptor,
194 // so only need to swap these two fields.
196 if (Configuration2
!= Configuration1
) {
197 AddrRangeMin
= Configuration1
->AddrRangeMin
;
198 Configuration1
->AddrRangeMin
= Configuration2
->AddrRangeMin
;
199 Configuration2
->AddrRangeMin
= AddrRangeMin
;
201 AddrLen
= Configuration1
->AddrLen
;
202 Configuration1
->AddrLen
= Configuration2
->AddrLen
;
203 Configuration2
->AddrLen
= AddrLen
;
208 // Get the bus number to start with
210 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
213 // Initialize the subordinate bus number
215 SubBusNumber
= StartBusNumber
;
218 // Reset all assigned PCI bus number
220 ResetAllPpbBusNumber (
228 Status
= PciScanBus (
235 if (EFI_ERROR (Status
)) {
241 // Assign max bus number scanned
244 Status
= PciAllocateBusNumber (RootBridgeDev
, SubBusNumber
, PaddedBusRange
, &SubBusNumber
);
245 if (EFI_ERROR (Status
)) {
250 // Find the bus range which contains the higest bus number, then returns the number of buses
251 // that should be decoded.
253 while (Configuration
->AddrRangeMin
+ Configuration
->AddrLen
- 1 < SubBusNumber
) {
256 AddrLen
= Configuration
->AddrLen
;
257 Configuration
->AddrLen
= SubBusNumber
- Configuration
->AddrRangeMin
+ 1;
260 // Save the Desc field of the next descriptor. Mark the next descriptor as an END descriptor.
263 Desc
= Configuration
->Desc
;
264 Configuration
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
269 Status
= PciResAlloc
->SetBusNumbers (
272 RootBridgeDev
->BusNumberRanges
276 // Restore changed fields
278 Configuration
->Desc
= Desc
;
279 (Configuration
- 1)->AddrLen
= AddrLen
;
285 This routine is used to process all PCI devices' Option Rom
286 on a certain root bridge.
288 @param Bridge Given parent's root bridge.
289 @param RomBase Base address of ROM driver loaded from.
290 @param MaxLength Maximum rom size.
295 IN PCI_IO_DEVICE
*Bridge
,
300 LIST_ENTRY
*CurrentLink
;
304 // Go through bridges to reach all devices
306 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
307 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
308 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
309 if (!IsListEmpty (&Temp
->ChildList
)) {
312 // Go further to process the option rom under this bridge
314 ProcessOptionRom (Temp
, RomBase
, MaxLength
);
317 if (Temp
->RomSize
!= 0 && Temp
->RomSize
<= MaxLength
) {
320 // Load and process the option rom
322 LoadOpRomImage (Temp
, RomBase
);
325 CurrentLink
= CurrentLink
->ForwardLink
;
330 This routine is used to assign bus number to the given PCI bus system
332 @param Bridge Parent root bridge instance.
333 @param StartBusNumber Number of beginning.
334 @param SubBusNumber The number of sub bus.
336 @retval EFI_SUCCESS Successfully assigned bus number.
337 @retval EFI_DEVICE_ERROR Failed to assign bus number.
342 IN PCI_IO_DEVICE
*Bridge
,
343 IN UINT8 StartBusNumber
,
344 OUT UINT8
*SubBusNumber
355 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
357 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
362 *SubBusNumber
= StartBusNumber
;
365 // First check to see whether the parent is ppb
367 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
368 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
371 // Check to see whether a pci device is present
373 Status
= PciDevicePresent (
381 if (EFI_ERROR (Status
) && Func
== 0) {
383 // go to next device if there is no Function 0
388 if (!EFI_ERROR (Status
) &&
389 (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
392 // Reserved one bus for cardbus bridge
394 Status
= PciAllocateBusNumber (Bridge
, *SubBusNumber
, 1, SubBusNumber
);
395 if (EFI_ERROR (Status
)) {
398 SecondBus
= *SubBusNumber
;
400 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
402 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
404 Status
= PciRootBridgeIo
->Pci
.Write (
413 // Initialize SubBusNumber to SecondBus
415 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
416 Status
= PciRootBridgeIo
->Pci
.Write (
424 // If it is PPB, resursively search down this bridge
426 if (IS_PCI_BRIDGE (&Pci
)) {
429 Status
= PciRootBridgeIo
->Pci
.Write (
437 Status
= PciAssignBusNumber (
443 if (EFI_ERROR (Status
)) {
444 return EFI_DEVICE_ERROR
;
449 // Set the current maximum bus number under the PPB
451 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
453 Status
= PciRootBridgeIo
->Pci
.Write (
463 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
466 // Skip sub functions, this is not a multi function device
477 This routine is used to determine the root bridge attribute by interfacing
478 the host bridge resource allocation protocol.
480 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
481 @param RootBridgeDev Root bridge instance
483 @retval EFI_SUCCESS Successfully got root bridge's attribute.
484 @retval other Failed to get attribute.
488 DetermineRootBridgeAttributes (
489 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
490 IN PCI_IO_DEVICE
*RootBridgeDev
495 EFI_HANDLE RootBridgeHandle
;
498 RootBridgeHandle
= RootBridgeDev
->Handle
;
501 // Get root bridge attribute by calling into pci host bridge resource allocation protocol
503 Status
= PciResAlloc
->GetAllocAttributes (
509 if (EFI_ERROR (Status
)) {
514 // Here is the point where PCI bus driver calls HOST bridge allocation protocol
515 // Currently we hardcoded for ea815
517 if ((Attributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) {
518 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
;
521 if ((Attributes
& EFI_PCI_HOST_BRIDGE_MEM64_DECODE
) != 0) {
522 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM64_DECODE_SUPPORTED
;
523 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
526 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
527 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
528 RootBridgeDev
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
534 Get Max Option Rom size on specified bridge.
536 @param Bridge Given bridge device instance.
538 @return Max size of option rom needed.
542 GetMaxOptionRomSize (
543 IN PCI_IO_DEVICE
*Bridge
546 LIST_ENTRY
*CurrentLink
;
548 UINT64 MaxOptionRomSize
;
549 UINT64 TempOptionRomSize
;
551 MaxOptionRomSize
= 0;
554 // Go through bridges to reach all devices
556 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
557 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
558 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
559 if (!IsListEmpty (&Temp
->ChildList
)) {
562 // Get max option rom size under this bridge
564 TempOptionRomSize
= GetMaxOptionRomSize (Temp
);
567 // Compare with the option rom size of the bridge
568 // Get the larger one
570 if (Temp
->RomSize
> TempOptionRomSize
) {
571 TempOptionRomSize
= Temp
->RomSize
;
577 // For devices get the rom size directly
579 TempOptionRomSize
= Temp
->RomSize
;
583 // Get the largest rom size on this bridge
585 if (TempOptionRomSize
> MaxOptionRomSize
) {
586 MaxOptionRomSize
= TempOptionRomSize
;
589 CurrentLink
= CurrentLink
->ForwardLink
;
592 return MaxOptionRomSize
;
596 Process attributes of devices on this host bridge
598 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
600 @retval EFI_SUCCESS Successfully process attribute.
601 @retval EFI_NOT_FOUND Can not find the specific root bridge device.
602 @retval other Failed to determine the root bridge device's attribute.
606 PciHostBridgeDeviceAttribute (
607 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
610 EFI_HANDLE RootBridgeHandle
;
611 PCI_IO_DEVICE
*RootBridgeDev
;
614 RootBridgeHandle
= NULL
;
616 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
619 // Get RootBridg Device by handle
621 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
623 if (RootBridgeDev
== NULL
) {
624 return EFI_NOT_FOUND
;
628 // Set the attributes for devcies behind the Root Bridge
630 Status
= DetermineDeviceAttribute (RootBridgeDev
);
631 if (EFI_ERROR (Status
)) {
641 Get resource allocation status from the ACPI resource descriptor.
643 @param AcpiConfig Point to Acpi configuration table.
644 @param IoResStatus Return the status of I/O resource.
645 @param Mem32ResStatus Return the status of 32-bit Memory resource.
646 @param PMem32ResStatus Return the status of 32-bit Prefetchable Memory resource.
647 @param Mem64ResStatus Return the status of 64-bit Memory resource.
648 @param PMem64ResStatus Return the status of 64-bit Prefetchable Memory resource.
652 GetResourceAllocationStatus (
654 OUT UINT64
*IoResStatus
,
655 OUT UINT64
*Mem32ResStatus
,
656 OUT UINT64
*PMem32ResStatus
,
657 OUT UINT64
*Mem64ResStatus
,
658 OUT UINT64
*PMem64ResStatus
663 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*ACPIAddressDesc
;
665 Temp
= (UINT8
*) AcpiConfig
;
667 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
669 ACPIAddressDesc
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
670 ResStatus
= ACPIAddressDesc
->AddrTranslationOffset
;
672 switch (ACPIAddressDesc
->ResType
) {
674 if (ACPIAddressDesc
->AddrSpaceGranularity
== 32) {
675 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
679 *PMem32ResStatus
= ResStatus
;
684 *Mem32ResStatus
= ResStatus
;
688 if (ACPIAddressDesc
->AddrSpaceGranularity
== 64) {
689 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
693 *PMem64ResStatus
= ResStatus
;
698 *Mem64ResStatus
= ResStatus
;
708 *IoResStatus
= ResStatus
;
715 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
720 Remove a PCI device from device pool and mark its bar.
722 @param PciDevice Instance of Pci device.
724 @retval EFI_SUCCESS Successfully remove the PCI device.
725 @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
730 IN PCI_IO_DEVICE
*PciDevice
733 PCI_IO_DEVICE
*Bridge
;
735 LIST_ENTRY
*CurrentLink
;
738 // Remove the padding resource from a bridge
740 if ( IS_PCI_BRIDGE(&PciDevice
->Pci
) &&
741 PciDevice
->ResourcePaddingDescriptors
!= NULL
) {
742 FreePool (PciDevice
->ResourcePaddingDescriptors
);
743 PciDevice
->ResourcePaddingDescriptors
= NULL
;
750 if (IS_PCI_BRIDGE (&PciDevice
->Pci
) || (PciDevice
->Parent
== NULL
)) {
754 if (IS_CARDBUS_BRIDGE (&PciDevice
->Pci
)) {
756 // Get the root bridge device
759 while (Bridge
->Parent
!= NULL
) {
760 Bridge
= Bridge
->Parent
;
763 RemoveAllPciDeviceOnBridge (Bridge
->Handle
, PciDevice
);
768 InitializeP2C (PciDevice
);
774 Bridge
= PciDevice
->Parent
;
775 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
776 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
777 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
778 if (Temp
== PciDevice
) {
779 InitializePciDevice (Temp
);
780 RemoveEntryList (CurrentLink
);
784 CurrentLink
= CurrentLink
->ForwardLink
;
791 Determine whethter a PCI device can be rejected.
793 @param PciResNode Pointer to Pci resource node instance.
795 @retval TRUE The PCI device can be rejected.
796 @retval TRUE The PCI device cannot be rejected.
801 IN PCI_RESOURCE_NODE
*PciResNode
806 Temp
= PciResNode
->PciDev
;
809 // Ensure the device is present
816 // PPB and RB should go ahead
818 if (IS_PCI_BRIDGE (&Temp
->Pci
) || (Temp
->Parent
== NULL
)) {
823 // Skip device on Bus0
825 if ((Temp
->Parent
!= NULL
) && (Temp
->BusNumber
== 0)) {
832 if (IS_PCI_VGA (&Temp
->Pci
)) {
840 Compare two resource nodes and get the larger resource consumer.
842 @param PciResNode1 resource node 1 want to be compared
843 @param PciResNode2 resource node 2 want to be compared
845 @return Larger resource node.
849 GetLargerConsumerDevice (
850 IN PCI_RESOURCE_NODE
*PciResNode1
,
851 IN PCI_RESOURCE_NODE
*PciResNode2
854 if (PciResNode2
== NULL
) {
858 if ((IS_PCI_BRIDGE(&(PciResNode2
->PciDev
->Pci
)) || (PciResNode2
->PciDev
->Parent
== NULL
)) \
859 && (PciResNode2
->ResourceUsage
!= PciResUsagePadding
) )
864 if (PciResNode1
== NULL
) {
868 if ((PciResNode1
->Length
) > (PciResNode2
->Length
)) {
877 Get the max resource consumer in the host resource pool.
879 @param ResPool Pointer to resource pool node.
881 @return The max resource consumer in the host resource pool.
885 GetMaxResourceConsumerDevice (
886 IN PCI_RESOURCE_NODE
*ResPool
889 PCI_RESOURCE_NODE
*Temp
;
890 LIST_ENTRY
*CurrentLink
;
891 PCI_RESOURCE_NODE
*PciResNode
;
892 PCI_RESOURCE_NODE
*PPBResNode
;
896 CurrentLink
= ResPool
->ChildList
.ForwardLink
;
897 while (CurrentLink
!= NULL
&& CurrentLink
!= &ResPool
->ChildList
) {
899 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
901 if (!IsRejectiveDevice (Temp
)) {
902 CurrentLink
= CurrentLink
->ForwardLink
;
906 if ((IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
)) || (Temp
->PciDev
->Parent
== NULL
)) \
907 && (Temp
->ResourceUsage
!= PciResUsagePadding
))
909 PPBResNode
= GetMaxResourceConsumerDevice (Temp
);
910 PciResNode
= GetLargerConsumerDevice (PciResNode
, PPBResNode
);
912 PciResNode
= GetLargerConsumerDevice (PciResNode
, Temp
);
915 CurrentLink
= CurrentLink
->ForwardLink
;
922 Adjust host bridge allocation so as to reduce resource requirement
924 @param IoPool Pointer to instance of I/O resource Node.
925 @param Mem32Pool Pointer to instance of 32-bit memory resource Node.
926 @param PMem32Pool Pointer to instance of 32-bit Prefetchable memory resource node.
927 @param Mem64Pool Pointer to instance of 64-bit memory resource node.
928 @param PMem64Pool Pointer to instance of 64-bit Prefetchable memory resource node.
929 @param IoResStatus Status of I/O resource Node.
930 @param Mem32ResStatus Status of 32-bit memory resource Node.
931 @param PMem32ResStatus Status of 32-bit Prefetchable memory resource node.
932 @param Mem64ResStatus Status of 64-bit memory resource node.
933 @param PMem64ResStatus Status of 64-bit Prefetchable memory resource node.
935 @retval EFI_SUCCESS Successfully adjusted resource on host bridge.
936 @retval EFI_ABORTED Host bridge hasn't this resource type or no resource be adjusted.
940 PciHostBridgeAdjustAllocation (
941 IN PCI_RESOURCE_NODE
*IoPool
,
942 IN PCI_RESOURCE_NODE
*Mem32Pool
,
943 IN PCI_RESOURCE_NODE
*PMem32Pool
,
944 IN PCI_RESOURCE_NODE
*Mem64Pool
,
945 IN PCI_RESOURCE_NODE
*PMem64Pool
,
946 IN UINT64 IoResStatus
,
947 IN UINT64 Mem32ResStatus
,
948 IN UINT64 PMem32ResStatus
,
949 IN UINT64 Mem64ResStatus
,
950 IN UINT64 PMem64ResStatus
953 BOOLEAN AllocationAjusted
;
954 PCI_RESOURCE_NODE
*PciResNode
;
955 PCI_RESOURCE_NODE
*ResPool
[5];
956 PCI_IO_DEVICE
*RemovedPciDev
[5];
958 UINTN RemovedPciDevNum
;
962 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
965 ZeroMem (RemovedPciDev
, 5 * sizeof (PCI_IO_DEVICE
*));
966 RemovedPciDevNum
= 0;
969 ResPool
[1] = Mem32Pool
;
970 ResPool
[2] = PMem32Pool
;
971 ResPool
[3] = Mem64Pool
;
972 ResPool
[4] = PMem64Pool
;
974 ResStatus
[0] = IoResStatus
;
975 ResStatus
[1] = Mem32ResStatus
;
976 ResStatus
[2] = PMem32ResStatus
;
977 ResStatus
[3] = Mem64ResStatus
;
978 ResStatus
[4] = PMem64ResStatus
;
980 AllocationAjusted
= FALSE
;
982 for (ResType
= 0; ResType
< 5; ResType
++) {
984 if (ResStatus
[ResType
] == EFI_RESOURCE_SATISFIED
) {
988 if (ResStatus
[ResType
] == EFI_RESOURCE_NOT_SATISFIED
) {
990 // Host bridge hasn't this resource type
996 // Hostbridge hasn't enough resource
998 PciResNode
= GetMaxResourceConsumerDevice (ResPool
[ResType
]);
999 if (PciResNode
== NULL
) {
1004 // Check if the device has been removed before
1006 for (DevIndex
= 0; DevIndex
< RemovedPciDevNum
; DevIndex
++) {
1007 if (PciResNode
->PciDev
== RemovedPciDev
[DevIndex
]) {
1012 if (DevIndex
!= RemovedPciDevNum
) {
1017 // Remove the device if it isn't in the array
1019 Status
= RejectPciDevice (PciResNode
->PciDev
);
1020 if (Status
== EFI_SUCCESS
) {
1023 "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",
1024 PciResNode
->PciDev
->BusNumber
, PciResNode
->PciDev
->DeviceNumber
, PciResNode
->PciDev
->FunctionNumber
1028 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
1031 // Have no way to get ReqRes, AllocRes & Bar here
1033 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
1034 AllocFailExtendedData
.DevicePathSize
= (UINT16
) sizeof (EFI_DEVICE_PATH_PROTOCOL
);
1035 AllocFailExtendedData
.DevicePath
= (UINT8
*) PciResNode
->PciDev
->DevicePath
;
1036 AllocFailExtendedData
.Bar
= PciResNode
->Bar
;
1038 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1040 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
1041 (VOID
*) &AllocFailExtendedData
,
1042 sizeof (AllocFailExtendedData
)
1046 // Add it to the array and indicate at least a device has been rejected
1048 RemovedPciDev
[RemovedPciDevNum
++] = PciResNode
->PciDev
;
1049 AllocationAjusted
= TRUE
;
1056 if (AllocationAjusted
) {
1064 Summary requests for all resource type, and construct ACPI resource
1067 @param Bridge detecting bridge
1068 @param IoNode Pointer to instance of I/O resource Node
1069 @param Mem32Node Pointer to instance of 32-bit memory resource Node
1070 @param PMem32Node Pointer to instance of 32-bit Pmemory resource node
1071 @param Mem64Node Pointer to instance of 64-bit memory resource node
1072 @param PMem64Node Pointer to instance of 64-bit Pmemory resource node
1073 @param Config Output buffer holding new constructed APCI resource requestor
1075 @retval EFI_SUCCESS Successfully constructed ACPI resource.
1076 @retval EFI_OUT_OF_RESOURCES No memory available.
1080 ConstructAcpiResourceRequestor (
1081 IN PCI_IO_DEVICE
*Bridge
,
1082 IN PCI_RESOURCE_NODE
*IoNode
,
1083 IN PCI_RESOURCE_NODE
*Mem32Node
,
1084 IN PCI_RESOURCE_NODE
*PMem32Node
,
1085 IN PCI_RESOURCE_NODE
*Mem64Node
,
1086 IN PCI_RESOURCE_NODE
*PMem64Node
,
1092 UINT8
*Configuration
;
1093 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1094 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
1102 // if there is io request, add to the io aperture
1104 if (ResourceRequestExisted (IoNode
)) {
1110 // if there is mem32 request, add to the mem32 aperture
1112 if (ResourceRequestExisted (Mem32Node
)) {
1118 // if there is pmem32 request, add to the pmem32 aperture
1120 if (ResourceRequestExisted (PMem32Node
)) {
1126 // if there is mem64 request, add to the mem64 aperture
1128 if (ResourceRequestExisted (Mem64Node
)) {
1134 // if there is pmem64 request, add to the pmem64 aperture
1136 if (ResourceRequestExisted (PMem64Node
)) {
1141 if (NumConfig
!= 0) {
1144 // If there is at least one type of resource request,
1145 // allocate a acpi resource node
1147 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1148 if (Configuration
== NULL
) {
1149 return EFI_OUT_OF_RESOURCES
;
1152 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1155 // Deal with io aperture
1157 if ((Aperture
& 0x01) != 0) {
1158 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1159 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1163 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1167 Ptr
->SpecificFlag
= 1;
1168 Ptr
->AddrLen
= IoNode
->Length
;
1169 Ptr
->AddrRangeMax
= IoNode
->Alignment
;
1174 // Deal with mem32 aperture
1176 if ((Aperture
& 0x02) != 0) {
1177 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1178 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1182 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1186 Ptr
->SpecificFlag
= 0;
1190 Ptr
->AddrSpaceGranularity
= 32;
1191 Ptr
->AddrLen
= Mem32Node
->Length
;
1192 Ptr
->AddrRangeMax
= Mem32Node
->Alignment
;
1198 // Deal with Pmem32 aperture
1200 if ((Aperture
& 0x04) != 0) {
1201 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1202 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1206 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1210 Ptr
->SpecificFlag
= 0x6;
1214 Ptr
->AddrSpaceGranularity
= 32;
1215 Ptr
->AddrLen
= PMem32Node
->Length
;
1216 Ptr
->AddrRangeMax
= PMem32Node
->Alignment
;
1221 // Deal with mem64 aperture
1223 if ((Aperture
& 0x08) != 0) {
1224 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1225 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1229 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1233 Ptr
->SpecificFlag
= 0;
1237 Ptr
->AddrSpaceGranularity
= 64;
1238 Ptr
->AddrLen
= Mem64Node
->Length
;
1239 Ptr
->AddrRangeMax
= Mem64Node
->Alignment
;
1244 // Deal with Pmem64 aperture
1246 if ((Aperture
& 0x10) != 0) {
1247 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1248 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1252 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1256 Ptr
->SpecificFlag
= 0x06;
1260 Ptr
->AddrSpaceGranularity
= 64;
1261 Ptr
->AddrLen
= PMem64Node
->Length
;
1262 Ptr
->AddrRangeMax
= PMem64Node
->Alignment
;
1270 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
;
1272 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1273 PtrEnd
->Checksum
= 0;
1278 // If there is no resource request
1280 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1281 if (Configuration
== NULL
) {
1282 return EFI_OUT_OF_RESOURCES
;
1285 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Configuration
);
1286 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1287 PtrEnd
->Checksum
= 0;
1290 *Config
= Configuration
;
1296 Get resource base from an acpi configuration descriptor.
1298 @param Config An acpi configuration descriptor.
1299 @param IoBase Output of I/O resource base address.
1300 @param Mem32Base Output of 32-bit memory base address.
1301 @param PMem32Base Output of 32-bit prefetchable memory base address.
1302 @param Mem64Base Output of 64-bit memory base address.
1303 @param PMem64Base Output of 64-bit prefetchable memory base address.
1310 OUT UINT64
*Mem32Base
,
1311 OUT UINT64
*PMem32Base
,
1312 OUT UINT64
*Mem64Base
,
1313 OUT UINT64
*PMem64Base
1317 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1320 ASSERT (Config
!= NULL
);
1322 *IoBase
= 0xFFFFFFFFFFFFFFFFULL
;
1323 *Mem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1324 *PMem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1325 *Mem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1326 *PMem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1328 Temp
= (UINT8
*) Config
;
1330 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1332 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1333 ResStatus
= Ptr
->AddrTranslationOffset
;
1335 if (ResStatus
== EFI_RESOURCE_SATISFIED
) {
1337 switch (Ptr
->ResType
) {
1340 // Memory type aperture
1345 // Check to see the granularity
1347 if (Ptr
->AddrSpaceGranularity
== 32) {
1348 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1349 *PMem32Base
= Ptr
->AddrRangeMin
;
1351 *Mem32Base
= Ptr
->AddrRangeMin
;
1355 if (Ptr
->AddrSpaceGranularity
== 64) {
1356 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1357 *PMem64Base
= Ptr
->AddrRangeMin
;
1359 *Mem64Base
= Ptr
->AddrRangeMin
;
1369 *IoBase
= Ptr
->AddrRangeMin
;
1383 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1388 Enumerate pci bridge, allocate resource and determine attribute
1389 for devices on this bridge.
1391 @param BridgeDev Pointer to instance of bridge device.
1393 @retval EFI_SUCCESS Successfully enumerated PCI bridge.
1394 @retval other Failed to enumerate.
1398 PciBridgeEnumerator (
1399 IN PCI_IO_DEVICE
*BridgeDev
1403 UINT8 StartBusNumber
;
1404 EFI_PCI_IO_PROTOCOL
*PciIo
;
1409 PciIo
= &(BridgeDev
->PciIo
);
1410 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x19, 1, &StartBusNumber
);
1412 if (EFI_ERROR (Status
)) {
1416 Status
= PciAssignBusNumber (
1422 if (EFI_ERROR (Status
)) {
1426 Status
= PciPciDeviceInfoCollector (BridgeDev
, StartBusNumber
);
1428 if (EFI_ERROR (Status
)) {
1432 Status
= PciBridgeResourceAllocator (BridgeDev
);
1434 if (EFI_ERROR (Status
)) {
1438 Status
= DetermineDeviceAttribute (BridgeDev
);
1440 if (EFI_ERROR (Status
)) {
1449 Allocate all kinds of resource for PCI bridge.
1451 @param Bridge Pointer to bridge instance.
1453 @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
1454 @retval other Failed to allocate resource for bridge.
1458 PciBridgeResourceAllocator (
1459 IN PCI_IO_DEVICE
*Bridge
1462 PCI_RESOURCE_NODE
*IoBridge
;
1463 PCI_RESOURCE_NODE
*Mem32Bridge
;
1464 PCI_RESOURCE_NODE
*PMem32Bridge
;
1465 PCI_RESOURCE_NODE
*Mem64Bridge
;
1466 PCI_RESOURCE_NODE
*PMem64Bridge
;
1474 IoBridge
= CreateResourceNode (
1477 Bridge
->BridgeIoAlignment
,
1483 Mem32Bridge
= CreateResourceNode (
1492 PMem32Bridge
= CreateResourceNode (
1501 Mem64Bridge
= CreateResourceNode (
1510 PMem64Bridge
= CreateResourceNode (
1520 // Create resourcemap by going through all the devices subject to this root bridge
1531 Status
= GetResourceBaseFromBridge (
1540 if (EFI_ERROR (Status
)) {
1545 // Program IO resources
1553 // Program Mem32 resources
1561 // Program PMem32 resources
1569 // Program Mem64 resources
1577 // Program PMem64 resources
1584 DestroyResourceTree (IoBridge
);
1585 DestroyResourceTree (Mem32Bridge
);
1586 DestroyResourceTree (PMem32Bridge
);
1587 DestroyResourceTree (PMem64Bridge
);
1588 DestroyResourceTree (Mem64Bridge
);
1590 gBS
->FreePool (IoBridge
);
1591 gBS
->FreePool (Mem32Bridge
);
1592 gBS
->FreePool (PMem32Bridge
);
1593 gBS
->FreePool (PMem64Bridge
);
1594 gBS
->FreePool (Mem64Bridge
);
1600 Get resource base address for a pci bridge device.
1602 @param Bridge Given Pci driver instance.
1603 @param IoBase Output for base address of I/O type resource.
1604 @param Mem32Base Output for base address of 32-bit memory type resource.
1605 @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
1606 @param Mem64Base Output for base address of 64-bit memory type resource.
1607 @param PMem64Base Output for base address of 64-bit Pmemory type resource.
1609 @retval EFI_SUCCESS Successfully got resource base address.
1610 @retval EFI_OUT_OF_RESOURCES PCI bridge is not available.
1614 GetResourceBaseFromBridge (
1615 IN PCI_IO_DEVICE
*Bridge
,
1617 OUT UINT64
*Mem32Base
,
1618 OUT UINT64
*PMem32Base
,
1619 OUT UINT64
*Mem64Base
,
1620 OUT UINT64
*PMem64Base
1623 if (!Bridge
->Allocated
) {
1624 return EFI_OUT_OF_RESOURCES
;
1628 *Mem32Base
= gAllOne
;
1629 *PMem32Base
= gAllOne
;
1630 *Mem64Base
= gAllOne
;
1631 *PMem64Base
= gAllOne
;
1633 if (IS_PCI_BRIDGE (&Bridge
->Pci
)) {
1635 if (Bridge
->PciBar
[PPB_IO_RANGE
].Length
> 0) {
1636 *IoBase
= Bridge
->PciBar
[PPB_IO_RANGE
].BaseAddress
;
1639 if (Bridge
->PciBar
[PPB_MEM32_RANGE
].Length
> 0) {
1640 *Mem32Base
= Bridge
->PciBar
[PPB_MEM32_RANGE
].BaseAddress
;
1643 if (Bridge
->PciBar
[PPB_PMEM32_RANGE
].Length
> 0) {
1644 *PMem32Base
= Bridge
->PciBar
[PPB_PMEM32_RANGE
].BaseAddress
;
1647 if (Bridge
->PciBar
[PPB_PMEM64_RANGE
].Length
> 0) {
1648 *PMem64Base
= Bridge
->PciBar
[PPB_PMEM64_RANGE
].BaseAddress
;
1650 *PMem64Base
= gAllOne
;
1655 if (IS_CARDBUS_BRIDGE (&Bridge
->Pci
)) {
1656 if (Bridge
->PciBar
[P2C_IO_1
].Length
> 0) {
1657 *IoBase
= Bridge
->PciBar
[P2C_IO_1
].BaseAddress
;
1659 if (Bridge
->PciBar
[P2C_IO_2
].Length
> 0) {
1660 *IoBase
= Bridge
->PciBar
[P2C_IO_2
].BaseAddress
;
1664 if (Bridge
->PciBar
[P2C_MEM_1
].Length
> 0) {
1665 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypePMem32
) {
1666 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1669 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypeMem32
) {
1670 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1674 if (Bridge
->PciBar
[P2C_MEM_2
].Length
> 0) {
1675 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypePMem32
) {
1676 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1679 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypeMem32
) {
1680 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1689 These are the notifications from the PCI bus driver that it is about to enter a certain
1690 phase of the PCI enumeration process.
1692 This member function can be used to notify the host bridge driver to perform specific actions,
1693 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1694 Eight notification points are defined at this time. See belows:
1695 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
1696 structures. The PCI enumerator should issue this notification
1697 before starting a fresh enumeration process. Enumeration cannot
1698 be restarted after sending any other notification such as
1699 EfiPciHostBridgeBeginBusAllocation.
1700 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
1701 required here. This notification can be used to perform any
1702 chipset-specific programming.
1703 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
1704 specific action is required here. This notification can be used to
1705 perform any chipset-specific programming.
1706 EfiPciHostBridgeBeginResourceAllocation
1707 The resource allocation phase is about to begin. No specific
1708 action is required here. This notification can be used to perform
1709 any chipset-specific programming.
1710 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
1711 root bridges. These resource settings are returned on the next call to
1712 GetProposedResources(). Before calling NotifyPhase() with a Phase of
1713 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
1714 for gathering I/O and memory requests for
1715 all the PCI root bridges and submitting these requests using
1716 SubmitResources(). This function pads the resource amount
1717 to suit the root bridge hardware, takes care of dependencies between
1718 the PCI root bridges, and calls the Global Coherency Domain (GCD)
1719 with the allocation request. In the case of padding, the allocated range
1720 could be bigger than what was requested.
1721 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
1722 resources (proposed resources) for all the PCI root bridges. After the
1723 hardware is programmed, reassigning resources will not be supported.
1724 The bus settings are not affected.
1725 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
1726 root bridges and resets the I/O and memory apertures to their initial
1727 state. The bus settings are not affected. If the request to allocate
1728 resources fails, the PCI enumerator can use this notification to
1729 deallocate previous resources, adjust the requests, and retry
1731 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
1732 required here. This notification can be used to perform any chipsetspecific
1735 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1736 @param[in] Phase The phase during enumeration
1738 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
1739 is valid for a Phase of EfiPciHostBridgeAllocateResources if
1740 SubmitResources() has not been called for one or more
1741 PCI root bridges before this call
1742 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
1743 for a Phase of EfiPciHostBridgeSetResources.
1744 @retval EFI_INVALID_PARAMETER Invalid phase parameter
1745 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1746 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1747 previously submitted resource requests cannot be fulfilled or
1748 were only partially fulfilled.
1749 @retval EFI_SUCCESS The notification was accepted without any errors.
1754 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
1755 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1758 EFI_HANDLE HostBridgeHandle
;
1759 EFI_HANDLE RootBridgeHandle
;
1760 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1763 HostBridgeHandle
= NULL
;
1764 RootBridgeHandle
= NULL
;
1765 if (gPciPlatformProtocol
!= NULL
) {
1767 // Get Host Bridge Handle.
1769 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1772 // Get the rootbridge Io protocol to find the host bridge handle
1774 Status
= gBS
->HandleProtocol (
1776 &gEfiPciRootBridgeIoProtocolGuid
,
1777 (VOID
**) &PciRootBridgeIo
1780 if (EFI_ERROR (Status
)) {
1781 return EFI_NOT_FOUND
;
1784 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1787 // Call PlatformPci::PlatformNotify() if the protocol is present.
1789 gPciPlatformProtocol
->PlatformNotify (
1790 gPciPlatformProtocol
,
1795 } else if (gPciOverrideProtocol
!= NULL
){
1797 // Get Host Bridge Handle.
1799 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1802 // Get the rootbridge Io protocol to find the host bridge handle
1804 Status
= gBS
->HandleProtocol (
1806 &gEfiPciRootBridgeIoProtocolGuid
,
1807 (VOID
**) &PciRootBridgeIo
1810 if (EFI_ERROR (Status
)) {
1811 return EFI_NOT_FOUND
;
1814 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1817 // Call PlatformPci::PhaseNotify() if the protocol is present.
1819 gPciOverrideProtocol
->PlatformNotify (
1820 gPciOverrideProtocol
,
1827 Status
= PciResAlloc
->NotifyPhase (
1832 if (gPciPlatformProtocol
!= NULL
) {
1834 // Call PlatformPci::PlatformNotify() if the protocol is present.
1836 gPciPlatformProtocol
->PlatformNotify (
1837 gPciPlatformProtocol
,
1843 } else if (gPciOverrideProtocol
!= NULL
) {
1845 // Call PlatformPci::PhaseNotify() if the protocol is present.
1847 gPciOverrideProtocol
->PlatformNotify (
1848 gPciOverrideProtocol
,
1859 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1860 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1861 PCI controllers before enumeration.
1863 This function is called during the PCI enumeration process. No specific action is expected from this
1864 member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1867 @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1868 @param Bus The bus number of the pci device.
1869 @param Device The device number of the pci device.
1870 @param Func The function number of the pci device.
1871 @param Phase The phase of the PCI device enumeration.
1873 @retval EFI_SUCCESS The requested parameters were returned.
1874 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
1875 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
1876 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1877 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
1878 not enumerate this device, including its child devices if it is a PCI-to-PCI
1883 PreprocessController (
1884 IN PCI_IO_DEVICE
*Bridge
,
1888 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1891 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress
;
1892 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
1893 EFI_HANDLE RootBridgeHandle
;
1894 EFI_HANDLE HostBridgeHandle
;
1898 // Get the host bridge handle
1900 HostBridgeHandle
= Bridge
->PciRootBridgeIo
->ParentHandle
;
1903 // Get the pci host bridge resource allocation protocol
1905 Status
= gBS
->OpenProtocol (
1907 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
1908 (VOID
**) &PciResAlloc
,
1911 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1914 if (EFI_ERROR (Status
)) {
1915 return EFI_UNSUPPORTED
;
1919 // Get Root Brige Handle
1921 while (Bridge
->Parent
!= NULL
) {
1922 Bridge
= Bridge
->Parent
;
1925 RootBridgeHandle
= Bridge
->Handle
;
1927 RootBridgePciAddress
.Register
= 0;
1928 RootBridgePciAddress
.Function
= Func
;
1929 RootBridgePciAddress
.Device
= Device
;
1930 RootBridgePciAddress
.Bus
= Bus
;
1931 RootBridgePciAddress
.ExtendedRegister
= 0;
1933 if (gPciPlatformProtocol
!= NULL
) {
1935 // Call PlatformPci::PrepController() if the protocol is present.
1937 gPciPlatformProtocol
->PlatformPrepController (
1938 gPciPlatformProtocol
,
1941 RootBridgePciAddress
,
1945 } else if (gPciOverrideProtocol
!= NULL
) {
1947 // Call PlatformPci::PrepController() if the protocol is present.
1949 gPciOverrideProtocol
->PlatformPrepController (
1950 gPciOverrideProtocol
,
1953 RootBridgePciAddress
,
1959 Status
= PciResAlloc
->PreprocessController (
1962 RootBridgePciAddress
,
1966 if (gPciPlatformProtocol
!= NULL
) {
1968 // Call PlatformPci::PrepController() if the protocol is present.
1970 gPciPlatformProtocol
->PlatformPrepController (
1971 gPciPlatformProtocol
,
1974 RootBridgePciAddress
,
1978 } else if (gPciOverrideProtocol
!= NULL
) {
1980 // Call PlatformPci::PrepController() if the protocol is present.
1982 gPciOverrideProtocol
->PlatformPrepController (
1983 gPciOverrideProtocol
,
1986 RootBridgePciAddress
,
1996 This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
1997 happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
1999 @param This A pointer to the hot plug request protocol.
2000 @param Operation The operation the PCI bus driver is requested to make.
2001 @param Controller The handle of the hot-plug controller.
2002 @param RemainingDevicePath The remaining device path for the PCI-like hot-plug device.
2003 @param NumberOfChildren The number of child handles.
2004 For a add operation, it is an output parameter.
2005 For a remove operation, it's an input parameter.
2006 @param ChildHandleBuffer The buffer which contains the child handles.
2008 @retval EFI_INVALID_PARAMETER Operation is not a legal value.
2009 Controller is NULL or not a valid handle.
2010 NumberOfChildren is NULL.
2011 ChildHandleBuffer is NULL while Operation is add.
2012 @retval EFI_OUT_OF_RESOURCES There are no enough resources to start the devices.
2013 @retval EFI_NOT_FOUND Can not find bridge according to controller handle.
2014 @retval EFI_SUCCESS The handles for the specified device have been created or destroyed
2015 as requested, and for an add operation, the new handles are
2016 returned in ChildHandleBuffer.
2020 PciHotPlugRequestNotify (
2021 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL
* This
,
2022 IN EFI_PCI_HOTPLUG_OPERATION Operation
,
2023 IN EFI_HANDLE Controller
,
2024 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
,
2025 IN OUT UINT8
*NumberOfChildren
,
2026 IN OUT EFI_HANDLE
* ChildHandleBuffer
2029 PCI_IO_DEVICE
*Bridge
;
2030 PCI_IO_DEVICE
*Temp
;
2031 EFI_PCI_IO_PROTOCOL
*PciIo
;
2033 EFI_HANDLE RootBridgeHandle
;
2037 // Check input parameter validity
2039 if ((Controller
== NULL
) || (NumberOfChildren
== NULL
)){
2040 return EFI_INVALID_PARAMETER
;
2043 if ((Operation
!= EfiPciHotPlugRequestAdd
) && (Operation
!= EfiPciHotplugRequestRemove
)) {
2044 return EFI_INVALID_PARAMETER
;
2047 if (Operation
== EfiPciHotPlugRequestAdd
){
2048 if (ChildHandleBuffer
== NULL
) {
2049 return EFI_INVALID_PARAMETER
;
2051 } else if ((Operation
== EfiPciHotplugRequestRemove
) && (*NumberOfChildren
!= 0)) {
2052 if (ChildHandleBuffer
== NULL
) {
2053 return EFI_INVALID_PARAMETER
;
2057 Status
= gBS
->OpenProtocol (
2059 &gEfiPciIoProtocolGuid
,
2061 gPciBusDriverBinding
.DriverBindingHandle
,
2063 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2066 if (EFI_ERROR (Status
)) {
2067 return EFI_NOT_FOUND
;
2070 Bridge
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
2073 // Get root bridge handle
2076 while (Temp
->Parent
!= NULL
) {
2077 Temp
= Temp
->Parent
;
2080 RootBridgeHandle
= Temp
->Handle
;
2082 if (Operation
== EfiPciHotPlugRequestAdd
) {
2084 // Report Status Code to indicate hot plug happens
2086 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
2088 (EFI_IO_BUS_PCI
| EFI_IOB_PC_HOTPLUG
),
2092 if (NumberOfChildren
!= NULL
) {
2093 *NumberOfChildren
= 0;
2096 if (IsListEmpty (&Bridge
->ChildList
)) {
2098 Status
= PciBridgeEnumerator (Bridge
);
2100 if (EFI_ERROR (Status
)) {
2105 Status
= StartPciDevicesOnBridge (
2108 RemainingDevicePath
,
2116 if (Operation
== EfiPciHotplugRequestRemove
) {
2118 if (*NumberOfChildren
== 0) {
2120 // Remove all devices on the bridge
2122 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Bridge
);
2127 for (Index
= 0; Index
< *NumberOfChildren
; Index
++) {
2129 // De register all the pci device
2131 Status
= DeRegisterPciDevice (RootBridgeHandle
, ChildHandleBuffer
[Index
]);
2133 if (EFI_ERROR (Status
)) {
2148 Search hostbridge according to given handle
2150 @param RootBridgeHandle Host bridge handle.
2152 @retval TRUE Found host bridge handle.
2153 @retval FALSE Not found hot bridge handle.
2157 SearchHostBridgeHandle (
2158 IN EFI_HANDLE RootBridgeHandle
2161 EFI_HANDLE HostBridgeHandle
;
2162 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2167 // Get the rootbridge Io protocol to find the host bridge handle
2169 Status
= gBS
->OpenProtocol (
2171 &gEfiPciRootBridgeIoProtocolGuid
,
2172 (VOID
**) &PciRootBridgeIo
,
2173 gPciBusDriverBinding
.DriverBindingHandle
,
2175 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2178 if (EFI_ERROR (Status
)) {
2182 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
2183 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2184 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2193 Add host bridge handle to global variable for enumerating.
2195 @param HostBridgeHandle Host bridge handle.
2197 @retval EFI_SUCCESS Successfully added host bridge.
2198 @retval EFI_ABORTED Host bridge is NULL, or given host bridge
2199 has been in host bridge list.
2203 AddHostBridgeEnumerator (
2204 IN EFI_HANDLE HostBridgeHandle
2209 if (HostBridgeHandle
== NULL
) {
2213 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2214 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2219 if (Index
< PCI_MAX_HOST_BRIDGE_NUM
) {
2220 gPciHostBrigeHandles
[Index
] = HostBridgeHandle
;
2221 gPciHostBridgeNumber
++;