2 PCI emumeration support functions implementation for PCI Bus module.
4 Copyright (c) 2006 - 2010, 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.
18 This routine is used to check whether the pci device is present.
20 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
21 @param Pci Output buffer for PCI device configuration space.
22 @param Bus PCI bus NO.
23 @param Device PCI device NO.
24 @param Func PCI Func NO.
26 @retval EFI_NOT_FOUND PCI device not present.
27 @retval EFI_SUCCESS PCI device is found.
32 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
43 // Create PCI address map in terms of Bus, Device and Func
45 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Func
, 0);
48 // Read the Vendor ID register
50 Status
= PciRootBridgeIo
->Pci
.Read (
58 if (!EFI_ERROR (Status
) && (Pci
->Hdr
).VendorId
!= 0xffff) {
60 // Read the entire config header for the device
62 Status
= PciRootBridgeIo
->Pci
.Read (
66 sizeof (PCI_TYPE00
) / sizeof (UINT32
),
77 Collect all the resource information under this root bridge.
79 A database that records all the information about pci device subject to this
80 root bridge will then be created.
82 @param Bridge Parent bridge instance.
83 @param StartBusNumber Bus number of begining.
85 @retval EFI_SUCCESS PCI device is found.
86 @retval other Some error occurred when reading PCI bridge information.
90 PciPciDeviceInfoCollector (
91 IN PCI_IO_DEVICE
*Bridge
,
92 IN UINT8 StartBusNumber
100 PCI_IO_DEVICE
*PciIoDevice
;
101 EFI_PCI_IO_PROTOCOL
*PciIo
;
103 Status
= EFI_SUCCESS
;
106 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
108 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
111 // Check to see whether PCI device is present
113 Status
= PciDevicePresent (
114 Bridge
->PciRootBridgeIo
,
116 (UINT8
) StartBusNumber
,
120 if (!EFI_ERROR (Status
)) {
123 // Call back to host bridge function
125 PreprocessController (Bridge
, (UINT8
) StartBusNumber
, Device
, Func
, EfiPciBeforeResourceCollection
);
128 // Collect all the information about the PCI device discovered
130 Status
= PciSearchDevice (
133 (UINT8
) StartBusNumber
,
140 // Recursively scan PCI busses on the other side of PCI-PCI bridges
143 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
146 // If it is PPB, we need to get the secondary bus to continue the enumeration
148 PciIo
= &(PciIoDevice
->PciIo
);
150 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET
, 1, &SecBus
);
152 if (EFI_ERROR (Status
)) {
157 // Get resource padding for PPB
159 GetResourcePaddingPpb (PciIoDevice
);
162 // Deep enumerate the next level bus
164 Status
= PciPciDeviceInfoCollector (
171 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
174 // Skip sub functions, this is not a multi function device
187 Seach required device and create PCI device instance.
189 @param Bridge Parent bridge instance.
190 @param Pci Input PCI device information block.
191 @param Bus PCI bus NO.
192 @param Device PCI device NO.
193 @param Func PCI func NO.
194 @param PciDevice Output of searched PCI device instance.
196 @retval EFI_SUCCESS Successfully created PCI device instance.
197 @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.
202 IN PCI_IO_DEVICE
*Bridge
,
207 OUT PCI_IO_DEVICE
**PciDevice
210 PCI_IO_DEVICE
*PciIoDevice
;
214 if (!IS_PCI_BRIDGE (Pci
)) {
216 if (IS_CARDBUS_BRIDGE (Pci
)) {
217 PciIoDevice
= GatherP2CInfo (
224 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
225 InitializeP2C (PciIoDevice
);
230 // Create private data for Pci Device
232 PciIoDevice
= GatherDeviceInfo (
245 // Create private data for PPB
247 PciIoDevice
= GatherPpbInfo (
256 // Special initialization for PPB including making the PPB quiet
258 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
259 InitializePpb (PciIoDevice
);
263 if (PciIoDevice
== NULL
) {
264 return EFI_OUT_OF_RESOURCES
;
268 // Update the bar information for this PCI device so as to support some specific device
270 UpdatePciInfo (PciIoDevice
);
272 if (PciIoDevice
->DevicePath
== NULL
) {
273 return EFI_OUT_OF_RESOURCES
;
277 // Detect this function has option rom
279 if (gFullEnumeration
) {
281 if (!IS_CARDBUS_BRIDGE (Pci
)) {
283 GetOpRomInfo (PciIoDevice
);
287 ResetPowerManagementFeature (PciIoDevice
);
292 // Insert it into a global tree for future reference
294 InsertPciDevice (Bridge
, PciIoDevice
);
297 // Determine PCI device attributes
300 if (PciDevice
!= NULL
) {
301 *PciDevice
= PciIoDevice
;
308 Create PCI device instance for PCI device.
310 @param Bridge Parent bridge instance.
311 @param Pci Input PCI device information block.
312 @param Bus PCI device Bus NO.
313 @param Device PCI device Device NO.
314 @param Func PCI device's func NO.
316 @return Created PCI device instance.
321 IN PCI_IO_DEVICE
*Bridge
,
330 PCI_IO_DEVICE
*PciIoDevice
;
332 PciIoDevice
= CreatePciIoDevice (
340 if (PciIoDevice
== NULL
) {
345 // Create a device path for this PCI device and store it into its private data
347 CreatePciDevicePath (
353 // If it is a full enumeration, disconnect the device in advance
355 if (gFullEnumeration
) {
357 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
362 // Start to parse the bars
364 for (Offset
= 0x10, BarIndex
= 0; Offset
<= 0x24 && BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
365 Offset
= PciParseBar (PciIoDevice
, Offset
, BarIndex
);
369 // Parse the SR-IOV VF bars
371 if (PcdGetBool (PcdSrIovSupport
) && PciIoDevice
->SrIovCapabilityOffset
!= 0) {
372 for (Offset
= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0
, BarIndex
= 0;
373 Offset
<= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5
;
376 ASSERT (BarIndex
< PCI_MAX_BAR
);
377 Offset
= PciIovParseVfBar (PciIoDevice
, Offset
, BarIndex
);
384 Create PCI device instance for PCI-PCI bridge.
386 @param Bridge Parent bridge instance.
387 @param Pci Input PCI device information block.
388 @param Bus PCI device Bus NO.
389 @param Device PCI device Device NO.
390 @param Func PCI device's func NO.
392 @return Created PCI device instance.
397 IN PCI_IO_DEVICE
*Bridge
,
404 PCI_IO_DEVICE
*PciIoDevice
;
407 EFI_PCI_IO_PROTOCOL
*PciIo
;
410 PciIoDevice
= CreatePciIoDevice (
418 if (PciIoDevice
== NULL
) {
423 // Create a device path for this PCI device and store it into its private data
425 CreatePciDevicePath (
430 if (gFullEnumeration
) {
431 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
434 // Initalize the bridge control register
436 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED
);
441 // PPB can have two BARs
443 if (PciParseBar (PciIoDevice
, 0x10, PPB_BAR_0
) == 0x14) {
447 PciParseBar (PciIoDevice
, 0x14, PPB_BAR_1
);
450 PciIo
= &PciIoDevice
->PciIo
;
453 // Test whether it support 32 decode or not
455 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
456 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
457 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
458 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
461 if ((Value
& 0x01) != 0) {
462 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
464 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
469 // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes
470 // PCI bridge supporting non-stardard I/O window alignment less than 4K.
473 PciIoDevice
->BridgeIoAlignment
= 0xFFF;
474 if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
)) {
476 // Check any bits of bit 3-1 of I/O Base Register are writable.
477 // if so, it is assumed non-stardard I/O window alignment is supported by this bridge.
478 // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.
480 Value
= (UINT8
)(Temp
^ (BIT3
| BIT2
| BIT1
));
481 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
482 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
483 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
484 Value
= (UINT8
)((Value
^ Temp
) & (BIT3
| BIT2
| BIT1
));
487 PciIoDevice
->BridgeIoAlignment
= 0x7FF;
490 PciIoDevice
->BridgeIoAlignment
= 0x3FF;
492 case BIT3
| BIT2
| BIT1
:
493 PciIoDevice
->BridgeIoAlignment
= 0x1FF;
498 Status
= BarExisted (
506 // Test if it supports 64 memory or not
508 if (!EFI_ERROR (Status
)) {
510 Status
= BarExisted (
517 if (!EFI_ERROR (Status
)) {
518 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
519 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
521 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
526 // Memory 32 code is required for ppb
528 PciIoDevice
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
530 GetResourcePaddingPpb (PciIoDevice
);
537 Create PCI device instance for PCI Card bridge device.
539 @param Bridge Parent bridge instance.
540 @param Pci Input PCI device information block.
541 @param Bus PCI device Bus NO.
542 @param Device PCI device Device NO.
543 @param Func PCI device's func NO.
545 @return Created PCI device instance.
550 IN PCI_IO_DEVICE
*Bridge
,
557 PCI_IO_DEVICE
*PciIoDevice
;
559 PciIoDevice
= CreatePciIoDevice (
567 if (PciIoDevice
== NULL
) {
572 // Create a device path for this PCI device and store it into its private data
574 CreatePciDevicePath (
579 if (gFullEnumeration
) {
580 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
583 // Initalize the bridge control register
585 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED
);
589 // P2C only has one bar that is in 0x10
591 PciParseBar (PciIoDevice
, 0x10, P2C_BAR_0
);
594 // Read PciBar information from the bar register
596 GetBackPcCardBar (PciIoDevice
);
597 PciIoDevice
->Decodes
= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
|
598 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
|
599 EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
605 Create device path for pci deivce.
607 @param ParentDevicePath Parent bridge's path.
608 @param PciIoDevice Pci device instance.
610 @return Device path protocol instance for specific pci device.
613 EFI_DEVICE_PATH_PROTOCOL
*
614 CreatePciDevicePath (
615 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
616 IN PCI_IO_DEVICE
*PciIoDevice
620 PCI_DEVICE_PATH PciNode
;
623 // Create PCI device path
625 PciNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
626 PciNode
.Header
.SubType
= HW_PCI_DP
;
627 SetDevicePathNodeLength (&PciNode
.Header
, sizeof (PciNode
));
629 PciNode
.Device
= PciIoDevice
->DeviceNumber
;
630 PciNode
.Function
= PciIoDevice
->FunctionNumber
;
631 PciIoDevice
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, &PciNode
.Header
);
633 return PciIoDevice
->DevicePath
;
637 Check whether the PCI IOV VF bar is existed or not.
639 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
640 @param Offset The offset.
641 @param BarLengthValue The bar length value returned.
642 @param OriginalBarValue The original bar value returned.
644 @retval EFI_NOT_FOUND The bar doesn't exist.
645 @retval EFI_SUCCESS The bar exist.
650 IN PCI_IO_DEVICE
*PciIoDevice
,
652 OUT UINT32
*BarLengthValue
,
653 OUT UINT32
*OriginalBarValue
656 EFI_PCI_IO_PROTOCOL
*PciIo
;
657 UINT32 OriginalValue
;
662 // Ensure it is called properly
664 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
665 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
666 return EFI_NOT_FOUND
;
669 PciIo
= &PciIoDevice
->PciIo
;
672 // Preserve the original value
675 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
678 // Raise TPL to high level to disable timer interrupt while the BAR is probed
680 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
682 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &gAllOne
);
683 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &Value
);
686 // Write back the original value
688 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
691 // Restore TPL to its original level
693 gBS
->RestoreTPL (OldTpl
);
695 if (BarLengthValue
!= NULL
) {
696 *BarLengthValue
= Value
;
699 if (OriginalBarValue
!= NULL
) {
700 *OriginalBarValue
= OriginalValue
;
704 return EFI_NOT_FOUND
;
711 Check whether the bar is existed or not.
713 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
714 @param Offset The offset.
715 @param BarLengthValue The bar length value returned.
716 @param OriginalBarValue The original bar value returned.
718 @retval EFI_NOT_FOUND The bar doesn't exist.
719 @retval EFI_SUCCESS The bar exist.
724 IN PCI_IO_DEVICE
*PciIoDevice
,
726 OUT UINT32
*BarLengthValue
,
727 OUT UINT32
*OriginalBarValue
730 EFI_PCI_IO_PROTOCOL
*PciIo
;
731 UINT32 OriginalValue
;
735 PciIo
= &PciIoDevice
->PciIo
;
738 // Preserve the original value
740 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
743 // Raise TPL to high level to disable timer interrupt while the BAR is probed
745 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
747 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &gAllOne
);
748 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &Value
);
751 // Write back the original value
753 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
756 // Restore TPL to its original level
758 gBS
->RestoreTPL (OldTpl
);
760 if (BarLengthValue
!= NULL
) {
761 *BarLengthValue
= Value
;
764 if (OriginalBarValue
!= NULL
) {
765 *OriginalBarValue
= OriginalValue
;
769 return EFI_NOT_FOUND
;
776 Test whether the device can support given attributes.
778 @param PciIoDevice Pci device instance.
779 @param Command Input command register value, and
780 returned supported register value.
781 @param BridgeControl Inout bridge control value for PPB or P2C, and
782 returned supported bridge control value.
783 @param OldCommand Returned and stored old command register offset.
784 @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
788 PciTestSupportedAttribute (
789 IN PCI_IO_DEVICE
*PciIoDevice
,
790 IN OUT UINT16
*Command
,
791 IN OUT UINT16
*BridgeControl
,
792 OUT UINT16
*OldCommand
,
793 OUT UINT16
*OldBridgeControl
799 // Preserve the original value
801 PCI_READ_COMMAND_REGISTER (PciIoDevice
, OldCommand
);
804 // Raise TPL to high level to disable timer interrupt while the BAR is probed
806 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
808 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *Command
);
809 PCI_READ_COMMAND_REGISTER (PciIoDevice
, Command
);
812 // Write back the original value
814 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *OldCommand
);
817 // Restore TPL to its original level
819 gBS
->RestoreTPL (OldTpl
);
821 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
824 // Preserve the original value
826 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, OldBridgeControl
);
829 // Raise TPL to high level to disable timer interrupt while the BAR is probed
831 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
833 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *BridgeControl
);
834 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, BridgeControl
);
837 // Write back the original value
839 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *OldBridgeControl
);
842 // Restore TPL to its original level
844 gBS
->RestoreTPL (OldTpl
);
847 *OldBridgeControl
= 0;
853 Set the supported or current attributes of a PCI device.
855 @param PciIoDevice Structure pointer for PCI device.
856 @param Command Command register value.
857 @param BridgeControl Bridge control value for PPB or P2C.
858 @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
862 PciSetDeviceAttribute (
863 IN PCI_IO_DEVICE
*PciIoDevice
,
865 IN UINT16 BridgeControl
,
873 if ((Command
& EFI_PCI_COMMAND_IO_SPACE
) != 0) {
874 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IO
;
877 if ((Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) != 0) {
878 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY
;
881 if ((Command
& EFI_PCI_COMMAND_BUS_MASTER
) != 0) {
882 Attributes
|= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
;
885 if ((Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
886 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
889 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
) != 0) {
890 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
893 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
) != 0) {
894 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
895 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
896 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
899 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
) != 0) {
900 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
;
901 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
;
904 if (Option
== EFI_SET_SUPPORTS
) {
906 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
907 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
|
908 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE
|
909 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
910 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
911 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
;
913 if ((Attributes
& EFI_PCI_IO_ATTRIBUTE_IO
) != 0) {
914 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
915 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
918 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
920 // For bridge, it should support IDE attributes
922 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
923 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
926 if (IS_PCI_IDE (&PciIoDevice
->Pci
)) {
927 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
928 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
931 if (IS_PCI_VGA (&PciIoDevice
->Pci
)) {
932 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
933 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
937 PciIoDevice
->Supports
= Attributes
;
938 PciIoDevice
->Supports
&= ( (PciIoDevice
->Parent
->Supports
) | \
939 EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
| \
940 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
);
944 // When this attribute is clear, the RomImage and RomSize fields in the PCI IO were
945 // initialized based on the PCI option ROM found through the ROM BAR of the PCI controller.
946 // When this attribute is set, the PCI option ROM described by the RomImage and RomSize
947 // fields is not from the the ROM BAR of the PCI controller.
949 if (!PciIoDevice
->EmbeddedRom
) {
950 Attributes
|= EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
;
952 PciIoDevice
->Attributes
= Attributes
;
957 Determine if the device can support Fast Back to Back attribute.
959 @param PciIoDevice Pci device instance.
960 @param StatusIndex Status register value.
962 @retval EFI_SUCCESS This device support Fast Back to Back attribute.
963 @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.
967 GetFastBackToBackSupport (
968 IN PCI_IO_DEVICE
*PciIoDevice
,
972 EFI_PCI_IO_PROTOCOL
*PciIo
;
974 UINT32 StatusRegister
;
977 // Read the status register
979 PciIo
= &PciIoDevice
->PciIo
;
980 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, StatusIndex
, 1, &StatusRegister
);
981 if (EFI_ERROR (Status
)) {
982 return EFI_UNSUPPORTED
;
986 // Check the Fast B2B bit
988 if ((StatusRegister
& EFI_PCI_FAST_BACK_TO_BACK_CAPABLE
) != 0) {
991 return EFI_UNSUPPORTED
;
996 Process the option ROM for all the children of the specified parent PCI device.
997 It can only be used after the first full Option ROM process.
999 @param PciIoDevice Pci device instance.
1003 ProcessOptionRomLight (
1004 IN PCI_IO_DEVICE
*PciIoDevice
1007 PCI_IO_DEVICE
*Temp
;
1008 LIST_ENTRY
*CurrentLink
;
1011 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1013 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1014 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1016 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1018 if (!IsListEmpty (&Temp
->ChildList
)) {
1019 ProcessOptionRomLight (Temp
);
1022 PciRomGetImageMapping (Temp
);
1025 // The OpRom has already been processed in the first round
1027 Temp
->AllOpRomProcessed
= TRUE
;
1029 CurrentLink
= CurrentLink
->ForwardLink
;
1034 Determine the related attributes of all devices under a Root Bridge.
1036 @param PciIoDevice PCI device instance.
1040 DetermineDeviceAttribute (
1041 IN PCI_IO_DEVICE
*PciIoDevice
1045 UINT16 BridgeControl
;
1047 UINT16 OldBridgeControl
;
1048 BOOLEAN FastB2BSupport
;
1049 PCI_IO_DEVICE
*Temp
;
1050 LIST_ENTRY
*CurrentLink
;
1054 // For Root Bridge, just copy it by RootBridgeIo proctocol
1055 // so as to keep consistent with the actual attribute
1057 if (PciIoDevice
->Parent
== NULL
) {
1058 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
1059 PciIoDevice
->PciRootBridgeIo
,
1060 &PciIoDevice
->Supports
,
1061 &PciIoDevice
->Attributes
1063 if (EFI_ERROR (Status
)) {
1069 // Set the attributes to be checked for common PCI devices and PPB or P2C
1070 // Since some devices only support part of them, it is better to set the
1071 // attribute according to its command or bridge control register
1073 Command
= EFI_PCI_COMMAND_IO_SPACE
|
1074 EFI_PCI_COMMAND_MEMORY_SPACE
|
1075 EFI_PCI_COMMAND_BUS_MASTER
|
1076 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1078 BridgeControl
= EFI_PCI_BRIDGE_CONTROL_ISA
| EFI_PCI_BRIDGE_CONTROL_VGA
| EFI_PCI_BRIDGE_CONTROL_VGA_16
;
1081 // Test whether the device can support attributes above
1083 PciTestSupportedAttribute (PciIoDevice
, &Command
, &BridgeControl
, &OldCommand
, &OldBridgeControl
);
1086 // Set the supported attributes for specified PCI device
1088 PciSetDeviceAttribute (PciIoDevice
, Command
, BridgeControl
, EFI_SET_SUPPORTS
);
1091 // Set the current attributes for specified PCI device
1093 PciSetDeviceAttribute (PciIoDevice
, OldCommand
, OldBridgeControl
, EFI_SET_ATTRIBUTES
);
1096 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
1098 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE
);
1101 FastB2BSupport
= TRUE
;
1104 // P2C can not support FB2B on the secondary side
1106 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1107 FastB2BSupport
= FALSE
;
1111 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1113 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1114 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1116 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1117 Status
= DetermineDeviceAttribute (Temp
);
1118 if (EFI_ERROR (Status
)) {
1122 // Detect Fast Bact to Bact support for the device under the bridge
1124 Status
= GetFastBackToBackSupport (Temp
, PCI_PRIMARY_STATUS_OFFSET
);
1125 if (FastB2BSupport
&& EFI_ERROR (Status
)) {
1126 FastB2BSupport
= FALSE
;
1129 CurrentLink
= CurrentLink
->ForwardLink
;
1132 // Set or clear Fast Back to Back bit for the whole bridge
1134 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
1136 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
1138 Status
= GetFastBackToBackSupport (PciIoDevice
, PCI_BRIDGE_STATUS_REGISTER_OFFSET
);
1140 if (EFI_ERROR (Status
) || (!FastB2BSupport
)) {
1141 FastB2BSupport
= FALSE
;
1142 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1144 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1148 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1149 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1150 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1151 if (FastB2BSupport
) {
1152 PCI_ENABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1154 PCI_DISABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1157 CurrentLink
= CurrentLink
->ForwardLink
;
1161 // End for IsListEmpty
1167 This routine is used to update the bar information for those incompatible PCI device.
1169 @param PciIoDevice Input Pci device instance. Output Pci device instance with updated
1172 @retval EFI_SUCCESS Successfully updated bar information.
1173 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
1178 IN OUT PCI_IO_DEVICE
*PciIoDevice
1185 VOID
*Configuration
;
1186 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1188 Configuration
= NULL
;
1189 Status
= EFI_SUCCESS
;
1191 if (gEfiIncompatiblePciDeviceSupport
== NULL
) {
1193 // It can only be supported after the Incompatible PCI Device
1194 // Support Protocol has been installed
1196 Status
= gBS
->LocateProtocol (
1197 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
1199 (VOID
**) &gEfiIncompatiblePciDeviceSupport
1202 if (Status
== EFI_SUCCESS
) {
1204 // Check whether the device belongs to incompatible devices from protocol or not
1205 // If it is , then get its special requirement in the ACPI table
1207 Status
= gEfiIncompatiblePciDeviceSupport
->CheckDevice (
1208 gEfiIncompatiblePciDeviceSupport
,
1209 PciIoDevice
->Pci
.Hdr
.VendorId
,
1210 PciIoDevice
->Pci
.Hdr
.DeviceId
,
1211 PciIoDevice
->Pci
.Hdr
.RevisionID
,
1212 PciIoDevice
->Pci
.Device
.SubsystemVendorID
,
1213 PciIoDevice
->Pci
.Device
.SubsystemID
,
1219 if (EFI_ERROR (Status
) || Configuration
== NULL
) {
1220 return EFI_UNSUPPORTED
;
1224 // Update PCI device information from the ACPI table
1226 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1228 while (Ptr
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1230 if (Ptr
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1232 // The format is not support
1237 BarIndex
= (UINTN
) Ptr
->AddrTranslationOffset
;
1238 BarEndIndex
= BarIndex
;
1241 // Update all the bars in the device
1243 if (BarIndex
== PCI_BAR_ALL
) {
1245 BarEndIndex
= PCI_MAX_BAR
- 1;
1248 if (BarIndex
> PCI_MAX_BAR
) {
1253 for (; BarIndex
<= BarEndIndex
; BarIndex
++) {
1255 switch (Ptr
->ResType
) {
1256 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1259 // Make sure the bar is memory type
1261 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeMem
)) {
1266 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1269 // Make sure the bar is IO type
1271 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeIo
)) {
1280 // Update the new alignment for the device
1282 SetNewAlign (&(PciIoDevice
->PciBar
[BarIndex
].Alignment
), Ptr
->AddrRangeMax
);
1285 // Update the new length for the device
1287 if (Ptr
->AddrLen
!= PCI_BAR_NOCHANGE
) {
1288 PciIoDevice
->PciBar
[BarIndex
].Length
= Ptr
->AddrLen
;
1296 FreePool (Configuration
);
1302 This routine will update the alignment with the new alignment.
1304 @param Alignment Input Old alignment. Output updated alignment.
1305 @param NewAlignment New alignment.
1310 IN OUT UINT64
*Alignment
,
1311 IN UINT64 NewAlignment
1314 UINT64 OldAlignment
;
1318 // The new alignment is the same as the original,
1321 if (NewAlignment
== PCI_BAR_OLD_ALIGN
) {
1325 // Check the validity of the parameter
1327 if (NewAlignment
!= PCI_BAR_EVEN_ALIGN
&&
1328 NewAlignment
!= PCI_BAR_SQUAD_ALIGN
&&
1329 NewAlignment
!= PCI_BAR_DQUAD_ALIGN
) {
1330 *Alignment
= NewAlignment
;
1334 OldAlignment
= (*Alignment
) + 1;
1338 // Get the first non-zero hex value of the length
1340 while ((OldAlignment
& 0x0F) == 0x00) {
1341 OldAlignment
= RShiftU64 (OldAlignment
, 4);
1346 // Adjust the alignment to even, quad or double quad boundary
1348 if (NewAlignment
== PCI_BAR_EVEN_ALIGN
) {
1349 if ((OldAlignment
& 0x01) != 0) {
1350 OldAlignment
= OldAlignment
+ 2 - (OldAlignment
& 0x01);
1352 } else if (NewAlignment
== PCI_BAR_SQUAD_ALIGN
) {
1353 if ((OldAlignment
& 0x03) != 0) {
1354 OldAlignment
= OldAlignment
+ 4 - (OldAlignment
& 0x03);
1356 } else if (NewAlignment
== PCI_BAR_DQUAD_ALIGN
) {
1357 if ((OldAlignment
& 0x07) != 0) {
1358 OldAlignment
= OldAlignment
+ 8 - (OldAlignment
& 0x07);
1363 // Update the old value
1365 NewAlignment
= LShiftU64 (OldAlignment
, ShiftBit
) - 1;
1366 *Alignment
= NewAlignment
;
1372 Parse PCI IOV VF bar information and fill them into PCI device instance.
1374 @param PciIoDevice Pci device instance.
1375 @param Offset Bar offset.
1376 @param BarIndex Bar index.
1378 @return Next bar offset.
1383 IN PCI_IO_DEVICE
*PciIoDevice
,
1389 UINT32 OriginalValue
;
1396 // Ensure it is called properly
1398 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
1399 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
1406 Status
= VfBarExisted (
1413 if (EFI_ERROR (Status
)) {
1414 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1415 PciIoDevice
->VfPciBar
[BarIndex
].Length
= 0;
1416 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1419 // Scan all the BARs anyway
1421 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT16
) Offset
;
1425 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT16
) Offset
;
1426 if ((Value
& 0x01) != 0) {
1428 // Device I/Os. Impossible
1437 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1439 switch (Value
& 0x07) {
1442 //memory space; anywhere in 32 bit address space
1445 if ((Value
& 0x08) != 0) {
1446 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1448 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1451 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1452 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1457 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1461 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1462 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1468 // memory space; anywhere in 64 bit address space
1471 if ((Value
& 0x08) != 0) {
1472 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1474 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1478 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1479 // is regarded as an extension for the first bar. As a result
1480 // the sizing will be conducted on combined 64 bit value
1481 // Here just store the masked first 32bit value for future size
1484 PciIoDevice
->VfPciBar
[BarIndex
].Length
= Value
& Mask
;
1485 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1487 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1488 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1492 // Increment the offset to point to next DWORD
1496 Status
= VfBarExisted (
1503 if (EFI_ERROR (Status
)) {
1508 // Fix the length to support some spefic 64 bit BAR
1512 for (Data
= Value
; Data
!= 0; Data
>>= 1) {
1515 Value
|= ((UINT32
)(-1) << Index
);
1518 // Calculate the size of 64bit bar
1520 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1522 PciIoDevice
->VfPciBar
[BarIndex
].Length
= PciIoDevice
->VfPciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1523 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(PciIoDevice
->VfPciBar
[BarIndex
].Length
)) + 1;
1524 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1529 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1533 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1534 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1543 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1544 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1545 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1547 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1548 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1556 // Check the length again so as to keep compatible with some special bars
1558 if (PciIoDevice
->VfPciBar
[BarIndex
].Length
== 0) {
1559 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1560 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1561 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1565 // Increment number of bar
1571 Parse PCI bar information and fill them into PCI device instance.
1573 @param PciIoDevice Pci device instance.
1574 @param Offset Bar offset.
1575 @param BarIndex Bar index.
1577 @return Next bar offset.
1582 IN PCI_IO_DEVICE
*PciIoDevice
,
1588 UINT32 OriginalValue
;
1597 Status
= BarExisted (
1604 if (EFI_ERROR (Status
)) {
1605 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1606 PciIoDevice
->PciBar
[BarIndex
].Length
= 0;
1607 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1610 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1612 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1616 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1617 if ((Value
& 0x01) != 0) {
1623 if ((Value
& 0xFFFF0000) != 0) {
1627 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo32
;
1628 PciIoDevice
->PciBar
[BarIndex
].Length
= ((~(Value
& Mask
)) + 1);
1629 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1635 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo16
;
1636 PciIoDevice
->PciBar
[BarIndex
].Length
= 0x0000FFFF & ((~(Value
& Mask
)) + 1);
1637 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1641 // Workaround. Some platforms inplement IO bar with 0 length
1642 // Need to treat it as no-bar
1644 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1645 PciIoDevice
->PciBar
[BarIndex
].BarType
= (PCI_BAR_TYPE
) 0;
1648 PciIoDevice
->PciBar
[BarIndex
].Prefetchable
= FALSE
;
1649 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1655 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1657 switch (Value
& 0x07) {
1660 //memory space; anywhere in 32 bit address space
1663 if ((Value
& 0x08) != 0) {
1664 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1666 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1669 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1670 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1672 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1674 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1676 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1681 // memory space; anywhere in 64 bit address space
1684 if ((Value
& 0x08) != 0) {
1685 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1687 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1691 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1692 // is regarded as an extension for the first bar. As a result
1693 // the sizing will be conducted on combined 64 bit value
1694 // Here just store the masked first 32bit value for future size
1697 PciIoDevice
->PciBar
[BarIndex
].Length
= Value
& Mask
;
1698 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1701 // Increment the offset to point to next DWORD
1705 Status
= BarExisted (
1712 if (EFI_ERROR (Status
)) {
1714 // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
1716 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1718 // some device implement MMIO bar with 0 length, need to treat it as no-bar
1720 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1726 // Fix the length to support some spefic 64 bit BAR
1730 for (Data
= Value
; Data
!= 0; Data
>>= 1) {
1733 Value
|= ((UINT32
)(-1) << Index
);
1736 // Calculate the size of 64bit bar
1738 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1740 PciIoDevice
->PciBar
[BarIndex
].Length
= PciIoDevice
->PciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1741 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(PciIoDevice
->PciBar
[BarIndex
].Length
)) + 1;
1742 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1744 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1746 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1748 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1757 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1758 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1759 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1761 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1763 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1765 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1772 // Check the length again so as to keep compatible with some special bars
1774 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1775 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1776 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1777 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1781 // Increment number of bar
1787 This routine is used to initialize the bar of a PCI device.
1789 @param PciIoDevice Pci device instance.
1791 @note It can be called typically when a device is going to be rejected.
1795 InitializePciDevice (
1796 IN PCI_IO_DEVICE
*PciIoDevice
1799 EFI_PCI_IO_PROTOCOL
*PciIo
;
1802 PciIo
= &(PciIoDevice
->PciIo
);
1805 // Put all the resource apertures
1806 // Resource base is set to all ones so as to indicate its resource
1807 // has not been alloacted
1809 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
1810 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllOne
);
1815 This routine is used to initialize the bar of a PCI-PCI Bridge device.
1817 @param PciIoDevice PCI-PCI bridge device instance.
1822 IN PCI_IO_DEVICE
*PciIoDevice
1825 EFI_PCI_IO_PROTOCOL
*PciIo
;
1827 PciIo
= &(PciIoDevice
->PciIo
);
1830 // Put all the resource apertures including IO16
1831 // Io32, pMem32, pMem64 to quiescent state
1832 // Resource base all ones, Resource limit all zeros
1834 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
1835 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1D, 1, &gAllZero
);
1837 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x20, 1, &gAllOne
);
1838 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x22, 1, &gAllZero
);
1840 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x24, 1, &gAllOne
);
1841 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x26, 1, &gAllZero
);
1843 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllOne
);
1844 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2C, 1, &gAllZero
);
1847 // Don't support use io32 as for now
1849 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x30, 1, &gAllOne
);
1850 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x32, 1, &gAllZero
);
1853 // Force Interrupt line to zero for cards that come up randomly
1855 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1859 This routine is used to initialize the bar of a PCI Card Bridge device.
1861 @param PciIoDevice PCI Card bridge device.
1866 IN PCI_IO_DEVICE
*PciIoDevice
1869 EFI_PCI_IO_PROTOCOL
*PciIo
;
1871 PciIo
= &(PciIoDevice
->PciIo
);
1874 // Put all the resource apertures including IO16
1875 // Io32, pMem32, pMem64 to quiescent state(
1876 // Resource base all ones, Resource limit all zeros
1878 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x1c, 1, &gAllOne
);
1879 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x20, 1, &gAllZero
);
1881 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x24, 1, &gAllOne
);
1882 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllZero
);
1884 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2c, 1, &gAllOne
);
1885 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x30, 1, &gAllZero
);
1887 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x34, 1, &gAllOne
);
1888 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x38, 1, &gAllZero
);
1891 // Force Interrupt line to zero for cards that come up randomly
1893 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1897 Create and initiliaze general PCI I/O device instance for
1898 PCI device/bridge device/hotplug bridge device.
1900 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1901 @param Pci Input Pci information block.
1902 @param Bus Device Bus NO.
1903 @param Device Device device NO.
1904 @param Func Device func NO.
1906 @return Instance of PCI device. NULL means no instance created.
1911 IN PCI_IO_DEVICE
*Bridge
,
1918 PCI_IO_DEVICE
*PciIoDevice
;
1919 EFI_PCI_IO_PROTOCOL
*PciIo
;
1922 PciIoDevice
= AllocateZeroPool (sizeof (PCI_IO_DEVICE
));
1923 if (PciIoDevice
== NULL
) {
1927 PciIoDevice
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
1928 PciIoDevice
->Handle
= NULL
;
1929 PciIoDevice
->PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1930 PciIoDevice
->DevicePath
= NULL
;
1931 PciIoDevice
->BusNumber
= Bus
;
1932 PciIoDevice
->DeviceNumber
= Device
;
1933 PciIoDevice
->FunctionNumber
= Func
;
1934 PciIoDevice
->Decodes
= 0;
1936 if (gFullEnumeration
) {
1937 PciIoDevice
->Allocated
= FALSE
;
1939 PciIoDevice
->Allocated
= TRUE
;
1942 PciIoDevice
->Registered
= FALSE
;
1943 PciIoDevice
->Attributes
= 0;
1944 PciIoDevice
->Supports
= 0;
1945 PciIoDevice
->BusOverride
= FALSE
;
1946 PciIoDevice
->AllOpRomProcessed
= FALSE
;
1948 PciIoDevice
->IsPciExp
= FALSE
;
1950 CopyMem (&(PciIoDevice
->Pci
), Pci
, sizeof (PCI_TYPE01
));
1953 // Initialize the PCI I/O instance structure
1955 InitializePciIoInstance (PciIoDevice
);
1956 InitializePciDriverOverrideInstance (PciIoDevice
);
1957 InitializePciLoadFile2 (PciIoDevice
);
1958 PciIo
= &PciIoDevice
->PciIo
;
1961 // Detect if PCI Express Device
1963 PciIoDevice
->PciExpressCapabilityOffset
= 0;
1964 Status
= LocateCapabilityRegBlock (
1966 EFI_PCI_CAPABILITY_ID_PCIEXP
,
1967 &PciIoDevice
->PciExpressCapabilityOffset
,
1970 if (!EFI_ERROR (Status
)) {
1971 PciIoDevice
->IsPciExp
= TRUE
;
1974 if (PcdGetBool (PcdAriSupport
)) {
1976 // Check if the device is an ARI device.
1978 Status
= LocatePciExpressCapabilityRegBlock (
1980 EFI_PCIE_CAPABILITY_ID_ARI
,
1981 &PciIoDevice
->AriCapabilityOffset
,
1984 if (!EFI_ERROR (Status
)) {
1986 // We need to enable ARI feature before calculate BusReservation,
1987 // because FirstVFOffset and VFStride may change after that.
1989 EFI_PCI_IO_PROTOCOL
*ParentPciIo
;
1993 // Check if its parent supports ARI forwarding.
1995 ParentPciIo
= &Bridge
->PciIo
;
1996 ParentPciIo
->Pci
.Read (
1998 EfiPciIoWidthUint32
,
1999 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_OFFSET
,
2003 if ((Data32
& EFI_PCIE_CAPABILITY_DEVICE_CAPABILITIES_2_ARI_FORWARDING
) != 0) {
2005 // ARI forward support in bridge, so enable it.
2007 ParentPciIo
->Pci
.Read (
2009 EfiPciIoWidthUint32
,
2010 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
,
2014 if ((Data32
& EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING
) == 0) {
2015 Data32
|= EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_ARI_FORWARDING
;
2016 ParentPciIo
->Pci
.Write (
2018 EfiPciIoWidthUint32
,
2019 Bridge
->PciExpressCapabilityOffset
+ EFI_PCIE_CAPABILITY_DEVICE_CONTROL_2_OFFSET
,
2025 "PCI B%x.D%x.F%x - ARI forwarding enabled\n",
2026 (UINTN
)Bridge
->BusNumber
,
2027 (UINTN
)Bridge
->DeviceNumber
,
2028 (UINTN
)Bridge
->FunctionNumber
2035 "PCI ARI B%x.D%x.F%x - ARI Cap offset - 0x%x\n",
2039 (UINTN
)PciIoDevice
->AriCapabilityOffset
2045 // Initialization for SR-IOV
2048 if (PcdGetBool (PcdSrIovSupport
)) {
2049 Status
= LocatePciExpressCapabilityRegBlock (
2051 EFI_PCIE_CAPABILITY_ID_SRIOV
,
2052 &PciIoDevice
->SrIovCapabilityOffset
,
2055 if (!EFI_ERROR (Status
)) {
2057 UINT16 FirstVFOffset
;
2063 // If the SR-IOV device is an ARI device, then Set ARI Capable Hierarchy for the device.
2065 if (PcdGetBool (PcdAriSupport
) && PciIoDevice
->AriCapabilityOffset
!= 0) {
2068 EfiPciIoWidthUint16
,
2069 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
,
2073 Data16
|= EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL_ARI_HIERARCHY
;
2076 EfiPciIoWidthUint16
,
2077 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_CONTROL
,
2084 // Calculate SystemPageSize
2089 EfiPciIoWidthUint32
,
2090 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE
,
2092 &PciIoDevice
->SystemPageSize
2096 "PCI SR-IOV B%x.D%x.F%x - SupportedPageSize - 0x%x\n",
2100 PciIoDevice
->SystemPageSize
2103 PciIoDevice
->SystemPageSize
= (PcdGet32 (PcdSrIovSystemPageSize
) & PciIoDevice
->SystemPageSize
);
2104 ASSERT (PciIoDevice
->SystemPageSize
!= 0);
2108 EfiPciIoWidthUint32
,
2109 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE
,
2111 &PciIoDevice
->SystemPageSize
2115 "PCI SR-IOV B%x.D%x.F%x - SystemPageSize - 0x%x\n",
2119 PciIoDevice
->SystemPageSize
2122 // Adjust SystemPageSize for Alignment usage later
2124 PciIoDevice
->SystemPageSize
<<= 12;
2127 // Calculate BusReservation for PCI IOV
2131 // Read First FirstVFOffset, InitialVFs, and VFStride
2135 EfiPciIoWidthUint16
,
2136 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF
,
2142 "PCI SR-IOV B%x.D%x.F%x - FirstVFOffset - 0x%x\n",
2146 (UINTN
)FirstVFOffset
2151 EfiPciIoWidthUint16
,
2152 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS
,
2154 &PciIoDevice
->InitialVFs
2158 "PCI SR-IOV B%x.D%x.F%x - InitialVFs - 0x%x\n",
2162 (UINTN
)PciIoDevice
->InitialVFs
2167 EfiPciIoWidthUint16
,
2168 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE
,
2174 "PCI SR-IOV B%x.D%x.F%x - VFStride - 0x%x\n",
2184 PFRid
= EFI_PCI_RID(Bus
, Device
, Func
);
2185 LastVF
= PFRid
+ FirstVFOffset
+ (PciIoDevice
->InitialVFs
- 1) * VFStride
;
2188 // Calculate ReservedBusNum for this PF
2190 PciIoDevice
->ReservedBusNum
= (UINT16
)(EFI_PCI_BUS_OF_RID (LastVF
) - Bus
+ 1);
2193 "PCI SR-IOV B%x.D%x.F%x - reserved bus number - 0x%x\n",
2197 (UINTN
)PciIoDevice
->ReservedBusNum
2202 "PCI SR-IOV B%x.D%x.F%x - SRIOV Cap offset - 0x%x\n",
2206 (UINTN
)PciIoDevice
->SrIovCapabilityOffset
2211 if (PcdGetBool (PcdMrIovSupport
)) {
2212 Status
= LocatePciExpressCapabilityRegBlock (
2214 EFI_PCIE_CAPABILITY_ID_MRIOV
,
2215 &PciIoDevice
->MrIovCapabilityOffset
,
2218 if (!EFI_ERROR (Status
)) {
2221 "PCI MR-IOV B%x.D%x.F%x - MRIOV Cap offset - 0x%x\n",
2225 (UINTN
)PciIoDevice
->MrIovCapabilityOffset
2231 // Initialize the reserved resource list
2233 InitializeListHead (&PciIoDevice
->ReservedResourceList
);
2236 // Initialize the driver list
2238 InitializeListHead (&PciIoDevice
->OptionRomDriverList
);
2241 // Initialize the child list
2243 InitializeListHead (&PciIoDevice
->ChildList
);
2249 This routine is used to enumerate entire pci bus system
2250 in a given platform.
2252 It is only called on the second start on the same Root Bridge.
2254 @param Controller Parent bridge handler.
2256 @retval EFI_SUCCESS PCI enumeration finished successfully.
2257 @retval other Some error occurred when enumerating the pci bus system.
2261 PciEnumeratorLight (
2262 IN EFI_HANDLE Controller
2267 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2268 PCI_IO_DEVICE
*RootBridgeDev
;
2271 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
2274 MaxBus
= PCI_MAX_BUS
;
2278 // If this root bridge has been already enumerated, then return successfully
2280 if (GetRootBridgeByHandle (Controller
) != NULL
) {
2285 // Open pci root bridge io protocol
2287 Status
= gBS
->OpenProtocol (
2289 &gEfiPciRootBridgeIoProtocolGuid
,
2290 (VOID
**) &PciRootBridgeIo
,
2291 gPciBusDriverBinding
.DriverBindingHandle
,
2293 EFI_OPEN_PROTOCOL_BY_DRIVER
2295 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2299 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
2301 if (EFI_ERROR (Status
)) {
2305 while (PciGetBusRange (&Descriptors
, &MinBus
, &MaxBus
, NULL
) == EFI_SUCCESS
) {
2308 // Create a device node for root bridge device with a NULL host bridge controller handle
2310 RootBridgeDev
= CreateRootBridge (Controller
);
2312 if (RootBridgeDev
== NULL
) {
2318 // Record the root bridgeio protocol
2320 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2322 Status
= PciPciDeviceInfoCollector (
2327 if (!EFI_ERROR (Status
)) {
2330 // Remove those PCI devices which are rejected when full enumeration
2332 RemoveRejectedPciDevices (RootBridgeDev
->Handle
, RootBridgeDev
);
2335 // Process option rom light
2337 ProcessOptionRomLight (RootBridgeDev
);
2340 // Determine attributes for all devices under this root bridge
2342 DetermineDeviceAttribute (RootBridgeDev
);
2345 // If successfully, insert the node into device pool
2347 InsertRootBridge (RootBridgeDev
);
2351 // If unsuccessly, destroy the entire node
2353 DestroyRootBridge (RootBridgeDev
);
2363 Get bus range from PCI resource descriptor list.
2365 @param Descriptors A pointer to the address space descriptor.
2366 @param MinBus The min bus returned.
2367 @param MaxBus The max bus returned.
2368 @param BusRange The bus range returned.
2370 @retval EFI_SUCCESS Successfully got bus range.
2371 @retval EFI_NOT_FOUND Can not find the specific bus.
2376 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptors
,
2379 OUT UINT16
*BusRange
2382 while ((*Descriptors
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
2383 if ((*Descriptors
)->ResType
== ACPI_ADDRESS_SPACE_TYPE_BUS
) {
2384 if (MinBus
!= NULL
) {
2385 *MinBus
= (UINT16
) (*Descriptors
)->AddrRangeMin
;
2388 if (MaxBus
!= NULL
) {
2389 *MaxBus
= (UINT16
) (*Descriptors
)->AddrRangeMax
;
2392 if (BusRange
!= NULL
) {
2393 *BusRange
= (UINT16
) (*Descriptors
)->AddrLen
;
2402 return EFI_NOT_FOUND
;
2406 This routine can be used to start the root bridge.
2408 @param RootBridgeDev Pci device instance.
2410 @retval EFI_SUCCESS This device started.
2411 @retval other Failed to get PCI Root Bridge I/O protocol.
2415 StartManagingRootBridge (
2416 IN PCI_IO_DEVICE
*RootBridgeDev
2419 EFI_HANDLE RootBridgeHandle
;
2421 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2424 // Get the root bridge handle
2426 RootBridgeHandle
= RootBridgeDev
->Handle
;
2427 PciRootBridgeIo
= NULL
;
2430 // Get the pci root bridge io protocol
2432 Status
= gBS
->OpenProtocol (
2434 &gEfiPciRootBridgeIoProtocolGuid
,
2435 (VOID
**) &PciRootBridgeIo
,
2436 gPciBusDriverBinding
.DriverBindingHandle
,
2438 EFI_OPEN_PROTOCOL_BY_DRIVER
2441 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2446 // Store the PciRootBridgeIo protocol into root bridge private data
2448 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2455 This routine can be used to check whether a PCI device should be rejected when light enumeration.
2457 @param PciIoDevice Pci device instance.
2459 @retval TRUE This device should be rejected.
2460 @retval FALSE This device shouldn't be rejected.
2464 IsPciDeviceRejected (
2465 IN PCI_IO_DEVICE
*PciIoDevice
2475 // PPB should be skip!
2477 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
2481 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
2483 // Only test base registers for P2C
2485 for (BarOffset
= 0x1C; BarOffset
<= 0x38; BarOffset
+= 2 * sizeof (UINT32
)) {
2487 Mask
= (BarOffset
< 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
2488 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2489 if (EFI_ERROR (Status
)) {
2493 TestValue
= TestValue
& Mask
;
2494 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2496 // The bar isn't programed, so it should be rejected
2505 for (BarOffset
= 0x14; BarOffset
<= 0x24; BarOffset
+= sizeof (UINT32
)) {
2509 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2510 if (EFI_ERROR (Status
)) {
2514 if ((TestValue
& 0x01) != 0) {
2520 TestValue
= TestValue
& Mask
;
2521 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2531 TestValue
= TestValue
& Mask
;
2533 if ((TestValue
& 0x07) == 0x04) {
2538 BarOffset
+= sizeof (UINT32
);
2539 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2542 // Test its high 32-Bit BAR
2544 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2545 if (TestValue
== OldValue
) {
2555 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2566 Reset all bus number from specific bridge.
2568 @param Bridge Parent specific bridge.
2569 @param StartBusNumber Start bus number.
2573 ResetAllPpbBusNumber (
2574 IN PCI_IO_DEVICE
*Bridge
,
2575 IN UINT8 StartBusNumber
2585 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2587 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
2589 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
2590 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
2593 // Check to see whether a pci device is present
2595 Status
= PciDevicePresent (
2603 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
))) {
2606 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
2607 Status
= PciRootBridgeIo
->Pci
.Read (
2614 SecondaryBus
= (UINT8
)(Register
>> 8);
2616 if (SecondaryBus
!= 0) {
2617 ResetAllPpbBusNumber (Bridge
, SecondaryBus
);
2621 // Reset register 18h, 19h, 1Ah on PCI Bridge
2623 Register
&= 0xFF000000;
2624 Status
= PciRootBridgeIo
->Pci
.Write (
2633 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
2635 // Skip sub functions, this is not a multi function device
2637 Func
= PCI_MAX_FUNC
;