2 PCI emumeration support functions implementation for PCI Bus module.
4 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 extern CHAR16
*mBarTypeStr
[];
21 This routine is used to check whether the pci device is present.
23 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
24 @param Pci Output buffer for PCI device configuration space.
25 @param Bus PCI bus NO.
26 @param Device PCI device NO.
27 @param Func PCI Func NO.
29 @retval EFI_NOT_FOUND PCI device not present.
30 @retval EFI_SUCCESS PCI device is found.
35 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
46 // Create PCI address map in terms of Bus, Device and Func
48 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Func
, 0);
51 // Read the Vendor ID register
53 Status
= PciRootBridgeIo
->Pci
.Read (
61 if (!EFI_ERROR (Status
) && (Pci
->Hdr
).VendorId
!= 0xffff) {
63 // Read the entire config header for the device
65 Status
= PciRootBridgeIo
->Pci
.Read (
69 sizeof (PCI_TYPE00
) / sizeof (UINT32
),
80 Collect all the resource information under this root bridge.
82 A database that records all the information about pci device subject to this
83 root bridge will then be created.
85 @param Bridge Parent bridge instance.
86 @param StartBusNumber Bus number of begining.
88 @retval EFI_SUCCESS PCI device is found.
89 @retval other Some error occurred when reading PCI bridge information.
93 PciPciDeviceInfoCollector (
94 IN PCI_IO_DEVICE
*Bridge
,
95 IN UINT8 StartBusNumber
103 PCI_IO_DEVICE
*PciIoDevice
;
104 EFI_PCI_IO_PROTOCOL
*PciIo
;
106 Status
= EFI_SUCCESS
;
109 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
111 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
114 // Check to see whether PCI device is present
116 Status
= PciDevicePresent (
117 Bridge
->PciRootBridgeIo
,
119 (UINT8
) StartBusNumber
,
124 if (EFI_ERROR (Status
) && Func
== 0) {
126 // go to next device if there is no Function 0
131 if (!EFI_ERROR (Status
)) {
134 // Call back to host bridge function
136 PreprocessController (Bridge
, (UINT8
) StartBusNumber
, Device
, Func
, EfiPciBeforeResourceCollection
);
139 // Collect all the information about the PCI device discovered
141 Status
= PciSearchDevice (
144 (UINT8
) StartBusNumber
,
151 // Recursively scan PCI busses on the other side of PCI-PCI bridges
154 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
157 // If it is PPB, we need to get the secondary bus to continue the enumeration
159 PciIo
= &(PciIoDevice
->PciIo
);
161 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET
, 1, &SecBus
);
163 if (EFI_ERROR (Status
)) {
168 // Get resource padding for PPB
170 GetResourcePaddingPpb (PciIoDevice
);
173 // Deep enumerate the next level bus
175 Status
= PciPciDeviceInfoCollector (
182 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
185 // Skip sub functions, this is not a multi function device
198 Seach required device and create PCI device instance.
200 @param Bridge Parent bridge instance.
201 @param Pci Input PCI device information block.
202 @param Bus PCI bus NO.
203 @param Device PCI device NO.
204 @param Func PCI func NO.
205 @param PciDevice Output of searched PCI device instance.
207 @retval EFI_SUCCESS Successfully created PCI device instance.
208 @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.
213 IN PCI_IO_DEVICE
*Bridge
,
218 OUT PCI_IO_DEVICE
**PciDevice
221 PCI_IO_DEVICE
*PciIoDevice
;
227 "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
228 IS_PCI_BRIDGE (Pci
) ? L
"PPB" :
229 IS_CARDBUS_BRIDGE (Pci
) ? L
"P2C" :
234 if (!IS_PCI_BRIDGE (Pci
)) {
236 if (IS_CARDBUS_BRIDGE (Pci
)) {
237 PciIoDevice
= GatherP2CInfo (
244 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
245 InitializeP2C (PciIoDevice
);
250 // Create private data for Pci Device
252 PciIoDevice
= GatherDeviceInfo (
265 // Create private data for PPB
267 PciIoDevice
= GatherPpbInfo (
276 // Special initialization for PPB including making the PPB quiet
278 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
279 InitializePpb (PciIoDevice
);
283 if (PciIoDevice
== NULL
) {
284 return EFI_OUT_OF_RESOURCES
;
288 // Update the bar information for this PCI device so as to support some specific device
290 UpdatePciInfo (PciIoDevice
);
292 if (PciIoDevice
->DevicePath
== NULL
) {
293 return EFI_OUT_OF_RESOURCES
;
297 // Detect this function has option rom
299 if (gFullEnumeration
) {
301 if (!IS_CARDBUS_BRIDGE (Pci
)) {
303 GetOpRomInfo (PciIoDevice
);
307 ResetPowerManagementFeature (PciIoDevice
);
312 // Insert it into a global tree for future reference
314 InsertPciDevice (Bridge
, PciIoDevice
);
317 // Determine PCI device attributes
320 if (PciDevice
!= NULL
) {
321 *PciDevice
= PciIoDevice
;
328 Dump the PPB padding resource information.
330 @param PciIoDevice PCI IO instance.
331 @param ResourceType The desired resource type to dump.
332 PciBarTypeUnknown means to dump all types of resources.
335 DumpPpbPaddingResource (
336 IN PCI_IO_DEVICE
*PciIoDevice
,
337 IN PCI_BAR_TYPE ResourceType
340 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
343 if (PciIoDevice
->ResourcePaddingDescriptors
== NULL
) {
347 if (ResourceType
== PciBarTypeIo16
|| ResourceType
== PciBarTypeIo32
) {
348 ResourceType
= PciBarTypeIo
;
351 for (Descriptor
= PciIoDevice
->ResourcePaddingDescriptors
; Descriptor
->Desc
!= ACPI_END_TAG_DESCRIPTOR
; Descriptor
++) {
353 Type
= PciBarTypeUnknown
;
354 if (Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
) {
356 } else if (Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
&& Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
358 if (Descriptor
->AddrSpaceGranularity
== 32) {
362 if (Descriptor
->SpecificFlag
== EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) {
363 Type
= PciBarTypePMem32
;
369 if (Descriptor
->SpecificFlag
== 0) {
370 Type
= PciBarTypeMem32
;
374 if (Descriptor
->AddrSpaceGranularity
== 64) {
378 if (Descriptor
->SpecificFlag
== EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) {
379 Type
= PciBarTypePMem64
;
385 if (Descriptor
->SpecificFlag
== 0) {
386 Type
= PciBarTypeMem64
;
391 if ((Type
!= PciBarTypeUnknown
) && ((ResourceType
== PciBarTypeUnknown
) || (ResourceType
== Type
))) {
394 " Padding: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx\n",
395 mBarTypeStr
[Type
], Descriptor
->AddrRangeMax
, Descriptor
->AddrLen
403 Dump the PCI BAR information.
405 @param PciIoDevice PCI IO instance.
409 IN PCI_IO_DEVICE
*PciIoDevice
414 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
415 if (PciIoDevice
->PciBar
[Index
].BarType
== PciBarTypeUnknown
) {
421 " BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
422 Index
, mBarTypeStr
[MIN (PciIoDevice
->PciBar
[Index
].BarType
, PciBarTypeMaxType
)],
423 PciIoDevice
->PciBar
[Index
].Alignment
, PciIoDevice
->PciBar
[Index
].Length
, PciIoDevice
->PciBar
[Index
].Offset
427 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
428 if ((PciIoDevice
->VfPciBar
[Index
].BarType
== PciBarTypeUnknown
) && (PciIoDevice
->VfPciBar
[Index
].Length
== 0)) {
434 " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
435 Index
, mBarTypeStr
[MIN (PciIoDevice
->VfPciBar
[Index
].BarType
, PciBarTypeMaxType
)],
436 PciIoDevice
->VfPciBar
[Index
].Alignment
, PciIoDevice
->VfPciBar
[Index
].Length
, PciIoDevice
->VfPciBar
[Index
].Offset
439 DEBUG ((EFI_D_INFO
, "\n"));
443 Create PCI device instance for PCI device.
445 @param Bridge Parent bridge instance.
446 @param Pci Input PCI device information block.
447 @param Bus PCI device Bus NO.
448 @param Device PCI device Device NO.
449 @param Func PCI device's func NO.
451 @return Created PCI device instance.
456 IN PCI_IO_DEVICE
*Bridge
,
465 PCI_IO_DEVICE
*PciIoDevice
;
467 PciIoDevice
= CreatePciIoDevice (
475 if (PciIoDevice
== NULL
) {
480 // If it is a full enumeration, disconnect the device in advance
482 if (gFullEnumeration
) {
484 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
489 // Start to parse the bars
491 for (Offset
= 0x10, BarIndex
= 0; Offset
<= 0x24 && BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
492 Offset
= PciParseBar (PciIoDevice
, Offset
, BarIndex
);
496 // Parse the SR-IOV VF bars
498 if (PcdGetBool (PcdSrIovSupport
) && PciIoDevice
->SrIovCapabilityOffset
!= 0) {
499 for (Offset
= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0
, BarIndex
= 0;
500 Offset
<= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5
;
503 ASSERT (BarIndex
< PCI_MAX_BAR
);
504 Offset
= PciIovParseVfBar (PciIoDevice
, Offset
, BarIndex
);
508 DEBUG_CODE (DumpPciBars (PciIoDevice
););
513 Create PCI device instance for PCI-PCI bridge.
515 @param Bridge Parent bridge instance.
516 @param Pci Input PCI device information block.
517 @param Bus PCI device Bus NO.
518 @param Device PCI device Device NO.
519 @param Func PCI device's func NO.
521 @return Created PCI device instance.
526 IN PCI_IO_DEVICE
*Bridge
,
533 PCI_IO_DEVICE
*PciIoDevice
;
536 EFI_PCI_IO_PROTOCOL
*PciIo
;
538 UINT32 PMemBaseLimit
;
539 UINT16 PrefetchableMemoryBase
;
540 UINT16 PrefetchableMemoryLimit
;
542 PciIoDevice
= CreatePciIoDevice (
550 if (PciIoDevice
== NULL
) {
554 if (gFullEnumeration
) {
555 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
558 // Initalize the bridge control register
560 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED
);
565 // PPB can have two BARs
567 if (PciParseBar (PciIoDevice
, 0x10, PPB_BAR_0
) == 0x14) {
571 PciParseBar (PciIoDevice
, 0x14, PPB_BAR_1
);
574 PciIo
= &PciIoDevice
->PciIo
;
577 // Test whether it support 32 decode or not
579 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
580 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
581 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
582 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
585 if ((Value
& 0x01) != 0) {
586 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
588 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
593 // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes
594 // PCI bridge supporting non-stardard I/O window alignment less than 4K.
597 PciIoDevice
->BridgeIoAlignment
= 0xFFF;
598 if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
)) {
600 // Check any bits of bit 3-1 of I/O Base Register are writable.
601 // if so, it is assumed non-stardard I/O window alignment is supported by this bridge.
602 // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.
604 Value
= (UINT8
)(Temp
^ (BIT3
| BIT2
| BIT1
));
605 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
606 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
607 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
608 Value
= (UINT8
)((Value
^ Temp
) & (BIT3
| BIT2
| BIT1
));
611 PciIoDevice
->BridgeIoAlignment
= 0x7FF;
614 PciIoDevice
->BridgeIoAlignment
= 0x3FF;
616 case BIT3
| BIT2
| BIT1
:
617 PciIoDevice
->BridgeIoAlignment
= 0x1FF;
622 Status
= BarExisted (
630 // Test if it supports 64 memory or not
632 // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit
634 // 0 - the bridge supports only 32 bit addresses.
635 // 1 - the bridge supports 64-bit addresses.
637 PrefetchableMemoryBase
= (UINT16
)(PMemBaseLimit
& 0xffff);
638 PrefetchableMemoryLimit
= (UINT16
)(PMemBaseLimit
>> 16);
639 if (!EFI_ERROR (Status
) &&
640 (PrefetchableMemoryBase
& 0x000f) == 0x0001 &&
641 (PrefetchableMemoryLimit
& 0x000f) == 0x0001) {
642 Status
= BarExisted (
649 if (!EFI_ERROR (Status
)) {
650 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
651 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
653 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
658 // Memory 32 code is required for ppb
660 PciIoDevice
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
662 GetResourcePaddingPpb (PciIoDevice
);
665 DumpPpbPaddingResource (PciIoDevice
, PciBarTypeUnknown
);
666 DumpPciBars (PciIoDevice
);
674 Create PCI device instance for PCI Card bridge device.
676 @param Bridge Parent bridge instance.
677 @param Pci Input PCI device information block.
678 @param Bus PCI device Bus NO.
679 @param Device PCI device Device NO.
680 @param Func PCI device's func NO.
682 @return Created PCI device instance.
687 IN PCI_IO_DEVICE
*Bridge
,
694 PCI_IO_DEVICE
*PciIoDevice
;
696 PciIoDevice
= CreatePciIoDevice (
704 if (PciIoDevice
== NULL
) {
708 if (gFullEnumeration
) {
709 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
712 // Initalize the bridge control register
714 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED
);
718 // P2C only has one bar that is in 0x10
720 PciParseBar (PciIoDevice
, 0x10, P2C_BAR_0
);
723 // Read PciBar information from the bar register
725 GetBackPcCardBar (PciIoDevice
);
726 PciIoDevice
->Decodes
= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
|
727 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
|
728 EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
730 DEBUG_CODE (DumpPciBars (PciIoDevice
););
736 Create device path for pci deivce.
738 @param ParentDevicePath Parent bridge's path.
739 @param PciIoDevice Pci device instance.
741 @return Device path protocol instance for specific pci device.
744 EFI_DEVICE_PATH_PROTOCOL
*
745 CreatePciDevicePath (
746 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
747 IN PCI_IO_DEVICE
*PciIoDevice
751 PCI_DEVICE_PATH PciNode
;
754 // Create PCI device path
756 PciNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
757 PciNode
.Header
.SubType
= HW_PCI_DP
;
758 SetDevicePathNodeLength (&PciNode
.Header
, sizeof (PciNode
));
760 PciNode
.Device
= PciIoDevice
->DeviceNumber
;
761 PciNode
.Function
= PciIoDevice
->FunctionNumber
;
762 PciIoDevice
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, &PciNode
.Header
);
764 return PciIoDevice
->DevicePath
;
768 Check whether the PCI IOV VF bar is existed or not.
770 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
771 @param Offset The offset.
772 @param BarLengthValue The bar length value returned.
773 @param OriginalBarValue The original bar value returned.
775 @retval EFI_NOT_FOUND The bar doesn't exist.
776 @retval EFI_SUCCESS The bar exist.
781 IN PCI_IO_DEVICE
*PciIoDevice
,
783 OUT UINT32
*BarLengthValue
,
784 OUT UINT32
*OriginalBarValue
787 EFI_PCI_IO_PROTOCOL
*PciIo
;
788 UINT32 OriginalValue
;
793 // Ensure it is called properly
795 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
796 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
797 return EFI_NOT_FOUND
;
800 PciIo
= &PciIoDevice
->PciIo
;
803 // Preserve the original value
806 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
809 // Raise TPL to high level to disable timer interrupt while the BAR is probed
811 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
813 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &gAllOne
);
814 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &Value
);
817 // Write back the original value
819 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
822 // Restore TPL to its original level
824 gBS
->RestoreTPL (OldTpl
);
826 if (BarLengthValue
!= NULL
) {
827 *BarLengthValue
= Value
;
830 if (OriginalBarValue
!= NULL
) {
831 *OriginalBarValue
= OriginalValue
;
835 return EFI_NOT_FOUND
;
842 Check whether the bar is existed or not.
844 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
845 @param Offset The offset.
846 @param BarLengthValue The bar length value returned.
847 @param OriginalBarValue The original bar value returned.
849 @retval EFI_NOT_FOUND The bar doesn't exist.
850 @retval EFI_SUCCESS The bar exist.
855 IN PCI_IO_DEVICE
*PciIoDevice
,
857 OUT UINT32
*BarLengthValue
,
858 OUT UINT32
*OriginalBarValue
861 EFI_PCI_IO_PROTOCOL
*PciIo
;
862 UINT32 OriginalValue
;
866 PciIo
= &PciIoDevice
->PciIo
;
869 // Preserve the original value
871 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
874 // Raise TPL to high level to disable timer interrupt while the BAR is probed
876 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
878 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &gAllOne
);
879 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &Value
);
882 // Write back the original value
884 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
887 // Restore TPL to its original level
889 gBS
->RestoreTPL (OldTpl
);
891 if (BarLengthValue
!= NULL
) {
892 *BarLengthValue
= Value
;
895 if (OriginalBarValue
!= NULL
) {
896 *OriginalBarValue
= OriginalValue
;
900 return EFI_NOT_FOUND
;
907 Test whether the device can support given attributes.
909 @param PciIoDevice Pci device instance.
910 @param Command Input command register value, and
911 returned supported register value.
912 @param BridgeControl Inout bridge control value for PPB or P2C, and
913 returned supported bridge control value.
914 @param OldCommand Returned and stored old command register offset.
915 @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
919 PciTestSupportedAttribute (
920 IN PCI_IO_DEVICE
*PciIoDevice
,
921 IN OUT UINT16
*Command
,
922 IN OUT UINT16
*BridgeControl
,
923 OUT UINT16
*OldCommand
,
924 OUT UINT16
*OldBridgeControl
930 // Preserve the original value
932 PCI_READ_COMMAND_REGISTER (PciIoDevice
, OldCommand
);
935 // Raise TPL to high level to disable timer interrupt while the BAR is probed
937 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
939 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *Command
);
940 PCI_READ_COMMAND_REGISTER (PciIoDevice
, Command
);
943 // Write back the original value
945 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *OldCommand
);
948 // Restore TPL to its original level
950 gBS
->RestoreTPL (OldTpl
);
952 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
955 // Preserve the original value
957 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, OldBridgeControl
);
960 // Raise TPL to high level to disable timer interrupt while the BAR is probed
962 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
964 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *BridgeControl
);
965 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, BridgeControl
);
968 // Write back the original value
970 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *OldBridgeControl
);
973 // Restore TPL to its original level
975 gBS
->RestoreTPL (OldTpl
);
978 *OldBridgeControl
= 0;
984 Set the supported or current attributes of a PCI device.
986 @param PciIoDevice Structure pointer for PCI device.
987 @param Command Command register value.
988 @param BridgeControl Bridge control value for PPB or P2C.
989 @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
993 PciSetDeviceAttribute (
994 IN PCI_IO_DEVICE
*PciIoDevice
,
996 IN UINT16 BridgeControl
,
1004 if ((Command
& EFI_PCI_COMMAND_IO_SPACE
) != 0) {
1005 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IO
;
1008 if ((Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) != 0) {
1009 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY
;
1012 if ((Command
& EFI_PCI_COMMAND_BUS_MASTER
) != 0) {
1013 Attributes
|= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
;
1016 if ((Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
1017 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
1020 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
) != 0) {
1021 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
1024 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
) != 0) {
1025 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
1026 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
1027 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
1030 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
) != 0) {
1031 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
;
1032 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
;
1035 if (Option
== EFI_SET_SUPPORTS
) {
1037 Attributes
|= (UINT64
) (EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
1038 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
|
1039 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE
|
1040 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
1041 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
1042 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
);
1044 if (IS_PCI_LPC (&PciIoDevice
->Pci
)) {
1045 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
1046 Attributes
|= (mReserveIsaAliases
? (UINT64
) EFI_PCI_IO_ATTRIBUTE_ISA_IO
: \
1047 (UINT64
) EFI_PCI_IO_ATTRIBUTE_ISA_IO_16
);
1050 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1052 // For bridge, it should support IDE attributes
1054 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
1055 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
1057 if (mReserveVgaAliases
) {
1058 Attributes
&= ~(UINT64
)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
| \
1059 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
);
1061 Attributes
&= ~(UINT64
)(EFI_PCI_IO_ATTRIBUTE_VGA_IO
| \
1062 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
);
1066 if (IS_PCI_IDE (&PciIoDevice
->Pci
)) {
1067 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
1068 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
1071 if (IS_PCI_VGA (&PciIoDevice
->Pci
)) {
1072 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
1073 Attributes
|= (mReserveVgaAliases
? (UINT64
) EFI_PCI_IO_ATTRIBUTE_VGA_IO
: \
1074 (UINT64
) EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
);
1078 PciIoDevice
->Supports
= Attributes
;
1079 PciIoDevice
->Supports
&= ( (PciIoDevice
->Parent
->Supports
) | \
1080 EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
| \
1081 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
);
1085 // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were
1086 // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.
1087 // When this attribute is set, the PCI option ROM described by the RomImage and RomSize
1088 // fields is not from the the ROM BAR of the PCI controller.
1090 if (!PciIoDevice
->EmbeddedRom
) {
1091 Attributes
|= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
;
1093 PciIoDevice
->Attributes
= Attributes
;
1098 Determine if the device can support Fast Back to Back attribute.
1100 @param PciIoDevice Pci device instance.
1101 @param StatusIndex Status register value.
1103 @retval EFI_SUCCESS This device support Fast Back to Back attribute.
1104 @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.
1108 GetFastBackToBackSupport (
1109 IN PCI_IO_DEVICE
*PciIoDevice
,
1110 IN UINT8 StatusIndex
1113 EFI_PCI_IO_PROTOCOL
*PciIo
;
1115 UINT32 StatusRegister
;
1118 // Read the status register
1120 PciIo
= &PciIoDevice
->PciIo
;
1121 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, StatusIndex
, 1, &StatusRegister
);
1122 if (EFI_ERROR (Status
)) {
1123 return EFI_UNSUPPORTED
;
1127 // Check the Fast B2B bit
1129 if ((StatusRegister
& EFI_PCI_FAST_BACK_TO_BACK_CAPABLE
) != 0) {
1132 return EFI_UNSUPPORTED
;
1137 Process the option ROM for all the children of the specified parent PCI device.
1138 It can only be used after the first full Option ROM process.
1140 @param PciIoDevice Pci device instance.
1144 ProcessOptionRomLight (
1145 IN PCI_IO_DEVICE
*PciIoDevice
1148 PCI_IO_DEVICE
*Temp
;
1149 LIST_ENTRY
*CurrentLink
;
1152 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1154 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1155 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1157 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1159 if (!IsListEmpty (&Temp
->ChildList
)) {
1160 ProcessOptionRomLight (Temp
);
1163 PciRomGetImageMapping (Temp
);
1166 // The OpRom has already been processed in the first round
1168 Temp
->AllOpRomProcessed
= TRUE
;
1170 CurrentLink
= CurrentLink
->ForwardLink
;
1175 Determine the related attributes of all devices under a Root Bridge.
1177 @param PciIoDevice PCI device instance.
1181 DetermineDeviceAttribute (
1182 IN PCI_IO_DEVICE
*PciIoDevice
1186 UINT16 BridgeControl
;
1188 UINT16 OldBridgeControl
;
1189 BOOLEAN FastB2BSupport
;
1190 PCI_IO_DEVICE
*Temp
;
1191 LIST_ENTRY
*CurrentLink
;
1195 // For Root Bridge, just copy it by RootBridgeIo proctocol
1196 // so as to keep consistent with the actual attribute
1198 if (PciIoDevice
->Parent
== NULL
) {
1199 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
1200 PciIoDevice
->PciRootBridgeIo
,
1201 &PciIoDevice
->Supports
,
1202 &PciIoDevice
->Attributes
1204 if (EFI_ERROR (Status
)) {
1208 // Assume the PCI Root Bridge supports DAC
1210 PciIoDevice
->Supports
|= (UINT64
)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
1211 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
1212 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
);
1217 // Set the attributes to be checked for common PCI devices and PPB or P2C
1218 // Since some devices only support part of them, it is better to set the
1219 // attribute according to its command or bridge control register
1221 Command
= EFI_PCI_COMMAND_IO_SPACE
|
1222 EFI_PCI_COMMAND_MEMORY_SPACE
|
1223 EFI_PCI_COMMAND_BUS_MASTER
|
1224 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1226 BridgeControl
= EFI_PCI_BRIDGE_CONTROL_ISA
| EFI_PCI_BRIDGE_CONTROL_VGA
| EFI_PCI_BRIDGE_CONTROL_VGA_16
;
1229 // Test whether the device can support attributes above
1231 PciTestSupportedAttribute (PciIoDevice
, &Command
, &BridgeControl
, &OldCommand
, &OldBridgeControl
);
1234 // Set the supported attributes for specified PCI device
1236 PciSetDeviceAttribute (PciIoDevice
, Command
, BridgeControl
, EFI_SET_SUPPORTS
);
1239 // Set the current attributes for specified PCI device
1241 PciSetDeviceAttribute (PciIoDevice
, OldCommand
, OldBridgeControl
, EFI_SET_ATTRIBUTES
);
1244 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
1246 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE
);
1249 FastB2BSupport
= TRUE
;
1252 // P2C can not support FB2B on the secondary side
1254 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1255 FastB2BSupport
= FALSE
;
1259 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1261 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1262 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1264 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1265 Status
= DetermineDeviceAttribute (Temp
);
1266 if (EFI_ERROR (Status
)) {
1270 // Detect Fast Bact to Bact support for the device under the bridge
1272 Status
= GetFastBackToBackSupport (Temp
, PCI_PRIMARY_STATUS_OFFSET
);
1273 if (FastB2BSupport
&& EFI_ERROR (Status
)) {
1274 FastB2BSupport
= FALSE
;
1277 CurrentLink
= CurrentLink
->ForwardLink
;
1280 // Set or clear Fast Back to Back bit for the whole bridge
1282 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
1284 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
1286 Status
= GetFastBackToBackSupport (PciIoDevice
, PCI_BRIDGE_STATUS_REGISTER_OFFSET
);
1288 if (EFI_ERROR (Status
) || (!FastB2BSupport
)) {
1289 FastB2BSupport
= FALSE
;
1290 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1292 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1296 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1297 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1298 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1299 if (FastB2BSupport
) {
1300 PCI_ENABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1302 PCI_DISABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1305 CurrentLink
= CurrentLink
->ForwardLink
;
1309 // End for IsListEmpty
1315 This routine is used to update the bar information for those incompatible PCI device.
1317 @param PciIoDevice Input Pci device instance. Output Pci device instance with updated
1320 @retval EFI_SUCCESS Successfully updated bar information.
1321 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
1326 IN OUT PCI_IO_DEVICE
*PciIoDevice
1333 VOID
*Configuration
;
1334 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1336 Configuration
= NULL
;
1337 Status
= EFI_SUCCESS
;
1339 if (gEfiIncompatiblePciDeviceSupport
== NULL
) {
1341 // It can only be supported after the Incompatible PCI Device
1342 // Support Protocol has been installed
1344 Status
= gBS
->LocateProtocol (
1345 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
1347 (VOID
**) &gEfiIncompatiblePciDeviceSupport
1350 if (Status
== EFI_SUCCESS
) {
1352 // Check whether the device belongs to incompatible devices from protocol or not
1353 // If it is , then get its special requirement in the ACPI table
1355 Status
= gEfiIncompatiblePciDeviceSupport
->CheckDevice (
1356 gEfiIncompatiblePciDeviceSupport
,
1357 PciIoDevice
->Pci
.Hdr
.VendorId
,
1358 PciIoDevice
->Pci
.Hdr
.DeviceId
,
1359 PciIoDevice
->Pci
.Hdr
.RevisionID
,
1360 PciIoDevice
->Pci
.Device
.SubsystemVendorID
,
1361 PciIoDevice
->Pci
.Device
.SubsystemID
,
1367 if (EFI_ERROR (Status
) || Configuration
== NULL
) {
1368 return EFI_UNSUPPORTED
;
1372 // Update PCI device information from the ACPI table
1374 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1376 while (Ptr
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1378 if (Ptr
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1380 // The format is not support
1385 BarIndex
= (UINTN
) Ptr
->AddrTranslationOffset
;
1386 BarEndIndex
= BarIndex
;
1389 // Update all the bars in the device
1391 if (BarIndex
== PCI_BAR_ALL
) {
1393 BarEndIndex
= PCI_MAX_BAR
- 1;
1396 if (BarIndex
> PCI_MAX_BAR
) {
1401 for (; BarIndex
<= BarEndIndex
; BarIndex
++) {
1403 switch (Ptr
->ResType
) {
1404 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1407 // Make sure the bar is memory type
1409 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeMem
)) {
1414 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1417 // Make sure the bar is IO type
1419 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeIo
)) {
1428 // Update the new alignment for the device
1430 SetNewAlign (&(PciIoDevice
->PciBar
[BarIndex
].Alignment
), Ptr
->AddrRangeMax
);
1433 // Update the new length for the device
1435 if (Ptr
->AddrLen
!= PCI_BAR_NOCHANGE
) {
1436 PciIoDevice
->PciBar
[BarIndex
].Length
= Ptr
->AddrLen
;
1444 FreePool (Configuration
);
1450 This routine will update the alignment with the new alignment.
1452 @param Alignment Input Old alignment. Output updated alignment.
1453 @param NewAlignment New alignment.
1458 IN OUT UINT64
*Alignment
,
1459 IN UINT64 NewAlignment
1462 UINT64 OldAlignment
;
1466 // The new alignment is the same as the original,
1469 if (NewAlignment
== PCI_BAR_OLD_ALIGN
) {
1473 // Check the validity of the parameter
1475 if (NewAlignment
!= PCI_BAR_EVEN_ALIGN
&&
1476 NewAlignment
!= PCI_BAR_SQUAD_ALIGN
&&
1477 NewAlignment
!= PCI_BAR_DQUAD_ALIGN
) {
1478 *Alignment
= NewAlignment
;
1482 OldAlignment
= (*Alignment
) + 1;
1486 // Get the first non-zero hex value of the length
1488 while ((OldAlignment
& 0x0F) == 0x00) {
1489 OldAlignment
= RShiftU64 (OldAlignment
, 4);
1494 // Adjust the alignment to even, quad or double quad boundary
1496 if (NewAlignment
== PCI_BAR_EVEN_ALIGN
) {
1497 if ((OldAlignment
& 0x01) != 0) {
1498 OldAlignment
= OldAlignment
+ 2 - (OldAlignment
& 0x01);
1500 } else if (NewAlignment
== PCI_BAR_SQUAD_ALIGN
) {
1501 if ((OldAlignment
& 0x03) != 0) {
1502 OldAlignment
= OldAlignment
+ 4 - (OldAlignment
& 0x03);
1504 } else if (NewAlignment
== PCI_BAR_DQUAD_ALIGN
) {
1505 if ((OldAlignment
& 0x07) != 0) {
1506 OldAlignment
= OldAlignment
+ 8 - (OldAlignment
& 0x07);
1511 // Update the old value
1513 NewAlignment
= LShiftU64 (OldAlignment
, ShiftBit
) - 1;
1514 *Alignment
= NewAlignment
;
1520 Parse PCI IOV VF bar information and fill them into PCI device instance.
1522 @param PciIoDevice Pci device instance.
1523 @param Offset Bar offset.
1524 @param BarIndex Bar index.
1526 @return Next bar offset.
1531 IN PCI_IO_DEVICE
*PciIoDevice
,
1537 UINT32 OriginalValue
;
1542 // Ensure it is called properly
1544 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
1545 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
1552 Status
= VfBarExisted (
1559 if (EFI_ERROR (Status
)) {
1560 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1561 PciIoDevice
->VfPciBar
[BarIndex
].Length
= 0;
1562 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1565 // Scan all the BARs anyway
1567 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT16
) Offset
;
1571 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT16
) Offset
;
1572 if ((Value
& 0x01) != 0) {
1574 // Device I/Os. Impossible
1583 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1585 switch (Value
& 0x07) {
1588 //memory space; anywhere in 32 bit address space
1591 if ((Value
& 0x08) != 0) {
1592 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1594 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1597 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1598 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1603 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1607 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1608 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1614 // memory space; anywhere in 64 bit address space
1617 if ((Value
& 0x08) != 0) {
1618 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1620 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1624 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1625 // is regarded as an extension for the first bar. As a result
1626 // the sizing will be conducted on combined 64 bit value
1627 // Here just store the masked first 32bit value for future size
1630 PciIoDevice
->VfPciBar
[BarIndex
].Length
= Value
& Mask
;
1631 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1633 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1634 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1638 // Increment the offset to point to next DWORD
1642 Status
= VfBarExisted (
1649 if (EFI_ERROR (Status
)) {
1654 // Fix the length to support some spefic 64 bit BAR
1656 Value
|= ((UINT32
) -1 << HighBitSet32 (Value
));
1659 // Calculate the size of 64bit bar
1661 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1663 PciIoDevice
->VfPciBar
[BarIndex
].Length
= PciIoDevice
->VfPciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1664 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(PciIoDevice
->VfPciBar
[BarIndex
].Length
)) + 1;
1665 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1670 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1674 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1675 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1684 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1685 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1686 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1688 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1689 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1697 // Check the length again so as to keep compatible with some special bars
1699 if (PciIoDevice
->VfPciBar
[BarIndex
].Length
== 0) {
1700 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1701 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1702 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1706 // Increment number of bar
1712 Parse PCI bar information and fill them into PCI device instance.
1714 @param PciIoDevice Pci device instance.
1715 @param Offset Bar offset.
1716 @param BarIndex Bar index.
1718 @return Next bar offset.
1723 IN PCI_IO_DEVICE
*PciIoDevice
,
1729 UINT32 OriginalValue
;
1736 Status
= BarExisted (
1743 if (EFI_ERROR (Status
)) {
1744 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1745 PciIoDevice
->PciBar
[BarIndex
].Length
= 0;
1746 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1749 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1751 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1755 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1756 if ((Value
& 0x01) != 0) {
1762 if ((Value
& 0xFFFF0000) != 0) {
1766 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo32
;
1767 PciIoDevice
->PciBar
[BarIndex
].Length
= ((~(Value
& Mask
)) + 1);
1768 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1774 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo16
;
1775 PciIoDevice
->PciBar
[BarIndex
].Length
= 0x0000FFFF & ((~(Value
& Mask
)) + 1);
1776 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1780 // Workaround. Some platforms inplement IO bar with 0 length
1781 // Need to treat it as no-bar
1783 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1784 PciIoDevice
->PciBar
[BarIndex
].BarType
= (PCI_BAR_TYPE
) 0;
1787 PciIoDevice
->PciBar
[BarIndex
].Prefetchable
= FALSE
;
1788 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1794 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1796 switch (Value
& 0x07) {
1799 //memory space; anywhere in 32 bit address space
1802 if ((Value
& 0x08) != 0) {
1803 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1805 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1808 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1809 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1811 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1813 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1815 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1820 // memory space; anywhere in 64 bit address space
1823 if ((Value
& 0x08) != 0) {
1824 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1826 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1830 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1831 // is regarded as an extension for the first bar. As a result
1832 // the sizing will be conducted on combined 64 bit value
1833 // Here just store the masked first 32bit value for future size
1836 PciIoDevice
->PciBar
[BarIndex
].Length
= Value
& Mask
;
1837 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1840 // Increment the offset to point to next DWORD
1844 Status
= BarExisted (
1851 if (EFI_ERROR (Status
)) {
1853 // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
1855 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1857 // some device implement MMIO bar with 0 length, need to treat it as no-bar
1859 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1865 // Fix the length to support some spefic 64 bit BAR
1868 DEBUG ((EFI_D_INFO
, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
1869 Value
= (UINT32
) -1;
1871 Value
|= ((UINT32
)(-1) << HighBitSet32 (Value
));
1875 // Calculate the size of 64bit bar
1877 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1879 PciIoDevice
->PciBar
[BarIndex
].Length
= PciIoDevice
->PciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1880 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(PciIoDevice
->PciBar
[BarIndex
].Length
)) + 1;
1881 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1883 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1885 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1887 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1896 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1897 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1898 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1900 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1902 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1904 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1911 // Check the length again so as to keep compatible with some special bars
1913 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1914 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1915 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1916 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1920 // Increment number of bar
1926 This routine is used to initialize the bar of a PCI device.
1928 @param PciIoDevice Pci device instance.
1930 @note It can be called typically when a device is going to be rejected.
1934 InitializePciDevice (
1935 IN PCI_IO_DEVICE
*PciIoDevice
1938 EFI_PCI_IO_PROTOCOL
*PciIo
;
1941 PciIo
= &(PciIoDevice
->PciIo
);
1944 // Put all the resource apertures
1945 // Resource base is set to all ones so as to indicate its resource
1946 // has not been alloacted
1948 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
1949 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllOne
);
1954 This routine is used to initialize the bar of a PCI-PCI Bridge device.
1956 @param PciIoDevice PCI-PCI bridge device instance.
1961 IN PCI_IO_DEVICE
*PciIoDevice
1964 EFI_PCI_IO_PROTOCOL
*PciIo
;
1966 PciIo
= &(PciIoDevice
->PciIo
);
1969 // Put all the resource apertures including IO16
1970 // Io32, pMem32, pMem64 to quiescent state
1971 // Resource base all ones, Resource limit all zeros
1973 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
1974 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1D, 1, &gAllZero
);
1976 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x20, 1, &gAllOne
);
1977 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x22, 1, &gAllZero
);
1979 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x24, 1, &gAllOne
);
1980 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x26, 1, &gAllZero
);
1982 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllOne
);
1983 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2C, 1, &gAllZero
);
1986 // Don't support use io32 as for now
1988 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x30, 1, &gAllOne
);
1989 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x32, 1, &gAllZero
);
1992 // Force Interrupt line to zero for cards that come up randomly
1994 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1998 This routine is used to initialize the bar of a PCI Card Bridge device.
2000 @param PciIoDevice PCI Card bridge device.
2005 IN PCI_IO_DEVICE
*PciIoDevice
2008 EFI_PCI_IO_PROTOCOL
*PciIo
;
2010 PciIo
= &(PciIoDevice
->PciIo
);
2013 // Put all the resource apertures including IO16
2014 // Io32, pMem32, pMem64 to quiescent state(
2015 // Resource base all ones, Resource limit all zeros
2017 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x1c, 1, &gAllOne
);
2018 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x20, 1, &gAllZero
);
2020 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x24, 1, &gAllOne
);
2021 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllZero
);
2023 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2c, 1, &gAllOne
);
2024 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x30, 1, &gAllZero
);
2026 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x34, 1, &gAllOne
);
2027 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x38, 1, &gAllZero
);
2030 // Force Interrupt line to zero for cards that come up randomly
2032 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
2036 Create and initiliaze general PCI I/O device instance for
2037 PCI device/bridge device/hotplug bridge device.
2039 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2040 @param Pci Input Pci information block.
2041 @param Bus Device Bus NO.
2042 @param Device Device device NO.
2043 @param Func Device func NO.
2045 @return Instance of PCI device. NULL means no instance created.
2050 IN PCI_IO_DEVICE
*Bridge
,
2057 PCI_IO_DEVICE
*PciIoDevice
;
2058 EFI_PCI_IO_PROTOCOL
*PciIo
;
2061 PciIoDevice
= AllocateZeroPool (sizeof (PCI_IO_DEVICE
));
2062 if (PciIoDevice
== NULL
) {
2066 PciIoDevice
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
2067 PciIoDevice
->Handle
= NULL
;
2068 PciIoDevice
->PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
2069 PciIoDevice
->DevicePath
= NULL
;
2070 PciIoDevice
->BusNumber
= Bus
;
2071 PciIoDevice
->DeviceNumber
= Device
;
2072 PciIoDevice
->FunctionNumber
= Func
;
2073 PciIoDevice
->Decodes
= 0;
2075 if (gFullEnumeration
) {
2076 PciIoDevice
->Allocated
= FALSE
;
2078 PciIoDevice
->Allocated
= TRUE
;
2081 PciIoDevice
->Registered
= FALSE
;
2082 PciIoDevice
->Attributes
= 0;
2083 PciIoDevice
->Supports
= 0;
2084 PciIoDevice
->BusOverride
= FALSE
;
2085 PciIoDevice
->AllOpRomProcessed
= FALSE
;
2087 PciIoDevice
->IsPciExp
= FALSE
;
2089 CopyMem (&(PciIoDevice
->Pci
), Pci
, sizeof (PCI_TYPE01
));
2092 // Initialize the PCI I/O instance structure
2094 InitializePciIoInstance (PciIoDevice
);
2095 InitializePciDriverOverrideInstance (PciIoDevice
);
2096 InitializePciLoadFile2 (PciIoDevice
);
2097 PciIo
= &PciIoDevice
->PciIo
;
2100 // Create a device path for this PCI device and store it into its private data
2102 CreatePciDevicePath (
2108 // Detect if PCI Express Device
2110 PciIoDevice
->PciExpressCapabilityOffset
= 0;
2111 Status
= LocateCapabilityRegBlock (
2113 EFI_PCI_CAPABILITY_ID_PCIEXP
,
2114 &PciIoDevice
->PciExpressCapabilityOffset
,
2117 if (!EFI_ERROR (Status
)) {
2118 PciIoDevice
->IsPciExp
= TRUE
;
2121 if (PcdGetBool (PcdAriSupport
)) {
2123 // Check if the device is an ARI device.
2125 Status
= LocatePciExpressCapabilityRegBlock (
2127 EFI_PCIE_CAPABILITY_ID_ARI
,
2128 &PciIoDevice
->AriCapabilityOffset
,
2131 if (!EFI_ERROR (Status
)) {
2133 // We need to enable ARI feature before calculate BusReservation,
2134 // because FirstVFOffset and VFStride may change after that.
2136 EFI_PCI_IO_PROTOCOL
*ParentPciIo
;
2140 // Check if its parent supports ARI forwarding.
2142 ParentPciIo
= &Bridge
->PciIo
;
2143 ParentPciIo
->Pci
.Read (
2145 EfiPciIoWidthUint32
,
2146 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET
,
2150 if ((Data32
& EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING
) != 0) {
2152 // ARI forward support in bridge, so enable it.
2154 ParentPciIo
->Pci
.Read (
2156 EfiPciIoWidthUint32
,
2157 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
,
2161 if ((Data32
& EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING
) == 0) {
2162 Data32
|= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING
;
2163 ParentPciIo
->Pci
.Write (
2165 EfiPciIoWidthUint32
,
2166 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
,
2172 " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
2174 Bridge
->DeviceNumber
,
2175 Bridge
->FunctionNumber
2180 DEBUG ((EFI_D_INFO
, " ARI: CapOffset = 0x%x\n", PciIoDevice
->AriCapabilityOffset
));
2185 // Initialization for SR-IOV
2188 if (PcdGetBool (PcdSrIovSupport
)) {
2189 Status
= LocatePciExpressCapabilityRegBlock (
2191 EFI_PCIE_CAPABILITY_ID_SRIOV
,
2192 &PciIoDevice
->SrIovCapabilityOffset
,
2195 if (!EFI_ERROR (Status
)) {
2196 UINT32 SupportedPageSize
;
2198 UINT16 FirstVFOffset
;
2204 // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
2206 if (PcdGetBool (PcdAriSupport
) && PciIoDevice
->AriCapabilityOffset
!= 0) {
2209 EfiPciIoWidthUint16
,
2210 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
,
2214 Data16
|= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY
;
2217 EfiPciIoWidthUint16
,
2218 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
,
2225 // Calculate SystemPageSize
2230 EfiPciIoWidthUint32
,
2231 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE
,
2235 PciIoDevice
->SystemPageSize
= (PcdGet32 (PcdSrIovSystemPageSize
) & SupportedPageSize
);
2236 ASSERT (PciIoDevice
->SystemPageSize
!= 0);
2240 EfiPciIoWidthUint32
,
2241 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE
,
2243 &PciIoDevice
->SystemPageSize
2246 // Adjust SystemPageSize for Alignment usage later
2248 PciIoDevice
->SystemPageSize
<<= 12;
2251 // Calculate BusReservation for PCI IOV
2255 // Read First FirstVFOffset, InitialVFs, and VFStride
2259 EfiPciIoWidthUint16
,
2260 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF
,
2266 EfiPciIoWidthUint16
,
2267 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS
,
2269 &PciIoDevice
->InitialVFs
2273 EfiPciIoWidthUint16
,
2274 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE
,
2281 PFRid
= EFI_PCI_RID(Bus
, Device
, Func
);
2282 LastVF
= PFRid
+ FirstVFOffset
+ (PciIoDevice
->InitialVFs
- 1) * VFStride
;
2285 // Calculate ReservedBusNum for this PF
2287 PciIoDevice
->ReservedBusNum
= (UINT16
)(EFI_PCI_BUS_OF_RID (LastVF
) - Bus
+ 1);
2291 " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
2292 SupportedPageSize
, PciIoDevice
->SystemPageSize
>> 12, FirstVFOffset
2296 " InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
2297 PciIoDevice
->InitialVFs
, PciIoDevice
->ReservedBusNum
, PciIoDevice
->SrIovCapabilityOffset
2302 if (PcdGetBool (PcdMrIovSupport
)) {
2303 Status
= LocatePciExpressCapabilityRegBlock (
2305 EFI_PCIE_CAPABILITY_ID_MRIOV
,
2306 &PciIoDevice
->MrIovCapabilityOffset
,
2309 if (!EFI_ERROR (Status
)) {
2310 DEBUG ((EFI_D_INFO
, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice
->MrIovCapabilityOffset
));
2315 // Initialize the reserved resource list
2317 InitializeListHead (&PciIoDevice
->ReservedResourceList
);
2320 // Initialize the driver list
2322 InitializeListHead (&PciIoDevice
->OptionRomDriverList
);
2325 // Initialize the child list
2327 InitializeListHead (&PciIoDevice
->ChildList
);
2333 This routine is used to enumerate entire pci bus system
2334 in a given platform.
2336 It is only called on the second start on the same Root Bridge.
2338 @param Controller Parent bridge handler.
2340 @retval EFI_SUCCESS PCI enumeration finished successfully.
2341 @retval other Some error occurred when enumerating the pci bus system.
2345 PciEnumeratorLight (
2346 IN EFI_HANDLE Controller
2351 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2352 PCI_IO_DEVICE
*RootBridgeDev
;
2355 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
2358 MaxBus
= PCI_MAX_BUS
;
2362 // If this root bridge has been already enumerated, then return successfully
2364 if (GetRootBridgeByHandle (Controller
) != NULL
) {
2369 // Open pci root bridge io protocol
2371 Status
= gBS
->OpenProtocol (
2373 &gEfiPciRootBridgeIoProtocolGuid
,
2374 (VOID
**) &PciRootBridgeIo
,
2375 gPciBusDriverBinding
.DriverBindingHandle
,
2377 EFI_OPEN_PROTOCOL_BY_DRIVER
2379 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2383 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
2385 if (EFI_ERROR (Status
)) {
2389 while (PciGetBusRange (&Descriptors
, &MinBus
, &MaxBus
, NULL
) == EFI_SUCCESS
) {
2392 // Create a device node for root bridge device with a NULL host bridge controller handle
2394 RootBridgeDev
= CreateRootBridge (Controller
);
2396 if (RootBridgeDev
== NULL
) {
2402 // Record the root bridgeio protocol
2404 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2406 Status
= PciPciDeviceInfoCollector (
2411 if (!EFI_ERROR (Status
)) {
2414 // Remove those PCI devices which are rejected when full enumeration
2416 RemoveRejectedPciDevices (RootBridgeDev
->Handle
, RootBridgeDev
);
2419 // Process option rom light
2421 ProcessOptionRomLight (RootBridgeDev
);
2424 // Determine attributes for all devices under this root bridge
2426 DetermineDeviceAttribute (RootBridgeDev
);
2429 // If successfully, insert the node into device pool
2431 InsertRootBridge (RootBridgeDev
);
2435 // If unsuccessly, destroy the entire node
2437 DestroyRootBridge (RootBridgeDev
);
2447 Get bus range from PCI resource descriptor list.
2449 @param Descriptors A pointer to the address space descriptor.
2450 @param MinBus The min bus returned.
2451 @param MaxBus The max bus returned.
2452 @param BusRange The bus range returned.
2454 @retval EFI_SUCCESS Successfully got bus range.
2455 @retval EFI_NOT_FOUND Can not find the specific bus.
2460 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptors
,
2463 OUT UINT16
*BusRange
2466 while ((*Descriptors
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
2467 if ((*Descriptors
)->ResType
== ACPI_ADDRESS_SPACE_TYPE_BUS
) {
2468 if (MinBus
!= NULL
) {
2469 *MinBus
= (UINT16
) (*Descriptors
)->AddrRangeMin
;
2472 if (MaxBus
!= NULL
) {
2473 *MaxBus
= (UINT16
) (*Descriptors
)->AddrRangeMax
;
2476 if (BusRange
!= NULL
) {
2477 *BusRange
= (UINT16
) (*Descriptors
)->AddrLen
;
2486 return EFI_NOT_FOUND
;
2490 This routine can be used to start the root bridge.
2492 @param RootBridgeDev Pci device instance.
2494 @retval EFI_SUCCESS This device started.
2495 @retval other Failed to get PCI Root Bridge I/O protocol.
2499 StartManagingRootBridge (
2500 IN PCI_IO_DEVICE
*RootBridgeDev
2503 EFI_HANDLE RootBridgeHandle
;
2505 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2508 // Get the root bridge handle
2510 RootBridgeHandle
= RootBridgeDev
->Handle
;
2511 PciRootBridgeIo
= NULL
;
2514 // Get the pci root bridge io protocol
2516 Status
= gBS
->OpenProtocol (
2518 &gEfiPciRootBridgeIoProtocolGuid
,
2519 (VOID
**) &PciRootBridgeIo
,
2520 gPciBusDriverBinding
.DriverBindingHandle
,
2522 EFI_OPEN_PROTOCOL_BY_DRIVER
2525 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2530 // Store the PciRootBridgeIo protocol into root bridge private data
2532 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2539 This routine can be used to check whether a PCI device should be rejected when light enumeration.
2541 @param PciIoDevice Pci device instance.
2543 @retval TRUE This device should be rejected.
2544 @retval FALSE This device shouldn't be rejected.
2548 IsPciDeviceRejected (
2549 IN PCI_IO_DEVICE
*PciIoDevice
2559 // PPB should be skip!
2561 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
2565 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
2567 // Only test base registers for P2C
2569 for (BarOffset
= 0x1C; BarOffset
<= 0x38; BarOffset
+= 2 * sizeof (UINT32
)) {
2571 Mask
= (BarOffset
< 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
2572 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2573 if (EFI_ERROR (Status
)) {
2577 TestValue
= TestValue
& Mask
;
2578 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2580 // The bar isn't programed, so it should be rejected
2589 for (BarOffset
= 0x14; BarOffset
<= 0x24; BarOffset
+= sizeof (UINT32
)) {
2593 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2594 if (EFI_ERROR (Status
)) {
2598 if ((TestValue
& 0x01) != 0) {
2604 TestValue
= TestValue
& Mask
;
2605 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2615 TestValue
= TestValue
& Mask
;
2617 if ((TestValue
& 0x07) == 0x04) {
2622 BarOffset
+= sizeof (UINT32
);
2623 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2626 // Test its high 32-Bit BAR
2628 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2629 if (TestValue
== OldValue
) {
2639 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2650 Reset all bus number from specific bridge.
2652 @param Bridge Parent specific bridge.
2653 @param StartBusNumber Start bus number.
2657 ResetAllPpbBusNumber (
2658 IN PCI_IO_DEVICE
*Bridge
,
2659 IN UINT8 StartBusNumber
2669 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2671 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
2673 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
2674 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
2677 // Check to see whether a pci device is present
2679 Status
= PciDevicePresent (
2687 if (EFI_ERROR (Status
) && Func
== 0) {
2689 // go to next device if there is no Function 0
2694 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
))) {
2697 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
2698 Status
= PciRootBridgeIo
->Pci
.Read (
2705 SecondaryBus
= (UINT8
)(Register
>> 8);
2707 if (SecondaryBus
!= 0) {
2708 ResetAllPpbBusNumber (Bridge
, SecondaryBus
);
2712 // Reset register 18h, 19h, 1Ah on PCI Bridge
2714 Register
&= 0xFF000000;
2715 Status
= PciRootBridgeIo
->Pci
.Write (
2724 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
2726 // Skip sub functions, this is not a multi function device
2728 Func
= PCI_MAX_FUNC
;