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, 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 ResetAllPpbBusReg (Bridge
, StartBusNumber
);
1263 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1264 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1267 // Check to see whether a pci device is present
1269 Status
= PciDevicePresent (
1277 if (!EFI_ERROR (Status
) &&
1278 (IS_PCI_BRIDGE (&Pci
) ||
1279 IS_CARDBUS_BRIDGE (&Pci
))) {
1282 // Get the bridge information
1284 Status
= PciSearchDevice (
1293 if (EFI_ERROR (Status
)) {
1299 SecondBus
= (*SubBusNumber
);
1301 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1303 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1305 Status
= PciRootBridgeIoWrite (
1315 // Initialize SubBusNumber to SecondBus
1317 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1318 Status
= PciRootBridgeIoWrite (
1327 // If it is PPB, resursively search down this bridge
1329 if (IS_PCI_BRIDGE (&Pci
)) {
1331 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1332 // PCI configuration transaction to go through any PPB
1334 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1336 Status
= PciRootBridgeIoWrite (
1345 PreprocessController (
1347 PciDevice
->BusNumber
,
1348 PciDevice
->DeviceNumber
,
1349 PciDevice
->FunctionNumber
,
1350 EfiPciBeforeChildBusEnumeration
1353 Status
= PciScanBus (
1355 (UINT8
) (SecondBus
),
1360 if (EFI_ERROR (Status
)) {
1361 return EFI_DEVICE_ERROR
;
1366 // Set the current maximum bus number under the PPB
1369 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1371 Status
= PciRootBridgeIoWrite (
1382 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1385 // Skip sub functions, this is not a multi function device
1388 Func
= PCI_MAX_FUNC
;
1397 PciScanBus_WithHotPlugDeviceSupport (
1398 IN PCI_IO_DEVICE
*Bridge
,
1399 IN UINT8 StartBusNumber
,
1400 OUT UINT8
*SubBusNumber
,
1401 OUT UINT8
*PaddedBusRange
1405 Routine Description:
1407 This routine is used to assign bus number to the given PCI bus system
1411 Bridge - A pointer to the PCI_IO_DEVICE structure.
1412 StartBusNumber - The start bus number.
1413 SubBusNumber - A pointer to the sub bus number.
1414 PaddedBusRange - A pointer to the padded bus range.
1421 // TODO: EFI_DEVICE_ERROR - add return value to function comment
1422 // TODO: EFI_SUCCESS - add return value to function comment
1432 PCI_IO_DEVICE
*PciDevice
;
1434 EFI_HPC_STATE State
;
1436 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
1437 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1439 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1442 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1446 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
1449 ResetAllPpbBusReg (Bridge
, StartBusNumber
);
1451 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1452 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1455 // Check to see whether a pci device is present
1457 Status
= PciDevicePresent (
1465 if (EFI_ERROR (Status
)) {
1468 // Skip sub functions, this is not a multi function device
1470 Func
= PCI_MAX_FUNC
;
1477 // Get the PCI device information
1479 Status
= PciSearchDevice (
1488 ASSERT (!EFI_ERROR (Status
));
1490 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1492 if (!IS_PCI_BRIDGE (&Pci
)) {
1494 // PCI bridges will be called later
1495 // Here just need for PCI device or PCI to cardbus controller
1496 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1498 PreprocessController (
1500 PciDevice
->BusNumber
,
1501 PciDevice
->DeviceNumber
,
1502 PciDevice
->FunctionNumber
,
1503 EfiPciBeforeChildBusEnumeration
1508 // For Pci Hotplug controller devcie only
1510 if (gPciHotPlugInit
!= NULL
) {
1512 // Check if it is a Hotplug PCI controller
1514 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1516 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1518 Status
= CreateEventForHpc (HpIndex
, &Event
);
1520 ASSERT (!EFI_ERROR (Status
));
1522 Status
= gPciHotPlugInit
->InitializeRootHpc (
1524 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1530 PreprocessController (
1532 PciDevice
->BusNumber
,
1533 PciDevice
->DeviceNumber
,
1534 PciDevice
->FunctionNumber
,
1535 EfiPciBeforeChildBusEnumeration
1542 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1545 // Get the bridge information
1548 if (gPciHotPlugInit
!= NULL
) {
1550 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
1553 // If it is initialized, get the padded bus range
1555 Status
= gPciHotPlugInit
->GetResourcePadding (
1557 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
1560 (VOID
**) &Descriptors
,
1564 if (EFI_ERROR (Status
)) {
1569 Status
= PciGetBusRange (
1576 gBS
->FreePool (Descriptors
);
1578 if (EFI_ERROR (Status
)) {
1587 SecondBus
= *SubBusNumber
;
1589 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1590 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1592 Status
= PciRootBridgeIoWrite (
1603 // If it is PPB, resursively search down this bridge
1605 if (IS_PCI_BRIDGE (&Pci
)) {
1608 // Initialize SubBusNumber to Maximum bus number
1611 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1612 Status
= PciRootBridgeIoWrite (
1622 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1624 PreprocessController (
1626 PciDevice
->BusNumber
,
1627 PciDevice
->DeviceNumber
,
1628 PciDevice
->FunctionNumber
,
1629 EfiPciBeforeChildBusEnumeration
1632 Status
= PciScanBus (
1634 (UINT8
) (SecondBus
),
1639 if (EFI_ERROR (Status
)) {
1640 return EFI_DEVICE_ERROR
;
1646 // Ensure the device is enabled and initialized
1648 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1649 (State
& EFI_HPC_STATE_ENABLED
) &&
1650 (State
& EFI_HPC_STATE_INITIALIZED
) ) {
1651 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
1653 *SubBusNumber
= (UINT8
) ((UINT8
) (BusRange
) +*SubBusNumber
);
1658 // Set the current maximum bus number under the PPB
1660 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1662 Status
= PciRootBridgeIoWrite (
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 DestroyRootBridge (RootBridgeDev
);
1877 if (EFI_ERROR (Status
)) {
1883 // Notify the bus allocation phase is finished for the first time
1885 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1887 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1889 if (gPciHotPlugInit
!= NULL
) {
1891 // Wait for all HPC initialized
1893 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1895 if (EFI_ERROR (Status
)) {
1900 // Notify the bus allocation phase is about to start for the 2nd time
1902 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1904 RootBridgeHandle
= NULL
;
1905 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1908 // if a root bridge instance is found, create root bridge device for it
1911 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1913 if (RootBridgeDev
== NULL
) {
1914 return EFI_OUT_OF_RESOURCES
;
1918 // Enumerate all the buses under this root bridge
1921 Status
= PciRootBridgeEnumerator (
1926 DestroyRootBridge (RootBridgeDev
);
1927 if (EFI_ERROR (Status
)) {
1933 // Notify the bus allocation phase is to end for the 2nd time
1935 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1940 // Notify the resource allocation phase is to start
1942 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1944 RootBridgeHandle
= NULL
;
1945 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1948 // if a root bridge instance is found, create root bridge device for it
1951 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1953 if (RootBridgeDev
== NULL
) {
1954 return EFI_OUT_OF_RESOURCES
;
1957 Status
= StartManagingRootBridge (RootBridgeDev
);
1959 if (EFI_ERROR (Status
)) {
1963 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1964 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1966 if (EFI_ERROR (Status
)) {
1970 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1972 if (EFI_ERROR (Status
)) {
1977 // Determine root bridge attribute by calling interface of Pcihostbridge
1980 DetermineRootBridgeAttributes (
1986 // Collect all the resource information under this root bridge
1987 // A database that records all the information about pci device subject to this
1988 // root bridge will then be created
1990 Status
= PciPciDeviceInfoCollector (
1995 if (EFI_ERROR (Status
)) {
1999 InsertRootBridge (RootBridgeDev
);
2002 // Record the hostbridge handle
2004 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);
2011 Read PCI device configuration register by specified address.
2013 This function check the incompatiblilites on PCI device. Return the register
2016 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2017 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2018 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2019 @param Width Signifies the width of the memory operations.
2020 @Param Address The address within the PCI configuration space for the PCI controller.
2021 @param Buffer For read operations, the destination buffer to store the results. For
2022 write operations, the source buffer to write data from.
2024 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2025 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2026 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2027 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2033 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2034 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2035 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2043 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
2044 UINT64 AccessAddress
;
2049 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2051 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) {
2053 // check access compatibility at first time
2055 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, Address
& 0xff, Width
, &PciRegisterAccessData
);
2057 if (Status
== EFI_SUCCESS
) {
2059 // there exist incompatibility on this operation
2061 AccessWidth
= Width
;
2063 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2064 AccessWidth
= PciRegisterAccessData
->Width
;
2067 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
2071 Pointer
= (UINT8
*) &TempBuffer
;
2075 if (PciRootBridgeIo
!= NULL
) {
2076 Status
= PciRootBridgeIo
->Pci
.Read (
2078 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
2083 } else if (PciIo
!= NULL
) {
2084 Status
= PciIo
->Pci
.Read (
2086 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
2087 (UINT32
) AccessAddress
,
2093 if (Status
!= EFI_SUCCESS
) {
2097 Stride
= 1 << AccessWidth
;
2098 AccessAddress
+= Stride
;
2099 if (AccessAddress
>= (Address
+ (1 << Width
))) {
2101 // if all datas have been read, exist
2108 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
2110 // if current offset doesn't reach the end
2115 FreePool (PciRegisterAccessData
);
2118 // continue checking access incompatibility
2120 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
2121 if (Status
== EFI_SUCCESS
) {
2122 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2123 AccessWidth
= PciRegisterAccessData
->Width
;
2128 FreePool (PciRegisterAccessData
);
2131 case EfiPciWidthUint8
:
2132 * (UINT8
*) Buffer
= (UINT8
) TempBuffer
;
2134 case EfiPciWidthUint16
:
2135 * (UINT16
*) Buffer
= (UINT16
) TempBuffer
;
2137 case EfiPciWidthUint32
:
2138 * (UINT32
*) Buffer
= (UINT32
) TempBuffer
;
2141 return EFI_UNSUPPORTED
;
2148 // AccessWidth incompatible check not supportted
2149 // or, there doesn't exist incompatibility on this operation
2151 if (PciRootBridgeIo
!= NULL
) {
2152 Status
= PciRootBridgeIo
->Pci
.Read (
2154 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
2161 Status
= PciIo
->Pci
.Read (
2163 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
2174 Update register value by checking PCI device incompatibility.
2176 This function check register value incompatibilites on PCI device. Return the register
2179 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2180 @param AccessType Access type, READ or WRITE.
2181 @Param Address The address within the PCI configuration space.
2182 @param Buffer Store the register data.
2184 @retval EFI_SUCCESS The data has been updated.
2190 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2191 IN UINT64 AccessType
,
2198 EFI_PCI_REGISTER_VALUE_DATA
*PciRegisterData
;
2204 // check register value incompatibility
2206 Status
= PciRegisterUpdateCheck (PciDeviceInfo
, AccessType
, Address
& 0xff, &PciRegisterData
);
2208 if (Status
== EFI_SUCCESS
) {
2210 AndValue
= ((UINT32
) PciRegisterData
->AndValue
) >> (((UINT8
) Address
& 0x3) * 8);
2211 OrValue
= ((UINT32
) PciRegisterData
->OrValue
) >> (((UINT8
) Address
& 0x3) * 8);
2213 TempValue
= * (UINT32
*) Buffer
;
2214 if (PciRegisterData
->AndValue
!= VALUE_NOCARE
) {
2215 TempValue
&= AndValue
;
2217 if (PciRegisterData
->OrValue
!= VALUE_NOCARE
) {
2218 TempValue
|= OrValue
;
2222 case EfiPciWidthUint8
:
2223 *(UINT8
*)Buffer
= (UINT8
) TempValue
;
2226 case EfiPciWidthUint16
:
2227 *(UINT16
*)Buffer
= (UINT16
) TempValue
;
2229 case EfiPciWidthUint32
:
2230 *(UINT32
*)Buffer
= TempValue
;
2234 return EFI_UNSUPPORTED
;
2237 FreePool (PciRegisterData
);
2244 Write PCI device configuration register by specified address.
2246 This function check the incompatiblilites on PCI device, and write date
2249 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2250 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2251 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2252 @param Width Signifies the width of the memory operations.
2253 @Param Address The address within the PCI configuration space for the PCI controller.
2254 @param Buffer For read operations, the destination buffer to store the results. For
2255 write operations, the source buffer to write data from.
2257 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2258 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2259 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2260 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2266 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2267 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2268 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2276 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
2277 UINT64 AccessAddress
;
2283 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2285 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) {
2287 // check access compatibility at first time
2289 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, Address
& 0xff, Width
, &PciRegisterAccessData
);
2291 if (Status
== EFI_SUCCESS
) {
2293 // there exist incompatibility on this operation
2295 AccessWidth
= Width
;
2297 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2298 AccessWidth
= PciRegisterAccessData
->Width
;
2301 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
2304 Pointer
= (UINT8
*) &Buffer
;
2305 Data
= * (UINT64
*) Buffer
;
2309 if (AccessWidth
> Width
) {
2311 // if actual access width is larger than orignal one, additional data need to be read back firstly
2313 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, PciDeviceInfo
, AccessWidth
, AccessAddress
, &Data
);
2314 if (Status
!= EFI_SUCCESS
) {
2319 // check data read incompatibility
2321 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_READ
, AccessWidth
, AccessAddress
& 0xff, &Data
);
2323 Shift
= (UINTN
)(Address
- AccessAddress
) * 8;
2325 case EfiPciWidthUint8
:
2326 Data
= (* (UINT8
*) Buffer
) << Shift
| (Data
& ~(0xff << Shift
));
2329 case EfiPciWidthUint16
:
2330 Data
= (* (UINT16
*) Buffer
) << Shift
| (Data
& ~(0xffff << Shift
));
2335 // check data write incompatibility
2337 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessWidth
, MultU64x32 (AccessAddress
, 0xff), &Data
);
2340 if (PciRootBridgeIo
!= NULL
) {
2341 Status
= PciRootBridgeIo
->Pci
.Write (
2343 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
2349 Status
= PciIo
->Pci
.Write (
2351 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
2352 (UINT32
) AccessAddress
,
2358 if (Status
!= EFI_SUCCESS
) {
2362 Data
= RShiftU64 (Data
, ((1 << AccessWidth
) * 8));
2364 Stride
= 1 << AccessWidth
;
2365 AccessAddress
+= Stride
;
2366 if (AccessAddress
>= (Address
+ (1 << Width
))) {
2368 // if all datas have been written, exist
2375 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
2377 // if current offset doesn't reach the end
2382 FreePool (PciRegisterAccessData
);
2385 // continue checking access incompatibility
2387 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
2388 if (Status
== EFI_SUCCESS
) {
2389 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2390 AccessWidth
= PciRegisterAccessData
->Width
;
2395 FreePool (PciRegisterAccessData
);
2402 // AccessWidth incompatible check not supportted
2403 // or, there doesn't exist incompatibility on this operation
2405 if (PciRootBridgeIo
!= NULL
) {
2406 Status
= PciRootBridgeIo
->Pci
.Write (
2408 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
2414 Status
= PciIo
->Pci
.Write (
2416 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
2427 Abstract PCI device device information.
2429 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2430 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2431 @param Pci A pointer to PCI_TYPE00.
2432 @Param Address The address within the PCI configuration space for the PCI controller.
2433 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2435 @retval EFI_SUCCESS Pci device device information has been abstracted.
2440 GetPciDeviceDeviceInfo (
2441 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2442 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2443 IN PCI_TYPE00
*Pci
, OPTIONAL
2444 IN UINT64 Address
, OPTIONAL
2445 OUT EFI_PCI_DEVICE_INFO
*PciDeviceInfo
2450 UINT32 PciConfigData
;
2451 PCI_IO_DEVICE
*PciIoDevice
;
2453 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2455 if (PciIo
!= NULL
) {
2456 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
2459 // get pointer to PCI_TYPE00 from PciIoDevice
2461 Pci
= &PciIoDevice
->Pci
;
2466 // while PCI_TYPE00 hasn't been gotten, read PCI device device information directly
2468 PciAddress
= Address
& 0xffffffffffffff00ULL
;
2469 Status
= PciRootBridgeIo
->Pci
.Read (
2477 if (EFI_ERROR (Status
)) {
2481 if ((PciConfigData
& 0xffff) == 0xffff) {
2482 return EFI_NOT_FOUND
;
2485 PciDeviceInfo
->VendorID
= PciConfigData
& 0xffff;
2486 PciDeviceInfo
->DeviceID
= PciConfigData
>> 16;
2488 Status
= PciRootBridgeIo
->Pci
.Read (
2495 if (EFI_ERROR (Status
)) {
2499 PciDeviceInfo
->RevisionID
= PciConfigData
& 0xf;
2501 Status
= PciRootBridgeIo
->Pci
.Read (
2509 if (EFI_ERROR (Status
)) {
2513 PciDeviceInfo
->SubsystemVendorID
= PciConfigData
& 0xffff;
2514 PciDeviceInfo
->SubsystemID
= PciConfigData
>> 16;
2517 PciDeviceInfo
->VendorID
= Pci
->Hdr
.VendorId
;
2518 PciDeviceInfo
->DeviceID
= Pci
->Hdr
.DeviceId
;
2519 PciDeviceInfo
->RevisionID
= Pci
->Hdr
.RevisionID
;
2520 PciDeviceInfo
->SubsystemVendorID
= Pci
->Device
.SubsystemVendorID
;
2521 PciDeviceInfo
->SubsystemID
= Pci
->Device
.SubsystemID
;
2528 Read PCI configuration space with incompatibility check.
2530 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2531 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2532 @param Pci A pointer to PCI_TYPE00.
2533 @param Width Signifies the width of the memory operations.
2534 @Param Address The address within the PCI configuration space for the PCI controller.
2535 @param Buffer For read operations, the destination buffer to store the results. For
2536 write operations, the source buffer to write data from.
2538 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2539 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2540 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2541 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2546 PciIncompatibilityCheckRead (
2547 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2548 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2549 IN PCI_TYPE00
*Pci
, OPTIONAL
2557 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
2560 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2563 // get PCI device device information
2565 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
2566 if (Status
!= EFI_SUCCESS
) {
2570 Stride
= 1 << Width
;
2572 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*)Buffer
+ Stride
) {
2575 // read configuration register
2577 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, (UINT64
) Width
, Address
, Buffer
);
2579 if (Status
!= EFI_SUCCESS
) {
2584 // update the data read from configuration register
2586 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) {
2587 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_READ
, Width
, Address
& 0xff, Buffer
);
2595 Write PCI configuration space with incompatibility check.
2597 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2598 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2599 @param Pci A pointer to PCI_TYPE00.
2600 @param Width Signifies the width of the memory operations.
2601 @Param Address The address within the PCI configuration space for the PCI controller.
2602 @param Buffer For read operations, the destination buffer to store the results. For
2603 write operations, the source buffer to write data from.
2605 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2606 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2607 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2608 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2613 PciIncompatibilityCheckWrite (
2614 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2615 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2616 IN PCI_TYPE00
*Pci
, OPTIONAL
2624 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
2628 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2631 // get PCI device device information
2633 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
2634 if (Status
!= EFI_SUCCESS
) {
2638 Stride
= 1 << Width
;
2640 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*) Buffer
+ Stride
) {
2645 case EfiPciWidthUint8
:
2646 Data
= * (UINT8
*) Buffer
;
2648 case EfiPciWidthUint16
:
2649 Data
= * (UINT16
*) Buffer
;
2652 case EfiPciWidthUint32
:
2653 Data
= * (UINT32
*) Buffer
;
2657 return EFI_UNSUPPORTED
;
2661 // update the data writen into configuration register
2663 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) {
2664 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_WRITE
, Width
, Address
& 0xff, &Data
);
2668 // write configuration register
2670 Status
= WriteConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, Width
, Address
, &Data
);
2672 if (Status
!= EFI_SUCCESS
) {
2681 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2683 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2684 @param Pci A pointer to PCI_TYPE00.
2685 @param Width Signifies the width of the memory operations.
2686 @Param Address The address within the PCI configuration space for the PCI controller.
2687 @param Buffer For read operations, the destination buffer to store the results. For
2688 write operations, the source buffer to write data from.
2690 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2691 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2692 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2693 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2697 PciRootBridgeIoRead (
2698 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2699 IN PCI_TYPE00
*Pci
, OPTIONAL
2700 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2706 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) {
2708 // if PCI incompatibility check enabled
2710 return PciIncompatibilityCheckRead (
2720 return PciRootBridgeIo
->Pci
.Read (
2731 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2733 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2734 @param Pci A pointer to PCI_TYPE00.
2735 @param Width Signifies the width of the memory operations.
2736 @Param Address The address within the PCI configuration space for the PCI controller.
2737 @param Buffer For read operations, the destination buffer to store the results. For
2738 write operations, the source buffer to write data from.
2740 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2741 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2742 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2743 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2747 PciRootBridgeIoWrite (
2748 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2750 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2756 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) {
2758 // if PCI incompatibility check enabled
2760 return PciIncompatibilityCheckWrite (
2771 return PciRootBridgeIo
->Pci
.Write (
2782 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.
2784 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2785 @param Width Signifies the width of the memory operations.
2786 @Param Address The address within the PCI configuration space for the PCI controller.
2787 @param Buffer For read operations, the destination buffer to store the results. For
2788 write operations, the source buffer to write data from.
2790 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2791 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2792 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2793 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2798 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2799 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2805 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) {
2807 // if PCI incompatibility check enabled
2809 return PciIncompatibilityCheckRead (
2819 return PciIo
->Pci
.Read (
2830 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.
2832 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2833 @param Width Signifies the width of the memory operations.
2834 @Param Address The address within the PCI configuration space for the PCI controller.
2835 @param Buffer For read operations, the destination buffer to store the results. For
2836 write operations, the source buffer to write data from.
2838 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2839 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2840 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2841 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2846 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2847 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2853 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) {
2856 // if PCI incompatibility check enabled
2858 return PciIncompatibilityCheckWrite (
2869 return PciIo
->Pci
.Write (