2 PCI eunmeration implementation on entire PCI bus system for PCI Bus module.
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
13 This routine is used to enumerate entire pci bus system
16 @param Controller Parent controller handle.
17 @param HostBridgeHandle Host bridge handle.
19 @retval EFI_SUCCESS PCI enumeration finished successfully.
20 @retval other Some error occurred when enumerating the pci bus system.
25 IN EFI_HANDLE Controller
,
26 IN EFI_HANDLE HostBridgeHandle
30 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
33 // Get the pci host bridge resource allocation protocol
35 Status
= gBS
->OpenProtocol (
37 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
38 (VOID
**) &PciResAlloc
,
39 gPciBusDriverBinding
.DriverBindingHandle
,
41 EFI_OPEN_PROTOCOL_GET_PROTOCOL
44 if (EFI_ERROR (Status
)) {
49 // Notify the pci bus enumeration is about to begin
51 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginEnumeration
);
53 if (EFI_ERROR (Status
)) {
58 // Start the bus allocation phase
60 Status
= PciHostBridgeEnumerator (PciResAlloc
);
62 if (EFI_ERROR (Status
)) {
67 // Submit the resource request
69 Status
= PciHostBridgeResourceAllocator (PciResAlloc
);
71 if (EFI_ERROR (Status
)) {
76 // Notify the pci bus enumeration is about to complete
78 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndEnumeration
);
80 if (EFI_ERROR (Status
)) {
87 Status
= PciHostBridgeP2CProcess (PciResAlloc
);
89 if (EFI_ERROR (Status
)) {
94 // Process attributes for devices on this host bridge
96 Status
= PciHostBridgeDeviceAttribute (PciResAlloc
);
97 if (EFI_ERROR (Status
)) {
105 Enumerate PCI root bridge.
107 @param PciResAlloc Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
108 @param RootBridgeDev Instance of root bridge device.
110 @retval EFI_SUCCESS Successfully enumerated root bridge.
111 @retval other Failed to enumerate root bridge.
115 PciRootBridgeEnumerator (
116 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
117 IN PCI_IO_DEVICE
*RootBridgeDev
121 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
122 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration1
;
123 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration2
;
124 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration3
;
126 UINT8 StartBusNumber
;
127 UINT8 PaddedBusRange
;
128 EFI_HANDLE RootBridgeHandle
;
138 // Get the root bridge handle
140 RootBridgeHandle
= RootBridgeDev
->Handle
;
142 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
144 EFI_IO_BUS_PCI
| EFI_IOB_PCI_BUS_ENUM
,
145 RootBridgeDev
->DevicePath
149 // Get the Bus information
151 Status
= PciResAlloc
->StartBusEnumeration (
154 (VOID
**) &Configuration
157 if (EFI_ERROR (Status
)) {
161 if (Configuration
== NULL
|| Configuration
->Desc
== ACPI_END_TAG_DESCRIPTOR
) {
162 return EFI_INVALID_PARAMETER
;
164 RootBridgeDev
->BusNumberRanges
= Configuration
;
167 // Sort the descriptors in ascending order
169 for (Configuration1
= Configuration
; Configuration1
->Desc
!= ACPI_END_TAG_DESCRIPTOR
; Configuration1
++) {
170 Configuration2
= Configuration1
;
171 for (Configuration3
= Configuration1
+ 1; Configuration3
->Desc
!= ACPI_END_TAG_DESCRIPTOR
; Configuration3
++) {
172 if (Configuration2
->AddrRangeMin
> Configuration3
->AddrRangeMin
) {
173 Configuration2
= Configuration3
;
177 // All other fields other than AddrRangeMin and AddrLen are ignored in a descriptor,
178 // so only need to swap these two fields.
180 if (Configuration2
!= Configuration1
) {
181 AddrRangeMin
= Configuration1
->AddrRangeMin
;
182 Configuration1
->AddrRangeMin
= Configuration2
->AddrRangeMin
;
183 Configuration2
->AddrRangeMin
= AddrRangeMin
;
185 AddrLen
= Configuration1
->AddrLen
;
186 Configuration1
->AddrLen
= Configuration2
->AddrLen
;
187 Configuration2
->AddrLen
= AddrLen
;
192 // Get the bus number to start with
194 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
197 // Initialize the subordinate bus number
199 SubBusNumber
= StartBusNumber
;
202 // Reset all assigned PCI bus number
204 ResetAllPpbBusNumber (
212 Status
= PciScanBus (
219 if (EFI_ERROR (Status
)) {
225 // Assign max bus number scanned
228 Status
= PciAllocateBusNumber (RootBridgeDev
, SubBusNumber
, PaddedBusRange
, &SubBusNumber
);
229 if (EFI_ERROR (Status
)) {
234 // Find the bus range which contains the higest bus number, then returns the number of buses
235 // that should be decoded.
237 while (Configuration
->AddrRangeMin
+ Configuration
->AddrLen
- 1 < SubBusNumber
) {
240 AddrLen
= Configuration
->AddrLen
;
241 Configuration
->AddrLen
= SubBusNumber
- Configuration
->AddrRangeMin
+ 1;
244 // Save the Desc field of the next descriptor. Mark the next descriptor as an END descriptor.
247 Desc
= Configuration
->Desc
;
248 Configuration
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
253 Status
= PciResAlloc
->SetBusNumbers (
256 RootBridgeDev
->BusNumberRanges
260 // Restore changed fields
262 Configuration
->Desc
= Desc
;
263 (Configuration
- 1)->AddrLen
= AddrLen
;
269 This routine is used to process all PCI devices' Option Rom
270 on a certain root bridge.
272 @param Bridge Given parent's root bridge.
273 @param RomBase Base address of ROM driver loaded from.
274 @param MaxLength Maximum rom size.
279 IN PCI_IO_DEVICE
*Bridge
,
284 LIST_ENTRY
*CurrentLink
;
288 // Go through bridges to reach all devices
290 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
291 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
292 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
293 if (!IsListEmpty (&Temp
->ChildList
)) {
296 // Go further to process the option rom under this bridge
298 ProcessOptionRom (Temp
, RomBase
, MaxLength
);
301 if (Temp
->RomSize
!= 0 && Temp
->RomSize
<= MaxLength
) {
304 // Load and process the option rom
306 LoadOpRomImage (Temp
, RomBase
);
309 CurrentLink
= CurrentLink
->ForwardLink
;
314 This routine is used to assign bus number to the given PCI bus system
316 @param Bridge Parent root bridge instance.
317 @param StartBusNumber Number of beginning.
318 @param SubBusNumber The number of sub bus.
320 @retval EFI_SUCCESS Successfully assigned bus number.
321 @retval EFI_DEVICE_ERROR Failed to assign bus number.
326 IN PCI_IO_DEVICE
*Bridge
,
327 IN UINT8 StartBusNumber
,
328 OUT UINT8
*SubBusNumber
339 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
341 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
346 *SubBusNumber
= StartBusNumber
;
349 // First check to see whether the parent is ppb
351 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
352 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
355 // Check to see whether a pci device is present
357 Status
= PciDevicePresent (
365 if (EFI_ERROR (Status
) && Func
== 0) {
367 // go to next device if there is no Function 0
372 if (!EFI_ERROR (Status
) &&
373 (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
376 // Reserved one bus for cardbus bridge
378 Status
= PciAllocateBusNumber (Bridge
, *SubBusNumber
, 1, SubBusNumber
);
379 if (EFI_ERROR (Status
)) {
382 SecondBus
= *SubBusNumber
;
384 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
386 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
388 Status
= PciRootBridgeIo
->Pci
.Write (
397 // Initialize SubBusNumber to SecondBus
399 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
400 Status
= PciRootBridgeIo
->Pci
.Write (
408 // If it is PPB, resursively search down this bridge
410 if (IS_PCI_BRIDGE (&Pci
)) {
413 Status
= PciRootBridgeIo
->Pci
.Write (
421 Status
= PciAssignBusNumber (
427 if (EFI_ERROR (Status
)) {
428 return EFI_DEVICE_ERROR
;
433 // Set the current maximum bus number under the PPB
435 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
437 Status
= PciRootBridgeIo
->Pci
.Write (
447 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
450 // Skip sub functions, this is not a multi function device
461 This routine is used to determine the root bridge attribute by interfacing
462 the host bridge resource allocation protocol.
464 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
465 @param RootBridgeDev Root bridge instance
467 @retval EFI_SUCCESS Successfully got root bridge's attribute.
468 @retval other Failed to get attribute.
472 DetermineRootBridgeAttributes (
473 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
474 IN PCI_IO_DEVICE
*RootBridgeDev
479 EFI_HANDLE RootBridgeHandle
;
482 RootBridgeHandle
= RootBridgeDev
->Handle
;
485 // Get root bridge attribute by calling into pci host bridge resource allocation protocol
487 Status
= PciResAlloc
->GetAllocAttributes (
493 if (EFI_ERROR (Status
)) {
498 // Here is the point where PCI bus driver calls HOST bridge allocation protocol
499 // Currently we hardcoded for ea815
501 if ((Attributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) {
502 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
;
505 if ((Attributes
& EFI_PCI_HOST_BRIDGE_MEM64_DECODE
) != 0) {
506 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM64_DECODE_SUPPORTED
;
507 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
510 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
511 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
512 RootBridgeDev
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
518 Get Max Option Rom size on specified bridge.
520 @param Bridge Given bridge device instance.
522 @return Max size of option rom needed.
526 GetMaxOptionRomSize (
527 IN PCI_IO_DEVICE
*Bridge
530 LIST_ENTRY
*CurrentLink
;
532 UINT32 MaxOptionRomSize
;
533 UINT32 TempOptionRomSize
;
535 MaxOptionRomSize
= 0;
538 // Go through bridges to reach all devices
540 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
541 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
542 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
543 if (!IsListEmpty (&Temp
->ChildList
)) {
546 // Get max option rom size under this bridge
548 TempOptionRomSize
= GetMaxOptionRomSize (Temp
);
551 // Compare with the option rom size of the bridge
552 // Get the larger one
554 if (Temp
->RomSize
> TempOptionRomSize
) {
555 TempOptionRomSize
= Temp
->RomSize
;
561 // For devices get the rom size directly
563 TempOptionRomSize
= Temp
->RomSize
;
567 // Get the largest rom size on this bridge
569 if (TempOptionRomSize
> MaxOptionRomSize
) {
570 MaxOptionRomSize
= TempOptionRomSize
;
573 CurrentLink
= CurrentLink
->ForwardLink
;
576 return MaxOptionRomSize
;
580 Process attributes of devices on this host bridge
582 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
584 @retval EFI_SUCCESS Successfully process attribute.
585 @retval EFI_NOT_FOUND Can not find the specific root bridge device.
586 @retval other Failed to determine the root bridge device's attribute.
590 PciHostBridgeDeviceAttribute (
591 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
594 EFI_HANDLE RootBridgeHandle
;
595 PCI_IO_DEVICE
*RootBridgeDev
;
598 RootBridgeHandle
= NULL
;
600 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
603 // Get RootBridg Device by handle
605 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
607 if (RootBridgeDev
== NULL
) {
608 return EFI_NOT_FOUND
;
612 // Set the attributes for devcies behind the Root Bridge
614 Status
= DetermineDeviceAttribute (RootBridgeDev
);
615 if (EFI_ERROR (Status
)) {
625 Get resource allocation status from the ACPI resource descriptor.
627 @param AcpiConfig Point to Acpi configuration table.
628 @param IoResStatus Return the status of I/O resource.
629 @param Mem32ResStatus Return the status of 32-bit Memory resource.
630 @param PMem32ResStatus Return the status of 32-bit Prefetchable Memory resource.
631 @param Mem64ResStatus Return the status of 64-bit Memory resource.
632 @param PMem64ResStatus Return the status of 64-bit Prefetchable Memory resource.
636 GetResourceAllocationStatus (
638 OUT UINT64
*IoResStatus
,
639 OUT UINT64
*Mem32ResStatus
,
640 OUT UINT64
*PMem32ResStatus
,
641 OUT UINT64
*Mem64ResStatus
,
642 OUT UINT64
*PMem64ResStatus
647 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*ACPIAddressDesc
;
649 Temp
= (UINT8
*) AcpiConfig
;
651 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
653 ACPIAddressDesc
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
654 ResStatus
= ACPIAddressDesc
->AddrTranslationOffset
;
656 switch (ACPIAddressDesc
->ResType
) {
658 if (ACPIAddressDesc
->AddrSpaceGranularity
== 32) {
659 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
663 *PMem32ResStatus
= ResStatus
;
668 *Mem32ResStatus
= ResStatus
;
672 if (ACPIAddressDesc
->AddrSpaceGranularity
== 64) {
673 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
677 *PMem64ResStatus
= ResStatus
;
682 *Mem64ResStatus
= ResStatus
;
692 *IoResStatus
= ResStatus
;
699 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
704 Remove a PCI device from device pool and mark its bar.
706 @param PciDevice Instance of Pci device.
708 @retval EFI_SUCCESS Successfully remove the PCI device.
709 @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
714 IN PCI_IO_DEVICE
*PciDevice
717 PCI_IO_DEVICE
*Bridge
;
719 LIST_ENTRY
*CurrentLink
;
722 // Remove the padding resource from a bridge
724 if ( IS_PCI_BRIDGE(&PciDevice
->Pci
) &&
725 PciDevice
->ResourcePaddingDescriptors
!= NULL
) {
726 FreePool (PciDevice
->ResourcePaddingDescriptors
);
727 PciDevice
->ResourcePaddingDescriptors
= NULL
;
734 if (IS_PCI_BRIDGE (&PciDevice
->Pci
) || (PciDevice
->Parent
== NULL
)) {
738 if (IS_CARDBUS_BRIDGE (&PciDevice
->Pci
)) {
740 // Get the root bridge device
743 while (Bridge
->Parent
!= NULL
) {
744 Bridge
= Bridge
->Parent
;
747 RemoveAllPciDeviceOnBridge (Bridge
->Handle
, PciDevice
);
752 InitializeP2C (PciDevice
);
758 Bridge
= PciDevice
->Parent
;
759 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
760 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
761 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
762 if (Temp
== PciDevice
) {
763 InitializePciDevice (Temp
);
764 RemoveEntryList (CurrentLink
);
768 CurrentLink
= CurrentLink
->ForwardLink
;
775 Determine whethter a PCI device can be rejected.
777 @param PciResNode Pointer to Pci resource node instance.
779 @retval TRUE The PCI device can be rejected.
780 @retval TRUE The PCI device cannot be rejected.
785 IN PCI_RESOURCE_NODE
*PciResNode
790 Temp
= PciResNode
->PciDev
;
793 // Ensure the device is present
800 // PPB and RB should go ahead
802 if (IS_PCI_BRIDGE (&Temp
->Pci
) || (Temp
->Parent
== NULL
)) {
807 // Skip device on Bus0
809 if ((Temp
->Parent
!= NULL
) && (Temp
->BusNumber
== 0)) {
816 if (IS_PCI_VGA (&Temp
->Pci
)) {
824 Compare two resource nodes and get the larger resource consumer.
826 @param PciResNode1 resource node 1 want to be compared
827 @param PciResNode2 resource node 2 want to be compared
829 @return Larger resource node.
833 GetLargerConsumerDevice (
834 IN PCI_RESOURCE_NODE
*PciResNode1
,
835 IN PCI_RESOURCE_NODE
*PciResNode2
838 if (PciResNode2
== NULL
) {
842 if ((IS_PCI_BRIDGE(&(PciResNode2
->PciDev
->Pci
)) || (PciResNode2
->PciDev
->Parent
== NULL
)) \
843 && (PciResNode2
->ResourceUsage
!= PciResUsagePadding
) )
848 if (PciResNode1
== NULL
) {
852 if ((PciResNode1
->Length
) > (PciResNode2
->Length
)) {
861 Get the max resource consumer in the host resource pool.
863 @param ResPool Pointer to resource pool node.
865 @return The max resource consumer in the host resource pool.
869 GetMaxResourceConsumerDevice (
870 IN PCI_RESOURCE_NODE
*ResPool
873 PCI_RESOURCE_NODE
*Temp
;
874 LIST_ENTRY
*CurrentLink
;
875 PCI_RESOURCE_NODE
*PciResNode
;
876 PCI_RESOURCE_NODE
*PPBResNode
;
880 CurrentLink
= ResPool
->ChildList
.ForwardLink
;
881 while (CurrentLink
!= NULL
&& CurrentLink
!= &ResPool
->ChildList
) {
883 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
885 if (!IsRejectiveDevice (Temp
)) {
886 CurrentLink
= CurrentLink
->ForwardLink
;
890 if ((IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
)) || (Temp
->PciDev
->Parent
== NULL
)) \
891 && (Temp
->ResourceUsage
!= PciResUsagePadding
))
893 PPBResNode
= GetMaxResourceConsumerDevice (Temp
);
894 PciResNode
= GetLargerConsumerDevice (PciResNode
, PPBResNode
);
896 PciResNode
= GetLargerConsumerDevice (PciResNode
, Temp
);
899 CurrentLink
= CurrentLink
->ForwardLink
;
906 Adjust host bridge allocation so as to reduce resource requirement
908 @param IoPool Pointer to instance of I/O resource Node.
909 @param Mem32Pool Pointer to instance of 32-bit memory resource Node.
910 @param PMem32Pool Pointer to instance of 32-bit Prefetchable memory resource node.
911 @param Mem64Pool Pointer to instance of 64-bit memory resource node.
912 @param PMem64Pool Pointer to instance of 64-bit Prefetchable memory resource node.
913 @param IoResStatus Status of I/O resource Node.
914 @param Mem32ResStatus Status of 32-bit memory resource Node.
915 @param PMem32ResStatus Status of 32-bit Prefetchable memory resource node.
916 @param Mem64ResStatus Status of 64-bit memory resource node.
917 @param PMem64ResStatus Status of 64-bit Prefetchable memory resource node.
919 @retval EFI_SUCCESS Successfully adjusted resource on host bridge.
920 @retval EFI_ABORTED Host bridge hasn't this resource type or no resource be adjusted.
924 PciHostBridgeAdjustAllocation (
925 IN PCI_RESOURCE_NODE
*IoPool
,
926 IN PCI_RESOURCE_NODE
*Mem32Pool
,
927 IN PCI_RESOURCE_NODE
*PMem32Pool
,
928 IN PCI_RESOURCE_NODE
*Mem64Pool
,
929 IN PCI_RESOURCE_NODE
*PMem64Pool
,
930 IN UINT64 IoResStatus
,
931 IN UINT64 Mem32ResStatus
,
932 IN UINT64 PMem32ResStatus
,
933 IN UINT64 Mem64ResStatus
,
934 IN UINT64 PMem64ResStatus
937 BOOLEAN AllocationAjusted
;
938 PCI_RESOURCE_NODE
*PciResNode
;
939 PCI_RESOURCE_NODE
*ResPool
[5];
940 PCI_IO_DEVICE
*RemovedPciDev
[5];
942 UINTN RemovedPciDevNum
;
946 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
949 ZeroMem (RemovedPciDev
, 5 * sizeof (PCI_IO_DEVICE
*));
950 RemovedPciDevNum
= 0;
953 ResPool
[1] = Mem32Pool
;
954 ResPool
[2] = PMem32Pool
;
955 ResPool
[3] = Mem64Pool
;
956 ResPool
[4] = PMem64Pool
;
958 ResStatus
[0] = IoResStatus
;
959 ResStatus
[1] = Mem32ResStatus
;
960 ResStatus
[2] = PMem32ResStatus
;
961 ResStatus
[3] = Mem64ResStatus
;
962 ResStatus
[4] = PMem64ResStatus
;
964 AllocationAjusted
= FALSE
;
966 for (ResType
= 0; ResType
< 5; ResType
++) {
968 if (ResStatus
[ResType
] == EFI_RESOURCE_SATISFIED
) {
972 if (ResStatus
[ResType
] == EFI_RESOURCE_NOT_SATISFIED
) {
974 // Host bridge hasn't this resource type
980 // Hostbridge hasn't enough resource
982 PciResNode
= GetMaxResourceConsumerDevice (ResPool
[ResType
]);
983 if (PciResNode
== NULL
) {
988 // Check if the device has been removed before
990 for (DevIndex
= 0; DevIndex
< RemovedPciDevNum
; DevIndex
++) {
991 if (PciResNode
->PciDev
== RemovedPciDev
[DevIndex
]) {
996 if (DevIndex
!= RemovedPciDevNum
) {
1001 // Remove the device if it isn't in the array
1003 Status
= RejectPciDevice (PciResNode
->PciDev
);
1004 if (Status
== EFI_SUCCESS
) {
1007 "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",
1008 PciResNode
->PciDev
->BusNumber
, PciResNode
->PciDev
->DeviceNumber
, PciResNode
->PciDev
->FunctionNumber
1012 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
1015 // Have no way to get ReqRes, AllocRes & Bar here
1017 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
1018 AllocFailExtendedData
.DevicePathSize
= (UINT16
) sizeof (EFI_DEVICE_PATH_PROTOCOL
);
1019 AllocFailExtendedData
.DevicePath
= (UINT8
*) PciResNode
->PciDev
->DevicePath
;
1020 AllocFailExtendedData
.Bar
= PciResNode
->Bar
;
1022 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1024 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
1025 (VOID
*) &AllocFailExtendedData
,
1026 sizeof (AllocFailExtendedData
)
1030 // Add it to the array and indicate at least a device has been rejected
1032 RemovedPciDev
[RemovedPciDevNum
++] = PciResNode
->PciDev
;
1033 AllocationAjusted
= TRUE
;
1040 if (AllocationAjusted
) {
1048 Summary requests for all resource type, and construct ACPI resource
1051 @param Bridge detecting bridge
1052 @param IoNode Pointer to instance of I/O resource Node
1053 @param Mem32Node Pointer to instance of 32-bit memory resource Node
1054 @param PMem32Node Pointer to instance of 32-bit Pmemory resource node
1055 @param Mem64Node Pointer to instance of 64-bit memory resource node
1056 @param PMem64Node Pointer to instance of 64-bit Pmemory resource node
1057 @param Config Output buffer holding new constructed APCI resource requestor
1059 @retval EFI_SUCCESS Successfully constructed ACPI resource.
1060 @retval EFI_OUT_OF_RESOURCES No memory available.
1064 ConstructAcpiResourceRequestor (
1065 IN PCI_IO_DEVICE
*Bridge
,
1066 IN PCI_RESOURCE_NODE
*IoNode
,
1067 IN PCI_RESOURCE_NODE
*Mem32Node
,
1068 IN PCI_RESOURCE_NODE
*PMem32Node
,
1069 IN PCI_RESOURCE_NODE
*Mem64Node
,
1070 IN PCI_RESOURCE_NODE
*PMem64Node
,
1076 UINT8
*Configuration
;
1077 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1078 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
1086 // if there is io request, add to the io aperture
1088 if (ResourceRequestExisted (IoNode
)) {
1094 // if there is mem32 request, add to the mem32 aperture
1096 if (ResourceRequestExisted (Mem32Node
)) {
1102 // if there is pmem32 request, add to the pmem32 aperture
1104 if (ResourceRequestExisted (PMem32Node
)) {
1110 // if there is mem64 request, add to the mem64 aperture
1112 if (ResourceRequestExisted (Mem64Node
)) {
1118 // if there is pmem64 request, add to the pmem64 aperture
1120 if (ResourceRequestExisted (PMem64Node
)) {
1125 if (NumConfig
!= 0) {
1128 // If there is at least one type of resource request,
1129 // allocate a acpi resource node
1131 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1132 if (Configuration
== NULL
) {
1133 return EFI_OUT_OF_RESOURCES
;
1136 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1139 // Deal with io aperture
1141 if ((Aperture
& 0x01) != 0) {
1142 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1143 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1147 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1151 Ptr
->SpecificFlag
= 1;
1152 Ptr
->AddrLen
= IoNode
->Length
;
1153 Ptr
->AddrRangeMax
= IoNode
->Alignment
;
1158 // Deal with mem32 aperture
1160 if ((Aperture
& 0x02) != 0) {
1161 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1162 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1166 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1170 Ptr
->SpecificFlag
= 0;
1174 Ptr
->AddrSpaceGranularity
= 32;
1175 Ptr
->AddrLen
= Mem32Node
->Length
;
1176 Ptr
->AddrRangeMax
= Mem32Node
->Alignment
;
1182 // Deal with Pmem32 aperture
1184 if ((Aperture
& 0x04) != 0) {
1185 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1186 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1190 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1194 Ptr
->SpecificFlag
= 0x6;
1198 Ptr
->AddrSpaceGranularity
= 32;
1199 Ptr
->AddrLen
= PMem32Node
->Length
;
1200 Ptr
->AddrRangeMax
= PMem32Node
->Alignment
;
1205 // Deal with mem64 aperture
1207 if ((Aperture
& 0x08) != 0) {
1208 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1209 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1213 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1217 Ptr
->SpecificFlag
= 0;
1221 Ptr
->AddrSpaceGranularity
= 64;
1222 Ptr
->AddrLen
= Mem64Node
->Length
;
1223 Ptr
->AddrRangeMax
= Mem64Node
->Alignment
;
1228 // Deal with Pmem64 aperture
1230 if ((Aperture
& 0x10) != 0) {
1231 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1232 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1236 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1240 Ptr
->SpecificFlag
= 0x06;
1244 Ptr
->AddrSpaceGranularity
= 64;
1245 Ptr
->AddrLen
= PMem64Node
->Length
;
1246 Ptr
->AddrRangeMax
= PMem64Node
->Alignment
;
1254 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
;
1256 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1257 PtrEnd
->Checksum
= 0;
1262 // If there is no resource request
1264 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1265 if (Configuration
== NULL
) {
1266 return EFI_OUT_OF_RESOURCES
;
1269 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Configuration
);
1270 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1271 PtrEnd
->Checksum
= 0;
1274 *Config
= Configuration
;
1280 Get resource base from an acpi configuration descriptor.
1282 @param Config An acpi configuration descriptor.
1283 @param IoBase Output of I/O resource base address.
1284 @param Mem32Base Output of 32-bit memory base address.
1285 @param PMem32Base Output of 32-bit prefetchable memory base address.
1286 @param Mem64Base Output of 64-bit memory base address.
1287 @param PMem64Base Output of 64-bit prefetchable memory base address.
1294 OUT UINT64
*Mem32Base
,
1295 OUT UINT64
*PMem32Base
,
1296 OUT UINT64
*Mem64Base
,
1297 OUT UINT64
*PMem64Base
1301 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1304 ASSERT (Config
!= NULL
);
1306 *IoBase
= 0xFFFFFFFFFFFFFFFFULL
;
1307 *Mem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1308 *PMem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1309 *Mem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1310 *PMem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1312 Temp
= (UINT8
*) Config
;
1314 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1316 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1317 ResStatus
= Ptr
->AddrTranslationOffset
;
1319 if (ResStatus
== EFI_RESOURCE_SATISFIED
) {
1321 switch (Ptr
->ResType
) {
1324 // Memory type aperture
1329 // Check to see the granularity
1331 if (Ptr
->AddrSpaceGranularity
== 32) {
1332 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1333 *PMem32Base
= Ptr
->AddrRangeMin
;
1335 *Mem32Base
= Ptr
->AddrRangeMin
;
1339 if (Ptr
->AddrSpaceGranularity
== 64) {
1340 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1341 *PMem64Base
= Ptr
->AddrRangeMin
;
1343 *Mem64Base
= Ptr
->AddrRangeMin
;
1353 *IoBase
= Ptr
->AddrRangeMin
;
1367 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1372 Enumerate pci bridge, allocate resource and determine attribute
1373 for devices on this bridge.
1375 @param BridgeDev Pointer to instance of bridge device.
1377 @retval EFI_SUCCESS Successfully enumerated PCI bridge.
1378 @retval other Failed to enumerate.
1382 PciBridgeEnumerator (
1383 IN PCI_IO_DEVICE
*BridgeDev
1387 UINT8 StartBusNumber
;
1388 EFI_PCI_IO_PROTOCOL
*PciIo
;
1393 PciIo
= &(BridgeDev
->PciIo
);
1394 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x19, 1, &StartBusNumber
);
1396 if (EFI_ERROR (Status
)) {
1400 Status
= PciAssignBusNumber (
1406 if (EFI_ERROR (Status
)) {
1410 Status
= PciPciDeviceInfoCollector (BridgeDev
, StartBusNumber
);
1412 if (EFI_ERROR (Status
)) {
1416 Status
= PciBridgeResourceAllocator (BridgeDev
);
1418 if (EFI_ERROR (Status
)) {
1422 Status
= DetermineDeviceAttribute (BridgeDev
);
1424 if (EFI_ERROR (Status
)) {
1433 Allocate all kinds of resource for PCI bridge.
1435 @param Bridge Pointer to bridge instance.
1437 @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
1438 @retval other Failed to allocate resource for bridge.
1442 PciBridgeResourceAllocator (
1443 IN PCI_IO_DEVICE
*Bridge
1446 PCI_RESOURCE_NODE
*IoBridge
;
1447 PCI_RESOURCE_NODE
*Mem32Bridge
;
1448 PCI_RESOURCE_NODE
*PMem32Bridge
;
1449 PCI_RESOURCE_NODE
*Mem64Bridge
;
1450 PCI_RESOURCE_NODE
*PMem64Bridge
;
1458 IoBridge
= CreateResourceNode (
1461 Bridge
->BridgeIoAlignment
,
1467 Mem32Bridge
= CreateResourceNode (
1476 PMem32Bridge
= CreateResourceNode (
1485 Mem64Bridge
= CreateResourceNode (
1494 PMem64Bridge
= CreateResourceNode (
1504 // Create resourcemap by going through all the devices subject to this root bridge
1515 Status
= GetResourceBaseFromBridge (
1524 if (EFI_ERROR (Status
)) {
1529 // Program IO resources
1537 // Program Mem32 resources
1545 // Program PMem32 resources
1553 // Program Mem64 resources
1561 // Program PMem64 resources
1568 DestroyResourceTree (IoBridge
);
1569 DestroyResourceTree (Mem32Bridge
);
1570 DestroyResourceTree (PMem32Bridge
);
1571 DestroyResourceTree (PMem64Bridge
);
1572 DestroyResourceTree (Mem64Bridge
);
1574 gBS
->FreePool (IoBridge
);
1575 gBS
->FreePool (Mem32Bridge
);
1576 gBS
->FreePool (PMem32Bridge
);
1577 gBS
->FreePool (PMem64Bridge
);
1578 gBS
->FreePool (Mem64Bridge
);
1584 Get resource base address for a pci bridge device.
1586 @param Bridge Given Pci driver instance.
1587 @param IoBase Output for base address of I/O type resource.
1588 @param Mem32Base Output for base address of 32-bit memory type resource.
1589 @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
1590 @param Mem64Base Output for base address of 64-bit memory type resource.
1591 @param PMem64Base Output for base address of 64-bit Pmemory type resource.
1593 @retval EFI_SUCCESS Successfully got resource base address.
1594 @retval EFI_OUT_OF_RESOURCES PCI bridge is not available.
1598 GetResourceBaseFromBridge (
1599 IN PCI_IO_DEVICE
*Bridge
,
1601 OUT UINT64
*Mem32Base
,
1602 OUT UINT64
*PMem32Base
,
1603 OUT UINT64
*Mem64Base
,
1604 OUT UINT64
*PMem64Base
1607 if (!Bridge
->Allocated
) {
1608 return EFI_OUT_OF_RESOURCES
;
1612 *Mem32Base
= gAllOne
;
1613 *PMem32Base
= gAllOne
;
1614 *Mem64Base
= gAllOne
;
1615 *PMem64Base
= gAllOne
;
1617 if (IS_PCI_BRIDGE (&Bridge
->Pci
)) {
1619 if (Bridge
->PciBar
[PPB_IO_RANGE
].Length
> 0) {
1620 *IoBase
= Bridge
->PciBar
[PPB_IO_RANGE
].BaseAddress
;
1623 if (Bridge
->PciBar
[PPB_MEM32_RANGE
].Length
> 0) {
1624 *Mem32Base
= Bridge
->PciBar
[PPB_MEM32_RANGE
].BaseAddress
;
1627 if (Bridge
->PciBar
[PPB_PMEM32_RANGE
].Length
> 0) {
1628 *PMem32Base
= Bridge
->PciBar
[PPB_PMEM32_RANGE
].BaseAddress
;
1631 if (Bridge
->PciBar
[PPB_PMEM64_RANGE
].Length
> 0) {
1632 *PMem64Base
= Bridge
->PciBar
[PPB_PMEM64_RANGE
].BaseAddress
;
1634 *PMem64Base
= gAllOne
;
1639 if (IS_CARDBUS_BRIDGE (&Bridge
->Pci
)) {
1640 if (Bridge
->PciBar
[P2C_IO_1
].Length
> 0) {
1641 *IoBase
= Bridge
->PciBar
[P2C_IO_1
].BaseAddress
;
1643 if (Bridge
->PciBar
[P2C_IO_2
].Length
> 0) {
1644 *IoBase
= Bridge
->PciBar
[P2C_IO_2
].BaseAddress
;
1648 if (Bridge
->PciBar
[P2C_MEM_1
].Length
> 0) {
1649 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypePMem32
) {
1650 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1653 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypeMem32
) {
1654 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1658 if (Bridge
->PciBar
[P2C_MEM_2
].Length
> 0) {
1659 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypePMem32
) {
1660 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1663 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypeMem32
) {
1664 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1673 These are the notifications from the PCI bus driver that it is about to enter a certain
1674 phase of the PCI enumeration process.
1676 This member function can be used to notify the host bridge driver to perform specific actions,
1677 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1678 Eight notification points are defined at this time. See belows:
1679 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
1680 structures. The PCI enumerator should issue this notification
1681 before starting a fresh enumeration process. Enumeration cannot
1682 be restarted after sending any other notification such as
1683 EfiPciHostBridgeBeginBusAllocation.
1684 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
1685 required here. This notification can be used to perform any
1686 chipset-specific programming.
1687 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
1688 specific action is required here. This notification can be used to
1689 perform any chipset-specific programming.
1690 EfiPciHostBridgeBeginResourceAllocation
1691 The resource allocation phase is about to begin. No specific
1692 action is required here. This notification can be used to perform
1693 any chipset-specific programming.
1694 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
1695 root bridges. These resource settings are returned on the next call to
1696 GetProposedResources(). Before calling NotifyPhase() with a Phase of
1697 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
1698 for gathering I/O and memory requests for
1699 all the PCI root bridges and submitting these requests using
1700 SubmitResources(). This function pads the resource amount
1701 to suit the root bridge hardware, takes care of dependencies between
1702 the PCI root bridges, and calls the Global Coherency Domain (GCD)
1703 with the allocation request. In the case of padding, the allocated range
1704 could be bigger than what was requested.
1705 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
1706 resources (proposed resources) for all the PCI root bridges. After the
1707 hardware is programmed, reassigning resources will not be supported.
1708 The bus settings are not affected.
1709 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
1710 root bridges and resets the I/O and memory apertures to their initial
1711 state. The bus settings are not affected. If the request to allocate
1712 resources fails, the PCI enumerator can use this notification to
1713 deallocate previous resources, adjust the requests, and retry
1715 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
1716 required here. This notification can be used to perform any chipsetspecific
1719 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1720 @param[in] Phase The phase during enumeration
1722 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
1723 is valid for a Phase of EfiPciHostBridgeAllocateResources if
1724 SubmitResources() has not been called for one or more
1725 PCI root bridges before this call
1726 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
1727 for a Phase of EfiPciHostBridgeSetResources.
1728 @retval EFI_INVALID_PARAMETER Invalid phase parameter
1729 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1730 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1731 previously submitted resource requests cannot be fulfilled or
1732 were only partially fulfilled.
1733 @retval EFI_SUCCESS The notification was accepted without any errors.
1738 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
1739 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1742 EFI_HANDLE HostBridgeHandle
;
1743 EFI_HANDLE RootBridgeHandle
;
1744 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1747 HostBridgeHandle
= NULL
;
1748 RootBridgeHandle
= NULL
;
1749 if (gPciPlatformProtocol
!= NULL
) {
1751 // Get Host Bridge Handle.
1753 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1756 // Get the rootbridge Io protocol to find the host bridge handle
1758 Status
= gBS
->HandleProtocol (
1760 &gEfiPciRootBridgeIoProtocolGuid
,
1761 (VOID
**) &PciRootBridgeIo
1764 if (EFI_ERROR (Status
)) {
1765 return EFI_NOT_FOUND
;
1768 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1771 // Call PlatformPci::PlatformNotify() if the protocol is present.
1773 gPciPlatformProtocol
->PlatformNotify (
1774 gPciPlatformProtocol
,
1779 } else if (gPciOverrideProtocol
!= NULL
){
1781 // Get Host Bridge Handle.
1783 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1786 // Get the rootbridge Io protocol to find the host bridge handle
1788 Status
= gBS
->HandleProtocol (
1790 &gEfiPciRootBridgeIoProtocolGuid
,
1791 (VOID
**) &PciRootBridgeIo
1794 if (EFI_ERROR (Status
)) {
1795 return EFI_NOT_FOUND
;
1798 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1801 // Call PlatformPci::PhaseNotify() if the protocol is present.
1803 gPciOverrideProtocol
->PlatformNotify (
1804 gPciOverrideProtocol
,
1811 Status
= PciResAlloc
->NotifyPhase (
1816 if (gPciPlatformProtocol
!= NULL
) {
1818 // Call PlatformPci::PlatformNotify() if the protocol is present.
1820 gPciPlatformProtocol
->PlatformNotify (
1821 gPciPlatformProtocol
,
1827 } else if (gPciOverrideProtocol
!= NULL
) {
1829 // Call PlatformPci::PhaseNotify() if the protocol is present.
1831 gPciOverrideProtocol
->PlatformNotify (
1832 gPciOverrideProtocol
,
1843 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1844 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1845 PCI controllers before enumeration.
1847 This function is called during the PCI enumeration process. No specific action is expected from this
1848 member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1851 @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1852 @param Bus The bus number of the pci device.
1853 @param Device The device number of the pci device.
1854 @param Func The function number of the pci device.
1855 @param Phase The phase of the PCI device enumeration.
1857 @retval EFI_SUCCESS The requested parameters were returned.
1858 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
1859 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
1860 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1861 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
1862 not enumerate this device, including its child devices if it is a PCI-to-PCI
1867 PreprocessController (
1868 IN PCI_IO_DEVICE
*Bridge
,
1872 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1875 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress
;
1876 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
1877 EFI_HANDLE RootBridgeHandle
;
1878 EFI_HANDLE HostBridgeHandle
;
1882 // Get the host bridge handle
1884 HostBridgeHandle
= Bridge
->PciRootBridgeIo
->ParentHandle
;
1887 // Get the pci host bridge resource allocation protocol
1889 Status
= gBS
->OpenProtocol (
1891 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
1892 (VOID
**) &PciResAlloc
,
1895 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1898 if (EFI_ERROR (Status
)) {
1899 return EFI_UNSUPPORTED
;
1903 // Get Root Brige Handle
1905 while (Bridge
->Parent
!= NULL
) {
1906 Bridge
= Bridge
->Parent
;
1909 RootBridgeHandle
= Bridge
->Handle
;
1911 RootBridgePciAddress
.Register
= 0;
1912 RootBridgePciAddress
.Function
= Func
;
1913 RootBridgePciAddress
.Device
= Device
;
1914 RootBridgePciAddress
.Bus
= Bus
;
1915 RootBridgePciAddress
.ExtendedRegister
= 0;
1917 if (gPciPlatformProtocol
!= NULL
) {
1919 // Call PlatformPci::PrepController() if the protocol is present.
1921 gPciPlatformProtocol
->PlatformPrepController (
1922 gPciPlatformProtocol
,
1925 RootBridgePciAddress
,
1929 } else if (gPciOverrideProtocol
!= NULL
) {
1931 // Call PlatformPci::PrepController() if the protocol is present.
1933 gPciOverrideProtocol
->PlatformPrepController (
1934 gPciOverrideProtocol
,
1937 RootBridgePciAddress
,
1943 Status
= PciResAlloc
->PreprocessController (
1946 RootBridgePciAddress
,
1950 if (gPciPlatformProtocol
!= NULL
) {
1952 // Call PlatformPci::PrepController() if the protocol is present.
1954 gPciPlatformProtocol
->PlatformPrepController (
1955 gPciPlatformProtocol
,
1958 RootBridgePciAddress
,
1962 } else if (gPciOverrideProtocol
!= NULL
) {
1964 // Call PlatformPci::PrepController() if the protocol is present.
1966 gPciOverrideProtocol
->PlatformPrepController (
1967 gPciOverrideProtocol
,
1970 RootBridgePciAddress
,
1980 This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
1981 happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
1983 @param This A pointer to the hot plug request protocol.
1984 @param Operation The operation the PCI bus driver is requested to make.
1985 @param Controller The handle of the hot-plug controller.
1986 @param RemainingDevicePath The remaining device path for the PCI-like hot-plug device.
1987 @param NumberOfChildren The number of child handles.
1988 For a add operation, it is an output parameter.
1989 For a remove operation, it's an input parameter.
1990 @param ChildHandleBuffer The buffer which contains the child handles.
1992 @retval EFI_INVALID_PARAMETER Operation is not a legal value.
1993 Controller is NULL or not a valid handle.
1994 NumberOfChildren is NULL.
1995 ChildHandleBuffer is NULL while Operation is add.
1996 @retval EFI_OUT_OF_RESOURCES There are no enough resources to start the devices.
1997 @retval EFI_NOT_FOUND Can not find bridge according to controller handle.
1998 @retval EFI_SUCCESS The handles for the specified device have been created or destroyed
1999 as requested, and for an add operation, the new handles are
2000 returned in ChildHandleBuffer.
2004 PciHotPlugRequestNotify (
2005 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL
* This
,
2006 IN EFI_PCI_HOTPLUG_OPERATION Operation
,
2007 IN EFI_HANDLE Controller
,
2008 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
,
2009 IN OUT UINT8
*NumberOfChildren
,
2010 IN OUT EFI_HANDLE
* ChildHandleBuffer
2013 PCI_IO_DEVICE
*Bridge
;
2014 PCI_IO_DEVICE
*Temp
;
2015 EFI_PCI_IO_PROTOCOL
*PciIo
;
2017 EFI_HANDLE RootBridgeHandle
;
2021 // Check input parameter validity
2023 if ((Controller
== NULL
) || (NumberOfChildren
== NULL
)){
2024 return EFI_INVALID_PARAMETER
;
2027 if ((Operation
!= EfiPciHotPlugRequestAdd
) && (Operation
!= EfiPciHotplugRequestRemove
)) {
2028 return EFI_INVALID_PARAMETER
;
2031 if (Operation
== EfiPciHotPlugRequestAdd
){
2032 if (ChildHandleBuffer
== NULL
) {
2033 return EFI_INVALID_PARAMETER
;
2035 } else if ((Operation
== EfiPciHotplugRequestRemove
) && (*NumberOfChildren
!= 0)) {
2036 if (ChildHandleBuffer
== NULL
) {
2037 return EFI_INVALID_PARAMETER
;
2041 Status
= gBS
->OpenProtocol (
2043 &gEfiPciIoProtocolGuid
,
2045 gPciBusDriverBinding
.DriverBindingHandle
,
2047 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2050 if (EFI_ERROR (Status
)) {
2051 return EFI_NOT_FOUND
;
2054 Bridge
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
2057 // Get root bridge handle
2060 while (Temp
->Parent
!= NULL
) {
2061 Temp
= Temp
->Parent
;
2064 RootBridgeHandle
= Temp
->Handle
;
2066 if (Operation
== EfiPciHotPlugRequestAdd
) {
2068 // Report Status Code to indicate hot plug happens
2070 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
2072 (EFI_IO_BUS_PCI
| EFI_IOB_PC_HOTPLUG
),
2076 if (NumberOfChildren
!= NULL
) {
2077 *NumberOfChildren
= 0;
2080 if (IsListEmpty (&Bridge
->ChildList
)) {
2082 Status
= PciBridgeEnumerator (Bridge
);
2084 if (EFI_ERROR (Status
)) {
2089 Status
= StartPciDevicesOnBridge (
2092 RemainingDevicePath
,
2100 if (Operation
== EfiPciHotplugRequestRemove
) {
2102 if (*NumberOfChildren
== 0) {
2104 // Remove all devices on the bridge
2106 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Bridge
);
2111 for (Index
= 0; Index
< *NumberOfChildren
; Index
++) {
2113 // De register all the pci device
2115 Status
= DeRegisterPciDevice (RootBridgeHandle
, ChildHandleBuffer
[Index
]);
2117 if (EFI_ERROR (Status
)) {
2132 Search hostbridge according to given handle
2134 @param RootBridgeHandle Host bridge handle.
2136 @retval TRUE Found host bridge handle.
2137 @retval FALSE Not found hot bridge handle.
2141 SearchHostBridgeHandle (
2142 IN EFI_HANDLE RootBridgeHandle
2145 EFI_HANDLE HostBridgeHandle
;
2146 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2151 // Get the rootbridge Io protocol to find the host bridge handle
2153 Status
= gBS
->OpenProtocol (
2155 &gEfiPciRootBridgeIoProtocolGuid
,
2156 (VOID
**) &PciRootBridgeIo
,
2157 gPciBusDriverBinding
.DriverBindingHandle
,
2159 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2162 if (EFI_ERROR (Status
)) {
2166 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
2167 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2168 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2177 Add host bridge handle to global variable for enumerating.
2179 @param HostBridgeHandle Host bridge handle.
2181 @retval EFI_SUCCESS Successfully added host bridge.
2182 @retval EFI_ABORTED Host bridge is NULL, or given host bridge
2183 has been in host bridge list.
2187 AddHostBridgeEnumerator (
2188 IN EFI_HANDLE HostBridgeHandle
2193 if (HostBridgeHandle
== NULL
) {
2197 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2198 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2203 if (Index
< PCI_MAX_HOST_BRIDGE_NUM
) {
2204 gPciHostBrigeHandles
[Index
] = HostBridgeHandle
;
2205 gPciHostBridgeNumber
++;