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 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest
= {
29 PciHotPlugRequestNotify
34 InstallHotPlugRequestProtocol (
42 Status - A pointer to the status.
52 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
57 *Status
= gBS
->InstallProtocolInterface (
59 &gEfiPciHotPlugRequestProtocolGuid
,
66 InstallPciHotplugGuid (
67 IN PCI_IO_DEVICE
*PciIoDevice
75 PciIoDevice - A pointer to the PCI_IO_DEVICE.
85 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
89 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Parent
->Pci
)) {
91 Status
= gBS
->InstallProtocolInterface (
93 &gEfiPciHotplugDeviceGuid
,
101 UninstallPciHotplugGuid (
102 IN PCI_IO_DEVICE
*PciIoDevice
110 PciIoDevice - A pointer to the PCI_IO_DEVICE.
120 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
124 Status
= gBS
->OpenProtocol (
126 &gEfiPciHotplugDeviceGuid
,
130 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
133 if (Status
== EFI_SUCCESS
) {
135 // This may triger CardBus driver to stop for
136 // Pccard devices opened the GUID via BY_DRIVER
138 Status
= gBS
->UninstallProtocolInterface (
140 &gEfiPciHotplugDeviceGuid
,
148 IN PCI_IO_DEVICE
*PciIoDevice
157 PciIoDevice - A pointer to the PCI_IO_DEVICE.
167 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
172 // Read PciBar information from the bar register
174 if (!gFullEnumeration
) {
177 PciIoDevice
->PciIo
.Pci
.Read (
178 &(PciIoDevice
->PciIo
),
185 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
186 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
187 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
190 PciIoDevice
->PciIo
.Pci
.Read (
191 &(PciIoDevice
->PciIo
),
197 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
198 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
199 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
202 PciIoDevice
->PciIo
.Pci
.Read (
203 &(PciIoDevice
->PciIo
),
209 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
210 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
211 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
214 PciIoDevice
->PciIo
.Pci
.Read (
215 &(PciIoDevice
->PciIo
),
221 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
222 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
223 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
227 if (gPciHotPlugInit
!= NULL
) {
228 GetResourcePaddingForHpb (PciIoDevice
);
233 RemoveRejectedPciDevices (
234 EFI_HANDLE RootBridgeHandle
,
235 IN PCI_IO_DEVICE
*Bridge
244 RootBridgeHandle - An efi handle.
245 Bridge - An pointer to the PCI_IO_DEVICE.
252 // TODO: EFI_SUCCESS - add return value to function comment
255 LIST_ENTRY
*CurrentLink
;
256 LIST_ENTRY
*LastLink
;
258 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
262 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
264 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
266 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
268 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
270 // Remove rejected devices recusively
272 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
275 // Skip rejection for all PPBs, while detect rejection for others
277 if (IsPciDeviceRejected (Temp
)) {
280 // For P2C, remove all devices on it
283 if (!IsListEmpty (&Temp
->ChildList
)) {
284 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
288 // Finally remove itself
291 LastLink
= CurrentLink
->BackLink
;
292 RemoveEntryList (CurrentLink
);
293 FreePciDevice (Temp
);
295 CurrentLink
= LastLink
;
299 CurrentLink
= CurrentLink
->ForwardLink
;
306 PciHostBridgeResourceAllocator (
307 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
310 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
311 return PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
315 return PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
323 PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
324 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
337 // TODO: PciResAlloc - add argument and description to function comment
338 // TODO: EFI_NOT_FOUND - add return value to function comment
339 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
340 // TODO: EFI_NOT_FOUND - add return value to function comment
341 // TODO: EFI_SUCCESS - add return value to function comment
343 PCI_IO_DEVICE
*RootBridgeDev
;
344 EFI_HANDLE RootBridgeHandle
;
352 UINT64 MaxOptionRomSize
;
353 PCI_RESOURCE_NODE
*IoBridge
;
354 PCI_RESOURCE_NODE
*Mem32Bridge
;
355 PCI_RESOURCE_NODE
*PMem32Bridge
;
356 PCI_RESOURCE_NODE
*Mem64Bridge
;
357 PCI_RESOURCE_NODE
*PMem64Bridge
;
358 PCI_RESOURCE_NODE IoPool
;
359 PCI_RESOURCE_NODE Mem32Pool
;
360 PCI_RESOURCE_NODE PMem32Pool
;
361 PCI_RESOURCE_NODE Mem64Pool
;
362 PCI_RESOURCE_NODE PMem64Pool
;
363 REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA ExtendedData
;
366 // Initialize resource pool
369 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
370 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
371 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
372 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
373 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
375 RootBridgeDev
= NULL
;
376 RootBridgeHandle
= 0;
378 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
380 // Get RootBridg Device by handle
382 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
384 if (RootBridgeDev
== NULL
) {
385 return EFI_NOT_FOUND
;
389 // Get host bridge handle for status report
391 ExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
394 // Create the entire system resource map from the information collected by
395 // enumerator. Several resource tree was created
398 IoBridge
= CreateResourceNode (
407 Mem32Bridge
= CreateResourceNode (
416 PMem32Bridge
= CreateResourceNode (
425 Mem64Bridge
= CreateResourceNode (
434 PMem64Bridge
= CreateResourceNode (
444 // Create resourcemap by going through all the devices subject to this root bridge
446 Status
= CreateResourceMap (
456 // Get the max ROM size that the root bridge can process
458 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
461 // Get Max Option Rom size for current root bridge
463 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
466 // Enlarger the mem32 resource to accomdate the option rom
467 // if the mem32 resource is not enough to hold the rom
469 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
471 Mem32Bridge
->Length
= MaxOptionRomSize
;
472 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
475 // Alignment should be adjusted as well
477 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
478 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
483 // Based on the all the resource tree, contruct ACPI resource node to
484 // submit the resource aperture to pci host bridge protocol
486 Status
= ConstructAcpiResourceRequestor (
497 // Insert these resource nodes into the database
499 InsertResourceNode (&IoPool
, IoBridge
);
500 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
501 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
502 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
503 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
505 if (Status
== EFI_SUCCESS
) {
507 // Submit the resource requirement
509 Status
= PciResAlloc
->SubmitResources (
511 RootBridgeDev
->Handle
,
516 // Free acpi resource node
519 gBS
->FreePool (AcpiConfig
);
522 if (EFI_ERROR (Status
)) {
524 // Destroy all the resource tree
526 DestroyResourceTree (&IoPool
);
527 DestroyResourceTree (&Mem32Pool
);
528 DestroyResourceTree (&PMem32Pool
);
529 DestroyResourceTree (&Mem64Pool
);
530 DestroyResourceTree (&PMem64Pool
);
539 // Notify pci bus driver starts to program the resource
541 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
543 if (EFI_ERROR (Status
)) {
545 // Allocation failed, then return
547 return EFI_OUT_OF_RESOURCES
;
550 // Raise the EFI_IOB_PCI_RES_ALLOC status code
552 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
554 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
555 (VOID
*) &ExtendedData
,
556 sizeof (ExtendedData
)
560 // Notify pci bus driver starts to program the resource
562 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
564 RootBridgeDev
= NULL
;
566 RootBridgeHandle
= 0;
568 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
570 // Get RootBridg Device by handle
572 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
574 if (RootBridgeDev
== NULL
) {
575 return EFI_NOT_FOUND
;
579 // Get acpi resource node for all the resource types
582 Status
= PciResAlloc
->GetProposedResources (
584 RootBridgeDev
->Handle
,
588 if (EFI_ERROR (Status
)) {
593 // Get the resource base by interpreting acpi resource node
606 // Process option rom for this root bridge
608 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
611 // Create the entire system resource map from the information collected by
612 // enumerator. Several resource tree was created
614 Status
= GetResourceMap (
628 if (EFI_ERROR (Status
)) {
633 // Program IO resources
641 // Program Mem32 resources
649 // Program PMem32 resources
657 // Program Mem64 resources
665 // Program PMem64 resources
672 if (AcpiConfig
!= NULL
) {
673 gBS
->FreePool (AcpiConfig
);
678 // Destroy all the resource tree
680 DestroyResourceTree (&IoPool
);
681 DestroyResourceTree (&Mem32Pool
);
682 DestroyResourceTree (&PMem32Pool
);
683 DestroyResourceTree (&Mem64Pool
);
684 DestroyResourceTree (&PMem64Pool
);
687 // Notify the resource allocation phase is to end
689 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
696 PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
697 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
703 Host brige resource allocator.
707 PciResAlloc - A pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
714 // TODO: EFI_NOT_FOUND - add return value to function comment
715 // TODO: EFI_NOT_FOUND - add return value to function comment
716 // TODO: EFI_NOT_FOUND - add return value to function comment
717 // TODO: EFI_SUCCESS - add return value to function comment
719 PCI_IO_DEVICE
*RootBridgeDev
;
720 EFI_HANDLE RootBridgeHandle
;
729 UINT64 Mem32ResStatus
;
730 UINT64 PMem32ResStatus
;
731 UINT64 Mem64ResStatus
;
732 UINT64 PMem64ResStatus
;
733 UINT64 MaxOptionRomSize
;
734 PCI_RESOURCE_NODE
*IoBridge
;
735 PCI_RESOURCE_NODE
*Mem32Bridge
;
736 PCI_RESOURCE_NODE
*PMem32Bridge
;
737 PCI_RESOURCE_NODE
*Mem64Bridge
;
738 PCI_RESOURCE_NODE
*PMem64Bridge
;
739 PCI_RESOURCE_NODE IoPool
;
740 PCI_RESOURCE_NODE Mem32Pool
;
741 PCI_RESOURCE_NODE PMem32Pool
;
742 PCI_RESOURCE_NODE Mem64Pool
;
743 PCI_RESOURCE_NODE PMem64Pool
;
745 REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA HandleExtendedData
;
746 REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData
;
754 // It will try several times if the resource allocation fails
759 // Initialize resource pool
761 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
762 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
763 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
764 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
765 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
767 RootBridgeDev
= NULL
;
768 RootBridgeHandle
= 0;
770 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
773 // Get RootBridg Device by handle
775 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
777 if (RootBridgeDev
== NULL
) {
778 return EFI_NOT_FOUND
;
782 // Create the entire system resource map from the information collected by
783 // enumerator. Several resource tree was created
786 IoBridge
= CreateResourceNode (
795 Mem32Bridge
= CreateResourceNode (
804 PMem32Bridge
= CreateResourceNode (
813 Mem64Bridge
= CreateResourceNode (
822 PMem64Bridge
= CreateResourceNode (
832 // Create resourcemap by going through all the devices subject to this root bridge
834 Status
= CreateResourceMap (
844 // Get the max ROM size that the root bridge can process
846 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
849 // Skip to enlarge the resource request during realloction
853 // Get Max Option Rom size for current root bridge
855 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
858 // Enlarger the mem32 resource to accomdate the option rom
859 // if the mem32 resource is not enough to hold the rom
861 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
863 Mem32Bridge
->Length
= MaxOptionRomSize
;
864 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
867 // Alignment should be adjusted as well
869 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
870 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
876 // Based on the all the resource tree, contruct ACPI resource node to
877 // submit the resource aperture to pci host bridge protocol
879 Status
= ConstructAcpiResourceRequestor (
890 // Insert these resource nodes into the database
892 InsertResourceNode (&IoPool
, IoBridge
);
893 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
894 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
895 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
896 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
898 if (Status
== EFI_SUCCESS
) {
900 // Submit the resource requirement
902 Status
= PciResAlloc
->SubmitResources (
904 RootBridgeDev
->Handle
,
910 // Free acpi resource node
912 if (AcpiConfig
!= NULL
) {
913 gBS
->FreePool (AcpiConfig
);
916 if (EFI_ERROR (Status
)) {
918 // Destroy all the resource tree
920 DestroyResourceTree (&IoPool
);
921 DestroyResourceTree (&Mem32Pool
);
922 DestroyResourceTree (&PMem32Pool
);
923 DestroyResourceTree (&Mem64Pool
);
924 DestroyResourceTree (&PMem64Pool
);
930 // Notify pci bus driver starts to program the resource
933 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
935 if (!EFI_ERROR (Status
)) {
937 // Allocation succeed, then continue the following
943 // If the resource allocation is unsuccessful, free resources on bridge
946 RootBridgeDev
= NULL
;
947 RootBridgeHandle
= 0;
949 IoResStatus
= EFI_RESOURCE_SATISFIED
;
950 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
951 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
952 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
953 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
955 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
957 // Get RootBridg Device by handle
959 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
960 if (RootBridgeDev
== NULL
) {
961 return EFI_NOT_FOUND
;
965 // Get host bridge handle for status report
967 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
970 // Get acpi resource node for all the resource types
974 Status
= PciResAlloc
->GetProposedResources (
976 RootBridgeDev
->Handle
,
980 if (EFI_ERROR (Status
)) {
984 if (AcpiConfig
!= NULL
) {
986 // Adjust resource allocation policy for each RB
988 GetResourceAllocationStatus (
996 gBS
->FreePool (AcpiConfig
);
1004 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
1007 // It is very difficult to follow the spec here
1008 // Device path , Bar index can not be get here
1010 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
1012 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1014 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
1015 (VOID
*) &AllocFailExtendedData
,
1016 sizeof (AllocFailExtendedData
)
1019 Status
= PciHostBridgeAdjustAllocation (
1033 // Destroy all the resource tree
1035 DestroyResourceTree (&IoPool
);
1036 DestroyResourceTree (&Mem32Pool
);
1037 DestroyResourceTree (&PMem32Pool
);
1038 DestroyResourceTree (&Mem64Pool
);
1039 DestroyResourceTree (&PMem64Pool
);
1041 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
1043 if (EFI_ERROR (Status
)) {
1055 // Raise the EFI_IOB_PCI_RES_ALLOC status code
1057 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1059 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
1060 (VOID
*) &HandleExtendedData
,
1061 sizeof (HandleExtendedData
)
1065 // Notify pci bus driver starts to program the resource
1067 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
1069 RootBridgeDev
= NULL
;
1071 RootBridgeHandle
= 0;
1073 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1076 // Get RootBridg Device by handle
1078 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1080 if (RootBridgeDev
== NULL
) {
1081 return EFI_NOT_FOUND
;
1085 // Get acpi resource node for all the resource types
1088 Status
= PciResAlloc
->GetProposedResources (
1090 RootBridgeDev
->Handle
,
1094 if (EFI_ERROR (Status
)) {
1099 // Get the resource base by interpreting acpi resource node
1112 // Process option rom for this root bridge
1114 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
1117 // Create the entire system resource map from the information collected by
1118 // enumerator. Several resource tree was created
1120 Status
= GetResourceMap (
1134 if (EFI_ERROR (Status
)) {
1139 // Program IO resources
1147 // Program Mem32 resources
1155 // Program PMem32 resources
1163 // Program Mem64 resources
1171 // Program PMem64 resources
1178 if (AcpiConfig
!= NULL
) {
1179 gBS
->FreePool (AcpiConfig
);
1184 // Destroy all the resource tree
1186 DestroyResourceTree (&IoPool
);
1187 DestroyResourceTree (&Mem32Pool
);
1188 DestroyResourceTree (&PMem32Pool
);
1189 DestroyResourceTree (&Mem64Pool
);
1190 DestroyResourceTree (&PMem64Pool
);
1193 // Notify the resource allocation phase is to end
1195 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
1203 IN PCI_IO_DEVICE
*Bridge
,
1204 IN UINT8 StartBusNumber
,
1205 OUT UINT8
*SubBusNumber
,
1206 OUT UINT8
*PaddedBusRange
1209 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1210 return PciScanBus_WithHotPlugDeviceSupport (
1217 return PciScanBus_WithoutHotPlugDeviceSupport (
1228 PciScanBus_WithoutHotPlugDeviceSupport (
1229 IN PCI_IO_DEVICE
*Bridge
,
1230 IN UINT8 StartBusNumber
,
1231 OUT UINT8
*SubBusNumber
,
1232 OUT UINT8
*PaddedBusRange
1236 Routine Description:
1238 This routine is used to assign bus number to the given PCI bus system
1247 // TODO: Bridge - add argument and description to function comment
1248 // TODO: StartBusNumber - add argument and description to function comment
1249 // TODO: SubBusNumber - add argument and description to function comment
1250 // TODO: PaddedBusRange - add argument and description to function comment
1251 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1252 // TODO: EFI_SUCCESS - add return value to function comment
1261 PCI_IO_DEVICE
*PciDevice
;
1262 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1264 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1268 ResetAllPpbBusReg (Bridge
, StartBusNumber
);
1270 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1271 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1274 // Check to see whether a pci device is present
1276 Status
= PciDevicePresent (
1284 if (!EFI_ERROR (Status
) &&
1285 (IS_PCI_BRIDGE (&Pci
) ||
1286 IS_CARDBUS_BRIDGE (&Pci
))) {
1289 // Get the bridge information
1291 Status
= PciSearchDevice (
1300 if (EFI_ERROR (Status
)) {
1306 SecondBus
= (*SubBusNumber
);
1308 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1310 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1312 Status
= PciRootBridgeIo
->Pci
.Write (
1321 // Initialize SubBusNumber to SecondBus
1323 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1324 Status
= PciRootBridgeIo
->Pci
.Write (
1332 // If it is PPB, resursively search down this bridge
1334 if (IS_PCI_BRIDGE (&Pci
)) {
1336 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1337 // PCI configuration transaction to go through any PPB
1339 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1341 Status
= PciRootBridgeIo
->Pci
.Write (
1349 PreprocessController (
1351 PciDevice
->BusNumber
,
1352 PciDevice
->DeviceNumber
,
1353 PciDevice
->FunctionNumber
,
1354 EfiPciBeforeChildBusEnumeration
1357 Status
= PciScanBus (
1359 (UINT8
) (SecondBus
),
1364 if (EFI_ERROR (Status
)) {
1365 return EFI_DEVICE_ERROR
;
1370 // Set the current maximum bus number under the PPB
1373 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1375 Status
= PciRootBridgeIo
->Pci
.Write (
1385 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1388 // Skip sub functions, this is not a multi function device
1391 Func
= PCI_MAX_FUNC
;
1400 PciScanBus_WithHotPlugDeviceSupport (
1401 IN PCI_IO_DEVICE
*Bridge
,
1402 IN UINT8 StartBusNumber
,
1403 OUT UINT8
*SubBusNumber
,
1404 OUT UINT8
*PaddedBusRange
1408 Routine Description:
1410 This routine is used to assign bus number to the given PCI bus system
1414 Bridge - A pointer to the PCI_IO_DEVICE structure.
1415 StartBusNumber - The start bus number.
1416 SubBusNumber - A pointer to the sub bus number.
1417 PaddedBusRange - A pointer to the padded bus range.
1424 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1425 // TODO: EFI_SUCCESS - add return value to function comment
1435 PCI_IO_DEVICE
*PciDevice
;
1437 EFI_HPC_STATE State
;
1439 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
1440 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1442 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1445 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1452 ResetAllPpbBusReg (Bridge
, StartBusNumber
);
1454 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1455 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1458 // Check to see whether a pci device is present
1460 Status
= PciDevicePresent (
1468 if (EFI_ERROR (Status
)) {
1471 // Skip sub functions, this is not a multi function device
1473 Func
= PCI_MAX_FUNC
;
1480 // Get the PCI device information
1482 Status
= PciSearchDevice (
1491 ASSERT (!EFI_ERROR (Status
));
1493 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1495 if (!IS_PCI_BRIDGE (&Pci
)) {
1497 // PCI bridges will be called later
1498 // Here just need for PCI device or PCI to cardbus controller
1499 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1501 PreprocessController (
1503 PciDevice
->BusNumber
,
1504 PciDevice
->DeviceNumber
,
1505 PciDevice
->FunctionNumber
,
1506 EfiPciBeforeChildBusEnumeration
1511 // For Pci Hotplug controller devcie only
1513 if (gPciHotPlugInit
!= NULL
) {
1515 // Check if it is a Hotplug PCI controller
1517 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1519 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1521 Status
= CreateEventForHpc (HpIndex
, &Event
);
1523 ASSERT (!EFI_ERROR (Status
));
1525 Status
= gPciHotPlugInit
->InitializeRootHpc (
1527 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1533 PreprocessController (
1535 PciDevice
->BusNumber
,
1536 PciDevice
->DeviceNumber
,
1537 PciDevice
->FunctionNumber
,
1538 EfiPciBeforeChildBusEnumeration
1545 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1548 // Get the bridge information
1551 if (gPciHotPlugInit
!= NULL
) {
1553 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
1556 // If it is initialized, get the padded bus range
1558 Status
= gPciHotPlugInit
->GetResourcePadding (
1560 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
1563 (VOID
**) &Descriptors
,
1567 if (EFI_ERROR (Status
)) {
1572 Status
= PciGetBusRange (
1579 gBS
->FreePool (Descriptors
);
1581 if (EFI_ERROR (Status
)) {
1590 SecondBus
= *SubBusNumber
;
1592 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1593 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1595 Status
= PciRootBridgeIo
->Pci
.Write (
1605 // If it is PPB, resursively search down this bridge
1607 if (IS_PCI_BRIDGE (&Pci
)) {
1610 // Initialize SubBusNumber to Maximum bus number
1613 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1614 Status
= PciRootBridgeIo
->Pci
.Write (
1623 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1625 PreprocessController (
1627 PciDevice
->BusNumber
,
1628 PciDevice
->DeviceNumber
,
1629 PciDevice
->FunctionNumber
,
1630 EfiPciBeforeChildBusEnumeration
1633 Status
= PciScanBus (
1635 (UINT8
) (SecondBus
),
1640 if (EFI_ERROR (Status
)) {
1641 return EFI_DEVICE_ERROR
;
1647 // Ensure the device is enabled and initialized
1649 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1650 (State
& EFI_HPC_STATE_ENABLED
) &&
1651 (State
& EFI_HPC_STATE_INITIALIZED
) ) {
1652 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
1654 *SubBusNumber
= (UINT8
) ((UINT8
) (BusRange
) +*SubBusNumber
);
1659 // Set the current maximum bus number under the PPB
1661 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1663 Status
= PciRootBridgeIo
->Pci
.Write (
1672 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1675 // Skip sub functions, this is not a multi function device
1677 Func
= PCI_MAX_FUNC
;
1687 PciRootBridgeP2CProcess (
1688 IN PCI_IO_DEVICE
*Bridge
1692 Routine Description:
1694 Process Option Rom on this host bridge
1703 // TODO: Bridge - add argument and description to function comment
1704 // TODO: EFI_SUCCESS - add return value to function comment
1706 LIST_ENTRY
*CurrentLink
;
1707 PCI_IO_DEVICE
*Temp
;
1708 EFI_HPC_STATE State
;
1712 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1714 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
1716 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1718 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1720 if (gPciHotPlugInit
&& Temp
->Allocated
) {
1723 // Raise the EFI_IOB_PCI_HPC_INIT status code
1725 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1727 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_HPC_INIT
,
1731 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1732 Status
= gPciHotPlugInit
->InitializeRootHpc (
1740 if (!EFI_ERROR (Status
)) {
1741 Status
= PciBridgeEnumerator (Temp
);
1743 if (EFI_ERROR (Status
)) {
1748 CurrentLink
= CurrentLink
->ForwardLink
;
1754 if (!IsListEmpty (&Temp
->ChildList
)) {
1755 Status
= PciRootBridgeP2CProcess (Temp
);
1758 CurrentLink
= CurrentLink
->ForwardLink
;
1765 PciHostBridgeP2CProcess (
1766 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1770 Routine Description:
1779 // TODO: PciResAlloc - add argument and description to function comment
1780 // TODO: EFI_NOT_FOUND - add return value to function comment
1781 // TODO: EFI_SUCCESS - add return value to function comment
1783 EFI_HANDLE RootBridgeHandle
;
1784 PCI_IO_DEVICE
*RootBridgeDev
;
1787 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1791 RootBridgeHandle
= NULL
;
1793 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1796 // Get RootBridg Device by handle
1798 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1800 if (RootBridgeDev
== NULL
) {
1801 return EFI_NOT_FOUND
;
1804 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1806 if (EFI_ERROR (Status
)) {
1816 PciHostBridgeEnumerator (
1817 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1821 Routine Description:
1823 This function is used to enumerate the entire host bridge
1828 PciResAlloc - A pointer to the resource allocate protocol.
1835 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1836 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1837 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1838 // TODO: EFI_SUCCESS - add return value to function comment
1840 EFI_HANDLE RootBridgeHandle
;
1841 PCI_IO_DEVICE
*RootBridgeDev
;
1843 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1845 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1847 InitializeHotPlugSupport ();
1850 // Notify the bus allocation phase is about to start
1852 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1854 RootBridgeHandle
= NULL
;
1855 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1858 // if a root bridge instance is found, create root bridge device for it
1861 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1863 if (RootBridgeDev
== NULL
) {
1864 return EFI_OUT_OF_RESOURCES
;
1868 // Enumerate all the buses under this root bridge
1871 Status
= PciRootBridgeEnumerator (
1876 if (EFI_ERROR (Status
)) {
1880 DestroyRootBridge (RootBridgeDev
);
1883 // Error proccess here
1887 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1890 // Notify the bus allocation phase is finished for the first time
1892 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1895 if (gPciHotPlugInit
!= NULL
) {
1897 // Wait for all HPC initialized
1899 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1901 if (EFI_ERROR (Status
)) {
1906 // Notify the bus allocation phase is about to start for the 2nd time
1908 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1910 RootBridgeHandle
= NULL
;
1911 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1914 // if a root bridge instance is found, create root bridge device for it
1917 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1919 if (RootBridgeDev
== NULL
) {
1920 return EFI_OUT_OF_RESOURCES
;
1924 // Enumerate all the buses under this root bridge
1927 Status
= PciRootBridgeEnumerator (
1932 DestroyRootBridge (RootBridgeDev
);
1933 if (EFI_ERROR (Status
)) {
1939 // Notify the bus allocation phase is to end
1941 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1945 // Notify the bus allocation phase is to end
1947 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1951 // Notify the resource allocation phase is to start
1953 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1955 RootBridgeHandle
= NULL
;
1956 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1959 // if a root bridge instance is found, create root bridge device for it
1962 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1964 if (RootBridgeDev
== NULL
) {
1965 return EFI_OUT_OF_RESOURCES
;
1968 Status
= StartManagingRootBridge (RootBridgeDev
);
1970 if (EFI_ERROR (Status
)) {
1974 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1975 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1977 if (EFI_ERROR (Status
)) {
1981 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1983 if (EFI_ERROR (Status
)) {
1988 // Determine root bridge attribute by calling interface of Pcihostbridge
1991 DetermineRootBridgeAttributes (
1997 // Collect all the resource information under this root bridge
1998 // A database that records all the information about pci device subject to this
1999 // root bridge will then be created
2001 Status
= PciPciDeviceInfoCollector (
2006 if (EFI_ERROR (Status
)) {
2010 InsertRootBridge (RootBridgeDev
);
2013 // Record the hostbridge handle
2015 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);