3 Copyright (c) 2006, 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"
22 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
32 This routine is used to check whether the pci device is present
41 // TODO: PciRootBridgeIo - add argument and description to function comment
42 // TODO: Pci - add argument and description to function comment
43 // TODO: Bus - add argument and description to function comment
44 // TODO: Device - add argument and description to function comment
45 // TODO: Func - add argument and description to function comment
46 // TODO: EFI_SUCCESS - add return value to function comment
47 // TODO: EFI_NOT_FOUND - add return value to function comment
53 // Create PCI address map in terms of Bus, Device and Func
55 Address
= EFI_PCI_ADDRESS (Bus
, Device
, Func
, 0);
58 // Read the Vendor Id register
60 Status
= PciRootBridgeIoRead (
69 if (!EFI_ERROR (Status
) && (Pci
->Hdr
).VendorId
!= 0xffff) {
72 // Read the entire config header for the device
75 Status
= PciRootBridgeIoRead (
80 sizeof (PCI_TYPE00
) / sizeof (UINT32
),
91 PciPciDeviceInfoCollector (
92 IN PCI_IO_DEVICE
*Bridge
,
106 // TODO: Bridge - add argument and description to function comment
107 // TODO: StartBusNumber - add argument and description to function comment
108 // TODO: EFI_SUCCESS - add return value to function comment
115 PCI_IO_DEVICE
*PciIoDevice
;
116 EFI_PCI_IO_PROTOCOL
*PciIo
;
118 Status
= EFI_SUCCESS
;
121 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
123 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
126 // Check to see whether PCI device is present
129 Status
= PciDevicePresent (
130 Bridge
->PciRootBridgeIo
,
132 (UINT8
) StartBusNumber
,
137 if (!EFI_ERROR (Status
)) {
140 // Call back to host bridge function
142 PreprocessController (Bridge
, (UINT8
) StartBusNumber
, Device
, Func
, EfiPciBeforeResourceCollection
);
145 // Collect all the information about the PCI device discovered
147 Status
= PciSearchDevice (
150 (UINT8
) StartBusNumber
,
157 // Recursively scan PCI busses on the other side of PCI-PCI bridges
161 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
) || IS_CARDBUS_BRIDGE (&Pci
))) {
164 // If it is PPB, we need to get the secondary bus to continue the enumeration
166 PciIo
= &(PciIoDevice
->PciIo
);
168 Status
= PciIoRead (PciIo
, EfiPciIoWidthUint8
, 0x19, 1, &SecBus
);
170 if (EFI_ERROR (Status
)) {
175 // Get resource padding for PPB
177 GetResourcePaddingPpb (PciIoDevice
);
180 // Deep enumerate the next level bus
182 Status
= PciPciDeviceInfoCollector (
189 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
192 // Skip sub functions, this is not a multi function device
206 IN PCI_IO_DEVICE
*Bridge
,
211 OUT PCI_IO_DEVICE
**PciDevice
217 Search required device.
221 Bridge - A pointer to the PCI_IO_DEVICE.
222 Pci - A pointer to the PCI_TYPE00.
224 Device - Device number.
225 Func - Function number.
226 PciDevice - The Required pci device.
233 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
234 // TODO: EFI_OUT_OF_RESOURCES - add return value to function comment
235 // TODO: EFI_SUCCESS - add return value to function comment
237 PCI_IO_DEVICE
*PciIoDevice
;
241 if (!IS_PCI_BRIDGE (Pci
)) {
243 if (IS_CARDBUS_BRIDGE (Pci
)) {
244 PciIoDevice
= GatherP2CInfo (
251 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
252 InitializeP2C (PciIoDevice
);
257 // Create private data for Pci Device
259 PciIoDevice
= GatherDeviceInfo (
272 // Create private data for PPB
274 PciIoDevice
= GatherPpbInfo (
283 // Special initialization for PPB including making the PPB quiet
285 if ((PciIoDevice
!= NULL
) && gFullEnumeration
) {
286 InitializePpb (PciIoDevice
);
291 return EFI_OUT_OF_RESOURCES
;
295 // Update the bar information for this PCI device so as to support some specific device
297 UpdatePciInfo (PciIoDevice
);
299 if (PciIoDevice
->DevicePath
== NULL
) {
300 return EFI_OUT_OF_RESOURCES
;
304 // Detect this function has option rom
306 if (gFullEnumeration
) {
308 if (!IS_CARDBUS_BRIDGE (Pci
)) {
310 GetOpRomInfo (PciIoDevice
);
314 ResetPowerManagementFeature (PciIoDevice
);
319 // Insert it into a global tree for future reference
321 InsertPciDevice (Bridge
, PciIoDevice
);
324 // Determine PCI device attributes
327 if (PciDevice
!= NULL
) {
328 *PciDevice
= PciIoDevice
;
336 IN PCI_IO_DEVICE
*Bridge
,
353 // TODO: Bridge - add argument and description to function comment
354 // TODO: Pci - add argument and description to function comment
355 // TODO: Bus - add argument and description to function comment
356 // TODO: Device - add argument and description to function comment
357 // TODO: Func - add argument and description to function comment
361 PCI_IO_DEVICE
*PciIoDevice
;
362 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
364 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
365 PciIoDevice
= CreatePciIoDevice (
378 // Create a device path for this PCI device and store it into its private data
380 CreatePciDevicePath (
386 // If it is a full enumeration, disconnect the device in advance
388 if (gFullEnumeration
) {
390 PciDisableCommandRegister (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
395 // Start to parse the bars
397 for (Offset
= 0x10, BarIndex
= 0; Offset
<= 0x24; BarIndex
++) {
398 Offset
= PciParseBar (PciIoDevice
, Offset
, BarIndex
);
406 IN PCI_IO_DEVICE
*Bridge
,
423 // TODO: Bridge - add argument and description to function comment
424 // TODO: Pci - add argument and description to function comment
425 // TODO: Bus - add argument and description to function comment
426 // TODO: Device - add argument and description to function comment
427 // TODO: Func - add argument and description to function comment
429 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
430 PCI_IO_DEVICE
*PciIoDevice
;
433 EFI_PCI_IO_PROTOCOL
*PciIo
;
436 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
437 PciIoDevice
= CreatePciIoDevice (
450 // Create a device path for this PCI device and store it into its private data
452 CreatePciDevicePath (
457 if (gFullEnumeration
) {
458 PciDisableCommandRegister (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
461 // Initalize the bridge control register
463 PciDisableBridgeControlRegister (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_BITS_OWNED
);
468 // PPB can have two BARs
470 if (PciParseBar (PciIoDevice
, 0x10, PPB_BAR_0
) == 0x14) {
474 PciParseBar (PciIoDevice
, 0x14, PPB_BAR_1
);
477 PciIo
= &PciIoDevice
->PciIo
;
480 // Test whether it support 32 decode or not
482 PciIoRead (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
483 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
484 PciIoRead (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Value
);
485 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &Temp
);
489 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
491 PciIoDevice
->Decodes
|= EFI_BRIDGE_IO16_DECODE_SUPPORTED
;
494 // changed to support En1K for IO Bridge Device
496 if( (Value
& 0x0c) == 0x0c ){
497 PciIoDevice
->Decodes
|= EFI_BRIDGE_IOEN1K_DECODE_SUPPORTED
;
501 Status
= BarExisted (
509 // test if it supports 64 memory or not
511 if (!EFI_ERROR (Status
)) {
513 Status
= BarExisted (
520 if (!EFI_ERROR (Status
)) {
521 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
522 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED
;
524 PciIoDevice
->Decodes
|= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
;
529 // Memory 32 code is required for ppb
531 PciIoDevice
->Decodes
|= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
;
533 GetResourcePaddingPpb (PciIoDevice
);
540 IN PCI_IO_DEVICE
*Bridge
,
557 // TODO: Bridge - add argument and description to function comment
558 // TODO: Pci - add argument and description to function comment
559 // TODO: Bus - add argument and description to function comment
560 // TODO: Device - add argument and description to function comment
561 // TODO: Func - add argument and description to function comment
563 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
564 PCI_IO_DEVICE
*PciIoDevice
;
566 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
567 PciIoDevice
= CreatePciIoDevice (
580 // Create a device path for this PCI device and store it into its private data
582 CreatePciDevicePath (
587 if (gFullEnumeration
) {
588 PciDisableCommandRegister (PciIoDevice
, EFI_PCI_COMMAND_BITS_OWNED
);
591 // Initalize the bridge control register
593 PciDisableBridgeControlRegister (PciIoDevice
, EFI_PCCARD_BRIDGE_CONTROL_BITS_OWNED
);
597 // P2C only has one bar that is in 0x10
599 PciParseBar (PciIoDevice
, 0x10, P2C_BAR_0
);
602 // Read PciBar information from the bar register
604 GetBackPcCardBar (PciIoDevice
);
605 PciIoDevice
->Decodes
= EFI_BRIDGE_MEM32_DECODE_SUPPORTED
|
606 EFI_BRIDGE_PMEM32_DECODE_SUPPORTED
|
607 EFI_BRIDGE_IO32_DECODE_SUPPORTED
;
612 EFI_DEVICE_PATH_PROTOCOL
*
613 CreatePciDevicePath (
614 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
615 IN PCI_IO_DEVICE
*PciIoDevice
628 // TODO: ParentDevicePath - add argument and description to function comment
629 // TODO: PciIoDevice - add argument and description to function comment
632 PCI_DEVICE_PATH PciNode
;
635 // Create PCI device path
637 PciNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
638 PciNode
.Header
.SubType
= HW_PCI_DP
;
639 SetDevicePathNodeLength (&PciNode
.Header
, sizeof (PciNode
));
641 PciNode
.Device
= PciIoDevice
->DeviceNumber
;
642 PciNode
.Function
= PciIoDevice
->FunctionNumber
;
643 PciIoDevice
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, &PciNode
.Header
);
645 return PciIoDevice
->DevicePath
;
650 IN PCI_IO_DEVICE
*PciIoDevice
,
652 OUT UINT32
*BarLengthValue
,
653 OUT UINT32
*OriginalBarValue
659 Check the bar is existed or not.
663 PciIoDevice - A pointer to the PCI_IO_DEVICE.
665 BarLengthValue - The bar length value.
666 OriginalBarValue - The original bar value.
670 EFI_NOT_FOUND - The bar don't exist.
671 EFI_SUCCESS - The bar exist.
675 EFI_PCI_IO_PROTOCOL
*PciIo
;
676 UINT32 OriginalValue
;
680 PciIo
= &PciIoDevice
->PciIo
;
683 // Preserve the original value
686 PciIoRead (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
689 // Raise TPL to high level to disable timer interrupt while the BAR is probed
691 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
693 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &gAllOne
);
694 PciIoRead (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &Value
);
697 // Write back the original value
699 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, (UINT8
) Offset
, 1, &OriginalValue
);
702 // Restore TPL to its original level
704 gBS
->RestoreTPL (OldTpl
);
706 if (BarLengthValue
!= NULL
) {
707 *BarLengthValue
= Value
;
710 if (OriginalBarValue
!= NULL
) {
711 *OriginalBarValue
= OriginalValue
;
715 return EFI_NOT_FOUND
;
722 PciTestSupportedAttribute (
723 IN PCI_IO_DEVICE
*PciIoDevice
,
725 IN UINT16
*BridgeControl
,
726 IN UINT16
*OldCommand
,
727 IN UINT16
*OldBridgeControl
740 // TODO: PciIoDevice - add argument and description to function comment
741 // TODO: Command - add argument and description to function comment
742 // TODO: BridgeControl - add argument and description to function comment
743 // TODO: OldCommand - add argument and description to function comment
744 // TODO: OldBridgeControl - add argument and description to function comment
745 // TODO: EFI_SUCCESS - add return value to function comment
750 // Preserve the original value
752 PciReadCommandRegister (PciIoDevice
, OldCommand
);
755 // Raise TPL to high level to disable timer interrupt while the BAR is probed
757 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
759 PciSetCommandRegister (PciIoDevice
, *Command
);
760 PciReadCommandRegister (PciIoDevice
, Command
);
763 // Write back the original value
765 PciSetCommandRegister (PciIoDevice
, *OldCommand
);
768 // Restore TPL to its original level
770 gBS
->RestoreTPL (OldTpl
);
772 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
775 // Preserve the original value
777 PciReadBridgeControlRegister (PciIoDevice
, OldBridgeControl
);
780 // Raise TPL to high level to disable timer interrupt while the BAR is probed
782 OldTpl
= gBS
->RaiseTPL (TPL_HIGH_LEVEL
);
784 PciSetBridgeControlRegister (PciIoDevice
, *BridgeControl
);
785 PciReadBridgeControlRegister (PciIoDevice
, BridgeControl
);
788 // Write back the original value
790 PciSetBridgeControlRegister (PciIoDevice
, *OldBridgeControl
);
793 // Restore TPL to its original level
795 gBS
->RestoreTPL (OldTpl
);
798 *OldBridgeControl
= 0;
806 PciSetDeviceAttribute (
807 IN PCI_IO_DEVICE
*PciIoDevice
,
809 IN UINT16 BridgeControl
,
815 Set the supported or current attributes of a PCI device
818 PciIoDevice - Structure pointer for PCI device.
819 Command - Command register value.
820 BridgeControl - Bridge control value for PPB or P2C.
821 Option - Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES.
838 EFI_SUCCESS Always success
847 if (Command
& EFI_PCI_COMMAND_IO_SPACE
) {
848 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IO
;
851 if (Command
& EFI_PCI_COMMAND_MEMORY_SPACE
) {
852 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY
;
855 if (Command
& EFI_PCI_COMMAND_BUS_MASTER
) {
856 Attributes
|= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
;
859 if (Command
& EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
) {
860 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
863 if (BridgeControl
& EFI_PCI_BRIDGE_CONTROL_ISA
) {
864 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
867 if (BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA
) {
868 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
869 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
870 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO
;
873 if (BridgeControl
& EFI_PCI_BRIDGE_CONTROL_VGA_16
) {
874 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
;
875 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16
;
878 if (Option
== EFI_SET_SUPPORTS
) {
880 Attributes
|= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE
|
881 EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED
|
882 EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE
|
883 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE
|
884 EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM
|
885 EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE
;
887 if (Attributes
& EFI_PCI_IO_ATTRIBUTE_IO
) {
888 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO
;
889 Attributes
|= EFI_PCI_IO_ATTRIBUTE_ISA_IO
;
892 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
) || IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
894 // For bridge, it should support IDE attributes
896 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
897 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
900 if (IS_PCI_IDE (&PciIoDevice
->Pci
)) {
901 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO
;
902 Attributes
|= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO
;
905 if (IS_PCI_VGA (&PciIoDevice
->Pci
)) {
906 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
;
907 Attributes
|= EFI_PCI_IO_ATTRIBUTE_VGA_IO
;
911 PciIoDevice
->Supports
= Attributes
;
912 PciIoDevice
->Supports
&= ( (PciIoDevice
->Parent
->Supports
) | \
913 EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
| \
914 EFI_PCI_IO_ATTRIBUTE_BUS_MASTER
);
917 PciIoDevice
->Attributes
= Attributes
;
924 GetFastBackToBackSupport (
925 IN PCI_IO_DEVICE
*PciIoDevice
,
932 Determine if the device can support Fast Back to Back attribute
941 // TODO: PciIoDevice - add argument and description to function comment
942 // TODO: StatusIndex - add argument and description to function comment
943 // TODO: EFI_UNSUPPORTED - add return value to function comment
944 // TODO: EFI_SUCCESS - add return value to function comment
945 // TODO: EFI_UNSUPPORTED - add return value to function comment
947 EFI_PCI_IO_PROTOCOL
*PciIo
;
949 UINT32 StatusRegister
;
952 // Read the status register
954 PciIo
= &PciIoDevice
->PciIo
;
955 Status
= PciIoRead (PciIo
, EfiPciIoWidthUint16
, StatusIndex
, 1, &StatusRegister
);
956 if (EFI_ERROR (Status
)) {
957 return EFI_UNSUPPORTED
;
961 // Check the Fast B2B bit
963 if (StatusRegister
& EFI_PCI_FAST_BACK_TO_BACK_CAPABLE
) {
966 return EFI_UNSUPPORTED
;
973 ProcessOptionRomLight (
974 IN PCI_IO_DEVICE
*PciIoDevice
980 Process the option ROM for all the children of the specified parent PCI device.
981 It can only be used after the first full Option ROM process.
990 // TODO: PciIoDevice - add argument and description to function comment
991 // TODO: EFI_SUCCESS - add return value to function comment
994 LIST_ENTRY
*CurrentLink
;
997 // For RootBridge, PPB , P2C, go recursively to traverse all its children
999 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1000 while (CurrentLink
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1002 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1004 if (!IsListEmpty (&Temp
->ChildList
)) {
1005 ProcessOptionRomLight (Temp
);
1008 PciRomGetImageMapping (Temp
);
1011 // The OpRom has already been processed in the first round
1013 Temp
->AllOpRomProcessed
= TRUE
;
1015 CurrentLink
= CurrentLink
->ForwardLink
;
1022 DetermineDeviceAttribute (
1023 IN PCI_IO_DEVICE
*PciIoDevice
1027 Routine Description:
1029 Determine the related attributes of all devices under a Root Bridge
1038 // TODO: PciIoDevice - add argument and description to function comment
1039 // TODO: EFI_SUCCESS - add return value to function comment
1042 UINT16 BridgeControl
;
1044 UINT16 OldBridgeControl
;
1045 BOOLEAN FastB2BSupport
;
1049 EFI_PCI_IO_PROTOCOL *PciIo;
1051 PCI_IO_DEVICE
*Temp
;
1052 LIST_ENTRY
*CurrentLink
;
1056 // For Root Bridge, just copy it by RootBridgeIo proctocol
1057 // so as to keep consistent with the actual attribute
1059 if (!PciIoDevice
->Parent
) {
1060 Status
= PciIoDevice
->PciRootBridgeIo
->GetAttributes (
1061 PciIoDevice
->PciRootBridgeIo
,
1062 &PciIoDevice
->Supports
,
1063 &PciIoDevice
->Attributes
1065 if (EFI_ERROR (Status
)) {
1071 // Set the attributes to be checked for common PCI devices and PPB or P2C
1072 // Since some devices only support part of them, it is better to set the
1073 // attribute according to its command or bridge control register
1075 Command
= EFI_PCI_COMMAND_IO_SPACE
|
1076 EFI_PCI_COMMAND_MEMORY_SPACE
|
1077 EFI_PCI_COMMAND_BUS_MASTER
|
1078 EFI_PCI_COMMAND_VGA_PALETTE_SNOOP
;
1080 BridgeControl
= EFI_PCI_BRIDGE_CONTROL_ISA
| EFI_PCI_BRIDGE_CONTROL_VGA
| EFI_PCI_BRIDGE_CONTROL_VGA_16
;
1083 // Test whether the device can support attributes above
1085 PciTestSupportedAttribute (PciIoDevice
, &Command
, &BridgeControl
, &OldCommand
, &OldBridgeControl
);
1088 // Set the supported attributes for specified PCI device
1090 PciSetDeviceAttribute (PciIoDevice
, Command
, BridgeControl
, EFI_SET_SUPPORTS
);
1093 // Set the current attributes for specified PCI device
1095 PciSetDeviceAttribute (PciIoDevice
, OldCommand
, OldBridgeControl
, EFI_SET_ATTRIBUTES
);
1098 // Enable other supported attributes but not defined in PCI_IO_PROTOCOL
1100 PciEnableCommandRegister (PciIoDevice
, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE
);
1103 // Enable IDE native mode
1106 if (IS_PCI_IDE(&PciIoDevice->Pci)) {
1108 PciIo = &PciIoDevice->PciIo;
1119 // Set native mode if it can be supported
1121 IdePI |= (((IdePI & 0x0F) >> 1) & 0x05);
1135 FastB2BSupport
= TRUE
;
1138 // P2C can not support FB2B on the secondary side
1140 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
1141 FastB2BSupport
= FALSE
;
1145 // For RootBridge, PPB , P2C, go recursively to traverse all its children
1147 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1148 while (CurrentLink
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1150 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1151 Status
= DetermineDeviceAttribute (Temp
);
1152 if (EFI_ERROR (Status
)) {
1156 // Detect Fast Bact to Bact support for the device under the bridge
1158 Status
= GetFastBackToBackSupport (Temp
, PCI_PRIMARY_STATUS_OFFSET
);
1159 if (FastB2BSupport
&& EFI_ERROR (Status
)) {
1160 FastB2BSupport
= FALSE
;
1163 CurrentLink
= CurrentLink
->ForwardLink
;
1166 // Set or clear Fast Back to Back bit for the whole bridge
1168 if (!IsListEmpty (&PciIoDevice
->ChildList
)) {
1170 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
1172 Status
= GetFastBackToBackSupport (PciIoDevice
, PCI_BRIDGE_STATUS_REGISTER_OFFSET
);
1174 if (EFI_ERROR (Status
) || (!FastB2BSupport
)) {
1175 FastB2BSupport
= FALSE
;
1176 PciDisableBridgeControlRegister (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1178 PciEnableBridgeControlRegister (PciIoDevice
, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK
);
1182 CurrentLink
= PciIoDevice
->ChildList
.ForwardLink
;
1183 while (CurrentLink
&& CurrentLink
!= &PciIoDevice
->ChildList
) {
1184 Temp
= PCI_IO_DEVICE_FROM_LINK (CurrentLink
);
1185 if (FastB2BSupport
) {
1186 PciEnableCommandRegister (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1188 PciDisableCommandRegister (Temp
, EFI_PCI_COMMAND_FAST_BACK_TO_BACK
);
1191 CurrentLink
= CurrentLink
->ForwardLink
;
1195 // End for IsListEmpty
1202 IN PCI_IO_DEVICE
*PciIoDevice
1206 Routine Description:
1208 This routine is used to update the bar information for those incompatible PCI device
1217 // TODO: PciIoDevice - add argument and description to function comment
1218 // TODO: EFI_UNSUPPORTED - add return value to function comment
1224 EFI_PCI_DEVICE_INFO PciDeviceInfo
;
1225 VOID
*Configuration
;
1226 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Ptr
;
1228 Configuration
= NULL
;
1229 Status
= EFI_SUCCESS
;
1231 if (gEfiIncompatiblePciDeviceSupport
== NULL
) {
1233 // It can only be supported after the Incompatible PCI Device
1234 // Support Protocol has been installed
1236 Status
= gBS
->LocateProtocol (
1237 &gEfiIncompatiblePciDeviceSupportProtocolGuid
,
1239 (VOID
**) &gEfiIncompatiblePciDeviceSupport
1242 if (Status
== EFI_SUCCESS
) {
1244 // Check whether the device belongs to incompatible devices from protocol or not
1245 // If it is , then get its special requirement in the ACPI table
1247 Status
= gEfiIncompatiblePciDeviceSupport
->CheckDevice (
1248 gEfiIncompatiblePciDeviceSupport
,
1249 PciIoDevice
->Pci
.Hdr
.VendorId
,
1250 PciIoDevice
->Pci
.Hdr
.DeviceId
,
1251 PciIoDevice
->Pci
.Hdr
.RevisionID
,
1252 PciIoDevice
->Pci
.Device
.SubsystemVendorID
,
1253 PciIoDevice
->Pci
.Device
.SubsystemID
,
1259 if (EFI_ERROR (Status
)) {
1261 // Check whether the device belongs to incompatible devices from library or not
1262 // If it is , then get its special requirement in the ACPI table
1264 if (PcdGet8 (PcdPciIncompatibleDeviceSupportMask
) & PCI_INCOMPATIBLE_ACPI_RESOURCE_SUPPORT
) {
1265 PciDeviceInfo
.VendorID
= PciIoDevice
->Pci
.Hdr
.VendorId
;
1266 PciDeviceInfo
.DeviceID
= PciIoDevice
->Pci
.Hdr
.DeviceId
;
1267 PciDeviceInfo
.RevisionID
= PciIoDevice
->Pci
.Hdr
.RevisionID
;
1268 PciDeviceInfo
.SubsystemVendorID
= PciIoDevice
->Pci
.Device
.SubsystemVendorID
;
1269 PciDeviceInfo
.SubsystemID
= PciIoDevice
->Pci
.Device
.SubsystemID
;
1271 Status
= PciResourceUpdateCheck (&PciDeviceInfo
, &Configuration
);
1275 if (EFI_ERROR (Status
)) {
1276 return EFI_UNSUPPORTED
;
1280 // Update PCI device information from the ACPI table
1282 Ptr
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1284 while (Ptr
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1286 if (Ptr
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) {
1288 // The format is not support
1293 BarIndex
= (UINTN
) Ptr
->AddrTranslationOffset
;
1294 BarEndIndex
= BarIndex
;
1297 // Update all the bars in the device
1299 if (BarIndex
== PCI_BAR_ALL
) {
1301 BarEndIndex
= PCI_MAX_BAR
- 1;
1304 if (BarIndex
>= PCI_MAX_BAR
) {
1309 for (; BarIndex
<= BarEndIndex
; BarIndex
++) {
1311 switch (Ptr
->ResType
) {
1312 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1315 // Make sure the bar is memory type
1317 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeMem
)) {
1322 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1325 // Make sure the bar is IO type
1327 if (CheckBarType (PciIoDevice
, (UINT8
) BarIndex
, PciBarTypeIo
)) {
1336 // Update the new alignment for the device
1338 SetNewAlign (&(PciIoDevice
->PciBar
[BarIndex
].Alignment
), Ptr
->AddrRangeMax
);
1341 // Update the new length for the device
1343 if (Ptr
->AddrLen
!= PCI_BAR_NOCHANGE
) {
1344 PciIoDevice
->PciBar
[BarIndex
].Length
= Ptr
->AddrLen
;
1352 gBS
->FreePool (Configuration
);
1359 IN UINT64
*Alignment
,
1360 IN UINT64 NewAlignment
1364 Routine Description:
1366 This routine will update the alignment with the new alignment
1375 // TODO: Alignment - add argument and description to function comment
1376 // TODO: NewAlignment - add argument and description to function comment
1378 UINT64 OldAlignment
;
1382 // The new alignment is the same as the original,
1385 if (NewAlignment
== PCI_BAR_OLD_ALIGN
) {
1389 // Check the validity of the parameter
1391 if (NewAlignment
!= PCI_BAR_EVEN_ALIGN
&&
1392 NewAlignment
!= PCI_BAR_SQUAD_ALIGN
&&
1393 NewAlignment
!= PCI_BAR_DQUAD_ALIGN
) {
1394 *Alignment
= NewAlignment
;
1398 OldAlignment
= (*Alignment
) + 1;
1402 // Get the first non-zero hex value of the length
1404 while ((OldAlignment
& 0x0F) == 0x00) {
1405 OldAlignment
= RShiftU64 (OldAlignment
, 4);
1410 // Adjust the alignment to even, quad or double quad boundary
1412 if (NewAlignment
== PCI_BAR_EVEN_ALIGN
) {
1413 if (OldAlignment
& 0x01) {
1414 OldAlignment
= OldAlignment
+ 2 - (OldAlignment
& 0x01);
1416 } else if (NewAlignment
== PCI_BAR_SQUAD_ALIGN
) {
1417 if (OldAlignment
& 0x03) {
1418 OldAlignment
= OldAlignment
+ 4 - (OldAlignment
& 0x03);
1420 } else if (NewAlignment
== PCI_BAR_DQUAD_ALIGN
) {
1421 if (OldAlignment
& 0x07) {
1422 OldAlignment
= OldAlignment
+ 8 - (OldAlignment
& 0x07);
1427 // Update the old value
1429 NewAlignment
= LShiftU64 (OldAlignment
, ShiftBit
) - 1;
1430 *Alignment
= NewAlignment
;
1437 IN PCI_IO_DEVICE
*PciIoDevice
,
1443 Routine Description:
1452 // TODO: PciIoDevice - add argument and description to function comment
1453 // TODO: Offset - add argument and description to function comment
1454 // TODO: BarIndex - add argument and description to function comment
1457 UINT32 OriginalValue
;
1466 Status
= BarExisted (
1473 if (EFI_ERROR (Status
)) {
1474 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1475 PciIoDevice
->PciBar
[BarIndex
].Length
= 0;
1476 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1479 // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway
1481 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1485 PciIoDevice
->PciBar
[BarIndex
].Offset
= (UINT8
) Offset
;
1492 if (Value
& 0xFFFF0000) {
1496 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo32
;
1497 PciIoDevice
->PciBar
[BarIndex
].Length
= ((~(Value
& Mask
)) + 1);
1498 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1504 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeIo16
;
1505 PciIoDevice
->PciBar
[BarIndex
].Length
= 0x0000FFFF & ((~(Value
& Mask
)) + 1);
1506 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1510 // Workaround. Some platforms inplement IO bar with 0 length
1511 // Need to treat it as no-bar
1513 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1514 PciIoDevice
->PciBar
[BarIndex
].BarType
= (PCI_BAR_TYPE
) 0;
1517 PciIoDevice
->PciBar
[BarIndex
].Prefetchable
= FALSE
;
1518 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1524 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= OriginalValue
& Mask
;
1526 switch (Value
& 0x07) {
1529 //memory space; anywhere in 32 bit address space
1533 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem32
;
1535 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem32
;
1538 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1539 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1544 // memory space; anywhere in 64 bit address space
1548 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypePMem64
;
1550 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeMem64
;
1554 // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar
1555 // is regarded as an extension for the first bar. As a result
1556 // the sizing will be conducted on combined 64 bit value
1557 // Here just store the masked first 32bit value for future size
1560 PciIoDevice
->PciBar
[BarIndex
].Length
= Value
& Mask
;
1561 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1564 // Increment the offset to point to next DWORD
1568 Status
= BarExisted (
1575 if (EFI_ERROR (Status
)) {
1580 // Fix the length to support some spefic 64 bit BAR
1584 for (Data
= Value
; Data
!= 0; Data
>>= 1) {
1587 Value
|= ((UINT32
)(-1) << Index
);
1590 // Calculate the size of 64bit bar
1592 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
|= LShiftU64 ((UINT64
) OriginalValue
, 32);
1594 PciIoDevice
->PciBar
[BarIndex
].Length
= PciIoDevice
->PciBar
[BarIndex
].Length
| LShiftU64 ((UINT64
) Value
, 32);
1595 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(PciIoDevice
->PciBar
[BarIndex
].Length
)) + 1;
1596 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1604 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1605 PciIoDevice
->PciBar
[BarIndex
].Length
= (~(Value
& Mask
)) + 1;
1606 PciIoDevice
->PciBar
[BarIndex
].Alignment
= PciIoDevice
->PciBar
[BarIndex
].Length
- 1;
1613 // Check the length again so as to keep compatible with some special bars
1615 if (PciIoDevice
->PciBar
[BarIndex
].Length
== 0) {
1616 PciIoDevice
->PciBar
[BarIndex
].BarType
= PciBarTypeUnknown
;
1617 PciIoDevice
->PciBar
[BarIndex
].BaseAddress
= 0;
1618 PciIoDevice
->PciBar
[BarIndex
].Alignment
= 0;
1622 // Increment number of bar
1628 InitializePciDevice (
1629 IN PCI_IO_DEVICE
*PciIoDevice
1633 Routine Description:
1635 This routine is used to initialize the bar of a PCI device
1636 It can be called typically when a device is going to be rejected
1645 // TODO: PciIoDevice - add argument and description to function comment
1646 // TODO: EFI_SUCCESS - add return value to function comment
1648 EFI_PCI_IO_PROTOCOL
*PciIo
;
1651 PciIo
= &(PciIoDevice
->PciIo
);
1654 // Put all the resource apertures
1655 // Resource base is set to all ones so as to indicate its resource
1656 // has not been alloacted
1658 for (Offset
= 0x10; Offset
<= 0x24; Offset
+= sizeof (UINT32
)) {
1659 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, Offset
, 1, &gAllOne
);
1667 IN PCI_IO_DEVICE
*PciIoDevice
1671 Routine Description:
1680 // TODO: PciIoDevice - add argument and description to function comment
1681 // TODO: EFI_SUCCESS - add return value to function comment
1683 EFI_PCI_IO_PROTOCOL
*PciIo
;
1685 PciIo
= &(PciIoDevice
->PciIo
);
1688 // Put all the resource apertures including IO16
1689 // Io32, pMem32, pMem64 to quiescent state
1690 // Resource base all ones, Resource limit all zeros
1692 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1C, 1, &gAllOne
);
1693 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x1D, 1, &gAllZero
);
1695 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x20, 1, &gAllOne
);
1696 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x22, 1, &gAllZero
);
1698 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x24, 1, &gAllOne
);
1699 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x26, 1, &gAllZero
);
1701 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllOne
);
1702 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x2C, 1, &gAllZero
);
1705 // don't support use io32 as for now
1707 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x30, 1, &gAllOne
);
1708 PciIoWrite (PciIo
, EfiPciIoWidthUint16
, 0x32, 1, &gAllZero
);
1711 // Force Interrupt line to zero for cards that come up randomly
1713 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1720 IN PCI_IO_DEVICE
*PciIoDevice
1724 Routine Description:
1733 // TODO: PciIoDevice - add argument and description to function comment
1734 // TODO: EFI_SUCCESS - add return value to function comment
1736 EFI_PCI_IO_PROTOCOL
*PciIo
;
1738 PciIo
= &(PciIoDevice
->PciIo
);
1741 // Put all the resource apertures including IO16
1742 // Io32, pMem32, pMem64 to quiescent state(
1743 // Resource base all ones, Resource limit all zeros
1745 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x1c, 1, &gAllOne
);
1746 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x20, 1, &gAllZero
);
1748 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x24, 1, &gAllOne
);
1749 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x28, 1, &gAllZero
);
1751 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x2c, 1, &gAllOne
);
1752 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x30, 1, &gAllZero
);
1754 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x34, 1, &gAllOne
);
1755 PciIoWrite (PciIo
, EfiPciIoWidthUint32
, 0x38, 1, &gAllZero
);
1758 // Force Interrupt line to zero for cards that come up randomly
1760 PciIoWrite (PciIo
, EfiPciIoWidthUint8
, 0x3C, 1, &gAllZero
);
1766 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
,
1774 Routine Description:
1783 // TODO: PciRootBridgeIo - add argument and description to function comment
1784 // TODO: Pci - add argument and description to function comment
1785 // TODO: Bus - add argument and description to function comment
1786 // TODO: Device - add argument and description to function comment
1787 // TODO: Func - add argument and description to function comment
1791 PCI_IO_DEVICE
*PciIoDevice
;
1795 Status
= gBS
->AllocatePool (
1796 EfiBootServicesData
,
1797 sizeof (PCI_IO_DEVICE
),
1798 (VOID
**) &PciIoDevice
1801 if (EFI_ERROR (Status
)) {
1805 ZeroMem (PciIoDevice
, sizeof (PCI_IO_DEVICE
));
1807 PciIoDevice
->Signature
= PCI_IO_DEVICE_SIGNATURE
;
1808 PciIoDevice
->Handle
= NULL
;
1809 PciIoDevice
->PciRootBridgeIo
= PciRootBridgeIo
;
1810 PciIoDevice
->DevicePath
= NULL
;
1811 PciIoDevice
->BusNumber
= Bus
;
1812 PciIoDevice
->DeviceNumber
= Device
;
1813 PciIoDevice
->FunctionNumber
= Func
;
1814 PciIoDevice
->Decodes
= 0;
1815 if (gFullEnumeration
) {
1816 PciIoDevice
->Allocated
= FALSE
;
1818 PciIoDevice
->Allocated
= TRUE
;
1821 PciIoDevice
->Registered
= FALSE
;
1822 PciIoDevice
->Attributes
= 0;
1823 PciIoDevice
->Supports
= 0;
1824 PciIoDevice
->BusOverride
= FALSE
;
1825 PciIoDevice
->AllOpRomProcessed
= FALSE
;
1827 PciIoDevice
->IsPciExp
= FALSE
;
1829 CopyMem (&(PciIoDevice
->Pci
), Pci
, sizeof (PCI_TYPE01
));
1832 // Initialize the PCI I/O instance structure
1835 Status
= InitializePciIoInstance (PciIoDevice
);
1836 Status
= InitializePciDriverOverrideInstance (PciIoDevice
);
1838 if (EFI_ERROR (Status
)) {
1839 gBS
->FreePool (PciIoDevice
);
1844 // Initialize the reserved resource list
1846 InitializeListHead (&PciIoDevice
->ReservedResourceList
);
1849 // Initialize the driver list
1851 InitializeListHead (&PciIoDevice
->OptionRomDriverList
);
1854 // Initialize the child list
1856 InitializeListHead (&PciIoDevice
->ChildList
);
1862 PciEnumeratorLight (
1863 IN EFI_HANDLE Controller
1867 Routine Description:
1869 This routine is used to enumerate entire pci bus system
1871 It is only called on the second start on the same Root Bridge.
1880 // TODO: Controller - add argument and description to function comment
1881 // TODO: EFI_SUCCESS - add return value to function comment
1882 // TODO: EFI_SUCCESS - add return value to function comment
1886 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
1887 PCI_IO_DEVICE
*RootBridgeDev
;
1890 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptors
;
1893 MaxBus
= PCI_MAX_BUS
;
1897 // If this root bridge has been already enumerated, then return successfully
1899 if (GetRootBridgeByHandle (Controller
) != NULL
) {
1904 // Open pci root bridge io protocol
1906 Status
= gBS
->OpenProtocol (
1908 &gEfiPciRootBridgeIoProtocolGuid
,
1909 (VOID
**) &PciRootBridgeIo
,
1910 gPciBusDriverBinding
.DriverBindingHandle
,
1912 EFI_OPEN_PROTOCOL_BY_DRIVER
1914 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
1918 Status
= PciRootBridgeIo
->Configuration (PciRootBridgeIo
, (VOID
**) &Descriptors
);
1920 if (EFI_ERROR (Status
)) {
1924 while (PciGetBusRange (&Descriptors
, &MinBus
, &MaxBus
, NULL
) == EFI_SUCCESS
) {
1927 // Create a device node for root bridge device with a NULL host bridge controller handle
1929 RootBridgeDev
= CreateRootBridge (Controller
);
1931 if (!RootBridgeDev
) {
1937 // Record the root bridge io protocol
1939 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
1941 Status
= PciPciDeviceInfoCollector (
1946 if (!EFI_ERROR (Status
)) {
1949 // Remove those PCI devices which are rejected when full enumeration
1951 RemoveRejectedPciDevices (RootBridgeDev
->Handle
, RootBridgeDev
);
1954 // Process option rom light
1956 ProcessOptionRomLight (RootBridgeDev
);
1959 // Determine attributes for all devices under this root bridge
1961 DetermineDeviceAttribute (RootBridgeDev
);
1964 // If successfully, insert the node into device pool
1966 InsertRootBridge (RootBridgeDev
);
1970 // If unsuccessly, destroy the entire node
1972 DestroyRootBridge (RootBridgeDev
);
1983 IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
**Descriptors
,
1986 OUT UINT16
*BusRange
1990 Routine Description:
1996 Descriptors - A pointer to the address space descriptor.
1997 MinBus - The min bus.
1998 MaxBus - The max bus.
1999 BusRange - The bus range.
2006 // TODO: EFI_SUCCESS - add return value to function comment
2007 // TODO: EFI_NOT_FOUND - add return value to function comment
2010 while ((*Descriptors
)->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
2011 if ((*Descriptors
)->ResType
== ACPI_ADDRESS_SPACE_TYPE_BUS
) {
2012 if (MinBus
!= NULL
) {
2013 *MinBus
= (UINT16
) (*Descriptors
)->AddrRangeMin
;
2016 if (MaxBus
!= NULL
) {
2017 *MaxBus
= (UINT16
) (*Descriptors
)->AddrRangeMax
;
2020 if (BusRange
!= NULL
) {
2021 *BusRange
= (UINT16
) (*Descriptors
)->AddrLen
;
2030 return EFI_NOT_FOUND
;
2034 StartManagingRootBridge (
2035 IN PCI_IO_DEVICE
*RootBridgeDev
2039 Routine Description:
2049 // TODO: RootBridgeDev - add argument and description to function comment
2050 // TODO: EFI_SUCCESS - add return value to function comment
2052 EFI_HANDLE RootBridgeHandle
;
2054 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2057 // Get the root bridge handle
2059 RootBridgeHandle
= RootBridgeDev
->Handle
;
2060 PciRootBridgeIo
= NULL
;
2063 // Get the pci root bridge io protocol
2065 Status
= gBS
->OpenProtocol (
2067 &gEfiPciRootBridgeIoProtocolGuid
,
2068 (VOID
**) &PciRootBridgeIo
,
2069 gPciBusDriverBinding
.DriverBindingHandle
,
2071 EFI_OPEN_PROTOCOL_BY_DRIVER
2074 if (EFI_ERROR (Status
) && Status
!= EFI_ALREADY_STARTED
) {
2079 // Store the PciRootBridgeIo protocol into root bridge private data
2081 RootBridgeDev
->PciRootBridgeIo
= PciRootBridgeIo
;
2088 IsPciDeviceRejected (
2089 IN PCI_IO_DEVICE
*PciIoDevice
2093 Routine Description:
2095 This routine can be used to check whether a PCI device should be rejected when light enumeration
2101 TRUE This device should be rejected
2102 FALSE This device shouldn't be rejected
2105 // TODO: PciIoDevice - add argument and description to function comment
2114 // PPB should be skip!
2116 if (IS_PCI_BRIDGE (&PciIoDevice
->Pci
)) {
2120 if (IS_CARDBUS_BRIDGE (&PciIoDevice
->Pci
)) {
2122 // Only test base registers for P2C
2124 for (BarOffset
= 0x1C; BarOffset
<= 0x38; BarOffset
+= 2 * sizeof (UINT32
)) {
2126 Mask
= (BarOffset
< 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC;
2127 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2128 if (EFI_ERROR (Status
)) {
2132 TestValue
= TestValue
& Mask
;
2133 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2135 // The bar isn't programed, so it should be rejected
2144 for (BarOffset
= 0x14; BarOffset
<= 0x24; BarOffset
+= sizeof (UINT32
)) {
2148 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2149 if (EFI_ERROR (Status
)) {
2153 if (TestValue
& 0x01) {
2160 TestValue
= TestValue
& Mask
;
2161 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2172 TestValue
= TestValue
& Mask
;
2174 if ((TestValue
& 0x07) == 0x04) {
2179 BarOffset
+= sizeof (UINT32
);
2180 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2183 // Test its high 32-Bit BAR
2186 Status
= BarExisted (PciIoDevice
, BarOffset
, &TestValue
, &OldValue
);
2187 if (TestValue
== OldValue
) {
2197 if ((TestValue
!= 0) && (TestValue
== (OldValue
& Mask
))) {
2208 ResetAllPpbBusNumber (
2209 IN PCI_IO_DEVICE
*Bridge
,
2210 IN UINT8 StartBusNumber
2214 Routine Description:
2216 TODO: Add function description
2220 Bridge - TODO: add argument description
2221 StartBusNumber - TODO: add argument description
2225 EFI_SUCCESS - TODO: Add description for return value
2236 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
*PciRootBridgeIo
;
2238 PciRootBridgeIo
= Bridge
->PciRootBridgeIo
;
2240 for (Device
= 0; Device
<= PCI_MAX_DEVICE
; Device
++) {
2241 for (Func
= 0; Func
<= PCI_MAX_FUNC
; Func
++) {
2244 // Check to see whether a pci device is present
2246 Status
= PciDevicePresent (
2254 if (!EFI_ERROR (Status
) && (IS_PCI_BRIDGE (&Pci
))) {
2257 Address
= EFI_PCI_ADDRESS (StartBusNumber
, Device
, Func
, 0x18);
2258 Status
= PciRootBridgeIoRead (
2266 SecondaryBus
= (UINT8
)(Register
>> 8);
2268 if (SecondaryBus
!= 0) {
2269 ResetAllPpbBusNumber (Bridge
, SecondaryBus
);
2273 // Reset register 18h, 19h, 1Ah on PCI Bridge
2275 Register
&= 0xFF000000;
2276 Status
= PciRootBridgeIoWrite (
2286 if (Func
== 0 && !IS_PCI_MULTI_FUNC (&Pci
)) {
2288 // Skip sub functions, this is not a multi function device
2290 Func
= PCI_MAX_FUNC
;