3 Copyright (c) 2006 - 2009, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "PciEnumeratorSupport.h"
17 #include "PciCommand.h"
21 This routine is used to check whether the pci device is present.
23 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
24 @param Pci Output buffer for PCI device structure.
25 @param Bus PCI bus NO.
26 @param Device PCI device NO.
27 @param Func PCI Func NO.
29 @retval EFI_NOT_FOUND device not present.
30 @retval EFI_SUCCESS device is found.
34 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
45 // Create PCI address map in terms of Bus, Device and Func
47 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Func
, 0);
50 // Read the Vendor Id register
52 Status
= PciRootBridgeIoRead (
61 if (!EFI_ERROR (Status
) && (Pci
->Hdr
).VendorId
!= 0xffff) {
64 // Read the entire config header for the device
67 Status
= PciRootBridgeIoRead (
72 sizeof (PCI_TYPE00
) / sizeof (UINT32
),
83 Collect all the resource information under this root bridge
84 A database that records all the information about pci device subject to this
85 root bridge will then be created.
87 @param Bridge Parent bridge instance.
88 @param StartBusNumber Bus number of begining.
91 PciPciDeviceInfoCollector (
92 IN PCI_IO_DEVICE
*Bridge
,
101 PCI_IO_DEVICE
*PciIoDevice
;
102 EFI_PCI_IO_PROTOCOL
*PciIo
;
104 Status
= EFI_SUCCESS
;
107 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
109 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
112 // Check to see whether PCI device is present
115 Status
= PciDevicePresent (
116 Bridge
->PciRootBridgeIo
,
118 (UINT8
) StartBusNumber
,
123 if (!EFI_ERROR (Status
)) {
126 // Call back to host bridge function
128 PreprocessController (Bridge
, (UINT8
) StartBusNumber
, Device
, Func
, EfiPciBeforeResourceCollection
);
131 // Collect all the information about the PCI device discovered
133 Status
= PciSearchDevice (
136 (UINT8
) StartBusNumber
,
143 // Recursively scan PCI busses on the other side of PCI-PCI bridges
147 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
150 // If it is PPB, we need to get the secondary bus to continue the enumeration
152 PciIo
= &(PciIoDevice
->PciIo
);
154 Status
= PciIoRead (PciIo
, EfiPciIoWidthUint8
, 0x19, 1, &SecBus
);
156 if (EFI_ERROR (Status
)) {
161 // Get resource padding for PPB
163 GetResourcePaddingPpb (PciIoDevice
);
166 // Deep enumerate the next level bus
168 Status
= PciPciDeviceInfoCollector (
175 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
178 // Skip sub functions, this is not a multi function device
191 Seach required device and get PCI device info block
193 @param Bridge Parent bridge instance.
194 @param Pci Output of PCI device info block.
195 @param Bus PCI bus NO.
196 @param Device PCI device NO.
197 @param Func PCI func NO.
198 @param PciDevice output of searched PCI device instance.
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 private data for PCI device
310 @param Bridge Parent bridge instance.
311 @param Pci PCI bar block
312 @param Bus PCI device Bus NO.
313 @param Device PCI device DeviceNO.
314 @param Func PCI device's func NO.
316 @return new PCI device's private date structure.
320 IN PCI_IO_DEVICE
*Bridge
,
329 PCI_IO_DEVICE
*PciIoDevice
;
330 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
332 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
333 PciIoDevice
= CreatePciIoDevice (
341 if (PciIoDevice
== NULL
) {
346 // Create a device path for this PCI device and store it into its private data
348 CreatePciDevicePath (
354 // If it is a full enumeration, disconnect the device in advance
356 if (gFullEnumeration
) {
358 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
363 // Start to parse the bars
365 for (Offset
= 0x10, BarIndex
= 0; Offset
<= 0x24 && BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
366 Offset
= PciParseBar (PciIoDevice
, Offset
, BarIndex
);
373 Create private data for bridge device's PPB.
375 @param Bridge Parent bridge
376 @param Pci Pci device block
377 @param Bus Bridge device's bus NO.
378 @param Device Bridge device's device NO.
379 @param Func Bridge device's func NO.
381 @return bridge device instance.
385 IN PCI_IO_DEVICE
*Bridge
,
392 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
393 PCI_IO_DEVICE
*PciIoDevice
;
396 EFI_PCI_IO_PROTOCOL
*PciIo
;
399 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
400 PciIoDevice
= CreatePciIoDevice (
408 if (PciIoDevice
== NULL
) {
413 // Create a device path for this PCI device and store it into its private data
415 CreatePciDevicePath (
420 if (gFullEnumeration
) {
421 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
424 // Initalize the bridge control register
426 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED
);
431 // PPB can have two BARs
433 if (PciParseBar (PciIoDevice
, 0x10, PPB_BAR_0
) == 0x14) {
437 PciParseBar (PciIoDevice
, 0x14, PPB_BAR_1
);
440 PciIo
= &PciIoDevice
->PciIo
;
443 // Test whether it support 32 decode or not
445 PciIoRead (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
446 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
447 PciIoRead (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
448 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
451 if ((Value
& 0x01) != 0) {
452 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
454 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
458 Status
= BarExisted (
466 // test if it supports 64 memory or not
468 if (!EFI_ERROR (Status
)) {
470 Status
= BarExisted (
477 if (!EFI_ERROR (Status
)) {
478 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
479 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
481 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
486 // Memory 32 code is required for ppb
488 PciIoDevice
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
490 GetResourcePaddingPpb (PciIoDevice
);
496 Create private data for hotplug bridge device
498 @param Bridge Parent bridge instance
499 @param Pci PCI bar block
500 @param Bus hotplug bridge device's bus NO.
501 @param Device hotplug bridge device's device NO.
502 @param Func hotplug bridge device's Func NO.
504 @return hotplug bridge device instance.
508 IN PCI_IO_DEVICE
*Bridge
,
515 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
516 PCI_IO_DEVICE
*PciIoDevice
;
518 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
519 PciIoDevice
= CreatePciIoDevice (
527 if (PciIoDevice
== NULL
) {
532 // Create a device path for this PCI device and store it into its private data
534 CreatePciDevicePath (
539 if (gFullEnumeration
) {
540 PCI_DISABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
543 // Initalize the bridge control register
545 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED
);
549 // P2C only has one bar that is in 0x10
551 PciParseBar (PciIoDevice
, 0x10, P2C_BAR_0
);
554 // Read PciBar information from the bar register
556 GetBackPcCardBar (PciIoDevice
);
557 PciIoDevice
->Decodes
= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
|
558 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
|
559 EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
565 Create device path for pci deivce
567 @param ParentDevicePath Parent bridge's path.
568 @param PciIoDevice Pci device instance.
570 @return device path protocol instance for specific pci device.
572 EFI_DEVICE_PATH_PROTOCOL
*
573 CreatePciDevicePath (
574 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
575 IN PCI_IO_DEVICE
*PciIoDevice
579 PCI_DEVICE_PATH PciNode
;
582 // Create PCI device path
584 PciNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
585 PciNode
.Header
.SubType
= HW_PCI_DP
;
586 SetDevicePathNodeLength (&PciNode
.Header
, sizeof (PciNode
));
588 PciNode
.Device
= PciIoDevice
->DeviceNumber
;
589 PciNode
.Function
= PciIoDevice
->FunctionNumber
;
590 PciIoDevice
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, &PciNode
.Header
);
592 return PciIoDevice
->DevicePath
;
596 Check the bar is existed or not.
598 @param PciIoDevice - A pointer to the PCI_IO_DEVICE.
599 @param Offset - The offset.
600 @param BarLengthValue - The bar length value.
601 @param OriginalBarValue - The original bar value.
603 @retval EFI_NOT_FOUND - The bar don't exist.
604 @retval EFI_SUCCESS - The bar exist.
609 IN PCI_IO_DEVICE
*PciIoDevice
,
611 OUT UINT32
*BarLengthValue
,
612 OUT UINT32
*OriginalBarValue
616 EFI_PCI_IO_PROTOCOL
*PciIo
;
617 UINT32 OriginalValue
;
621 PciIo
= &PciIoDevice
->PciIo
;
624 // Preserve the original value
627 PciIoRead (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
630 // Raise TPL to high level to disable timer interrupt while the BAR is probed
632 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
634 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &gAllOne
);
635 PciIoRead (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &Value
);
638 // Write back the original value
640 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
643 // Restore TPL to its original level
645 gBS
->RestoreTPL (OldTpl
);
647 if (BarLengthValue
!= NULL
) {
648 *BarLengthValue
= Value
;
651 if (OriginalBarValue
!= NULL
) {
652 *OriginalBarValue
= OriginalValue
;
656 return EFI_NOT_FOUND
;
663 Test whether the device can support attributes
665 @param PciIoDevice Pci device instance.
666 @param Command Command register value.
667 @param BridgeControl Bridge control value for PPB or P2C.
668 @param OldCommand Old command register offset.
669 @param OldBridgeControl Old Bridge control value for PPB or P2C.
674 PciTestSupportedAttribute (
675 IN PCI_IO_DEVICE
*PciIoDevice
,
677 IN UINT16
*BridgeControl
,
678 IN UINT16
*OldCommand
,
679 IN UINT16
*OldBridgeControl
685 // Preserve the original value
687 PCI_READ_COMMAND_REGISTER (PciIoDevice
, OldCommand
);
690 // Raise TPL to high level to disable timer interrupt while the BAR is probed
692 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
694 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *Command
);
695 PCI_READ_COMMAND_REGISTER (PciIoDevice
, Command
);
698 // Write back the original value
700 PCI_SET_COMMAND_REGISTER (PciIoDevice
, *OldCommand
);
703 // Restore TPL to its original level
705 gBS
->RestoreTPL (OldTpl
);
707 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
710 // Preserve the original value
712 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, OldBridgeControl
);
715 // Raise TPL to high level to disable timer interrupt while the BAR is probed
717 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
719 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *BridgeControl
);
720 PCI_READ_BRIDGE_CONTROL_REGISTER (PciIoDevice
, BridgeControl
);
723 // Write back the original value
725 PCI_SET_BRIDGE_CONTROL_REGISTER (PciIoDevice
, *OldBridgeControl
);
728 // Restore TPL to its original level
730 gBS
->RestoreTPL (OldTpl
);
733 *OldBridgeControl
= 0;
741 Set the supported or current attributes of a PCI device
743 @param PciIoDevice - Structure pointer for PCI device.
744 @param Command - Command register value.
745 @param BridgeControl - Bridge control value for PPB or P2C.
746 @param Option - Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
750 PciSetDeviceAttribute (
751 IN PCI_IO_DEVICE
*PciIoDevice
,
753 IN UINT16 BridgeControl
,
761 if ((Command
& EFI_PCI_COMMAND_IO_SPACE
) != 0) {
762 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IO
;
765 if ((Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) != 0) {
766 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY
;
769 if ((Command
& EFI_PCI_COMMAND_BUS_MASTER
) != 0) {
770 Attributes
|= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
;
773 if ((Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) != 0) {
774 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
777 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
) != 0) {
778 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
781 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
) != 0) {
782 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
783 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
784 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
787 if ((BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
) != 0) {
788 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
;
789 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
;
792 if (Option
== EFI_SET_SUPPORTS
) {
794 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
795 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
|
796 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE
|
797 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
798 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
799 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
;
801 if ((Attributes
& EFI_PCI_IO_ATTRIBUTE_IO
) != 0) {
802 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
803 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
806 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
808 // For bridge, it should support IDE attributes
810 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
811 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
814 if (IS_PCI_IDE (&PciIoDevice
->Pci
)) {
815 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
816 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
819 if (IS_PCI_VGA (&PciIoDevice
->Pci
)) {
820 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
821 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
825 PciIoDevice
->Supports
= Attributes
;
826 PciIoDevice
->Supports
&= ( (PciIoDevice
->Parent
->Supports
) | \
827 EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
| \
828 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
);
831 PciIoDevice
->Attributes
= Attributes
;
838 Determine if the device can support Fast Back to Back attribute.
840 @param PciIoDevice Pci device instance.
841 @param StatusIndex Status register value.
844 GetFastBackToBackSupport (
845 IN PCI_IO_DEVICE
*PciIoDevice
,
849 EFI_PCI_IO_PROTOCOL
*PciIo
;
851 UINT32 StatusRegister
;
854 // Read the status register
856 PciIo
= &PciIoDevice
->PciIo
;
857 Status
= PciIoRead (PciIo
, EfiPciIoWidthUint16
, StatusIndex
, 1, &StatusRegister
);
858 if (EFI_ERROR (Status
)) {
859 return EFI_UNSUPPORTED
;
863 // Check the Fast B2B bit
865 if ((StatusRegister
& EFI_PCI_FAST_BACK_TO_BACK_CAPABLE
) != 0) {
868 return EFI_UNSUPPORTED
;
874 Process the option ROM for all the children of the specified parent PCI device.
875 It can only be used after the first full Option ROM process.
877 @param PciIoDevice Pci device instance.
879 @retval EFI_SUCCESS Success Operation.
882 ProcessOptionRomLight (
883 IN PCI_IO_DEVICE
*PciIoDevice
887 LIST_ENTRY
*CurrentLink
;
890 // For RootBridge, PPB , P2C, go recursively to traverse all its children
892 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
893 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
895 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
897 if (!IsListEmpty (&Temp
->ChildList
)) {
898 ProcessOptionRomLight (Temp
);
901 PciRomGetImageMapping (Temp
);
904 // The OpRom has already been processed in the first round
906 Temp
->AllOpRomProcessed
= TRUE
;
908 CurrentLink
= CurrentLink
->ForwardLink
;
915 Determine the related attributes of all devices under a Root Bridge
917 @param PciIoDevice PCI device instance.
921 DetermineDeviceAttribute (
922 IN PCI_IO_DEVICE
*PciIoDevice
926 UINT16 BridgeControl
;
928 UINT16 OldBridgeControl
;
929 BOOLEAN FastB2BSupport
;
933 EFI_PCI_IO_PROTOCOL *PciIo;
936 LIST_ENTRY
*CurrentLink
;
940 // For Root Bridge, just copy it by RootBridgeIo proctocol
941 // so as to keep consistent with the actual attribute
943 if (PciIoDevice
->Parent
== NULL
) {
944 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
945 PciIoDevice
->PciRootBridgeIo
,
946 &PciIoDevice
->Supports
,
947 &PciIoDevice
->Attributes
949 if (EFI_ERROR (Status
)) {
955 // Set the attributes to be checked for common PCI devices and PPB or P2C
956 // Since some devices only support part of them, it is better to set the
957 // attribute according to its command or bridge control register
959 Command
= EFI_PCI_COMMAND_IO_SPACE
|
960 EFI_PCI_COMMAND_MEMORY_SPACE
|
961 EFI_PCI_COMMAND_BUS_MASTER
|
962 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
964 BridgeControl
= EFI_PCI_BRIDGE_CONTROL_ISA
| EFI_PCI_BRIDGE_CONTROL_VGA
| EFI_PCI_BRIDGE_CONTROL_VGA_16
;
967 // Test whether the device can support attributes above
969 PciTestSupportedAttribute (PciIoDevice
, &Command
, &BridgeControl
, &OldCommand
, &OldBridgeControl
);
972 // Set the supported attributes for specified PCI device
974 PciSetDeviceAttribute (PciIoDevice
, Command
, BridgeControl
, EFI_SET_SUPPORTS
);
977 // Set the current attributes for specified PCI device
979 PciSetDeviceAttribute (PciIoDevice
, OldCommand
, OldBridgeControl
, EFI_SET_ATTRIBUTES
);
982 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
984 PCI_ENABLE_COMMAND_REGISTER (PciIoDevice
, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE
);
987 // Enable IDE native mode
990 if (IS_PCI_IDE(&PciIoDevice->Pci)) {
992 PciIo = &PciIoDevice->PciIo;
1003 // Set native mode if it can be supported
1005 IdePI |= (((IdePI & 0x0F) >> 1) & 0x05);
1019 FastB2BSupport
= TRUE
;
1022 // P2C can not support FB2B on the secondary side
1024 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1025 FastB2BSupport
= FALSE
;
1029 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1031 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1032 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1034 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1035 Status
= DetermineDeviceAttribute (Temp
);
1036 if (EFI_ERROR (Status
)) {
1040 // Detect Fast Bact to Bact support for the device under the bridge
1042 Status
= GetFastBackToBackSupport (Temp
, PCI_PRIMARY_STATUS_OFFSET
);
1043 if (FastB2BSupport
&& EFI_ERROR (Status
)) {
1044 FastB2BSupport
= FALSE
;
1047 CurrentLink
= CurrentLink
->ForwardLink
;
1050 // Set or clear Fast Back to Back bit for the whole bridge
1052 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
1054 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
1056 Status
= GetFastBackToBackSupport (PciIoDevice
, PCI_BRIDGE_STATUS_REGISTER_OFFSET
);
1058 if (EFI_ERROR (Status
) || (!FastB2BSupport
)) {
1059 FastB2BSupport
= FALSE
;
1060 PCI_DISABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1062 PCI_ENABLE_BRIDGE_CONTROL_REGISTER (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1066 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1067 while (CurrentLink
!= NULL
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1068 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1069 if (FastB2BSupport
) {
1070 PCI_ENABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1072 PCI_DISABLE_COMMAND_REGISTER (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1075 CurrentLink
= CurrentLink
->ForwardLink
;
1079 // End for IsListEmpty
1085 This routine is used to update the bar information for those incompatible PCI device
1087 @param PciIoDevice Pci device instance.
1088 @return EFI_UNSUPPORTED failed to update Pci Info.
1092 IN PCI_IO_DEVICE
*PciIoDevice
1099 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
1100 VOID
*Configuration
;
1101 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1103 Configuration
= NULL
;
1104 Status
= EFI_SUCCESS
;
1106 if (gEfiIncompatiblePciDeviceSupport
== NULL
) {
1108 // It can only be supported after the Incompatible PCI Device
1109 // Support Protocol has been installed
1111 Status
= gBS
->LocateProtocol (
1112 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
1114 (VOID
**) &gEfiIncompatiblePciDeviceSupport
1117 if (Status
== EFI_SUCCESS
) {
1119 // Check whether the device belongs to incompatible devices from protocol or not
1120 // If it is , then get its special requirement in the ACPI table
1122 Status
= gEfiIncompatiblePciDeviceSupport
->CheckDevice (
1123 gEfiIncompatiblePciDeviceSupport
,
1124 PciIoDevice
->Pci
.Hdr
.VendorId
,
1125 PciIoDevice
->Pci
.Hdr
.DeviceId
,
1126 PciIoDevice
->Pci
.Hdr
.RevisionID
,
1127 PciIoDevice
->Pci
.Device
.SubsystemVendorID
,
1128 PciIoDevice
->Pci
.Device
.SubsystemID
,
1134 if (EFI_ERROR (Status
)) {
1136 // Check whether the device belongs to incompatible devices from library or not
1137 // If it is , then get its special requirement in the ACPI table
1139 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACPI_RESOURCE_SUPPORT
) {
1140 PciDeviceInfo
.VendorID
= PciIoDevice
->Pci
.Hdr
.VendorId
;
1141 PciDeviceInfo
.DeviceID
= PciIoDevice
->Pci
.Hdr
.DeviceId
;
1142 PciDeviceInfo
.RevisionID
= PciIoDevice
->Pci
.Hdr
.RevisionID
;
1143 PciDeviceInfo
.SubsystemVendorID
= PciIoDevice
->Pci
.Device
.SubsystemVendorID
;
1144 PciDeviceInfo
.SubsystemID
= PciIoDevice
->Pci
.Device
.SubsystemID
;
1146 Status
= PciResourceUpdateCheck (&PciDeviceInfo
, &Configuration
);
1150 if (EFI_ERROR (Status
) || Configuration
== NULL
) {
1151 return EFI_UNSUPPORTED
;
1155 // Update PCI device information from the ACPI table
1157 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1159 while (Ptr
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1161 if (Ptr
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1163 // The format is not support
1168 BarIndex
= (UINTN
) Ptr
->AddrTranslationOffset
;
1169 BarEndIndex
= BarIndex
;
1172 // Update all the bars in the device
1174 if (BarIndex
== PCI_BAR_ALL
) {
1176 BarEndIndex
= PCI_MAX_BAR
- 1;
1179 if (BarIndex
>= PCI_MAX_BAR
) {
1184 for (; BarIndex
<= BarEndIndex
; BarIndex
++) {
1186 switch (Ptr
->ResType
) {
1187 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1190 // Make sure the bar is memory type
1192 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeMem
)) {
1197 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1200 // Make sure the bar is IO type
1202 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeIo
)) {
1211 // Update the new alignment for the device
1213 SetNewAlign (&(PciIoDevice
->PciBar
[BarIndex
].Alignment
), Ptr
->AddrRangeMax
);
1216 // Update the new length for the device
1218 if (Ptr
->AddrLen
!= PCI_BAR_NOCHANGE
) {
1219 PciIoDevice
->PciBar
[BarIndex
].Length
= Ptr
->AddrLen
;
1227 gBS
->FreePool (Configuration
);
1233 This routine will update the alignment with the new alignment
1235 @param Alignment old alignment.
1236 @param NewAlignment new alignment.
1241 IN UINT64
*Alignment
,
1242 IN UINT64 NewAlignment
1245 UINT64 OldAlignment
;
1249 // The new alignment is the same as the original,
1252 if (NewAlignment
== PCI_BAR_OLD_ALIGN
) {
1256 // Check the validity of the parameter
1258 if (NewAlignment
!= PCI_BAR_EVEN_ALIGN
&&
1259 NewAlignment
!= PCI_BAR_SQUAD_ALIGN
&&
1260 NewAlignment
!= PCI_BAR_DQUAD_ALIGN
) {
1261 *Alignment
= NewAlignment
;
1265 OldAlignment
= (*Alignment
) + 1;
1269 // Get the first non-zero hex value of the length
1271 while ((OldAlignment
& 0x0F) == 0x00) {
1272 OldAlignment
= RShiftU64 (OldAlignment
, 4);
1277 // Adjust the alignment to even, quad or double quad boundary
1279 if (NewAlignment
== PCI_BAR_EVEN_ALIGN
) {
1280 if ((OldAlignment
& 0x01) != 0) {
1281 OldAlignment
= OldAlignment
+ 2 - (OldAlignment
& 0x01);
1283 } else if (NewAlignment
== PCI_BAR_SQUAD_ALIGN
) {
1284 if ((OldAlignment
& 0x03) != 0) {
1285 OldAlignment
= OldAlignment
+ 4 - (OldAlignment
& 0x03);
1287 } else if (NewAlignment
== PCI_BAR_DQUAD_ALIGN
) {
1288 if ((OldAlignment
& 0x07) != 0) {
1289 OldAlignment
= OldAlignment
+ 8 - (OldAlignment
& 0x07);
1294 // Update the old value
1296 NewAlignment
= LShiftU64 (OldAlignment
, ShiftBit
) - 1;
1297 *Alignment
= NewAlignment
;
1305 @param PciIoDevice Pci device instance.
1306 @param Offset bar offset.
1307 @param BarIndex bar index.
1309 @return next bar offset.
1313 IN PCI_IO_DEVICE
*PciIoDevice
,
1319 UINT32 OriginalValue
;
1328 Status
= BarExisted (
1335 if (EFI_ERROR (Status
)) {
1336 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1337 PciIoDevice
->PciBar
[BarIndex
].Length
= 0;
1338 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1341 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1343 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1347 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1348 if ((Value
& 0x01) != 0) {
1354 if ((Value
& 0xFFFF0000) != 0) {
1358 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo32
;
1359 PciIoDevice
->PciBar
[BarIndex
].Length
= ((~(Value
& Mask
)) + 1);
1360 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1366 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo16
;
1367 PciIoDevice
->PciBar
[BarIndex
].Length
= 0x0000FFFF & ((~(Value
& Mask
)) + 1);
1368 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1372 // Workaround. Some platforms inplement IO bar with 0 length
1373 // Need to treat it as no-bar
1375 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1376 PciIoDevice
->PciBar
[BarIndex
].BarType
= (PCI_BAR_TYPE
) 0;
1379 PciIoDevice
->PciBar
[BarIndex
].Prefetchable
= FALSE
;
1380 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1386 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1388 switch (Value
& 0x07) {
1391 //memory space; anywhere in 32 bit address space
1394 if ((Value
& 0x08) != 0) {
1395 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1397 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1400 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1401 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1406 // memory space; anywhere in 64 bit address space
1409 if ((Value
& 0x08) != 0) {
1410 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1412 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1416 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1417 // is regarded as an extension for the first bar. As a result
1418 // the sizing will be conducted on combined 64 bit value
1419 // Here just store the masked first 32bit value for future size
1422 PciIoDevice
->PciBar
[BarIndex
].Length
= Value
& Mask
;
1423 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1426 // Increment the offset to point to next DWORD
1430 Status
= BarExisted (
1437 if (EFI_ERROR (Status
)) {
1442 // Fix the length to support some spefic 64 bit BAR
1446 for (Data
= Value
; Data
!= 0; Data
>>= 1) {
1449 Value
|= ((UINT32
)(-1) << Index
);
1452 // Calculate the size of 64bit bar
1454 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1456 PciIoDevice
->PciBar
[BarIndex
].Length
= PciIoDevice
->PciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1457 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(PciIoDevice
->PciBar
[BarIndex
].Length
)) + 1;
1458 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1466 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1467 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1468 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1475 // Check the length again so as to keep compatible with some special bars
1477 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1478 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1479 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1480 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1484 // Increment number of bar
1490 This routine is used to initialize the bar of a PCI device.
1491 It can be called typically when a device is going to be rejected.
1493 @param PciIoDevice Pci device instance.
1496 InitializePciDevice (
1497 IN PCI_IO_DEVICE
*PciIoDevice
1500 EFI_PCI_IO_PROTOCOL
*PciIo
;
1503 PciIo
= &(PciIoDevice
->PciIo
);
1506 // Put all the resource apertures
1507 // Resource base is set to all ones so as to indicate its resource
1508 // has not been alloacted
1510 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
1511 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllOne
);
1518 Init PPB for bridge device
1520 @param PciIoDevice Pci device instance.
1524 IN PCI_IO_DEVICE
*PciIoDevice
1527 EFI_PCI_IO_PROTOCOL
*PciIo
;
1529 PciIo
= &(PciIoDevice
->PciIo
);
1532 // Put all the resource apertures including IO16
1533 // Io32, pMem32, pMem64 to quiescent state
1534 // Resource base all ones, Resource limit all zeros
1536 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
1537 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1D, 1, &gAllZero
);
1539 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x20, 1, &gAllOne
);
1540 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x22, 1, &gAllZero
);
1542 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x24, 1, &gAllOne
);
1543 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x26, 1, &gAllZero
);
1545 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllOne
);
1546 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x2C, 1, &gAllZero
);
1549 // don't support use io32 as for now
1551 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x30, 1, &gAllOne
);
1552 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x32, 1, &gAllZero
);
1555 // Force Interrupt line to zero for cards that come up randomly
1557 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1563 Init private data for Hotplug bridge device
1565 @param PciIoDevice hotplug bridge device.
1569 IN PCI_IO_DEVICE
*PciIoDevice
1572 EFI_PCI_IO_PROTOCOL
*PciIo
;
1574 PciIo
= &(PciIoDevice
->PciIo
);
1577 // Put all the resource apertures including IO16
1578 // Io32, pMem32, pMem64 to quiescent state(
1579 // Resource base all ones, Resource limit all zeros
1581 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x1c, 1, &gAllOne
);
1582 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x20, 1, &gAllZero
);
1584 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x24, 1, &gAllOne
);
1585 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllZero
);
1587 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x2c, 1, &gAllOne
);
1588 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x30, 1, &gAllZero
);
1590 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x34, 1, &gAllOne
);
1591 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x38, 1, &gAllZero
);
1594 // Force Interrupt line to zero for cards that come up randomly
1596 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1601 Create and initiliaze general PCI I/O device instance for
1602 PCI device/bridge device/hotplug bridge device.
1604 @param PciRootBridgeIo Pointer to instance of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1605 @param Pci Pci bar block.
1606 @param Bus device Bus NO.
1607 @param Device device device NO.
1608 @param Func device func NO.
1610 @return instance of PCI device.
1614 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
1623 PCI_IO_DEVICE
*PciIoDevice
;
1627 Status
= gBS
->AllocatePool (
1628 EfiBootServicesData
,
1629 sizeof (PCI_IO_DEVICE
),
1630 (VOID
**) &PciIoDevice
1633 if (EFI_ERROR (Status
)) {
1637 ZeroMem (PciIoDevice
, sizeof (PCI_IO_DEVICE
));
1639 PciIoDevice
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
1640 PciIoDevice
->Handle
= NULL
;
1641 PciIoDevice
->PciRootBridgeIo
= PciRootBridgeIo
;
1642 PciIoDevice
->DevicePath
= NULL
;
1643 PciIoDevice
->BusNumber
= Bus
;
1644 PciIoDevice
->DeviceNumber
= Device
;
1645 PciIoDevice
->FunctionNumber
= Func
;
1646 PciIoDevice
->Decodes
= 0;
1647 if (gFullEnumeration
) {
1648 PciIoDevice
->Allocated
= FALSE
;
1650 PciIoDevice
->Allocated
= TRUE
;
1653 PciIoDevice
->Registered
= FALSE
;
1654 PciIoDevice
->Attributes
= 0;
1655 PciIoDevice
->Supports
= 0;
1656 PciIoDevice
->BusOverride
= FALSE
;
1657 PciIoDevice
->AllOpRomProcessed
= FALSE
;
1659 PciIoDevice
->IsPciExp
= FALSE
;
1661 CopyMem (&(PciIoDevice
->Pci
), Pci
, sizeof (PCI_TYPE01
));
1664 // Initialize the PCI I/O instance structure
1667 InitializePciIoInstance (PciIoDevice
);
1668 InitializePciDriverOverrideInstance (PciIoDevice
);
1669 InitializePciLoadFile2 (PciIoDevice
);
1673 // Initialize the reserved resource list
1675 InitializeListHead (&PciIoDevice
->ReservedResourceList
);
1678 // Initialize the driver list
1680 InitializeListHead (&PciIoDevice
->OptionRomDriverList
);
1683 // Initialize the child list
1685 InitializeListHead (&PciIoDevice
->ChildList
);
1691 This routine is used to enumerate entire pci bus system
1693 It is only called on the second start on the same Root Bridge.
1695 @param Controller Parent bridge handler.
1697 @return status of operation.
1700 PciEnumeratorLight (
1701 IN EFI_HANDLE Controller
1706 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1707 PCI_IO_DEVICE
*RootBridgeDev
;
1710 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1713 MaxBus
= PCI_MAX_BUS
;
1717 // If this root bridge has been already enumerated, then return successfully
1719 if (GetRootBridgeByHandle (Controller
) != NULL
) {
1724 // Open pci root bridge io protocol
1726 Status
= gBS
->OpenProtocol (
1728 &gEfiPciRootBridgeIoProtocolGuid
,
1729 (VOID
**) &PciRootBridgeIo
,
1730 gPciBusDriverBinding
.DriverBindingHandle
,
1732 EFI_OPEN_PROTOCOL_BY_DRIVER
1734 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
1738 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1740 if (EFI_ERROR (Status
)) {
1744 while (PciGetBusRange (&Descriptors
, &MinBus
, &MaxBus
, NULL
) == EFI_SUCCESS
) {
1747 // Create a device node for root bridge device with a NULL host bridge controller handle
1749 RootBridgeDev
= CreateRootBridge (Controller
);
1751 if (RootBridgeDev
== NULL
) {
1757 // Record the root bridge io protocol
1759 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
1761 Status
= PciPciDeviceInfoCollector (
1766 if (!EFI_ERROR (Status
)) {
1769 // Remove those PCI devices which are rejected when full enumeration
1771 RemoveRejectedPciDevices (RootBridgeDev
->Handle
, RootBridgeDev
);
1774 // Process option rom light
1776 ProcessOptionRomLight (RootBridgeDev
);
1779 // Determine attributes for all devices under this root bridge
1781 DetermineDeviceAttribute (RootBridgeDev
);
1784 // If successfully, insert the node into device pool
1786 InsertRootBridge (RootBridgeDev
);
1790 // If unsuccessly, destroy the entire node
1792 DestroyRootBridge (RootBridgeDev
);
1804 @param Descriptors A pointer to the address space descriptor.
1805 @param MinBus The min bus.
1806 @param MaxBus The max bus.
1807 @param BusRange The bus range.
1809 @retval EFI_SUCCESS Success operation.
1810 @retval EFI_NOT_FOUND can not find the specific bus.
1814 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptors
,
1817 OUT UINT16
*BusRange
1821 while ((*Descriptors
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1822 if ((*Descriptors
)->ResType
== ACPI_ADDRESS_SPACE_TYPE_BUS
) {
1823 if (MinBus
!= NULL
) {
1824 *MinBus
= (UINT16
) (*Descriptors
)->AddrRangeMin
;
1827 if (MaxBus
!= NULL
) {
1828 *MaxBus
= (UINT16
) (*Descriptors
)->AddrRangeMax
;
1831 if (BusRange
!= NULL
) {
1832 *BusRange
= (UINT16
) (*Descriptors
)->AddrLen
;
1841 return EFI_NOT_FOUND
;
1845 This routine can be used to start the root bridge.
1847 @param RootBridgeDev Pci device instance.
1849 @retval EFI_SUCCESS This device started.
1853 StartManagingRootBridge (
1854 IN PCI_IO_DEVICE
*RootBridgeDev
1857 EFI_HANDLE RootBridgeHandle
;
1859 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1862 // Get the root bridge handle
1864 RootBridgeHandle
= RootBridgeDev
->Handle
;
1865 PciRootBridgeIo
= NULL
;
1868 // Get the pci root bridge io protocol
1870 Status
= gBS
->OpenProtocol (
1872 &gEfiPciRootBridgeIoProtocolGuid
,
1873 (VOID
**) &PciRootBridgeIo
,
1874 gPciBusDriverBinding
.DriverBindingHandle
,
1876 EFI_OPEN_PROTOCOL_BY_DRIVER
1879 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
1884 // Store the PciRootBridgeIo protocol into root bridge private data
1886 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
1893 This routine can be used to check whether a PCI device should be rejected when light enumeration
1895 @param PciIoDevice Pci device instance.
1897 @retval TRUE This device should be rejected.
1898 @retval FALSE This device shouldn't be rejected.
1902 IsPciDeviceRejected (
1903 IN PCI_IO_DEVICE
*PciIoDevice
1913 // PPB should be skip!
1915 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
1919 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1921 // Only test base registers for P2C
1923 for (BarOffset
= 0x1C; BarOffset
<= 0x38; BarOffset
+= 2 * sizeof (UINT32
)) {
1925 Mask
= (BarOffset
< 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
1926 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
1927 if (EFI_ERROR (Status
)) {
1931 TestValue
= TestValue
& Mask
;
1932 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
1934 // The bar isn't programed, so it should be rejected
1943 for (BarOffset
= 0x14; BarOffset
<= 0x24; BarOffset
+= sizeof (UINT32
)) {
1947 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
1948 if (EFI_ERROR (Status
)) {
1952 if ((TestValue
& 0x01) != 0) {
1959 TestValue
= TestValue
& Mask
;
1960 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
1971 TestValue
= TestValue
& Mask
;
1973 if ((TestValue
& 0x07) == 0x04) {
1978 BarOffset
+= sizeof (UINT32
);
1979 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
1982 // Test its high 32-Bit BAR
1985 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
1986 if (TestValue
== OldValue
) {
1996 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2007 Reset and all bus number from specific bridge.
2009 @param Bridge Parent specific bridge.
2010 @param StartBusNumber start bus number.
2013 ResetAllPpbBusNumber (
2014 IN PCI_IO_DEVICE
*Bridge
,
2015 IN UINT8 StartBusNumber
2025 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2027 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
2029 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
2030 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
2033 // Check to see whether a pci device is present
2035 Status
= PciDevicePresent (
2043 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
))) {
2046 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
2047 Status
= PciRootBridgeIoRead (
2055 SecondaryBus
= (UINT8
)(Register
>> 8);
2057 if (SecondaryBus
!= 0) {
2058 ResetAllPpbBusNumber (Bridge
, SecondaryBus
);
2062 // Reset register 18h, 19h, 1Ah on PCI Bridge
2064 Register
&= 0xFF000000;
2065 Status
= PciRootBridgeIoWrite (
2075 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
2077 // Skip sub functions, this is not a multi function device
2079 Func
= PCI_MAX_FUNC
;