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 "PciOptionRomSupport.h"
20 This routine is used to enumerate entire pci bus system
23 @param Controller Parent controller handle.
25 @return Status of enumerating.
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 Success to enumerate root bridge.
134 @retval Others Fail 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 gBS
->FreePool (Configuration
);
228 if (EFI_ERROR (Status
)) {
236 This routine is used to process option rom on a certain root bridge
238 @param Bridge Given parent's root bridge
239 @param RomBase Base address of ROM driver loaded from
240 @param MaxLength Max rom size
242 @retval EFI_SUCCESS Success to process option rom image.
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
;
283 This routine is used to assign bus number to the given PCI bus system
285 @param Bridge Parent root bridge instance.
286 @param StartBusNumber Number of beginning.
287 @param SubBusNumber the number of sub bus.
289 @retval EFI_SUCCESS Success 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
325 Status
= PciDevicePresent (
333 if (!EFI_ERROR (Status
) &&
334 (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
337 // Reserved one bus for cardbus bridge
339 SecondBus
= ++(*SubBusNumber
);
341 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
343 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
345 Status
= PciRootBridgeIoWrite (
355 // Initialize SubBusNumber to SecondBus
357 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
358 Status
= PciRootBridgeIoWrite (
367 // If it is PPB, resursively search down this bridge
369 if (IS_PCI_BRIDGE (&Pci
)) {
372 Status
= PciRootBridgeIoWrite (
381 Status
= PciAssignBusNumber (
387 if (EFI_ERROR (Status
)) {
388 return EFI_DEVICE_ERROR
;
393 // Set the current maximum bus number under the PPB
396 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
398 Status
= PciRootBridgeIoWrite (
409 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
412 // Skip sub functions, this is not a multi function device
424 This routine is used to determine the root bridge attribute by interfacing
425 the host bridge resource allocation protocol.
427 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
428 @param RootBridgeDev Root bridge instance
430 @retval EFI_SUCCESS Success to get root bridge's attribute
431 @retval Others Fail to get attribute
434 DetermineRootBridgeAttributes (
435 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
436 IN PCI_IO_DEVICE
*RootBridgeDev
441 EFI_HANDLE RootBridgeHandle
;
444 RootBridgeHandle
= RootBridgeDev
->Handle
;
447 // Get root bridge attribute by calling into pci host bridge resource allocation protocol
449 Status
= PciResAlloc
->GetAllocAttributes (
455 if (EFI_ERROR (Status
)) {
460 // Here is the point where PCI bus driver calls HOST bridge allocation protocol
461 // Currently we hardcoded for ea815
464 if ((Attributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) {
465 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
;
468 if ((Attributes
& EFI_PCI_HOST_BRIDGE_MEM64_DECODE
) != 0) {
469 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
472 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
473 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
474 RootBridgeDev
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
480 Get Max Option Rom size on this bridge
482 @param Bridge Bridge device instance.
483 @return Max size of option rom.
486 GetMaxOptionRomSize (
487 IN PCI_IO_DEVICE
*Bridge
490 LIST_ENTRY
*CurrentLink
;
492 UINT64 MaxOptionRomSize
;
493 UINT64 TempOptionRomSize
;
495 MaxOptionRomSize
= 0;
498 // Go through bridges to reach all devices
500 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
501 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
502 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
503 if (!IsListEmpty (&Temp
->ChildList
)) {
506 // Get max option rom size under this bridge
508 TempOptionRomSize
= GetMaxOptionRomSize (Temp
);
511 // Compare with the option rom size of the bridge
512 // Get the larger one
514 if (Temp
->RomSize
> TempOptionRomSize
) {
515 TempOptionRomSize
= Temp
->RomSize
;
521 // For devices get the rom size directly
523 TempOptionRomSize
= Temp
->RomSize
;
527 // Get the largest rom size on this bridge
529 if (TempOptionRomSize
> MaxOptionRomSize
) {
530 MaxOptionRomSize
= TempOptionRomSize
;
533 CurrentLink
= CurrentLink
->ForwardLink
;
536 return MaxOptionRomSize
;
540 Process attributes of devices on this host bridge
542 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
544 @retval EFI_NOT_FOUND Can not find the specific root bridge device.
545 @retval EFI_SUCCESS Success Process attribute.
546 @retval Others Can not 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 pointer
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 PMemory resource
590 @param Mem64ResStatus Return the status of 64-bit Memory resource
591 @param PMem64ResStatus Return the status of 64-bit PMemory resource
593 @retval EFI_SUCCESS Success to get resource allocation status from ACPI configuration table.
596 GetResourceAllocationStatus (
598 OUT UINT64
*IoResStatus
,
599 OUT UINT64
*Mem32ResStatus
,
600 OUT UINT64
*PMem32ResStatus
,
601 OUT UINT64
*Mem64ResStatus
,
602 OUT UINT64
*PMem64ResStatus
608 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*ACPIAddressDesc
;
610 Temp
= (UINT8
*) AcpiConfig
;
612 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
614 ACPIAddressDesc
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
615 ResStatus
= ACPIAddressDesc
->AddrTranslationOffset
;
617 switch (ACPIAddressDesc
->ResType
) {
619 if (ACPIAddressDesc
->AddrSpaceGranularity
== 32) {
620 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
624 *PMem32ResStatus
= ResStatus
;
629 *Mem32ResStatus
= ResStatus
;
633 if (ACPIAddressDesc
->AddrSpaceGranularity
== 64) {
634 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
638 *PMem64ResStatus
= ResStatus
;
643 *Mem64ResStatus
= ResStatus
;
653 *IoResStatus
= ResStatus
;
660 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
667 Remove a PCI device from device pool and mark its bar
669 @param PciDevice Instance of Pci device.
671 @retval EFI_SUCCESS Success Operation.
672 @retval EFI_ABORTED Pci device is a root bridge.
676 IN PCI_IO_DEVICE
*PciDevice
679 PCI_IO_DEVICE
*Bridge
;
681 LIST_ENTRY
*CurrentLink
;
684 // Remove the padding resource from a bridge
686 if ( IS_PCI_BRIDGE(&PciDevice
->Pci
) && \
687 PciDevice
->ResourcePaddingDescriptors
!= NULL
) {
688 gBS
->FreePool (PciDevice
->ResourcePaddingDescriptors
);
689 PciDevice
->ResourcePaddingDescriptors
= NULL
;
696 if (IS_PCI_BRIDGE (&PciDevice
->Pci
) || (PciDevice
->Parent
== NULL
)) {
700 if (IS_CARDBUS_BRIDGE (&PciDevice
->Pci
)) {
702 // Get the root bridge device
705 while (Bridge
->Parent
!= NULL
) {
706 Bridge
= Bridge
->Parent
;
709 RemoveAllPciDeviceOnBridge (Bridge
->Handle
, PciDevice
);
714 InitializeP2C (PciDevice
);
720 Bridge
= PciDevice
->Parent
;
721 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
722 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
723 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
724 if (Temp
== PciDevice
) {
725 InitializePciDevice (Temp
);
726 RemoveEntryList (CurrentLink
);
727 FreePciDevice (Temp
);
731 CurrentLink
= CurrentLink
->ForwardLink
;
738 Determine whethter a PCI device can be rejected.
740 @param PciResNode Pointer to Pci resource node instance.
742 @return whethter a PCI device can be rejected.
746 IN PCI_RESOURCE_NODE
*PciResNode
751 Temp
= PciResNode
->PciDev
;
754 // Ensure the device is present
761 // PPB and RB should go ahead
763 if (IS_PCI_BRIDGE (&Temp
->Pci
) || (Temp
->Parent
== NULL
)) {
768 // Skip device on Bus0
770 if ((Temp
->Parent
!= NULL
) && (Temp
->BusNumber
== 0)) {
777 if (IS_PCI_VGA (&Temp
->Pci
)) {
785 Compare two resource node and get the larger resource consumer
787 @param PciResNode1 resource node 1 want to be compared
788 @param PciResNode2 resource node 2 want to be compared
790 @return Larger resource consumer.
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
)) {
822 Get the max resource consumer in the host resource pool.
824 @param ResPool Pointer to resource pool node.
826 @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 Pmemory resource node.
871 @param Mem64Pool Pointer to instance of 64-bit memory resource node.
872 @param PMem64Pool Pointer to instance of 64-bit Pmemory 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 Pmemory resource node.
876 @param Mem64ResStatus Status of 64-bit memory resource node.
877 @param PMem64ResStatus Status of 64-bit Pmemory resource node.
880 PciHostBridgeAdjustAllocation (
881 IN PCI_RESOURCE_NODE
*IoPool
,
882 IN PCI_RESOURCE_NODE
*Mem32Pool
,
883 IN PCI_RESOURCE_NODE
*PMem32Pool
,
884 IN PCI_RESOURCE_NODE
*Mem64Pool
,
885 IN PCI_RESOURCE_NODE
*PMem64Pool
,
886 IN UINT64 IoResStatus
,
887 IN UINT64 Mem32ResStatus
,
888 IN UINT64 PMem32ResStatus
,
889 IN UINT64 Mem64ResStatus
,
890 IN UINT64 PMem64ResStatus
893 BOOLEAN AllocationAjusted
;
894 PCI_RESOURCE_NODE
*PciResNode
;
895 PCI_RESOURCE_NODE
*ResPool
[5];
896 PCI_IO_DEVICE
*RemovedPciDev
[5];
898 UINTN RemovedPciDevNum
;
902 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
905 ZeroMem (RemovedPciDev
, 5 * sizeof (PCI_IO_DEVICE
*));
906 RemovedPciDevNum
= 0;
909 ResPool
[1] = Mem32Pool
;
910 ResPool
[2] = PMem32Pool
;
911 ResPool
[3] = Mem64Pool
;
912 ResPool
[4] = PMem64Pool
;
914 ResStatus
[0] = IoResStatus
;
915 ResStatus
[1] = Mem32ResStatus
;
916 ResStatus
[2] = PMem32ResStatus
;
917 ResStatus
[3] = Mem64ResStatus
;
918 ResStatus
[4] = PMem64ResStatus
;
920 AllocationAjusted
= FALSE
;
922 for (ResType
= 0; ResType
< 5; ResType
++) {
924 if (ResStatus
[ResType
] == EFI_RESOURCE_SATISFIED
) {
928 if (ResStatus
[ResType
] == EFI_RESOURCE_NOT_SATISFIED
) {
930 // Hostbridge hasn't this resource type
936 // Hostbridge hasn't enough resource
938 PciResNode
= GetMaxResourceConsumerDevice (ResPool
[ResType
]);
939 if (PciResNode
== NULL
) {
944 // Check if the device has been removed before
946 for (DevIndex
= 0; DevIndex
< RemovedPciDevNum
; DevIndex
++) {
947 if (PciResNode
->PciDev
== RemovedPciDev
[DevIndex
]) {
952 if (DevIndex
!= RemovedPciDevNum
) {
957 // Remove the device if it isn't in the array
959 Status
= RejectPciDevice (PciResNode
->PciDev
);
960 if (Status
== EFI_SUCCESS
) {
963 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
966 // Have no way to get ReqRes, AllocRes & Bar here
968 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
969 AllocFailExtendedData
.DevicePathSize
= sizeof (EFI_DEVICE_PATH_PROTOCOL
);
970 AllocFailExtendedData
.DevicePath
= (UINT8
*) PciResNode
->PciDev
->DevicePath
;
971 AllocFailExtendedData
.Bar
= PciResNode
->Bar
;
973 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
975 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
976 (VOID
*) &AllocFailExtendedData
,
977 sizeof (AllocFailExtendedData
)
981 // Add it to the array and indicate at least a device has been rejected
983 RemovedPciDev
[RemovedPciDevNum
++] = PciResNode
->PciDev
;
984 AllocationAjusted
= TRUE
;
991 if (AllocationAjusted
) {
999 Summary requests for all resource type, and contruct ACPI resource
1002 @param Bridge detecting bridge
1003 @param IoNode Pointer to instance of I/O resource Node
1004 @param Mem32Node Pointer to instance of 32-bit memory resource Node
1005 @param PMem32Node Pointer to instance of 32-bit Pmemory resource node
1006 @param Mem64Node Pointer to instance of 64-bit memory resource node
1007 @param PMem64Node Pointer to instance of 64-bit Pmemory resource node
1008 @param pConfig outof buffer holding new constructed APCI resource requestor
1011 ConstructAcpiResourceRequestor (
1012 IN PCI_IO_DEVICE
*Bridge
,
1013 IN PCI_RESOURCE_NODE
*IoNode
,
1014 IN PCI_RESOURCE_NODE
*Mem32Node
,
1015 IN PCI_RESOURCE_NODE
*PMem32Node
,
1016 IN PCI_RESOURCE_NODE
*Mem64Node
,
1017 IN PCI_RESOURCE_NODE
*PMem64Node
,
1023 UINT8
*Configuration
;
1024 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1025 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
1033 // if there is io request, add to the io aperture
1035 if (ResourceRequestExisted (IoNode
)) {
1041 // if there is mem32 request, add to the mem32 aperture
1043 if (ResourceRequestExisted (Mem32Node
)) {
1049 // if there is pmem32 request, add to the pmem32 aperture
1051 if (ResourceRequestExisted (PMem32Node
)) {
1057 // if there is mem64 request, add to the mem64 aperture
1059 if (ResourceRequestExisted (Mem64Node
)) {
1065 // if there is pmem64 request, add to the pmem64 aperture
1067 if (ResourceRequestExisted (PMem64Node
)) {
1072 if (NumConfig
!= 0) {
1075 // If there is at least one type of resource request,
1076 // allocate a acpi resource node
1078 Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1079 if (Configuration
== NULL
) {
1080 return EFI_OUT_OF_RESOURCES
;
1085 sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
1088 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1091 // Deal with io aperture
1093 if ((Aperture
& 0x01) != 0) {
1094 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1095 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1099 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1103 Ptr
->SpecificFlag
= 1;
1104 Ptr
->AddrLen
= IoNode
->Length
;
1105 Ptr
->AddrRangeMax
= IoNode
->Alignment
;
1107 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) ((UINT8
*) Ptr
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1110 // Deal with mem32 aperture
1112 if ((Aperture
& 0x02) != 0) {
1113 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1114 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1118 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1122 Ptr
->SpecificFlag
= 0;
1126 Ptr
->AddrSpaceGranularity
= 32;
1127 Ptr
->AddrLen
= Mem32Node
->Length
;
1128 Ptr
->AddrRangeMax
= Mem32Node
->Alignment
;
1130 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) ((UINT8
*) Ptr
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1134 // Deal with Pmem32 aperture
1136 if ((Aperture
& 0x04) != 0) {
1137 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1138 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1142 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1146 Ptr
->SpecificFlag
= 0x6;
1150 Ptr
->AddrSpaceGranularity
= 32;
1151 Ptr
->AddrLen
= PMem32Node
->Length
;
1152 Ptr
->AddrRangeMax
= PMem32Node
->Alignment
;
1154 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) ((UINT8
*) Ptr
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1157 // Deal with mem64 aperture
1159 if ((Aperture
& 0x08) != 0) {
1160 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1161 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1165 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1169 Ptr
->SpecificFlag
= 0;
1173 Ptr
->AddrSpaceGranularity
= 64;
1174 Ptr
->AddrLen
= Mem64Node
->Length
;
1175 Ptr
->AddrRangeMax
= Mem64Node
->Alignment
;
1177 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) ((UINT8
*) Ptr
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1180 // Deal with Pmem64 aperture
1182 if ((Aperture
& 0x10) != 0) {
1183 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1184 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1188 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1192 Ptr
->SpecificFlag
= 0x06;
1196 Ptr
->AddrSpaceGranularity
= 64;
1197 Ptr
->AddrLen
= PMem64Node
->Length
;
1198 Ptr
->AddrRangeMax
= PMem64Node
->Alignment
;
1200 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) ((UINT8
*) Ptr
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1206 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) ((UINT8
*) Ptr
);
1208 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1209 PtrEnd
->Checksum
= 0;
1214 // If there is no resource request
1216 Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1217 if (Configuration
== NULL
) {
1218 return EFI_OUT_OF_RESOURCES
;
1221 ZeroMem (Configuration
, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1223 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (Configuration
);
1224 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1226 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Configuration
+ sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
));
1227 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1228 PtrEnd
->Checksum
= 0;
1231 *pConfig
= Configuration
;
1237 Get resource base from a acpi configuration descriptor.
1239 @param pConfig an acpi configuration descriptor.
1240 @param IoBase output of I/O resource base address.
1241 @param Mem32Base output of 32-bit memory base address.
1242 @param PMem32Base output of 32-bit pmemory base address.
1243 @param Mem64Base output of 64-bit memory base address.
1244 @param PMem64Base output of 64-bit pmemory base address.
1246 @return EFI_SUCCESS Success operation.
1252 OUT UINT64
*Mem32Base
,
1253 OUT UINT64
*PMem32Base
,
1254 OUT UINT64
*Mem64Base
,
1255 OUT UINT64
*PMem64Base
1259 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1262 *IoBase
= 0xFFFFFFFFFFFFFFFFULL
;
1263 *Mem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1264 *PMem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1265 *Mem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1266 *PMem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1268 Temp
= (UINT8
*) pConfig
;
1270 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1272 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1273 ResStatus
= Ptr
->AddrTranslationOffset
;
1275 if (ResStatus
== EFI_RESOURCE_SATISFIED
) {
1277 switch (Ptr
->ResType
) {
1280 // Memory type aperture
1285 // Check to see the granularity
1287 if (Ptr
->AddrSpaceGranularity
== 32) {
1288 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1289 *PMem32Base
= Ptr
->AddrRangeMin
;
1291 *Mem32Base
= Ptr
->AddrRangeMin
;
1295 if (Ptr
->AddrSpaceGranularity
== 64) {
1296 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1297 *PMem64Base
= Ptr
->AddrRangeMin
;
1299 *Mem64Base
= Ptr
->AddrRangeMin
;
1309 *IoBase
= Ptr
->AddrRangeMin
;
1323 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1330 Enumerate pci bridge, allocate resource and determine attribute
1331 for devices on this bridge
1333 @param BridgeDev Pointer to instance of bridge device.
1335 @retval EFI_SUCCESS Success operation.
1336 @retval Others Fail to enumerate.
1339 PciBridgeEnumerator (
1340 IN PCI_IO_DEVICE
*BridgeDev
1344 UINT8 StartBusNumber
;
1345 EFI_PCI_IO_PROTOCOL
*PciIo
;
1350 PciIo
= &(BridgeDev
->PciIo
);
1351 Status
= PciIoRead (PciIo
, EfiPciIoWidthUint8
, 0x19, 1, &StartBusNumber
);
1353 if (EFI_ERROR (Status
)) {
1357 Status
= PciAssignBusNumber (
1363 if (EFI_ERROR (Status
)) {
1367 Status
= PciPciDeviceInfoCollector (BridgeDev
, StartBusNumber
);
1369 if (EFI_ERROR (Status
)) {
1373 Status
= PciBridgeResourceAllocator (BridgeDev
);
1375 if (EFI_ERROR (Status
)) {
1379 Status
= DetermineDeviceAttribute (BridgeDev
);
1381 if (EFI_ERROR (Status
)) {
1390 Allocate all kinds of resource for bridge
1392 @param Bridge Pointer to bridge instance.
1394 @retval EFI_SUCCESS Success operation.
1395 @retval Others Fail to allocate resource for bridge.
1398 PciBridgeResourceAllocator (
1399 IN PCI_IO_DEVICE
*Bridge
1402 PCI_RESOURCE_NODE
*IoBridge
;
1403 PCI_RESOURCE_NODE
*Mem32Bridge
;
1404 PCI_RESOURCE_NODE
*PMem32Bridge
;
1405 PCI_RESOURCE_NODE
*Mem64Bridge
;
1406 PCI_RESOURCE_NODE
*PMem64Bridge
;
1414 IoBridge
= CreateResourceNode (
1423 Mem32Bridge
= CreateResourceNode (
1432 PMem32Bridge
= CreateResourceNode (
1441 Mem64Bridge
= CreateResourceNode (
1450 PMem64Bridge
= CreateResourceNode (
1460 // Create resourcemap by going through all the devices subject to this root bridge
1462 Status
= CreateResourceMap (
1471 if (EFI_ERROR (Status
)) {
1475 Status
= GetResourceBaseFromBridge (
1484 if (EFI_ERROR (Status
)) {
1489 // Program IO resources
1497 // Program Mem32 resources
1505 // Program PMem32 resources
1513 // Program Mem64 resources
1521 // Program PMem64 resources
1528 DestroyResourceTree (IoBridge
);
1529 DestroyResourceTree (Mem32Bridge
);
1530 DestroyResourceTree (PMem32Bridge
);
1531 DestroyResourceTree (PMem64Bridge
);
1532 DestroyResourceTree (Mem64Bridge
);
1534 gBS
->FreePool (IoBridge
);
1535 gBS
->FreePool (Mem32Bridge
);
1536 gBS
->FreePool (PMem32Bridge
);
1537 gBS
->FreePool (PMem64Bridge
);
1538 gBS
->FreePool (Mem64Bridge
);
1544 Get resource base address for a pci bridge device
1546 @param Bridge Given Pci driver instance.
1547 @param IoBase output for base address of I/O type resource.
1548 @param Mem32Base output for base address of 32-bit memory type resource.
1549 @param PMem32Base output for base address of 32-bit Pmemory type resource.
1550 @param Mem64Base output for base address of 64-bit memory type resource.
1551 @param PMem64Base output for base address of 64-bit Pmemory type resource.
1553 @retval EFI_SUCCESS Succes to get resource base address.
1556 GetResourceBaseFromBridge (
1557 IN PCI_IO_DEVICE
*Bridge
,
1559 OUT UINT64
*Mem32Base
,
1560 OUT UINT64
*PMem32Base
,
1561 OUT UINT64
*Mem64Base
,
1562 OUT UINT64
*PMem64Base
1565 if (!Bridge
->Allocated
) {
1566 return EFI_OUT_OF_RESOURCES
;
1570 *Mem32Base
= gAllOne
;
1571 *PMem32Base
= gAllOne
;
1572 *Mem64Base
= gAllOne
;
1573 *PMem64Base
= gAllOne
;
1575 if (IS_PCI_BRIDGE (&Bridge
->Pci
)) {
1577 if (Bridge
->PciBar
[PPB_IO_RANGE
].Length
> 0) {
1578 *IoBase
= Bridge
->PciBar
[PPB_IO_RANGE
].BaseAddress
;
1581 if (Bridge
->PciBar
[PPB_MEM32_RANGE
].Length
> 0) {
1582 *Mem32Base
= Bridge
->PciBar
[PPB_MEM32_RANGE
].BaseAddress
;
1585 if (Bridge
->PciBar
[PPB_PMEM32_RANGE
].Length
> 0) {
1586 *PMem32Base
= Bridge
->PciBar
[PPB_PMEM32_RANGE
].BaseAddress
;
1589 if (Bridge
->PciBar
[PPB_PMEM64_RANGE
].Length
> 0) {
1590 *PMem64Base
= Bridge
->PciBar
[PPB_PMEM64_RANGE
].BaseAddress
;
1592 *PMem64Base
= gAllOne
;
1597 if (IS_CARDBUS_BRIDGE (&Bridge
->Pci
)) {
1598 if (Bridge
->PciBar
[P2C_IO_1
].Length
> 0) {
1599 *IoBase
= Bridge
->PciBar
[P2C_IO_1
].BaseAddress
;
1601 if (Bridge
->PciBar
[P2C_IO_2
].Length
> 0) {
1602 *IoBase
= Bridge
->PciBar
[P2C_IO_2
].BaseAddress
;
1606 if (Bridge
->PciBar
[P2C_MEM_1
].Length
> 0) {
1607 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypePMem32
) {
1608 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1611 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypeMem32
) {
1612 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1616 if (Bridge
->PciBar
[P2C_MEM_2
].Length
> 0) {
1617 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypePMem32
) {
1618 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1621 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypeMem32
) {
1622 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1631 These are the notifications from the PCI bus driver that it is about to enter a certain
1632 phase of the PCI enumeration process.
1634 This member function can be used to notify the host bridge driver to perform specific actions,
1635 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1636 Eight notification points are defined at this time. See belows:
1637 EfiPciHostBridgeBeginEnumeration - Resets the host bridge PCI apertures and internal data
1638 structures. The PCI enumerator should issue this notification
1639 before starting a fresh enumeration process. Enumeration cannot
1640 be restarted after sending any other notification such as
1641 EfiPciHostBridgeBeginBusAllocation.
1642 EfiPciHostBridgeBeginBusAllocation - The bus allocation phase is about to begin. No specific action is
1643 required here. This notification can be used to perform any
1644 chipset-specific programming.
1645 EfiPciHostBridgeEndBusAllocation - The bus allocation and bus programming phase is complete. No
1646 specific action is required here. This notification can be used to
1647 perform any chipset-specific programming.
1648 EfiPciHostBridgeBeginResourceAllocation - The resource allocation phase is about to begin. No specific
1649 action is required here. This notification can be used to perform
1650 any chipset-specific programming.
1651 EfiPciHostBridgeAllocateResources - Allocates resources per previously submitted requests for all the PCI
1652 root bridges. These resource settings are returned on the next call to
1653 GetProposedResources(). Before calling NotifyPhase() with a Phase of
1654 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible for gathering I/O and memory requests for
1655 all the PCI root bridges and submitting these requests using
1656 SubmitResources(). This function pads the resource amount
1657 to suit the root bridge hardware, takes care of dependencies between
1658 the PCI root bridges, and calls the Global Coherency Domain (GCD)
1659 with the allocation request. In the case of padding, the allocated range
1660 could be bigger than what was requested.
1661 EfiPciHostBridgeSetResources - Programs the host bridge hardware to decode previously allocated
1662 resources (proposed resources) for all the PCI root bridges. After the
1663 hardware is programmed, reassigning resources will not be supported.
1664 The bus settings are not affected.
1665 EfiPciHostBridgeFreeResources - Deallocates resources that were previously allocated for all the PCI
1666 root bridges and resets the I/O and memory apertures to their initial
1667 state. The bus settings are not affected. If the request to allocate
1668 resources fails, the PCI enumerator can use this notification to
1669 deallocate previous resources, adjust the requests, and retry
1671 EfiPciHostBridgeEndResourceAllocation- The resource allocation phase is completed. No specific action is
1672 required here. This notification can be used to perform any chipsetspecific
1675 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1676 @param[in] Phase The phase during enumeration
1678 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
1679 is valid for a Phase of EfiPciHostBridgeAllocateResources if
1680 SubmitResources() has not been called for one or more
1681 PCI root bridges before this call
1682 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
1683 for a Phase of EfiPciHostBridgeSetResources.
1684 @retval EFI_INVALID_PARAMETER Invalid phase parameter
1685 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1686 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1687 previously submitted resource requests cannot be fulfilled or
1688 were only partially fulfilled.
1689 @retval EFI_SUCCESS The notification was accepted without any errors.
1694 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
1695 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1698 EFI_HANDLE HostBridgeHandle
;
1699 EFI_HANDLE RootBridgeHandle
;
1700 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1703 HostBridgeHandle
= NULL
;
1704 RootBridgeHandle
= NULL
;
1705 if (gPciPlatformProtocol
!= NULL
) {
1707 // Get Host Bridge Handle.
1709 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1712 // Get the rootbridge Io protocol to find the host bridge handle
1714 Status
= gBS
->HandleProtocol (
1716 &gEfiPciRootBridgeIoProtocolGuid
,
1717 (VOID
**) &PciRootBridgeIo
1720 if (EFI_ERROR (Status
)) {
1721 return EFI_NOT_FOUND
;
1724 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1727 // Call PlatformPci::PhaseNotify() if the protocol is present.
1729 gPciPlatformProtocol
->PhaseNotify (
1730 gPciPlatformProtocol
,
1737 Status
= PciResAlloc
->NotifyPhase (
1742 if (gPciPlatformProtocol
!= NULL
) {
1744 // Call PlatformPci::PhaseNotify() if the protocol is present.
1746 gPciPlatformProtocol
->PhaseNotify (
1747 gPciPlatformProtocol
,
1759 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1760 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1761 PCI controllers before enumeration.
1763 This function is called during the PCI enumeration process. No specific action is expected from this
1764 member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1767 @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1768 @param Bus The bus number of the pci device.
1769 @param Device The device number of the pci device.
1770 @param Func The function number of the pci device.
1771 @param Phase The phase of the PCI device enumeration.
1773 @retval EFI_SUCCESS The requested parameters were returned.
1774 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
1775 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
1776 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1777 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
1778 not enumerate this device, including its child devices if it is a PCI-to-PCI
1783 PreprocessController (
1784 IN PCI_IO_DEVICE
*Bridge
,
1788 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1791 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress
;
1792 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
1793 EFI_HANDLE RootBridgeHandle
;
1794 EFI_HANDLE HostBridgeHandle
;
1798 // Get the host bridge handle
1800 HostBridgeHandle
= Bridge
->PciRootBridgeIo
->ParentHandle
;
1803 // Get the pci host bridge resource allocation protocol
1805 Status
= gBS
->OpenProtocol (
1807 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
1808 (VOID
**) &PciResAlloc
,
1811 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1814 if (EFI_ERROR (Status
)) {
1815 return EFI_UNSUPPORTED
;
1819 // Get Root Brige Handle
1821 while (Bridge
->Parent
!= NULL
) {
1822 Bridge
= Bridge
->Parent
;
1825 RootBridgeHandle
= Bridge
->Handle
;
1827 RootBridgePciAddress
.Register
= 0;
1828 RootBridgePciAddress
.Function
= Func
;
1829 RootBridgePciAddress
.Device
= Device
;
1830 RootBridgePciAddress
.Bus
= Bus
;
1831 RootBridgePciAddress
.ExtendedRegister
= 0;
1833 if (gPciPlatformProtocol
!= NULL
) {
1835 // Call PlatformPci::PrepController() if the protocol is present.
1837 gPciPlatformProtocol
->PlatformPrepController (
1838 gPciPlatformProtocol
,
1841 RootBridgePciAddress
,
1847 Status
= PciResAlloc
->PreprocessController (
1850 RootBridgePciAddress
,
1854 if (gPciPlatformProtocol
!= NULL
) {
1856 // Call PlatformPci::PrepController() if the protocol is present.
1858 gPciPlatformProtocol
->PlatformPrepController (
1859 gPciPlatformProtocol
,
1862 RootBridgePciAddress
,
1872 Hot plug request notify.
1874 @param This - A pointer to the hot plug request protocol.
1875 @param Operation - The operation.
1876 @param Controller - A pointer to the controller.
1877 @param RemainingDevicePath - A pointer to the device path.
1878 @param NumberOfChildren - A the number of child handle in the ChildHandleBuffer.
1879 @param ChildHandleBuffer - A pointer to the array contain the child handle.
1881 @retval EFI_NOT_FOUND Can not find bridge according to controller handle.
1882 @retval EFI_SUCCESS Success operating.
1886 PciHotPlugRequestNotify (
1887 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL
* This
,
1888 IN EFI_PCI_HOTPLUG_OPERATION Operation
,
1889 IN EFI_HANDLE Controller
,
1890 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
,
1891 IN OUT UINT8
*NumberOfChildren
,
1892 IN OUT EFI_HANDLE
* ChildHandleBuffer
1895 PCI_IO_DEVICE
*Bridge
;
1896 PCI_IO_DEVICE
*Temp
;
1897 EFI_PCI_IO_PROTOCOL
*PciIo
;
1899 EFI_HANDLE RootBridgeHandle
;
1902 Status
= gBS
->OpenProtocol (
1904 &gEfiPciIoProtocolGuid
,
1906 gPciBusDriverBinding
.DriverBindingHandle
,
1908 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1911 if (EFI_ERROR (Status
)) {
1912 return EFI_NOT_FOUND
;
1915 Bridge
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
1918 // Get root bridge handle
1921 while (Temp
->Parent
!= NULL
) {
1922 Temp
= Temp
->Parent
;
1925 RootBridgeHandle
= Temp
->Handle
;
1927 if (Operation
== EfiPciHotPlugRequestAdd
) {
1929 if (NumberOfChildren
!= NULL
) {
1930 *NumberOfChildren
= 0;
1933 if (IsListEmpty (&Bridge
->ChildList
)) {
1935 Status
= PciBridgeEnumerator (Bridge
);
1937 if (EFI_ERROR (Status
)) {
1942 Status
= StartPciDevicesOnBridge (
1945 RemainingDevicePath
,
1953 if (Operation
== EfiPciHotplugRequestRemove
) {
1955 if (*NumberOfChildren
== 0) {
1957 // Remove all devices on the bridge
1959 Status
= RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Bridge
);
1964 for (Index
= 0; Index
< *NumberOfChildren
; Index
++) {
1966 // De register all the pci device
1968 Status
= DeRegisterPciDevice (RootBridgeHandle
, ChildHandleBuffer
[Index
]);
1970 if (EFI_ERROR (Status
)) {
1985 Search hostbridge according to given handle
1987 @param RootBridgeHandle - Host bridge handle.
1990 @return FALSE Not found.
1993 SearchHostBridgeHandle (
1994 IN EFI_HANDLE RootBridgeHandle
1997 EFI_HANDLE HostBridgeHandle
;
1998 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2003 // Get the rootbridge Io protocol to find the host bridge handle
2005 Status
= gBS
->OpenProtocol (
2007 &gEfiPciRootBridgeIoProtocolGuid
,
2008 (VOID
**) &PciRootBridgeIo
,
2009 gPciBusDriverBinding
.DriverBindingHandle
,
2011 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2014 if (EFI_ERROR (Status
)) {
2018 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
2019 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2020 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2029 Add host bridge handle to global variable for enumating.
2031 @param HostBridgeHandle host bridge handle.
2034 AddHostBridgeEnumerator (
2035 IN EFI_HANDLE HostBridgeHandle
2040 if (HostBridgeHandle
== NULL
) {
2044 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2045 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2050 if (Index
< PCI_MAX_HOST_BRIDGE_NUM
) {
2051 gPciHostBrigeHandles
[Index
] = HostBridgeHandle
;
2052 gPciHostBridgeNumber
++;