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
;
331 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
333 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
334 PciIoDevice
= CreatePciIoDevice (
342 if (PciIoDevice
== NULL
) {
347 // Create a device path for this PCI device and store it into its private data
349 CreatePciDevicePath (
355 // If it is a full enumeration, disconnect the device in advance
357 if (gFullEnumeration
) {
359 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
364 // Start to parse the bars
366 for (Offset
= 0x10, BarIndex
= 0; Offset
<= 0x24 && BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
367 Offset
= PciParseBar (PciIoDevice
, Offset
, BarIndex
);
371 // Parse the SR-IOV VF bars
373 if ((PciIoDevice
->SrIovCapabilityOffset
!= 0) && ((FeaturePcdGet(PcdSrIovSupport
)& EFI_PCI_IOV_POLICY_SRIOV
) != 0)) {
374 for (Offset
= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR0
, BarIndex
= 0;
375 Offset
<= PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_BAR5
;
378 ASSERT (BarIndex
< PCI_MAX_BAR
);
379 Offset
= PciIovParseVfBar (PciIoDevice
, Offset
, BarIndex
);
386 Create PCI device instance for PCI-PCI bridge.
388 @param Bridge Parent bridge instance.
389 @param Pci Input PCI device information block.
390 @param Bus PCI device Bus NO.
391 @param Device PCI device Device NO.
392 @param Func PCI device's func NO.
394 @return Created PCI device instance.
399 IN PCI_IO_DEVICE
*Bridge
,
406 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
407 PCI_IO_DEVICE
*PciIoDevice
;
410 EFI_PCI_IO_PROTOCOL
*PciIo
;
413 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
414 PciIoDevice
= CreatePciIoDevice (
422 if (PciIoDevice
== NULL
) {
427 // Create a device path for this PCI device and store it into its private data
429 CreatePciDevicePath (
434 if (gFullEnumeration
) {
435 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
438 // Initalize the bridge control register
440 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED
);
445 // PPB can have two BARs
447 if (PciParseBar (PciIoDevice
, 0x10, PPB_BAR_0
) == 0x14) {
451 PciParseBar (PciIoDevice
, 0x14, PPB_BAR_1
);
454 PciIo
= &PciIoDevice
->PciIo
;
457 // Test whether it support 32 decode or not
459 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
460 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
461 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
462 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
465 if ((Value
& 0x01) != 0) {
466 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
468 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
473 // if PcdPciBridgeIoAlignmentProbe is TRUE, PCI bus driver probes
474 // PCI bridge supporting non-stardard I/O window alignment less than 4K.
477 PciIoDevice
->BridgeIoAlignment
= 0xFFF;
478 if (FeaturePcdGet (PcdPciBridgeIoAlignmentProbe
)) {
480 // Check any bits of bit 3-1 of I/O Base Register are writable.
481 // if so, it is assumed non-stardard I/O window alignment is supported by this bridge.
482 // Per spec, bit 3-1 of I/O Base Register are reserved bits, so its content can't be assumed.
484 Value
= (UINT8
)(Temp
^ (BIT3
| BIT2
| BIT1
));
485 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
486 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
487 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
488 Value
= (UINT8
)((Value
^ Temp
) & (BIT3
| BIT2
| BIT1
));
491 PciIoDevice
->BridgeIoAlignment
= 0x7FF;
494 PciIoDevice
->BridgeIoAlignment
= 0x3FF;
496 case BIT3
| BIT2
| BIT1
:
497 PciIoDevice
->BridgeIoAlignment
= 0x1FF;
502 Status
= BarExisted (
510 // Test if it supports 64 memory or not
512 if (!EFI_ERROR (Status
)) {
514 Status
= BarExisted (
521 if (!EFI_ERROR (Status
)) {
522 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
523 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
525 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
530 // Memory 32 code is required for ppb
532 PciIoDevice
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
534 GetResourcePaddingPpb (PciIoDevice
);
541 Create PCI device instance for PCI Card bridge device.
543 @param Bridge Parent bridge instance.
544 @param Pci Input PCI device information block.
545 @param Bus PCI device Bus NO.
546 @param Device PCI device Device NO.
547 @param Func PCI device's func NO.
549 @return Created PCI device instance.
554 IN PCI_IO_DEVICE
*Bridge
,
561 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
562 PCI_IO_DEVICE
*PciIoDevice
;
564 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
565 PciIoDevice
= CreatePciIoDevice (
573 if (PciIoDevice
== NULL
) {
578 // Create a device path for this PCI device and store it into its private data
580 CreatePciDevicePath (
585 if (gFullEnumeration
) {
586 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
589 // Initalize the bridge control register
591 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED
);
595 // P2C only has one bar that is in 0x10
597 PciParseBar (PciIoDevice
, 0x10, P2C_BAR_0
);
600 // Read PciBar information from the bar register
602 GetBackPcCardBar (PciIoDevice
);
603 PciIoDevice
->Decodes
= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
|
604 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
|
605 EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
611 Create device path for pci deivce.
613 @param ParentDevicePath Parent bridge's path.
614 @param PciIoDevice Pci device instance.
616 @return Device path protocol instance for specific pci device.
619 EFI_DEVICE_PATH_PROTOCOL
*
620 CreatePciDevicePath (
621 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
622 IN PCI_IO_DEVICE
*PciIoDevice
626 PCI_DEVICE_PATH PciNode
;
629 // Create PCI device path
631 PciNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
632 PciNode
.Header
.SubType
= HW_PCI_DP
;
633 SetDevicePathNodeLength (&PciNode
.Header
, sizeof (PciNode
));
635 PciNode
.Device
= PciIoDevice
->DeviceNumber
;
636 PciNode
.Function
= PciIoDevice
->FunctionNumber
;
637 PciIoDevice
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, &PciNode
.Header
);
639 return PciIoDevice
->DevicePath
;
643 Check whether the PCI IOV VF bar is existed or not.
645 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
646 @param Offset The offset.
647 @param BarLengthValue The bar length value returned.
648 @param OriginalBarValue The original bar value returned.
650 @retval EFI_NOT_FOUND The bar doesn't exist.
651 @retval EFI_SUCCESS The bar exist.
656 IN PCI_IO_DEVICE
*PciIoDevice
,
658 OUT UINT32
*BarLengthValue
,
659 OUT UINT32
*OriginalBarValue
662 EFI_PCI_IO_PROTOCOL
*PciIo
;
663 UINT32 OriginalValue
;
668 // Ensure it is called properly
670 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
671 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
672 return EFI_NOT_FOUND
;
675 PciIo
= &PciIoDevice
->PciIo
;
678 // Preserve the original value
681 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
684 // Raise TPL to high level to disable timer interrupt while the BAR is probed
686 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
688 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &gAllOne
);
689 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &Value
);
692 // Write back the original value
694 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT32
)Offset
, 1, &OriginalValue
);
697 // Restore TPL to its original level
699 gBS
->RestoreTPL (OldTpl
);
701 if (BarLengthValue
!= NULL
) {
702 *BarLengthValue
= Value
;
705 if (OriginalBarValue
!= NULL
) {
706 *OriginalBarValue
= OriginalValue
;
710 return EFI_NOT_FOUND
;
717 Check whether the bar is existed or not.
719 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
720 @param Offset The offset.
721 @param BarLengthValue The bar length value returned.
722 @param OriginalBarValue The original bar value returned.
724 @retval EFI_NOT_FOUND The bar doesn't exist.
725 @retval EFI_SUCCESS The bar exist.
730 IN PCI_IO_DEVICE
*PciIoDevice
,
732 OUT UINT32
*BarLengthValue
,
733 OUT UINT32
*OriginalBarValue
736 EFI_PCI_IO_PROTOCOL
*PciIo
;
737 UINT32 OriginalValue
;
741 PciIo
= &PciIoDevice
->PciIo
;
744 // Preserve the original value
746 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
749 // Raise TPL to high level to disable timer interrupt while the BAR is probed
751 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
753 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &gAllOne
);
754 PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &Value
);
757 // Write back the original value
759 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
762 // Restore TPL to its original level
764 gBS
->RestoreTPL (OldTpl
);
766 if (BarLengthValue
!= NULL
) {
767 *BarLengthValue
= Value
;
770 if (OriginalBarValue
!= NULL
) {
771 *OriginalBarValue
= OriginalValue
;
775 return EFI_NOT_FOUND
;
782 Test whether the device can support given attributes.
784 @param PciIoDevice Pci device instance.
785 @param Command Input command register value, and
786 returned supported register value.
787 @param BridgeControl Inout bridge control value for PPB or P2C, and
788 returned supported bridge control value.
789 @param OldCommand Returned and stored old command register offset.
790 @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
794 PciTestSupportedAttribute (
795 IN PCI_IO_DEVICE
*PciIoDevice
,
796 IN OUT UINT16
*Command
,
797 IN OUT UINT16
*BridgeControl
,
798 OUT UINT16
*OldCommand
,
799 OUT UINT16
*OldBridgeControl
805 // Preserve the original value
807 PCI_READ_COMMAND_REGISTER (PciIoDevice
, OldCommand
);
810 // Raise TPL to high level to disable timer interrupt while the BAR is probed
812 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
814 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *Command
);
815 PCI_READ_COMMAND_REGISTER (PciIoDevice
, Command
);
818 // Write back the original value
820 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *OldCommand
);
823 // Restore TPL to its original level
825 gBS
->RestoreTPL (OldTpl
);
827 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
830 // Preserve the original value
832 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, OldBridgeControl
);
835 // Raise TPL to high level to disable timer interrupt while the BAR is probed
837 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
839 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *BridgeControl
);
840 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, BridgeControl
);
843 // Write back the original value
845 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *OldBridgeControl
);
848 // Restore TPL to its original level
850 gBS
->RestoreTPL (OldTpl
);
853 *OldBridgeControl
= 0;
859 Set the supported or current attributes of a PCI device.
861 @param PciIoDevice Structure pointer for PCI device.
862 @param Command Command register value.
863 @param BridgeControl Bridge control value for PPB or P2C.
864 @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
868 PciSetDeviceAttribute (
869 IN PCI_IO_DEVICE
*PciIoDevice
,
871 IN UINT16 BridgeControl
,
879 if ((Command
& EFI_PCI_COMMAND_IO_SPACE
) != 0) {
880 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IO
;
883 if ((Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) != 0) {
884 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY
;
887 if ((Command
& EFI_PCI_COMMAND_BUS_MASTER
) != 0) {
888 Attributes
|= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
;
891 if ((Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
892 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
895 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
) != 0) {
896 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
899 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
) != 0) {
900 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
901 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
902 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
905 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
) != 0) {
906 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
;
907 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
;
910 if (Option
== EFI_SET_SUPPORTS
) {
912 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
913 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
|
914 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE
|
915 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
916 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
917 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
;
919 if ((Attributes
& EFI_PCI_IO_ATTRIBUTE_IO
) != 0) {
920 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
921 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
924 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
926 // For bridge, it should support IDE attributes
928 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
929 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
932 if (IS_PCI_IDE (&PciIoDevice
->Pci
)) {
933 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
934 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
937 if (IS_PCI_VGA (&PciIoDevice
->Pci
)) {
938 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
939 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
943 PciIoDevice
->Supports
= Attributes
;
944 PciIoDevice
->Supports
&= ( (PciIoDevice
->Parent
->Supports
) | \
945 EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
| \
946 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
);
949 PciIoDevice
->Attributes
= Attributes
;
954 Determine if the device can support Fast Back to Back attribute.
956 @param PciIoDevice Pci device instance.
957 @param StatusIndex Status register value.
959 @retval EFI_SUCCESS This device support Fast Back to Back attribute.
960 @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.
964 GetFastBackToBackSupport (
965 IN PCI_IO_DEVICE
*PciIoDevice
,
969 EFI_PCI_IO_PROTOCOL
*PciIo
;
971 UINT32 StatusRegister
;
974 // Read the status register
976 PciIo
= &PciIoDevice
->PciIo
;
977 Status
= PciIo
->Pci
.Read (PciIo
, EfiPciIoWidthUint16
, StatusIndex
, 1, &StatusRegister
);
978 if (EFI_ERROR (Status
)) {
979 return EFI_UNSUPPORTED
;
983 // Check the Fast B2B bit
985 if ((StatusRegister
& EFI_PCI_FAST_BACK_TO_BACK_CAPABLE
) != 0) {
988 return EFI_UNSUPPORTED
;
993 Process the option ROM for all the children of the specified parent PCI device.
994 It can only be used after the first full Option ROM process.
996 @param PciIoDevice Pci device instance.
1000 ProcessOptionRomLight (
1001 IN PCI_IO_DEVICE
*PciIoDevice
1004 PCI_IO_DEVICE
*Temp
;
1005 LIST_ENTRY
*CurrentLink
;
1008 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1010 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1011 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1013 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1015 if (!IsListEmpty (&Temp
->ChildList
)) {
1016 ProcessOptionRomLight (Temp
);
1019 PciRomGetImageMapping (Temp
);
1022 // The OpRom has already been processed in the first round
1024 Temp
->AllOpRomProcessed
= TRUE
;
1026 CurrentLink
= CurrentLink
->ForwardLink
;
1031 Determine the related attributes of all devices under a Root Bridge.
1033 @param PciIoDevice PCI device instance.
1037 DetermineDeviceAttribute (
1038 IN PCI_IO_DEVICE
*PciIoDevice
1042 UINT16 BridgeControl
;
1044 UINT16 OldBridgeControl
;
1045 BOOLEAN FastB2BSupport
;
1046 PCI_IO_DEVICE
*Temp
;
1047 LIST_ENTRY
*CurrentLink
;
1051 // For Root Bridge, just copy it by RootBridgeIo proctocol
1052 // so as to keep consistent with the actual attribute
1054 if (PciIoDevice
->Parent
== NULL
) {
1055 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
1056 PciIoDevice
->PciRootBridgeIo
,
1057 &PciIoDevice
->Supports
,
1058 &PciIoDevice
->Attributes
1060 if (EFI_ERROR (Status
)) {
1066 // Set the attributes to be checked for common PCI devices and PPB or P2C
1067 // Since some devices only support part of them, it is better to set the
1068 // attribute according to its command or bridge control register
1070 Command
= EFI_PCI_COMMAND_IO_SPACE
|
1071 EFI_PCI_COMMAND_MEMORY_SPACE
|
1072 EFI_PCI_COMMAND_BUS_MASTER
|
1073 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1075 BridgeControl
= EFI_PCI_BRIDGE_CONTROL_ISA
| EFI_PCI_BRIDGE_CONTROL_VGA
| EFI_PCI_BRIDGE_CONTROL_VGA_16
;
1078 // Test whether the device can support attributes above
1080 PciTestSupportedAttribute (PciIoDevice
, &Command
, &BridgeControl
, &OldCommand
, &OldBridgeControl
);
1083 // Set the supported attributes for specified PCI device
1085 PciSetDeviceAttribute (PciIoDevice
, Command
, BridgeControl
, EFI_SET_SUPPORTS
);
1088 // Set the current attributes for specified PCI device
1090 PciSetDeviceAttribute (PciIoDevice
, OldCommand
, OldBridgeControl
, EFI_SET_ATTRIBUTES
);
1093 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
1095 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE
);
1098 FastB2BSupport
= TRUE
;
1101 // P2C can not support FB2B on the secondary side
1103 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1104 FastB2BSupport
= FALSE
;
1108 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1110 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1111 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1113 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1114 Status
= DetermineDeviceAttribute (Temp
);
1115 if (EFI_ERROR (Status
)) {
1119 // Detect Fast Bact to Bact support for the device under the bridge
1121 Status
= GetFastBackToBackSupport (Temp
, PCI_PRIMARY_STATUS_OFFSET
);
1122 if (FastB2BSupport
&& EFI_ERROR (Status
)) {
1123 FastB2BSupport
= FALSE
;
1126 CurrentLink
= CurrentLink
->ForwardLink
;
1129 // Set or clear Fast Back to Back bit for the whole bridge
1131 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
1133 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
1135 Status
= GetFastBackToBackSupport (PciIoDevice
, PCI_BRIDGE_STATUS_REGISTER_OFFSET
);
1137 if (EFI_ERROR (Status
) || (!FastB2BSupport
)) {
1138 FastB2BSupport
= FALSE
;
1139 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1141 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1145 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1146 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1147 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1148 if (FastB2BSupport
) {
1149 PCI_ENABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1151 PCI_DISABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1154 CurrentLink
= CurrentLink
->ForwardLink
;
1158 // End for IsListEmpty
1164 This routine is used to update the bar information for those incompatible PCI device.
1166 @param PciIoDevice Input Pci device instance. Output Pci device instance with updated
1169 @retval EFI_SUCCESS Successfully updated bar information.
1170 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
1175 IN OUT PCI_IO_DEVICE
*PciIoDevice
1182 VOID
*Configuration
;
1183 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1185 Configuration
= NULL
;
1186 Status
= EFI_SUCCESS
;
1188 if (gEfiIncompatiblePciDeviceSupport
== NULL
) {
1190 // It can only be supported after the Incompatible PCI Device
1191 // Support Protocol has been installed
1193 Status
= gBS
->LocateProtocol (
1194 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
1196 (VOID
**) &gEfiIncompatiblePciDeviceSupport
1199 if (Status
== EFI_SUCCESS
) {
1201 // Check whether the device belongs to incompatible devices from protocol or not
1202 // If it is , then get its special requirement in the ACPI table
1204 Status
= gEfiIncompatiblePciDeviceSupport
->CheckDevice (
1205 gEfiIncompatiblePciDeviceSupport
,
1206 PciIoDevice
->Pci
.Hdr
.VendorId
,
1207 PciIoDevice
->Pci
.Hdr
.DeviceId
,
1208 PciIoDevice
->Pci
.Hdr
.RevisionID
,
1209 PciIoDevice
->Pci
.Device
.SubsystemVendorID
,
1210 PciIoDevice
->Pci
.Device
.SubsystemID
,
1216 if (EFI_ERROR (Status
) || Configuration
== NULL
) {
1217 return EFI_UNSUPPORTED
;
1221 // Update PCI device information from the ACPI table
1223 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1225 while (Ptr
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1227 if (Ptr
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1229 // The format is not support
1234 BarIndex
= (UINTN
) Ptr
->AddrTranslationOffset
;
1235 BarEndIndex
= BarIndex
;
1238 // Update all the bars in the device
1240 if (BarIndex
== PCI_BAR_ALL
) {
1242 BarEndIndex
= PCI_MAX_BAR
- 1;
1245 if (BarIndex
> PCI_MAX_BAR
) {
1250 for (; BarIndex
<= BarEndIndex
; BarIndex
++) {
1252 switch (Ptr
->ResType
) {
1253 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1256 // Make sure the bar is memory type
1258 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeMem
)) {
1263 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1266 // Make sure the bar is IO type
1268 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeIo
)) {
1277 // Update the new alignment for the device
1279 SetNewAlign (&(PciIoDevice
->PciBar
[BarIndex
].Alignment
), Ptr
->AddrRangeMax
);
1282 // Update the new length for the device
1284 if (Ptr
->AddrLen
!= PCI_BAR_NOCHANGE
) {
1285 PciIoDevice
->PciBar
[BarIndex
].Length
= Ptr
->AddrLen
;
1293 FreePool (Configuration
);
1299 This routine will update the alignment with the new alignment.
1301 @param Alignment Input Old alignment. Output updated alignment.
1302 @param NewAlignment New alignment.
1307 IN OUT UINT64
*Alignment
,
1308 IN UINT64 NewAlignment
1311 UINT64 OldAlignment
;
1315 // The new alignment is the same as the original,
1318 if (NewAlignment
== PCI_BAR_OLD_ALIGN
) {
1322 // Check the validity of the parameter
1324 if (NewAlignment
!= PCI_BAR_EVEN_ALIGN
&&
1325 NewAlignment
!= PCI_BAR_SQUAD_ALIGN
&&
1326 NewAlignment
!= PCI_BAR_DQUAD_ALIGN
) {
1327 *Alignment
= NewAlignment
;
1331 OldAlignment
= (*Alignment
) + 1;
1335 // Get the first non-zero hex value of the length
1337 while ((OldAlignment
& 0x0F) == 0x00) {
1338 OldAlignment
= RShiftU64 (OldAlignment
, 4);
1343 // Adjust the alignment to even, quad or double quad boundary
1345 if (NewAlignment
== PCI_BAR_EVEN_ALIGN
) {
1346 if ((OldAlignment
& 0x01) != 0) {
1347 OldAlignment
= OldAlignment
+ 2 - (OldAlignment
& 0x01);
1349 } else if (NewAlignment
== PCI_BAR_SQUAD_ALIGN
) {
1350 if ((OldAlignment
& 0x03) != 0) {
1351 OldAlignment
= OldAlignment
+ 4 - (OldAlignment
& 0x03);
1353 } else if (NewAlignment
== PCI_BAR_DQUAD_ALIGN
) {
1354 if ((OldAlignment
& 0x07) != 0) {
1355 OldAlignment
= OldAlignment
+ 8 - (OldAlignment
& 0x07);
1360 // Update the old value
1362 NewAlignment
= LShiftU64 (OldAlignment
, ShiftBit
) - 1;
1363 *Alignment
= NewAlignment
;
1369 Parse PCI IOV VF bar information and fill them into PCI device instance.
1371 @param PciIoDevice Pci device instance.
1372 @param Offset Bar offset.
1373 @param BarIndex Bar index.
1375 @return Next bar offset.
1380 IN PCI_IO_DEVICE
*PciIoDevice
,
1386 UINT32 OriginalValue
;
1393 // Ensure it is called properly
1395 ASSERT (PciIoDevice
->SrIovCapabilityOffset
!= 0);
1396 if (PciIoDevice
->SrIovCapabilityOffset
== 0) {
1403 Status
= VfBarExisted (
1410 if (EFI_ERROR (Status
)) {
1411 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1412 PciIoDevice
->VfPciBar
[BarIndex
].Length
= 0;
1413 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1416 // Scan all the BARs anyway
1418 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1422 PciIoDevice
->VfPciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1423 if ((Value
& 0x01) != 0) {
1425 // Device I/Os. Impossible
1434 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1436 switch (Value
& 0x07) {
1439 //memory space; anywhere in 32 bit address space
1442 if ((Value
& 0x08) != 0) {
1443 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1445 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1448 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1449 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1454 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1458 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1459 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1465 // memory space; anywhere in 64 bit address space
1468 if ((Value
& 0x08) != 0) {
1469 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1471 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1475 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1476 // is regarded as an extension for the first bar. As a result
1477 // the sizing will be conducted on combined 64 bit value
1478 // Here just store the masked first 32bit value for future size
1481 PciIoDevice
->VfPciBar
[BarIndex
].Length
= Value
& Mask
;
1482 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1484 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1485 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1489 // Increment the offset to point to next DWORD
1493 Status
= VfBarExisted (
1500 if (EFI_ERROR (Status
)) {
1505 // Fix the length to support some spefic 64 bit BAR
1509 for (Data
= Value
; Data
!= 0; Data
>>= 1) {
1512 Value
|= ((UINT32
)(-1) << Index
);
1515 // Calculate the size of 64bit bar
1517 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1519 PciIoDevice
->VfPciBar
[BarIndex
].Length
= PciIoDevice
->VfPciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1520 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(PciIoDevice
->VfPciBar
[BarIndex
].Length
)) + 1;
1521 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1526 PciIoDevice
->VfPciBar
[BarIndex
].Length
= MultU64x32 (PciIoDevice
->VfPciBar
[BarIndex
].Length
, PciIoDevice
->InitialVFs
);
1530 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1531 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1540 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1541 PciIoDevice
->VfPciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1542 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->VfPciBar
[BarIndex
].Length
- 1;
1544 if (PciIoDevice
->VfPciBar
[BarIndex
].Alignment
< PciIoDevice
->SystemPageSize
- 1) {
1545 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= PciIoDevice
->SystemPageSize
- 1;
1553 // Check the length again so as to keep compatible with some special bars
1555 if (PciIoDevice
->VfPciBar
[BarIndex
].Length
== 0) {
1556 PciIoDevice
->VfPciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1557 PciIoDevice
->VfPciBar
[BarIndex
].BaseAddress
= 0;
1558 PciIoDevice
->VfPciBar
[BarIndex
].Alignment
= 0;
1562 // Increment number of bar
1568 Parse PCI bar information and fill them into PCI device instance.
1570 @param PciIoDevice Pci device instance.
1571 @param Offset Bar offset.
1572 @param BarIndex Bar index.
1574 @return Next bar offset.
1579 IN PCI_IO_DEVICE
*PciIoDevice
,
1585 UINT32 OriginalValue
;
1594 Status
= BarExisted (
1601 if (EFI_ERROR (Status
)) {
1602 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1603 PciIoDevice
->PciBar
[BarIndex
].Length
= 0;
1604 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1607 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1609 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1613 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1614 if ((Value
& 0x01) != 0) {
1620 if ((Value
& 0xFFFF0000) != 0) {
1624 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo32
;
1625 PciIoDevice
->PciBar
[BarIndex
].Length
= ((~(Value
& Mask
)) + 1);
1626 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1632 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo16
;
1633 PciIoDevice
->PciBar
[BarIndex
].Length
= 0x0000FFFF & ((~(Value
& Mask
)) + 1);
1634 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1638 // Workaround. Some platforms inplement IO bar with 0 length
1639 // Need to treat it as no-bar
1641 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1642 PciIoDevice
->PciBar
[BarIndex
].BarType
= (PCI_BAR_TYPE
) 0;
1645 PciIoDevice
->PciBar
[BarIndex
].Prefetchable
= FALSE
;
1646 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1652 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1654 switch (Value
& 0x07) {
1657 //memory space; anywhere in 32 bit address space
1660 if ((Value
& 0x08) != 0) {
1661 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1663 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1666 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1667 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1669 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1671 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1673 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1678 // memory space; anywhere in 64 bit address space
1681 if ((Value
& 0x08) != 0) {
1682 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1684 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1688 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1689 // is regarded as an extension for the first bar. As a result
1690 // the sizing will be conducted on combined 64 bit value
1691 // Here just store the masked first 32bit value for future size
1694 PciIoDevice
->PciBar
[BarIndex
].Length
= Value
& Mask
;
1695 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1698 // Increment the offset to point to next DWORD
1702 Status
= BarExisted (
1709 if (EFI_ERROR (Status
)) {
1711 // the high 32 bit does not claim any BAR, we need to re-check the low 32 bit BAR again
1713 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1715 // some device implement MMIO bar with 0 length, need to treat it as no-bar
1717 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1723 // Fix the length to support some spefic 64 bit BAR
1727 for (Data
= Value
; Data
!= 0; Data
>>= 1) {
1730 Value
|= ((UINT32
)(-1) << Index
);
1733 // Calculate the size of 64bit bar
1735 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1737 PciIoDevice
->PciBar
[BarIndex
].Length
= PciIoDevice
->PciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1738 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(PciIoDevice
->PciBar
[BarIndex
].Length
)) + 1;
1739 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1741 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1743 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1745 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1754 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1755 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1756 if (PciIoDevice
->PciBar
[BarIndex
].Length
< (SIZE_4KB
)) {
1758 // Force minimum 4KByte alignment for Virtualization technology for Directed I/O
1760 PciIoDevice
->PciBar
[BarIndex
].Alignment
= (SIZE_4KB
- 1);
1762 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1769 // Check the length again so as to keep compatible with some special bars
1771 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1772 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1773 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1774 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1778 // Increment number of bar
1784 This routine is used to initialize the bar of a PCI device.
1786 @param PciIoDevice Pci device instance.
1788 @note It can be called typically when a device is going to be rejected.
1792 InitializePciDevice (
1793 IN PCI_IO_DEVICE
*PciIoDevice
1796 EFI_PCI_IO_PROTOCOL
*PciIo
;
1799 PciIo
= &(PciIoDevice
->PciIo
);
1802 // Put all the resource apertures
1803 // Resource base is set to all ones so as to indicate its resource
1804 // has not been alloacted
1806 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
1807 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllOne
);
1812 This routine is used to initialize the bar of a PCI-PCI Bridge device.
1814 @param PciIoDevice PCI-PCI bridge device instance.
1819 IN PCI_IO_DEVICE
*PciIoDevice
1822 EFI_PCI_IO_PROTOCOL
*PciIo
;
1824 PciIo
= &(PciIoDevice
->PciIo
);
1827 // Put all the resource apertures including IO16
1828 // Io32, pMem32, pMem64 to quiescent state
1829 // Resource base all ones, Resource limit all zeros
1831 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
1832 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x1D, 1, &gAllZero
);
1834 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x20, 1, &gAllOne
);
1835 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x22, 1, &gAllZero
);
1837 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x24, 1, &gAllOne
);
1838 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x26, 1, &gAllZero
);
1840 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllOne
);
1841 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2C, 1, &gAllZero
);
1844 // Don't support use io32 as for now
1846 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x30, 1, &gAllOne
);
1847 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint16
, 0x32, 1, &gAllZero
);
1850 // Force Interrupt line to zero for cards that come up randomly
1852 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1856 This routine is used to initialize the bar of a PCI Card Bridge device.
1858 @param PciIoDevice PCI Card bridge device.
1863 IN PCI_IO_DEVICE
*PciIoDevice
1866 EFI_PCI_IO_PROTOCOL
*PciIo
;
1868 PciIo
= &(PciIoDevice
->PciIo
);
1871 // Put all the resource apertures including IO16
1872 // Io32, pMem32, pMem64 to quiescent state(
1873 // Resource base all ones, Resource limit all zeros
1875 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x1c, 1, &gAllOne
);
1876 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x20, 1, &gAllZero
);
1878 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x24, 1, &gAllOne
);
1879 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllZero
);
1881 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x2c, 1, &gAllOne
);
1882 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x30, 1, &gAllZero
);
1884 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x34, 1, &gAllOne
);
1885 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint32
, 0x38, 1, &gAllZero
);
1888 // Force Interrupt line to zero for cards that come up randomly
1890 PciIo
->Pci
.Write (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1894 Create and initiliaze general PCI I/O device instance for
1895 PCI device/bridge device/hotplug bridge device.
1897 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1898 @param Pci Input Pci information block.
1899 @param Bus Device Bus NO.
1900 @param Device Device device NO.
1901 @param Func Device func NO.
1903 @return Instance of PCI device. NULL means no instance created.
1908 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
1915 PCI_IO_DEVICE
*PciIoDevice
;
1916 EFI_PCI_IO_PROTOCOL
*PciIo
;
1919 PciIoDevice
= AllocateZeroPool (sizeof (PCI_IO_DEVICE
));
1920 if (PciIoDevice
== NULL
) {
1924 PciIoDevice
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
1925 PciIoDevice
->Handle
= NULL
;
1926 PciIoDevice
->PciRootBridgeIo
= PciRootBridgeIo
;
1927 PciIoDevice
->DevicePath
= NULL
;
1928 PciIoDevice
->BusNumber
= Bus
;
1929 PciIoDevice
->DeviceNumber
= Device
;
1930 PciIoDevice
->FunctionNumber
= Func
;
1931 PciIoDevice
->Decodes
= 0;
1933 if (gFullEnumeration
) {
1934 PciIoDevice
->Allocated
= FALSE
;
1936 PciIoDevice
->Allocated
= TRUE
;
1939 PciIoDevice
->Registered
= FALSE
;
1940 PciIoDevice
->Attributes
= 0;
1941 PciIoDevice
->Supports
= 0;
1942 PciIoDevice
->BusOverride
= FALSE
;
1943 PciIoDevice
->AllOpRomProcessed
= FALSE
;
1945 PciIoDevice
->IsPciExp
= FALSE
;
1947 CopyMem (&(PciIoDevice
->Pci
), Pci
, sizeof (PCI_TYPE01
));
1950 // Initialize the PCI I/O instance structure
1952 InitializePciIoInstance (PciIoDevice
);
1953 InitializePciDriverOverrideInstance (PciIoDevice
);
1954 InitializePciLoadFile2 (PciIoDevice
);
1955 PciIo
= &PciIoDevice
->PciIo
;
1958 // Detect if PCI Express Device
1960 PciIoDevice
->PciExpressCapabilityOffset
= 0;
1961 Status
= LocateCapabilityRegBlock (
1963 EFI_PCI_CAPABILITY_ID_PCIEXP
,
1964 &PciIoDevice
->PciExpressCapabilityOffset
,
1967 if (!EFI_ERROR (Status
)) {
1968 PciIoDevice
->IsPciExp
= TRUE
;
1972 // Initialize for PCI IOV
1976 // Check ARI for function 0 only
1978 Status
= LocatePciExpressCapabilityRegBlock (
1980 EFI_PCIE_CAPABILITY_ID_ARI
,
1981 &PciIoDevice
->AriCapabilityOffset
,
1984 if (!EFI_ERROR (Status
)) {
1987 "PCI-IOV B%x.D%x.F%x - ARI Cap offset - 0x%x\n",
1991 (UINTN
)PciIoDevice
->AriCapabilityOffset
1995 Status
= LocatePciExpressCapabilityRegBlock (
1997 EFI_PCIE_CAPABILITY_ID_SRIOV
,
1998 &PciIoDevice
->SrIovCapabilityOffset
,
2001 if (!EFI_ERROR (Status
)) {
2004 "PCI-IOV B%x.D%x.F%x - SRIOV Cap offset - 0x%x\n",
2008 (UINTN
)PciIoDevice
->SrIovCapabilityOffset
2012 Status
= LocatePciExpressCapabilityRegBlock (
2014 EFI_PCIE_CAPABILITY_ID_MRIOV
,
2015 &PciIoDevice
->MrIovCapabilityOffset
,
2018 if (!EFI_ERROR (Status
)) {
2021 "PCI-IOV B%x.D%x.F%x - MRIOV Cap offset - 0x%x\n",
2025 (UINTN
)PciIoDevice
->MrIovCapabilityOffset
2030 // Calculate SystemPageSize
2032 if ((PciIoDevice
->SrIovCapabilityOffset
!= 0) && ((FeaturePcdGet(PcdSrIovSupport
)& EFI_PCI_IOV_POLICY_SRIOV
) != 0)) {
2036 EfiPciIoWidthUint32
,
2037 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SUPPORTED_PAGE_SIZE
,
2039 &PciIoDevice
->SystemPageSize
2041 DEBUG ((EFI_D_INFO
, "PCI-IOV B%x.D%x.F%x - SupportedPageSize - 0x%x\n", (UINTN
)Bus
, (UINTN
)Device
, (UINTN
)Func
, PciIoDevice
->SystemPageSize
));
2043 PciIoDevice
->SystemPageSize
= (PcdGet32 (PcdSrIovSystemPageSize
) & PciIoDevice
->SystemPageSize
);
2044 ASSERT (PciIoDevice
->SystemPageSize
!= 0);
2048 EfiPciIoWidthUint32
,
2049 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_SYSTEM_PAGE_SIZE
,
2051 &PciIoDevice
->SystemPageSize
2053 DEBUG ((EFI_D_INFO
, "PCI-IOV B%x.D%x.F%x - SystemPageSize - 0x%x\n", (UINTN
)Bus
, (UINTN
)Device
, (UINTN
)Func
, PciIoDevice
->SystemPageSize
));
2055 // Adjust SystemPageSize for Alignment usage later
2057 PciIoDevice
->SystemPageSize
<<= 12;
2060 // Calculate BusReservation for PCI IOV
2062 if ((PciIoDevice
->SrIovCapabilityOffset
!= 0) && ((FeaturePcdGet(PcdSrIovSupport
)& EFI_PCI_IOV_POLICY_SRIOV
) != 0)) {
2064 UINT16 FirstVFOffset
;
2069 // Read First FirstVFOffset, InitialVFs, and VFStride
2073 EfiPciIoWidthUint16
,
2074 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_FIRSTVF
,
2078 DEBUG ((EFI_D_INFO
, "PCI-IOV B%x.D%x.F%x - FirstVFOffset - 0x%x\n", (UINTN
)Bus
, (UINTN
)Device
, (UINTN
)Func
, (UINTN
)FirstVFOffset
));
2082 EfiPciIoWidthUint16
,
2083 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_INITIALVFS
,
2085 &PciIoDevice
->InitialVFs
2087 DEBUG ((EFI_D_INFO
, "PCI-IOV B%x.D%x.F%x - InitialVFs - 0x%x\n", (UINTN
)Bus
, (UINTN
)Device
, (UINTN
)Func
, (UINTN
)PciIoDevice
->InitialVFs
));
2091 EfiPciIoWidthUint16
,
2092 PciIoDevice
->SrIovCapabilityOffset
+ EFI_PCIE_CAPABILITY_ID_SRIOV_VFSTRIDE
,
2096 DEBUG ((EFI_D_INFO
, "PCI-IOV B%x.D%x.F%x - VFStride - 0x%x\n", (UINTN
)Bus
, (UINTN
)Device
, (UINTN
)Func
, (UINTN
)VFStride
));
2101 PFRid
= EFI_PCI_RID(Bus
, Device
, Func
);
2102 LastVF
= PFRid
+ FirstVFOffset
+ (PciIoDevice
->InitialVFs
- 1) * VFStride
;
2105 // Calculate ReservedBusNum for this PF
2107 PciIoDevice
->ReservedBusNum
= (UINT16
)(EFI_PCI_BUS_OF_RID (LastVF
) - Bus
+ 1);
2108 DEBUG ((EFI_D_INFO
, "PCI-IOV B%x.D%x.F%x - reserved bus number - 0x%x\n", (UINTN
)Bus
, (UINTN
)Device
, (UINTN
)Func
, (UINTN
)PciIoDevice
->ReservedBusNum
));
2113 // Initialize the reserved resource list
2115 InitializeListHead (&PciIoDevice
->ReservedResourceList
);
2118 // Initialize the driver list
2120 InitializeListHead (&PciIoDevice
->OptionRomDriverList
);
2123 // Initialize the child list
2125 InitializeListHead (&PciIoDevice
->ChildList
);
2131 This routine is used to enumerate entire pci bus system
2132 in a given platform.
2134 It is only called on the second start on the same Root Bridge.
2136 @param Controller Parent bridge handler.
2138 @retval EFI_SUCCESS PCI enumeration finished successfully.
2139 @retval other Some error occurred when enumerating the pci bus system.
2143 PciEnumeratorLight (
2144 IN EFI_HANDLE Controller
2149 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2150 PCI_IO_DEVICE
*RootBridgeDev
;
2153 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
2156 MaxBus
= PCI_MAX_BUS
;
2160 // If this root bridge has been already enumerated, then return successfully
2162 if (GetRootBridgeByHandle (Controller
) != NULL
) {
2167 // Open pci root bridge io protocol
2169 Status
= gBS
->OpenProtocol (
2171 &gEfiPciRootBridgeIoProtocolGuid
,
2172 (VOID
**) &PciRootBridgeIo
,
2173 gPciBusDriverBinding
.DriverBindingHandle
,
2175 EFI_OPEN_PROTOCOL_BY_DRIVER
2177 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2181 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
2183 if (EFI_ERROR (Status
)) {
2187 while (PciGetBusRange (&Descriptors
, &MinBus
, &MaxBus
, NULL
) == EFI_SUCCESS
) {
2190 // Create a device node for root bridge device with a NULL host bridge controller handle
2192 RootBridgeDev
= CreateRootBridge (Controller
);
2194 if (RootBridgeDev
== NULL
) {
2200 // Record the root bridgeio protocol
2202 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2204 Status
= PciPciDeviceInfoCollector (
2209 if (!EFI_ERROR (Status
)) {
2212 // Remove those PCI devices which are rejected when full enumeration
2214 RemoveRejectedPciDevices (RootBridgeDev
->Handle
, RootBridgeDev
);
2217 // Process option rom light
2219 ProcessOptionRomLight (RootBridgeDev
);
2222 // Determine attributes for all devices under this root bridge
2224 DetermineDeviceAttribute (RootBridgeDev
);
2227 // If successfully, insert the node into device pool
2229 InsertRootBridge (RootBridgeDev
);
2233 // If unsuccessly, destroy the entire node
2235 DestroyRootBridge (RootBridgeDev
);
2245 Get bus range from PCI resource descriptor list.
2247 @param Descriptors A pointer to the address space descriptor.
2248 @param MinBus The min bus returned.
2249 @param MaxBus The max bus returned.
2250 @param BusRange The bus range returned.
2252 @retval EFI_SUCCESS Successfully got bus range.
2253 @retval EFI_NOT_FOUND Can not find the specific bus.
2258 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptors
,
2261 OUT UINT16
*BusRange
2264 while ((*Descriptors
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
2265 if ((*Descriptors
)->ResType
== ACPI_ADDRESS_SPACE_TYPE_BUS
) {
2266 if (MinBus
!= NULL
) {
2267 *MinBus
= (UINT16
) (*Descriptors
)->AddrRangeMin
;
2270 if (MaxBus
!= NULL
) {
2271 *MaxBus
= (UINT16
) (*Descriptors
)->AddrRangeMax
;
2274 if (BusRange
!= NULL
) {
2275 *BusRange
= (UINT16
) (*Descriptors
)->AddrLen
;
2284 return EFI_NOT_FOUND
;
2288 This routine can be used to start the root bridge.
2290 @param RootBridgeDev Pci device instance.
2292 @retval EFI_SUCCESS This device started.
2293 @retval other Failed to get PCI Root Bridge I/O protocol.
2297 StartManagingRootBridge (
2298 IN PCI_IO_DEVICE
*RootBridgeDev
2301 EFI_HANDLE RootBridgeHandle
;
2303 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2306 // Get the root bridge handle
2308 RootBridgeHandle
= RootBridgeDev
->Handle
;
2309 PciRootBridgeIo
= NULL
;
2312 // Get the pci root bridge io protocol
2314 Status
= gBS
->OpenProtocol (
2316 &gEfiPciRootBridgeIoProtocolGuid
,
2317 (VOID
**) &PciRootBridgeIo
,
2318 gPciBusDriverBinding
.DriverBindingHandle
,
2320 EFI_OPEN_PROTOCOL_BY_DRIVER
2323 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2328 // Store the PciRootBridgeIo protocol into root bridge private data
2330 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2337 This routine can be used to check whether a PCI device should be rejected when light enumeration.
2339 @param PciIoDevice Pci device instance.
2341 @retval TRUE This device should be rejected.
2342 @retval FALSE This device shouldn't be rejected.
2346 IsPciDeviceRejected (
2347 IN PCI_IO_DEVICE
*PciIoDevice
2357 // PPB should be skip!
2359 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
2363 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
2365 // Only test base registers for P2C
2367 for (BarOffset
= 0x1C; BarOffset
<= 0x38; BarOffset
+= 2 * sizeof (UINT32
)) {
2369 Mask
= (BarOffset
< 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
2370 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2371 if (EFI_ERROR (Status
)) {
2375 TestValue
= TestValue
& Mask
;
2376 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2378 // The bar isn't programed, so it should be rejected
2387 for (BarOffset
= 0x14; BarOffset
<= 0x24; BarOffset
+= sizeof (UINT32
)) {
2391 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2392 if (EFI_ERROR (Status
)) {
2396 if ((TestValue
& 0x01) != 0) {
2402 TestValue
= TestValue
& Mask
;
2403 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2413 TestValue
= TestValue
& Mask
;
2415 if ((TestValue
& 0x07) == 0x04) {
2420 BarOffset
+= sizeof (UINT32
);
2421 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2424 // Test its high 32-Bit BAR
2426 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2427 if (TestValue
== OldValue
) {
2437 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2448 Reset all bus number from specific bridge.
2450 @param Bridge Parent specific bridge.
2451 @param StartBusNumber Start bus number.
2455 ResetAllPpbBusNumber (
2456 IN PCI_IO_DEVICE
*Bridge
,
2457 IN UINT8 StartBusNumber
2467 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2469 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
2471 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
2472 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
2475 // Check to see whether a pci device is present
2477 Status
= PciDevicePresent (
2485 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
))) {
2488 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
2489 Status
= PciRootBridgeIo
->Pci
.Read (
2496 SecondaryBus
= (UINT8
)(Register
>> 8);
2498 if (SecondaryBus
!= 0) {
2499 ResetAllPpbBusNumber (Bridge
, SecondaryBus
);
2503 // Reset register 18h, 19h, 1Ah on PCI Bridge
2505 Register
&= 0xFF000000;
2506 Status
= PciRootBridgeIo
->Pci
.Write (
2515 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
2517 // Skip sub functions, this is not a multi function device
2519 Func
= PCI_MAX_FUNC
;