3 Copyright (c) 2006, 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.
18 PCI Bus Driver Lib file
19 It abstracts some functions that can be different
20 between light PCI bus driver and full PCI bus driver
28 EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest
= {
29 PciHotPlugRequestNotify
34 InstallHotPlugRequestProtocol (
42 Status - A pointer to the status.
53 *Status
= gBS
->InstallProtocolInterface (
55 &gEfiPciHotPlugRequestProtocolGuid
,
62 InstallPciHotplugGuid (
63 IN PCI_IO_DEVICE
*PciIoDevice
71 PciIoDevice - A pointer to the PCI_IO_DEVICE.
81 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Parent
->Pci
)) {
83 Status
= gBS
->InstallProtocolInterface (
85 &gEfiPciHotplugDeviceGuid
,
93 UninstallPciHotplugGuid (
94 IN PCI_IO_DEVICE
*PciIoDevice
102 PciIoDevice - A pointer to the PCI_IO_DEVICE.
112 Status
= gBS
->OpenProtocol (
114 &gEfiPciHotplugDeviceGuid
,
118 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
121 if (Status
== EFI_SUCCESS
) {
123 // This may triger CardBus driver to stop for
124 // Pccard devices opened the GUID via BY_DRIVER
126 Status
= gBS
->UninstallProtocolInterface (
128 &gEfiPciHotplugDeviceGuid
,
136 IN PCI_IO_DEVICE
*PciIoDevice
145 PciIoDevice - A pointer to the PCI_IO_DEVICE.
156 // Read PciBar information from the bar register
158 if (!gFullEnumeration
) {
161 PciIoDevice
->PciIo
.Pci
.Read (
162 &(PciIoDevice
->PciIo
),
169 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
170 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
171 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
174 PciIoDevice
->PciIo
.Pci
.Read (
175 &(PciIoDevice
->PciIo
),
181 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
182 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
183 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
186 PciIoDevice
->PciIo
.Pci
.Read (
187 &(PciIoDevice
->PciIo
),
193 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
194 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
195 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
198 PciIoDevice
->PciIo
.Pci
.Read (
199 &(PciIoDevice
->PciIo
),
205 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
206 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
207 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
211 if (gPciHotPlugInit
!= NULL
) {
212 GetResourcePaddingForHpb (PciIoDevice
);
217 RemoveRejectedPciDevices (
218 EFI_HANDLE RootBridgeHandle
,
219 IN PCI_IO_DEVICE
*Bridge
228 RootBridgeHandle - An efi handle.
229 Bridge - An pointer to the PCI_IO_DEVICE.
236 // TODO: EFI_SUCCESS - add return value to function comment
239 LIST_ENTRY
*CurrentLink
;
240 LIST_ENTRY
*LastLink
;
242 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
244 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
246 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
248 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
250 // Remove rejected devices recusively
252 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
255 // Skip rejection for all PPBs, while detect rejection for others
257 if (IsPciDeviceRejected (Temp
)) {
260 // For P2C, remove all devices on it
263 if (!IsListEmpty (&Temp
->ChildList
)) {
264 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
268 // Finally remove itself
271 LastLink
= CurrentLink
->BackLink
;
272 RemoveEntryList (CurrentLink
);
273 FreePciDevice (Temp
);
275 CurrentLink
= LastLink
;
279 CurrentLink
= CurrentLink
->ForwardLink
;
286 PciHostBridgeResourceAllocator (
287 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
293 Host brige resource allocator.
297 PciResAlloc - A pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
304 // TODO: EFI_NOT_FOUND - add return value to function comment
305 // TODO: EFI_NOT_FOUND - add return value to function comment
306 // TODO: EFI_NOT_FOUND - add return value to function comment
307 // TODO: EFI_SUCCESS - add return value to function comment
309 PCI_IO_DEVICE
*RootBridgeDev
;
310 EFI_HANDLE RootBridgeHandle
;
319 UINT64 Mem32ResStatus
;
320 UINT64 PMem32ResStatus
;
321 UINT64 Mem64ResStatus
;
322 UINT64 PMem64ResStatus
;
323 UINT64 MaxOptionRomSize
;
324 PCI_RESOURCE_NODE
*IoBridge
;
325 PCI_RESOURCE_NODE
*Mem32Bridge
;
326 PCI_RESOURCE_NODE
*PMem32Bridge
;
327 PCI_RESOURCE_NODE
*Mem64Bridge
;
328 PCI_RESOURCE_NODE
*PMem64Bridge
;
329 PCI_RESOURCE_NODE IoPool
;
330 PCI_RESOURCE_NODE Mem32Pool
;
331 PCI_RESOURCE_NODE PMem32Pool
;
332 PCI_RESOURCE_NODE Mem64Pool
;
333 PCI_RESOURCE_NODE PMem64Pool
;
335 REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA HandleExtendedData
;
336 REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData
;
344 // It will try several times if the resource allocation fails
349 // Initialize resource pool
351 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
352 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
353 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
354 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
355 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
357 RootBridgeDev
= NULL
;
358 RootBridgeHandle
= 0;
360 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
363 // Get RootBridg Device by handle
365 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
367 if (RootBridgeDev
== NULL
) {
368 return EFI_NOT_FOUND
;
372 // Create the entire system resource map from the information collected by
373 // enumerator. Several resource tree was created
376 IoBridge
= CreateResourceNode (
385 Mem32Bridge
= CreateResourceNode (
394 PMem32Bridge
= CreateResourceNode (
403 Mem64Bridge
= CreateResourceNode (
412 PMem64Bridge
= CreateResourceNode (
422 // Create resourcemap by going through all the devices subject to this root bridge
424 Status
= CreateResourceMap (
434 // Get the max ROM size that the root bridge can process
436 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
439 // Skip to enlarge the resource request during realloction
443 // Get Max Option Rom size for current root bridge
445 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
448 // Enlarger the mem32 resource to accomdate the option rom
449 // if the mem32 resource is not enough to hold the rom
451 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
453 Mem32Bridge
->Length
= MaxOptionRomSize
;
454 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
457 // Alignment should be adjusted as well
459 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
460 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
466 // Based on the all the resource tree, contruct ACPI resource node to
467 // submit the resource aperture to pci host bridge protocol
469 Status
= ConstructAcpiResourceRequestor (
480 // Insert these resource nodes into the database
482 InsertResourceNode (&IoPool
, IoBridge
);
483 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
484 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
485 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
486 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
488 if (Status
== EFI_SUCCESS
) {
490 // Submit the resource requirement
492 Status
= PciResAlloc
->SubmitResources (
494 RootBridgeDev
->Handle
,
500 // Free acpi resource node
502 if (AcpiConfig
!= NULL
) {
503 gBS
->FreePool (AcpiConfig
);
506 if (EFI_ERROR (Status
)) {
508 // Destroy all the resource tree
510 DestroyResourceTree (&IoPool
);
511 DestroyResourceTree (&Mem32Pool
);
512 DestroyResourceTree (&PMem32Pool
);
513 DestroyResourceTree (&Mem64Pool
);
514 DestroyResourceTree (&PMem64Pool
);
520 // Notify pci bus driver starts to program the resource
523 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
525 if (!EFI_ERROR (Status
)) {
527 // Allocation succeed, then continue the following
533 // If the resource allocation is unsuccessful, free resources on bridge
536 RootBridgeDev
= NULL
;
537 RootBridgeHandle
= 0;
539 IoResStatus
= EFI_RESOURCE_SATISFIED
;
540 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
541 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
542 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
543 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
545 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
547 // Get RootBridg Device by handle
549 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
550 if (RootBridgeDev
== NULL
) {
551 return EFI_NOT_FOUND
;
555 // Get host bridge handle for status report
557 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
560 // Get acpi resource node for all the resource types
564 Status
= PciResAlloc
->GetProposedResources (
566 RootBridgeDev
->Handle
,
570 if (EFI_ERROR (Status
)) {
574 if (AcpiConfig
!= NULL
) {
576 // Adjust resource allocation policy for each RB
578 GetResourceAllocationStatus (
586 gBS
->FreePool (AcpiConfig
);
594 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
597 // It is very difficult to follow the spec here
598 // Device path , Bar index can not be get here
600 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
602 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
604 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
605 (VOID
*) &AllocFailExtendedData
,
606 sizeof (AllocFailExtendedData
)
609 Status
= PciHostBridgeAdjustAllocation (
623 // Destroy all the resource tree
625 DestroyResourceTree (&IoPool
);
626 DestroyResourceTree (&Mem32Pool
);
627 DestroyResourceTree (&PMem32Pool
);
628 DestroyResourceTree (&Mem64Pool
);
629 DestroyResourceTree (&PMem64Pool
);
631 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
633 if (EFI_ERROR (Status
)) {
645 // Raise the EFI_IOB_PCI_RES_ALLOC status code
647 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
649 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
650 (VOID
*) &HandleExtendedData
,
651 sizeof (HandleExtendedData
)
655 // Notify pci bus driver starts to program the resource
657 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
659 RootBridgeDev
= NULL
;
661 RootBridgeHandle
= 0;
663 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
666 // Get RootBridg Device by handle
668 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
670 if (RootBridgeDev
== NULL
) {
671 return EFI_NOT_FOUND
;
675 // Get acpi resource node for all the resource types
678 Status
= PciResAlloc
->GetProposedResources (
680 RootBridgeDev
->Handle
,
684 if (EFI_ERROR (Status
)) {
689 // Get the resource base by interpreting acpi resource node
702 // Process option rom for this root bridge
704 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
707 // Create the entire system resource map from the information collected by
708 // enumerator. Several resource tree was created
710 Status
= GetResourceMap (
724 if (EFI_ERROR (Status
)) {
729 // Program IO resources
737 // Program Mem32 resources
745 // Program PMem32 resources
753 // Program Mem64 resources
761 // Program PMem64 resources
768 if (AcpiConfig
!= NULL
) {
769 gBS
->FreePool (AcpiConfig
);
774 // Destroy all the resource tree
776 DestroyResourceTree (&IoPool
);
777 DestroyResourceTree (&Mem32Pool
);
778 DestroyResourceTree (&PMem32Pool
);
779 DestroyResourceTree (&Mem64Pool
);
780 DestroyResourceTree (&PMem64Pool
);
783 // Notify the resource allocation phase is to end
785 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
792 IN PCI_IO_DEVICE
*Bridge
,
793 IN UINT8 StartBusNumber
,
794 OUT UINT8
*SubBusNumber
,
795 OUT UINT8
*PaddedBusRange
801 This routine is used to assign bus number to the given PCI bus system
805 Bridge - A pointer to the PCI_IO_DEVICE structure.
806 StartBusNumber - The start bus number.
807 SubBusNumber - A pointer to the sub bus number.
808 PaddedBusRange - A pointer to the padded bus range.
815 // TODO: EFI_DEVICE_ERROR - add return value to function comment
816 // TODO: EFI_SUCCESS - add return value to function comment
826 PCI_IO_DEVICE
*PciDevice
;
830 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
831 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
833 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
836 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
843 ResetAllPpbBusReg (Bridge
, StartBusNumber
);
845 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
846 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
849 // Check to see whether a pci device is present
851 Status
= PciDevicePresent (
859 if (EFI_ERROR (Status
)) {
862 // Skip sub functions, this is not a multi function device
871 // Get the PCI device information
873 Status
= PciSearchDevice (
882 ASSERT (!EFI_ERROR (Status
));
884 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
886 if (!IS_PCI_BRIDGE (&Pci
)) {
888 // PCI bridges will be called later
889 // Here just need for PCI device or PCI to cardbus controller
890 // EfiPciBeforeChildBusEnumeration for PCI Device Node
892 PreprocessController (
894 PciDevice
->BusNumber
,
895 PciDevice
->DeviceNumber
,
896 PciDevice
->FunctionNumber
,
897 EfiPciBeforeChildBusEnumeration
902 // For Pci Hotplug controller devcie only
904 if (gPciHotPlugInit
!= NULL
) {
906 // Check if it is a Hotplug PCI controller
908 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
910 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
912 Status
= CreateEventForHpc (HpIndex
, &Event
);
914 ASSERT (!EFI_ERROR (Status
));
916 Status
= gPciHotPlugInit
->InitializeRootHpc (
918 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
924 PreprocessController (
926 PciDevice
->BusNumber
,
927 PciDevice
->DeviceNumber
,
928 PciDevice
->FunctionNumber
,
929 EfiPciBeforeChildBusEnumeration
936 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
939 // Get the bridge information
942 if (gPciHotPlugInit
!= NULL
) {
944 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
947 // If it is initialized, get the padded bus range
949 Status
= gPciHotPlugInit
->GetResourcePadding (
951 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
954 (VOID
**) &Descriptors
,
958 if (EFI_ERROR (Status
)) {
963 Status
= PciGetBusRange (
970 gBS
->FreePool (Descriptors
);
972 if (EFI_ERROR (Status
)) {
981 SecondBus
= *SubBusNumber
;
983 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
984 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
986 Status
= PciRootBridgeIo
->Pci
.Write (
996 // If it is PPB, resursively search down this bridge
998 if (IS_PCI_BRIDGE (&Pci
)) {
1001 // Initialize SubBusNumber to Maximum bus number
1004 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1005 Status
= PciRootBridgeIo
->Pci
.Write (
1014 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1016 PreprocessController (
1018 PciDevice
->BusNumber
,
1019 PciDevice
->DeviceNumber
,
1020 PciDevice
->FunctionNumber
,
1021 EfiPciBeforeChildBusEnumeration
1024 Status
= PciScanBus (
1026 (UINT8
) (SecondBus
),
1031 if (EFI_ERROR (Status
)) {
1032 return EFI_DEVICE_ERROR
;
1038 // Ensure the device is enabled and initialized
1040 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1041 (State
& EFI_HPC_STATE_ENABLED
) &&
1042 (State
& EFI_HPC_STATE_INITIALIZED
) ) {
1043 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
1045 *SubBusNumber
= (UINT8
) ((UINT8
) (BusRange
) +*SubBusNumber
);
1050 // Set the current maximum bus number under the PPB
1052 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1054 Status
= PciRootBridgeIo
->Pci
.Write (
1063 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1066 // Skip sub functions, this is not a multi function device
1068 Func
= PCI_MAX_FUNC
;
1078 PciRootBridgeP2CProcess (
1079 IN PCI_IO_DEVICE
*Bridge
1083 Routine Description:
1085 Process Option Rom on this host bridge
1094 // TODO: Bridge - add argument and description to function comment
1095 // TODO: EFI_SUCCESS - add return value to function comment
1097 LIST_ENTRY
*CurrentLink
;
1098 PCI_IO_DEVICE
*Temp
;
1099 EFI_HPC_STATE State
;
1103 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1105 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
1107 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1109 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1111 if (gPciHotPlugInit
&& Temp
->Allocated
) {
1114 // Raise the EFI_IOB_PCI_HPC_INIT status code
1116 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1118 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_HPC_INIT
,
1122 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1123 Status
= gPciHotPlugInit
->InitializeRootHpc (
1131 if (!EFI_ERROR (Status
)) {
1132 Status
= PciBridgeEnumerator (Temp
);
1134 if (EFI_ERROR (Status
)) {
1139 CurrentLink
= CurrentLink
->ForwardLink
;
1145 if (!IsListEmpty (&Temp
->ChildList
)) {
1146 Status
= PciRootBridgeP2CProcess (Temp
);
1149 CurrentLink
= CurrentLink
->ForwardLink
;
1156 PciHostBridgeP2CProcess (
1157 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1161 Routine Description:
1170 // TODO: PciResAlloc - add argument and description to function comment
1171 // TODO: EFI_NOT_FOUND - add return value to function comment
1172 // TODO: EFI_SUCCESS - add return value to function comment
1174 EFI_HANDLE RootBridgeHandle
;
1175 PCI_IO_DEVICE
*RootBridgeDev
;
1178 RootBridgeHandle
= NULL
;
1180 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1183 // Get RootBridg Device by handle
1185 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1187 if (RootBridgeDev
== NULL
) {
1188 return EFI_NOT_FOUND
;
1191 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1193 if (EFI_ERROR (Status
)) {
1203 PciHostBridgeEnumerator (
1204 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1208 Routine Description:
1210 This function is used to enumerate the entire host bridge
1215 PciResAlloc - A pointer to the resource allocate protocol.
1222 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1223 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1224 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1225 // TODO: EFI_SUCCESS - add return value to function comment
1227 EFI_HANDLE RootBridgeHandle
;
1228 PCI_IO_DEVICE
*RootBridgeDev
;
1230 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1232 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1234 InitializeHotPlugSupport ();
1237 // Notify the bus allocation phase is about to start
1239 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1241 RootBridgeHandle
= NULL
;
1242 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1245 // if a root bridge instance is found, create root bridge device for it
1248 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1250 if (RootBridgeDev
== NULL
) {
1251 return EFI_OUT_OF_RESOURCES
;
1255 // Enumerate all the buses under this root bridge
1258 Status
= PciRootBridgeEnumerator (
1263 if (EFI_ERROR (Status
)) {
1267 DestroyRootBridge (RootBridgeDev
);
1270 // Error proccess here
1275 // Notify the bus allocation phase is finished for the first time
1277 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1280 if (gPciHotPlugInit
!= NULL
) {
1282 // Wait for all HPC initialized
1284 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1286 if (EFI_ERROR (Status
)) {
1291 // Notify the bus allocation phase is about to start for the 2nd time
1293 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1295 RootBridgeHandle
= NULL
;
1296 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1299 // if a root bridge instance is found, create root bridge device for it
1302 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1304 if (RootBridgeDev
== NULL
) {
1305 return EFI_OUT_OF_RESOURCES
;
1309 // Enumerate all the buses under this root bridge
1312 Status
= PciRootBridgeEnumerator (
1317 DestroyRootBridge (RootBridgeDev
);
1318 if (EFI_ERROR (Status
)) {
1324 // Notify the bus allocation phase is to end
1326 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1330 // Notify the resource allocation phase is to start
1332 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1334 RootBridgeHandle
= NULL
;
1335 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1338 // if a root bridge instance is found, create root bridge device for it
1341 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1343 if (RootBridgeDev
== NULL
) {
1344 return EFI_OUT_OF_RESOURCES
;
1347 Status
= StartManagingRootBridge (RootBridgeDev
);
1349 if (EFI_ERROR (Status
)) {
1353 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1354 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1356 if (EFI_ERROR (Status
)) {
1360 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1362 if (EFI_ERROR (Status
)) {
1367 // Determine root bridge attribute by calling interface of Pcihostbridge
1370 DetermineRootBridgeAttributes (
1376 // Collect all the resource information under this root bridge
1377 // A database that records all the information about pci device subject to this
1378 // root bridge will then be created
1380 Status
= PciPciDeviceInfoCollector (
1385 if (EFI_ERROR (Status
)) {
1389 InsertRootBridge (RootBridgeDev
);
1392 // Record the hostbridge handle
1394 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);