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
= PciRootBridgeIo
->Pci
.Write (
353 // Initialize SubBusNumber to SecondBus
355 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
356 Status
= PciRootBridgeIo
->Pci
.Write (
364 // If it is PPB, resursively search down this bridge
366 if (IS_PCI_BRIDGE (&Pci
)) {
369 Status
= PciRootBridgeIo
->Pci
.Write (
377 Status
= PciAssignBusNumber (
383 if (EFI_ERROR (Status
)) {
384 return EFI_DEVICE_ERROR
;
389 // Set the current maximum bus number under the PPB
391 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
393 Status
= PciRootBridgeIo
->Pci
.Write (
403 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
406 // Skip sub functions, this is not a multi function device
417 This routine is used to determine the root bridge attribute by interfacing
418 the host bridge resource allocation protocol.
420 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
421 @param RootBridgeDev Root bridge instance
423 @retval EFI_SUCCESS Successfully got root bridge's attribute.
424 @retval other Failed to get attribute.
428 DetermineRootBridgeAttributes (
429 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
430 IN PCI_IO_DEVICE
*RootBridgeDev
435 EFI_HANDLE RootBridgeHandle
;
438 RootBridgeHandle
= RootBridgeDev
->Handle
;
441 // Get root bridge attribute by calling into pci host bridge resource allocation protocol
443 Status
= PciResAlloc
->GetAllocAttributes (
449 if (EFI_ERROR (Status
)) {
454 // Here is the point where PCI bus driver calls HOST bridge allocation protocol
455 // Currently we hardcoded for ea815
457 if ((Attributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) {
458 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED
;
461 if ((Attributes
& EFI_PCI_HOST_BRIDGE_MEM64_DECODE
) != 0) {
462 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
465 RootBridgeDev
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
466 RootBridgeDev
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
467 RootBridgeDev
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
473 Get Max Option Rom size on specified bridge.
475 @param Bridge Given bridge device instance.
477 @return Max size of option rom needed.
481 GetMaxOptionRomSize (
482 IN PCI_IO_DEVICE
*Bridge
485 LIST_ENTRY
*CurrentLink
;
487 UINT64 MaxOptionRomSize
;
488 UINT64 TempOptionRomSize
;
490 MaxOptionRomSize
= 0;
493 // Go through bridges to reach all devices
495 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
496 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
497 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
498 if (!IsListEmpty (&Temp
->ChildList
)) {
501 // Get max option rom size under this bridge
503 TempOptionRomSize
= GetMaxOptionRomSize (Temp
);
506 // Compare with the option rom size of the bridge
507 // Get the larger one
509 if (Temp
->RomSize
> TempOptionRomSize
) {
510 TempOptionRomSize
= Temp
->RomSize
;
516 // For devices get the rom size directly
518 TempOptionRomSize
= Temp
->RomSize
;
522 // Get the largest rom size on this bridge
524 if (TempOptionRomSize
> MaxOptionRomSize
) {
525 MaxOptionRomSize
= TempOptionRomSize
;
528 CurrentLink
= CurrentLink
->ForwardLink
;
531 return MaxOptionRomSize
;
535 Process attributes of devices on this host bridge
537 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
539 @retval EFI_SUCCESS Successfully process attribute.
540 @retval EFI_NOT_FOUND Can not find the specific root bridge device.
541 @retval other Failed to determine the root bridge device's attribute.
545 PciHostBridgeDeviceAttribute (
546 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
549 EFI_HANDLE RootBridgeHandle
;
550 PCI_IO_DEVICE
*RootBridgeDev
;
553 RootBridgeHandle
= NULL
;
555 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
558 // Get RootBridg Device by handle
560 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
562 if (RootBridgeDev
== NULL
) {
563 return EFI_NOT_FOUND
;
567 // Set the attributes for devcies behind the Root Bridge
569 Status
= DetermineDeviceAttribute (RootBridgeDev
);
570 if (EFI_ERROR (Status
)) {
580 Get resource allocation status from the ACPI resource descriptor.
582 @param AcpiConfig Point to Acpi configuration table.
583 @param IoResStatus Return the status of I/O resource.
584 @param Mem32ResStatus Return the status of 32-bit Memory resource.
585 @param PMem32ResStatus Return the status of 32-bit Prefetchable Memory resource.
586 @param Mem64ResStatus Return the status of 64-bit Memory resource.
587 @param PMem64ResStatus Return the status of 64-bit Prefetchable Memory resource.
591 GetResourceAllocationStatus (
593 OUT UINT64
*IoResStatus
,
594 OUT UINT64
*Mem32ResStatus
,
595 OUT UINT64
*PMem32ResStatus
,
596 OUT UINT64
*Mem64ResStatus
,
597 OUT UINT64
*PMem64ResStatus
602 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*ACPIAddressDesc
;
604 Temp
= (UINT8
*) AcpiConfig
;
606 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
608 ACPIAddressDesc
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
609 ResStatus
= ACPIAddressDesc
->AddrTranslationOffset
;
611 switch (ACPIAddressDesc
->ResType
) {
613 if (ACPIAddressDesc
->AddrSpaceGranularity
== 32) {
614 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
618 *PMem32ResStatus
= ResStatus
;
623 *Mem32ResStatus
= ResStatus
;
627 if (ACPIAddressDesc
->AddrSpaceGranularity
== 64) {
628 if (ACPIAddressDesc
->SpecificFlag
== 0x06) {
632 *PMem64ResStatus
= ResStatus
;
637 *Mem64ResStatus
= ResStatus
;
647 *IoResStatus
= ResStatus
;
654 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
659 Remove a PCI device from device pool and mark its bar.
661 @param PciDevice Instance of Pci device.
663 @retval EFI_SUCCESS Successfully remove the PCI device.
664 @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
669 IN PCI_IO_DEVICE
*PciDevice
672 PCI_IO_DEVICE
*Bridge
;
674 LIST_ENTRY
*CurrentLink
;
677 // Remove the padding resource from a bridge
679 if ( IS_PCI_BRIDGE(&PciDevice
->Pci
) &&
680 PciDevice
->ResourcePaddingDescriptors
!= NULL
) {
681 FreePool (PciDevice
->ResourcePaddingDescriptors
);
682 PciDevice
->ResourcePaddingDescriptors
= NULL
;
689 if (IS_PCI_BRIDGE (&PciDevice
->Pci
) || (PciDevice
->Parent
== NULL
)) {
693 if (IS_CARDBUS_BRIDGE (&PciDevice
->Pci
)) {
695 // Get the root bridge device
698 while (Bridge
->Parent
!= NULL
) {
699 Bridge
= Bridge
->Parent
;
702 RemoveAllPciDeviceOnBridge (Bridge
->Handle
, PciDevice
);
707 InitializeP2C (PciDevice
);
713 Bridge
= PciDevice
->Parent
;
714 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
715 while (CurrentLink
!= NULL
&& CurrentLink
!= &Bridge
->ChildList
) {
716 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
717 if (Temp
== PciDevice
) {
718 InitializePciDevice (Temp
);
719 RemoveEntryList (CurrentLink
);
720 FreePciDevice (Temp
);
724 CurrentLink
= CurrentLink
->ForwardLink
;
731 Determine whethter a PCI device can be rejected.
733 @param PciResNode Pointer to Pci resource node instance.
735 @retval TRUE The PCI device can be rejected.
736 @retval TRUE The PCI device cannot be rejected.
741 IN PCI_RESOURCE_NODE
*PciResNode
746 Temp
= PciResNode
->PciDev
;
749 // Ensure the device is present
756 // PPB and RB should go ahead
758 if (IS_PCI_BRIDGE (&Temp
->Pci
) || (Temp
->Parent
== NULL
)) {
763 // Skip device on Bus0
765 if ((Temp
->Parent
!= NULL
) && (Temp
->BusNumber
== 0)) {
772 if (IS_PCI_VGA (&Temp
->Pci
)) {
780 Compare two resource nodes and get the larger resource consumer.
782 @param PciResNode1 resource node 1 want to be compared
783 @param PciResNode2 resource node 2 want to be compared
785 @return Larger resource node.
789 GetLargerConsumerDevice (
790 IN PCI_RESOURCE_NODE
*PciResNode1
,
791 IN PCI_RESOURCE_NODE
*PciResNode2
794 if (PciResNode2
== NULL
) {
798 if ((IS_PCI_BRIDGE(&(PciResNode2
->PciDev
->Pci
)) || (PciResNode2
->PciDev
->Parent
== NULL
)) \
799 && (PciResNode2
->ResourceUsage
!= PciResUsagePadding
) )
804 if (PciResNode1
== NULL
) {
808 if ((PciResNode1
->Length
) > (PciResNode2
->Length
)) {
817 Get the max resource consumer in the host resource pool.
819 @param ResPool Pointer to resource pool node.
821 @return The max resource consumer in the host resource pool.
825 GetMaxResourceConsumerDevice (
826 IN PCI_RESOURCE_NODE
*ResPool
829 PCI_RESOURCE_NODE
*Temp
;
830 LIST_ENTRY
*CurrentLink
;
831 PCI_RESOURCE_NODE
*PciResNode
;
832 PCI_RESOURCE_NODE
*PPBResNode
;
836 CurrentLink
= ResPool
->ChildList
.ForwardLink
;
837 while (CurrentLink
!= NULL
&& CurrentLink
!= &ResPool
->ChildList
) {
839 Temp
= RESOURCE_NODE_FROM_LINK (CurrentLink
);
841 if (!IsRejectiveDevice (Temp
)) {
842 CurrentLink
= CurrentLink
->ForwardLink
;
846 if ((IS_PCI_BRIDGE (&(Temp
->PciDev
->Pci
)) || (Temp
->PciDev
->Parent
== NULL
)) \
847 && (Temp
->ResourceUsage
!= PciResUsagePadding
))
849 PPBResNode
= GetMaxResourceConsumerDevice (Temp
);
850 PciResNode
= GetLargerConsumerDevice (PciResNode
, PPBResNode
);
852 PciResNode
= GetLargerConsumerDevice (PciResNode
, Temp
);
855 CurrentLink
= CurrentLink
->ForwardLink
;
862 Adjust host bridge allocation so as to reduce resource requirement
864 @param IoPool Pointer to instance of I/O resource Node.
865 @param Mem32Pool Pointer to instance of 32-bit memory resource Node.
866 @param PMem32Pool Pointer to instance of 32-bit Prefetchable memory resource node.
867 @param Mem64Pool Pointer to instance of 64-bit memory resource node.
868 @param PMem64Pool Pointer to instance of 64-bit Prefetchable memory resource node.
869 @param IoResStatus Status of I/O resource Node.
870 @param Mem32ResStatus Status of 32-bit memory resource Node.
871 @param PMem32ResStatus Status of 32-bit Prefetchable memory resource node.
872 @param Mem64ResStatus Status of 64-bit memory resource node.
873 @param PMem64ResStatus Status of 64-bit Prefetchable memory resource node.
875 @retval EFI_SUCCESS Successfully adjusted resoruce on host bridge.
876 @retval EFI_ABORTED Host bridge hasn't this resource type or no resource be adjusted.
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 // Host bridge 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 Config Output buffer holding new constructed APCI resource requestor
1010 @retval EFI_SUCCESS Successfully constructed ACPI resource.
1011 @retval EFI_OUT_OF_RESOURCES No memory availabe.
1015 ConstructAcpiResourceRequestor (
1016 IN PCI_IO_DEVICE
*Bridge
,
1017 IN PCI_RESOURCE_NODE
*IoNode
,
1018 IN PCI_RESOURCE_NODE
*Mem32Node
,
1019 IN PCI_RESOURCE_NODE
*PMem32Node
,
1020 IN PCI_RESOURCE_NODE
*Mem64Node
,
1021 IN PCI_RESOURCE_NODE
*PMem64Node
,
1027 UINT8
*Configuration
;
1028 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1029 EFI_ACPI_END_TAG_DESCRIPTOR
*PtrEnd
;
1037 // if there is io request, add to the io aperture
1039 if (ResourceRequestExisted (IoNode
)) {
1045 // if there is mem32 request, add to the mem32 aperture
1047 if (ResourceRequestExisted (Mem32Node
)) {
1053 // if there is pmem32 request, add to the pmem32 aperture
1055 if (ResourceRequestExisted (PMem32Node
)) {
1061 // if there is mem64 request, add to the mem64 aperture
1063 if (ResourceRequestExisted (Mem64Node
)) {
1069 // if there is pmem64 request, add to the pmem64 aperture
1071 if (ResourceRequestExisted (PMem64Node
)) {
1076 if (NumConfig
!= 0) {
1079 // If there is at least one type of resource request,
1080 // allocate a acpi resource node
1082 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) * NumConfig
+ sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1083 if (Configuration
== NULL
) {
1084 return EFI_OUT_OF_RESOURCES
;
1087 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1090 // Deal with io aperture
1092 if ((Aperture
& 0x01) != 0) {
1093 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1094 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1098 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1102 Ptr
->SpecificFlag
= 1;
1103 Ptr
->AddrLen
= IoNode
->Length
;
1104 Ptr
->AddrRangeMax
= IoNode
->Alignment
;
1109 // Deal with mem32 aperture
1111 if ((Aperture
& 0x02) != 0) {
1112 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1113 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1117 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1121 Ptr
->SpecificFlag
= 0;
1125 Ptr
->AddrSpaceGranularity
= 32;
1126 Ptr
->AddrLen
= Mem32Node
->Length
;
1127 Ptr
->AddrRangeMax
= Mem32Node
->Alignment
;
1133 // Deal with Pmem32 aperture
1135 if ((Aperture
& 0x04) != 0) {
1136 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1137 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1141 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1145 Ptr
->SpecificFlag
= 0x6;
1149 Ptr
->AddrSpaceGranularity
= 32;
1150 Ptr
->AddrLen
= PMem32Node
->Length
;
1151 Ptr
->AddrRangeMax
= PMem32Node
->Alignment
;
1156 // Deal with mem64 aperture
1158 if ((Aperture
& 0x08) != 0) {
1159 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1160 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1164 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1168 Ptr
->SpecificFlag
= 0;
1172 Ptr
->AddrSpaceGranularity
= 64;
1173 Ptr
->AddrLen
= Mem64Node
->Length
;
1174 Ptr
->AddrRangeMax
= Mem64Node
->Alignment
;
1179 // Deal with Pmem64 aperture
1181 if ((Aperture
& 0x10) != 0) {
1182 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1183 Ptr
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1187 Ptr
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1191 Ptr
->SpecificFlag
= 0x06;
1195 Ptr
->AddrSpaceGranularity
= 64;
1196 Ptr
->AddrLen
= PMem64Node
->Length
;
1197 Ptr
->AddrRangeMax
= PMem64Node
->Alignment
;
1205 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Ptr
;
1207 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1208 PtrEnd
->Checksum
= 0;
1213 // If there is no resource request
1215 Configuration
= AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1216 if (Configuration
== NULL
) {
1217 return EFI_OUT_OF_RESOURCES
;
1220 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (Configuration
);
1221 Ptr
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1223 PtrEnd
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Ptr
+ 1);
1224 PtrEnd
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1225 PtrEnd
->Checksum
= 0;
1228 *Config
= Configuration
;
1234 Get resource base from an acpi configuration descriptor.
1236 @param Config An acpi configuration descriptor.
1237 @param IoBase Output of I/O resource base address.
1238 @param Mem32Base Output of 32-bit memory base address.
1239 @param PMem32Base Output of 32-bit prefetchable memory base address.
1240 @param Mem64Base Output of 64-bit memory base address.
1241 @param PMem64Base Output of 64-bit prefetchable memory base address.
1248 OUT UINT64
*Mem32Base
,
1249 OUT UINT64
*PMem32Base
,
1250 OUT UINT64
*Mem64Base
,
1251 OUT UINT64
*PMem64Base
1255 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1258 ASSERT (Config
!= NULL
);
1260 *IoBase
= 0xFFFFFFFFFFFFFFFFULL
;
1261 *Mem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1262 *PMem32Base
= 0xFFFFFFFFFFFFFFFFULL
;
1263 *Mem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1264 *PMem64Base
= 0xFFFFFFFFFFFFFFFFULL
;
1266 Temp
= (UINT8
*) Config
;
1268 while (*Temp
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1270 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Temp
;
1271 ResStatus
= Ptr
->AddrTranslationOffset
;
1273 if (ResStatus
== EFI_RESOURCE_SATISFIED
) {
1275 switch (Ptr
->ResType
) {
1278 // Memory type aperture
1283 // Check to see the granularity
1285 if (Ptr
->AddrSpaceGranularity
== 32) {
1286 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1287 *PMem32Base
= Ptr
->AddrRangeMin
;
1289 *Mem32Base
= Ptr
->AddrRangeMin
;
1293 if (Ptr
->AddrSpaceGranularity
== 64) {
1294 if ((Ptr
->SpecificFlag
& 0x06) != 0) {
1295 *PMem64Base
= Ptr
->AddrRangeMin
;
1297 *Mem64Base
= Ptr
->AddrRangeMin
;
1307 *IoBase
= Ptr
->AddrRangeMin
;
1321 Temp
+= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
);
1326 Enumerate pci bridge, allocate resource and determine attribute
1327 for devices on this bridge.
1329 @param BridgeDev Pointer to instance of bridge device.
1331 @retval EFI_SUCCESS Successfully enumerated PCI bridge.
1332 @retval other Failed to enumerate.
1336 PciBridgeEnumerator (
1337 IN PCI_IO_DEVICE
*BridgeDev
1341 UINT8 StartBusNumber
;
1342 EFI_PCI_IO_PROTOCOL
*PciIo
;
1347 PciIo
= &(BridgeDev
->PciIo
);
1348 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x19, 1, &StartBusNumber
);
1350 if (EFI_ERROR (Status
)) {
1354 Status
= PciAssignBusNumber (
1360 if (EFI_ERROR (Status
)) {
1364 Status
= PciPciDeviceInfoCollector (BridgeDev
, StartBusNumber
);
1366 if (EFI_ERROR (Status
)) {
1370 Status
= PciBridgeResourceAllocator (BridgeDev
);
1372 if (EFI_ERROR (Status
)) {
1376 Status
= DetermineDeviceAttribute (BridgeDev
);
1378 if (EFI_ERROR (Status
)) {
1387 Allocate all kinds of resource for PCI bridge.
1389 @param Bridge Pointer to bridge instance.
1391 @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
1392 @retval other Failed to allocate resource for bridge.
1396 PciBridgeResourceAllocator (
1397 IN PCI_IO_DEVICE
*Bridge
1400 PCI_RESOURCE_NODE
*IoBridge
;
1401 PCI_RESOURCE_NODE
*Mem32Bridge
;
1402 PCI_RESOURCE_NODE
*PMem32Bridge
;
1403 PCI_RESOURCE_NODE
*Mem64Bridge
;
1404 PCI_RESOURCE_NODE
*PMem64Bridge
;
1412 IoBridge
= CreateResourceNode (
1421 Mem32Bridge
= CreateResourceNode (
1430 PMem32Bridge
= CreateResourceNode (
1439 Mem64Bridge
= CreateResourceNode (
1448 PMem64Bridge
= CreateResourceNode (
1458 // Create resourcemap by going through all the devices subject to this root bridge
1469 Status
= GetResourceBaseFromBridge (
1478 if (EFI_ERROR (Status
)) {
1483 // Program IO resources
1491 // Program Mem32 resources
1499 // Program PMem32 resources
1507 // Program Mem64 resources
1515 // Program PMem64 resources
1522 DestroyResourceTree (IoBridge
);
1523 DestroyResourceTree (Mem32Bridge
);
1524 DestroyResourceTree (PMem32Bridge
);
1525 DestroyResourceTree (PMem64Bridge
);
1526 DestroyResourceTree (Mem64Bridge
);
1528 gBS
->FreePool (IoBridge
);
1529 gBS
->FreePool (Mem32Bridge
);
1530 gBS
->FreePool (PMem32Bridge
);
1531 gBS
->FreePool (PMem64Bridge
);
1532 gBS
->FreePool (Mem64Bridge
);
1538 Get resource base address for a pci bridge device.
1540 @param Bridge Given Pci driver instance.
1541 @param IoBase Output for base address of I/O type resource.
1542 @param Mem32Base Output for base address of 32-bit memory type resource.
1543 @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
1544 @param Mem64Base Output for base address of 64-bit memory type resource.
1545 @param PMem64Base Output for base address of 64-bit Pmemory type resource.
1547 @retval EFI_SUCCESS Successfully got resource base address.
1548 @retval EFI_OUT_OF_RESOURCES PCI bridge is not available.
1552 GetResourceBaseFromBridge (
1553 IN PCI_IO_DEVICE
*Bridge
,
1555 OUT UINT64
*Mem32Base
,
1556 OUT UINT64
*PMem32Base
,
1557 OUT UINT64
*Mem64Base
,
1558 OUT UINT64
*PMem64Base
1561 if (!Bridge
->Allocated
) {
1562 return EFI_OUT_OF_RESOURCES
;
1566 *Mem32Base
= gAllOne
;
1567 *PMem32Base
= gAllOne
;
1568 *Mem64Base
= gAllOne
;
1569 *PMem64Base
= gAllOne
;
1571 if (IS_PCI_BRIDGE (&Bridge
->Pci
)) {
1573 if (Bridge
->PciBar
[PPB_IO_RANGE
].Length
> 0) {
1574 *IoBase
= Bridge
->PciBar
[PPB_IO_RANGE
].BaseAddress
;
1577 if (Bridge
->PciBar
[PPB_MEM32_RANGE
].Length
> 0) {
1578 *Mem32Base
= Bridge
->PciBar
[PPB_MEM32_RANGE
].BaseAddress
;
1581 if (Bridge
->PciBar
[PPB_PMEM32_RANGE
].Length
> 0) {
1582 *PMem32Base
= Bridge
->PciBar
[PPB_PMEM32_RANGE
].BaseAddress
;
1585 if (Bridge
->PciBar
[PPB_PMEM64_RANGE
].Length
> 0) {
1586 *PMem64Base
= Bridge
->PciBar
[PPB_PMEM64_RANGE
].BaseAddress
;
1588 *PMem64Base
= gAllOne
;
1593 if (IS_CARDBUS_BRIDGE (&Bridge
->Pci
)) {
1594 if (Bridge
->PciBar
[P2C_IO_1
].Length
> 0) {
1595 *IoBase
= Bridge
->PciBar
[P2C_IO_1
].BaseAddress
;
1597 if (Bridge
->PciBar
[P2C_IO_2
].Length
> 0) {
1598 *IoBase
= Bridge
->PciBar
[P2C_IO_2
].BaseAddress
;
1602 if (Bridge
->PciBar
[P2C_MEM_1
].Length
> 0) {
1603 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypePMem32
) {
1604 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1607 if (Bridge
->PciBar
[P2C_MEM_1
].BarType
== PciBarTypeMem32
) {
1608 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_1
].BaseAddress
;
1612 if (Bridge
->PciBar
[P2C_MEM_2
].Length
> 0) {
1613 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypePMem32
) {
1614 *PMem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1617 if (Bridge
->PciBar
[P2C_MEM_2
].BarType
== PciBarTypeMem32
) {
1618 *Mem32Base
= Bridge
->PciBar
[P2C_MEM_2
].BaseAddress
;
1627 These are the notifications from the PCI bus driver that it is about to enter a certain
1628 phase of the PCI enumeration process.
1630 This member function can be used to notify the host bridge driver to perform specific actions,
1631 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1632 Eight notification points are defined at this time. See belows:
1633 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
1634 structures. The PCI enumerator should issue this notification
1635 before starting a fresh enumeration process. Enumeration cannot
1636 be restarted after sending any other notification such as
1637 EfiPciHostBridgeBeginBusAllocation.
1638 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
1639 required here. This notification can be used to perform any
1640 chipset-specific programming.
1641 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
1642 specific action is required here. This notification can be used to
1643 perform any chipset-specific programming.
1644 EfiPciHostBridgeBeginResourceAllocation
1645 The resource allocation phase is about to begin. No specific
1646 action is required here. This notification can be used to perform
1647 any chipset-specific programming.
1648 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
1649 root bridges. These resource settings are returned on the next call to
1650 GetProposedResources(). Before calling NotifyPhase() with a Phase of
1651 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
1652 for gathering I/O and memory requests for
1653 all the PCI root bridges and submitting these requests using
1654 SubmitResources(). This function pads the resource amount
1655 to suit the root bridge hardware, takes care of dependencies between
1656 the PCI root bridges, and calls the Global Coherency Domain (GCD)
1657 with the allocation request. In the case of padding, the allocated range
1658 could be bigger than what was requested.
1659 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
1660 resources (proposed resources) for all the PCI root bridges. After the
1661 hardware is programmed, reassigning resources will not be supported.
1662 The bus settings are not affected.
1663 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
1664 root bridges and resets the I/O and memory apertures to their initial
1665 state. The bus settings are not affected. If the request to allocate
1666 resources fails, the PCI enumerator can use this notification to
1667 deallocate previous resources, adjust the requests, and retry
1669 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
1670 required here. This notification can be used to perform any chipsetspecific
1673 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1674 @param[in] Phase The phase during enumeration
1676 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
1677 is valid for a Phase of EfiPciHostBridgeAllocateResources if
1678 SubmitResources() has not been called for one or more
1679 PCI root bridges before this call
1680 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
1681 for a Phase of EfiPciHostBridgeSetResources.
1682 @retval EFI_INVALID_PARAMETER Invalid phase parameter
1683 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1684 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1685 previously submitted resource requests cannot be fulfilled or
1686 were only partially fulfilled.
1687 @retval EFI_SUCCESS The notification was accepted without any errors.
1692 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
,
1693 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1696 EFI_HANDLE HostBridgeHandle
;
1697 EFI_HANDLE RootBridgeHandle
;
1698 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1701 HostBridgeHandle
= NULL
;
1702 RootBridgeHandle
= NULL
;
1703 if (gPciPlatformProtocol
!= NULL
) {
1705 // Get Host Bridge Handle.
1707 PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
);
1710 // Get the rootbridge Io protocol to find the host bridge handle
1712 Status
= gBS
->HandleProtocol (
1714 &gEfiPciRootBridgeIoProtocolGuid
,
1715 (VOID
**) &PciRootBridgeIo
1718 if (EFI_ERROR (Status
)) {
1719 return EFI_NOT_FOUND
;
1722 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
1725 // Call PlatformPci::PlatformNotify() if the protocol is present.
1727 gPciPlatformProtocol
->PlatformNotify (
1728 gPciPlatformProtocol
,
1735 Status
= PciResAlloc
->NotifyPhase (
1740 if (gPciPlatformProtocol
!= NULL
) {
1742 // Call PlatformPci::PlatformNotify() if the protocol is present.
1744 gPciPlatformProtocol
->PlatformNotify (
1745 gPciPlatformProtocol
,
1757 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1758 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1759 PCI controllers before enumeration.
1761 This function is called during the PCI enumeration process. No specific action is expected from this
1762 member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1765 @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1766 @param Bus The bus number of the pci device.
1767 @param Device The device number of the pci device.
1768 @param Func The function number of the pci device.
1769 @param Phase The phase of the PCI device enumeration.
1771 @retval EFI_SUCCESS The requested parameters were returned.
1772 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
1773 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
1774 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1775 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
1776 not enumerate this device, including its child devices if it is a PCI-to-PCI
1781 PreprocessController (
1782 IN PCI_IO_DEVICE
*Bridge
,
1786 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1789 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress
;
1790 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
;
1791 EFI_HANDLE RootBridgeHandle
;
1792 EFI_HANDLE HostBridgeHandle
;
1796 // Get the host bridge handle
1798 HostBridgeHandle
= Bridge
->PciRootBridgeIo
->ParentHandle
;
1801 // Get the pci host bridge resource allocation protocol
1803 Status
= gBS
->OpenProtocol (
1805 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
1806 (VOID
**) &PciResAlloc
,
1809 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1812 if (EFI_ERROR (Status
)) {
1813 return EFI_UNSUPPORTED
;
1817 // Get Root Brige Handle
1819 while (Bridge
->Parent
!= NULL
) {
1820 Bridge
= Bridge
->Parent
;
1823 RootBridgeHandle
= Bridge
->Handle
;
1825 RootBridgePciAddress
.Register
= 0;
1826 RootBridgePciAddress
.Function
= Func
;
1827 RootBridgePciAddress
.Device
= Device
;
1828 RootBridgePciAddress
.Bus
= Bus
;
1829 RootBridgePciAddress
.ExtendedRegister
= 0;
1831 if (gPciPlatformProtocol
!= NULL
) {
1833 // Call PlatformPci::PrepController() if the protocol is present.
1835 gPciPlatformProtocol
->PlatformPrepController (
1836 gPciPlatformProtocol
,
1839 RootBridgePciAddress
,
1845 Status
= PciResAlloc
->PreprocessController (
1848 RootBridgePciAddress
,
1852 if (gPciPlatformProtocol
!= NULL
) {
1854 // Call PlatformPci::PrepController() if the protocol is present.
1856 gPciPlatformProtocol
->PlatformPrepController (
1857 gPciPlatformProtocol
,
1860 RootBridgePciAddress
,
1870 This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
1871 happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
1873 @param This A pointer to the hot plug request protocol.
1874 @param Operation The operation the PCI bus driver is requested to make.
1875 @param Controller The handle of the hot-plug controller.
1876 @param RemainingDevicePath The remaining device path for the PCI-like hot-plug device.
1877 @param NumberOfChildren The number of child handles.
1878 For a add operation, it is an output parameter.
1879 For a remove operation, it?¡¥s an input parameter.
1880 @param ChildHandleBuffer The buffer which contains the child handles.
1882 @retval EFI_INVALID_PARAMETER Operation is not a legal value.
1883 Controller is NULL or not a valid handle.
1884 NumberOfChildren is NULL.
1885 ChildHandleBuffer is NULL while Operation is add.
1886 @retval EFI_OUT_OF_RESOURCES There are no enough resources to start the devices.
1887 @retval EFI_NOT_FOUND Can not find bridge according to controller handle.
1888 @retval EFI_SUCCESS The handles for the specified device have been created or destroyed
1889 as requested, and for an add operation, the new handles are
1890 returned in ChildHandleBuffer.
1894 PciHotPlugRequestNotify (
1895 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL
* This
,
1896 IN EFI_PCI_HOTPLUG_OPERATION Operation
,
1897 IN EFI_HANDLE Controller
,
1898 IN EFI_DEVICE_PATH_PROTOCOL
* RemainingDevicePath OPTIONAL
,
1899 IN OUT UINT8
*NumberOfChildren
,
1900 IN OUT EFI_HANDLE
* ChildHandleBuffer
1903 PCI_IO_DEVICE
*Bridge
;
1904 PCI_IO_DEVICE
*Temp
;
1905 EFI_PCI_IO_PROTOCOL
*PciIo
;
1907 EFI_HANDLE RootBridgeHandle
;
1910 Status
= gBS
->OpenProtocol (
1912 &gEfiPciIoProtocolGuid
,
1914 gPciBusDriverBinding
.DriverBindingHandle
,
1916 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1919 if (EFI_ERROR (Status
)) {
1920 return EFI_NOT_FOUND
;
1923 Bridge
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
1926 // Get root bridge handle
1929 while (Temp
->Parent
!= NULL
) {
1930 Temp
= Temp
->Parent
;
1933 RootBridgeHandle
= Temp
->Handle
;
1935 if (Operation
== EfiPciHotPlugRequestAdd
) {
1937 if (NumberOfChildren
!= NULL
) {
1938 *NumberOfChildren
= 0;
1941 if (IsListEmpty (&Bridge
->ChildList
)) {
1943 Status
= PciBridgeEnumerator (Bridge
);
1945 if (EFI_ERROR (Status
)) {
1950 Status
= StartPciDevicesOnBridge (
1953 RemainingDevicePath
,
1961 if (Operation
== EfiPciHotplugRequestRemove
) {
1963 if (*NumberOfChildren
== 0) {
1965 // Remove all devices on the bridge
1967 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Bridge
);
1972 for (Index
= 0; Index
< *NumberOfChildren
; Index
++) {
1974 // De register all the pci device
1976 Status
= DeRegisterPciDevice (RootBridgeHandle
, ChildHandleBuffer
[Index
]);
1978 if (EFI_ERROR (Status
)) {
1993 Search hostbridge according to given handle
1995 @param RootBridgeHandle Host bridge handle.
1997 @retval TRUE Found host bridge handle.
1998 @retval FALSE Not found hot bridge handle.
2002 SearchHostBridgeHandle (
2003 IN EFI_HANDLE RootBridgeHandle
2006 EFI_HANDLE HostBridgeHandle
;
2007 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2012 // Get the rootbridge Io protocol to find the host bridge handle
2014 Status
= gBS
->OpenProtocol (
2016 &gEfiPciRootBridgeIoProtocolGuid
,
2017 (VOID
**) &PciRootBridgeIo
,
2018 gPciBusDriverBinding
.DriverBindingHandle
,
2020 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2023 if (EFI_ERROR (Status
)) {
2027 HostBridgeHandle
= PciRootBridgeIo
->ParentHandle
;
2028 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2029 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2038 Add host bridge handle to global variable for enumerating.
2040 @param HostBridgeHandle Host bridge handle.
2042 @retval EFI_SUCCESS Successfully added host bridge.
2043 @retval EFI_ABORTED Host bridge is NULL, or given host bridge
2044 has been in host bridge list.
2048 AddHostBridgeEnumerator (
2049 IN EFI_HANDLE HostBridgeHandle
2054 if (HostBridgeHandle
== NULL
) {
2058 for (Index
= 0; Index
< gPciHostBridgeNumber
; Index
++) {
2059 if (HostBridgeHandle
== gPciHostBrigeHandles
[Index
]) {
2064 if (Index
< PCI_MAX_HOST_BRIDGE_NUM
) {
2065 gPciHostBrigeHandles
[Index
] = HostBridgeHandle
;
2066 gPciHostBridgeNumber
++;