3 PCI Bus Driver Lib file
4 It abstracts some functions that can be different
5 between light PCI bus driver and full PCI bus driver
7 Copyright (c) 2006 - 2008, Intel Corporation
8 All rights reserved. This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
20 GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest
= {
21 PciHotPlugRequestNotify
26 InstallHotPlugRequestProtocol (
34 Status - A pointer to the status.
44 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
49 *Status
= gBS
->InstallProtocolInterface (
51 &gEfiPciHotPlugRequestProtocolGuid
,
58 InstallPciHotplugGuid (
59 IN PCI_IO_DEVICE
*PciIoDevice
67 PciIoDevice - A pointer to the PCI_IO_DEVICE.
77 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
81 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Parent
->Pci
)) {
83 Status
= gBS
->InstallProtocolInterface (
85 &gEfiPciHotplugDeviceGuid
,
89 ASSERT_EFI_ERROR (Status
);
94 UninstallPciHotplugGuid (
95 IN PCI_IO_DEVICE
*PciIoDevice
103 PciIoDevice - A pointer to the PCI_IO_DEVICE.
113 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
117 Status
= gBS
->OpenProtocol (
119 &gEfiPciHotplugDeviceGuid
,
123 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
126 if (Status
== EFI_SUCCESS
) {
128 // This may triger CardBus driver to stop for
129 // Pccard devices opened the GUID via BY_DRIVER
131 Status
= gBS
->UninstallProtocolInterface (
133 &gEfiPciHotplugDeviceGuid
,
141 IN PCI_IO_DEVICE
*PciIoDevice
150 PciIoDevice - A pointer to the PCI_IO_DEVICE.
160 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
165 // Read PciBar information from the bar register
167 if (!gFullEnumeration
) {
171 &(PciIoDevice
->PciIo
),
178 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
179 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
180 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
184 &(PciIoDevice
->PciIo
),
190 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
191 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
192 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
196 &(PciIoDevice
->PciIo
),
202 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
203 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
204 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
208 &(PciIoDevice
->PciIo
),
214 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
215 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
216 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
220 if (gPciHotPlugInit
!= NULL
) {
221 GetResourcePaddingForHpb (PciIoDevice
);
226 RemoveRejectedPciDevices (
227 EFI_HANDLE RootBridgeHandle
,
228 IN PCI_IO_DEVICE
*Bridge
237 RootBridgeHandle - An efi handle.
238 Bridge - An pointer to the PCI_IO_DEVICE.
245 // TODO: EFI_SUCCESS - add return value to function comment
248 LIST_ENTRY
*CurrentLink
;
249 LIST_ENTRY
*LastLink
;
251 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
255 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
257 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
259 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
261 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
263 // Remove rejected devices recusively
265 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
268 // Skip rejection for all PPBs, while detect rejection for others
270 if (IsPciDeviceRejected (Temp
)) {
273 // For P2C, remove all devices on it
276 if (!IsListEmpty (&Temp
->ChildList
)) {
277 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
281 // Finally remove itself
284 LastLink
= CurrentLink
->BackLink
;
285 RemoveEntryList (CurrentLink
);
286 FreePciDevice (Temp
);
288 CurrentLink
= LastLink
;
292 CurrentLink
= CurrentLink
->ForwardLink
;
299 PciHostBridgeResourceAllocator (
300 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
303 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
304 return PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
308 return PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
316 PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
317 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
330 // TODO: PciResAlloc - add argument and description to function comment
331 // TODO: EFI_NOT_FOUND - add return value to function comment
332 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
333 // TODO: EFI_NOT_FOUND - add return value to function comment
334 // TODO: EFI_SUCCESS - add return value to function comment
336 PCI_IO_DEVICE
*RootBridgeDev
;
337 EFI_HANDLE RootBridgeHandle
;
345 UINT64 MaxOptionRomSize
;
346 PCI_RESOURCE_NODE
*IoBridge
;
347 PCI_RESOURCE_NODE
*Mem32Bridge
;
348 PCI_RESOURCE_NODE
*PMem32Bridge
;
349 PCI_RESOURCE_NODE
*Mem64Bridge
;
350 PCI_RESOURCE_NODE
*PMem64Bridge
;
351 PCI_RESOURCE_NODE IoPool
;
352 PCI_RESOURCE_NODE Mem32Pool
;
353 PCI_RESOURCE_NODE PMem32Pool
;
354 PCI_RESOURCE_NODE Mem64Pool
;
355 PCI_RESOURCE_NODE PMem64Pool
;
356 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD ExtendedData
;
359 // Initialize resource pool
362 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
363 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
364 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
365 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
366 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
368 RootBridgeDev
= NULL
;
369 RootBridgeHandle
= 0;
371 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
373 // Get RootBridg Device by handle
375 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
377 if (RootBridgeDev
== NULL
) {
378 return EFI_NOT_FOUND
;
382 // Get host bridge handle for status report
384 ExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
387 // Create the entire system resource map from the information collected by
388 // enumerator. Several resource tree was created
391 IoBridge
= CreateResourceNode (
400 Mem32Bridge
= CreateResourceNode (
409 PMem32Bridge
= CreateResourceNode (
418 Mem64Bridge
= CreateResourceNode (
427 PMem64Bridge
= CreateResourceNode (
437 // Create resourcemap by going through all the devices subject to this root bridge
439 Status
= CreateResourceMap (
449 // Get the max ROM size that the root bridge can process
451 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
454 // Get Max Option Rom size for current root bridge
456 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
459 // Enlarger the mem32 resource to accomdate the option rom
460 // if the mem32 resource is not enough to hold the rom
462 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
464 Mem32Bridge
->Length
= MaxOptionRomSize
;
465 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
468 // Alignment should be adjusted as well
470 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
471 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
476 // Based on the all the resource tree, contruct ACPI resource node to
477 // submit the resource aperture to pci host bridge protocol
479 Status
= ConstructAcpiResourceRequestor (
490 // Insert these resource nodes into the database
492 InsertResourceNode (&IoPool
, IoBridge
);
493 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
494 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
495 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
496 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
498 if (Status
== EFI_SUCCESS
) {
500 // Submit the resource requirement
502 Status
= PciResAlloc
->SubmitResources (
504 RootBridgeDev
->Handle
,
509 // Free acpi resource node
511 if (AcpiConfig
!= NULL
) {
512 FreePool (AcpiConfig
);
515 if (EFI_ERROR (Status
)) {
517 // Destroy all the resource tree
519 DestroyResourceTree (&IoPool
);
520 DestroyResourceTree (&Mem32Pool
);
521 DestroyResourceTree (&PMem32Pool
);
522 DestroyResourceTree (&Mem64Pool
);
523 DestroyResourceTree (&PMem64Pool
);
532 // Notify pci bus driver starts to program the resource
534 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
536 if (EFI_ERROR (Status
)) {
538 // Allocation failed, then return
540 return EFI_OUT_OF_RESOURCES
;
543 // Raise the EFI_IOB_PCI_RES_ALLOC status code
545 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
547 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
548 (VOID
*) &ExtendedData
,
549 sizeof (ExtendedData
)
553 // Notify pci bus driver starts to program the resource
555 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
557 RootBridgeDev
= NULL
;
559 RootBridgeHandle
= 0;
561 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
563 // Get RootBridg Device by handle
565 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
567 if (RootBridgeDev
== NULL
) {
568 return EFI_NOT_FOUND
;
572 // Get acpi resource node for all the resource types
575 Status
= PciResAlloc
->GetProposedResources (
577 RootBridgeDev
->Handle
,
581 if (EFI_ERROR (Status
)) {
586 // Get the resource base by interpreting acpi resource node
599 // Process option rom for this root bridge
601 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
604 // Create the entire system resource map from the information collected by
605 // enumerator. Several resource tree was created
607 Status
= GetResourceMap (
621 if (EFI_ERROR (Status
)) {
626 // Program IO resources
634 // Program Mem32 resources
642 // Program PMem32 resources
650 // Program Mem64 resources
658 // Program PMem64 resources
665 if (AcpiConfig
!= NULL
) {
666 FreePool (AcpiConfig
);
671 // Destroy all the resource tree
673 DestroyResourceTree (&IoPool
);
674 DestroyResourceTree (&Mem32Pool
);
675 DestroyResourceTree (&PMem32Pool
);
676 DestroyResourceTree (&Mem64Pool
);
677 DestroyResourceTree (&PMem64Pool
);
680 // Notify the resource allocation phase is to end
682 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
689 PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
690 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
696 Host brige resource allocator.
700 PciResAlloc - A pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
707 // TODO: EFI_NOT_FOUND - add return value to function comment
708 // TODO: EFI_NOT_FOUND - add return value to function comment
709 // TODO: EFI_NOT_FOUND - add return value to function comment
710 // TODO: EFI_SUCCESS - add return value to function comment
712 PCI_IO_DEVICE
*RootBridgeDev
;
713 EFI_HANDLE RootBridgeHandle
;
722 UINT64 Mem32ResStatus
;
723 UINT64 PMem32ResStatus
;
724 UINT64 Mem64ResStatus
;
725 UINT64 PMem64ResStatus
;
726 UINT64 MaxOptionRomSize
;
727 PCI_RESOURCE_NODE
*IoBridge
;
728 PCI_RESOURCE_NODE
*Mem32Bridge
;
729 PCI_RESOURCE_NODE
*PMem32Bridge
;
730 PCI_RESOURCE_NODE
*Mem64Bridge
;
731 PCI_RESOURCE_NODE
*PMem64Bridge
;
732 PCI_RESOURCE_NODE IoPool
;
733 PCI_RESOURCE_NODE Mem32Pool
;
734 PCI_RESOURCE_NODE PMem32Pool
;
735 PCI_RESOURCE_NODE Mem64Pool
;
736 PCI_RESOURCE_NODE PMem64Pool
;
738 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
739 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
747 // It will try several times if the resource allocation fails
752 // Initialize resource pool
754 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
755 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
756 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
757 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
758 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
760 RootBridgeDev
= NULL
;
761 RootBridgeHandle
= 0;
763 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
766 // Get RootBridg Device by handle
768 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
770 if (RootBridgeDev
== NULL
) {
771 return EFI_NOT_FOUND
;
775 // Create the entire system resource map from the information collected by
776 // enumerator. Several resource tree was created
779 IoBridge
= CreateResourceNode (
788 Mem32Bridge
= CreateResourceNode (
797 PMem32Bridge
= CreateResourceNode (
806 Mem64Bridge
= CreateResourceNode (
815 PMem64Bridge
= CreateResourceNode (
825 // Create resourcemap by going through all the devices subject to this root bridge
827 Status
= CreateResourceMap (
837 // Get the max ROM size that the root bridge can process
839 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
842 // Skip to enlarge the resource request during realloction
846 // Get Max Option Rom size for current root bridge
848 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
851 // Enlarger the mem32 resource to accomdate the option rom
852 // if the mem32 resource is not enough to hold the rom
854 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
856 Mem32Bridge
->Length
= MaxOptionRomSize
;
857 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
860 // Alignment should be adjusted as well
862 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
863 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
869 // Based on the all the resource tree, contruct ACPI resource node to
870 // submit the resource aperture to pci host bridge protocol
872 Status
= ConstructAcpiResourceRequestor (
883 // Insert these resource nodes into the database
885 InsertResourceNode (&IoPool
, IoBridge
);
886 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
887 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
888 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
889 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
891 if (Status
== EFI_SUCCESS
) {
893 // Submit the resource requirement
895 Status
= PciResAlloc
->SubmitResources (
897 RootBridgeDev
->Handle
,
903 // Free acpi resource node
905 if (AcpiConfig
!= NULL
) {
906 FreePool (AcpiConfig
);
909 if (EFI_ERROR (Status
)) {
911 // Destroy all the resource tree
913 DestroyResourceTree (&IoPool
);
914 DestroyResourceTree (&Mem32Pool
);
915 DestroyResourceTree (&PMem32Pool
);
916 DestroyResourceTree (&Mem64Pool
);
917 DestroyResourceTree (&PMem64Pool
);
923 // Notify pci bus driver starts to program the resource
926 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
928 if (!EFI_ERROR (Status
)) {
930 // Allocation succeed, then continue the following
936 // If the resource allocation is unsuccessful, free resources on bridge
939 RootBridgeDev
= NULL
;
940 RootBridgeHandle
= 0;
942 IoResStatus
= EFI_RESOURCE_SATISFIED
;
943 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
944 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
945 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
946 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
948 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
950 // Get RootBridg Device by handle
952 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
953 if (RootBridgeDev
== NULL
) {
954 return EFI_NOT_FOUND
;
958 // Get host bridge handle for status report
960 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
963 // Get acpi resource node for all the resource types
967 Status
= PciResAlloc
->GetProposedResources (
969 RootBridgeDev
->Handle
,
973 if (EFI_ERROR (Status
)) {
977 if (AcpiConfig
!= NULL
) {
979 // Adjust resource allocation policy for each RB
981 GetResourceAllocationStatus (
989 FreePool (AcpiConfig
);
997 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
1000 // It is very difficult to follow the spec here
1001 // Device path , Bar index can not be get here
1003 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
1005 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1007 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
1008 (VOID
*) &AllocFailExtendedData
,
1009 sizeof (AllocFailExtendedData
)
1012 Status
= PciHostBridgeAdjustAllocation (
1026 // Destroy all the resource tree
1028 DestroyResourceTree (&IoPool
);
1029 DestroyResourceTree (&Mem32Pool
);
1030 DestroyResourceTree (&PMem32Pool
);
1031 DestroyResourceTree (&Mem64Pool
);
1032 DestroyResourceTree (&PMem64Pool
);
1034 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
1036 if (EFI_ERROR (Status
)) {
1048 // Raise the EFI_IOB_PCI_RES_ALLOC status code
1050 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1052 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
1053 (VOID
*) &HandleExtendedData
,
1054 sizeof (HandleExtendedData
)
1058 // Notify pci bus driver starts to program the resource
1060 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
1062 RootBridgeDev
= NULL
;
1064 RootBridgeHandle
= 0;
1066 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1069 // Get RootBridg Device by handle
1071 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1073 if (RootBridgeDev
== NULL
) {
1074 return EFI_NOT_FOUND
;
1078 // Get acpi resource node for all the resource types
1081 Status
= PciResAlloc
->GetProposedResources (
1083 RootBridgeDev
->Handle
,
1087 if (EFI_ERROR (Status
)) {
1092 // Get the resource base by interpreting acpi resource node
1105 // Process option rom for this root bridge
1107 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
1110 // Create the entire system resource map from the information collected by
1111 // enumerator. Several resource tree was created
1113 Status
= GetResourceMap (
1127 if (EFI_ERROR (Status
)) {
1132 // Program IO resources
1140 // Program Mem32 resources
1148 // Program PMem32 resources
1156 // Program Mem64 resources
1164 // Program PMem64 resources
1171 if (AcpiConfig
!= NULL
) {
1172 gBS
->FreePool (AcpiConfig
);
1177 // Destroy all the resource tree
1179 DestroyResourceTree (&IoPool
);
1180 DestroyResourceTree (&Mem32Pool
);
1181 DestroyResourceTree (&PMem32Pool
);
1182 DestroyResourceTree (&Mem64Pool
);
1183 DestroyResourceTree (&PMem64Pool
);
1186 // Notify the resource allocation phase is to end
1188 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
1196 IN PCI_IO_DEVICE
*Bridge
,
1197 IN UINT8 StartBusNumber
,
1198 OUT UINT8
*SubBusNumber
,
1199 OUT UINT8
*PaddedBusRange
1202 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1203 return PciScanBus_WithHotPlugDeviceSupport (
1210 return PciScanBus_WithoutHotPlugDeviceSupport (
1221 PciScanBus_WithoutHotPlugDeviceSupport (
1222 IN PCI_IO_DEVICE
*Bridge
,
1223 IN UINT8 StartBusNumber
,
1224 OUT UINT8
*SubBusNumber
,
1225 OUT UINT8
*PaddedBusRange
1229 Routine Description:
1231 This routine is used to assign bus number to the given PCI bus system
1240 // TODO: Bridge - add argument and description to function comment
1241 // TODO: StartBusNumber - add argument and description to function comment
1242 // TODO: SubBusNumber - add argument and description to function comment
1243 // TODO: PaddedBusRange - add argument and description to function comment
1244 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1245 // TODO: EFI_SUCCESS - add return value to function comment
1254 PCI_IO_DEVICE
*PciDevice
;
1255 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1257 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1261 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1262 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1265 // Check to see whether a pci device is present
1267 Status
= PciDevicePresent (
1275 if (!EFI_ERROR (Status
) &&
1276 (IS_PCI_BRIDGE (&Pci
) ||
1277 IS_CARDBUS_BRIDGE (&Pci
))) {
1279 DEBUG((EFI_D_ERROR
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
1282 // Get the bridge information
1284 Status
= PciSearchDevice (
1293 if (EFI_ERROR (Status
)) {
1298 // Add feature to support customized secondary bus number
1300 if (*SubBusNumber
== 0) {
1301 *SubBusNumber
= *PaddedBusRange
;
1302 *PaddedBusRange
= 0;
1307 SecondBus
= (*SubBusNumber
);
1309 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1311 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1313 Status
= PciRootBridgeIoWrite (
1323 // Initialize SubBusNumber to SecondBus
1325 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1326 Status
= PciRootBridgeIoWrite (
1335 // If it is PPB, resursively search down this bridge
1337 if (IS_PCI_BRIDGE (&Pci
)) {
1339 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1340 // PCI configuration transaction to go through any PPB
1342 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1344 Status
= PciRootBridgeIoWrite (
1353 PreprocessController (
1355 PciDevice
->BusNumber
,
1356 PciDevice
->DeviceNumber
,
1357 PciDevice
->FunctionNumber
,
1358 EfiPciBeforeChildBusEnumeration
1361 DEBUG((EFI_D_ERROR
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
1362 Status
= PciScanBus (
1364 (UINT8
) (SecondBus
),
1369 if (EFI_ERROR (Status
)) {
1370 return EFI_DEVICE_ERROR
;
1375 // Set the current maximum bus number under the PPB
1378 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1380 Status
= PciRootBridgeIoWrite (
1391 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1394 // Skip sub functions, this is not a multi function device
1397 Func
= PCI_MAX_FUNC
;
1406 PciScanBus_WithHotPlugDeviceSupport (
1407 IN PCI_IO_DEVICE
*Bridge
,
1408 IN UINT8 StartBusNumber
,
1409 OUT UINT8
*SubBusNumber
,
1410 OUT UINT8
*PaddedBusRange
1414 Routine Description:
1416 This routine is used to assign bus number to the given PCI bus system
1420 Bridge - A pointer to the PCI_IO_DEVICE structure.
1421 StartBusNumber - The start bus number.
1422 SubBusNumber - A pointer to the sub bus number.
1423 PaddedBusRange - A pointer to the padded bus range.
1430 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1431 // TODO: EFI_SUCCESS - add return value to function comment
1441 PCI_IO_DEVICE
*PciDevice
;
1443 EFI_HPC_STATE State
;
1445 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
1446 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1448 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1451 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1455 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
1458 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1459 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1462 // Check to see whether a pci device is present
1464 Status
= PciDevicePresent (
1472 if (EFI_ERROR (Status
)) {
1475 // Skip sub functions, this is not a multi function device
1477 Func
= PCI_MAX_FUNC
;
1483 DEBUG((EFI_D_ERROR
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
1486 // Get the PCI device information
1488 Status
= PciSearchDevice (
1497 ASSERT (!EFI_ERROR (Status
));
1499 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1501 if (!IS_PCI_BRIDGE (&Pci
)) {
1503 // PCI bridges will be called later
1504 // Here just need for PCI device or PCI to cardbus controller
1505 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1507 PreprocessController (
1509 PciDevice
->BusNumber
,
1510 PciDevice
->DeviceNumber
,
1511 PciDevice
->FunctionNumber
,
1512 EfiPciBeforeChildBusEnumeration
1517 // For Pci Hotplug controller devcie only
1519 if (gPciHotPlugInit
!= NULL
) {
1521 // Check if it is a Hotplug PCI controller
1523 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1525 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1527 Status
= CreateEventForHpc (HpIndex
, &Event
);
1529 ASSERT (!EFI_ERROR (Status
));
1531 Status
= gPciHotPlugInit
->InitializeRootHpc (
1533 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1539 PreprocessController (
1541 PciDevice
->BusNumber
,
1542 PciDevice
->DeviceNumber
,
1543 PciDevice
->FunctionNumber
,
1544 EfiPciBeforeChildBusEnumeration
1550 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1553 // Get the bridge information
1556 if (gPciHotPlugInit
!= NULL
) {
1558 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
1561 // If it is initialized, get the padded bus range
1563 Status
= gPciHotPlugInit
->GetResourcePadding (
1565 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
1568 (VOID
**) &Descriptors
,
1572 if (EFI_ERROR (Status
)) {
1577 Status
= PciGetBusRange (
1584 gBS
->FreePool (Descriptors
);
1586 if (EFI_ERROR (Status
)) {
1595 // Add feature to support customized secondary bus number
1597 if (*SubBusNumber
== 0) {
1598 *SubBusNumber
= *PaddedBusRange
;
1599 *PaddedBusRange
= 0;
1603 SecondBus
= *SubBusNumber
;
1605 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1606 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1608 Status
= PciRootBridgeIoWrite (
1619 // If it is PPB, resursively search down this bridge
1621 if (IS_PCI_BRIDGE (&Pci
)) {
1624 // Initialize SubBusNumber to Maximum bus number
1627 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1628 Status
= PciRootBridgeIoWrite (
1638 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1640 PreprocessController (
1642 PciDevice
->BusNumber
,
1643 PciDevice
->DeviceNumber
,
1644 PciDevice
->FunctionNumber
,
1645 EfiPciBeforeChildBusEnumeration
1648 DEBUG((EFI_D_ERROR
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
1649 Status
= PciScanBus (
1651 (UINT8
) (SecondBus
),
1656 if (EFI_ERROR (Status
)) {
1657 return EFI_DEVICE_ERROR
;
1663 // Ensure the device is enabled and initialized
1665 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1666 (State
& EFI_HPC_STATE_ENABLED
) &&
1667 (State
& EFI_HPC_STATE_INITIALIZED
) ) {
1668 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
1670 *SubBusNumber
= (UINT8
) ((UINT8
) (BusRange
) +*SubBusNumber
);
1675 // Set the current maximum bus number under the PPB
1677 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1679 Status
= PciRootBridgeIoWrite (
1689 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1692 // Skip sub functions, this is not a multi function device
1694 Func
= PCI_MAX_FUNC
;
1704 PciRootBridgeP2CProcess (
1705 IN PCI_IO_DEVICE
*Bridge
1709 Routine Description:
1711 Process Option Rom on this host bridge
1720 // TODO: Bridge - add argument and description to function comment
1721 // TODO: EFI_SUCCESS - add return value to function comment
1723 LIST_ENTRY
*CurrentLink
;
1724 PCI_IO_DEVICE
*Temp
;
1725 EFI_HPC_STATE State
;
1729 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1731 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
1733 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1735 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1737 if (gPciHotPlugInit
&& Temp
->Allocated
) {
1740 // Raise the EFI_IOB_PCI_HPC_INIT status code
1742 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1744 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_HPC_INIT
,
1748 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1749 Status
= gPciHotPlugInit
->InitializeRootHpc (
1757 if (!EFI_ERROR (Status
)) {
1758 Status
= PciBridgeEnumerator (Temp
);
1760 if (EFI_ERROR (Status
)) {
1765 CurrentLink
= CurrentLink
->ForwardLink
;
1771 if (!IsListEmpty (&Temp
->ChildList
)) {
1772 Status
= PciRootBridgeP2CProcess (Temp
);
1775 CurrentLink
= CurrentLink
->ForwardLink
;
1782 PciHostBridgeP2CProcess (
1783 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1787 Routine Description:
1796 // TODO: PciResAlloc - add argument and description to function comment
1797 // TODO: EFI_NOT_FOUND - add return value to function comment
1798 // TODO: EFI_SUCCESS - add return value to function comment
1800 EFI_HANDLE RootBridgeHandle
;
1801 PCI_IO_DEVICE
*RootBridgeDev
;
1804 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1808 RootBridgeHandle
= NULL
;
1810 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1813 // Get RootBridg Device by handle
1815 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1817 if (RootBridgeDev
== NULL
) {
1818 return EFI_NOT_FOUND
;
1821 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1823 if (EFI_ERROR (Status
)) {
1833 PciHostBridgeEnumerator (
1834 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1838 Routine Description:
1840 This function is used to enumerate the entire host bridge
1845 PciResAlloc - A pointer to the resource allocate protocol.
1852 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1853 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1854 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
1855 // TODO: EFI_SUCCESS - add return value to function comment
1857 EFI_HANDLE RootBridgeHandle
;
1858 PCI_IO_DEVICE
*RootBridgeDev
;
1860 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1862 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1863 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*pConfiguration
;
1864 UINT8 StartBusNumber
;
1865 LIST_ENTRY RootBridgeList
;
1868 InitializeHotPlugSupport ();
1870 InitializeListHead (&RootBridgeList
);
1873 // Notify the bus allocation phase is about to start
1875 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1877 DEBUG((EFI_D_ERROR
, "PCI Bus First Scanning\n"));
1878 RootBridgeHandle
= NULL
;
1879 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1882 // if a root bridge instance is found, create root bridge device for it
1885 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1887 if (RootBridgeDev
== NULL
) {
1888 return EFI_OUT_OF_RESOURCES
;
1892 // Enumerate all the buses under this root bridge
1895 Status
= PciRootBridgeEnumerator (
1900 if (gPciHotPlugInit
!= NULL
) {
1901 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1903 DestroyRootBridge (RootBridgeDev
);
1905 if (EFI_ERROR (Status
)) {
1911 // Notify the bus allocation phase is finished for the first time
1913 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1915 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1917 if (gPciHotPlugInit
!= NULL
) {
1919 // Reset all assigned PCI bus number in all PPB
1921 RootBridgeHandle
= NULL
;
1922 Link
= GetFirstNode (&RootBridgeList
);
1923 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1924 (!IsNull (&RootBridgeList
, Link
))) {
1925 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1927 // Get the Bus information
1929 Status
= PciResAlloc
->StartBusEnumeration (
1932 (VOID
**) &pConfiguration
1934 if (EFI_ERROR (Status
)) {
1939 // Get the bus number to start with
1941 StartBusNumber
= (UINT8
) (pConfiguration
->AddrRangeMin
);
1943 ResetAllPpbBusNumber (
1948 gBS
->FreePool (pConfiguration
);
1949 Link
= GetNextNode (&RootBridgeList
, Link
);
1950 DestroyRootBridge (RootBridgeDev
);
1954 // Wait for all HPC initialized
1956 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1958 if (EFI_ERROR (Status
)) {
1963 // Notify the bus allocation phase is about to start for the 2nd time
1965 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1967 DEBUG((EFI_D_ERROR
, "PCI Bus Second Scanning\n"));
1968 RootBridgeHandle
= NULL
;
1969 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1972 // if a root bridge instance is found, create root bridge device for it
1975 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1977 if (RootBridgeDev
== NULL
) {
1978 return EFI_OUT_OF_RESOURCES
;
1982 // Enumerate all the buses under this root bridge
1985 Status
= PciRootBridgeEnumerator (
1990 DestroyRootBridge (RootBridgeDev
);
1991 if (EFI_ERROR (Status
)) {
1997 // Notify the bus allocation phase is to end for the 2nd time
1999 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
2004 // Notify the resource allocation phase is to start
2006 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
2008 RootBridgeHandle
= NULL
;
2009 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
2012 // if a root bridge instance is found, create root bridge device for it
2015 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
2017 if (RootBridgeDev
== NULL
) {
2018 return EFI_OUT_OF_RESOURCES
;
2021 Status
= StartManagingRootBridge (RootBridgeDev
);
2023 if (EFI_ERROR (Status
)) {
2027 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
2028 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
2030 if (EFI_ERROR (Status
)) {
2034 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
2036 if (EFI_ERROR (Status
)) {
2041 // Determine root bridge attribute by calling interface of Pcihostbridge
2044 DetermineRootBridgeAttributes (
2050 // Collect all the resource information under this root bridge
2051 // A database that records all the information about pci device subject to this
2052 // root bridge will then be created
2054 Status
= PciPciDeviceInfoCollector (
2059 if (EFI_ERROR (Status
)) {
2063 InsertRootBridge (RootBridgeDev
);
2066 // Record the hostbridge handle
2068 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);
2075 Read PCI device configuration register by specified address.
2077 This function check the incompatiblilites on PCI device. Return the register
2080 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2081 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2082 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2083 @param Width Signifies the width of the memory operations.
2084 @Param Address The address within the PCI configuration space for the PCI controller.
2085 @param Buffer For read operations, the destination buffer to store the results. For
2086 write operations, the source buffer to write data from.
2088 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2089 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2090 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2091 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2097 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2098 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2099 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2107 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
2108 UINT64 AccessAddress
;
2113 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2115 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) {
2117 // check access compatibility at first time
2119 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, Address
& 0xff, Width
, &PciRegisterAccessData
);
2121 if (Status
== EFI_SUCCESS
) {
2123 // there exist incompatibility on this operation
2125 AccessWidth
= Width
;
2127 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2128 AccessWidth
= PciRegisterAccessData
->Width
;
2131 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
2135 Pointer
= (UINT8
*) &TempBuffer
;
2139 if (PciRootBridgeIo
!= NULL
) {
2140 Status
= PciRootBridgeIo
->Pci
.Read (
2142 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
2147 } else if (PciIo
!= NULL
) {
2148 Status
= PciIo
->Pci
.Read (
2150 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
2151 (UINT32
) AccessAddress
,
2157 if (Status
!= EFI_SUCCESS
) {
2161 Stride
= (UINTN
)1 << AccessWidth
;
2162 AccessAddress
+= Stride
;
2163 if (AccessAddress
>= (Address
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
2165 // if all datas have been read, exist
2172 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
2174 // if current offset doesn't reach the end
2179 FreePool (PciRegisterAccessData
);
2182 // continue checking access incompatibility
2184 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
2185 if (Status
== EFI_SUCCESS
) {
2186 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2187 AccessWidth
= PciRegisterAccessData
->Width
;
2192 FreePool (PciRegisterAccessData
);
2195 case EfiPciWidthUint8
:
2196 * (UINT8
*) Buffer
= (UINT8
) TempBuffer
;
2198 case EfiPciWidthUint16
:
2199 * (UINT16
*) Buffer
= (UINT16
) TempBuffer
;
2201 case EfiPciWidthUint32
:
2202 * (UINT32
*) Buffer
= (UINT32
) TempBuffer
;
2205 return EFI_UNSUPPORTED
;
2212 // AccessWidth incompatible check not supportted
2213 // or, there doesn't exist incompatibility on this operation
2215 if (PciRootBridgeIo
!= NULL
) {
2216 Status
= PciRootBridgeIo
->Pci
.Read (
2218 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
2225 Status
= PciIo
->Pci
.Read (
2227 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
2238 Update register value by checking PCI device incompatibility.
2240 This function check register value incompatibilites on PCI device. Return the register
2243 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2244 @param AccessType Access type, READ or WRITE.
2245 @Param Address The address within the PCI configuration space.
2246 @param Buffer Store the register data.
2248 @retval EFI_SUCCESS The data has been updated.
2254 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2255 IN UINT64 AccessType
,
2262 EFI_PCI_REGISTER_VALUE_DATA
*PciRegisterData
;
2268 // check register value incompatibility
2270 Status
= PciRegisterUpdateCheck (PciDeviceInfo
, AccessType
, Address
& 0xff, &PciRegisterData
);
2272 if (Status
== EFI_SUCCESS
) {
2274 AndValue
= ((UINT32
) PciRegisterData
->AndValue
) >> (((UINT8
) Address
& 0x3) * 8);
2275 OrValue
= ((UINT32
) PciRegisterData
->OrValue
) >> (((UINT8
) Address
& 0x3) * 8);
2277 TempValue
= * (UINT32
*) Buffer
;
2278 if (PciRegisterData
->AndValue
!= VALUE_NOCARE
) {
2279 TempValue
&= AndValue
;
2281 if (PciRegisterData
->OrValue
!= VALUE_NOCARE
) {
2282 TempValue
|= OrValue
;
2286 case EfiPciWidthUint8
:
2287 *(UINT8
*)Buffer
= (UINT8
) TempValue
;
2290 case EfiPciWidthUint16
:
2291 *(UINT16
*)Buffer
= (UINT16
) TempValue
;
2293 case EfiPciWidthUint32
:
2294 *(UINT32
*)Buffer
= TempValue
;
2298 return EFI_UNSUPPORTED
;
2301 FreePool (PciRegisterData
);
2308 Write PCI device configuration register by specified address.
2310 This function check the incompatiblilites on PCI device, and write date
2313 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2314 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2315 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2316 @param Width Signifies the width of the memory operations.
2317 @Param Address The address within the PCI configuration space for the PCI controller.
2318 @param Buffer For read operations, the destination buffer to store the results. For
2319 write operations, the source buffer to write data from.
2321 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2322 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2323 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2324 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2330 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2331 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2332 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2340 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
2341 UINT64 AccessAddress
;
2347 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2349 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) {
2351 // check access compatibility at first time
2353 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, Address
& 0xff, Width
, &PciRegisterAccessData
);
2355 if (Status
== EFI_SUCCESS
) {
2357 // there exist incompatibility on this operation
2359 AccessWidth
= Width
;
2361 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2362 AccessWidth
= PciRegisterAccessData
->Width
;
2365 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
2368 Pointer
= (UINT8
*) &Buffer
;
2369 Data
= * (UINT64
*) Buffer
;
2373 if (AccessWidth
> Width
) {
2375 // if actual access width is larger than orignal one, additional data need to be read back firstly
2377 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, PciDeviceInfo
, AccessWidth
, AccessAddress
, &Data
);
2378 if (Status
!= EFI_SUCCESS
) {
2383 // check data read incompatibility
2385 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_READ
, AccessWidth
, AccessAddress
& 0xff, &Data
);
2387 Shift
= (UINTN
)(Address
- AccessAddress
) * 8;
2389 case EfiPciWidthUint8
:
2390 Data
= (* (UINT8
*) Buffer
) << Shift
| (Data
& ~(0xff << Shift
));
2393 case EfiPciWidthUint16
:
2394 Data
= (* (UINT16
*) Buffer
) << Shift
| (Data
& ~(0xffff << Shift
));
2399 // check data write incompatibility
2401 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessWidth
, MultU64x32 (AccessAddress
, 0xff), &Data
);
2404 if (PciRootBridgeIo
!= NULL
) {
2405 Status
= PciRootBridgeIo
->Pci
.Write (
2407 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
2413 Status
= PciIo
->Pci
.Write (
2415 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
2416 (UINT32
) AccessAddress
,
2422 if (Status
!= EFI_SUCCESS
) {
2426 Data
= RShiftU64 (Data
, ((1 << AccessWidth
) * 8));
2428 Stride
= (UINTN
)1 << AccessWidth
;
2429 AccessAddress
+= Stride
;
2430 if (AccessAddress
>= (Address
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
2432 // if all datas have been written, exist
2439 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
2441 // if current offset doesn't reach the end
2446 FreePool (PciRegisterAccessData
);
2449 // continue checking access incompatibility
2451 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
2452 if (Status
== EFI_SUCCESS
) {
2453 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2454 AccessWidth
= PciRegisterAccessData
->Width
;
2459 FreePool (PciRegisterAccessData
);
2466 // AccessWidth incompatible check not supportted
2467 // or, there doesn't exist incompatibility on this operation
2469 if (PciRootBridgeIo
!= NULL
) {
2470 Status
= PciRootBridgeIo
->Pci
.Write (
2472 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
2478 Status
= PciIo
->Pci
.Write (
2480 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
2491 Abstract PCI device device information.
2493 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2494 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2495 @param Pci A pointer to PCI_TYPE00.
2496 @Param Address The address within the PCI configuration space for the PCI controller.
2497 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2499 @retval EFI_SUCCESS Pci device device information has been abstracted.
2504 GetPciDeviceDeviceInfo (
2505 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2506 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2507 IN PCI_TYPE00
*Pci
, OPTIONAL
2508 IN UINT64 Address
, OPTIONAL
2509 OUT EFI_PCI_DEVICE_INFO
*PciDeviceInfo
2514 UINT32 PciConfigData
;
2515 PCI_IO_DEVICE
*PciIoDevice
;
2517 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2519 if (PciIo
!= NULL
) {
2520 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
2523 // get pointer to PCI_TYPE00 from PciIoDevice
2525 Pci
= &PciIoDevice
->Pci
;
2530 // while PCI_TYPE00 hasn't been gotten, read PCI device device information directly
2532 PciAddress
= Address
& 0xffffffffffffff00ULL
;
2533 Status
= PciRootBridgeIo
->Pci
.Read (
2541 if (EFI_ERROR (Status
)) {
2545 if ((PciConfigData
& 0xffff) == 0xffff) {
2546 return EFI_NOT_FOUND
;
2549 PciDeviceInfo
->VendorID
= PciConfigData
& 0xffff;
2550 PciDeviceInfo
->DeviceID
= PciConfigData
>> 16;
2552 Status
= PciRootBridgeIo
->Pci
.Read (
2559 if (EFI_ERROR (Status
)) {
2563 PciDeviceInfo
->RevisionID
= PciConfigData
& 0xf;
2565 Status
= PciRootBridgeIo
->Pci
.Read (
2573 if (EFI_ERROR (Status
)) {
2577 PciDeviceInfo
->SubsystemVendorID
= PciConfigData
& 0xffff;
2578 PciDeviceInfo
->SubsystemID
= PciConfigData
>> 16;
2581 PciDeviceInfo
->VendorID
= Pci
->Hdr
.VendorId
;
2582 PciDeviceInfo
->DeviceID
= Pci
->Hdr
.DeviceId
;
2583 PciDeviceInfo
->RevisionID
= Pci
->Hdr
.RevisionID
;
2584 PciDeviceInfo
->SubsystemVendorID
= Pci
->Device
.SubsystemVendorID
;
2585 PciDeviceInfo
->SubsystemID
= Pci
->Device
.SubsystemID
;
2592 Read PCI configuration space with incompatibility check.
2594 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2595 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2596 @param Pci A pointer to PCI_TYPE00.
2597 @param Width Signifies the width of the memory operations.
2598 @Param Address The address within the PCI configuration space for the PCI controller.
2599 @param Buffer For read operations, the destination buffer to store the results. For
2600 write operations, the source buffer to write data from.
2602 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2603 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2604 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2605 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2610 PciIncompatibilityCheckRead (
2611 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2612 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2613 IN PCI_TYPE00
*Pci
, OPTIONAL
2621 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
2624 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2627 // get PCI device device information
2629 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
2630 if (Status
!= EFI_SUCCESS
) {
2634 Stride
= 1 << Width
;
2636 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*)Buffer
+ Stride
) {
2639 // read configuration register
2641 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, (UINT64
) Width
, Address
, Buffer
);
2643 if (Status
!= EFI_SUCCESS
) {
2648 // update the data read from configuration register
2650 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) {
2651 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_READ
, Width
, Address
& 0xff, Buffer
);
2659 Write PCI configuration space with incompatibility check.
2661 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2662 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2663 @param Pci A pointer to PCI_TYPE00.
2664 @param Width Signifies the width of the memory operations.
2665 @Param Address The address within the PCI configuration space for the PCI controller.
2666 @param Buffer For read operations, the destination buffer to store the results. For
2667 write operations, the source buffer to write data from.
2669 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2670 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2671 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2672 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2677 PciIncompatibilityCheckWrite (
2678 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2679 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2680 IN PCI_TYPE00
*Pci
, OPTIONAL
2688 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
2692 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2695 // get PCI device device information
2697 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
2698 if (Status
!= EFI_SUCCESS
) {
2702 Stride
= 1 << Width
;
2704 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*) Buffer
+ Stride
) {
2709 case EfiPciWidthUint8
:
2710 Data
= * (UINT8
*) Buffer
;
2712 case EfiPciWidthUint16
:
2713 Data
= * (UINT16
*) Buffer
;
2716 case EfiPciWidthUint32
:
2717 Data
= * (UINT32
*) Buffer
;
2721 return EFI_UNSUPPORTED
;
2725 // update the data writen into configuration register
2727 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) {
2728 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_WRITE
, Width
, Address
& 0xff, &Data
);
2732 // write configuration register
2734 Status
= WriteConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, Width
, Address
, &Data
);
2736 if (Status
!= EFI_SUCCESS
) {
2745 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2747 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2748 @param Pci A pointer to PCI_TYPE00.
2749 @param Width Signifies the width of the memory operations.
2750 @Param Address The address within the PCI configuration space for the PCI controller.
2751 @param Buffer For read operations, the destination buffer to store the results. For
2752 write operations, the source buffer to write data from.
2754 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2755 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2756 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2757 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2761 PciRootBridgeIoRead (
2762 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2763 IN PCI_TYPE00
*Pci
, OPTIONAL
2764 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2770 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) {
2772 // if PCI incompatibility check enabled
2774 return PciIncompatibilityCheckRead (
2784 return PciRootBridgeIo
->Pci
.Read (
2795 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2797 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2798 @param Pci A pointer to PCI_TYPE00.
2799 @param Width Signifies the width of the memory operations.
2800 @Param Address The address within the PCI configuration space for the PCI controller.
2801 @param Buffer For read operations, the destination buffer to store the results. For
2802 write operations, the source buffer to write data from.
2804 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2805 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2806 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2807 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2811 PciRootBridgeIoWrite (
2812 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2814 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2820 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) {
2822 // if PCI incompatibility check enabled
2824 return PciIncompatibilityCheckWrite (
2835 return PciRootBridgeIo
->Pci
.Write (
2846 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.
2848 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2849 @param Width Signifies the width of the memory operations.
2850 @Param Address The address within the PCI configuration space for the PCI controller.
2851 @param Buffer For read operations, the destination buffer to store the results. For
2852 write operations, the source buffer to write data from.
2854 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2855 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2856 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2857 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2862 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2863 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2869 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) {
2871 // if PCI incompatibility check enabled
2873 return PciIncompatibilityCheckRead (
2883 return PciIo
->Pci
.Read (
2894 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.
2896 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2897 @param Width Signifies the width of the memory operations.
2898 @Param Address The address within the PCI configuration space for the PCI controller.
2899 @param Buffer For read operations, the destination buffer to store the results. For
2900 write operations, the source buffer to write data from.
2902 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2903 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2904 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2905 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2910 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2911 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2917 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) {
2920 // if PCI incompatibility check enabled
2922 return PciIncompatibilityCheckWrite (
2933 return PciIo
->Pci
.Write (