3 Copyright (c) 2006 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "PciEnumerator.h"
17 #include "PciResourceSupport.h"
18 #include "PciOptionRomSupport.h"
21 This routine is used to enumerate entire pci bus system
24 @param Controller Parent controller handle.
26 @return Status of enumerating.
30 IN EFI_HANDLE Controller
34 EFI_HANDLE HostBridgeHandle
;
36 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
37 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
40 // If PCI bus has already done the full enumeration, never do it again
42 if (!gFullEnumeration
) {
43 return PciEnumeratorLight (Controller
);
47 // Get the rootbridge Io protocol to find the host bridge handle
49 Status
= gBS
->OpenProtocol (
51 &gEfiPciRootBridgeIoProtocolGuid
,
52 (VOID
**) &PciRootBridgeIo
,
53 gPciBusDriverBinding
.DriverBindingHandle
,
55 EFI_OPEN_PROTOCOL_GET_PROTOCOL
58 if (EFI_ERROR (Status
)) {
63 // Get the host bridge handle
65 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
68 // Get the pci host bridge resource allocation protocol
70 Status
= gBS
->OpenProtocol (
72 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
73 (VOID
**) &PciResAlloc
,
74 gPciBusDriverBinding
.DriverBindingHandle
,
76 EFI_OPEN_PROTOCOL_GET_PROTOCOL
79 if (EFI_ERROR (Status
)) {
84 // Notify the pci bus enumeration is about to begin
86 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginEnumeration
);
89 // Start the bus allocation phase
91 Status
= PciHostBridgeEnumerator (PciResAlloc
);
93 if (EFI_ERROR (Status
)) {
98 // Submit the resource request
100 Status
= PciHostBridgeResourceAllocator (PciResAlloc
);
102 if (EFI_ERROR (Status
)) {
109 Status
= PciHostBridgeP2CProcess (PciResAlloc
);
111 if (EFI_ERROR (Status
)) {
116 // Process attributes for devices on this host bridge
118 Status
= PciHostBridgeDeviceAttribute (PciResAlloc
);
119 if (EFI_ERROR (Status
)) {
123 gFullEnumeration
= FALSE
;
129 Enumerate PCI root bridge
131 @param PciResAlloc Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
132 @param RootBridgeDev Instance of root bridge device.
134 @retval EFI_SUCCESS Success to enumerate root bridge.
135 @retval Others Fail to enumerate root bridge.
139 PciRootBridgeEnumerator (
140 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
141 IN PCI_IO_DEVICE
*RootBridgeDev
145 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Configuration
;
147 UINT8 StartBusNumber
;
148 UINT8 PaddedBusRange
;
149 EFI_HANDLE RootBridgeHandle
;
156 // Get the root bridge handle
158 RootBridgeHandle
= RootBridgeDev
->Handle
;
160 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
162 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_BUS_ENUM
,
163 RootBridgeDev
->DevicePath
167 // Get the Bus information
169 Status
= PciResAlloc
->StartBusEnumeration (
172 (VOID
**) &Configuration
175 if (EFI_ERROR (Status
)) {
180 // Get the bus number to start with
182 StartBusNumber
= (UINT8
) (Configuration
->AddrRangeMin
);
183 PaddedBusRange
= (UINT8
) (Configuration
->AddrRangeMax
);
186 // Initialize the subordinate bus number
188 SubBusNumber
= StartBusNumber
;
191 // Reset all assigned PCI bus number
193 ResetAllPpbBusNumber (
201 Status
= PciScanBus (
203 (UINT8
) (Configuration
->AddrRangeMin
),
208 if (EFI_ERROR (Status
)) {
214 // Assign max bus number scanned
216 Configuration
->AddrLen
= SubBusNumber
- StartBusNumber
+ 1 + PaddedBusRange
;
221 Status
= PciResAlloc
->SetBusNumbers (
227 gBS
->FreePool (Configuration
);
229 if (EFI_ERROR (Status
)) {
237 This routine is used to process option rom 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 Max rom size
243 @retval EFI_SUCCESS Success to process option rom image.
247 IN PCI_IO_DEVICE
*Bridge
,
252 LIST_ENTRY
*CurrentLink
;
256 // Go through bridges to reach all devices
258 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
259 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
260 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
261 if (!IsListEmpty (&Temp
->ChildList
)) {
264 // Go further to process the option rom under this bridge
266 ProcessOptionRom (Temp
, RomBase
, MaxLength
);
269 if (Temp
->RomSize
!= 0 && Temp
->RomSize
<= MaxLength
) {
272 // Load and process the option rom
274 LoadOpRomImage (Temp
, RomBase
);
277 CurrentLink
= CurrentLink
->ForwardLink
;
284 This routine is used to assign bus number to the given PCI bus system
286 @param Bridge Parent root bridge instance.
287 @param StartBusNumber Number of beginning.
288 @param SubBusNumber the number of sub bus.
290 @retval EFI_SUCCESS Success to assign bus number.
294 IN PCI_IO_DEVICE
*Bridge
,
295 IN UINT8 StartBusNumber
,
296 OUT UINT8
*SubBusNumber
307 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
309 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
314 *SubBusNumber
= StartBusNumber
;
317 // First check to see whether the parent is ppb
319 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
320 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
323 // Check to see whether a pci device is present
326 Status
= PciDevicePresent (
334 if (!EFI_ERROR (Status
) &&
335 (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
338 // Reserved one bus for cardbus bridge
340 SecondBus
= ++(*SubBusNumber
);
342 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
344 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
346 Status
= PciRootBridgeIoWrite (
356 // Initialize SubBusNumber to SecondBus
358 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
359 Status
= PciRootBridgeIoWrite (
368 // If it is PPB, resursively search down this bridge
370 if (IS_PCI_BRIDGE (&Pci
)) {
373 Status
= PciRootBridgeIoWrite (
382 Status
= PciAssignBusNumber (
388 if (EFI_ERROR (Status
)) {
389 return EFI_DEVICE_ERROR
;
394 // Set the current maximum bus number under the PPB
397 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
399 Status
= PciRootBridgeIoWrite (
410 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
413 // Skip sub functions, this is not a multi function device
425 This routine is used to determine the root bridge attribute by interfacing
426 the host bridge resource allocation protocol.
428 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
429 @param RootBridgeDev Root bridge instance
431 @retval EFI_SUCCESS Success to get root bridge's attribute
432 @retval Others Fail to get attribute
435 DetermineRootBridgeAttributes (
436 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
437 IN PCI_IO_DEVICE
*RootBridgeDev
442 EFI_HANDLE RootBridgeHandle
;
445 RootBridgeHandle
= RootBridgeDev
->Handle
;
448 // Get root bridge attribute by calling into pci host bridge resource allocation protocol
450 Status
= PciResAlloc
->GetAllocAttributes (
456 if (EFI_ERROR (Status
)) {
461 // Here is the point where PCI bus driver calls HOST bridge allocation protocol
462 // Currently we hardcoded for ea815
465 if ((Attributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) {
466 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
;
469 if ((Attributes
& EFI_PCI_HOST_BRIDGE_MEM64_DECODE
) != 0) {
470 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
473 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
474 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
475 RootBridgeDev
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
481 Get Max Option Rom size on this bridge
483 @param Bridge Bridge device instance.
484 @return Max size of option rom.
487 GetMaxOptionRomSize (
488 IN PCI_IO_DEVICE
*Bridge
491 LIST_ENTRY
*CurrentLink
;
493 UINT64 MaxOptionRomSize
;
494 UINT64 TempOptionRomSize
;
496 MaxOptionRomSize
= 0;
499 // Go through bridges to reach all devices
501 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
502 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
503 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
504 if (!IsListEmpty (&Temp
->ChildList
)) {
507 // Get max option rom size under this bridge
509 TempOptionRomSize
= GetMaxOptionRomSize (Temp
);
512 // Compare with the option rom size of the bridge
513 // Get the larger one
515 if (Temp
->RomSize
> TempOptionRomSize
) {
516 TempOptionRomSize
= Temp
->RomSize
;
522 // For devices get the rom size directly
524 TempOptionRomSize
= Temp
->RomSize
;
528 // Get the largest rom size on this bridge
530 if (TempOptionRomSize
> MaxOptionRomSize
) {
531 MaxOptionRomSize
= TempOptionRomSize
;
534 CurrentLink
= CurrentLink
->ForwardLink
;
537 return MaxOptionRomSize
;
541 Process attributes of devices on this host bridge
543 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
545 @retval EFI_NOT_FOUND Can not find the specific root bridge device.
546 @retval EFI_SUCCESS Success Process attribute.
547 @retval Others Can not determine the root bridge device's attribute.
550 PciHostBridgeDeviceAttribute (
551 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
554 EFI_HANDLE RootBridgeHandle
;
555 PCI_IO_DEVICE
*RootBridgeDev
;
558 RootBridgeHandle
= NULL
;
560 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
563 // Get RootBridg Device by handle
565 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
567 if (RootBridgeDev
== NULL
) {
568 return EFI_NOT_FOUND
;
572 // Set the attributes for devcies behind the Root Bridge
574 Status
= DetermineDeviceAttribute (RootBridgeDev
);
575 if (EFI_ERROR (Status
)) {
585 Get resource allocation status from the ACPI pointer
587 @param AcpiConfig Point to Acpi configuration table
588 @param IoResStatus Return the status of I/O resource
589 @param Mem32ResStatus Return the status of 32-bit Memory resource
590 @param PMem32ResStatus Return the status of 32-bit PMemory resource
591 @param Mem64ResStatus Return the status of 64-bit Memory resource
592 @param PMem64ResStatus Return the status of 64-bit PMemory resource
594 @retval EFI_SUCCESS Success to get resource allocation status from ACPI configuration table.
597 GetResourceAllocationStatus (
599 OUT UINT64
*IoResStatus
,
600 OUT UINT64
*Mem32ResStatus
,
601 OUT UINT64
*PMem32ResStatus
,
602 OUT UINT64
*Mem64ResStatus
,
603 OUT UINT64
*PMem64ResStatus
609 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*ACPIAddressDesc
;
611 Temp
= (UINT8
*) AcpiConfig
;
613 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
615 ACPIAddressDesc
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
616 ResStatus
= ACPIAddressDesc
->AddrTranslationOffset
;
618 switch (ACPIAddressDesc
->ResType
) {
620 if (ACPIAddressDesc
->AddrSpaceGranularity
== 32) {
621 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
625 *PMem32ResStatus
= ResStatus
;
630 *Mem32ResStatus
= ResStatus
;
634 if (ACPIAddressDesc
->AddrSpaceGranularity
== 64) {
635 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
639 *PMem64ResStatus
= ResStatus
;
644 *Mem64ResStatus
= ResStatus
;
654 *IoResStatus
= ResStatus
;
661 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
668 Remove a PCI device from device pool and mark its bar
670 @param PciDevice Instance of Pci device.
672 @retval EFI_SUCCESS Success Operation.
673 @retval EFI_ABORTED Pci device is a root bridge.
677 IN PCI_IO_DEVICE
*PciDevice
680 PCI_IO_DEVICE
*Bridge
;
682 LIST_ENTRY
*CurrentLink
;
685 // Remove the padding resource from a bridge
687 if ( IS_PCI_BRIDGE(&PciDevice
->Pci
) && \
688 PciDevice
->ResourcePaddingDescriptors
!= NULL
) {
689 gBS
->FreePool (PciDevice
->ResourcePaddingDescriptors
);
690 PciDevice
->ResourcePaddingDescriptors
= NULL
;
697 if (IS_PCI_BRIDGE (&PciDevice
->Pci
) || (PciDevice
->Parent
== NULL
)) {
701 if (IS_CARDBUS_BRIDGE (&PciDevice
->Pci
)) {
703 // Get the root bridge device
706 while (Bridge
->Parent
!= NULL
) {
707 Bridge
= Bridge
->Parent
;
710 RemoveAllPciDeviceOnBridge (Bridge
->Handle
, PciDevice
);
715 InitializeP2C (PciDevice
);
721 Bridge
= PciDevice
->Parent
;
722 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
723 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
724 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
725 if (Temp
== PciDevice
) {
726 InitializePciDevice (Temp
);
727 RemoveEntryList (CurrentLink
);
728 FreePciDevice (Temp
);
732 CurrentLink
= CurrentLink
->ForwardLink
;
739 Determine whethter a PCI device can be rejected.
741 @param PciResNode Pointer to Pci resource node instance.
743 @return whethter a PCI device can be rejected.
747 IN PCI_RESOURCE_NODE
*PciResNode
752 Temp
= PciResNode
->PciDev
;
755 // Ensure the device is present
762 // PPB and RB should go ahead
764 if (IS_PCI_BRIDGE (&Temp
->Pci
) || (Temp
->Parent
== NULL
)) {
769 // Skip device on Bus0
771 if ((Temp
->Parent
!= NULL
) && (Temp
->BusNumber
== 0)) {
778 if (IS_PCI_VGA (&Temp
->Pci
)) {
786 Compare two resource node and get the larger resource consumer
788 @param PciResNode1 resource node 1 want to be compared
789 @param PciResNode2 resource node 2 want to be compared
791 @return Larger resource consumer.
794 GetLargerConsumerDevice (
795 IN PCI_RESOURCE_NODE
*PciResNode1
,
796 IN PCI_RESOURCE_NODE
*PciResNode2
799 if (PciResNode2
== NULL
) {
803 if ((IS_PCI_BRIDGE(&(PciResNode2
->PciDev
->Pci
)) || (PciResNode2
->PciDev
->Parent
== NULL
)) \
804 && (PciResNode2
->ResourceUsage
!= PciResUsagePadding
) )
809 if (PciResNode1
== NULL
) {
813 if ((PciResNode1
->Length
) > (PciResNode2
->Length
)) {
823 Get the max resource consumer in the host resource pool.
825 @param ResPool Pointer to resource pool node.
827 @return the max resource consumer in the host resource pool.
830 GetMaxResourceConsumerDevice (
831 IN PCI_RESOURCE_NODE
*ResPool
834 PCI_RESOURCE_NODE
*Temp
;
835 LIST_ENTRY
*CurrentLink
;
836 PCI_RESOURCE_NODE
*PciResNode
;
837 PCI_RESOURCE_NODE
*PPBResNode
;
841 CurrentLink
= ResPool
->ChildList
.ForwardLink
;
842 while (CurrentLink
!= NULL
&& CurrentLink
!= &ResPool
->ChildList
) {
844 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
846 if (!IsRejectiveDevice (Temp
)) {
847 CurrentLink
= CurrentLink
->ForwardLink
;
851 if ((IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
)) || (Temp
->PciDev
->Parent
== NULL
)) \
852 && (Temp
->ResourceUsage
!= PciResUsagePadding
))
854 PPBResNode
= GetMaxResourceConsumerDevice (Temp
);
855 PciResNode
= GetLargerConsumerDevice (PciResNode
, PPBResNode
);
857 PciResNode
= GetLargerConsumerDevice (PciResNode
, Temp
);
860 CurrentLink
= CurrentLink
->ForwardLink
;
867 Adjust host bridge allocation so as to reduce resource requirement
869 @param IoPool Pointer to instance of I/O resource Node.
870 @param Mem32Pool Pointer to instance of 32-bit memory resource Node.
871 @param PMem32Pool Pointer to instance of 32-bit Pmemory resource node.
872 @param Mem64Pool Pointer to instance of 64-bit memory resource node.
873 @param PMem64Pool Pointer to instance of 64-bit Pmemory resource node.
874 @param IoResStatus Status of I/O resource Node.
875 @param Mem32ResStatus Status of 32-bit memory resource Node.
876 @param PMem32ResStatus Status of 32-bit Pmemory resource node.
877 @param Mem64ResStatus Status of 64-bit memory resource node.
878 @param PMem64ResStatus Status of 64-bit Pmemory resource node.
881 PciHostBridgeAdjustAllocation (
882 IN PCI_RESOURCE_NODE
*IoPool
,
883 IN PCI_RESOURCE_NODE
*Mem32Pool
,
884 IN PCI_RESOURCE_NODE
*PMem32Pool
,
885 IN PCI_RESOURCE_NODE
*Mem64Pool
,
886 IN PCI_RESOURCE_NODE
*PMem64Pool
,
887 IN UINT64 IoResStatus
,
888 IN UINT64 Mem32ResStatus
,
889 IN UINT64 PMem32ResStatus
,
890 IN UINT64 Mem64ResStatus
,
891 IN UINT64 PMem64ResStatus
894 BOOLEAN AllocationAjusted
;
895 PCI_RESOURCE_NODE
*PciResNode
;
896 PCI_RESOURCE_NODE
*ResPool
[5];
897 PCI_IO_DEVICE
*RemovedPciDev
[5];
899 UINTN RemovedPciDevNum
;
903 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
906 ZeroMem (RemovedPciDev
, 5 * sizeof (PCI_IO_DEVICE
*));
907 RemovedPciDevNum
= 0;
910 ResPool
[1] = Mem32Pool
;
911 ResPool
[2] = PMem32Pool
;
912 ResPool
[3] = Mem64Pool
;
913 ResPool
[4] = PMem64Pool
;
915 ResStatus
[0] = IoResStatus
;
916 ResStatus
[1] = Mem32ResStatus
;
917 ResStatus
[2] = PMem32ResStatus
;
918 ResStatus
[3] = Mem64ResStatus
;
919 ResStatus
[4] = PMem64ResStatus
;
921 AllocationAjusted
= FALSE
;
923 for (ResType
= 0; ResType
< 5; ResType
++) {
925 if (ResStatus
[ResType
] == EFI_RESOURCE_SATISFIED
) {
929 if (ResStatus
[ResType
] == EFI_RESOURCE_NONEXISTENT
) {
931 // Hostbridge hasn't this resource type
937 // Hostbridge hasn't enough resource
939 PciResNode
= GetMaxResourceConsumerDevice (ResPool
[ResType
]);
940 if (PciResNode
== NULL
) {
945 // Check if the device has been removed before
947 for (DevIndex
= 0; DevIndex
< RemovedPciDevNum
; DevIndex
++) {
948 if (PciResNode
->PciDev
== RemovedPciDev
[DevIndex
]) {
953 if (DevIndex
!= RemovedPciDevNum
) {
958 // Remove the device if it isn't in the array
960 Status
= RejectPciDevice (PciResNode
->PciDev
);
961 if (Status
== EFI_SUCCESS
) {
964 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
967 // Have no way to get ReqRes, AllocRes & Bar here
969 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
970 AllocFailExtendedData
.DevicePathSize
= sizeof (EFI_DEVICE_PATH_PROTOCOL
);
971 AllocFailExtendedData
.DevicePath
= (UINT8
*) PciResNode
->PciDev
->DevicePath
;
972 AllocFailExtendedData
.Bar
= PciResNode
->Bar
;
974 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
976 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
977 (VOID
*) &AllocFailExtendedData
,
978 sizeof (AllocFailExtendedData
)
982 // Add it to the array and indicate at least a device has been rejected
984 RemovedPciDev
[RemovedPciDevNum
++] = PciResNode
->PciDev
;
985 AllocationAjusted
= TRUE
;
992 if (AllocationAjusted
) {
1000 Summary requests for all resource type, and contruct ACPI resource
1003 @param Bridge detecting bridge
1004 @param IoNode Pointer to instance of I/O resource Node
1005 @param Mem32Node Pointer to instance of 32-bit memory resource Node
1006 @param PMem32Node Pointer to instance of 32-bit Pmemory resource node
1007 @param Mem64Node Pointer to instance of 64-bit memory resource node
1008 @param PMem64Node Pointer to instance of 64-bit Pmemory resource node
1009 @param pConfig outof buffer holding new constructed APCI resource requestor
1012 ConstructAcpiResourceRequestor (
1013 IN PCI_IO_DEVICE
*Bridge
,
1014 IN PCI_RESOURCE_NODE
*IoNode
,
1015 IN PCI_RESOURCE_NODE
*Mem32Node
,
1016 IN PCI_RESOURCE_NODE
*PMem32Node
,
1017 IN PCI_RESOURCE_NODE
*Mem64Node
,
1018 IN PCI_RESOURCE_NODE
*PMem64Node
,
1024 UINT8
*Configuration
;
1025 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1026 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
1034 // if there is io request, add to the io aperture
1036 if (ResourceRequestExisted (IoNode
)) {
1042 // if there is mem32 request, add to the mem32 aperture
1044 if (ResourceRequestExisted (Mem32Node
)) {
1050 // if there is pmem32 request, add to the pmem32 aperture
1052 if (ResourceRequestExisted (PMem32Node
)) {
1058 // if there is mem64 request, add to the mem64 aperture
1060 if (ResourceRequestExisted (Mem64Node
)) {
1066 // if there is pmem64 request, add to the pmem64 aperture
1068 if (ResourceRequestExisted (PMem64Node
)) {
1073 if (NumConfig
!= 0) {
1076 // If there is at least one type of resource request,
1077 // allocate a acpi resource node
1079 Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1080 if (Configuration
== NULL
) {
1081 return EFI_OUT_OF_RESOURCES
;
1086 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
1089 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1092 // Deal with io aperture
1094 if ((Aperture
& 0x01) != 0) {
1095 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1096 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1100 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1104 Ptr
->SpecificFlag
= 1;
1105 Ptr
->AddrLen
= IoNode
->Length
;
1106 Ptr
->AddrRangeMax
= IoNode
->Alignment
;
1108 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) ((UINT8
*) Ptr
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1111 // Deal with mem32 aperture
1113 if ((Aperture
& 0x02) != 0) {
1114 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1115 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1119 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1123 Ptr
->SpecificFlag
= 0;
1127 Ptr
->AddrSpaceGranularity
= 32;
1128 Ptr
->AddrLen
= Mem32Node
->Length
;
1129 Ptr
->AddrRangeMax
= Mem32Node
->Alignment
;
1131 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) ((UINT8
*) Ptr
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1135 // Deal with Pmem32 aperture
1137 if ((Aperture
& 0x04) != 0) {
1138 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1139 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1143 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1147 Ptr
->SpecificFlag
= 0x6;
1151 Ptr
->AddrSpaceGranularity
= 32;
1152 Ptr
->AddrLen
= PMem32Node
->Length
;
1153 Ptr
->AddrRangeMax
= PMem32Node
->Alignment
;
1155 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) ((UINT8
*) Ptr
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1158 // Deal with mem64 aperture
1160 if ((Aperture
& 0x08) != 0) {
1161 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1162 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1166 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1170 Ptr
->SpecificFlag
= 0;
1174 Ptr
->AddrSpaceGranularity
= 64;
1175 Ptr
->AddrLen
= Mem64Node
->Length
;
1176 Ptr
->AddrRangeMax
= Mem64Node
->Alignment
;
1178 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) ((UINT8
*) Ptr
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1181 // Deal with Pmem64 aperture
1183 if ((Aperture
& 0x10) != 0) {
1184 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1185 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1189 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1193 Ptr
->SpecificFlag
= 0x06;
1197 Ptr
->AddrSpaceGranularity
= 64;
1198 Ptr
->AddrLen
= PMem64Node
->Length
;
1199 Ptr
->AddrRangeMax
= PMem64Node
->Alignment
;
1201 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) ((UINT8
*) Ptr
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1207 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) ((UINT8
*) Ptr
);
1209 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1210 PtrEnd
->Checksum
= 0;
1215 // If there is no resource request
1217 Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1218 if (Configuration
== NULL
) {
1219 return EFI_OUT_OF_RESOURCES
;
1222 ZeroMem (Configuration
, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1224 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (Configuration
);
1225 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1227 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Configuration
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1228 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1229 PtrEnd
->Checksum
= 0;
1232 *pConfig
= Configuration
;
1238 Get resource base from a acpi configuration descriptor.
1240 @param pConfig an acpi configuration descriptor.
1241 @param IoBase output of I/O resource base address.
1242 @param Mem32Base output of 32-bit memory base address.
1243 @param PMem32Base output of 32-bit pmemory base address.
1244 @param Mem64Base output of 64-bit memory base address.
1245 @param PMem64Base output of 64-bit pmemory base address.
1247 @return EFI_SUCCESS Success operation.
1253 OUT UINT64
*Mem32Base
,
1254 OUT UINT64
*PMem32Base
,
1255 OUT UINT64
*Mem64Base
,
1256 OUT UINT64
*PMem64Base
1260 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1263 *IoBase
= 0xFFFFFFFFFFFFFFFFULL
;
1264 *Mem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1265 *PMem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1266 *Mem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1267 *PMem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1269 Temp
= (UINT8
*) pConfig
;
1271 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1273 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1274 ResStatus
= Ptr
->AddrTranslationOffset
;
1276 if (ResStatus
== EFI_RESOURCE_SATISFIED
) {
1278 switch (Ptr
->ResType
) {
1281 // Memory type aperture
1286 // Check to see the granularity
1288 if (Ptr
->AddrSpaceGranularity
== 32) {
1289 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1290 *PMem32Base
= Ptr
->AddrRangeMin
;
1292 *Mem32Base
= Ptr
->AddrRangeMin
;
1296 if (Ptr
->AddrSpaceGranularity
== 64) {
1297 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1298 *PMem64Base
= Ptr
->AddrRangeMin
;
1300 *Mem64Base
= Ptr
->AddrRangeMin
;
1310 *IoBase
= Ptr
->AddrRangeMin
;
1324 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1331 Enumerate pci bridge, allocate resource and determine attribute
1332 for devices on this bridge
1334 @param BridgeDev Pointer to instance of bridge device.
1336 @retval EFI_SUCCESS Success operation.
1337 @retval Others Fail to enumerate.
1340 PciBridgeEnumerator (
1341 IN PCI_IO_DEVICE
*BridgeDev
1345 UINT8 StartBusNumber
;
1346 EFI_PCI_IO_PROTOCOL
*PciIo
;
1351 PciIo
= &(BridgeDev
->PciIo
);
1352 Status
= PciIoRead (PciIo
, EfiPciIoWidthUint8
, 0x19, 1, &StartBusNumber
);
1354 if (EFI_ERROR (Status
)) {
1358 Status
= PciAssignBusNumber (
1364 if (EFI_ERROR (Status
)) {
1368 Status
= PciPciDeviceInfoCollector (BridgeDev
, StartBusNumber
);
1370 if (EFI_ERROR (Status
)) {
1374 Status
= PciBridgeResourceAllocator (BridgeDev
);
1376 if (EFI_ERROR (Status
)) {
1380 Status
= DetermineDeviceAttribute (BridgeDev
);
1382 if (EFI_ERROR (Status
)) {
1391 Allocate all kinds of resource for bridge
1393 @param Bridge Pointer to bridge instance.
1395 @retval EFI_SUCCESS Success operation.
1396 @retval Others Fail to allocate resource for bridge.
1399 PciBridgeResourceAllocator (
1400 IN PCI_IO_DEVICE
*Bridge
1403 PCI_RESOURCE_NODE
*IoBridge
;
1404 PCI_RESOURCE_NODE
*Mem32Bridge
;
1405 PCI_RESOURCE_NODE
*PMem32Bridge
;
1406 PCI_RESOURCE_NODE
*Mem64Bridge
;
1407 PCI_RESOURCE_NODE
*PMem64Bridge
;
1415 IoBridge
= CreateResourceNode (
1424 Mem32Bridge
= CreateResourceNode (
1433 PMem32Bridge
= CreateResourceNode (
1442 Mem64Bridge
= CreateResourceNode (
1451 PMem64Bridge
= CreateResourceNode (
1461 // Create resourcemap by going through all the devices subject to this root bridge
1463 Status
= CreateResourceMap (
1472 if (EFI_ERROR (Status
)) {
1476 Status
= GetResourceBaseFromBridge (
1485 if (EFI_ERROR (Status
)) {
1490 // Program IO resources
1498 // Program Mem32 resources
1506 // Program PMem32 resources
1514 // Program Mem64 resources
1522 // Program PMem64 resources
1529 DestroyResourceTree (IoBridge
);
1530 DestroyResourceTree (Mem32Bridge
);
1531 DestroyResourceTree (PMem32Bridge
);
1532 DestroyResourceTree (PMem64Bridge
);
1533 DestroyResourceTree (Mem64Bridge
);
1535 gBS
->FreePool (IoBridge
);
1536 gBS
->FreePool (Mem32Bridge
);
1537 gBS
->FreePool (PMem32Bridge
);
1538 gBS
->FreePool (PMem64Bridge
);
1539 gBS
->FreePool (Mem64Bridge
);
1545 Get resource base address for a pci bridge device
1547 @param Bridge Given Pci driver instance.
1548 @param IoBase output for base address of I/O type resource.
1549 @param Mem32Base output for base address of 32-bit memory type resource.
1550 @param PMem32Base output for base address of 32-bit Pmemory type resource.
1551 @param Mem64Base output for base address of 64-bit memory type resource.
1552 @param PMem64Base output for base address of 64-bit Pmemory type resource.
1554 @retval EFI_SUCCESS Succes to get resource base address.
1557 GetResourceBaseFromBridge (
1558 IN PCI_IO_DEVICE
*Bridge
,
1560 OUT UINT64
*Mem32Base
,
1561 OUT UINT64
*PMem32Base
,
1562 OUT UINT64
*Mem64Base
,
1563 OUT UINT64
*PMem64Base
1566 if (!Bridge
->Allocated
) {
1567 return EFI_OUT_OF_RESOURCES
;
1571 *Mem32Base
= gAllOne
;
1572 *PMem32Base
= gAllOne
;
1573 *Mem64Base
= gAllOne
;
1574 *PMem64Base
= gAllOne
;
1576 if (IS_PCI_BRIDGE (&Bridge
->Pci
)) {
1578 if (Bridge
->PciBar
[PPB_IO_RANGE
].Length
> 0) {
1579 *IoBase
= Bridge
->PciBar
[PPB_IO_RANGE
].BaseAddress
;
1582 if (Bridge
->PciBar
[PPB_MEM32_RANGE
].Length
> 0) {
1583 *Mem32Base
= Bridge
->PciBar
[PPB_MEM32_RANGE
].BaseAddress
;
1586 if (Bridge
->PciBar
[PPB_PMEM32_RANGE
].Length
> 0) {
1587 *PMem32Base
= Bridge
->PciBar
[PPB_PMEM32_RANGE
].BaseAddress
;
1590 if (Bridge
->PciBar
[PPB_PMEM64_RANGE
].Length
> 0) {
1591 *PMem64Base
= Bridge
->PciBar
[PPB_PMEM64_RANGE
].BaseAddress
;
1593 *PMem64Base
= gAllOne
;
1598 if (IS_CARDBUS_BRIDGE (&Bridge
->Pci
)) {
1599 if (Bridge
->PciBar
[P2C_IO_1
].Length
> 0) {
1600 *IoBase
= Bridge
->PciBar
[P2C_IO_1
].BaseAddress
;
1602 if (Bridge
->PciBar
[P2C_IO_2
].Length
> 0) {
1603 *IoBase
= Bridge
->PciBar
[P2C_IO_2
].BaseAddress
;
1607 if (Bridge
->PciBar
[P2C_MEM_1
].Length
> 0) {
1608 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypePMem32
) {
1609 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1612 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypeMem32
) {
1613 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1617 if (Bridge
->PciBar
[P2C_MEM_2
].Length
> 0) {
1618 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypePMem32
) {
1619 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1622 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypeMem32
) {
1623 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1632 These are the notifications from the PCI bus driver that it is about to enter a certain
1633 phase of the PCI enumeration process.
1635 This member function can be used to notify the host bridge driver to perform specific actions,
1636 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1637 Eight notification points are defined at this time. See belows:
1638 EfiPciHostBridgeBeginEnumeration - Resets the host bridge PCI apertures and internal data
1639 structures. The PCI enumerator should issue this notification
1640 before starting a fresh enumeration process. Enumeration cannot
1641 be restarted after sending any other notification such as
1642 EfiPciHostBridgeBeginBusAllocation.
1643 EfiPciHostBridgeBeginBusAllocation - The bus allocation phase is about to begin. No specific action is
1644 required here. This notification can be used to perform any
1645 chipset-specific programming.
1646 EfiPciHostBridgeEndBusAllocation - The bus allocation and bus programming phase is complete. No
1647 specific action is required here. This notification can be used to
1648 perform any chipset-specific programming.
1649 EfiPciHostBridgeBeginResourceAllocation - The resource allocation phase is about to begin. No specific
1650 action is required here. This notification can be used to perform
1651 any chipset-specific programming.
1652 EfiPciHostBridgeAllocateResources - Allocates resources per previously submitted requests for all the PCI
1653 root bridges. These resource settings are returned on the next call to
1654 GetProposedResources(). Before calling NotifyPhase() with a Phase of
1655 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible for gathering I/O and memory requests for
1656 all the PCI root bridges and submitting these requests using
1657 SubmitResources(). This function pads the resource amount
1658 to suit the root bridge hardware, takes care of dependencies between
1659 the PCI root bridges, and calls the Global Coherency Domain (GCD)
1660 with the allocation request. In the case of padding, the allocated range
1661 could be bigger than what was requested.
1662 EfiPciHostBridgeSetResources - Programs the host bridge hardware to decode previously allocated
1663 resources (proposed resources) for all the PCI root bridges. After the
1664 hardware is programmed, reassigning resources will not be supported.
1665 The bus settings are not affected.
1666 EfiPciHostBridgeFreeResources - Deallocates resources that were previously allocated for all the PCI
1667 root bridges and resets the I/O and memory apertures to their initial
1668 state. The bus settings are not affected. If the request to allocate
1669 resources fails, the PCI enumerator can use this notification to
1670 deallocate previous resources, adjust the requests, and retry
1672 EfiPciHostBridgeEndResourceAllocation- The resource allocation phase is completed. No specific action is
1673 required here. This notification can be used to perform any chipsetspecific
1676 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1677 @param[in] Phase The phase during enumeration
1679 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
1680 is valid for a Phase of EfiPciHostBridgeAllocateResources if
1681 SubmitResources() has not been called for one or more
1682 PCI root bridges before this call
1683 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
1684 for a Phase of EfiPciHostBridgeSetResources.
1685 @retval EFI_INVALID_PARAMETER Invalid phase parameter
1686 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1687 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1688 previously submitted resource requests cannot be fulfilled or
1689 were only partially fulfilled.
1690 @retval EFI_SUCCESS The notification was accepted without any errors.
1695 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
1696 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1699 EFI_HANDLE HostBridgeHandle
;
1700 EFI_HANDLE RootBridgeHandle
;
1701 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1704 HostBridgeHandle
= NULL
;
1705 RootBridgeHandle
= NULL
;
1706 if (gPciPlatformProtocol
!= NULL
) {
1708 // Get Host Bridge Handle.
1710 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1713 // Get the rootbridge Io protocol to find the host bridge handle
1715 Status
= gBS
->HandleProtocol (
1717 &gEfiPciRootBridgeIoProtocolGuid
,
1718 (VOID
**) &PciRootBridgeIo
1721 if (EFI_ERROR (Status
)) {
1722 return EFI_NOT_FOUND
;
1725 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1728 // Call PlatformPci::PhaseNotify() if the protocol is present.
1730 gPciPlatformProtocol
->PhaseNotify (
1731 gPciPlatformProtocol
,
1738 Status
= PciResAlloc
->NotifyPhase (
1743 if (gPciPlatformProtocol
!= NULL
) {
1745 // Call PlatformPci::PhaseNotify() if the protocol is present.
1747 gPciPlatformProtocol
->PhaseNotify (
1748 gPciPlatformProtocol
,
1760 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1761 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1762 PCI controllers before enumeration.
1764 This function is called during the PCI enumeration process. No specific action is expected from this
1765 member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1768 @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1769 @param Bus The bus number of the pci device.
1770 @param Device The device number of the pci device.
1771 @param Func The function number of the pci device.
1772 @param Phase The phase of the PCI device enumeration.
1774 @retval EFI_SUCCESS The requested parameters were returned.
1775 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
1776 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
1777 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1778 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
1779 not enumerate this device, including its child devices if it is a PCI-to-PCI
1784 PreprocessController (
1785 IN PCI_IO_DEVICE
*Bridge
,
1789 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1792 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress
;
1793 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
1794 EFI_HANDLE RootBridgeHandle
;
1795 EFI_HANDLE HostBridgeHandle
;
1799 // Get the host bridge handle
1801 HostBridgeHandle
= Bridge
->PciRootBridgeIo
->ParentHandle
;
1804 // Get the pci host bridge resource allocation protocol
1806 Status
= gBS
->OpenProtocol (
1808 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
1809 (VOID
**) &PciResAlloc
,
1812 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1815 if (EFI_ERROR (Status
)) {
1816 return EFI_UNSUPPORTED
;
1820 // Get Root Brige Handle
1822 while (Bridge
->Parent
!= NULL
) {
1823 Bridge
= Bridge
->Parent
;
1826 RootBridgeHandle
= Bridge
->Handle
;
1828 RootBridgePciAddress
.Register
= 0;
1829 RootBridgePciAddress
.Function
= Func
;
1830 RootBridgePciAddress
.Device
= Device
;
1831 RootBridgePciAddress
.Bus
= Bus
;
1832 RootBridgePciAddress
.ExtendedRegister
= 0;
1834 if (gPciPlatformProtocol
!= NULL
) {
1836 // Call PlatformPci::PrepController() if the protocol is present.
1838 gPciPlatformProtocol
->PlatformPrepController (
1839 gPciPlatformProtocol
,
1842 RootBridgePciAddress
,
1848 Status
= PciResAlloc
->PreprocessController (
1851 RootBridgePciAddress
,
1855 if (gPciPlatformProtocol
!= NULL
) {
1857 // Call PlatformPci::PrepController() if the protocol is present.
1859 gPciPlatformProtocol
->PlatformPrepController (
1860 gPciPlatformProtocol
,
1863 RootBridgePciAddress
,
1873 Hot plug request notify.
1875 @param This - A pointer to the hot plug request protocol.
1876 @param Operation - The operation.
1877 @param Controller - A pointer to the controller.
1878 @param RemainingDevicePath - A pointer to the device path.
1879 @param NumberOfChildren - A the number of child handle in the ChildHandleBuffer.
1880 @param ChildHandleBuffer - A pointer to the array contain the child handle.
1882 @retval EFI_NOT_FOUND Can not find bridge according to controller handle.
1883 @retval EFI_SUCCESS Success operating.
1887 PciHotPlugRequestNotify (
1888 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL
* This
,
1889 IN EFI_PCI_HOTPLUG_OPERATION Operation
,
1890 IN EFI_HANDLE Controller
,
1891 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
,
1892 IN OUT UINT8
*NumberOfChildren
,
1893 IN OUT EFI_HANDLE
* ChildHandleBuffer
1896 PCI_IO_DEVICE
*Bridge
;
1897 PCI_IO_DEVICE
*Temp
;
1898 EFI_PCI_IO_PROTOCOL
*PciIo
;
1900 EFI_HANDLE RootBridgeHandle
;
1903 Status
= gBS
->OpenProtocol (
1905 &gEfiPciIoProtocolGuid
,
1907 gPciBusDriverBinding
.DriverBindingHandle
,
1909 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1912 if (EFI_ERROR (Status
)) {
1913 return EFI_NOT_FOUND
;
1916 Bridge
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
1919 // Get root bridge handle
1922 while (Temp
->Parent
!= NULL
) {
1923 Temp
= Temp
->Parent
;
1926 RootBridgeHandle
= Temp
->Handle
;
1928 if (Operation
== EfiPciHotPlugRequestAdd
) {
1930 if (NumberOfChildren
!= NULL
) {
1931 *NumberOfChildren
= 0;
1934 if (IsListEmpty (&Bridge
->ChildList
)) {
1936 Status
= PciBridgeEnumerator (Bridge
);
1938 if (EFI_ERROR (Status
)) {
1943 Status
= StartPciDevicesOnBridge (
1946 RemainingDevicePath
,
1954 if (Operation
== EfiPciHotplugRequestRemove
) {
1956 if (*NumberOfChildren
== 0) {
1958 // Remove all devices on the bridge
1960 Status
= RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Bridge
);
1965 for (Index
= 0; Index
< *NumberOfChildren
; Index
++) {
1967 // De register all the pci device
1969 Status
= DeRegisterPciDevice (RootBridgeHandle
, ChildHandleBuffer
[Index
]);
1971 if (EFI_ERROR (Status
)) {
1986 Search hostbridge according to given handle
1988 @param RootBridgeHandle - Host bridge handle.
1991 @return FALSE Not found.
1994 SearchHostBridgeHandle (
1995 IN EFI_HANDLE RootBridgeHandle
1998 EFI_HANDLE HostBridgeHandle
;
1999 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2004 // Get the rootbridge Io protocol to find the host bridge handle
2006 Status
= gBS
->OpenProtocol (
2008 &gEfiPciRootBridgeIoProtocolGuid
,
2009 (VOID
**) &PciRootBridgeIo
,
2010 gPciBusDriverBinding
.DriverBindingHandle
,
2012 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2015 if (EFI_ERROR (Status
)) {
2019 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
2020 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2021 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2030 Add host bridge handle to global variable for enumating.
2032 @param HostBridgeHandle host bridge handle.
2035 AddHostBridgeEnumerator (
2036 IN EFI_HANDLE HostBridgeHandle
2041 if (HostBridgeHandle
== NULL
) {
2045 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2046 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2051 if (Index
< PCI_MAX_HOST_BRIDGE_NUM
) {
2052 gPciHostBrigeHandles
[Index
] = HostBridgeHandle
;
2053 gPciHostBridgeNumber
++;