2 PCI eunmeration implementation on entire PCI bus system for PCI Bus module.
4 Copyright (c) 2006 - 2009, Intel Corporation
5 All rights reserved. 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
)) {
108 Status
= PciHostBridgeP2CProcess (PciResAlloc
);
110 if (EFI_ERROR (Status
)) {
115 // Process attributes for devices on this host bridge
117 Status
= PciHostBridgeDeviceAttribute (PciResAlloc
);
118 if (EFI_ERROR (Status
)) {
122 gFullEnumeration
= FALSE
;
128 Enumerate PCI root bridge.
130 @param PciResAlloc Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
131 @param RootBridgeDev Instance of root bridge device.
133 @retval EFI_SUCCESS Successfully enumerated root bridge.
134 @retval other Failed to enumerate root bridge.
138 PciRootBridgeEnumerator (
139 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
140 IN PCI_IO_DEVICE
*RootBridgeDev
144 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
146 UINT8 StartBusNumber
;
147 UINT8 PaddedBusRange
;
148 EFI_HANDLE RootBridgeHandle
;
155 // Get the root bridge handle
157 RootBridgeHandle
= RootBridgeDev
->Handle
;
159 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
161 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_BUS_ENUM
,
162 RootBridgeDev
->DevicePath
166 // Get the Bus information
168 Status
= PciResAlloc
->StartBusEnumeration (
171 (VOID
**) &Configuration
174 if (EFI_ERROR (Status
)) {
179 // Get the bus number to start with
181 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
182 PaddedBusRange
= (UINT8
) (Configuration
->AddrRangeMax
);
185 // Initialize the subordinate bus number
187 SubBusNumber
= StartBusNumber
;
190 // Reset all assigned PCI bus number
192 ResetAllPpbBusNumber (
200 Status
= PciScanBus (
202 (UINT8
) (Configuration
->AddrRangeMin
),
207 if (EFI_ERROR (Status
)) {
213 // Assign max bus number scanned
215 Configuration
->AddrLen
= SubBusNumber
- StartBusNumber
+ 1 + PaddedBusRange
;
220 Status
= PciResAlloc
->SetBusNumbers (
226 FreePool (Configuration
);
228 if (EFI_ERROR (Status
)) {
236 This routine is used to process all PCI devices' Option Rom
237 on a certain root bridge.
239 @param Bridge Given parent's root bridge.
240 @param RomBase Base address of ROM driver loaded from.
241 @param MaxLength Maximum rom size.
246 IN PCI_IO_DEVICE
*Bridge
,
251 LIST_ENTRY
*CurrentLink
;
255 // Go through bridges to reach all devices
257 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
258 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
259 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
260 if (!IsListEmpty (&Temp
->ChildList
)) {
263 // Go further to process the option rom under this bridge
265 ProcessOptionRom (Temp
, RomBase
, MaxLength
);
268 if (Temp
->RomSize
!= 0 && Temp
->RomSize
<= MaxLength
) {
271 // Load and process the option rom
273 LoadOpRomImage (Temp
, RomBase
);
276 CurrentLink
= CurrentLink
->ForwardLink
;
281 This routine is used to assign bus number to the given PCI bus system
283 @param Bridge Parent root bridge instance.
284 @param StartBusNumber Number of beginning.
285 @param SubBusNumber The number of sub bus.
287 @retval EFI_SUCCESS Successfully assigned bus number.
288 @retval EFI_DEVICE_ERROR Failed to assign bus number.
293 IN PCI_IO_DEVICE
*Bridge
,
294 IN UINT8 StartBusNumber
,
295 OUT UINT8
*SubBusNumber
306 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
308 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
313 *SubBusNumber
= StartBusNumber
;
316 // First check to see whether the parent is ppb
318 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
319 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
322 // Check to see whether a pci device is present
324 Status
= PciDevicePresent (
332 if (!EFI_ERROR (Status
) &&
333 (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
336 // Reserved one bus for cardbus bridge
338 SecondBus
= ++(*SubBusNumber
);
340 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
342 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
344 Status
= PciRootBridgeIoWrite (
354 // Initialize SubBusNumber to SecondBus
356 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
357 Status
= PciRootBridgeIoWrite (
366 // If it is PPB, resursively search down this bridge
368 if (IS_PCI_BRIDGE (&Pci
)) {
371 Status
= PciRootBridgeIoWrite (
380 Status
= PciAssignBusNumber (
386 if (EFI_ERROR (Status
)) {
387 return EFI_DEVICE_ERROR
;
392 // Set the current maximum bus number under the PPB
394 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
396 Status
= PciRootBridgeIoWrite (
407 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
410 // Skip sub functions, this is not a multi function device
421 This routine is used to determine the root bridge attribute by interfacing
422 the host bridge resource allocation protocol.
424 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
425 @param RootBridgeDev Root bridge instance
427 @retval EFI_SUCCESS Successfully got root bridge's attribute.
428 @retval other Failed to get attribute.
432 DetermineRootBridgeAttributes (
433 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
434 IN PCI_IO_DEVICE
*RootBridgeDev
439 EFI_HANDLE RootBridgeHandle
;
442 RootBridgeHandle
= RootBridgeDev
->Handle
;
445 // Get root bridge attribute by calling into pci host bridge resource allocation protocol
447 Status
= PciResAlloc
->GetAllocAttributes (
453 if (EFI_ERROR (Status
)) {
458 // Here is the point where PCI bus driver calls HOST bridge allocation protocol
459 // Currently we hardcoded for ea815
461 if ((Attributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) {
462 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
;
465 if ((Attributes
& EFI_PCI_HOST_BRIDGE_MEM64_DECODE
) != 0) {
466 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
469 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
470 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
471 RootBridgeDev
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
477 Get Max Option Rom size on specified bridge.
479 @param Bridge Given bridge device instance.
481 @return Max size of option rom needed.
485 GetMaxOptionRomSize (
486 IN PCI_IO_DEVICE
*Bridge
489 LIST_ENTRY
*CurrentLink
;
491 UINT64 MaxOptionRomSize
;
492 UINT64 TempOptionRomSize
;
494 MaxOptionRomSize
= 0;
497 // Go through bridges to reach all devices
499 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
500 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
501 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
502 if (!IsListEmpty (&Temp
->ChildList
)) {
505 // Get max option rom size under this bridge
507 TempOptionRomSize
= GetMaxOptionRomSize (Temp
);
510 // Compare with the option rom size of the bridge
511 // Get the larger one
513 if (Temp
->RomSize
> TempOptionRomSize
) {
514 TempOptionRomSize
= Temp
->RomSize
;
520 // For devices get the rom size directly
522 TempOptionRomSize
= Temp
->RomSize
;
526 // Get the largest rom size on this bridge
528 if (TempOptionRomSize
> MaxOptionRomSize
) {
529 MaxOptionRomSize
= TempOptionRomSize
;
532 CurrentLink
= CurrentLink
->ForwardLink
;
535 return MaxOptionRomSize
;
539 Process attributes of devices on this host bridge
541 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
543 @retval EFI_SUCCESS Successfully process attribute.
544 @retval EFI_NOT_FOUND Can not find the specific root bridge device.
545 @retval other Failed to determine the root bridge device's attribute.
549 PciHostBridgeDeviceAttribute (
550 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
553 EFI_HANDLE RootBridgeHandle
;
554 PCI_IO_DEVICE
*RootBridgeDev
;
557 RootBridgeHandle
= NULL
;
559 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
562 // Get RootBridg Device by handle
564 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
566 if (RootBridgeDev
== NULL
) {
567 return EFI_NOT_FOUND
;
571 // Set the attributes for devcies behind the Root Bridge
573 Status
= DetermineDeviceAttribute (RootBridgeDev
);
574 if (EFI_ERROR (Status
)) {
584 Get resource allocation status from the ACPI resource descriptor.
586 @param AcpiConfig Point to Acpi configuration table.
587 @param IoResStatus Return the status of I/O resource.
588 @param Mem32ResStatus Return the status of 32-bit Memory resource.
589 @param PMem32ResStatus Return the status of 32-bit Prefetchable Memory resource.
590 @param Mem64ResStatus Return the status of 64-bit Memory resource.
591 @param PMem64ResStatus Return the status of 64-bit Prefetchable Memory resource.
595 GetResourceAllocationStatus (
597 OUT UINT64
*IoResStatus
,
598 OUT UINT64
*Mem32ResStatus
,
599 OUT UINT64
*PMem32ResStatus
,
600 OUT UINT64
*Mem64ResStatus
,
601 OUT UINT64
*PMem64ResStatus
606 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*ACPIAddressDesc
;
608 Temp
= (UINT8
*) AcpiConfig
;
610 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
612 ACPIAddressDesc
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
613 ResStatus
= ACPIAddressDesc
->AddrTranslationOffset
;
615 switch (ACPIAddressDesc
->ResType
) {
617 if (ACPIAddressDesc
->AddrSpaceGranularity
== 32) {
618 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
622 *PMem32ResStatus
= ResStatus
;
627 *Mem32ResStatus
= ResStatus
;
631 if (ACPIAddressDesc
->AddrSpaceGranularity
== 64) {
632 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
636 *PMem64ResStatus
= ResStatus
;
641 *Mem64ResStatus
= ResStatus
;
651 *IoResStatus
= ResStatus
;
658 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
663 Remove a PCI device from device pool and mark its bar.
665 @param PciDevice Instance of Pci device.
667 @retval EFI_SUCCESS Successfully remove the PCI device.
668 @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
673 IN PCI_IO_DEVICE
*PciDevice
676 PCI_IO_DEVICE
*Bridge
;
678 LIST_ENTRY
*CurrentLink
;
681 // Remove the padding resource from a bridge
683 if ( IS_PCI_BRIDGE(&PciDevice
->Pci
) &&
684 PciDevice
->ResourcePaddingDescriptors
!= NULL
) {
685 FreePool (PciDevice
->ResourcePaddingDescriptors
);
686 PciDevice
->ResourcePaddingDescriptors
= NULL
;
693 if (IS_PCI_BRIDGE (&PciDevice
->Pci
) || (PciDevice
->Parent
== NULL
)) {
697 if (IS_CARDBUS_BRIDGE (&PciDevice
->Pci
)) {
699 // Get the root bridge device
702 while (Bridge
->Parent
!= NULL
) {
703 Bridge
= Bridge
->Parent
;
706 RemoveAllPciDeviceOnBridge (Bridge
->Handle
, PciDevice
);
711 InitializeP2C (PciDevice
);
717 Bridge
= PciDevice
->Parent
;
718 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
719 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
720 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
721 if (Temp
== PciDevice
) {
722 InitializePciDevice (Temp
);
723 RemoveEntryList (CurrentLink
);
724 FreePciDevice (Temp
);
728 CurrentLink
= CurrentLink
->ForwardLink
;
735 Determine whethter a PCI device can be rejected.
737 @param PciResNode Pointer to Pci resource node instance.
739 @retval TRUE The PCI device can be rejected.
740 @retval TRUE The PCI device cannot be rejected.
745 IN PCI_RESOURCE_NODE
*PciResNode
750 Temp
= PciResNode
->PciDev
;
753 // Ensure the device is present
760 // PPB and RB should go ahead
762 if (IS_PCI_BRIDGE (&Temp
->Pci
) || (Temp
->Parent
== NULL
)) {
767 // Skip device on Bus0
769 if ((Temp
->Parent
!= NULL
) && (Temp
->BusNumber
== 0)) {
776 if (IS_PCI_VGA (&Temp
->Pci
)) {
784 Compare two resource nodes and get the larger resource consumer.
786 @param PciResNode1 resource node 1 want to be compared
787 @param PciResNode2 resource node 2 want to be compared
789 @return Larger resource node.
793 GetLargerConsumerDevice (
794 IN PCI_RESOURCE_NODE
*PciResNode1
,
795 IN PCI_RESOURCE_NODE
*PciResNode2
798 if (PciResNode2
== NULL
) {
802 if ((IS_PCI_BRIDGE(&(PciResNode2
->PciDev
->Pci
)) || (PciResNode2
->PciDev
->Parent
== NULL
)) \
803 && (PciResNode2
->ResourceUsage
!= PciResUsagePadding
) )
808 if (PciResNode1
== NULL
) {
812 if ((PciResNode1
->Length
) > (PciResNode2
->Length
)) {
821 Get the max resource consumer in the host resource pool.
823 @param ResPool Pointer to resource pool node.
825 @return The max resource consumer in the host resource pool.
829 GetMaxResourceConsumerDevice (
830 IN PCI_RESOURCE_NODE
*ResPool
833 PCI_RESOURCE_NODE
*Temp
;
834 LIST_ENTRY
*CurrentLink
;
835 PCI_RESOURCE_NODE
*PciResNode
;
836 PCI_RESOURCE_NODE
*PPBResNode
;
840 CurrentLink
= ResPool
->ChildList
.ForwardLink
;
841 while (CurrentLink
!= NULL
&& CurrentLink
!= &ResPool
->ChildList
) {
843 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
845 if (!IsRejectiveDevice (Temp
)) {
846 CurrentLink
= CurrentLink
->ForwardLink
;
850 if ((IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
)) || (Temp
->PciDev
->Parent
== NULL
)) \
851 && (Temp
->ResourceUsage
!= PciResUsagePadding
))
853 PPBResNode
= GetMaxResourceConsumerDevice (Temp
);
854 PciResNode
= GetLargerConsumerDevice (PciResNode
, PPBResNode
);
856 PciResNode
= GetLargerConsumerDevice (PciResNode
, Temp
);
859 CurrentLink
= CurrentLink
->ForwardLink
;
866 Adjust host bridge allocation so as to reduce resource requirement
868 @param IoPool Pointer to instance of I/O resource Node.
869 @param Mem32Pool Pointer to instance of 32-bit memory resource Node.
870 @param PMem32Pool Pointer to instance of 32-bit Prefetchable memory resource node.
871 @param Mem64Pool Pointer to instance of 64-bit memory resource node.
872 @param PMem64Pool Pointer to instance of 64-bit Prefetchable memory resource node.
873 @param IoResStatus Status of I/O resource Node.
874 @param Mem32ResStatus Status of 32-bit memory resource Node.
875 @param PMem32ResStatus Status of 32-bit Prefetchable memory resource node.
876 @param Mem64ResStatus Status of 64-bit memory resource node.
877 @param PMem64ResStatus Status of 64-bit Prefetchable memory resource node.
879 @retval EFI_SUCCESS Successfully adjusted resoruce on host bridge.
880 @retval EFI_ABORTED Host bridge hasn't this resource type or no resource be adjusted.
884 PciHostBridgeAdjustAllocation (
885 IN PCI_RESOURCE_NODE
*IoPool
,
886 IN PCI_RESOURCE_NODE
*Mem32Pool
,
887 IN PCI_RESOURCE_NODE
*PMem32Pool
,
888 IN PCI_RESOURCE_NODE
*Mem64Pool
,
889 IN PCI_RESOURCE_NODE
*PMem64Pool
,
890 IN UINT64 IoResStatus
,
891 IN UINT64 Mem32ResStatus
,
892 IN UINT64 PMem32ResStatus
,
893 IN UINT64 Mem64ResStatus
,
894 IN UINT64 PMem64ResStatus
897 BOOLEAN AllocationAjusted
;
898 PCI_RESOURCE_NODE
*PciResNode
;
899 PCI_RESOURCE_NODE
*ResPool
[5];
900 PCI_IO_DEVICE
*RemovedPciDev
[5];
902 UINTN RemovedPciDevNum
;
906 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
909 ZeroMem (RemovedPciDev
, 5 * sizeof (PCI_IO_DEVICE
*));
910 RemovedPciDevNum
= 0;
913 ResPool
[1] = Mem32Pool
;
914 ResPool
[2] = PMem32Pool
;
915 ResPool
[3] = Mem64Pool
;
916 ResPool
[4] = PMem64Pool
;
918 ResStatus
[0] = IoResStatus
;
919 ResStatus
[1] = Mem32ResStatus
;
920 ResStatus
[2] = PMem32ResStatus
;
921 ResStatus
[3] = Mem64ResStatus
;
922 ResStatus
[4] = PMem64ResStatus
;
924 AllocationAjusted
= FALSE
;
926 for (ResType
= 0; ResType
< 5; ResType
++) {
928 if (ResStatus
[ResType
] == EFI_RESOURCE_SATISFIED
) {
932 if (ResStatus
[ResType
] == EFI_RESOURCE_NOT_SATISFIED
) {
934 // Host bridge hasn't this resource type
940 // Hostbridge hasn't enough resource
942 PciResNode
= GetMaxResourceConsumerDevice (ResPool
[ResType
]);
943 if (PciResNode
== NULL
) {
948 // Check if the device has been removed before
950 for (DevIndex
= 0; DevIndex
< RemovedPciDevNum
; DevIndex
++) {
951 if (PciResNode
->PciDev
== RemovedPciDev
[DevIndex
]) {
956 if (DevIndex
!= RemovedPciDevNum
) {
961 // Remove the device if it isn't in the array
963 Status
= RejectPciDevice (PciResNode
->PciDev
);
964 if (Status
== EFI_SUCCESS
) {
967 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
970 // Have no way to get ReqRes, AllocRes & Bar here
972 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
973 AllocFailExtendedData
.DevicePathSize
= sizeof (EFI_DEVICE_PATH_PROTOCOL
);
974 AllocFailExtendedData
.DevicePath
= (UINT8
*) PciResNode
->PciDev
->DevicePath
;
975 AllocFailExtendedData
.Bar
= PciResNode
->Bar
;
977 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
979 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
980 (VOID
*) &AllocFailExtendedData
,
981 sizeof (AllocFailExtendedData
)
985 // Add it to the array and indicate at least a device has been rejected
987 RemovedPciDev
[RemovedPciDevNum
++] = PciResNode
->PciDev
;
988 AllocationAjusted
= TRUE
;
995 if (AllocationAjusted
) {
1003 Summary requests for all resource type, and contruct ACPI resource
1006 @param Bridge detecting bridge
1007 @param IoNode Pointer to instance of I/O resource Node
1008 @param Mem32Node Pointer to instance of 32-bit memory resource Node
1009 @param PMem32Node Pointer to instance of 32-bit Pmemory resource node
1010 @param Mem64Node Pointer to instance of 64-bit memory resource node
1011 @param PMem64Node Pointer to instance of 64-bit Pmemory resource node
1012 @param Config Output buffer holding new constructed APCI resource requestor
1014 @retval EFI_SUCCESS Successfully constructed ACPI resource.
1015 @retval EFI_OUT_OF_RESOURCES No memory availabe.
1019 ConstructAcpiResourceRequestor (
1020 IN PCI_IO_DEVICE
*Bridge
,
1021 IN PCI_RESOURCE_NODE
*IoNode
,
1022 IN PCI_RESOURCE_NODE
*Mem32Node
,
1023 IN PCI_RESOURCE_NODE
*PMem32Node
,
1024 IN PCI_RESOURCE_NODE
*Mem64Node
,
1025 IN PCI_RESOURCE_NODE
*PMem64Node
,
1031 UINT8
*Configuration
;
1032 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1033 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
1041 // if there is io request, add to the io aperture
1043 if (ResourceRequestExisted (IoNode
)) {
1049 // if there is mem32 request, add to the mem32 aperture
1051 if (ResourceRequestExisted (Mem32Node
)) {
1057 // if there is pmem32 request, add to the pmem32 aperture
1059 if (ResourceRequestExisted (PMem32Node
)) {
1065 // if there is mem64 request, add to the mem64 aperture
1067 if (ResourceRequestExisted (Mem64Node
)) {
1073 // if there is pmem64 request, add to the pmem64 aperture
1075 if (ResourceRequestExisted (PMem64Node
)) {
1080 if (NumConfig
!= 0) {
1083 // If there is at least one type of resource request,
1084 // allocate a acpi resource node
1086 Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1087 if (Configuration
== NULL
) {
1088 return EFI_OUT_OF_RESOURCES
;
1093 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
1096 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1099 // Deal with io aperture
1101 if ((Aperture
& 0x01) != 0) {
1102 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1103 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1107 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1111 Ptr
->SpecificFlag
= 1;
1112 Ptr
->AddrLen
= IoNode
->Length
;
1113 Ptr
->AddrRangeMax
= IoNode
->Alignment
;
1118 // Deal with mem32 aperture
1120 if ((Aperture
& 0x02) != 0) {
1121 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1122 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1126 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1130 Ptr
->SpecificFlag
= 0;
1134 Ptr
->AddrSpaceGranularity
= 32;
1135 Ptr
->AddrLen
= Mem32Node
->Length
;
1136 Ptr
->AddrRangeMax
= Mem32Node
->Alignment
;
1142 // Deal with Pmem32 aperture
1144 if ((Aperture
& 0x04) != 0) {
1145 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1146 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1150 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1154 Ptr
->SpecificFlag
= 0x6;
1158 Ptr
->AddrSpaceGranularity
= 32;
1159 Ptr
->AddrLen
= PMem32Node
->Length
;
1160 Ptr
->AddrRangeMax
= PMem32Node
->Alignment
;
1165 // Deal with mem64 aperture
1167 if ((Aperture
& 0x08) != 0) {
1168 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1169 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1173 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1177 Ptr
->SpecificFlag
= 0;
1181 Ptr
->AddrSpaceGranularity
= 64;
1182 Ptr
->AddrLen
= Mem64Node
->Length
;
1183 Ptr
->AddrRangeMax
= Mem64Node
->Alignment
;
1188 // Deal with Pmem64 aperture
1190 if ((Aperture
& 0x10) != 0) {
1191 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1192 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1196 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1200 Ptr
->SpecificFlag
= 0x06;
1204 Ptr
->AddrSpaceGranularity
= 64;
1205 Ptr
->AddrLen
= PMem64Node
->Length
;
1206 Ptr
->AddrRangeMax
= PMem64Node
->Alignment
;
1214 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
;
1216 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1217 PtrEnd
->Checksum
= 0;
1222 // If there is no resource request
1224 Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1225 if (Configuration
== NULL
) {
1226 return EFI_OUT_OF_RESOURCES
;
1229 ZeroMem (Configuration
, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1231 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (Configuration
);
1232 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1234 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Ptr
+ 1);
1235 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1236 PtrEnd
->Checksum
= 0;
1239 *Config
= Configuration
;
1245 Get resource base from an acpi configuration descriptor.
1247 @param Config An acpi configuration descriptor.
1248 @param IoBase Output of I/O resource base address.
1249 @param Mem32Base Output of 32-bit memory base address.
1250 @param PMem32Base Output of 32-bit prefetchable memory base address.
1251 @param Mem64Base Output of 64-bit memory base address.
1252 @param PMem64Base Output of 64-bit prefetchable memory base address.
1259 OUT UINT64
*Mem32Base
,
1260 OUT UINT64
*PMem32Base
,
1261 OUT UINT64
*Mem64Base
,
1262 OUT UINT64
*PMem64Base
1266 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1269 ASSERT (Config
!= NULL
);
1271 *IoBase
= 0xFFFFFFFFFFFFFFFFULL
;
1272 *Mem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1273 *PMem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1274 *Mem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1275 *PMem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1277 Temp
= (UINT8
*) Config
;
1279 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1281 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1282 ResStatus
= Ptr
->AddrTranslationOffset
;
1284 if (ResStatus
== EFI_RESOURCE_SATISFIED
) {
1286 switch (Ptr
->ResType
) {
1289 // Memory type aperture
1294 // Check to see the granularity
1296 if (Ptr
->AddrSpaceGranularity
== 32) {
1297 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1298 *PMem32Base
= Ptr
->AddrRangeMin
;
1300 *Mem32Base
= Ptr
->AddrRangeMin
;
1304 if (Ptr
->AddrSpaceGranularity
== 64) {
1305 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1306 *PMem64Base
= Ptr
->AddrRangeMin
;
1308 *Mem64Base
= Ptr
->AddrRangeMin
;
1318 *IoBase
= Ptr
->AddrRangeMin
;
1332 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1337 Enumerate pci bridge, allocate resource and determine attribute
1338 for devices on this bridge.
1340 @param BridgeDev Pointer to instance of bridge device.
1342 @retval EFI_SUCCESS Successfully enumerated PCI bridge.
1343 @retval other Failed to enumerate.
1347 PciBridgeEnumerator (
1348 IN PCI_IO_DEVICE
*BridgeDev
1352 UINT8 StartBusNumber
;
1353 EFI_PCI_IO_PROTOCOL
*PciIo
;
1358 PciIo
= &(BridgeDev
->PciIo
);
1359 Status
= PciIoRead (PciIo
, EfiPciIoWidthUint8
, 0x19, 1, &StartBusNumber
);
1361 if (EFI_ERROR (Status
)) {
1365 Status
= PciAssignBusNumber (
1371 if (EFI_ERROR (Status
)) {
1375 Status
= PciPciDeviceInfoCollector (BridgeDev
, StartBusNumber
);
1377 if (EFI_ERROR (Status
)) {
1381 Status
= PciBridgeResourceAllocator (BridgeDev
);
1383 if (EFI_ERROR (Status
)) {
1387 Status
= DetermineDeviceAttribute (BridgeDev
);
1389 if (EFI_ERROR (Status
)) {
1398 Allocate all kinds of resource for PCI bridge.
1400 @param Bridge Pointer to bridge instance.
1402 @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
1403 @retval other Failed to allocate resource for bridge.
1407 PciBridgeResourceAllocator (
1408 IN PCI_IO_DEVICE
*Bridge
1411 PCI_RESOURCE_NODE
*IoBridge
;
1412 PCI_RESOURCE_NODE
*Mem32Bridge
;
1413 PCI_RESOURCE_NODE
*PMem32Bridge
;
1414 PCI_RESOURCE_NODE
*Mem64Bridge
;
1415 PCI_RESOURCE_NODE
*PMem64Bridge
;
1423 IoBridge
= CreateResourceNode (
1432 Mem32Bridge
= CreateResourceNode (
1441 PMem32Bridge
= CreateResourceNode (
1450 Mem64Bridge
= CreateResourceNode (
1459 PMem64Bridge
= CreateResourceNode (
1469 // Create resourcemap by going through all the devices subject to this root bridge
1480 Status
= GetResourceBaseFromBridge (
1489 if (EFI_ERROR (Status
)) {
1494 // Program IO resources
1502 // Program Mem32 resources
1510 // Program PMem32 resources
1518 // Program Mem64 resources
1526 // Program PMem64 resources
1533 DestroyResourceTree (IoBridge
);
1534 DestroyResourceTree (Mem32Bridge
);
1535 DestroyResourceTree (PMem32Bridge
);
1536 DestroyResourceTree (PMem64Bridge
);
1537 DestroyResourceTree (Mem64Bridge
);
1539 gBS
->FreePool (IoBridge
);
1540 gBS
->FreePool (Mem32Bridge
);
1541 gBS
->FreePool (PMem32Bridge
);
1542 gBS
->FreePool (PMem64Bridge
);
1543 gBS
->FreePool (Mem64Bridge
);
1549 Get resource base address for a pci bridge device.
1551 @param Bridge Given Pci driver instance.
1552 @param IoBase Output for base address of I/O type resource.
1553 @param Mem32Base Output for base address of 32-bit memory type resource.
1554 @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
1555 @param Mem64Base Output for base address of 64-bit memory type resource.
1556 @param PMem64Base Output for base address of 64-bit Pmemory type resource.
1558 @retval EFI_SUCCESS Successfully got resource base address.
1559 @retval EFI_OUT_OF_RESOURCES PCI bridge is not available.
1563 GetResourceBaseFromBridge (
1564 IN PCI_IO_DEVICE
*Bridge
,
1566 OUT UINT64
*Mem32Base
,
1567 OUT UINT64
*PMem32Base
,
1568 OUT UINT64
*Mem64Base
,
1569 OUT UINT64
*PMem64Base
1572 if (!Bridge
->Allocated
) {
1573 return EFI_OUT_OF_RESOURCES
;
1577 *Mem32Base
= gAllOne
;
1578 *PMem32Base
= gAllOne
;
1579 *Mem64Base
= gAllOne
;
1580 *PMem64Base
= gAllOne
;
1582 if (IS_PCI_BRIDGE (&Bridge
->Pci
)) {
1584 if (Bridge
->PciBar
[PPB_IO_RANGE
].Length
> 0) {
1585 *IoBase
= Bridge
->PciBar
[PPB_IO_RANGE
].BaseAddress
;
1588 if (Bridge
->PciBar
[PPB_MEM32_RANGE
].Length
> 0) {
1589 *Mem32Base
= Bridge
->PciBar
[PPB_MEM32_RANGE
].BaseAddress
;
1592 if (Bridge
->PciBar
[PPB_PMEM32_RANGE
].Length
> 0) {
1593 *PMem32Base
= Bridge
->PciBar
[PPB_PMEM32_RANGE
].BaseAddress
;
1596 if (Bridge
->PciBar
[PPB_PMEM64_RANGE
].Length
> 0) {
1597 *PMem64Base
= Bridge
->PciBar
[PPB_PMEM64_RANGE
].BaseAddress
;
1599 *PMem64Base
= gAllOne
;
1604 if (IS_CARDBUS_BRIDGE (&Bridge
->Pci
)) {
1605 if (Bridge
->PciBar
[P2C_IO_1
].Length
> 0) {
1606 *IoBase
= Bridge
->PciBar
[P2C_IO_1
].BaseAddress
;
1608 if (Bridge
->PciBar
[P2C_IO_2
].Length
> 0) {
1609 *IoBase
= Bridge
->PciBar
[P2C_IO_2
].BaseAddress
;
1613 if (Bridge
->PciBar
[P2C_MEM_1
].Length
> 0) {
1614 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypePMem32
) {
1615 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1618 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypeMem32
) {
1619 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1623 if (Bridge
->PciBar
[P2C_MEM_2
].Length
> 0) {
1624 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypePMem32
) {
1625 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1628 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypeMem32
) {
1629 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1638 These are the notifications from the PCI bus driver that it is about to enter a certain
1639 phase of the PCI enumeration process.
1641 This member function can be used to notify the host bridge driver to perform specific actions,
1642 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1643 Eight notification points are defined at this time. See belows:
1644 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
1645 structures. The PCI enumerator should issue this notification
1646 before starting a fresh enumeration process. Enumeration cannot
1647 be restarted after sending any other notification such as
1648 EfiPciHostBridgeBeginBusAllocation.
1649 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
1650 required here. This notification can be used to perform any
1651 chipset-specific programming.
1652 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
1653 specific action is required here. This notification can be used to
1654 perform any chipset-specific programming.
1655 EfiPciHostBridgeBeginResourceAllocation
1656 The resource allocation phase is about to begin. No specific
1657 action is required here. This notification can be used to perform
1658 any chipset-specific programming.
1659 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
1660 root bridges. These resource settings are returned on the next call to
1661 GetProposedResources(). Before calling NotifyPhase() with a Phase of
1662 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
1663 for gathering I/O and memory requests for
1664 all the PCI root bridges and submitting these requests using
1665 SubmitResources(). This function pads the resource amount
1666 to suit the root bridge hardware, takes care of dependencies between
1667 the PCI root bridges, and calls the Global Coherency Domain (GCD)
1668 with the allocation request. In the case of padding, the allocated range
1669 could be bigger than what was requested.
1670 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
1671 resources (proposed resources) for all the PCI root bridges. After the
1672 hardware is programmed, reassigning resources will not be supported.
1673 The bus settings are not affected.
1674 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
1675 root bridges and resets the I/O and memory apertures to their initial
1676 state. The bus settings are not affected. If the request to allocate
1677 resources fails, the PCI enumerator can use this notification to
1678 deallocate previous resources, adjust the requests, and retry
1680 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
1681 required here. This notification can be used to perform any chipsetspecific
1684 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1685 @param[in] Phase The phase during enumeration
1687 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
1688 is valid for a Phase of EfiPciHostBridgeAllocateResources if
1689 SubmitResources() has not been called for one or more
1690 PCI root bridges before this call
1691 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
1692 for a Phase of EfiPciHostBridgeSetResources.
1693 @retval EFI_INVALID_PARAMETER Invalid phase parameter
1694 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1695 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1696 previously submitted resource requests cannot be fulfilled or
1697 were only partially fulfilled.
1698 @retval EFI_SUCCESS The notification was accepted without any errors.
1703 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
1704 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1707 EFI_HANDLE HostBridgeHandle
;
1708 EFI_HANDLE RootBridgeHandle
;
1709 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1712 HostBridgeHandle
= NULL
;
1713 RootBridgeHandle
= NULL
;
1714 if (gPciPlatformProtocol
!= NULL
) {
1716 // Get Host Bridge Handle.
1718 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1721 // Get the rootbridge Io protocol to find the host bridge handle
1723 Status
= gBS
->HandleProtocol (
1725 &gEfiPciRootBridgeIoProtocolGuid
,
1726 (VOID
**) &PciRootBridgeIo
1729 if (EFI_ERROR (Status
)) {
1730 return EFI_NOT_FOUND
;
1733 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1736 // Call PlatformPci::PlatformNotify() if the protocol is present.
1738 gPciPlatformProtocol
->PlatformNotify (
1739 gPciPlatformProtocol
,
1746 Status
= PciResAlloc
->NotifyPhase (
1751 if (gPciPlatformProtocol
!= NULL
) {
1753 // Call PlatformPci::PlatformNotify() if the protocol is present.
1755 gPciPlatformProtocol
->PlatformNotify (
1756 gPciPlatformProtocol
,
1768 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1769 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1770 PCI controllers before enumeration.
1772 This function is called during the PCI enumeration process. No specific action is expected from this
1773 member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1776 @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1777 @param Bus The bus number of the pci device.
1778 @param Device The device number of the pci device.
1779 @param Func The function number of the pci device.
1780 @param Phase The phase of the PCI device enumeration.
1782 @retval EFI_SUCCESS The requested parameters were returned.
1783 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
1784 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
1785 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1786 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
1787 not enumerate this device, including its child devices if it is a PCI-to-PCI
1792 PreprocessController (
1793 IN PCI_IO_DEVICE
*Bridge
,
1797 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1800 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress
;
1801 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
1802 EFI_HANDLE RootBridgeHandle
;
1803 EFI_HANDLE HostBridgeHandle
;
1807 // Get the host bridge handle
1809 HostBridgeHandle
= Bridge
->PciRootBridgeIo
->ParentHandle
;
1812 // Get the pci host bridge resource allocation protocol
1814 Status
= gBS
->OpenProtocol (
1816 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
1817 (VOID
**) &PciResAlloc
,
1820 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1823 if (EFI_ERROR (Status
)) {
1824 return EFI_UNSUPPORTED
;
1828 // Get Root Brige Handle
1830 while (Bridge
->Parent
!= NULL
) {
1831 Bridge
= Bridge
->Parent
;
1834 RootBridgeHandle
= Bridge
->Handle
;
1836 RootBridgePciAddress
.Register
= 0;
1837 RootBridgePciAddress
.Function
= Func
;
1838 RootBridgePciAddress
.Device
= Device
;
1839 RootBridgePciAddress
.Bus
= Bus
;
1840 RootBridgePciAddress
.ExtendedRegister
= 0;
1842 if (gPciPlatformProtocol
!= NULL
) {
1844 // Call PlatformPci::PrepController() if the protocol is present.
1846 gPciPlatformProtocol
->PlatformPrepController (
1847 gPciPlatformProtocol
,
1850 RootBridgePciAddress
,
1856 Status
= PciResAlloc
->PreprocessController (
1859 RootBridgePciAddress
,
1863 if (gPciPlatformProtocol
!= NULL
) {
1865 // Call PlatformPci::PrepController() if the protocol is present.
1867 gPciPlatformProtocol
->PlatformPrepController (
1868 gPciPlatformProtocol
,
1871 RootBridgePciAddress
,
1881 This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
1882 happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
1884 @param This A pointer to the hot plug request protocol.
1885 @param Operation The operation the PCI bus driver is requested to make.
1886 @param Controller The handle of the hot-plug controller.
1887 @param RemainingDevicePath The remaining device path for the PCI-like hot-plug device.
1888 @param NumberOfChildren The number of child handles.
1889 For a add operation, it is an output parameter.
1890 For a remove operation, it?¡¥s an input parameter.
1891 @param ChildHandleBuffer The buffer which contains the child handles.
1893 @retval EFI_INVALID_PARAMETER Operation is not a legal value.
1894 Controller is NULL or not a valid handle.
1895 NumberOfChildren is NULL.
1896 ChildHandleBuffer is NULL while Operation is add.
1897 @retval EFI_OUT_OF_RESOURCES There are no enough resources to start the devices.
1898 @retval EFI_NOT_FOUND Can not find bridge according to controller handle.
1899 @retval EFI_SUCCESS The handles for the specified device have been created or destroyed
1900 as requested, and for an add operation, the new handles are
1901 returned in ChildHandleBuffer.
1905 PciHotPlugRequestNotify (
1906 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL
* This
,
1907 IN EFI_PCI_HOTPLUG_OPERATION Operation
,
1908 IN EFI_HANDLE Controller
,
1909 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
,
1910 IN OUT UINT8
*NumberOfChildren
,
1911 IN OUT EFI_HANDLE
* ChildHandleBuffer
1914 PCI_IO_DEVICE
*Bridge
;
1915 PCI_IO_DEVICE
*Temp
;
1916 EFI_PCI_IO_PROTOCOL
*PciIo
;
1918 EFI_HANDLE RootBridgeHandle
;
1921 Status
= gBS
->OpenProtocol (
1923 &gEfiPciIoProtocolGuid
,
1925 gPciBusDriverBinding
.DriverBindingHandle
,
1927 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1930 if (EFI_ERROR (Status
)) {
1931 return EFI_NOT_FOUND
;
1934 Bridge
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
1937 // Get root bridge handle
1940 while (Temp
->Parent
!= NULL
) {
1941 Temp
= Temp
->Parent
;
1944 RootBridgeHandle
= Temp
->Handle
;
1946 if (Operation
== EfiPciHotPlugRequestAdd
) {
1948 if (NumberOfChildren
!= NULL
) {
1949 *NumberOfChildren
= 0;
1952 if (IsListEmpty (&Bridge
->ChildList
)) {
1954 Status
= PciBridgeEnumerator (Bridge
);
1956 if (EFI_ERROR (Status
)) {
1961 Status
= StartPciDevicesOnBridge (
1964 RemainingDevicePath
,
1972 if (Operation
== EfiPciHotplugRequestRemove
) {
1974 if (*NumberOfChildren
== 0) {
1976 // Remove all devices on the bridge
1978 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Bridge
);
1983 for (Index
= 0; Index
< *NumberOfChildren
; Index
++) {
1985 // De register all the pci device
1987 Status
= DeRegisterPciDevice (RootBridgeHandle
, ChildHandleBuffer
[Index
]);
1989 if (EFI_ERROR (Status
)) {
2004 Search hostbridge according to given handle
2006 @param RootBridgeHandle Host bridge handle.
2008 @retval TRUE Found host bridge handle.
2009 @retval FALSE Not found hot bridge handle.
2013 SearchHostBridgeHandle (
2014 IN EFI_HANDLE RootBridgeHandle
2017 EFI_HANDLE HostBridgeHandle
;
2018 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2023 // Get the rootbridge Io protocol to find the host bridge handle
2025 Status
= gBS
->OpenProtocol (
2027 &gEfiPciRootBridgeIoProtocolGuid
,
2028 (VOID
**) &PciRootBridgeIo
,
2029 gPciBusDriverBinding
.DriverBindingHandle
,
2031 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2034 if (EFI_ERROR (Status
)) {
2038 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
2039 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2040 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2049 Add host bridge handle to global variable for enumerating.
2051 @param HostBridgeHandle Host bridge handle.
2053 @retval EFI_SUCCESS Successfully added host bridge.
2054 @retval EFI_ABORTED Host bridge is NULL, or given host bridge
2055 has been in host bridge list.
2059 AddHostBridgeEnumerator (
2060 IN EFI_HANDLE HostBridgeHandle
2065 if (HostBridgeHandle
== NULL
) {
2069 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2070 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2075 if (Index
< PCI_MAX_HOST_BRIDGE_NUM
) {
2076 gPciHostBrigeHandles
[Index
] = HostBridgeHandle
;
2077 gPciHostBridgeNumber
++;