2 PCI eunmeration implementation on entire PCI bus system for PCI Bus module.
4 Copyright (c) 2006 - 2009, 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
33 EFI_HANDLE HostBridgeHandle
;
35 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
36 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
39 // If PCI bus has already done the full enumeration, never do it again
41 if (!gFullEnumeration
) {
42 return PciEnumeratorLight (Controller
);
46 // Get the rootbridge Io protocol to find the host bridge handle
48 Status
= gBS
->OpenProtocol (
50 &gEfiPciRootBridgeIoProtocolGuid
,
51 (VOID
**) &PciRootBridgeIo
,
52 gPciBusDriverBinding
.DriverBindingHandle
,
54 EFI_OPEN_PROTOCOL_GET_PROTOCOL
57 if (EFI_ERROR (Status
)) {
62 // Get the host bridge handle
64 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
67 // Get the pci host bridge resource allocation protocol
69 Status
= gBS
->OpenProtocol (
71 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
72 (VOID
**) &PciResAlloc
,
73 gPciBusDriverBinding
.DriverBindingHandle
,
75 EFI_OPEN_PROTOCOL_GET_PROTOCOL
78 if (EFI_ERROR (Status
)) {
83 // Notify the pci bus enumeration is about to begin
85 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginEnumeration
);
88 // Start the bus allocation phase
90 Status
= PciHostBridgeEnumerator (PciResAlloc
);
92 if (EFI_ERROR (Status
)) {
97 // Submit the resource request
99 Status
= PciHostBridgeResourceAllocator (PciResAlloc
);
101 if (EFI_ERROR (Status
)) {
106 // Notify the pci bus enumeration is about to complete
108 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndEnumeration
);
113 Status
= PciHostBridgeP2CProcess (PciResAlloc
);
115 if (EFI_ERROR (Status
)) {
120 // Process attributes for devices on this host bridge
122 Status
= PciHostBridgeDeviceAttribute (PciResAlloc
);
123 if (EFI_ERROR (Status
)) {
127 gFullEnumeration
= FALSE
;
130 Status
= gBS
->InstallProtocolInterface (
132 &gEfiPciEnumerationCompleteProtocolGuid
,
133 EFI_NATIVE_INTERFACE
,
136 if (EFI_ERROR (Status
)) {
144 Enumerate PCI root bridge.
146 @param PciResAlloc Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
147 @param RootBridgeDev Instance of root bridge device.
149 @retval EFI_SUCCESS Successfully enumerated root bridge.
150 @retval other Failed to enumerate root bridge.
154 PciRootBridgeEnumerator (
155 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
156 IN PCI_IO_DEVICE
*RootBridgeDev
160 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
162 UINT8 StartBusNumber
;
163 UINT8 PaddedBusRange
;
164 EFI_HANDLE RootBridgeHandle
;
171 // Get the root bridge handle
173 RootBridgeHandle
= RootBridgeDev
->Handle
;
175 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
177 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_BUS_ENUM
,
178 RootBridgeDev
->DevicePath
182 // Get the Bus information
184 Status
= PciResAlloc
->StartBusEnumeration (
187 (VOID
**) &Configuration
190 if (EFI_ERROR (Status
)) {
195 // Get the bus number to start with
197 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
198 PaddedBusRange
= (UINT8
) (Configuration
->AddrRangeMax
);
201 // Initialize the subordinate bus number
203 SubBusNumber
= StartBusNumber
;
206 // Reset all assigned PCI bus number
208 ResetAllPpbBusNumber (
216 Status
= PciScanBus (
218 (UINT8
) (Configuration
->AddrRangeMin
),
223 if (EFI_ERROR (Status
)) {
229 // Assign max bus number scanned
231 Configuration
->AddrLen
= SubBusNumber
- StartBusNumber
+ 1 + PaddedBusRange
;
236 Status
= PciResAlloc
->SetBusNumbers (
242 FreePool (Configuration
);
244 if (EFI_ERROR (Status
)) {
252 This routine is used to process all PCI devices' Option Rom
253 on a certain root bridge.
255 @param Bridge Given parent's root bridge.
256 @param RomBase Base address of ROM driver loaded from.
257 @param MaxLength Maximum rom size.
262 IN PCI_IO_DEVICE
*Bridge
,
267 LIST_ENTRY
*CurrentLink
;
271 // Go through bridges to reach all devices
273 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
274 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
275 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
276 if (!IsListEmpty (&Temp
->ChildList
)) {
279 // Go further to process the option rom under this bridge
281 ProcessOptionRom (Temp
, RomBase
, MaxLength
);
284 if (Temp
->RomSize
!= 0 && Temp
->RomSize
<= MaxLength
) {
287 // Load and process the option rom
289 LoadOpRomImage (Temp
, RomBase
);
292 CurrentLink
= CurrentLink
->ForwardLink
;
297 This routine is used to assign bus number to the given PCI bus system
299 @param Bridge Parent root bridge instance.
300 @param StartBusNumber Number of beginning.
301 @param SubBusNumber The number of sub bus.
303 @retval EFI_SUCCESS Successfully assigned bus number.
304 @retval EFI_DEVICE_ERROR Failed to assign bus number.
309 IN PCI_IO_DEVICE
*Bridge
,
310 IN UINT8 StartBusNumber
,
311 OUT UINT8
*SubBusNumber
322 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
324 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
329 *SubBusNumber
= StartBusNumber
;
332 // First check to see whether the parent is ppb
334 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
335 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
338 // Check to see whether a pci device is present
340 Status
= PciDevicePresent (
348 if (!EFI_ERROR (Status
) &&
349 (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
352 // Reserved one bus for cardbus bridge
354 SecondBus
= ++(*SubBusNumber
);
356 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
358 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
360 Status
= PciRootBridgeIo
->Pci
.Write (
369 // Initialize SubBusNumber to SecondBus
371 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
372 Status
= PciRootBridgeIo
->Pci
.Write (
380 // If it is PPB, resursively search down this bridge
382 if (IS_PCI_BRIDGE (&Pci
)) {
385 Status
= PciRootBridgeIo
->Pci
.Write (
393 Status
= PciAssignBusNumber (
399 if (EFI_ERROR (Status
)) {
400 return EFI_DEVICE_ERROR
;
405 // Set the current maximum bus number under the PPB
407 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
409 Status
= PciRootBridgeIo
->Pci
.Write (
419 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
422 // Skip sub functions, this is not a multi function device
433 This routine is used to determine the root bridge attribute by interfacing
434 the host bridge resource allocation protocol.
436 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
437 @param RootBridgeDev Root bridge instance
439 @retval EFI_SUCCESS Successfully got root bridge's attribute.
440 @retval other Failed to get attribute.
444 DetermineRootBridgeAttributes (
445 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
446 IN PCI_IO_DEVICE
*RootBridgeDev
451 EFI_HANDLE RootBridgeHandle
;
454 RootBridgeHandle
= RootBridgeDev
->Handle
;
457 // Get root bridge attribute by calling into pci host bridge resource allocation protocol
459 Status
= PciResAlloc
->GetAllocAttributes (
465 if (EFI_ERROR (Status
)) {
470 // Here is the point where PCI bus driver calls HOST bridge allocation protocol
471 // Currently we hardcoded for ea815
473 if ((Attributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) {
474 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
;
477 if ((Attributes
& EFI_PCI_HOST_BRIDGE_MEM64_DECODE
) != 0) {
478 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM64_DECODE_SUPPORTED
;
479 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
482 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
483 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
484 RootBridgeDev
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
490 Get Max Option Rom size on specified bridge.
492 @param Bridge Given bridge device instance.
494 @return Max size of option rom needed.
498 GetMaxOptionRomSize (
499 IN PCI_IO_DEVICE
*Bridge
502 LIST_ENTRY
*CurrentLink
;
504 UINT64 MaxOptionRomSize
;
505 UINT64 TempOptionRomSize
;
507 MaxOptionRomSize
= 0;
510 // Go through bridges to reach all devices
512 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
513 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
514 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
515 if (!IsListEmpty (&Temp
->ChildList
)) {
518 // Get max option rom size under this bridge
520 TempOptionRomSize
= GetMaxOptionRomSize (Temp
);
523 // Compare with the option rom size of the bridge
524 // Get the larger one
526 if (Temp
->RomSize
> TempOptionRomSize
) {
527 TempOptionRomSize
= Temp
->RomSize
;
533 // For devices get the rom size directly
535 TempOptionRomSize
= Temp
->RomSize
;
539 // Get the largest rom size on this bridge
541 if (TempOptionRomSize
> MaxOptionRomSize
) {
542 MaxOptionRomSize
= TempOptionRomSize
;
545 CurrentLink
= CurrentLink
->ForwardLink
;
548 return MaxOptionRomSize
;
552 Process attributes of devices on this host bridge
554 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
556 @retval EFI_SUCCESS Successfully process attribute.
557 @retval EFI_NOT_FOUND Can not find the specific root bridge device.
558 @retval other Failed to determine the root bridge device's attribute.
562 PciHostBridgeDeviceAttribute (
563 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
566 EFI_HANDLE RootBridgeHandle
;
567 PCI_IO_DEVICE
*RootBridgeDev
;
570 RootBridgeHandle
= NULL
;
572 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
575 // Get RootBridg Device by handle
577 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
579 if (RootBridgeDev
== NULL
) {
580 return EFI_NOT_FOUND
;
584 // Set the attributes for devcies behind the Root Bridge
586 Status
= DetermineDeviceAttribute (RootBridgeDev
);
587 if (EFI_ERROR (Status
)) {
597 Get resource allocation status from the ACPI resource descriptor.
599 @param AcpiConfig Point to Acpi configuration table.
600 @param IoResStatus Return the status of I/O resource.
601 @param Mem32ResStatus Return the status of 32-bit Memory resource.
602 @param PMem32ResStatus Return the status of 32-bit Prefetchable Memory resource.
603 @param Mem64ResStatus Return the status of 64-bit Memory resource.
604 @param PMem64ResStatus Return the status of 64-bit Prefetchable Memory resource.
608 GetResourceAllocationStatus (
610 OUT UINT64
*IoResStatus
,
611 OUT UINT64
*Mem32ResStatus
,
612 OUT UINT64
*PMem32ResStatus
,
613 OUT UINT64
*Mem64ResStatus
,
614 OUT UINT64
*PMem64ResStatus
619 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*ACPIAddressDesc
;
621 Temp
= (UINT8
*) AcpiConfig
;
623 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
625 ACPIAddressDesc
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
626 ResStatus
= ACPIAddressDesc
->AddrTranslationOffset
;
628 switch (ACPIAddressDesc
->ResType
) {
630 if (ACPIAddressDesc
->AddrSpaceGranularity
== 32) {
631 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
635 *PMem32ResStatus
= ResStatus
;
640 *Mem32ResStatus
= ResStatus
;
644 if (ACPIAddressDesc
->AddrSpaceGranularity
== 64) {
645 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
649 *PMem64ResStatus
= ResStatus
;
654 *Mem64ResStatus
= ResStatus
;
664 *IoResStatus
= ResStatus
;
671 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
676 Remove a PCI device from device pool and mark its bar.
678 @param PciDevice Instance of Pci device.
680 @retval EFI_SUCCESS Successfully remove the PCI device.
681 @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
686 IN PCI_IO_DEVICE
*PciDevice
689 PCI_IO_DEVICE
*Bridge
;
691 LIST_ENTRY
*CurrentLink
;
694 // Remove the padding resource from a bridge
696 if ( IS_PCI_BRIDGE(&PciDevice
->Pci
) &&
697 PciDevice
->ResourcePaddingDescriptors
!= NULL
) {
698 FreePool (PciDevice
->ResourcePaddingDescriptors
);
699 PciDevice
->ResourcePaddingDescriptors
= NULL
;
706 if (IS_PCI_BRIDGE (&PciDevice
->Pci
) || (PciDevice
->Parent
== NULL
)) {
710 if (IS_CARDBUS_BRIDGE (&PciDevice
->Pci
)) {
712 // Get the root bridge device
715 while (Bridge
->Parent
!= NULL
) {
716 Bridge
= Bridge
->Parent
;
719 RemoveAllPciDeviceOnBridge (Bridge
->Handle
, PciDevice
);
724 InitializeP2C (PciDevice
);
730 Bridge
= PciDevice
->Parent
;
731 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
732 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
733 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
734 if (Temp
== PciDevice
) {
735 InitializePciDevice (Temp
);
736 RemoveEntryList (CurrentLink
);
737 FreePciDevice (Temp
);
741 CurrentLink
= CurrentLink
->ForwardLink
;
748 Determine whethter a PCI device can be rejected.
750 @param PciResNode Pointer to Pci resource node instance.
752 @retval TRUE The PCI device can be rejected.
753 @retval TRUE The PCI device cannot be rejected.
758 IN PCI_RESOURCE_NODE
*PciResNode
763 Temp
= PciResNode
->PciDev
;
766 // Ensure the device is present
773 // PPB and RB should go ahead
775 if (IS_PCI_BRIDGE (&Temp
->Pci
) || (Temp
->Parent
== NULL
)) {
780 // Skip device on Bus0
782 if ((Temp
->Parent
!= NULL
) && (Temp
->BusNumber
== 0)) {
789 if (IS_PCI_VGA (&Temp
->Pci
)) {
797 Compare two resource nodes and get the larger resource consumer.
799 @param PciResNode1 resource node 1 want to be compared
800 @param PciResNode2 resource node 2 want to be compared
802 @return Larger resource node.
806 GetLargerConsumerDevice (
807 IN PCI_RESOURCE_NODE
*PciResNode1
,
808 IN PCI_RESOURCE_NODE
*PciResNode2
811 if (PciResNode2
== NULL
) {
815 if ((IS_PCI_BRIDGE(&(PciResNode2
->PciDev
->Pci
)) || (PciResNode2
->PciDev
->Parent
== NULL
)) \
816 && (PciResNode2
->ResourceUsage
!= PciResUsagePadding
) )
821 if (PciResNode1
== NULL
) {
825 if ((PciResNode1
->Length
) > (PciResNode2
->Length
)) {
834 Get the max resource consumer in the host resource pool.
836 @param ResPool Pointer to resource pool node.
838 @return The max resource consumer in the host resource pool.
842 GetMaxResourceConsumerDevice (
843 IN PCI_RESOURCE_NODE
*ResPool
846 PCI_RESOURCE_NODE
*Temp
;
847 LIST_ENTRY
*CurrentLink
;
848 PCI_RESOURCE_NODE
*PciResNode
;
849 PCI_RESOURCE_NODE
*PPBResNode
;
853 CurrentLink
= ResPool
->ChildList
.ForwardLink
;
854 while (CurrentLink
!= NULL
&& CurrentLink
!= &ResPool
->ChildList
) {
856 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
858 if (!IsRejectiveDevice (Temp
)) {
859 CurrentLink
= CurrentLink
->ForwardLink
;
863 if ((IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
)) || (Temp
->PciDev
->Parent
== NULL
)) \
864 && (Temp
->ResourceUsage
!= PciResUsagePadding
))
866 PPBResNode
= GetMaxResourceConsumerDevice (Temp
);
867 PciResNode
= GetLargerConsumerDevice (PciResNode
, PPBResNode
);
869 PciResNode
= GetLargerConsumerDevice (PciResNode
, Temp
);
872 CurrentLink
= CurrentLink
->ForwardLink
;
879 Adjust host bridge allocation so as to reduce resource requirement
881 @param IoPool Pointer to instance of I/O resource Node.
882 @param Mem32Pool Pointer to instance of 32-bit memory resource Node.
883 @param PMem32Pool Pointer to instance of 32-bit Prefetchable memory resource node.
884 @param Mem64Pool Pointer to instance of 64-bit memory resource node.
885 @param PMem64Pool Pointer to instance of 64-bit Prefetchable memory resource node.
886 @param IoResStatus Status of I/O resource Node.
887 @param Mem32ResStatus Status of 32-bit memory resource Node.
888 @param PMem32ResStatus Status of 32-bit Prefetchable memory resource node.
889 @param Mem64ResStatus Status of 64-bit memory resource node.
890 @param PMem64ResStatus Status of 64-bit Prefetchable memory resource node.
892 @retval EFI_SUCCESS Successfully adjusted resoruce on host bridge.
893 @retval EFI_ABORTED Host bridge hasn't this resource type or no resource be adjusted.
897 PciHostBridgeAdjustAllocation (
898 IN PCI_RESOURCE_NODE
*IoPool
,
899 IN PCI_RESOURCE_NODE
*Mem32Pool
,
900 IN PCI_RESOURCE_NODE
*PMem32Pool
,
901 IN PCI_RESOURCE_NODE
*Mem64Pool
,
902 IN PCI_RESOURCE_NODE
*PMem64Pool
,
903 IN UINT64 IoResStatus
,
904 IN UINT64 Mem32ResStatus
,
905 IN UINT64 PMem32ResStatus
,
906 IN UINT64 Mem64ResStatus
,
907 IN UINT64 PMem64ResStatus
910 BOOLEAN AllocationAjusted
;
911 PCI_RESOURCE_NODE
*PciResNode
;
912 PCI_RESOURCE_NODE
*ResPool
[5];
913 PCI_IO_DEVICE
*RemovedPciDev
[5];
915 UINTN RemovedPciDevNum
;
919 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
922 ZeroMem (RemovedPciDev
, 5 * sizeof (PCI_IO_DEVICE
*));
923 RemovedPciDevNum
= 0;
926 ResPool
[1] = Mem32Pool
;
927 ResPool
[2] = PMem32Pool
;
928 ResPool
[3] = Mem64Pool
;
929 ResPool
[4] = PMem64Pool
;
931 ResStatus
[0] = IoResStatus
;
932 ResStatus
[1] = Mem32ResStatus
;
933 ResStatus
[2] = PMem32ResStatus
;
934 ResStatus
[3] = Mem64ResStatus
;
935 ResStatus
[4] = PMem64ResStatus
;
937 AllocationAjusted
= FALSE
;
939 for (ResType
= 0; ResType
< 5; ResType
++) {
941 if (ResStatus
[ResType
] == EFI_RESOURCE_SATISFIED
) {
945 if (ResStatus
[ResType
] == EFI_RESOURCE_NOT_SATISFIED
) {
947 // Host bridge hasn't this resource type
953 // Hostbridge hasn't enough resource
955 PciResNode
= GetMaxResourceConsumerDevice (ResPool
[ResType
]);
956 if (PciResNode
== NULL
) {
961 // Check if the device has been removed before
963 for (DevIndex
= 0; DevIndex
< RemovedPciDevNum
; DevIndex
++) {
964 if (PciResNode
->PciDev
== RemovedPciDev
[DevIndex
]) {
969 if (DevIndex
!= RemovedPciDevNum
) {
974 // Remove the device if it isn't in the array
976 Status
= RejectPciDevice (PciResNode
->PciDev
);
977 if (Status
== EFI_SUCCESS
) {
980 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
983 // Have no way to get ReqRes, AllocRes & Bar here
985 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
986 AllocFailExtendedData
.DevicePathSize
= (UINT16
) sizeof (EFI_DEVICE_PATH_PROTOCOL
);
987 AllocFailExtendedData
.DevicePath
= (UINT8
*) PciResNode
->PciDev
->DevicePath
;
988 AllocFailExtendedData
.Bar
= PciResNode
->Bar
;
990 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
992 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
993 (VOID
*) &AllocFailExtendedData
,
994 sizeof (AllocFailExtendedData
)
998 // Add it to the array and indicate at least a device has been rejected
1000 RemovedPciDev
[RemovedPciDevNum
++] = PciResNode
->PciDev
;
1001 AllocationAjusted
= TRUE
;
1008 if (AllocationAjusted
) {
1016 Summary requests for all resource type, and contruct ACPI resource
1019 @param Bridge detecting bridge
1020 @param IoNode Pointer to instance of I/O resource Node
1021 @param Mem32Node Pointer to instance of 32-bit memory resource Node
1022 @param PMem32Node Pointer to instance of 32-bit Pmemory resource node
1023 @param Mem64Node Pointer to instance of 64-bit memory resource node
1024 @param PMem64Node Pointer to instance of 64-bit Pmemory resource node
1025 @param Config Output buffer holding new constructed APCI resource requestor
1027 @retval EFI_SUCCESS Successfully constructed ACPI resource.
1028 @retval EFI_OUT_OF_RESOURCES No memory availabe.
1032 ConstructAcpiResourceRequestor (
1033 IN PCI_IO_DEVICE
*Bridge
,
1034 IN PCI_RESOURCE_NODE
*IoNode
,
1035 IN PCI_RESOURCE_NODE
*Mem32Node
,
1036 IN PCI_RESOURCE_NODE
*PMem32Node
,
1037 IN PCI_RESOURCE_NODE
*Mem64Node
,
1038 IN PCI_RESOURCE_NODE
*PMem64Node
,
1044 UINT8
*Configuration
;
1045 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1046 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
1054 // if there is io request, add to the io aperture
1056 if (ResourceRequestExisted (IoNode
)) {
1062 // if there is mem32 request, add to the mem32 aperture
1064 if (ResourceRequestExisted (Mem32Node
)) {
1070 // if there is pmem32 request, add to the pmem32 aperture
1072 if (ResourceRequestExisted (PMem32Node
)) {
1078 // if there is mem64 request, add to the mem64 aperture
1080 if (ResourceRequestExisted (Mem64Node
)) {
1086 // if there is pmem64 request, add to the pmem64 aperture
1088 if (ResourceRequestExisted (PMem64Node
)) {
1093 if (NumConfig
!= 0) {
1096 // If there is at least one type of resource request,
1097 // allocate a acpi resource node
1099 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1100 if (Configuration
== NULL
) {
1101 return EFI_OUT_OF_RESOURCES
;
1104 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1107 // Deal with io aperture
1109 if ((Aperture
& 0x01) != 0) {
1110 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1111 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1115 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1119 Ptr
->SpecificFlag
= 1;
1120 Ptr
->AddrLen
= IoNode
->Length
;
1121 Ptr
->AddrRangeMax
= IoNode
->Alignment
;
1126 // Deal with mem32 aperture
1128 if ((Aperture
& 0x02) != 0) {
1129 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1130 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1134 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1138 Ptr
->SpecificFlag
= 0;
1142 Ptr
->AddrSpaceGranularity
= 32;
1143 Ptr
->AddrLen
= Mem32Node
->Length
;
1144 Ptr
->AddrRangeMax
= Mem32Node
->Alignment
;
1150 // Deal with Pmem32 aperture
1152 if ((Aperture
& 0x04) != 0) {
1153 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1154 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1158 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1162 Ptr
->SpecificFlag
= 0x6;
1166 Ptr
->AddrSpaceGranularity
= 32;
1167 Ptr
->AddrLen
= PMem32Node
->Length
;
1168 Ptr
->AddrRangeMax
= PMem32Node
->Alignment
;
1173 // Deal with mem64 aperture
1175 if ((Aperture
& 0x08) != 0) {
1176 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1177 Ptr
->Len
= (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3);
1181 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1185 Ptr
->SpecificFlag
= 0;
1189 Ptr
->AddrSpaceGranularity
= 64;
1190 Ptr
->AddrLen
= Mem64Node
->Length
;
1191 Ptr
->AddrRangeMax
= Mem64Node
->Alignment
;
1196 // Deal with Pmem64 aperture
1198 if ((Aperture
& 0x10) != 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
= 0x06;
1212 Ptr
->AddrSpaceGranularity
= 64;
1213 Ptr
->AddrLen
= PMem64Node
->Length
;
1214 Ptr
->AddrRangeMax
= PMem64Node
->Alignment
;
1222 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
;
1224 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1225 PtrEnd
->Checksum
= 0;
1230 // If there is no resource request
1232 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1233 if (Configuration
== NULL
) {
1234 return EFI_OUT_OF_RESOURCES
;
1237 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (Configuration
);
1238 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1240 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Ptr
+ 1);
1241 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1242 PtrEnd
->Checksum
= 0;
1245 *Config
= Configuration
;
1251 Get resource base from an acpi configuration descriptor.
1253 @param Config An acpi configuration descriptor.
1254 @param IoBase Output of I/O resource base address.
1255 @param Mem32Base Output of 32-bit memory base address.
1256 @param PMem32Base Output of 32-bit prefetchable memory base address.
1257 @param Mem64Base Output of 64-bit memory base address.
1258 @param PMem64Base Output of 64-bit prefetchable memory base address.
1265 OUT UINT64
*Mem32Base
,
1266 OUT UINT64
*PMem32Base
,
1267 OUT UINT64
*Mem64Base
,
1268 OUT UINT64
*PMem64Base
1272 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1275 ASSERT (Config
!= NULL
);
1277 *IoBase
= 0xFFFFFFFFFFFFFFFFULL
;
1278 *Mem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1279 *PMem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1280 *Mem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1281 *PMem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1283 Temp
= (UINT8
*) Config
;
1285 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1287 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1288 ResStatus
= Ptr
->AddrTranslationOffset
;
1290 if (ResStatus
== EFI_RESOURCE_SATISFIED
) {
1292 switch (Ptr
->ResType
) {
1295 // Memory type aperture
1300 // Check to see the granularity
1302 if (Ptr
->AddrSpaceGranularity
== 32) {
1303 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1304 *PMem32Base
= Ptr
->AddrRangeMin
;
1306 *Mem32Base
= Ptr
->AddrRangeMin
;
1310 if (Ptr
->AddrSpaceGranularity
== 64) {
1311 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1312 *PMem64Base
= Ptr
->AddrRangeMin
;
1314 *Mem64Base
= Ptr
->AddrRangeMin
;
1324 *IoBase
= Ptr
->AddrRangeMin
;
1338 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1343 Enumerate pci bridge, allocate resource and determine attribute
1344 for devices on this bridge.
1346 @param BridgeDev Pointer to instance of bridge device.
1348 @retval EFI_SUCCESS Successfully enumerated PCI bridge.
1349 @retval other Failed to enumerate.
1353 PciBridgeEnumerator (
1354 IN PCI_IO_DEVICE
*BridgeDev
1358 UINT8 StartBusNumber
;
1359 EFI_PCI_IO_PROTOCOL
*PciIo
;
1364 PciIo
= &(BridgeDev
->PciIo
);
1365 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x19, 1, &StartBusNumber
);
1367 if (EFI_ERROR (Status
)) {
1371 Status
= PciAssignBusNumber (
1377 if (EFI_ERROR (Status
)) {
1381 Status
= PciPciDeviceInfoCollector (BridgeDev
, StartBusNumber
);
1383 if (EFI_ERROR (Status
)) {
1387 Status
= PciBridgeResourceAllocator (BridgeDev
);
1389 if (EFI_ERROR (Status
)) {
1393 Status
= DetermineDeviceAttribute (BridgeDev
);
1395 if (EFI_ERROR (Status
)) {
1404 Allocate all kinds of resource for PCI bridge.
1406 @param Bridge Pointer to bridge instance.
1408 @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
1409 @retval other Failed to allocate resource for bridge.
1413 PciBridgeResourceAllocator (
1414 IN PCI_IO_DEVICE
*Bridge
1417 PCI_RESOURCE_NODE
*IoBridge
;
1418 PCI_RESOURCE_NODE
*Mem32Bridge
;
1419 PCI_RESOURCE_NODE
*PMem32Bridge
;
1420 PCI_RESOURCE_NODE
*Mem64Bridge
;
1421 PCI_RESOURCE_NODE
*PMem64Bridge
;
1429 IoBridge
= CreateResourceNode (
1432 Bridge
->BridgeIoAlignment
,
1438 Mem32Bridge
= CreateResourceNode (
1447 PMem32Bridge
= CreateResourceNode (
1456 Mem64Bridge
= CreateResourceNode (
1465 PMem64Bridge
= CreateResourceNode (
1475 // Create resourcemap by going through all the devices subject to this root bridge
1486 Status
= GetResourceBaseFromBridge (
1495 if (EFI_ERROR (Status
)) {
1500 // Program IO resources
1508 // Program Mem32 resources
1516 // Program PMem32 resources
1524 // Program Mem64 resources
1532 // Program PMem64 resources
1539 DestroyResourceTree (IoBridge
);
1540 DestroyResourceTree (Mem32Bridge
);
1541 DestroyResourceTree (PMem32Bridge
);
1542 DestroyResourceTree (PMem64Bridge
);
1543 DestroyResourceTree (Mem64Bridge
);
1545 gBS
->FreePool (IoBridge
);
1546 gBS
->FreePool (Mem32Bridge
);
1547 gBS
->FreePool (PMem32Bridge
);
1548 gBS
->FreePool (PMem64Bridge
);
1549 gBS
->FreePool (Mem64Bridge
);
1555 Get resource base address for a pci bridge device.
1557 @param Bridge Given Pci driver instance.
1558 @param IoBase Output for base address of I/O type resource.
1559 @param Mem32Base Output for base address of 32-bit memory type resource.
1560 @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
1561 @param Mem64Base Output for base address of 64-bit memory type resource.
1562 @param PMem64Base Output for base address of 64-bit Pmemory type resource.
1564 @retval EFI_SUCCESS Successfully got resource base address.
1565 @retval EFI_OUT_OF_RESOURCES PCI bridge is not available.
1569 GetResourceBaseFromBridge (
1570 IN PCI_IO_DEVICE
*Bridge
,
1572 OUT UINT64
*Mem32Base
,
1573 OUT UINT64
*PMem32Base
,
1574 OUT UINT64
*Mem64Base
,
1575 OUT UINT64
*PMem64Base
1578 if (!Bridge
->Allocated
) {
1579 return EFI_OUT_OF_RESOURCES
;
1583 *Mem32Base
= gAllOne
;
1584 *PMem32Base
= gAllOne
;
1585 *Mem64Base
= gAllOne
;
1586 *PMem64Base
= gAllOne
;
1588 if (IS_PCI_BRIDGE (&Bridge
->Pci
)) {
1590 if (Bridge
->PciBar
[PPB_IO_RANGE
].Length
> 0) {
1591 *IoBase
= Bridge
->PciBar
[PPB_IO_RANGE
].BaseAddress
;
1594 if (Bridge
->PciBar
[PPB_MEM32_RANGE
].Length
> 0) {
1595 *Mem32Base
= Bridge
->PciBar
[PPB_MEM32_RANGE
].BaseAddress
;
1598 if (Bridge
->PciBar
[PPB_PMEM32_RANGE
].Length
> 0) {
1599 *PMem32Base
= Bridge
->PciBar
[PPB_PMEM32_RANGE
].BaseAddress
;
1602 if (Bridge
->PciBar
[PPB_PMEM64_RANGE
].Length
> 0) {
1603 *PMem64Base
= Bridge
->PciBar
[PPB_PMEM64_RANGE
].BaseAddress
;
1605 *PMem64Base
= gAllOne
;
1610 if (IS_CARDBUS_BRIDGE (&Bridge
->Pci
)) {
1611 if (Bridge
->PciBar
[P2C_IO_1
].Length
> 0) {
1612 *IoBase
= Bridge
->PciBar
[P2C_IO_1
].BaseAddress
;
1614 if (Bridge
->PciBar
[P2C_IO_2
].Length
> 0) {
1615 *IoBase
= Bridge
->PciBar
[P2C_IO_2
].BaseAddress
;
1619 if (Bridge
->PciBar
[P2C_MEM_1
].Length
> 0) {
1620 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypePMem32
) {
1621 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1624 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypeMem32
) {
1625 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1629 if (Bridge
->PciBar
[P2C_MEM_2
].Length
> 0) {
1630 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypePMem32
) {
1631 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1634 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypeMem32
) {
1635 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1644 These are the notifications from the PCI bus driver that it is about to enter a certain
1645 phase of the PCI enumeration process.
1647 This member function can be used to notify the host bridge driver to perform specific actions,
1648 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1649 Eight notification points are defined at this time. See belows:
1650 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
1651 structures. The PCI enumerator should issue this notification
1652 before starting a fresh enumeration process. Enumeration cannot
1653 be restarted after sending any other notification such as
1654 EfiPciHostBridgeBeginBusAllocation.
1655 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
1656 required here. This notification can be used to perform any
1657 chipset-specific programming.
1658 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
1659 specific action is required here. This notification can be used to
1660 perform any chipset-specific programming.
1661 EfiPciHostBridgeBeginResourceAllocation
1662 The resource allocation phase is about to begin. No specific
1663 action is required here. This notification can be used to perform
1664 any chipset-specific programming.
1665 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
1666 root bridges. These resource settings are returned on the next call to
1667 GetProposedResources(). Before calling NotifyPhase() with a Phase of
1668 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
1669 for gathering I/O and memory requests for
1670 all the PCI root bridges and submitting these requests using
1671 SubmitResources(). This function pads the resource amount
1672 to suit the root bridge hardware, takes care of dependencies between
1673 the PCI root bridges, and calls the Global Coherency Domain (GCD)
1674 with the allocation request. In the case of padding, the allocated range
1675 could be bigger than what was requested.
1676 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
1677 resources (proposed resources) for all the PCI root bridges. After the
1678 hardware is programmed, reassigning resources will not be supported.
1679 The bus settings are not affected.
1680 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
1681 root bridges and resets the I/O and memory apertures to their initial
1682 state. The bus settings are not affected. If the request to allocate
1683 resources fails, the PCI enumerator can use this notification to
1684 deallocate previous resources, adjust the requests, and retry
1686 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
1687 required here. This notification can be used to perform any chipsetspecific
1690 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1691 @param[in] Phase The phase during enumeration
1693 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
1694 is valid for a Phase of EfiPciHostBridgeAllocateResources if
1695 SubmitResources() has not been called for one or more
1696 PCI root bridges before this call
1697 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
1698 for a Phase of EfiPciHostBridgeSetResources.
1699 @retval EFI_INVALID_PARAMETER Invalid phase parameter
1700 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1701 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1702 previously submitted resource requests cannot be fulfilled or
1703 were only partially fulfilled.
1704 @retval EFI_SUCCESS The notification was accepted without any errors.
1709 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
1710 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1713 EFI_HANDLE HostBridgeHandle
;
1714 EFI_HANDLE RootBridgeHandle
;
1715 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1718 HostBridgeHandle
= NULL
;
1719 RootBridgeHandle
= NULL
;
1720 if (gPciPlatformProtocol
!= NULL
) {
1722 // Get Host Bridge Handle.
1724 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1727 // Get the rootbridge Io protocol to find the host bridge handle
1729 Status
= gBS
->HandleProtocol (
1731 &gEfiPciRootBridgeIoProtocolGuid
,
1732 (VOID
**) &PciRootBridgeIo
1735 if (EFI_ERROR (Status
)) {
1736 return EFI_NOT_FOUND
;
1739 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1742 // Call PlatformPci::PlatformNotify() if the protocol is present.
1744 gPciPlatformProtocol
->PlatformNotify (
1745 gPciPlatformProtocol
,
1750 } else if (gPciOverrideProtocol
!= NULL
){
1752 // Get Host Bridge Handle.
1754 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1757 // Get the rootbridge Io protocol to find the host bridge handle
1759 Status
= gBS
->HandleProtocol (
1761 &gEfiPciRootBridgeIoProtocolGuid
,
1762 (VOID
**) &PciRootBridgeIo
1765 if (EFI_ERROR (Status
)) {
1766 return EFI_NOT_FOUND
;
1769 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1772 // Call PlatformPci::PhaseNotify() if the protocol is present.
1774 gPciOverrideProtocol
->PlatformNotify (
1775 gPciOverrideProtocol
,
1782 Status
= PciResAlloc
->NotifyPhase (
1787 if (gPciPlatformProtocol
!= NULL
) {
1789 // Call PlatformPci::PlatformNotify() if the protocol is present.
1791 gPciPlatformProtocol
->PlatformNotify (
1792 gPciPlatformProtocol
,
1798 } else if (gPciOverrideProtocol
!= NULL
) {
1800 // Call PlatformPci::PhaseNotify() if the protocol is present.
1802 gPciOverrideProtocol
->PlatformNotify (
1803 gPciOverrideProtocol
,
1814 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1815 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1816 PCI controllers before enumeration.
1818 This function is called during the PCI enumeration process. No specific action is expected from this
1819 member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1822 @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1823 @param Bus The bus number of the pci device.
1824 @param Device The device number of the pci device.
1825 @param Func The function number of the pci device.
1826 @param Phase The phase of the PCI device enumeration.
1828 @retval EFI_SUCCESS The requested parameters were returned.
1829 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
1830 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
1831 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1832 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
1833 not enumerate this device, including its child devices if it is a PCI-to-PCI
1838 PreprocessController (
1839 IN PCI_IO_DEVICE
*Bridge
,
1843 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1846 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress
;
1847 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
1848 EFI_HANDLE RootBridgeHandle
;
1849 EFI_HANDLE HostBridgeHandle
;
1853 // Get the host bridge handle
1855 HostBridgeHandle
= Bridge
->PciRootBridgeIo
->ParentHandle
;
1858 // Get the pci host bridge resource allocation protocol
1860 Status
= gBS
->OpenProtocol (
1862 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
1863 (VOID
**) &PciResAlloc
,
1866 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1869 if (EFI_ERROR (Status
)) {
1870 return EFI_UNSUPPORTED
;
1874 // Get Root Brige Handle
1876 while (Bridge
->Parent
!= NULL
) {
1877 Bridge
= Bridge
->Parent
;
1880 RootBridgeHandle
= Bridge
->Handle
;
1882 RootBridgePciAddress
.Register
= 0;
1883 RootBridgePciAddress
.Function
= Func
;
1884 RootBridgePciAddress
.Device
= Device
;
1885 RootBridgePciAddress
.Bus
= Bus
;
1886 RootBridgePciAddress
.ExtendedRegister
= 0;
1888 if (gPciPlatformProtocol
!= NULL
) {
1890 // Call PlatformPci::PrepController() if the protocol is present.
1892 gPciPlatformProtocol
->PlatformPrepController (
1893 gPciPlatformProtocol
,
1896 RootBridgePciAddress
,
1900 } else if (gPciOverrideProtocol
!= NULL
) {
1902 // Call PlatformPci::PrepController() if the protocol is present.
1904 gPciOverrideProtocol
->PlatformPrepController (
1905 gPciOverrideProtocol
,
1908 RootBridgePciAddress
,
1914 Status
= PciResAlloc
->PreprocessController (
1917 RootBridgePciAddress
,
1921 if (gPciPlatformProtocol
!= NULL
) {
1923 // Call PlatformPci::PrepController() if the protocol is present.
1925 gPciPlatformProtocol
->PlatformPrepController (
1926 gPciPlatformProtocol
,
1929 RootBridgePciAddress
,
1933 } else if (gPciOverrideProtocol
!= NULL
) {
1935 // Call PlatformPci::PrepController() if the protocol is present.
1937 gPciOverrideProtocol
->PlatformPrepController (
1938 gPciOverrideProtocol
,
1941 RootBridgePciAddress
,
1951 This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
1952 happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
1954 @param This A pointer to the hot plug request protocol.
1955 @param Operation The operation the PCI bus driver is requested to make.
1956 @param Controller The handle of the hot-plug controller.
1957 @param RemainingDevicePath The remaining device path for the PCI-like hot-plug device.
1958 @param NumberOfChildren The number of child handles.
1959 For a add operation, it is an output parameter.
1960 For a remove operation, it's an input parameter.
1961 @param ChildHandleBuffer The buffer which contains the child handles.
1963 @retval EFI_INVALID_PARAMETER Operation is not a legal value.
1964 Controller is NULL or not a valid handle.
1965 NumberOfChildren is NULL.
1966 ChildHandleBuffer is NULL while Operation is add.
1967 @retval EFI_OUT_OF_RESOURCES There are no enough resources to start the devices.
1968 @retval EFI_NOT_FOUND Can not find bridge according to controller handle.
1969 @retval EFI_SUCCESS The handles for the specified device have been created or destroyed
1970 as requested, and for an add operation, the new handles are
1971 returned in ChildHandleBuffer.
1975 PciHotPlugRequestNotify (
1976 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL
* This
,
1977 IN EFI_PCI_HOTPLUG_OPERATION Operation
,
1978 IN EFI_HANDLE Controller
,
1979 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
,
1980 IN OUT UINT8
*NumberOfChildren
,
1981 IN OUT EFI_HANDLE
* ChildHandleBuffer
1984 PCI_IO_DEVICE
*Bridge
;
1985 PCI_IO_DEVICE
*Temp
;
1986 EFI_PCI_IO_PROTOCOL
*PciIo
;
1988 EFI_HANDLE RootBridgeHandle
;
1992 // Check input parameter validity
1994 if ((Controller
== NULL
) || (NumberOfChildren
== NULL
)){
1995 return EFI_INVALID_PARAMETER
;
1998 if ((Operation
!= EfiPciHotPlugRequestAdd
) && (Operation
!= EfiPciHotplugRequestRemove
)) {
1999 return EFI_INVALID_PARAMETER
;
2002 if (Operation
== EfiPciHotPlugRequestAdd
){
2003 if (ChildHandleBuffer
== NULL
) {
2004 return EFI_INVALID_PARAMETER
;
2006 } else if ((Operation
== EfiPciHotplugRequestRemove
) && (*NumberOfChildren
!= 0)) {
2007 if (ChildHandleBuffer
== NULL
) {
2008 return EFI_INVALID_PARAMETER
;
2012 Status
= gBS
->OpenProtocol (
2014 &gEfiPciIoProtocolGuid
,
2016 gPciBusDriverBinding
.DriverBindingHandle
,
2018 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2021 if (EFI_ERROR (Status
)) {
2022 return EFI_NOT_FOUND
;
2025 Bridge
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
2028 // Get root bridge handle
2031 while (Temp
->Parent
!= NULL
) {
2032 Temp
= Temp
->Parent
;
2035 RootBridgeHandle
= Temp
->Handle
;
2037 if (Operation
== EfiPciHotPlugRequestAdd
) {
2039 if (NumberOfChildren
!= NULL
) {
2040 *NumberOfChildren
= 0;
2043 if (IsListEmpty (&Bridge
->ChildList
)) {
2045 Status
= PciBridgeEnumerator (Bridge
);
2047 if (EFI_ERROR (Status
)) {
2052 Status
= StartPciDevicesOnBridge (
2055 RemainingDevicePath
,
2063 if (Operation
== EfiPciHotplugRequestRemove
) {
2065 if (*NumberOfChildren
== 0) {
2067 // Remove all devices on the bridge
2069 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Bridge
);
2074 for (Index
= 0; Index
< *NumberOfChildren
; Index
++) {
2076 // De register all the pci device
2078 Status
= DeRegisterPciDevice (RootBridgeHandle
, ChildHandleBuffer
[Index
]);
2080 if (EFI_ERROR (Status
)) {
2095 Search hostbridge according to given handle
2097 @param RootBridgeHandle Host bridge handle.
2099 @retval TRUE Found host bridge handle.
2100 @retval FALSE Not found hot bridge handle.
2104 SearchHostBridgeHandle (
2105 IN EFI_HANDLE RootBridgeHandle
2108 EFI_HANDLE HostBridgeHandle
;
2109 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2114 // Get the rootbridge Io protocol to find the host bridge handle
2116 Status
= gBS
->OpenProtocol (
2118 &gEfiPciRootBridgeIoProtocolGuid
,
2119 (VOID
**) &PciRootBridgeIo
,
2120 gPciBusDriverBinding
.DriverBindingHandle
,
2122 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2125 if (EFI_ERROR (Status
)) {
2129 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
2130 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2131 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2140 Add host bridge handle to global variable for enumerating.
2142 @param HostBridgeHandle Host bridge handle.
2144 @retval EFI_SUCCESS Successfully added host bridge.
2145 @retval EFI_ABORTED Host bridge is NULL, or given host bridge
2146 has been in host bridge list.
2150 AddHostBridgeEnumerator (
2151 IN EFI_HANDLE HostBridgeHandle
2156 if (HostBridgeHandle
== NULL
) {
2160 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2161 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2166 if (Index
< PCI_MAX_HOST_BRIDGE_NUM
) {
2167 gPciHostBrigeHandles
[Index
] = HostBridgeHandle
;
2168 gPciHostBridgeNumber
++;