2 PCI emumeration support functions implementation for PCI Bus module.
4 Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 extern CHAR16
*mBarTypeStr
[];
20 This routine is used to check whether the pci device is present.
22 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
23 @param Pci Output buffer for PCI device configuration space.
24 @param Bus PCI bus NO.
25 @param Device PCI device NO.
26 @param Func PCI Func NO.
28 @retval EFI_NOT_FOUND PCI device not present.
29 @retval EFI_SUCCESS PCI device is found.
34 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
45 // Create PCI address map in terms of Bus, Device and Func
47 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Func
, 0);
50 // Read the Vendor ID register
52 Status
= PciRootBridgeIo
->Pci
.Read (
60 if (!EFI_ERROR (Status
) && (Pci
->Hdr
).VendorId
!= 0xffff) {
62 // Read the entire config header for the device
64 Status
= PciRootBridgeIo
->Pci
.Read (
68 sizeof (PCI_TYPE00
) / sizeof (UINT32
),
79 Collect all the resource information under this root bridge.
81 A database that records all the information about pci device subject to this
82 root bridge will then be created.
84 @param Bridge Parent bridge instance.
85 @param StartBusNumber Bus number of begining.
87 @retval EFI_SUCCESS PCI device is found.
88 @retval other Some error occurred when reading PCI bridge information.
92 PciPciDeviceInfoCollector (
93 IN PCI_IO_DEVICE
*Bridge
,
94 IN UINT8 StartBusNumber
102 PCI_IO_DEVICE
*PciIoDevice
;
103 EFI_PCI_IO_PROTOCOL
*PciIo
;
105 Status
= EFI_SUCCESS
;
108 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
110 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
113 // Check to see whether PCI device is present
115 Status
= PciDevicePresent (
116 Bridge
->PciRootBridgeIo
,
118 (UINT8
) StartBusNumber
,
122 if (!EFI_ERROR (Status
)) {
125 // Call back to host bridge function
127 PreprocessController (Bridge
, (UINT8
) StartBusNumber
, Device
, Func
, EfiPciBeforeResourceCollection
);
130 // Collect all the information about the PCI device discovered
132 Status
= PciSearchDevice (
135 (UINT8
) StartBusNumber
,
142 // Recursively scan PCI busses on the other side of PCI-PCI bridges
145 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
148 // If it is PPB, we need to get the secondary bus to continue the enumeration
150 PciIo
= &(PciIoDevice
->PciIo
);
152 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET
, 1, &SecBus
);
154 if (EFI_ERROR (Status
)) {
159 // Get resource padding for PPB
161 GetResourcePaddingPpb (PciIoDevice
);
164 // Deep enumerate the next level bus
166 Status
= PciPciDeviceInfoCollector (
173 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
176 // Skip sub functions, this is not a multi function device
189 Seach required device and create PCI device instance.
191 @param Bridge Parent bridge instance.
192 @param Pci Input PCI device information block.
193 @param Bus PCI bus NO.
194 @param Device PCI device NO.
195 @param Func PCI func NO.
196 @param PciDevice Output of searched PCI device instance.
198 @retval EFI_SUCCESS Successfully created PCI device instance.
199 @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.
204 IN PCI_IO_DEVICE
*Bridge
,
209 OUT PCI_IO_DEVICE
**PciDevice
212 PCI_IO_DEVICE
*PciIoDevice
;
218 "PciBus: Discovered %s @ [%02x|%02x|%02x]\n",
219 IS_PCI_BRIDGE (Pci
) ? L
"PPB" :
220 IS_CARDBUS_BRIDGE (Pci
) ? L
"P2C" :
225 if (!IS_PCI_BRIDGE (Pci
)) {
227 if (IS_CARDBUS_BRIDGE (Pci
)) {
228 PciIoDevice
= GatherP2CInfo (
235 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
236 InitializeP2C (PciIoDevice
);
241 // Create private data for Pci Device
243 PciIoDevice
= GatherDeviceInfo (
256 // Create private data for PPB
258 PciIoDevice
= GatherPpbInfo (
267 // Special initialization for PPB including making the PPB quiet
269 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
270 InitializePpb (PciIoDevice
);
274 if (PciIoDevice
== NULL
) {
275 return EFI_OUT_OF_RESOURCES
;
279 // Update the bar information for this PCI device so as to support some specific device
281 UpdatePciInfo (PciIoDevice
);
283 if (PciIoDevice
->DevicePath
== NULL
) {
284 return EFI_OUT_OF_RESOURCES
;
288 // Detect this function has option rom
290 if (gFullEnumeration
) {
292 if (!IS_CARDBUS_BRIDGE (Pci
)) {
294 GetOpRomInfo (PciIoDevice
);
298 ResetPowerManagementFeature (PciIoDevice
);
303 // Insert it into a global tree for future reference
305 InsertPciDevice (Bridge
, PciIoDevice
);
308 // Determine PCI device attributes
311 if (PciDevice
!= NULL
) {
312 *PciDevice
= PciIoDevice
;
319 Dump the PCI BAR information.
321 @param PciIoDevice PCI IO instance.
325 IN PCI_IO_DEVICE
*PciIoDevice
330 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
331 if (PciIoDevice
->PciBar
[Index
].BarType
== PciBarTypeUnknown
) {
337 " BAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
338 Index
, mBarTypeStr
[MIN (PciIoDevice
->PciBar
[Index
].BarType
, PciBarTypeMaxType
)],
339 PciIoDevice
->PciBar
[Index
].Alignment
, PciIoDevice
->PciBar
[Index
].Length
, PciIoDevice
->PciBar
[Index
].Offset
343 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
344 if ((PciIoDevice
->VfPciBar
[Index
].BarType
== PciBarTypeUnknown
) && (PciIoDevice
->VfPciBar
[Index
].Length
== 0)) {
350 " VFBAR[%d]: Type = %s; Alignment = 0x%lx;\tLength = 0x%lx;\tOffset = 0x%02x\n",
351 Index
, mBarTypeStr
[MIN (PciIoDevice
->VfPciBar
[Index
].BarType
, PciBarTypeMaxType
)],
352 PciIoDevice
->VfPciBar
[Index
].Alignment
, PciIoDevice
->VfPciBar
[Index
].Length
, PciIoDevice
->VfPciBar
[Index
].Offset
355 DEBUG ((EFI_D_INFO
, "\n"));
359 Create PCI device instance for PCI device.
361 @param Bridge Parent bridge instance.
362 @param Pci Input PCI device information block.
363 @param Bus PCI device Bus NO.
364 @param Device PCI device Device NO.
365 @param Func PCI device's func NO.
367 @return Created PCI device instance.
372 IN PCI_IO_DEVICE
*Bridge
,
381 PCI_IO_DEVICE
*PciIoDevice
;
383 PciIoDevice
= CreatePciIoDevice (
391 if (PciIoDevice
== NULL
) {
396 // If it is a full enumeration, disconnect the device in advance
398 if (gFullEnumeration
) {
400 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
405 // Start to parse the bars
407 for (Offset
= 0x10, BarIndex
= 0; Offset
<= 0x24 && BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
408 Offset
= PciParseBar (PciIoDevice
, Offset
, BarIndex
);
412 // Parse the SR-IOV VF bars
414 if (PcdGetBool (PcdSrIovSupport
) && PciIoDevice
->SrIovCapabilityOffset
!= 0) {
415 for (Offset
= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0
, BarIndex
= 0;
416 Offset
<= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5
;
419 ASSERT (BarIndex
< PCI_MAX_BAR
);
420 Offset
= PciIovParseVfBar (PciIoDevice
, Offset
, BarIndex
);
424 DEBUG_CODE (DumpPciBars (PciIoDevice
););
429 Create PCI device instance for PCI-PCI bridge.
431 @param Bridge Parent bridge instance.
432 @param Pci Input PCI device information block.
433 @param Bus PCI device Bus NO.
434 @param Device PCI device Device NO.
435 @param Func PCI device's func NO.
437 @return Created PCI device instance.
442 IN PCI_IO_DEVICE
*Bridge
,
449 PCI_IO_DEVICE
*PciIoDevice
;
452 EFI_PCI_IO_PROTOCOL
*PciIo
;
454 UINT32 PMemBaseLimit
;
455 UINT16 PrefetchableMemoryBase
;
456 UINT16 PrefetchableMemoryLimit
;
458 PciIoDevice
= CreatePciIoDevice (
466 if (PciIoDevice
== NULL
) {
470 if (gFullEnumeration
) {
471 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
474 // Initalize the bridge control register
476 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED
);
481 // PPB can have two BARs
483 if (PciParseBar (PciIoDevice
, 0x10, PPB_BAR_0
) == 0x14) {
487 PciParseBar (PciIoDevice
, 0x14, PPB_BAR_1
);
490 PciIo
= &PciIoDevice
->PciIo
;
493 // Test whether it support 32 decode or not
495 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
496 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
497 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
498 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
501 if ((Value
& 0x01) != 0) {
502 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
504 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
509 // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes
510 // PCI bridge supporting non-stardard I/O window alignment less than 4K.
513 PciIoDevice
->BridgeIoAlignment
= 0xFFF;
514 if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
)) {
516 // Check any bits of bit 3-1 of I/O Base Register are writable.
517 // if so, it is assumed non-stardard I/O window alignment is supported by this bridge.
518 // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.
520 Value
= (UINT8
)(Temp
^ (BIT3
| BIT2
| BIT1
));
521 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
522 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
523 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
524 Value
= (UINT8
)((Value
^ Temp
) & (BIT3
| BIT2
| BIT1
));
527 PciIoDevice
->BridgeIoAlignment
= 0x7FF;
530 PciIoDevice
->BridgeIoAlignment
= 0x3FF;
532 case BIT3
| BIT2
| BIT1
:
533 PciIoDevice
->BridgeIoAlignment
= 0x1FF;
538 Status
= BarExisted (
546 // Test if it supports 64 memory or not
548 // The bottom 4 bits of both the Prefetchable Memory Base and Prefetchable Memory Limit
550 // 0 - the bridge supports only 32 bit addresses.
551 // 1 - the bridge supports 64-bit addresses.
553 PrefetchableMemoryBase
= (UINT16
)(PMemBaseLimit
& 0xffff);
554 PrefetchableMemoryLimit
= (UINT16
)(PMemBaseLimit
>> 16);
555 if (!EFI_ERROR (Status
) &&
556 (PrefetchableMemoryBase
& 0x000f) == 0x0001 &&
557 (PrefetchableMemoryLimit
& 0x000f) == 0x0001) {
558 Status
= BarExisted (
565 if (!EFI_ERROR (Status
)) {
566 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
567 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
569 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
574 // Memory 32 code is required for ppb
576 PciIoDevice
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
578 GetResourcePaddingPpb (PciIoDevice
);
580 DEBUG_CODE (DumpPciBars (PciIoDevice
););
587 Create PCI device instance for PCI Card bridge device.
589 @param Bridge Parent bridge instance.
590 @param Pci Input PCI device information block.
591 @param Bus PCI device Bus NO.
592 @param Device PCI device Device NO.
593 @param Func PCI device's func NO.
595 @return Created PCI device instance.
600 IN PCI_IO_DEVICE
*Bridge
,
607 PCI_IO_DEVICE
*PciIoDevice
;
609 PciIoDevice
= CreatePciIoDevice (
617 if (PciIoDevice
== NULL
) {
621 if (gFullEnumeration
) {
622 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
625 // Initalize the bridge control register
627 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED
);
631 // P2C only has one bar that is in 0x10
633 PciParseBar (PciIoDevice
, 0x10, P2C_BAR_0
);
636 // Read PciBar information from the bar register
638 GetBackPcCardBar (PciIoDevice
);
639 PciIoDevice
->Decodes
= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
|
640 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
|
641 EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
643 DEBUG_CODE (DumpPciBars (PciIoDevice
););
649 Create device path for pci deivce.
651 @param ParentDevicePath Parent bridge's path.
652 @param PciIoDevice Pci device instance.
654 @return Device path protocol instance for specific pci device.
657 EFI_DEVICE_PATH_PROTOCOL
*
658 CreatePciDevicePath (
659 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
660 IN PCI_IO_DEVICE
*PciIoDevice
664 PCI_DEVICE_PATH PciNode
;
667 // Create PCI device path
669 PciNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
670 PciNode
.Header
.SubType
= HW_PCI_DP
;
671 SetDevicePathNodeLength (&PciNode
.Header
, sizeof (PciNode
));
673 PciNode
.Device
= PciIoDevice
->DeviceNumber
;
674 PciNode
.Function
= PciIoDevice
->FunctionNumber
;
675 PciIoDevice
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, &PciNode
.Header
);
677 return PciIoDevice
->DevicePath
;
681 Check whether the PCI IOV VF bar is existed or not.
683 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
684 @param Offset The offset.
685 @param BarLengthValue The bar length value returned.
686 @param OriginalBarValue The original bar value returned.
688 @retval EFI_NOT_FOUND The bar doesn't exist.
689 @retval EFI_SUCCESS The bar exist.
694 IN PCI_IO_DEVICE
*PciIoDevice
,
696 OUT UINT32
*BarLengthValue
,
697 OUT UINT32
*OriginalBarValue
700 EFI_PCI_IO_PROTOCOL
*PciIo
;
701 UINT32 OriginalValue
;
706 // Ensure it is called properly
708 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
709 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
710 return EFI_NOT_FOUND
;
713 PciIo
= &PciIoDevice
->PciIo
;
716 // Preserve the original value
719 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
722 // Raise TPL to high level to disable timer interrupt while the BAR is probed
724 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
726 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &gAllOne
);
727 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &Value
);
730 // Write back the original value
732 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
735 // Restore TPL to its original level
737 gBS
->RestoreTPL (OldTpl
);
739 if (BarLengthValue
!= NULL
) {
740 *BarLengthValue
= Value
;
743 if (OriginalBarValue
!= NULL
) {
744 *OriginalBarValue
= OriginalValue
;
748 return EFI_NOT_FOUND
;
755 Check whether the bar is existed or not.
757 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
758 @param Offset The offset.
759 @param BarLengthValue The bar length value returned.
760 @param OriginalBarValue The original bar value returned.
762 @retval EFI_NOT_FOUND The bar doesn't exist.
763 @retval EFI_SUCCESS The bar exist.
768 IN PCI_IO_DEVICE
*PciIoDevice
,
770 OUT UINT32
*BarLengthValue
,
771 OUT UINT32
*OriginalBarValue
774 EFI_PCI_IO_PROTOCOL
*PciIo
;
775 UINT32 OriginalValue
;
779 PciIo
= &PciIoDevice
->PciIo
;
782 // Preserve the original value
784 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
787 // Raise TPL to high level to disable timer interrupt while the BAR is probed
789 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
791 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &gAllOne
);
792 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &Value
);
795 // Write back the original value
797 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
800 // Restore TPL to its original level
802 gBS
->RestoreTPL (OldTpl
);
804 if (BarLengthValue
!= NULL
) {
805 *BarLengthValue
= Value
;
808 if (OriginalBarValue
!= NULL
) {
809 *OriginalBarValue
= OriginalValue
;
813 return EFI_NOT_FOUND
;
820 Test whether the device can support given attributes.
822 @param PciIoDevice Pci device instance.
823 @param Command Input command register value, and
824 returned supported register value.
825 @param BridgeControl Inout bridge control value for PPB or P2C, and
826 returned supported bridge control value.
827 @param OldCommand Returned and stored old command register offset.
828 @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
832 PciTestSupportedAttribute (
833 IN PCI_IO_DEVICE
*PciIoDevice
,
834 IN OUT UINT16
*Command
,
835 IN OUT UINT16
*BridgeControl
,
836 OUT UINT16
*OldCommand
,
837 OUT UINT16
*OldBridgeControl
843 // Preserve the original value
845 PCI_READ_COMMAND_REGISTER (PciIoDevice
, OldCommand
);
848 // Raise TPL to high level to disable timer interrupt while the BAR is probed
850 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
852 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *Command
);
853 PCI_READ_COMMAND_REGISTER (PciIoDevice
, Command
);
856 // Write back the original value
858 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *OldCommand
);
861 // Restore TPL to its original level
863 gBS
->RestoreTPL (OldTpl
);
865 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
868 // Preserve the original value
870 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, OldBridgeControl
);
873 // Raise TPL to high level to disable timer interrupt while the BAR is probed
875 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
877 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *BridgeControl
);
878 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, BridgeControl
);
881 // Write back the original value
883 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *OldBridgeControl
);
886 // Restore TPL to its original level
888 gBS
->RestoreTPL (OldTpl
);
891 *OldBridgeControl
= 0;
897 Set the supported or current attributes of a PCI device.
899 @param PciIoDevice Structure pointer for PCI device.
900 @param Command Command register value.
901 @param BridgeControl Bridge control value for PPB or P2C.
902 @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
906 PciSetDeviceAttribute (
907 IN PCI_IO_DEVICE
*PciIoDevice
,
909 IN UINT16 BridgeControl
,
917 if ((Command
& EFI_PCI_COMMAND_IO_SPACE
) != 0) {
918 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IO
;
921 if ((Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) != 0) {
922 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY
;
925 if ((Command
& EFI_PCI_COMMAND_BUS_MASTER
) != 0) {
926 Attributes
|= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
;
929 if ((Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
930 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
933 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
) != 0) {
934 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
937 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
) != 0) {
938 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
939 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
940 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
943 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
) != 0) {
944 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
;
945 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
;
948 if (Option
== EFI_SET_SUPPORTS
) {
950 Attributes
|= (UINT64
) (EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
951 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
|
952 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE
|
953 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
954 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
955 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
);
957 if (IS_PCI_LPC (&PciIoDevice
->Pci
)) {
958 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
959 Attributes
|= (mReserveIsaAliases
? (UINT64
) EFI_PCI_IO_ATTRIBUTE_ISA_IO
: \
960 (UINT64
) EFI_PCI_IO_ATTRIBUTE_ISA_IO_16
);
963 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
965 // For bridge, it should support IDE attributes
967 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
968 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
970 if (mReserveVgaAliases
) {
971 Attributes
&= ~(UINT64
)(EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
| \
972 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
);
974 Attributes
&= ~(UINT64
)(EFI_PCI_IO_ATTRIBUTE_VGA_IO
| \
975 EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
);
979 if (IS_PCI_IDE (&PciIoDevice
->Pci
)) {
980 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
981 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
984 if (IS_PCI_VGA (&PciIoDevice
->Pci
)) {
985 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
986 Attributes
|= (mReserveVgaAliases
? (UINT64
) EFI_PCI_IO_ATTRIBUTE_VGA_IO
: \
987 (UINT64
) EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
);
991 PciIoDevice
->Supports
= Attributes
;
992 PciIoDevice
->Supports
&= ( (PciIoDevice
->Parent
->Supports
) | \
993 EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
| \
994 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
);
998 // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were
999 // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.
1000 // When this attribute is set, the PCI option ROM described by the RomImage and RomSize
1001 // fields is not from the the ROM BAR of the PCI controller.
1003 if (!PciIoDevice
->EmbeddedRom
) {
1004 Attributes
|= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
;
1006 PciIoDevice
->Attributes
= Attributes
;
1011 Determine if the device can support Fast Back to Back attribute.
1013 @param PciIoDevice Pci device instance.
1014 @param StatusIndex Status register value.
1016 @retval EFI_SUCCESS This device support Fast Back to Back attribute.
1017 @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.
1021 GetFastBackToBackSupport (
1022 IN PCI_IO_DEVICE
*PciIoDevice
,
1023 IN UINT8 StatusIndex
1026 EFI_PCI_IO_PROTOCOL
*PciIo
;
1028 UINT32 StatusRegister
;
1031 // Read the status register
1033 PciIo
= &PciIoDevice
->PciIo
;
1034 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, StatusIndex
, 1, &StatusRegister
);
1035 if (EFI_ERROR (Status
)) {
1036 return EFI_UNSUPPORTED
;
1040 // Check the Fast B2B bit
1042 if ((StatusRegister
& EFI_PCI_FAST_BACK_TO_BACK_CAPABLE
) != 0) {
1045 return EFI_UNSUPPORTED
;
1050 Process the option ROM for all the children of the specified parent PCI device.
1051 It can only be used after the first full Option ROM process.
1053 @param PciIoDevice Pci device instance.
1057 ProcessOptionRomLight (
1058 IN PCI_IO_DEVICE
*PciIoDevice
1061 PCI_IO_DEVICE
*Temp
;
1062 LIST_ENTRY
*CurrentLink
;
1065 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1067 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1068 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1070 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1072 if (!IsListEmpty (&Temp
->ChildList
)) {
1073 ProcessOptionRomLight (Temp
);
1076 PciRomGetImageMapping (Temp
);
1079 // The OpRom has already been processed in the first round
1081 Temp
->AllOpRomProcessed
= TRUE
;
1083 CurrentLink
= CurrentLink
->ForwardLink
;
1088 Determine the related attributes of all devices under a Root Bridge.
1090 @param PciIoDevice PCI device instance.
1094 DetermineDeviceAttribute (
1095 IN PCI_IO_DEVICE
*PciIoDevice
1099 UINT16 BridgeControl
;
1101 UINT16 OldBridgeControl
;
1102 BOOLEAN FastB2BSupport
;
1103 PCI_IO_DEVICE
*Temp
;
1104 LIST_ENTRY
*CurrentLink
;
1108 // For Root Bridge, just copy it by RootBridgeIo proctocol
1109 // so as to keep consistent with the actual attribute
1111 if (PciIoDevice
->Parent
== NULL
) {
1112 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
1113 PciIoDevice
->PciRootBridgeIo
,
1114 &PciIoDevice
->Supports
,
1115 &PciIoDevice
->Attributes
1117 if (EFI_ERROR (Status
)) {
1121 // Assume the PCI Root Bridge supports DAC
1123 PciIoDevice
->Supports
|= (UINT64
)(EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
1124 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
1125 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
);
1130 // Set the attributes to be checked for common PCI devices and PPB or P2C
1131 // Since some devices only support part of them, it is better to set the
1132 // attribute according to its command or bridge control register
1134 Command
= EFI_PCI_COMMAND_IO_SPACE
|
1135 EFI_PCI_COMMAND_MEMORY_SPACE
|
1136 EFI_PCI_COMMAND_BUS_MASTER
|
1137 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1139 BridgeControl
= EFI_PCI_BRIDGE_CONTROL_ISA
| EFI_PCI_BRIDGE_CONTROL_VGA
| EFI_PCI_BRIDGE_CONTROL_VGA_16
;
1142 // Test whether the device can support attributes above
1144 PciTestSupportedAttribute (PciIoDevice
, &Command
, &BridgeControl
, &OldCommand
, &OldBridgeControl
);
1147 // Set the supported attributes for specified PCI device
1149 PciSetDeviceAttribute (PciIoDevice
, Command
, BridgeControl
, EFI_SET_SUPPORTS
);
1152 // Set the current attributes for specified PCI device
1154 PciSetDeviceAttribute (PciIoDevice
, OldCommand
, OldBridgeControl
, EFI_SET_ATTRIBUTES
);
1157 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
1159 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE
);
1162 FastB2BSupport
= TRUE
;
1165 // P2C can not support FB2B on the secondary side
1167 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1168 FastB2BSupport
= FALSE
;
1172 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1174 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1175 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1177 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1178 Status
= DetermineDeviceAttribute (Temp
);
1179 if (EFI_ERROR (Status
)) {
1183 // Detect Fast Bact to Bact support for the device under the bridge
1185 Status
= GetFastBackToBackSupport (Temp
, PCI_PRIMARY_STATUS_OFFSET
);
1186 if (FastB2BSupport
&& EFI_ERROR (Status
)) {
1187 FastB2BSupport
= FALSE
;
1190 CurrentLink
= CurrentLink
->ForwardLink
;
1193 // Set or clear Fast Back to Back bit for the whole bridge
1195 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
1197 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
1199 Status
= GetFastBackToBackSupport (PciIoDevice
, PCI_BRIDGE_STATUS_REGISTER_OFFSET
);
1201 if (EFI_ERROR (Status
) || (!FastB2BSupport
)) {
1202 FastB2BSupport
= FALSE
;
1203 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1205 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1209 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1210 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1211 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1212 if (FastB2BSupport
) {
1213 PCI_ENABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1215 PCI_DISABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1218 CurrentLink
= CurrentLink
->ForwardLink
;
1222 // End for IsListEmpty
1228 This routine is used to update the bar information for those incompatible PCI device.
1230 @param PciIoDevice Input Pci device instance. Output Pci device instance with updated
1233 @retval EFI_SUCCESS Successfully updated bar information.
1234 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
1239 IN OUT PCI_IO_DEVICE
*PciIoDevice
1246 VOID
*Configuration
;
1247 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1249 Configuration
= NULL
;
1250 Status
= EFI_SUCCESS
;
1252 if (gEfiIncompatiblePciDeviceSupport
== NULL
) {
1254 // It can only be supported after the Incompatible PCI Device
1255 // Support Protocol has been installed
1257 Status
= gBS
->LocateProtocol (
1258 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
1260 (VOID
**) &gEfiIncompatiblePciDeviceSupport
1263 if (Status
== EFI_SUCCESS
) {
1265 // Check whether the device belongs to incompatible devices from protocol or not
1266 // If it is , then get its special requirement in the ACPI table
1268 Status
= gEfiIncompatiblePciDeviceSupport
->CheckDevice (
1269 gEfiIncompatiblePciDeviceSupport
,
1270 PciIoDevice
->Pci
.Hdr
.VendorId
,
1271 PciIoDevice
->Pci
.Hdr
.DeviceId
,
1272 PciIoDevice
->Pci
.Hdr
.RevisionID
,
1273 PciIoDevice
->Pci
.Device
.SubsystemVendorID
,
1274 PciIoDevice
->Pci
.Device
.SubsystemID
,
1280 if (EFI_ERROR (Status
) || Configuration
== NULL
) {
1281 return EFI_UNSUPPORTED
;
1285 // Update PCI device information from the ACPI table
1287 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1289 while (Ptr
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1291 if (Ptr
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1293 // The format is not support
1298 BarIndex
= (UINTN
) Ptr
->AddrTranslationOffset
;
1299 BarEndIndex
= BarIndex
;
1302 // Update all the bars in the device
1304 if (BarIndex
== PCI_BAR_ALL
) {
1306 BarEndIndex
= PCI_MAX_BAR
- 1;
1309 if (BarIndex
> PCI_MAX_BAR
) {
1314 for (; BarIndex
<= BarEndIndex
; BarIndex
++) {
1316 switch (Ptr
->ResType
) {
1317 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1320 // Make sure the bar is memory type
1322 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeMem
)) {
1327 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1330 // Make sure the bar is IO type
1332 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeIo
)) {
1341 // Update the new alignment for the device
1343 SetNewAlign (&(PciIoDevice
->PciBar
[BarIndex
].Alignment
), Ptr
->AddrRangeMax
);
1346 // Update the new length for the device
1348 if (Ptr
->AddrLen
!= PCI_BAR_NOCHANGE
) {
1349 PciIoDevice
->PciBar
[BarIndex
].Length
= Ptr
->AddrLen
;
1357 FreePool (Configuration
);
1363 This routine will update the alignment with the new alignment.
1365 @param Alignment Input Old alignment. Output updated alignment.
1366 @param NewAlignment New alignment.
1371 IN OUT UINT64
*Alignment
,
1372 IN UINT64 NewAlignment
1375 UINT64 OldAlignment
;
1379 // The new alignment is the same as the original,
1382 if (NewAlignment
== PCI_BAR_OLD_ALIGN
) {
1386 // Check the validity of the parameter
1388 if (NewAlignment
!= PCI_BAR_EVEN_ALIGN
&&
1389 NewAlignment
!= PCI_BAR_SQUAD_ALIGN
&&
1390 NewAlignment
!= PCI_BAR_DQUAD_ALIGN
) {
1391 *Alignment
= NewAlignment
;
1395 OldAlignment
= (*Alignment
) + 1;
1399 // Get the first non-zero hex value of the length
1401 while ((OldAlignment
& 0x0F) == 0x00) {
1402 OldAlignment
= RShiftU64 (OldAlignment
, 4);
1407 // Adjust the alignment to even, quad or double quad boundary
1409 if (NewAlignment
== PCI_BAR_EVEN_ALIGN
) {
1410 if ((OldAlignment
& 0x01) != 0) {
1411 OldAlignment
= OldAlignment
+ 2 - (OldAlignment
& 0x01);
1413 } else if (NewAlignment
== PCI_BAR_SQUAD_ALIGN
) {
1414 if ((OldAlignment
& 0x03) != 0) {
1415 OldAlignment
= OldAlignment
+ 4 - (OldAlignment
& 0x03);
1417 } else if (NewAlignment
== PCI_BAR_DQUAD_ALIGN
) {
1418 if ((OldAlignment
& 0x07) != 0) {
1419 OldAlignment
= OldAlignment
+ 8 - (OldAlignment
& 0x07);
1424 // Update the old value
1426 NewAlignment
= LShiftU64 (OldAlignment
, ShiftBit
) - 1;
1427 *Alignment
= NewAlignment
;
1433 Parse PCI IOV VF bar information and fill them into PCI device instance.
1435 @param PciIoDevice Pci device instance.
1436 @param Offset Bar offset.
1437 @param BarIndex Bar index.
1439 @return Next bar offset.
1444 IN PCI_IO_DEVICE
*PciIoDevice
,
1450 UINT32 OriginalValue
;
1455 // Ensure it is called properly
1457 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
1458 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
1465 Status
= VfBarExisted (
1472 if (EFI_ERROR (Status
)) {
1473 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1474 PciIoDevice
->VfPciBar
[BarIndex
].Length
= 0;
1475 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1478 // Scan all the BARs anyway
1480 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT16
) Offset
;
1484 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT16
) Offset
;
1485 if ((Value
& 0x01) != 0) {
1487 // Device I/Os. Impossible
1496 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1498 switch (Value
& 0x07) {
1501 //memory space; anywhere in 32 bit address space
1504 if ((Value
& 0x08) != 0) {
1505 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1507 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1510 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1511 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1516 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1520 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1521 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1527 // memory space; anywhere in 64 bit address space
1530 if ((Value
& 0x08) != 0) {
1531 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1533 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1537 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1538 // is regarded as an extension for the first bar. As a result
1539 // the sizing will be conducted on combined 64 bit value
1540 // Here just store the masked first 32bit value for future size
1543 PciIoDevice
->VfPciBar
[BarIndex
].Length
= Value
& Mask
;
1544 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1546 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1547 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1551 // Increment the offset to point to next DWORD
1555 Status
= VfBarExisted (
1562 if (EFI_ERROR (Status
)) {
1567 // Fix the length to support some spefic 64 bit BAR
1569 Value
|= ((UINT32
) -1 << HighBitSet32 (Value
));
1572 // Calculate the size of 64bit bar
1574 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1576 PciIoDevice
->VfPciBar
[BarIndex
].Length
= PciIoDevice
->VfPciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1577 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(PciIoDevice
->VfPciBar
[BarIndex
].Length
)) + 1;
1578 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1583 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1587 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1588 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1597 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1598 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1599 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1601 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1602 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1610 // Check the length again so as to keep compatible with some special bars
1612 if (PciIoDevice
->VfPciBar
[BarIndex
].Length
== 0) {
1613 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1614 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1615 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1619 // Increment number of bar
1625 Parse PCI bar information and fill them into PCI device instance.
1627 @param PciIoDevice Pci device instance.
1628 @param Offset Bar offset.
1629 @param BarIndex Bar index.
1631 @return Next bar offset.
1636 IN PCI_IO_DEVICE
*PciIoDevice
,
1642 UINT32 OriginalValue
;
1649 Status
= BarExisted (
1656 if (EFI_ERROR (Status
)) {
1657 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1658 PciIoDevice
->PciBar
[BarIndex
].Length
= 0;
1659 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1662 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1664 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1668 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1669 if ((Value
& 0x01) != 0) {
1675 if ((Value
& 0xFFFF0000) != 0) {
1679 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo32
;
1680 PciIoDevice
->PciBar
[BarIndex
].Length
= ((~(Value
& Mask
)) + 1);
1681 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1687 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo16
;
1688 PciIoDevice
->PciBar
[BarIndex
].Length
= 0x0000FFFF & ((~(Value
& Mask
)) + 1);
1689 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1693 // Workaround. Some platforms inplement IO bar with 0 length
1694 // Need to treat it as no-bar
1696 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1697 PciIoDevice
->PciBar
[BarIndex
].BarType
= (PCI_BAR_TYPE
) 0;
1700 PciIoDevice
->PciBar
[BarIndex
].Prefetchable
= FALSE
;
1701 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1707 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1709 switch (Value
& 0x07) {
1712 //memory space; anywhere in 32 bit address space
1715 if ((Value
& 0x08) != 0) {
1716 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1718 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1721 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1722 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1724 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1726 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1728 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1733 // memory space; anywhere in 64 bit address space
1736 if ((Value
& 0x08) != 0) {
1737 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1739 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1743 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1744 // is regarded as an extension for the first bar. As a result
1745 // the sizing will be conducted on combined 64 bit value
1746 // Here just store the masked first 32bit value for future size
1749 PciIoDevice
->PciBar
[BarIndex
].Length
= Value
& Mask
;
1750 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1753 // Increment the offset to point to next DWORD
1757 Status
= BarExisted (
1764 if (EFI_ERROR (Status
)) {
1766 // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
1768 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1770 // some device implement MMIO bar with 0 length, need to treat it as no-bar
1772 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1778 // Fix the length to support some spefic 64 bit BAR
1781 DEBUG ((EFI_D_INFO
, "[PciBus]BAR probing for upper 32bit of MEM64 BAR returns 0, change to 0xFFFFFFFF.\n"));
1782 Value
= (UINT32
) -1;
1784 Value
|= ((UINT32
)(-1) << HighBitSet32 (Value
));
1788 // Calculate the size of 64bit bar
1790 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1792 PciIoDevice
->PciBar
[BarIndex
].Length
= PciIoDevice
->PciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1793 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(PciIoDevice
->PciBar
[BarIndex
].Length
)) + 1;
1794 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1796 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1798 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1800 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1809 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1810 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1811 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1813 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1815 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1817 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1824 // Check the length again so as to keep compatible with some special bars
1826 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1827 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1828 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1829 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1833 // Increment number of bar
1839 This routine is used to initialize the bar of a PCI device.
1841 @param PciIoDevice Pci device instance.
1843 @note It can be called typically when a device is going to be rejected.
1847 InitializePciDevice (
1848 IN PCI_IO_DEVICE
*PciIoDevice
1851 EFI_PCI_IO_PROTOCOL
*PciIo
;
1854 PciIo
= &(PciIoDevice
->PciIo
);
1857 // Put all the resource apertures
1858 // Resource base is set to all ones so as to indicate its resource
1859 // has not been alloacted
1861 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
1862 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllOne
);
1867 This routine is used to initialize the bar of a PCI-PCI Bridge device.
1869 @param PciIoDevice PCI-PCI bridge device instance.
1874 IN PCI_IO_DEVICE
*PciIoDevice
1877 EFI_PCI_IO_PROTOCOL
*PciIo
;
1879 PciIo
= &(PciIoDevice
->PciIo
);
1882 // Put all the resource apertures including IO16
1883 // Io32, pMem32, pMem64 to quiescent state
1884 // Resource base all ones, Resource limit all zeros
1886 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
1887 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1D, 1, &gAllZero
);
1889 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x20, 1, &gAllOne
);
1890 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x22, 1, &gAllZero
);
1892 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x24, 1, &gAllOne
);
1893 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x26, 1, &gAllZero
);
1895 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllOne
);
1896 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2C, 1, &gAllZero
);
1899 // Don't support use io32 as for now
1901 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x30, 1, &gAllOne
);
1902 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x32, 1, &gAllZero
);
1905 // Force Interrupt line to zero for cards that come up randomly
1907 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1911 This routine is used to initialize the bar of a PCI Card Bridge device.
1913 @param PciIoDevice PCI Card bridge device.
1918 IN PCI_IO_DEVICE
*PciIoDevice
1921 EFI_PCI_IO_PROTOCOL
*PciIo
;
1923 PciIo
= &(PciIoDevice
->PciIo
);
1926 // Put all the resource apertures including IO16
1927 // Io32, pMem32, pMem64 to quiescent state(
1928 // Resource base all ones, Resource limit all zeros
1930 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x1c, 1, &gAllOne
);
1931 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x20, 1, &gAllZero
);
1933 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x24, 1, &gAllOne
);
1934 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllZero
);
1936 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2c, 1, &gAllOne
);
1937 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x30, 1, &gAllZero
);
1939 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x34, 1, &gAllOne
);
1940 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x38, 1, &gAllZero
);
1943 // Force Interrupt line to zero for cards that come up randomly
1945 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1949 Create and initiliaze general PCI I/O device instance for
1950 PCI device/bridge device/hotplug bridge device.
1952 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1953 @param Pci Input Pci information block.
1954 @param Bus Device Bus NO.
1955 @param Device Device device NO.
1956 @param Func Device func NO.
1958 @return Instance of PCI device. NULL means no instance created.
1963 IN PCI_IO_DEVICE
*Bridge
,
1970 PCI_IO_DEVICE
*PciIoDevice
;
1971 EFI_PCI_IO_PROTOCOL
*PciIo
;
1974 PciIoDevice
= AllocateZeroPool (sizeof (PCI_IO_DEVICE
));
1975 if (PciIoDevice
== NULL
) {
1979 PciIoDevice
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
1980 PciIoDevice
->Handle
= NULL
;
1981 PciIoDevice
->PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1982 PciIoDevice
->DevicePath
= NULL
;
1983 PciIoDevice
->BusNumber
= Bus
;
1984 PciIoDevice
->DeviceNumber
= Device
;
1985 PciIoDevice
->FunctionNumber
= Func
;
1986 PciIoDevice
->Decodes
= 0;
1988 if (gFullEnumeration
) {
1989 PciIoDevice
->Allocated
= FALSE
;
1991 PciIoDevice
->Allocated
= TRUE
;
1994 PciIoDevice
->Registered
= FALSE
;
1995 PciIoDevice
->Attributes
= 0;
1996 PciIoDevice
->Supports
= 0;
1997 PciIoDevice
->BusOverride
= FALSE
;
1998 PciIoDevice
->AllOpRomProcessed
= FALSE
;
2000 PciIoDevice
->IsPciExp
= FALSE
;
2002 CopyMem (&(PciIoDevice
->Pci
), Pci
, sizeof (PCI_TYPE01
));
2005 // Initialize the PCI I/O instance structure
2007 InitializePciIoInstance (PciIoDevice
);
2008 InitializePciDriverOverrideInstance (PciIoDevice
);
2009 InitializePciLoadFile2 (PciIoDevice
);
2010 PciIo
= &PciIoDevice
->PciIo
;
2013 // Create a device path for this PCI device and store it into its private data
2015 CreatePciDevicePath (
2021 // Detect if PCI Express Device
2023 PciIoDevice
->PciExpressCapabilityOffset
= 0;
2024 Status
= LocateCapabilityRegBlock (
2026 EFI_PCI_CAPABILITY_ID_PCIEXP
,
2027 &PciIoDevice
->PciExpressCapabilityOffset
,
2030 if (!EFI_ERROR (Status
)) {
2031 PciIoDevice
->IsPciExp
= TRUE
;
2034 if (PcdGetBool (PcdAriSupport
)) {
2036 // Check if the device is an ARI device.
2038 Status
= LocatePciExpressCapabilityRegBlock (
2040 EFI_PCIE_CAPABILITY_ID_ARI
,
2041 &PciIoDevice
->AriCapabilityOffset
,
2044 if (!EFI_ERROR (Status
)) {
2046 // We need to enable ARI feature before calculate BusReservation,
2047 // because FirstVFOffset and VFStride may change after that.
2049 EFI_PCI_IO_PROTOCOL
*ParentPciIo
;
2053 // Check if its parent supports ARI forwarding.
2055 ParentPciIo
= &Bridge
->PciIo
;
2056 ParentPciIo
->Pci
.Read (
2058 EfiPciIoWidthUint32
,
2059 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET
,
2063 if ((Data32
& EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING
) != 0) {
2065 // ARI forward support in bridge, so enable it.
2067 ParentPciIo
->Pci
.Read (
2069 EfiPciIoWidthUint32
,
2070 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
,
2074 if ((Data32
& EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING
) == 0) {
2075 Data32
|= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING
;
2076 ParentPciIo
->Pci
.Write (
2078 EfiPciIoWidthUint32
,
2079 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
,
2085 " ARI: forwarding enabled for PPB[%02x:%02x:%02x]\n",
2087 Bridge
->DeviceNumber
,
2088 Bridge
->FunctionNumber
2093 DEBUG ((EFI_D_INFO
, " ARI: CapOffset = 0x%x\n", PciIoDevice
->AriCapabilityOffset
));
2098 // Initialization for SR-IOV
2101 if (PcdGetBool (PcdSrIovSupport
)) {
2102 Status
= LocatePciExpressCapabilityRegBlock (
2104 EFI_PCIE_CAPABILITY_ID_SRIOV
,
2105 &PciIoDevice
->SrIovCapabilityOffset
,
2108 if (!EFI_ERROR (Status
)) {
2109 UINT32 SupportedPageSize
;
2111 UINT16 FirstVFOffset
;
2117 // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
2119 if (PcdGetBool (PcdAriSupport
) && PciIoDevice
->AriCapabilityOffset
!= 0) {
2122 EfiPciIoWidthUint16
,
2123 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
,
2127 Data16
|= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY
;
2130 EfiPciIoWidthUint16
,
2131 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
,
2138 // Calculate SystemPageSize
2143 EfiPciIoWidthUint32
,
2144 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE
,
2148 PciIoDevice
->SystemPageSize
= (PcdGet32 (PcdSrIovSystemPageSize
) & SupportedPageSize
);
2149 ASSERT (PciIoDevice
->SystemPageSize
!= 0);
2153 EfiPciIoWidthUint32
,
2154 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE
,
2156 &PciIoDevice
->SystemPageSize
2159 // Adjust SystemPageSize for Alignment usage later
2161 PciIoDevice
->SystemPageSize
<<= 12;
2164 // Calculate BusReservation for PCI IOV
2168 // Read First FirstVFOffset, InitialVFs, and VFStride
2172 EfiPciIoWidthUint16
,
2173 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF
,
2179 EfiPciIoWidthUint16
,
2180 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS
,
2182 &PciIoDevice
->InitialVFs
2186 EfiPciIoWidthUint16
,
2187 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE
,
2194 PFRid
= EFI_PCI_RID(Bus
, Device
, Func
);
2195 LastVF
= PFRid
+ FirstVFOffset
+ (PciIoDevice
->InitialVFs
- 1) * VFStride
;
2198 // Calculate ReservedBusNum for this PF
2200 PciIoDevice
->ReservedBusNum
= (UINT16
)(EFI_PCI_BUS_OF_RID (LastVF
) - Bus
+ 1);
2204 " SR-IOV: SupportedPageSize = 0x%x; SystemPageSize = 0x%x; FirstVFOffset = 0x%x;\n",
2205 SupportedPageSize
, PciIoDevice
->SystemPageSize
>> 12, FirstVFOffset
2209 " InitialVFs = 0x%x; ReservedBusNum = 0x%x; CapOffset = 0x%x\n",
2210 PciIoDevice
->InitialVFs
, PciIoDevice
->ReservedBusNum
, PciIoDevice
->SrIovCapabilityOffset
2215 if (PcdGetBool (PcdMrIovSupport
)) {
2216 Status
= LocatePciExpressCapabilityRegBlock (
2218 EFI_PCIE_CAPABILITY_ID_MRIOV
,
2219 &PciIoDevice
->MrIovCapabilityOffset
,
2222 if (!EFI_ERROR (Status
)) {
2223 DEBUG ((EFI_D_INFO
, " MR-IOV: CapOffset = 0x%x\n", PciIoDevice
->MrIovCapabilityOffset
));
2228 // Initialize the reserved resource list
2230 InitializeListHead (&PciIoDevice
->ReservedResourceList
);
2233 // Initialize the driver list
2235 InitializeListHead (&PciIoDevice
->OptionRomDriverList
);
2238 // Initialize the child list
2240 InitializeListHead (&PciIoDevice
->ChildList
);
2246 This routine is used to enumerate entire pci bus system
2247 in a given platform.
2249 It is only called on the second start on the same Root Bridge.
2251 @param Controller Parent bridge handler.
2253 @retval EFI_SUCCESS PCI enumeration finished successfully.
2254 @retval other Some error occurred when enumerating the pci bus system.
2258 PciEnumeratorLight (
2259 IN EFI_HANDLE Controller
2264 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2265 PCI_IO_DEVICE
*RootBridgeDev
;
2268 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
2271 MaxBus
= PCI_MAX_BUS
;
2275 // If this root bridge has been already enumerated, then return successfully
2277 if (GetRootBridgeByHandle (Controller
) != NULL
) {
2282 // Open pci root bridge io protocol
2284 Status
= gBS
->OpenProtocol (
2286 &gEfiPciRootBridgeIoProtocolGuid
,
2287 (VOID
**) &PciRootBridgeIo
,
2288 gPciBusDriverBinding
.DriverBindingHandle
,
2290 EFI_OPEN_PROTOCOL_BY_DRIVER
2292 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2296 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
2298 if (EFI_ERROR (Status
)) {
2302 while (PciGetBusRange (&Descriptors
, &MinBus
, &MaxBus
, NULL
) == EFI_SUCCESS
) {
2305 // Create a device node for root bridge device with a NULL host bridge controller handle
2307 RootBridgeDev
= CreateRootBridge (Controller
);
2309 if (RootBridgeDev
== NULL
) {
2315 // Record the root bridgeio protocol
2317 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2319 Status
= PciPciDeviceInfoCollector (
2324 if (!EFI_ERROR (Status
)) {
2327 // Remove those PCI devices which are rejected when full enumeration
2329 RemoveRejectedPciDevices (RootBridgeDev
->Handle
, RootBridgeDev
);
2332 // Process option rom light
2334 ProcessOptionRomLight (RootBridgeDev
);
2337 // Determine attributes for all devices under this root bridge
2339 DetermineDeviceAttribute (RootBridgeDev
);
2342 // If successfully, insert the node into device pool
2344 InsertRootBridge (RootBridgeDev
);
2348 // If unsuccessly, destroy the entire node
2350 DestroyRootBridge (RootBridgeDev
);
2360 Get bus range from PCI resource descriptor list.
2362 @param Descriptors A pointer to the address space descriptor.
2363 @param MinBus The min bus returned.
2364 @param MaxBus The max bus returned.
2365 @param BusRange The bus range returned.
2367 @retval EFI_SUCCESS Successfully got bus range.
2368 @retval EFI_NOT_FOUND Can not find the specific bus.
2373 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptors
,
2376 OUT UINT16
*BusRange
2379 while ((*Descriptors
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
2380 if ((*Descriptors
)->ResType
== ACPI_ADDRESS_SPACE_TYPE_BUS
) {
2381 if (MinBus
!= NULL
) {
2382 *MinBus
= (UINT16
) (*Descriptors
)->AddrRangeMin
;
2385 if (MaxBus
!= NULL
) {
2386 *MaxBus
= (UINT16
) (*Descriptors
)->AddrRangeMax
;
2389 if (BusRange
!= NULL
) {
2390 *BusRange
= (UINT16
) (*Descriptors
)->AddrLen
;
2399 return EFI_NOT_FOUND
;
2403 This routine can be used to start the root bridge.
2405 @param RootBridgeDev Pci device instance.
2407 @retval EFI_SUCCESS This device started.
2408 @retval other Failed to get PCI Root Bridge I/O protocol.
2412 StartManagingRootBridge (
2413 IN PCI_IO_DEVICE
*RootBridgeDev
2416 EFI_HANDLE RootBridgeHandle
;
2418 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2421 // Get the root bridge handle
2423 RootBridgeHandle
= RootBridgeDev
->Handle
;
2424 PciRootBridgeIo
= NULL
;
2427 // Get the pci root bridge io protocol
2429 Status
= gBS
->OpenProtocol (
2431 &gEfiPciRootBridgeIoProtocolGuid
,
2432 (VOID
**) &PciRootBridgeIo
,
2433 gPciBusDriverBinding
.DriverBindingHandle
,
2435 EFI_OPEN_PROTOCOL_BY_DRIVER
2438 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2443 // Store the PciRootBridgeIo protocol into root bridge private data
2445 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2452 This routine can be used to check whether a PCI device should be rejected when light enumeration.
2454 @param PciIoDevice Pci device instance.
2456 @retval TRUE This device should be rejected.
2457 @retval FALSE This device shouldn't be rejected.
2461 IsPciDeviceRejected (
2462 IN PCI_IO_DEVICE
*PciIoDevice
2472 // PPB should be skip!
2474 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
2478 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
2480 // Only test base registers for P2C
2482 for (BarOffset
= 0x1C; BarOffset
<= 0x38; BarOffset
+= 2 * sizeof (UINT32
)) {
2484 Mask
= (BarOffset
< 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
2485 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2486 if (EFI_ERROR (Status
)) {
2490 TestValue
= TestValue
& Mask
;
2491 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2493 // The bar isn't programed, so it should be rejected
2502 for (BarOffset
= 0x14; BarOffset
<= 0x24; BarOffset
+= sizeof (UINT32
)) {
2506 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2507 if (EFI_ERROR (Status
)) {
2511 if ((TestValue
& 0x01) != 0) {
2517 TestValue
= TestValue
& Mask
;
2518 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2528 TestValue
= TestValue
& Mask
;
2530 if ((TestValue
& 0x07) == 0x04) {
2535 BarOffset
+= sizeof (UINT32
);
2536 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2539 // Test its high 32-Bit BAR
2541 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2542 if (TestValue
== OldValue
) {
2552 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2563 Reset all bus number from specific bridge.
2565 @param Bridge Parent specific bridge.
2566 @param StartBusNumber Start bus number.
2570 ResetAllPpbBusNumber (
2571 IN PCI_IO_DEVICE
*Bridge
,
2572 IN UINT8 StartBusNumber
2582 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2584 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
2586 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
2587 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
2590 // Check to see whether a pci device is present
2592 Status
= PciDevicePresent (
2600 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
))) {
2603 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
2604 Status
= PciRootBridgeIo
->Pci
.Read (
2611 SecondaryBus
= (UINT8
)(Register
>> 8);
2613 if (SecondaryBus
!= 0) {
2614 ResetAllPpbBusNumber (Bridge
, SecondaryBus
);
2618 // Reset register 18h, 19h, 1Ah on PCI Bridge
2620 Register
&= 0xFF000000;
2621 Status
= PciRootBridgeIo
->Pci
.Write (
2630 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
2632 // Skip sub functions, this is not a multi function device
2634 Func
= PCI_MAX_FUNC
;