2 PCI emumeration support functions implementation for PCI Bus module.
4 Copyright (c) 2006 - 2009, Intel Corporation
5 All rights reserved. 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
= PciRootBridgeIoRead (
59 if (!EFI_ERROR (Status
) && (Pci
->Hdr
).VendorId
!= 0xffff) {
61 // Read the entire config header for the device
63 Status
= PciRootBridgeIoRead (
68 sizeof (PCI_TYPE00
) / sizeof (UINT32
),
79 Collect all the resource information under this root bridge.
81 A database that records all the information about pci device subject to this
82 root bridge will then be created.
84 @param Bridge Parent bridge instance.
85 @param StartBusNumber Bus number of begining.
87 @retval EFI_SUCCESS PCI device is found.
88 @retval other Some error occurred when reading PCI bridge information.
92 PciPciDeviceInfoCollector (
93 IN PCI_IO_DEVICE
*Bridge
,
94 IN UINT8 StartBusNumber
102 PCI_IO_DEVICE
*PciIoDevice
;
103 EFI_PCI_IO_PROTOCOL
*PciIo
;
105 Status
= EFI_SUCCESS
;
108 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
110 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
113 // Check to see whether PCI device is present
115 Status
= PciDevicePresent (
116 Bridge
->PciRootBridgeIo
,
118 (UINT8
) StartBusNumber
,
122 if (!EFI_ERROR (Status
)) {
125 // Call back to host bridge function
127 PreprocessController (Bridge
, (UINT8
) StartBusNumber
, Device
, Func
, EfiPciBeforeResourceCollection
);
130 // Collect all the information about the PCI device discovered
132 Status
= PciSearchDevice (
135 (UINT8
) StartBusNumber
,
142 // Recursively scan PCI busses on the other side of PCI-PCI bridges
145 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
148 // If it is PPB, we need to get the secondary bus to continue the enumeration
150 PciIo
= &(PciIoDevice
->PciIo
);
152 Status
= PciIoRead (PciIo
, EfiPciIoWidthUint8
, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET
, 1, &SecBus
);
154 if (EFI_ERROR (Status
)) {
159 // Get resource padding for PPB
161 GetResourcePaddingPpb (PciIoDevice
);
164 // Deep enumerate the next level bus
166 Status
= PciPciDeviceInfoCollector (
173 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
176 // Skip sub functions, this is not a multi function device
189 Seach required device and create PCI device instance.
191 @param Bridge Parent bridge instance.
192 @param Pci Input PCI device information block.
193 @param Bus PCI bus NO.
194 @param Device PCI device NO.
195 @param Func PCI func NO.
196 @param PciDevice Output of searched PCI device instance.
198 @retval EFI_SUCCESS Successfully created PCI device instance.
199 @retval EFI_OUT_OF_RESOURCES Cannot get PCI device information.
204 IN PCI_IO_DEVICE
*Bridge
,
209 OUT PCI_IO_DEVICE
**PciDevice
212 PCI_IO_DEVICE
*PciIoDevice
;
216 if (!IS_PCI_BRIDGE (Pci
)) {
218 if (IS_CARDBUS_BRIDGE (Pci
)) {
219 PciIoDevice
= GatherP2CInfo (
226 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
227 InitializeP2C (PciIoDevice
);
232 // Create private data for Pci Device
234 PciIoDevice
= GatherDeviceInfo (
247 // Create private data for PPB
249 PciIoDevice
= GatherPpbInfo (
258 // Special initialization for PPB including making the PPB quiet
260 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
261 InitializePpb (PciIoDevice
);
265 if (PciIoDevice
== NULL
) {
266 return EFI_OUT_OF_RESOURCES
;
270 // Update the bar information for this PCI device so as to support some specific device
272 UpdatePciInfo (PciIoDevice
);
274 if (PciIoDevice
->DevicePath
== NULL
) {
275 return EFI_OUT_OF_RESOURCES
;
279 // Detect this function has option rom
281 if (gFullEnumeration
) {
283 if (!IS_CARDBUS_BRIDGE (Pci
)) {
285 GetOpRomInfo (PciIoDevice
);
289 ResetPowerManagementFeature (PciIoDevice
);
294 // Insert it into a global tree for future reference
296 InsertPciDevice (Bridge
, PciIoDevice
);
299 // Determine PCI device attributes
302 if (PciDevice
!= NULL
) {
303 *PciDevice
= PciIoDevice
;
310 Create PCI device instance for PCI device.
312 @param Bridge Parent bridge instance.
313 @param Pci Input PCI device information block.
314 @param Bus PCI device Bus NO.
315 @param Device PCI device Device NO.
316 @param Func PCI device's func NO.
318 @return Created PCI device instance.
323 IN PCI_IO_DEVICE
*Bridge
,
332 PCI_IO_DEVICE
*PciIoDevice
;
333 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
335 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
336 PciIoDevice
= CreatePciIoDevice (
344 if (PciIoDevice
== NULL
) {
349 // Create a device path for this PCI device and store it into its private data
351 CreatePciDevicePath (
357 // If it is a full enumeration, disconnect the device in advance
359 if (gFullEnumeration
) {
361 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
366 // Start to parse the bars
368 for (Offset
= 0x10, BarIndex
= 0; Offset
<= 0x24 && BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
369 Offset
= PciParseBar (PciIoDevice
, Offset
, BarIndex
);
376 Create PCI device instance for PCI-PCI bridge.
378 @param Bridge Parent bridge instance.
379 @param Pci Input PCI device information block.
380 @param Bus PCI device Bus NO.
381 @param Device PCI device Device NO.
382 @param Func PCI device's func NO.
384 @return Created PCI device instance.
389 IN PCI_IO_DEVICE
*Bridge
,
396 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
397 PCI_IO_DEVICE
*PciIoDevice
;
400 EFI_PCI_IO_PROTOCOL
*PciIo
;
403 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
404 PciIoDevice
= CreatePciIoDevice (
412 if (PciIoDevice
== NULL
) {
417 // Create a device path for this PCI device and store it into its private data
419 CreatePciDevicePath (
424 if (gFullEnumeration
) {
425 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
428 // Initalize the bridge control register
430 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED
);
435 // PPB can have two BARs
437 if (PciParseBar (PciIoDevice
, 0x10, PPB_BAR_0
) == 0x14) {
441 PciParseBar (PciIoDevice
, 0x14, PPB_BAR_1
);
444 PciIo
= &PciIoDevice
->PciIo
;
447 // Test whether it support 32 decode or not
449 PciIoRead (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
450 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
451 PciIoRead (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
452 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
455 if ((Value
& 0x01) != 0) {
456 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
458 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
462 Status
= BarExisted (
470 // Test if it supports 64 memory or not
472 if (!EFI_ERROR (Status
)) {
474 Status
= BarExisted (
481 if (!EFI_ERROR (Status
)) {
482 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
483 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
485 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
490 // Memory 32 code is required for ppb
492 PciIoDevice
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
494 GetResourcePaddingPpb (PciIoDevice
);
501 Create PCI device instance for PCI Card bridge device.
503 @param Bridge Parent bridge instance.
504 @param Pci Input PCI device information block.
505 @param Bus PCI device Bus NO.
506 @param Device PCI device Device NO.
507 @param Func PCI device's func NO.
509 @return Created PCI device instance.
514 IN PCI_IO_DEVICE
*Bridge
,
521 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
522 PCI_IO_DEVICE
*PciIoDevice
;
524 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
525 PciIoDevice
= CreatePciIoDevice (
533 if (PciIoDevice
== NULL
) {
538 // Create a device path for this PCI device and store it into its private data
540 CreatePciDevicePath (
545 if (gFullEnumeration
) {
546 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
549 // Initalize the bridge control register
551 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED
);
555 // P2C only has one bar that is in 0x10
557 PciParseBar (PciIoDevice
, 0x10, P2C_BAR_0
);
560 // Read PciBar information from the bar register
562 GetBackPcCardBar (PciIoDevice
);
563 PciIoDevice
->Decodes
= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
|
564 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
|
565 EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
571 Create device path for pci deivce.
573 @param ParentDevicePath Parent bridge's path.
574 @param PciIoDevice Pci device instance.
576 @return Device path protocol instance for specific pci device.
579 EFI_DEVICE_PATH_PROTOCOL
*
580 CreatePciDevicePath (
581 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
582 IN PCI_IO_DEVICE
*PciIoDevice
586 PCI_DEVICE_PATH PciNode
;
589 // Create PCI device path
591 PciNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
592 PciNode
.Header
.SubType
= HW_PCI_DP
;
593 SetDevicePathNodeLength (&PciNode
.Header
, sizeof (PciNode
));
595 PciNode
.Device
= PciIoDevice
->DeviceNumber
;
596 PciNode
.Function
= PciIoDevice
->FunctionNumber
;
597 PciIoDevice
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, &PciNode
.Header
);
599 return PciIoDevice
->DevicePath
;
603 Check whether the bar is existed or not.
605 @param PciIoDevice A pointer to the PCI_IO_DEVICE.
606 @param Offset The offset.
607 @param BarLengthValue The bar length value returned.
608 @param OriginalBarValue The original bar value returned.
610 @retval EFI_NOT_FOUND The bar doesn't exist.
611 @retval EFI_SUCCESS The bar exist.
616 IN PCI_IO_DEVICE
*PciIoDevice
,
618 OUT UINT32
*BarLengthValue
,
619 OUT UINT32
*OriginalBarValue
622 EFI_PCI_IO_PROTOCOL
*PciIo
;
623 UINT32 OriginalValue
;
627 PciIo
= &PciIoDevice
->PciIo
;
630 // Preserve the original value
632 PciIoRead (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
635 // Raise TPL to high level to disable timer interrupt while the BAR is probed
637 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
639 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &gAllOne
);
640 PciIoRead (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &Value
);
643 // Write back the original value
645 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
648 // Restore TPL to its original level
650 gBS
->RestoreTPL (OldTpl
);
652 if (BarLengthValue
!= NULL
) {
653 *BarLengthValue
= Value
;
656 if (OriginalBarValue
!= NULL
) {
657 *OriginalBarValue
= OriginalValue
;
661 return EFI_NOT_FOUND
;
668 Test whether the device can support given attributes.
670 @param PciIoDevice Pci device instance.
671 @param Command Input command register value, and
672 returned supported register value.
673 @param BridgeControl Inout bridge control value for PPB or P2C, and
674 returned supported bridge control value.
675 @param OldCommand Returned and stored old command register offset.
676 @param OldBridgeControl Returned and stored old Bridge control value for PPB or P2C.
680 PciTestSupportedAttribute (
681 IN PCI_IO_DEVICE
*PciIoDevice
,
682 IN OUT UINT16
*Command
,
683 IN OUT UINT16
*BridgeControl
,
684 OUT UINT16
*OldCommand
,
685 OUT UINT16
*OldBridgeControl
691 // Preserve the original value
693 PCI_READ_COMMAND_REGISTER (PciIoDevice
, OldCommand
);
696 // Raise TPL to high level to disable timer interrupt while the BAR is probed
698 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
700 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *Command
);
701 PCI_READ_COMMAND_REGISTER (PciIoDevice
, Command
);
704 // Write back the original value
706 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *OldCommand
);
709 // Restore TPL to its original level
711 gBS
->RestoreTPL (OldTpl
);
713 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
716 // Preserve the original value
718 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, OldBridgeControl
);
721 // Raise TPL to high level to disable timer interrupt while the BAR is probed
723 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
725 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *BridgeControl
);
726 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, BridgeControl
);
729 // Write back the original value
731 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *OldBridgeControl
);
734 // Restore TPL to its original level
736 gBS
->RestoreTPL (OldTpl
);
739 *OldBridgeControl
= 0;
745 Set the supported or current attributes of a PCI device.
747 @param PciIoDevice Structure pointer for PCI device.
748 @param Command Command register value.
749 @param BridgeControl Bridge control value for PPB or P2C.
750 @param Option Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
754 PciSetDeviceAttribute (
755 IN PCI_IO_DEVICE
*PciIoDevice
,
757 IN UINT16 BridgeControl
,
765 if ((Command
& EFI_PCI_COMMAND_IO_SPACE
) != 0) {
766 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IO
;
769 if ((Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) != 0) {
770 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY
;
773 if ((Command
& EFI_PCI_COMMAND_BUS_MASTER
) != 0) {
774 Attributes
|= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
;
777 if ((Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
778 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
781 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
) != 0) {
782 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
785 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
) != 0) {
786 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
787 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
788 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
791 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
) != 0) {
792 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
;
793 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
;
796 if (Option
== EFI_SET_SUPPORTS
) {
798 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
799 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
|
800 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE
|
801 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
802 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
803 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
;
805 if ((Attributes
& EFI_PCI_IO_ATTRIBUTE_IO
) != 0) {
806 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
807 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
810 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
812 // For bridge, it should support IDE attributes
814 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
815 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
818 if (IS_PCI_IDE (&PciIoDevice
->Pci
)) {
819 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
820 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
823 if (IS_PCI_VGA (&PciIoDevice
->Pci
)) {
824 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
825 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
829 PciIoDevice
->Supports
= Attributes
;
830 PciIoDevice
->Supports
&= ( (PciIoDevice
->Parent
->Supports
) | \
831 EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
| \
832 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
);
835 PciIoDevice
->Attributes
= Attributes
;
840 Determine if the device can support Fast Back to Back attribute.
842 @param PciIoDevice Pci device instance.
843 @param StatusIndex Status register value.
845 @retval EFI_SUCCESS This device support Fast Back to Back attribute.
846 @retval EFI_UNSUPPORTED This device doesn't support Fast Back to Back attribute.
850 GetFastBackToBackSupport (
851 IN PCI_IO_DEVICE
*PciIoDevice
,
855 EFI_PCI_IO_PROTOCOL
*PciIo
;
857 UINT32 StatusRegister
;
860 // Read the status register
862 PciIo
= &PciIoDevice
->PciIo
;
863 Status
= PciIoRead (PciIo
, EfiPciIoWidthUint16
, StatusIndex
, 1, &StatusRegister
);
864 if (EFI_ERROR (Status
)) {
865 return EFI_UNSUPPORTED
;
869 // Check the Fast B2B bit
871 if ((StatusRegister
& EFI_PCI_FAST_BACK_TO_BACK_CAPABLE
) != 0) {
874 return EFI_UNSUPPORTED
;
879 Process the option ROM for all the children of the specified parent PCI device.
880 It can only be used after the first full Option ROM process.
882 @param PciIoDevice Pci device instance.
886 ProcessOptionRomLight (
887 IN PCI_IO_DEVICE
*PciIoDevice
891 LIST_ENTRY
*CurrentLink
;
894 // For RootBridge, PPB , P2C, go recursively to traverse all its children
896 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
897 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
899 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
901 if (!IsListEmpty (&Temp
->ChildList
)) {
902 ProcessOptionRomLight (Temp
);
905 PciRomGetImageMapping (Temp
);
908 // The OpRom has already been processed in the first round
910 Temp
->AllOpRomProcessed
= TRUE
;
912 CurrentLink
= CurrentLink
->ForwardLink
;
917 Determine the related attributes of all devices under a Root Bridge.
919 @param PciIoDevice PCI device instance.
923 DetermineDeviceAttribute (
924 IN PCI_IO_DEVICE
*PciIoDevice
928 UINT16 BridgeControl
;
930 UINT16 OldBridgeControl
;
931 BOOLEAN FastB2BSupport
;
933 LIST_ENTRY
*CurrentLink
;
937 // For Root Bridge, just copy it by RootBridgeIo proctocol
938 // so as to keep consistent with the actual attribute
940 if (PciIoDevice
->Parent
== NULL
) {
941 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
942 PciIoDevice
->PciRootBridgeIo
,
943 &PciIoDevice
->Supports
,
944 &PciIoDevice
->Attributes
946 if (EFI_ERROR (Status
)) {
952 // Set the attributes to be checked for common PCI devices and PPB or P2C
953 // Since some devices only support part of them, it is better to set the
954 // attribute according to its command or bridge control register
956 Command
= EFI_PCI_COMMAND_IO_SPACE
|
957 EFI_PCI_COMMAND_MEMORY_SPACE
|
958 EFI_PCI_COMMAND_BUS_MASTER
|
959 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
961 BridgeControl
= EFI_PCI_BRIDGE_CONTROL_ISA
| EFI_PCI_BRIDGE_CONTROL_VGA
| EFI_PCI_BRIDGE_CONTROL_VGA_16
;
964 // Test whether the device can support attributes above
966 PciTestSupportedAttribute (PciIoDevice
, &Command
, &BridgeControl
, &OldCommand
, &OldBridgeControl
);
969 // Set the supported attributes for specified PCI device
971 PciSetDeviceAttribute (PciIoDevice
, Command
, BridgeControl
, EFI_SET_SUPPORTS
);
974 // Set the current attributes for specified PCI device
976 PciSetDeviceAttribute (PciIoDevice
, OldCommand
, OldBridgeControl
, EFI_SET_ATTRIBUTES
);
979 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
981 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE
);
984 FastB2BSupport
= TRUE
;
987 // P2C can not support FB2B on the secondary side
989 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
990 FastB2BSupport
= FALSE
;
994 // For RootBridge, PPB , P2C, go recursively to traverse all its children
996 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
997 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
999 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1000 Status
= DetermineDeviceAttribute (Temp
);
1001 if (EFI_ERROR (Status
)) {
1005 // Detect Fast Bact to Bact support for the device under the bridge
1007 Status
= GetFastBackToBackSupport (Temp
, PCI_PRIMARY_STATUS_OFFSET
);
1008 if (FastB2BSupport
&& EFI_ERROR (Status
)) {
1009 FastB2BSupport
= FALSE
;
1012 CurrentLink
= CurrentLink
->ForwardLink
;
1015 // Set or clear Fast Back to Back bit for the whole bridge
1017 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
1019 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
1021 Status
= GetFastBackToBackSupport (PciIoDevice
, PCI_BRIDGE_STATUS_REGISTER_OFFSET
);
1023 if (EFI_ERROR (Status
) || (!FastB2BSupport
)) {
1024 FastB2BSupport
= FALSE
;
1025 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1027 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1031 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1032 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1033 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1034 if (FastB2BSupport
) {
1035 PCI_ENABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1037 PCI_DISABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1040 CurrentLink
= CurrentLink
->ForwardLink
;
1044 // End for IsListEmpty
1050 This routine is used to update the bar information for those incompatible PCI device.
1052 @param PciIoDevice Pci device instance.
1054 @retval EFI_SUCCESS Successfully updated bar information.
1055 @retval EFI_UNSUPPORTED Given PCI device doesn't belong to incompatible PCI device list.
1056 @retval other Failed to check incompatibility device.
1061 IN PCI_IO_DEVICE
*PciIoDevice
1068 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
1069 VOID
*Configuration
;
1070 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1072 Configuration
= NULL
;
1073 Status
= EFI_SUCCESS
;
1075 if (gEfiIncompatiblePciDeviceSupport
== NULL
) {
1077 // It can only be supported after the Incompatible PCI Device
1078 // Support Protocol has been installed
1080 Status
= gBS
->LocateProtocol (
1081 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
1083 (VOID
**) &gEfiIncompatiblePciDeviceSupport
1086 if (Status
== EFI_SUCCESS
) {
1088 // Check whether the device belongs to incompatible devices from protocol or not
1089 // If it is , then get its special requirement in the ACPI table
1091 Status
= gEfiIncompatiblePciDeviceSupport
->CheckDevice (
1092 gEfiIncompatiblePciDeviceSupport
,
1093 PciIoDevice
->Pci
.Hdr
.VendorId
,
1094 PciIoDevice
->Pci
.Hdr
.DeviceId
,
1095 PciIoDevice
->Pci
.Hdr
.RevisionID
,
1096 PciIoDevice
->Pci
.Device
.SubsystemVendorID
,
1097 PciIoDevice
->Pci
.Device
.SubsystemID
,
1103 if (EFI_ERROR (Status
)) {
1105 // Check whether the device belongs to incompatible devices from library or not
1106 // If it is , then get its special requirement in the ACPI table
1108 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACPI_RESOURCE_SUPPORT
) {
1109 PciDeviceInfo
.VendorID
= PciIoDevice
->Pci
.Hdr
.VendorId
;
1110 PciDeviceInfo
.DeviceID
= PciIoDevice
->Pci
.Hdr
.DeviceId
;
1111 PciDeviceInfo
.RevisionID
= PciIoDevice
->Pci
.Hdr
.RevisionID
;
1112 PciDeviceInfo
.SubsystemVendorID
= PciIoDevice
->Pci
.Device
.SubsystemVendorID
;
1113 PciDeviceInfo
.SubsystemID
= PciIoDevice
->Pci
.Device
.SubsystemID
;
1115 Status
= PciResourceUpdateCheck (&PciDeviceInfo
, &Configuration
);
1119 if (EFI_ERROR (Status
) || Configuration
== NULL
) {
1120 return EFI_UNSUPPORTED
;
1124 // Update PCI device information from the ACPI table
1126 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1128 while (Ptr
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1130 if (Ptr
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1132 // The format is not support
1137 BarIndex
= (UINTN
) Ptr
->AddrTranslationOffset
;
1138 BarEndIndex
= BarIndex
;
1141 // Update all the bars in the device
1143 if (BarIndex
== PCI_BAR_ALL
) {
1145 BarEndIndex
= PCI_MAX_BAR
- 1;
1148 if (BarIndex
>= PCI_MAX_BAR
) {
1153 for (; BarIndex
<= BarEndIndex
; BarIndex
++) {
1155 switch (Ptr
->ResType
) {
1156 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1159 // Make sure the bar is memory type
1161 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeMem
)) {
1166 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1169 // Make sure the bar is IO type
1171 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeIo
)) {
1180 // Update the new alignment for the device
1182 SetNewAlign (&(PciIoDevice
->PciBar
[BarIndex
].Alignment
), Ptr
->AddrRangeMax
);
1185 // Update the new length for the device
1187 if (Ptr
->AddrLen
!= PCI_BAR_NOCHANGE
) {
1188 PciIoDevice
->PciBar
[BarIndex
].Length
= Ptr
->AddrLen
;
1196 if (Configuration
!= NULL
) {
1197 FreePool (Configuration
);
1204 This routine will update the alignment with the new alignment.
1206 @param Alignment Old alignment.
1207 @param NewAlignment New alignment.
1212 IN UINT64
*Alignment
,
1213 IN UINT64 NewAlignment
1216 UINT64 OldAlignment
;
1220 // The new alignment is the same as the original,
1223 if (NewAlignment
== PCI_BAR_OLD_ALIGN
) {
1227 // Check the validity of the parameter
1229 if (NewAlignment
!= PCI_BAR_EVEN_ALIGN
&&
1230 NewAlignment
!= PCI_BAR_SQUAD_ALIGN
&&
1231 NewAlignment
!= PCI_BAR_DQUAD_ALIGN
) {
1232 *Alignment
= NewAlignment
;
1236 OldAlignment
= (*Alignment
) + 1;
1240 // Get the first non-zero hex value of the length
1242 while ((OldAlignment
& 0x0F) == 0x00) {
1243 OldAlignment
= RShiftU64 (OldAlignment
, 4);
1248 // Adjust the alignment to even, quad or double quad boundary
1250 if (NewAlignment
== PCI_BAR_EVEN_ALIGN
) {
1251 if ((OldAlignment
& 0x01) != 0) {
1252 OldAlignment
= OldAlignment
+ 2 - (OldAlignment
& 0x01);
1254 } else if (NewAlignment
== PCI_BAR_SQUAD_ALIGN
) {
1255 if ((OldAlignment
& 0x03) != 0) {
1256 OldAlignment
= OldAlignment
+ 4 - (OldAlignment
& 0x03);
1258 } else if (NewAlignment
== PCI_BAR_DQUAD_ALIGN
) {
1259 if ((OldAlignment
& 0x07) != 0) {
1260 OldAlignment
= OldAlignment
+ 8 - (OldAlignment
& 0x07);
1265 // Update the old value
1267 NewAlignment
= LShiftU64 (OldAlignment
, ShiftBit
) - 1;
1268 *Alignment
= NewAlignment
;
1274 Parse PCI bar information and fill them into PCI device instance.
1276 @param PciIoDevice Pci device instance.
1277 @param Offset Bar offset.
1278 @param BarIndex Bar index.
1280 @return Next bar offset.
1285 IN PCI_IO_DEVICE
*PciIoDevice
,
1291 UINT32 OriginalValue
;
1300 Status
= BarExisted (
1307 if (EFI_ERROR (Status
)) {
1308 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1309 PciIoDevice
->PciBar
[BarIndex
].Length
= 0;
1310 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1313 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1315 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1319 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1320 if ((Value
& 0x01) != 0) {
1326 if ((Value
& 0xFFFF0000) != 0) {
1330 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo32
;
1331 PciIoDevice
->PciBar
[BarIndex
].Length
= ((~(Value
& Mask
)) + 1);
1332 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1338 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo16
;
1339 PciIoDevice
->PciBar
[BarIndex
].Length
= 0x0000FFFF & ((~(Value
& Mask
)) + 1);
1340 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1344 // Workaround. Some platforms inplement IO bar with 0 length
1345 // Need to treat it as no-bar
1347 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1348 PciIoDevice
->PciBar
[BarIndex
].BarType
= (PCI_BAR_TYPE
) 0;
1351 PciIoDevice
->PciBar
[BarIndex
].Prefetchable
= FALSE
;
1352 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1358 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1360 switch (Value
& 0x07) {
1363 //memory space; anywhere in 32 bit address space
1366 if ((Value
& 0x08) != 0) {
1367 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1369 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1372 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1373 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1378 // memory space; anywhere in 64 bit address space
1381 if ((Value
& 0x08) != 0) {
1382 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1384 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1388 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1389 // is regarded as an extension for the first bar. As a result
1390 // the sizing will be conducted on combined 64 bit value
1391 // Here just store the masked first 32bit value for future size
1394 PciIoDevice
->PciBar
[BarIndex
].Length
= Value
& Mask
;
1395 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1398 // Increment the offset to point to next DWORD
1402 Status
= BarExisted (
1409 if (EFI_ERROR (Status
)) {
1414 // Fix the length to support some spefic 64 bit BAR
1418 for (Data
= Value
; Data
!= 0; Data
>>= 1) {
1421 Value
|= ((UINT32
)(-1) << Index
);
1424 // Calculate the size of 64bit bar
1426 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1428 PciIoDevice
->PciBar
[BarIndex
].Length
= PciIoDevice
->PciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1429 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(PciIoDevice
->PciBar
[BarIndex
].Length
)) + 1;
1430 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1438 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1439 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1440 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1447 // Check the length again so as to keep compatible with some special bars
1449 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1450 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1451 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1452 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1456 // Increment number of bar
1462 This routine is used to initialize the bar of a PCI device.
1464 @param PciIoDevice Pci device instance.
1466 @note It can be called typically when a device is going to be rejected.
1470 InitializePciDevice (
1471 IN PCI_IO_DEVICE
*PciIoDevice
1474 EFI_PCI_IO_PROTOCOL
*PciIo
;
1477 PciIo
= &(PciIoDevice
->PciIo
);
1480 // Put all the resource apertures
1481 // Resource base is set to all ones so as to indicate its resource
1482 // has not been alloacted
1484 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
1485 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllOne
);
1490 This routine is used to initialize the bar of a PCI-PCI Bridge device.
1492 @param PciIoDevice PCI-PCI bridge device instance.
1497 IN PCI_IO_DEVICE
*PciIoDevice
1500 EFI_PCI_IO_PROTOCOL
*PciIo
;
1502 PciIo
= &(PciIoDevice
->PciIo
);
1505 // Put all the resource apertures including IO16
1506 // Io32, pMem32, pMem64 to quiescent state
1507 // Resource base all ones, Resource limit all zeros
1509 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
1510 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1D, 1, &gAllZero
);
1512 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x20, 1, &gAllOne
);
1513 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x22, 1, &gAllZero
);
1515 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x24, 1, &gAllOne
);
1516 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x26, 1, &gAllZero
);
1518 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllOne
);
1519 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x2C, 1, &gAllZero
);
1522 // don't support use io32 as for now
1524 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x30, 1, &gAllOne
);
1525 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x32, 1, &gAllZero
);
1528 // Force Interrupt line to zero for cards that come up randomly
1530 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1534 This routine is used to initialize the bar of a PCI Card Bridge device.
1536 @param PciIoDevice PCI Card bridge device.
1541 IN PCI_IO_DEVICE
*PciIoDevice
1544 EFI_PCI_IO_PROTOCOL
*PciIo
;
1546 PciIo
= &(PciIoDevice
->PciIo
);
1549 // Put all the resource apertures including IO16
1550 // Io32, pMem32, pMem64 to quiescent state(
1551 // Resource base all ones, Resource limit all zeros
1553 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x1c, 1, &gAllOne
);
1554 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x20, 1, &gAllZero
);
1556 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x24, 1, &gAllOne
);
1557 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllZero
);
1559 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x2c, 1, &gAllOne
);
1560 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x30, 1, &gAllZero
);
1562 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x34, 1, &gAllOne
);
1563 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x38, 1, &gAllZero
);
1566 // Force Interrupt line to zero for cards that come up randomly
1568 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1572 Create and initiliaze general PCI I/O device instance for
1573 PCI device/bridge device/hotplug bridge device.
1575 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1576 @param Pci Input Pci information block.
1577 @param Bus Device Bus NO.
1578 @param Device Device device NO.
1579 @param Func Device func NO.
1581 @return Instance of PCI device. NULL means no instance created.
1586 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
1593 PCI_IO_DEVICE
*PciIoDevice
;
1595 PciIoDevice
= AllocateZeroPool (sizeof (PCI_IO_DEVICE
));
1596 if (PciIoDevice
== NULL
) {
1600 PciIoDevice
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
1601 PciIoDevice
->Handle
= NULL
;
1602 PciIoDevice
->PciRootBridgeIo
= PciRootBridgeIo
;
1603 PciIoDevice
->DevicePath
= NULL
;
1604 PciIoDevice
->BusNumber
= Bus
;
1605 PciIoDevice
->DeviceNumber
= Device
;
1606 PciIoDevice
->FunctionNumber
= Func
;
1607 PciIoDevice
->Decodes
= 0;
1609 if (gFullEnumeration
) {
1610 PciIoDevice
->Allocated
= FALSE
;
1612 PciIoDevice
->Allocated
= TRUE
;
1615 PciIoDevice
->Registered
= FALSE
;
1616 PciIoDevice
->Attributes
= 0;
1617 PciIoDevice
->Supports
= 0;
1618 PciIoDevice
->BusOverride
= FALSE
;
1619 PciIoDevice
->AllOpRomProcessed
= FALSE
;
1621 PciIoDevice
->IsPciExp
= FALSE
;
1623 CopyMem (&(PciIoDevice
->Pci
), Pci
, sizeof (PCI_TYPE01
));
1626 // Initialize the PCI I/O instance structure
1628 InitializePciIoInstance (PciIoDevice
);
1629 InitializePciDriverOverrideInstance (PciIoDevice
);
1630 InitializePciLoadFile2 (PciIoDevice
);
1633 // Initialize the reserved resource list
1635 InitializeListHead (&PciIoDevice
->ReservedResourceList
);
1638 // Initialize the driver list
1640 InitializeListHead (&PciIoDevice
->OptionRomDriverList
);
1643 // Initialize the child list
1645 InitializeListHead (&PciIoDevice
->ChildList
);
1651 This routine is used to enumerate entire pci bus system
1652 in a given platform.
1654 It is only called on the second start on the same Root Bridge.
1656 @param Controller Parent bridge handler.
1658 @retval EFI_SUCCESS PCI enumeration finished successfully.
1659 @retval other Some error occurred when enumerating the pci bus system.
1663 PciEnumeratorLight (
1664 IN EFI_HANDLE Controller
1669 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1670 PCI_IO_DEVICE
*RootBridgeDev
;
1673 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1676 MaxBus
= PCI_MAX_BUS
;
1680 // If this root bridge has been already enumerated, then return successfully
1682 if (GetRootBridgeByHandle (Controller
) != NULL
) {
1687 // Open pci root bridge io protocol
1689 Status
= gBS
->OpenProtocol (
1691 &gEfiPciRootBridgeIoProtocolGuid
,
1692 (VOID
**) &PciRootBridgeIo
,
1693 gPciBusDriverBinding
.DriverBindingHandle
,
1695 EFI_OPEN_PROTOCOL_BY_DRIVER
1697 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
1701 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1703 if (EFI_ERROR (Status
)) {
1707 while (PciGetBusRange (&Descriptors
, &MinBus
, &MaxBus
, NULL
) == EFI_SUCCESS
) {
1710 // Create a device node for root bridge device with a NULL host bridge controller handle
1712 RootBridgeDev
= CreateRootBridge (Controller
);
1714 if (RootBridgeDev
== NULL
) {
1720 // Record the root bridgeio protocol
1722 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
1724 Status
= PciPciDeviceInfoCollector (
1729 if (!EFI_ERROR (Status
)) {
1732 // Remove those PCI devices which are rejected when full enumeration
1734 RemoveRejectedPciDevices (RootBridgeDev
->Handle
, RootBridgeDev
);
1737 // Process option rom light
1739 ProcessOptionRomLight (RootBridgeDev
);
1742 // Determine attributes for all devices under this root bridge
1744 DetermineDeviceAttribute (RootBridgeDev
);
1747 // If successfully, insert the node into device pool
1749 InsertRootBridge (RootBridgeDev
);
1753 // If unsuccessly, destroy the entire node
1755 DestroyRootBridge (RootBridgeDev
);
1765 Get bus range from PCI resource descriptor list.
1767 @param Descriptors A pointer to the address space descriptor.
1768 @param MinBus The min bus returned.
1769 @param MaxBus The max bus returned.
1770 @param BusRange The bus range returned.
1772 @retval EFI_SUCCESS Successfully got bus range.
1773 @retval EFI_NOT_FOUND Can not find the specific bus.
1778 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptors
,
1781 OUT UINT16
*BusRange
1784 while ((*Descriptors
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1785 if ((*Descriptors
)->ResType
== ACPI_ADDRESS_SPACE_TYPE_BUS
) {
1786 if (MinBus
!= NULL
) {
1787 *MinBus
= (UINT16
) (*Descriptors
)->AddrRangeMin
;
1790 if (MaxBus
!= NULL
) {
1791 *MaxBus
= (UINT16
) (*Descriptors
)->AddrRangeMax
;
1794 if (BusRange
!= NULL
) {
1795 *BusRange
= (UINT16
) (*Descriptors
)->AddrLen
;
1804 return EFI_NOT_FOUND
;
1808 This routine can be used to start the root bridge.
1810 @param RootBridgeDev Pci device instance.
1812 @retval EFI_SUCCESS This device started.
1813 @retval other Failed to get PCI Root Bridge I/O protocol.
1817 StartManagingRootBridge (
1818 IN PCI_IO_DEVICE
*RootBridgeDev
1821 EFI_HANDLE RootBridgeHandle
;
1823 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1826 // Get the root bridge handle
1828 RootBridgeHandle
= RootBridgeDev
->Handle
;
1829 PciRootBridgeIo
= NULL
;
1832 // Get the pci root bridge io protocol
1834 Status
= gBS
->OpenProtocol (
1836 &gEfiPciRootBridgeIoProtocolGuid
,
1837 (VOID
**) &PciRootBridgeIo
,
1838 gPciBusDriverBinding
.DriverBindingHandle
,
1840 EFI_OPEN_PROTOCOL_BY_DRIVER
1843 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
1848 // Store the PciRootBridgeIo protocol into root bridge private data
1850 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
1857 This routine can be used to check whether a PCI device should be rejected when light enumeration.
1859 @param PciIoDevice Pci device instance.
1861 @retval TRUE This device should be rejected.
1862 @retval FALSE This device shouldn't be rejected.
1866 IsPciDeviceRejected (
1867 IN PCI_IO_DEVICE
*PciIoDevice
1877 // PPB should be skip!
1879 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
1883 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1885 // Only test base registers for P2C
1887 for (BarOffset
= 0x1C; BarOffset
<= 0x38; BarOffset
+= 2 * sizeof (UINT32
)) {
1889 Mask
= (BarOffset
< 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
1890 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
1891 if (EFI_ERROR (Status
)) {
1895 TestValue
= TestValue
& Mask
;
1896 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
1898 // The bar isn't programed, so it should be rejected
1907 for (BarOffset
= 0x14; BarOffset
<= 0x24; BarOffset
+= sizeof (UINT32
)) {
1911 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
1912 if (EFI_ERROR (Status
)) {
1916 if ((TestValue
& 0x01) != 0) {
1922 TestValue
= TestValue
& Mask
;
1923 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
1933 TestValue
= TestValue
& Mask
;
1935 if ((TestValue
& 0x07) == 0x04) {
1940 BarOffset
+= sizeof (UINT32
);
1941 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
1944 // Test its high 32-Bit BAR
1946 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
1947 if (TestValue
== OldValue
) {
1957 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
1968 Reset all bus number from specific bridge.
1970 @param Bridge Parent specific bridge.
1971 @param StartBusNumber Start bus number.
1975 ResetAllPpbBusNumber (
1976 IN PCI_IO_DEVICE
*Bridge
,
1977 IN UINT8 StartBusNumber
1987 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1989 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
1991 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
1992 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
1995 // Check to see whether a pci device is present
1997 Status
= PciDevicePresent (
2005 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
))) {
2008 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
2009 Status
= PciRootBridgeIoRead (
2017 SecondaryBus
= (UINT8
)(Register
>> 8);
2019 if (SecondaryBus
!= 0) {
2020 ResetAllPpbBusNumber (Bridge
, SecondaryBus
);
2024 // Reset register 18h, 19h, 1Ah on PCI Bridge
2026 Register
&= 0xFF000000;
2027 Status
= PciRootBridgeIoWrite (
2037 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
2039 // Skip sub functions, this is not a multi function device
2041 Func
= PCI_MAX_FUNC
;