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
25 Install protocol gEfiPciHotPlugRequestProtocolGuid
26 @param Status return status of protocol installation.
29 InstallHotPlugRequestProtocol (
35 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
40 *Status
= gBS
->InstallProtocolInterface (
42 &gEfiPciHotPlugRequestProtocolGuid
,
49 Install protocol gEfiPciHotplugDeviceGuid into hotplug device
52 @param PciIoDevice hotplug device instance
56 InstallPciHotplugGuid (
57 IN PCI_IO_DEVICE
*PciIoDevice
62 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
66 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Parent
->Pci
)) {
68 Status
= gBS
->InstallProtocolInterface (
70 &gEfiPciHotplugDeviceGuid
,
74 ASSERT_EFI_ERROR (Status
);
79 UnInstall protocol gEfiPciHotplugDeviceGuid into hotplug device
82 @param PciIoDevice hotplug device instance
86 UninstallPciHotplugGuid (
87 IN PCI_IO_DEVICE
*PciIoDevice
92 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
96 Status
= gBS
->OpenProtocol (
98 &gEfiPciHotplugDeviceGuid
,
102 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
105 if (Status
== EFI_SUCCESS
) {
107 // This may triger CardBus driver to stop for
108 // Pccard devices opened the GUID via BY_DRIVER
110 Status
= gBS
->UninstallProtocolInterface (
112 &gEfiPciHotplugDeviceGuid
,
119 Retrieve the BAR information via PciIo interface
121 @param PciIoDevice Pci device instance
125 IN PCI_IO_DEVICE
*PciIoDevice
130 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
135 // Read PciBar information from the bar register
137 if (!gFullEnumeration
) {
141 &(PciIoDevice
->PciIo
),
148 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BaseAddress
= (UINT64
) (Address
);
149 (PciIoDevice
->PciBar
)[P2C_MEM_1
].Length
= 0x2000000;
150 (PciIoDevice
->PciBar
)[P2C_MEM_1
].BarType
= PciBarTypeMem32
;
154 &(PciIoDevice
->PciIo
),
160 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BaseAddress
= (UINT64
) (Address
);
161 (PciIoDevice
->PciBar
)[P2C_MEM_2
].Length
= 0x2000000;
162 (PciIoDevice
->PciBar
)[P2C_MEM_2
].BarType
= PciBarTypePMem32
;
166 &(PciIoDevice
->PciIo
),
172 (PciIoDevice
->PciBar
)[P2C_IO_1
].BaseAddress
= (UINT64
) (Address
);
173 (PciIoDevice
->PciBar
)[P2C_IO_1
].Length
= 0x100;
174 (PciIoDevice
->PciBar
)[P2C_IO_1
].BarType
= PciBarTypeIo16
;
178 &(PciIoDevice
->PciIo
),
184 (PciIoDevice
->PciBar
)[P2C_IO_2
].BaseAddress
= (UINT64
) (Address
);
185 (PciIoDevice
->PciBar
)[P2C_IO_2
].Length
= 0x100;
186 (PciIoDevice
->PciBar
)[P2C_IO_2
].BarType
= PciBarTypeIo16
;
190 if (gPciHotPlugInit
!= NULL
) {
191 GetResourcePaddingForHpb (PciIoDevice
);
196 Remove rejected pci device from specific root bridge
199 @param RootBridgeHandle specific parent root bridge handle
200 @param Bridge Bridge device instance
202 @retval EFI_SUCCESS Success operation.
205 RemoveRejectedPciDevices (
206 EFI_HANDLE RootBridgeHandle
,
207 IN PCI_IO_DEVICE
*Bridge
211 LIST_ENTRY
*CurrentLink
;
212 LIST_ENTRY
*LastLink
;
214 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
218 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
220 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
222 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
224 if (IS_PCI_BRIDGE (&Temp
->Pci
)) {
226 // Remove rejected devices recusively
228 RemoveRejectedPciDevices (RootBridgeHandle
, Temp
);
231 // Skip rejection for all PPBs, while detect rejection for others
233 if (IsPciDeviceRejected (Temp
)) {
236 // For P2C, remove all devices on it
239 if (!IsListEmpty (&Temp
->ChildList
)) {
240 RemoveAllPciDeviceOnBridge (RootBridgeHandle
, Temp
);
244 // Finally remove itself
247 LastLink
= CurrentLink
->BackLink
;
248 RemoveEntryList (CurrentLink
);
249 FreePciDevice (Temp
);
251 CurrentLink
= LastLink
;
255 CurrentLink
= CurrentLink
->ForwardLink
;
262 Wrapper function for allocating resource for pci host bridge.
264 @param PciResAlloc Point to protocol instance EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
268 PciHostBridgeResourceAllocator (
269 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
272 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
273 return PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
277 return PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
284 Submits the I/O and memory resource requirements for the specified PCI Root Bridge
286 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
288 @retval EFI_SUCCESS Success
291 PciHostBridgeResourceAllocator_WithoutHotPlugDeviceSupport (
292 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
295 PCI_IO_DEVICE
*RootBridgeDev
;
296 EFI_HANDLE RootBridgeHandle
;
304 UINT64 MaxOptionRomSize
;
305 PCI_RESOURCE_NODE
*IoBridge
;
306 PCI_RESOURCE_NODE
*Mem32Bridge
;
307 PCI_RESOURCE_NODE
*PMem32Bridge
;
308 PCI_RESOURCE_NODE
*Mem64Bridge
;
309 PCI_RESOURCE_NODE
*PMem64Bridge
;
310 PCI_RESOURCE_NODE IoPool
;
311 PCI_RESOURCE_NODE Mem32Pool
;
312 PCI_RESOURCE_NODE PMem32Pool
;
313 PCI_RESOURCE_NODE Mem64Pool
;
314 PCI_RESOURCE_NODE PMem64Pool
;
315 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD ExtendedData
;
318 // Initialize resource pool
321 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
322 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
323 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
324 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
325 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
327 RootBridgeDev
= NULL
;
328 RootBridgeHandle
= 0;
330 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
332 // Get RootBridg Device by handle
334 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
336 if (RootBridgeDev
== NULL
) {
337 return EFI_NOT_FOUND
;
341 // Get host bridge handle for status report
343 ExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
346 // Create the entire system resource map from the information collected by
347 // enumerator. Several resource tree was created
350 IoBridge
= CreateResourceNode (
359 Mem32Bridge
= CreateResourceNode (
368 PMem32Bridge
= CreateResourceNode (
377 Mem64Bridge
= CreateResourceNode (
386 PMem64Bridge
= CreateResourceNode (
396 // Create resourcemap by going through all the devices subject to this root bridge
398 Status
= CreateResourceMap (
408 // Get the max ROM size that the root bridge can process
410 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
413 // Get Max Option Rom size for current root bridge
415 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
418 // Enlarger the mem32 resource to accomdate the option rom
419 // if the mem32 resource is not enough to hold the rom
421 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
423 Mem32Bridge
->Length
= MaxOptionRomSize
;
424 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
427 // Alignment should be adjusted as well
429 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
430 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
435 // Based on the all the resource tree, contruct ACPI resource node to
436 // submit the resource aperture to pci host bridge protocol
438 Status
= ConstructAcpiResourceRequestor (
449 // Insert these resource nodes into the database
451 InsertResourceNode (&IoPool
, IoBridge
);
452 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
453 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
454 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
455 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
457 if (Status
== EFI_SUCCESS
) {
459 // Submit the resource requirement
461 Status
= PciResAlloc
->SubmitResources (
463 RootBridgeDev
->Handle
,
468 // Free acpi resource node
470 if (AcpiConfig
!= NULL
) {
471 FreePool (AcpiConfig
);
474 if (EFI_ERROR (Status
)) {
476 // Destroy all the resource tree
478 DestroyResourceTree (&IoPool
);
479 DestroyResourceTree (&Mem32Pool
);
480 DestroyResourceTree (&PMem32Pool
);
481 DestroyResourceTree (&Mem64Pool
);
482 DestroyResourceTree (&PMem64Pool
);
491 // Notify pci bus driver starts to program the resource
493 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
495 if (EFI_ERROR (Status
)) {
497 // Allocation failed, then return
499 return EFI_OUT_OF_RESOURCES
;
502 // Raise the EFI_IOB_PCI_RES_ALLOC status code
504 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
506 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
507 (VOID
*) &ExtendedData
,
508 sizeof (ExtendedData
)
512 // Notify pci bus driver starts to program the resource
514 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
516 RootBridgeDev
= NULL
;
518 RootBridgeHandle
= 0;
520 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
522 // Get RootBridg Device by handle
524 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
526 if (RootBridgeDev
== NULL
) {
527 return EFI_NOT_FOUND
;
531 // Get acpi resource node for all the resource types
534 Status
= PciResAlloc
->GetProposedResources (
536 RootBridgeDev
->Handle
,
540 if (EFI_ERROR (Status
)) {
545 // Get the resource base by interpreting acpi resource node
558 // Process option rom for this root bridge
560 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
563 // Create the entire system resource map from the information collected by
564 // enumerator. Several resource tree was created
566 Status
= GetResourceMap (
580 if (EFI_ERROR (Status
)) {
585 // Program IO resources
593 // Program Mem32 resources
601 // Program PMem32 resources
609 // Program Mem64 resources
617 // Program PMem64 resources
624 if (AcpiConfig
!= NULL
) {
625 FreePool (AcpiConfig
);
630 // Destroy all the resource tree
632 DestroyResourceTree (&IoPool
);
633 DestroyResourceTree (&Mem32Pool
);
634 DestroyResourceTree (&PMem32Pool
);
635 DestroyResourceTree (&Mem64Pool
);
636 DestroyResourceTree (&PMem64Pool
);
639 // Notify the resource allocation phase is to end
641 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
647 Submits the I/O and memory resource requirements for the specified PCI Root Bridge
649 @param PciResAlloc Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
651 @retval EFI_SUCCESS Success
655 PciHostBridgeResourceAllocator_WithHotPlugDeviceSupport (
656 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
659 PCI_IO_DEVICE
*RootBridgeDev
;
660 EFI_HANDLE RootBridgeHandle
;
669 UINT64 Mem32ResStatus
;
670 UINT64 PMem32ResStatus
;
671 UINT64 Mem64ResStatus
;
672 UINT64 PMem64ResStatus
;
673 UINT64 MaxOptionRomSize
;
674 PCI_RESOURCE_NODE
*IoBridge
;
675 PCI_RESOURCE_NODE
*Mem32Bridge
;
676 PCI_RESOURCE_NODE
*PMem32Bridge
;
677 PCI_RESOURCE_NODE
*Mem64Bridge
;
678 PCI_RESOURCE_NODE
*PMem64Bridge
;
679 PCI_RESOURCE_NODE IoPool
;
680 PCI_RESOURCE_NODE Mem32Pool
;
681 PCI_RESOURCE_NODE PMem32Pool
;
682 PCI_RESOURCE_NODE Mem64Pool
;
683 PCI_RESOURCE_NODE PMem64Pool
;
685 EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD HandleExtendedData
;
686 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData
;
694 // It will try several times if the resource allocation fails
699 // Initialize resource pool
701 InitializeResourcePool (&IoPool
, PciBarTypeIo16
);
702 InitializeResourcePool (&Mem32Pool
, PciBarTypeMem32
);
703 InitializeResourcePool (&PMem32Pool
, PciBarTypePMem32
);
704 InitializeResourcePool (&Mem64Pool
, PciBarTypeMem64
);
705 InitializeResourcePool (&PMem64Pool
, PciBarTypePMem64
);
707 RootBridgeDev
= NULL
;
708 RootBridgeHandle
= 0;
710 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
713 // Get RootBridg Device by handle
715 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
717 if (RootBridgeDev
== NULL
) {
718 return EFI_NOT_FOUND
;
722 // Create the entire system resource map from the information collected by
723 // enumerator. Several resource tree was created
726 IoBridge
= CreateResourceNode (
735 Mem32Bridge
= CreateResourceNode (
744 PMem32Bridge
= CreateResourceNode (
753 Mem64Bridge
= CreateResourceNode (
762 PMem64Bridge
= CreateResourceNode (
772 // Create resourcemap by going through all the devices subject to this root bridge
774 Status
= CreateResourceMap (
784 // Get the max ROM size that the root bridge can process
786 RootBridgeDev
->RomSize
= Mem32Bridge
->Length
;
789 // Skip to enlarge the resource request during realloction
793 // Get Max Option Rom size for current root bridge
795 MaxOptionRomSize
= GetMaxOptionRomSize (RootBridgeDev
);
798 // Enlarger the mem32 resource to accomdate the option rom
799 // if the mem32 resource is not enough to hold the rom
801 if (MaxOptionRomSize
> Mem32Bridge
->Length
) {
803 Mem32Bridge
->Length
= MaxOptionRomSize
;
804 RootBridgeDev
->RomSize
= MaxOptionRomSize
;
807 // Alignment should be adjusted as well
809 if (Mem32Bridge
->Alignment
< MaxOptionRomSize
- 1) {
810 Mem32Bridge
->Alignment
= MaxOptionRomSize
- 1;
816 // Based on the all the resource tree, contruct ACPI resource node to
817 // submit the resource aperture to pci host bridge protocol
819 Status
= ConstructAcpiResourceRequestor (
830 // Insert these resource nodes into the database
832 InsertResourceNode (&IoPool
, IoBridge
);
833 InsertResourceNode (&Mem32Pool
, Mem32Bridge
);
834 InsertResourceNode (&PMem32Pool
, PMem32Bridge
);
835 InsertResourceNode (&Mem64Pool
, Mem64Bridge
);
836 InsertResourceNode (&PMem64Pool
, PMem64Bridge
);
838 if (Status
== EFI_SUCCESS
) {
840 // Submit the resource requirement
842 Status
= PciResAlloc
->SubmitResources (
844 RootBridgeDev
->Handle
,
850 // Free acpi resource node
852 if (AcpiConfig
!= NULL
) {
853 FreePool (AcpiConfig
);
856 if (EFI_ERROR (Status
)) {
858 // Destroy all the resource tree
860 DestroyResourceTree (&IoPool
);
861 DestroyResourceTree (&Mem32Pool
);
862 DestroyResourceTree (&PMem32Pool
);
863 DestroyResourceTree (&Mem64Pool
);
864 DestroyResourceTree (&PMem64Pool
);
870 // Notify pci bus driver starts to program the resource
873 Status
= NotifyPhase (PciResAlloc
, EfiPciHostBridgeAllocateResources
);
875 if (!EFI_ERROR (Status
)) {
877 // Allocation succeed, then continue the following
883 // If the resource allocation is unsuccessful, free resources on bridge
886 RootBridgeDev
= NULL
;
887 RootBridgeHandle
= 0;
889 IoResStatus
= EFI_RESOURCE_SATISFIED
;
890 Mem32ResStatus
= EFI_RESOURCE_SATISFIED
;
891 PMem32ResStatus
= EFI_RESOURCE_SATISFIED
;
892 Mem64ResStatus
= EFI_RESOURCE_SATISFIED
;
893 PMem64ResStatus
= EFI_RESOURCE_SATISFIED
;
895 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
897 // Get RootBridg Device by handle
899 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
900 if (RootBridgeDev
== NULL
) {
901 return EFI_NOT_FOUND
;
905 // Get host bridge handle for status report
907 HandleExtendedData
.Handle
= RootBridgeDev
->PciRootBridgeIo
->ParentHandle
;
910 // Get acpi resource node for all the resource types
914 Status
= PciResAlloc
->GetProposedResources (
916 RootBridgeDev
->Handle
,
920 if (EFI_ERROR (Status
)) {
924 if (AcpiConfig
!= NULL
) {
926 // Adjust resource allocation policy for each RB
928 GetResourceAllocationStatus (
936 FreePool (AcpiConfig
);
944 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
947 // It is very difficult to follow the spec here
948 // Device path , Bar index can not be get here
950 ZeroMem (&AllocFailExtendedData
, sizeof (AllocFailExtendedData
));
952 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
954 EFI_IO_BUS_PCI
| EFI_IOB_EC_RESOURCE_CONFLICT
,
955 (VOID
*) &AllocFailExtendedData
,
956 sizeof (AllocFailExtendedData
)
959 Status
= PciHostBridgeAdjustAllocation (
973 // Destroy all the resource tree
975 DestroyResourceTree (&IoPool
);
976 DestroyResourceTree (&Mem32Pool
);
977 DestroyResourceTree (&PMem32Pool
);
978 DestroyResourceTree (&Mem64Pool
);
979 DestroyResourceTree (&PMem64Pool
);
981 NotifyPhase (PciResAlloc
, EfiPciHostBridgeFreeResources
);
983 if (EFI_ERROR (Status
)) {
995 // Raise the EFI_IOB_PCI_RES_ALLOC status code
997 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
999 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_RES_ALLOC
,
1000 (VOID
*) &HandleExtendedData
,
1001 sizeof (HandleExtendedData
)
1005 // Notify pci bus driver starts to program the resource
1007 NotifyPhase (PciResAlloc
, EfiPciHostBridgeSetResources
);
1009 RootBridgeDev
= NULL
;
1011 RootBridgeHandle
= 0;
1013 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1016 // Get RootBridg Device by handle
1018 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1020 if (RootBridgeDev
== NULL
) {
1021 return EFI_NOT_FOUND
;
1025 // Get acpi resource node for all the resource types
1028 Status
= PciResAlloc
->GetProposedResources (
1030 RootBridgeDev
->Handle
,
1034 if (EFI_ERROR (Status
)) {
1039 // Get the resource base by interpreting acpi resource node
1052 // Process option rom for this root bridge
1054 Status
= ProcessOptionRom (RootBridgeDev
, Mem32Base
, RootBridgeDev
->RomSize
);
1057 // Create the entire system resource map from the information collected by
1058 // enumerator. Several resource tree was created
1060 Status
= GetResourceMap (
1074 if (EFI_ERROR (Status
)) {
1079 // Program IO resources
1087 // Program Mem32 resources
1095 // Program PMem32 resources
1103 // Program Mem64 resources
1111 // Program PMem64 resources
1118 if (AcpiConfig
!= NULL
) {
1119 gBS
->FreePool (AcpiConfig
);
1124 // Destroy all the resource tree
1126 DestroyResourceTree (&IoPool
);
1127 DestroyResourceTree (&Mem32Pool
);
1128 DestroyResourceTree (&PMem32Pool
);
1129 DestroyResourceTree (&Mem64Pool
);
1130 DestroyResourceTree (&PMem64Pool
);
1133 // Notify the resource allocation phase is to end
1135 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndResourceAllocation
);
1141 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1142 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug
1144 @param Bridge Bridge device instance
1145 @param StartBusNumber start point
1146 @param SubBusNumber Point to sub bus number
1147 @param PaddedBusRange Customized bus number
1149 @retval EFI_SUCCESS Success
1150 @retval EFI_DEVICE_ERROR Fail to scan bus
1154 IN PCI_IO_DEVICE
*Bridge
,
1155 IN UINT8 StartBusNumber
,
1156 OUT UINT8
*SubBusNumber
,
1157 OUT UINT8
*PaddedBusRange
1160 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1161 return PciScanBus_WithHotPlugDeviceSupport (
1168 return PciScanBus_WithoutHotPlugDeviceSupport (
1178 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1179 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug
1181 @param Bridge Bridge device instance
1182 @param StartBusNumber start point
1183 @param SubBusNumber Point to sub bus number
1184 @param PaddedBusRange Customized bus number
1186 @retval EFI_SUCCESS Success
1187 @retval EFI_DEVICE_ERROR Fail to scan bus
1190 PciScanBus_WithoutHotPlugDeviceSupport (
1191 IN PCI_IO_DEVICE
*Bridge
,
1192 IN UINT8 StartBusNumber
,
1193 OUT UINT8
*SubBusNumber
,
1194 OUT UINT8
*PaddedBusRange
1204 PCI_IO_DEVICE
*PciDevice
;
1205 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1207 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1211 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1212 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1215 // Check to see whether a pci device is present
1217 Status
= PciDevicePresent (
1225 if (!EFI_ERROR (Status
)) {
1226 DEBUG((EFI_D_ERROR
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
1228 if (IS_PCI_BRIDGE (&Pci
) ||
1229 IS_CARDBUS_BRIDGE (&Pci
)) {
1232 // Get the bridge information
1234 Status
= PciSearchDevice (
1243 if (EFI_ERROR (Status
)) {
1248 // Add feature to support customized secondary bus number
1250 if (*SubBusNumber
== 0) {
1251 *SubBusNumber
= *PaddedBusRange
;
1252 *PaddedBusRange
= 0;
1257 SecondBus
= (*SubBusNumber
);
1259 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1261 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1263 Status
= PciRootBridgeIoWrite (
1273 // Initialize SubBusNumber to SecondBus
1275 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1276 Status
= PciRootBridgeIoWrite (
1285 // If it is PPB, resursively search down this bridge
1287 if (IS_PCI_BRIDGE (&Pci
)) {
1289 // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1290 // PCI configuration transaction to go through any PPB
1292 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1294 Status
= PciRootBridgeIoWrite (
1303 PreprocessController (
1305 PciDevice
->BusNumber
,
1306 PciDevice
->DeviceNumber
,
1307 PciDevice
->FunctionNumber
,
1308 EfiPciBeforeChildBusEnumeration
1311 DEBUG((EFI_D_ERROR
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
1312 Status
= PciScanBus (
1314 (UINT8
) (SecondBus
),
1319 if (EFI_ERROR (Status
)) {
1320 return EFI_DEVICE_ERROR
;
1325 // Set the current maximum bus number under the PPB
1328 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1330 Status
= PciRootBridgeIoWrite (
1341 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1344 // Skip sub functions, this is not a multi function device
1347 Func
= PCI_MAX_FUNC
;
1356 Wapper function of scanning pci bus and assign bus number to the given PCI bus system
1357 Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug
1359 @param Bridge Bridge device instance
1360 @param StartBusNumber start point
1361 @param SubBusNumber Point to sub bus number
1362 @param PaddedBusRange Customized bus number
1364 @retval EFI_SUCCESS Success
1365 @retval EFI_DEVICE_ERROR Fail to scan bus
1368 PciScanBus_WithHotPlugDeviceSupport (
1369 IN PCI_IO_DEVICE
*Bridge
,
1370 IN UINT8 StartBusNumber
,
1371 OUT UINT8
*SubBusNumber
,
1372 OUT UINT8
*PaddedBusRange
1383 PCI_IO_DEVICE
*PciDevice
;
1385 EFI_HPC_STATE State
;
1387 EFI_HPC_PADDING_ATTRIBUTES Attributes
;
1388 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1390 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1393 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1397 Attributes
= (EFI_HPC_PADDING_ATTRIBUTES
) 0;
1400 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1401 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1404 // Check to see whether a pci device is present
1406 Status
= PciDevicePresent (
1414 if (EFI_ERROR (Status
)) {
1417 // Skip sub functions, this is not a multi function device
1419 Func
= PCI_MAX_FUNC
;
1425 DEBUG((EFI_D_ERROR
, "Found DEV(%02d,%02d,%02d)\n", StartBusNumber
, Device
, Func
));
1428 // Get the PCI device information
1430 Status
= PciSearchDevice (
1439 ASSERT (!EFI_ERROR (Status
));
1441 PciAddress
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0);
1443 if (!IS_PCI_BRIDGE (&Pci
)) {
1445 // PCI bridges will be called later
1446 // Here just need for PCI device or PCI to cardbus controller
1447 // EfiPciBeforeChildBusEnumeration for PCI Device Node
1449 PreprocessController (
1451 PciDevice
->BusNumber
,
1452 PciDevice
->DeviceNumber
,
1453 PciDevice
->FunctionNumber
,
1454 EfiPciBeforeChildBusEnumeration
1459 // For Pci Hotplug controller devcie only
1461 if (gPciHotPlugInit
!= NULL
) {
1463 // Check if it is a Hotplug PCI controller
1465 if (IsRootPciHotPlugController (PciDevice
->DevicePath
, &HpIndex
)) {
1467 if (!gPciRootHpcData
[HpIndex
].Initialized
) {
1469 Status
= CreateEventForHpc (HpIndex
, &Event
);
1471 ASSERT (!EFI_ERROR (Status
));
1473 Status
= gPciHotPlugInit
->InitializeRootHpc (
1475 gPciRootHpcPool
[HpIndex
].HpcDevicePath
,
1481 PreprocessController (
1483 PciDevice
->BusNumber
,
1484 PciDevice
->DeviceNumber
,
1485 PciDevice
->FunctionNumber
,
1486 EfiPciBeforeChildBusEnumeration
1492 if (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
)) {
1495 // Get the bridge information
1498 if (gPciHotPlugInit
!= NULL
) {
1500 if (IsRootPciHotPlugBus (PciDevice
->DevicePath
, &HpIndex
)) {
1503 // If it is initialized, get the padded bus range
1505 Status
= gPciHotPlugInit
->GetResourcePadding (
1507 gPciRootHpcPool
[HpIndex
].HpbDevicePath
,
1510 (VOID
**) &Descriptors
,
1514 if (EFI_ERROR (Status
)) {
1519 Status
= PciGetBusRange (
1526 gBS
->FreePool (Descriptors
);
1528 if (EFI_ERROR (Status
)) {
1537 // Add feature to support customized secondary bus number
1539 if (*SubBusNumber
== 0) {
1540 *SubBusNumber
= *PaddedBusRange
;
1541 *PaddedBusRange
= 0;
1545 SecondBus
= *SubBusNumber
;
1547 Register
= (UINT16
) ((SecondBus
<< 8) | (UINT16
) StartBusNumber
);
1548 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
1550 Status
= PciRootBridgeIoWrite (
1561 // If it is PPB, resursively search down this bridge
1563 if (IS_PCI_BRIDGE (&Pci
)) {
1566 // Initialize SubBusNumber to Maximum bus number
1569 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1570 Status
= PciRootBridgeIoWrite (
1580 // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1582 PreprocessController (
1584 PciDevice
->BusNumber
,
1585 PciDevice
->DeviceNumber
,
1586 PciDevice
->FunctionNumber
,
1587 EfiPciBeforeChildBusEnumeration
1590 DEBUG((EFI_D_ERROR
, "Scan PPB(%02d,%02d,%02d)\n", PciDevice
->BusNumber
, PciDevice
->DeviceNumber
,PciDevice
->FunctionNumber
));
1591 Status
= PciScanBus (
1593 (UINT8
) (SecondBus
),
1598 if (EFI_ERROR (Status
)) {
1599 return EFI_DEVICE_ERROR
;
1605 // Ensure the device is enabled and initialized
1607 if ((Attributes
== EfiPaddingPciRootBridge
) &&
1608 (State
& EFI_HPC_STATE_ENABLED
) &&
1609 (State
& EFI_HPC_STATE_INITIALIZED
) ) {
1610 *PaddedBusRange
= (UINT8
) ((UINT8
) (BusRange
) +*PaddedBusRange
);
1612 *SubBusNumber
= (UINT8
) ((UINT8
) (BusRange
) +*SubBusNumber
);
1617 // Set the current maximum bus number under the PPB
1619 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x1A);
1621 Status
= PciRootBridgeIoWrite (
1631 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
1634 // Skip sub functions, this is not a multi function device
1636 Func
= PCI_MAX_FUNC
;
1646 Process Option Rom on this host bridge
1648 @param Bridge Pci bridge device instance
1650 @retval EFI_SUCCESS Success
1653 PciRootBridgeP2CProcess (
1654 IN PCI_IO_DEVICE
*Bridge
1657 LIST_ENTRY
*CurrentLink
;
1658 PCI_IO_DEVICE
*Temp
;
1659 EFI_HPC_STATE State
;
1663 CurrentLink
= Bridge
->ChildList
.ForwardLink
;
1665 while (CurrentLink
&& CurrentLink
!= &Bridge
->ChildList
) {
1667 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1669 if (IS_CARDBUS_BRIDGE (&Temp
->Pci
)) {
1671 if (gPciHotPlugInit
&& Temp
->Allocated
) {
1674 // Raise the EFI_IOB_PCI_HPC_INIT status code
1676 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1678 EFI_IO_BUS_PCI
| EFI_IOB_PCI_PC_HPC_INIT
,
1682 PciAddress
= EFI_PCI_ADDRESS (Temp
->BusNumber
, Temp
->DeviceNumber
, Temp
->FunctionNumber
, 0);
1683 Status
= gPciHotPlugInit
->InitializeRootHpc (
1691 if (!EFI_ERROR (Status
)) {
1692 Status
= PciBridgeEnumerator (Temp
);
1694 if (EFI_ERROR (Status
)) {
1699 CurrentLink
= CurrentLink
->ForwardLink
;
1705 if (!IsListEmpty (&Temp
->ChildList
)) {
1706 Status
= PciRootBridgeP2CProcess (Temp
);
1709 CurrentLink
= CurrentLink
->ForwardLink
;
1716 Process Option Rom on this host bridge
1718 @param PciResAlloc Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1720 @retval EFI_NOT_FOUND Can not find the root bridge instance
1721 @retval EFI_SUCCESS Success process
1724 PciHostBridgeP2CProcess (
1725 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1728 EFI_HANDLE RootBridgeHandle
;
1729 PCI_IO_DEVICE
*RootBridgeDev
;
1732 if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1736 RootBridgeHandle
= NULL
;
1738 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1741 // Get RootBridg Device by handle
1743 RootBridgeDev
= GetRootBridgeByHandle (RootBridgeHandle
);
1745 if (RootBridgeDev
== NULL
) {
1746 return EFI_NOT_FOUND
;
1749 Status
= PciRootBridgeP2CProcess (RootBridgeDev
);
1751 if (EFI_ERROR (Status
)) {
1761 This function is used to enumerate the entire host bridge
1764 @param PciResAlloc A pointer to the resource allocate protocol.
1766 @retval EFI_OUT_OF_RESOURCES no enough resource
1767 @retval EFI_SUCCESS Success
1771 PciHostBridgeEnumerator (
1772 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*PciResAlloc
1775 EFI_HANDLE RootBridgeHandle
;
1776 PCI_IO_DEVICE
*RootBridgeDev
;
1778 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1780 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1781 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*pConfiguration
;
1782 UINT8 StartBusNumber
;
1783 LIST_ENTRY RootBridgeList
;
1786 InitializeHotPlugSupport ();
1788 InitializeListHead (&RootBridgeList
);
1791 // Notify the bus allocation phase is about to start
1793 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1795 DEBUG((EFI_D_ERROR
, "PCI Bus First Scanning\n"));
1796 RootBridgeHandle
= NULL
;
1797 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1800 // if a root bridge instance is found, create root bridge device for it
1803 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1805 if (RootBridgeDev
== NULL
) {
1806 return EFI_OUT_OF_RESOURCES
;
1810 // Enumerate all the buses under this root bridge
1813 Status
= PciRootBridgeEnumerator (
1818 if (gPciHotPlugInit
!= NULL
) {
1819 InsertTailList (&RootBridgeList
, &(RootBridgeDev
->Link
));
1821 DestroyRootBridge (RootBridgeDev
);
1823 if (EFI_ERROR (Status
)) {
1829 // Notify the bus allocation phase is finished for the first time
1831 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1833 if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport
)) {
1835 if (gPciHotPlugInit
!= NULL
) {
1837 // Reset all assigned PCI bus number in all PPB
1839 RootBridgeHandle
= NULL
;
1840 Link
= GetFirstNode (&RootBridgeList
);
1841 while ((PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) &&
1842 (!IsNull (&RootBridgeList
, Link
))) {
1843 RootBridgeDev
= PCI_IO_DEVICE_FROM_LINK (Link
);
1845 // Get the Bus information
1847 Status
= PciResAlloc
->StartBusEnumeration (
1850 (VOID
**) &pConfiguration
1852 if (EFI_ERROR (Status
)) {
1857 // Get the bus number to start with
1859 StartBusNumber
= (UINT8
) (pConfiguration
->AddrRangeMin
);
1861 ResetAllPpbBusNumber (
1866 gBS
->FreePool (pConfiguration
);
1867 Link
= GetNextNode (&RootBridgeList
, Link
);
1868 DestroyRootBridge (RootBridgeDev
);
1872 // Wait for all HPC initialized
1874 Status
= AllRootHPCInitialized (STALL_1_SECOND
* 15);
1876 if (EFI_ERROR (Status
)) {
1881 // Notify the bus allocation phase is about to start for the 2nd time
1883 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginBusAllocation
);
1885 DEBUG((EFI_D_ERROR
, "PCI Bus Second Scanning\n"));
1886 RootBridgeHandle
= NULL
;
1887 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1890 // if a root bridge instance is found, create root bridge device for it
1893 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1895 if (RootBridgeDev
== NULL
) {
1896 return EFI_OUT_OF_RESOURCES
;
1900 // Enumerate all the buses under this root bridge
1903 Status
= PciRootBridgeEnumerator (
1908 DestroyRootBridge (RootBridgeDev
);
1909 if (EFI_ERROR (Status
)) {
1915 // Notify the bus allocation phase is to end for the 2nd time
1917 NotifyPhase (PciResAlloc
, EfiPciHostBridgeEndBusAllocation
);
1922 // Notify the resource allocation phase is to start
1924 NotifyPhase (PciResAlloc
, EfiPciHostBridgeBeginResourceAllocation
);
1926 RootBridgeHandle
= NULL
;
1927 while (PciResAlloc
->GetNextRootBridge (PciResAlloc
, &RootBridgeHandle
) == EFI_SUCCESS
) {
1930 // if a root bridge instance is found, create root bridge device for it
1933 RootBridgeDev
= CreateRootBridge (RootBridgeHandle
);
1935 if (RootBridgeDev
== NULL
) {
1936 return EFI_OUT_OF_RESOURCES
;
1939 Status
= StartManagingRootBridge (RootBridgeDev
);
1941 if (EFI_ERROR (Status
)) {
1945 PciRootBridgeIo
= RootBridgeDev
->PciRootBridgeIo
;
1946 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1948 if (EFI_ERROR (Status
)) {
1952 Status
= PciGetBusRange (&Descriptors
, &MinBus
, NULL
, NULL
);
1954 if (EFI_ERROR (Status
)) {
1959 // Determine root bridge attribute by calling interface of Pcihostbridge
1962 DetermineRootBridgeAttributes (
1968 // Collect all the resource information under this root bridge
1969 // A database that records all the information about pci device subject to this
1970 // root bridge will then be created
1972 Status
= PciPciDeviceInfoCollector (
1977 if (EFI_ERROR (Status
)) {
1981 InsertRootBridge (RootBridgeDev
);
1984 // Record the hostbridge handle
1986 AddHostBridgeEnumerator (RootBridgeDev
->PciRootBridgeIo
->ParentHandle
);
1993 Read PCI device configuration register by specified address.
1995 This function check the incompatiblilites on PCI device. Return the register
1998 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1999 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2000 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2001 @param Width Signifies the width of the memory operations.
2002 @Param Address The address within the PCI configuration space for the PCI controller.
2003 @param Buffer For read operations, the destination buffer to store the results. For
2004 write operations, the source buffer to write data from.
2006 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2007 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2008 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2009 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2015 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2016 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2017 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2025 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
2026 UINT64 AccessAddress
;
2031 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2033 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) {
2035 // check access compatibility at first time
2037 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, Address
& 0xff, Width
, &PciRegisterAccessData
);
2039 if (Status
== EFI_SUCCESS
) {
2041 // there exist incompatibility on this operation
2043 AccessWidth
= Width
;
2045 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2046 AccessWidth
= PciRegisterAccessData
->Width
;
2049 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
2053 Pointer
= (UINT8
*) &TempBuffer
;
2057 if (PciRootBridgeIo
!= NULL
) {
2058 Status
= PciRootBridgeIo
->Pci
.Read (
2060 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
2065 } else if (PciIo
!= NULL
) {
2066 Status
= PciIo
->Pci
.Read (
2068 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
2069 (UINT32
) AccessAddress
,
2075 if (Status
!= EFI_SUCCESS
) {
2079 Stride
= (UINTN
)1 << AccessWidth
;
2080 AccessAddress
+= Stride
;
2081 if (AccessAddress
>= (Address
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
2083 // if all datas have been read, exist
2090 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
2092 // if current offset doesn't reach the end
2097 FreePool (PciRegisterAccessData
);
2100 // continue checking access incompatibility
2102 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_READ
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
2103 if (Status
== EFI_SUCCESS
) {
2104 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2105 AccessWidth
= PciRegisterAccessData
->Width
;
2110 FreePool (PciRegisterAccessData
);
2113 case EfiPciWidthUint8
:
2114 * (UINT8
*) Buffer
= (UINT8
) TempBuffer
;
2116 case EfiPciWidthUint16
:
2117 * (UINT16
*) Buffer
= (UINT16
) TempBuffer
;
2119 case EfiPciWidthUint32
:
2120 * (UINT32
*) Buffer
= (UINT32
) TempBuffer
;
2123 return EFI_UNSUPPORTED
;
2130 // AccessWidth incompatible check not supportted
2131 // or, there doesn't exist incompatibility on this operation
2133 if (PciRootBridgeIo
!= NULL
) {
2134 Status
= PciRootBridgeIo
->Pci
.Read (
2136 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
2143 Status
= PciIo
->Pci
.Read (
2145 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
2156 Update register value by checking PCI device incompatibility.
2158 This function check register value incompatibilites on PCI device. Return the register
2161 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2162 @param AccessType Access type, READ or WRITE.
2163 @Param Address The address within the PCI configuration space.
2164 @param Buffer Store the register data.
2166 @retval EFI_SUCCESS The data has been updated.
2172 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2173 IN UINT64 AccessType
,
2180 EFI_PCI_REGISTER_VALUE_DATA
*PciRegisterData
;
2186 // check register value incompatibility
2188 Status
= PciRegisterUpdateCheck (PciDeviceInfo
, AccessType
, Address
& 0xff, &PciRegisterData
);
2190 if (Status
== EFI_SUCCESS
) {
2192 AndValue
= ((UINT32
) PciRegisterData
->AndValue
) >> (((UINT8
) Address
& 0x3) * 8);
2193 OrValue
= ((UINT32
) PciRegisterData
->OrValue
) >> (((UINT8
) Address
& 0x3) * 8);
2195 TempValue
= * (UINT32
*) Buffer
;
2196 if (PciRegisterData
->AndValue
!= VALUE_NOCARE
) {
2197 TempValue
&= AndValue
;
2199 if (PciRegisterData
->OrValue
!= VALUE_NOCARE
) {
2200 TempValue
|= OrValue
;
2204 case EfiPciWidthUint8
:
2205 *(UINT8
*)Buffer
= (UINT8
) TempValue
;
2208 case EfiPciWidthUint16
:
2209 *(UINT16
*)Buffer
= (UINT16
) TempValue
;
2211 case EfiPciWidthUint32
:
2212 *(UINT32
*)Buffer
= TempValue
;
2216 return EFI_UNSUPPORTED
;
2219 FreePool (PciRegisterData
);
2226 Write PCI device configuration register by specified address.
2228 This function check the incompatiblilites on PCI device, and write date
2231 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2232 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2233 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2234 @param Width Signifies the width of the memory operations.
2235 @Param Address The address within the PCI configuration space for the PCI controller.
2236 @param Buffer For read operations, the destination buffer to store the results. For
2237 write operations, the source buffer to write data from.
2239 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2240 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2241 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2242 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2248 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2249 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2250 IN EFI_PCI_DEVICE_INFO
*PciDeviceInfo
,
2258 EFI_PCI_REGISTER_ACCESS_DATA
*PciRegisterAccessData
;
2259 UINT64 AccessAddress
;
2265 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2267 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACCESS_WIDTH_SUPPORT
) {
2269 // check access compatibility at first time
2271 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, Address
& 0xff, Width
, &PciRegisterAccessData
);
2273 if (Status
== EFI_SUCCESS
) {
2275 // there exist incompatibility on this operation
2277 AccessWidth
= Width
;
2279 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2280 AccessWidth
= PciRegisterAccessData
->Width
;
2283 AccessAddress
= Address
& ~((1 << AccessWidth
) - 1);
2286 Pointer
= (UINT8
*) &Buffer
;
2287 Data
= * (UINT64
*) Buffer
;
2291 if (AccessWidth
> Width
) {
2293 // if actual access width is larger than orignal one, additional data need to be read back firstly
2295 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, PciDeviceInfo
, AccessWidth
, AccessAddress
, &Data
);
2296 if (Status
!= EFI_SUCCESS
) {
2301 // check data read incompatibility
2303 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_READ
, AccessWidth
, AccessAddress
& 0xff, &Data
);
2305 Shift
= (UINTN
)(Address
- AccessAddress
) * 8;
2307 case EfiPciWidthUint8
:
2308 Data
= (* (UINT8
*) Buffer
) << Shift
| (Data
& ~(0xff << Shift
));
2311 case EfiPciWidthUint16
:
2312 Data
= (* (UINT16
*) Buffer
) << Shift
| (Data
& ~(0xffff << Shift
));
2317 // check data write incompatibility
2319 UpdateConfigData (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessWidth
, MultU64x32 (AccessAddress
, 0xff), &Data
);
2322 if (PciRootBridgeIo
!= NULL
) {
2323 Status
= PciRootBridgeIo
->Pci
.Write (
2325 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) AccessWidth
,
2331 Status
= PciIo
->Pci
.Write (
2333 (EFI_PCI_IO_PROTOCOL_WIDTH
) AccessWidth
,
2334 (UINT32
) AccessAddress
,
2340 if (Status
!= EFI_SUCCESS
) {
2344 Data
= RShiftU64 (Data
, ((1 << AccessWidth
) * 8));
2346 Stride
= (UINTN
)1 << AccessWidth
;
2347 AccessAddress
+= Stride
;
2348 if (AccessAddress
>= (Address
+ LShiftU64 (1ULL, (UINTN
)Width
))) {
2350 // if all datas have been written, exist
2357 if ((AccessAddress
& 0xff) < PciRegisterAccessData
->EndOffset
) {
2359 // if current offset doesn't reach the end
2364 FreePool (PciRegisterAccessData
);
2367 // continue checking access incompatibility
2369 Status
= PciRegisterAccessCheck (PciDeviceInfo
, PCI_REGISTER_WRITE
, AccessAddress
& 0xff, AccessWidth
, &PciRegisterAccessData
);
2370 if (Status
== EFI_SUCCESS
) {
2371 if (PciRegisterAccessData
->Width
!= VALUE_NOCARE
) {
2372 AccessWidth
= PciRegisterAccessData
->Width
;
2377 FreePool (PciRegisterAccessData
);
2384 // AccessWidth incompatible check not supportted
2385 // or, there doesn't exist incompatibility on this operation
2387 if (PciRootBridgeIo
!= NULL
) {
2388 Status
= PciRootBridgeIo
->Pci
.Write (
2390 (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
) Width
,
2396 Status
= PciIo
->Pci
.Write (
2398 (EFI_PCI_IO_PROTOCOL_WIDTH
) Width
,
2409 Abstract PCI device device information.
2411 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2412 @param PciIo A pointer to EFI_PCI_PROTOCOL.
2413 @param Pci A pointer to PCI_TYPE00.
2414 @Param Address The address within the PCI configuration space for the PCI controller.
2415 @param PciDeviceInfo A pointer to EFI_PCI_DEVICE_INFO.
2417 @retval EFI_SUCCESS Pci device device information has been abstracted.
2422 GetPciDeviceDeviceInfo (
2423 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2424 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2425 IN PCI_TYPE00
*Pci
, OPTIONAL
2426 IN UINT64 Address
, OPTIONAL
2427 OUT EFI_PCI_DEVICE_INFO
*PciDeviceInfo
2432 UINT32 PciConfigData
;
2433 PCI_IO_DEVICE
*PciIoDevice
;
2435 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2437 if (PciIo
!= NULL
) {
2438 PciIoDevice
= PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo
);
2441 // get pointer to PCI_TYPE00 from PciIoDevice
2443 Pci
= &PciIoDevice
->Pci
;
2448 // while PCI_TYPE00 hasn't been gotten, read PCI device device information directly
2450 PciAddress
= Address
& 0xffffffffffffff00ULL
;
2451 Status
= PciRootBridgeIo
->Pci
.Read (
2459 if (EFI_ERROR (Status
)) {
2463 if ((PciConfigData
& 0xffff) == 0xffff) {
2464 return EFI_NOT_FOUND
;
2467 PciDeviceInfo
->VendorID
= PciConfigData
& 0xffff;
2468 PciDeviceInfo
->DeviceID
= PciConfigData
>> 16;
2470 Status
= PciRootBridgeIo
->Pci
.Read (
2477 if (EFI_ERROR (Status
)) {
2481 PciDeviceInfo
->RevisionID
= PciConfigData
& 0xf;
2483 Status
= PciRootBridgeIo
->Pci
.Read (
2491 if (EFI_ERROR (Status
)) {
2495 PciDeviceInfo
->SubsystemVendorID
= PciConfigData
& 0xffff;
2496 PciDeviceInfo
->SubsystemID
= PciConfigData
>> 16;
2499 PciDeviceInfo
->VendorID
= Pci
->Hdr
.VendorId
;
2500 PciDeviceInfo
->DeviceID
= Pci
->Hdr
.DeviceId
;
2501 PciDeviceInfo
->RevisionID
= Pci
->Hdr
.RevisionID
;
2502 PciDeviceInfo
->SubsystemVendorID
= Pci
->Device
.SubsystemVendorID
;
2503 PciDeviceInfo
->SubsystemID
= Pci
->Device
.SubsystemID
;
2510 Read PCI configuration space with incompatibility check.
2512 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2513 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2514 @param Pci A pointer to PCI_TYPE00.
2515 @param Width Signifies the width of the memory operations.
2516 @Param Address The address within the PCI configuration space for the PCI controller.
2517 @param Buffer For read operations, the destination buffer to store the results. For
2518 write operations, the source buffer to write data from.
2520 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2521 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2522 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2523 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2528 PciIncompatibilityCheckRead (
2529 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2530 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2531 IN PCI_TYPE00
*Pci
, OPTIONAL
2539 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
2542 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2545 // get PCI device device information
2547 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
2548 if (Status
!= EFI_SUCCESS
) {
2552 Stride
= 1 << Width
;
2554 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*)Buffer
+ Stride
) {
2557 // read configuration register
2559 Status
= ReadConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, (UINT64
) Width
, Address
, Buffer
);
2561 if (Status
!= EFI_SUCCESS
) {
2566 // update the data read from configuration register
2568 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) {
2569 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_READ
, Width
, Address
& 0xff, Buffer
);
2577 Write PCI configuration space with incompatibility check.
2579 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2580 @param PciIo A pointer to the EFI_PCI_IO_PROTOCOL.
2581 @param Pci A pointer to PCI_TYPE00.
2582 @param Width Signifies the width of the memory operations.
2583 @Param Address The address within the PCI configuration space for the PCI controller.
2584 @param Buffer For read operations, the destination buffer to store the results. For
2585 write operations, the source buffer to write data from.
2587 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2588 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2589 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2590 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2595 PciIncompatibilityCheckWrite (
2596 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
, OPTIONAL
2597 IN EFI_PCI_IO_PROTOCOL
*PciIo
, OPTIONAL
2598 IN PCI_TYPE00
*Pci
, OPTIONAL
2606 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
2610 ASSERT ((PciRootBridgeIo
== NULL
) ^ (PciIo
== NULL
));
2613 // get PCI device device information
2615 Status
= GetPciDeviceDeviceInfo (PciRootBridgeIo
, PciIo
, Pci
, Address
, &PciDeviceInfo
);
2616 if (Status
!= EFI_SUCCESS
) {
2620 Stride
= 1 << Width
;
2622 for (; Count
> 0; Count
--, Address
+= Stride
, Buffer
= (UINT8
*) Buffer
+ Stride
) {
2627 case EfiPciWidthUint8
:
2628 Data
= * (UINT8
*) Buffer
;
2630 case EfiPciWidthUint16
:
2631 Data
= * (UINT16
*) Buffer
;
2634 case EfiPciWidthUint32
:
2635 Data
= * (UINT32
*) Buffer
;
2639 return EFI_UNSUPPORTED
;
2643 // update the data writen into configuration register
2645 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_REGISTER_UPDATE_SUPPORT
) {
2646 UpdateConfigData (&PciDeviceInfo
, PCI_REGISTER_WRITE
, Width
, Address
& 0xff, &Data
);
2650 // write configuration register
2652 Status
= WriteConfigData (PciRootBridgeIo
, PciIo
, &PciDeviceInfo
, Width
, Address
, &Data
);
2654 if (Status
!= EFI_SUCCESS
) {
2663 Read PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2665 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2666 @param Pci A pointer to PCI_TYPE00.
2667 @param Width Signifies the width of the memory operations.
2668 @Param Address The address within the PCI configuration space for the PCI controller.
2669 @param Buffer For read operations, the destination buffer to store the results. For
2670 write operations, the source buffer to write data from.
2672 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2673 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2674 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2675 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2679 PciRootBridgeIoRead (
2680 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2681 IN PCI_TYPE00
*Pci
, OPTIONAL
2682 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2688 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) {
2690 // if PCI incompatibility check enabled
2692 return PciIncompatibilityCheckRead (
2702 return PciRootBridgeIo
->Pci
.Read (
2713 Write PCI configuration space through EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2715 @param PciRootBridgeIo A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2716 @param Pci A pointer to PCI_TYPE00.
2717 @param Width Signifies the width of the memory operations.
2718 @Param Address The address within the PCI configuration space for the PCI controller.
2719 @param Buffer For read operations, the destination buffer to store the results. For
2720 write operations, the source buffer to write data from.
2722 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2723 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2724 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2725 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2729 PciRootBridgeIoWrite (
2730 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
2732 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width
,
2738 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) {
2740 // if PCI incompatibility check enabled
2742 return PciIncompatibilityCheckWrite (
2753 return PciRootBridgeIo
->Pci
.Write (
2764 Read PCI configuration space through EFI_PCI_IO_PROTOCOL.
2766 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2767 @param Width Signifies the width of the memory operations.
2768 @Param Address The address within the PCI configuration space for the PCI controller.
2769 @param Buffer For read operations, the destination buffer to store the results. For
2770 write operations, the source buffer to write data from.
2772 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2773 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2774 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2775 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2780 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2781 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2787 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_READ_SUPPORT
) {
2789 // if PCI incompatibility check enabled
2791 return PciIncompatibilityCheckRead (
2801 return PciIo
->Pci
.Read (
2812 Write PCI configuration space through EFI_PCI_IO_PROTOCOL.
2814 @param PciIo A pointer to the EFI_PCI_O_PROTOCOL.
2815 @param Width Signifies the width of the memory operations.
2816 @Param Address The address within the PCI configuration space for the PCI controller.
2817 @param Buffer For read operations, the destination buffer to store the results. For
2818 write operations, the source buffer to write data from.
2820 @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
2821 @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
2822 @retval EFI_INVALID_PARAMETER Buffer is NULL.
2823 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
2828 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2829 IN EFI_PCI_IO_PROTOCOL_WIDTH Width
,
2835 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_WRITE_SUPPORT
) {
2838 // if PCI incompatibility check enabled
2840 return PciIncompatibilityCheckWrite (
2851 return PciIo
->Pci
.Write (