2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/bus/pci/enum.c
5 * PURPOSE: PCI Bus/Device Enumeration
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 /* FUNCTIONS ******************************************************************/
20 * 7. The IO/MEM/Busmaster decodes are disabled for the device.
21 * 8. The PCI bus driver sets the operating mode bits of the Programming
22 * Interface byte to switch the controller to native mode.
24 * Important: When the controller is set to native mode, it must quiet itself
25 * and must not decode I/O resources or generate interrupts until the operating
26 * system has enabled the ports in the PCI configuration header.
27 * The IO/MEM/BusMaster bits will be disabled before the mode change, but it
28 * is not possible to disable interrupts on the device. The device must not
29 * generate interrupts (either legacy or native mode) while the decodes are
30 * disabled in the command register.
32 * This operation is expected to be instantaneous and the operating system does
33 * not stall afterward. It is also expected that the interrupt pin register in
34 * the PCI Configuration space for this device is accurate. The operating system
35 * re-reads this data after previously ignoring it.
39 PciConfigureIdeController(IN PPCI_PDO_EXTENSION PdoExtension
,
40 IN PPCI_COMMON_HEADER PciData
,
43 UCHAR MasterMode
, SlaveMode
, MasterFixed
, SlaveFixed
, ProgIf
, NewProgIf
;
47 /* Assume it won't work */
50 /* Get master and slave current settings, and programmability flag */
51 ProgIf
= PciData
->ProgIf
;
52 MasterMode
= (ProgIf
& 1) == 1;
53 MasterFixed
= (ProgIf
& 2) == 0;
54 SlaveMode
= (ProgIf
& 4) == 4;
55 SlaveFixed
= (ProgIf
& 8) == 0;
58 * [..] In order for Windows XP SP1 and Windows Server 2003 to switch an ATA
59 * ATA controller from compatible mode to native mode, the following must be
62 * - The controller must indicate in its programming interface that both channels
63 * can be switched to native mode. Windows XP SP1 and Windows Server 2003 do
64 * not support switching only one IDE channel to native mode. See the PCI IDE
65 * Controller Specification Revision 1.0 for details.
67 if ((MasterMode
!= SlaveMode
) || (MasterFixed
!= SlaveFixed
))
69 /* Windows does not support this configuration, fail */
70 DPRINT1("PCI: Warning unsupported IDE controller configuration for VEN_%04x&DEV_%04x!",
71 PdoExtension
->VendorId
,
72 PdoExtension
->DeviceId
);
76 /* Check if the controller is already in native mode */
77 if ((MasterMode
) && (SlaveMode
))
79 /* Check if I/O decodes should be disabled */
80 if ((Initial
) || (PdoExtension
->IoSpaceUnderNativeIdeControl
))
82 /* Read the current command */
83 PciReadDeviceConfig(PdoExtension
,
85 FIELD_OFFSET(PCI_COMMON_HEADER
, Command
),
88 /* Disable I/O space decode */
89 Command
&= ~PCI_ENABLE_IO_SPACE
;
91 /* Update new command in PCI IDE controller */
92 PciWriteDeviceConfig(PdoExtension
,
94 FIELD_OFFSET(PCI_COMMON_HEADER
, Command
),
97 /* Save updated command value */
98 PciData
->Command
= Command
;
101 /* The controller is now in native mode */
104 else if (!(MasterFixed
) &&
106 (PdoExtension
->BIOSAllowsIDESwitchToNativeMode
) &&
107 !(PdoExtension
->HackFlags
& PCI_HACK_DISABLE_IDE_NATIVE_MODE
))
109 /* Turn off decodes */
110 PciDecodeEnable(PdoExtension
, FALSE
, NULL
);
112 /* Update the current command */
113 PciReadDeviceConfig(PdoExtension
,
115 FIELD_OFFSET(PCI_COMMON_HEADER
, Command
),
118 /* Enable native mode */
119 ProgIf
= PciData
->ProgIf
| 5;
120 PciWriteDeviceConfig(PdoExtension
,
122 FIELD_OFFSET(PCI_COMMON_HEADER
, ProgIf
),
125 /* Verify the setting "stuck" */
126 PciReadDeviceConfig(PdoExtension
,
128 FIELD_OFFSET(PCI_COMMON_HEADER
, ProgIf
),
130 if (NewProgIf
== ProgIf
)
132 /* Update the header and PDO data with the new programming mode */
133 PciData
->ProgIf
= ProgIf
;
134 PdoExtension
->ProgIf
= NewProgIf
;
136 /* Clear the first four BARs to reset current BAR setttings */
137 PciData
->u
.type0
.BaseAddresses
[0] = 0;
138 PciData
->u
.type0
.BaseAddresses
[1] = 0;
139 PciData
->u
.type0
.BaseAddresses
[2] = 0;
140 PciData
->u
.type0
.BaseAddresses
[3] = 0;
141 PciWriteDeviceConfig(PdoExtension
,
142 PciData
->u
.type0
.BaseAddresses
,
143 FIELD_OFFSET(PCI_COMMON_HEADER
,
144 u
.type0
.BaseAddresses
),
147 /* Re-read the BARs to have the latest data for native mode IDE */
148 PciReadDeviceConfig(PdoExtension
,
149 PciData
->u
.type0
.BaseAddresses
,
150 FIELD_OFFSET(PCI_COMMON_HEADER
,
151 u
.type0
.BaseAddresses
),
154 /* Re-read the interrupt pin used for native mode IDE */
155 PciReadDeviceConfig(PdoExtension
,
156 &PciData
->u
.type0
.InterruptPin
,
157 FIELD_OFFSET(PCI_COMMON_HEADER
,
158 u
.type0
.InterruptPin
),
161 /* The IDE Controller is now in native mode */
166 /* Settings did not work, fail */
167 DPRINT1("PCI: Warning failed switch to native mode for IDE controller VEN_%04x&DEV_%04x!",
173 /* Return whether or not native mode was enabled on the IDE controller */
179 PciApplyHacks(IN PPCI_FDO_EXTENSION DeviceExtension
,
180 IN PPCI_COMMON_HEADER PciData
,
181 IN PCI_SLOT_NUMBER SlotNumber
,
182 IN ULONG OperationType
,
183 PPCI_PDO_EXTENSION PdoExtension
)
185 ULONG LegacyBaseAddress
;
189 /* There should always be a PDO extension passed in */
190 ASSERT(PdoExtension
);
192 /* Check what kind of hack operation this is */
193 switch (OperationType
)
196 * This is mostly concerned with fixing up incorrect class data that can
197 * exist on certain PCI hardware before the 2.0 spec was ratified.
199 case PCI_HACK_FIXUP_BEFORE_CONFIGURATION
:
201 /* Note that the i82375 PCI/EISA and the i82378 PCI/ISA bridges that
202 * are present on certain DEC/NT Alpha machines are pre-PCI 2.0 devices
203 * and appear as non-classified, so their correct class/subclass data
204 * is written here instead.
206 if ((PciData
->VendorID
== 0x8086) &&
207 ((PciData
->DeviceID
== 0x482) || (PciData
->DeviceID
== 0x484)))
209 /* Note that 0x482 is the i82375 (EISA), 0x484 is the i82378 (ISA) */
210 PciData
->SubClass
= PciData
->DeviceID
== 0x482 ?
211 PCI_SUBCLASS_BR_EISA
: PCI_SUBCLASS_BR_ISA
;
212 PciData
->BaseClass
= PCI_CLASS_BRIDGE_DEV
;
215 * Because the software is modifying the actual header data from
216 * the BIOS, this flag tells the driver to ignore failures when
217 * comparing the original BIOS data with the PCI data.
219 if (PdoExtension
) PdoExtension
->ExpectedWritebackFailure
= TRUE
;
222 /* Note that in this case, an immediate return is issued */
226 * This is concerned with setting up interrupts correctly for native IDE
227 * mode, but will also handle broken VGA decoding on older bridges as
228 * well as a PAE-specific hack for certain Compaq Hot-Plug Controllers.
230 case PCI_HACK_FIXUP_AFTER_CONFIGURATION
:
233 * On the OPTi Viper-M IDE controller, Linux doesn't support IDE-DMA
234 * and FreeBSD bug reports indicate that the system crashes when the
235 * feature is enabled (so it's disabled on that OS as well). In the
236 * NT PCI Bus Driver, it seems Microsoft too, completely disables
237 * Native IDE functionality on this controller, so it would seem OPTi
238 * simply frelled up this controller.
240 if ((PciData
->VendorID
== 0x1045) && (PciData
->DeviceID
!= 0xC621))
242 /* Disable native mode */
243 PciData
->ProgIf
&= ~5;
244 PciData
->u
.type0
.InterruptPin
= 0;
247 * Because the software is modifying the actual header data from
248 * the BIOS, this flag tells the driver to ignore failures when
249 * comparing the original BIOS data with the PCI data.
251 PdoExtension
->ExpectedWritebackFailure
= TRUE
;
253 else if ((PciData
->BaseClass
== PCI_CLASS_MASS_STORAGE_CTLR
) &&
254 (PciData
->SubClass
== PCI_SUBCLASS_MSC_IDE_CTLR
))
256 /* For other IDE controllers, start out in compatible mode */
257 PdoExtension
->BIOSAllowsIDESwitchToNativeMode
= FALSE
;
260 * Registry must have enabled native mode (typically as a result
261 * of an INF file directive part of the IDE controller's driver)
262 * and the system must not be booted in Safe Mode. If that checks
263 * out, then evaluate the ACPI NATA method to see if the platform
264 * supports this. See the section "BIOS and Platform Prerequisites
265 * for Switching a Native-Mode-Capable Controller" in the Storage
266 * section of the Windows Driver Kit for more details:
268 * 5. For each ATA controller enumerated, the PCI bus driver checks
269 * the Programming Interface register of the IDE controller to
270 * see if it supports switching both channels to native mode.
271 * 6. The PCI bus driver checks whether the BIOS/platform supports
272 * switching the controller by checking the NATA method described
273 * earlier in this article.
275 * If an ATA controller does not indicate that it is native
276 * mode-capable, or if the BIOS NATA control method is missing
277 * or does not list that device, the PCI bus driver does not
278 * switch the controller and it is assigned legacy resources.
280 * If both the controller and the BIOS indicate that the controller
281 * can be switched, the process of switching the controller begins
282 * with the next step.
284 if ((PciEnableNativeModeATA
) &&
285 !(InitSafeBootMode
) &&
286 (PciIsSlotPresentInParentMethod(PdoExtension
, 'ATAN')))
288 /* The platform supports it, remember that */
289 PdoExtension
->BIOSAllowsIDESwitchToNativeMode
= TRUE
;
292 * Now switch the controller into native mode if both channels
293 * support native IDE mode. See "How Windows Switches an ATA
294 * Controller to Native Mode" in the Storage section of the
295 * Windows Driver Kit for more details.
297 PdoExtension
->SwitchedIDEToNativeMode
=
298 PciConfigureIdeController(PdoExtension
, PciData
, 1);
301 /* Is native mode enabled after all? */
302 if ((PciData
->ProgIf
& 5) != 5)
304 /* Compatible mode, so force ISA-style IRQ14 and IRQ 15 */
305 PciData
->u
.type0
.InterruptPin
= 0;
309 /* Is this a PCI device with legacy VGA card decodes on the root bus? */
310 if ((PdoExtension
->HackFlags
& PCI_HACK_VIDEO_LEGACY_DECODE
) &&
311 (PCI_IS_ROOT_FDO(DeviceExtension
)) &&
312 !(DeviceExtension
->BrokenVideoHackApplied
))
314 /* Tell the arbiter to apply a hack for these older devices */
315 ario_ApplyBrokenVideoHack(DeviceExtension
);
318 /* Is this a Compaq PCI Hotplug Controller (r17) on a PAE system ? */
319 if ((PciData
->VendorID
== 0xE11) &&
320 (PciData
->DeviceID
== 0xA0F7) &&
321 (PciData
->RevisionID
== 17) &&
322 (ExIsProcessorFeaturePresent(PF_PAE_ENABLED
)))
324 /* Turn off the decodes immediately */
325 PciData
->Command
&= ~(PCI_ENABLE_IO_SPACE
|
326 PCI_ENABLE_MEMORY_SPACE
|
327 PCI_ENABLE_BUS_MASTER
);
328 PciWriteDeviceConfig(PdoExtension
,
330 FIELD_OFFSET(PCI_COMMON_HEADER
, Command
),
333 /* Do not EVER turn them on again, this will blow up the system */
334 PdoExtension
->CommandEnables
&= ~(PCI_ENABLE_IO_SPACE
|
335 PCI_ENABLE_MEMORY_SPACE
|
336 PCI_ENABLE_BUS_MASTER
);
337 PdoExtension
->HackFlags
|= PCI_HACK_PRESERVE_COMMAND
;
342 * This is called whenever resources are changed and hardware needs to be
343 * updated. It is concerned with two highly specific erratas on an IBM
344 * hot-plug docking bridge used on the Thinkpad 600 Series and on Intel's
347 case PCI_HACK_FIXUP_BEFORE_UPDATE
:
349 /* Is this an IBM 20H2999 PCI Docking Bridge, used on Thinkpads? */
350 if ((PdoExtension
->VendorId
== 0x1014) &&
351 (PdoExtension
->DeviceId
== 0x95))
353 /* Read the current command */
354 PciReadDeviceConfig(PdoExtension
,
356 FIELD_OFFSET(PCI_COMMON_HEADER
, Command
),
359 /* Turn off the decodes */
360 PciDecodeEnable(PdoExtension
, FALSE
, &Command
);
362 /* Apply the required IBM workaround */
363 PciReadDeviceConfig(PdoExtension
, &RegValue
, 0xE0, sizeof(UCHAR
));
366 PciWriteDeviceConfig(PdoExtension
, &RegValue
, 0xE0, sizeof(UCHAR
));
368 /* Restore the command to its original value */
369 PciWriteDeviceConfig(PdoExtension
,
371 FIELD_OFFSET(PCI_COMMON_HEADER
, Command
),
377 * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
378 * i820, i840, i845 Chipsets) that have subtractive decode enabled,
379 * and whose hack flags do not specifiy that this support is broken.
381 if ((PdoExtension
->HeaderType
== PCI_BRIDGE_TYPE
) &&
382 (PdoExtension
->Dependent
.type1
.SubtractiveDecode
) &&
383 ((PdoExtension
->VendorId
== 0x8086) &&
384 ((PdoExtension
->DeviceId
== 0x2418) ||
385 (PdoExtension
->DeviceId
== 0x2428) ||
386 (PdoExtension
->DeviceId
== 0x244E) ||
387 (PdoExtension
->DeviceId
== 0x2448))) &&
388 !(PdoExtension
->HackFlags
& PCI_HACK_BROKEN_SUBTRACTIVE_DECODE
))
391 * The positive decode window shouldn't be used, these values are
392 * normally all read-only or initialized to 0 by the BIOS, but
393 * it appears Intel doesn't do this, so the PCI Bus Driver will
394 * do it in software instead. Note that this is used to prevent
395 * certain non-compliant PCI devices from breaking down due to the
396 * fact that these ICH bridges have a known "quirk" (which Intel
397 * documents as a known "erratum", although it's not not really
398 * an ICH bug since the PCI specification does allow for it) in
399 * that they will sometimes send non-zero addresses during special
400 * cycles (ie: non-zero data during the address phase). These
401 * broken PCI cards will mistakenly attempt to claim the special
402 * cycle and corrupt their I/O and RAM ranges. Again, in Intel's
403 * defense, the PCI specification only requires stable data, not
404 * necessarily zero data, during the address phase.
406 PciData
->u
.type1
.MemoryBase
= 0xFFFF;
407 PciData
->u
.type1
.PrefetchBase
= 0xFFFF;
408 PciData
->u
.type1
.IOBase
= 0xFF;
409 PciData
->u
.type1
.IOLimit
= 0;
410 PciData
->u
.type1
.MemoryLimit
= 0;
411 PciData
->u
.type1
.PrefetchLimit
= 0;
412 PciData
->u
.type1
.PrefetchBaseUpper32
= 0;
413 PciData
->u
.type1
.PrefetchLimitUpper32
= 0;
414 PciData
->u
.type1
.IOBaseUpper16
= 0;
415 PciData
->u
.type1
.IOLimitUpper16
= 0;
423 /* Finally, also check if this is this a CardBUS device? */
424 if (PCI_CONFIGURATION_TYPE(PciData
) == PCI_CARDBUS_BRIDGE_TYPE
)
427 * At offset 44h the LegacyBaseAddress is stored, which is cleared by
428 * ACPI-aware versions of Windows, to disable legacy-mode I/O access to
429 * CardBus controllers. For more information, see "Supporting CardBus
430 * Controllers under ACPI" in the "CardBus Controllers and Windows"
431 * Whitepaper on WHDC.
433 LegacyBaseAddress
= 0;
434 PciWriteDeviceConfig(PdoExtension
,
436 sizeof(PCI_COMMON_HEADER
) + sizeof(ULONG
),
444 PcipIsSameDevice(IN PPCI_PDO_EXTENSION DeviceExtension
,
445 IN PPCI_COMMON_HEADER PciData
)
447 BOOLEAN IdMatch
, RevMatch
, SubsysMatch
;
448 ULONGLONG HackFlags
= DeviceExtension
->HackFlags
;
450 /* Check if the IDs match */
451 IdMatch
= (PciData
->VendorID
== DeviceExtension
->VendorId
) &&
452 (PciData
->DeviceID
== DeviceExtension
->DeviceId
);
453 if (!IdMatch
) return FALSE
;
455 /* If the device has a valid revision, check if it matches */
456 RevMatch
= (HackFlags
& PCI_HACK_NO_REVISION_AFTER_D3
) ||
457 (PciData
->RevisionID
== DeviceExtension
->RevisionId
);
458 if (!RevMatch
) return FALSE
;
460 /* For multifunction devices, this is enough to assume they're the same */
461 if (PCI_MULTIFUNCTION_DEVICE(PciData
)) return TRUE
;
463 /* For bridge devices, there's also nothing else that can be checked */
464 if (DeviceExtension
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) return TRUE
;
466 /* Devices, on the other hand, have subsystem data that can be compared */
467 SubsysMatch
= (HackFlags
& (PCI_HACK_NO_SUBSYSTEM
|
468 PCI_HACK_NO_SUBSYSTEM_AFTER_D3
)) ||
469 ((DeviceExtension
->SubsystemVendorId
==
470 PciData
->u
.type0
.SubVendorID
) &&
471 (DeviceExtension
->SubsystemId
==
472 PciData
->u
.type0
.SubSystemID
));
478 PciSkipThisFunction(IN PPCI_COMMON_HEADER PciData
,
479 IN PCI_SLOT_NUMBER Slot
,
480 IN UCHAR OperationType
,
481 IN ULONGLONG HackFlags
)
485 /* Check if this is device enumeration */
486 if (OperationType
== PCI_SKIP_DEVICE_ENUMERATION
)
488 /* Check if there's a hackflag saying not to enumerate this device */
489 if (HackFlags
& PCI_HACK_NO_ENUM_AT_ALL
) break;
491 /* Check if this is the high end of a double decker device */
492 if ((HackFlags
& PCI_HACK_DOUBLE_DECKER
) &&
493 (Slot
.u
.bits
.DeviceNumber
>= 16))
495 /* It belongs to the same device, so skip it */
496 DPRINT1(" Device (Ven %04x Dev %04x (d=0x%x, f=0x%x)) is a ghost.\n",
499 Slot
.u
.bits
.DeviceNumber
,
500 Slot
.u
.bits
.FunctionNumber
);
504 else if (OperationType
== PCI_SKIP_RESOURCE_ENUMERATION
)
506 /* Resource enumeration, check for a hackflag saying not to do it */
507 if (HackFlags
& PCI_HACK_ENUM_NO_RESOURCE
) break;
511 /* Logic error in the driver */
512 ASSERTMSG(FALSE
, "PCI Skip Function - Operation type unknown.");
515 /* Check for legacy bridges during resource enumeration */
516 if ((PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
517 (PciData
->SubClass
<= PCI_SUBCLASS_BR_MCA
) &&
518 (OperationType
== PCI_SKIP_RESOURCE_ENUMERATION
))
520 /* Their resources are not enumerated, only PCI and Cardbus/PCMCIA */
523 else if (PciData
->BaseClass
== PCI_CLASS_NOT_DEFINED
)
525 /* Undefined base class (usually a PCI BIOS/ROM bug) */
526 DPRINT1(" Vendor %04x, Device %04x has class code of PCI_CLASS_NOT_DEFINED\n",
531 * The Alder has an Intel Extended Express System Support Controller
532 * which presents apparently spurious BARs. When the PCI resource
533 * code tries to reassign these BARs, the second IO-APIC gets
534 * disabled (with disastrous consequences). The first BAR is the
535 * actual IO-APIC, the remaining five bars seem to be spurious
536 * resources, so ignore this device completely.
538 if ((PciData
->VendorID
== 0x8086) && (PciData
->DeviceID
== 8)) break;
541 /* Other normal PCI cards and bridges are enumerated */
542 if (PCI_CONFIGURATION_TYPE(PciData
) <= PCI_CARDBUS_BRIDGE_TYPE
) return FALSE
;
545 /* Hit one of the known bugs/hackflags, or this is a new kind of PCI unit */
546 DPRINT1(" Device skipped (not enumerated).\n");
552 PciGetEnhancedCapabilities(IN PPCI_PDO_EXTENSION PdoExtension
,
553 IN PPCI_COMMON_HEADER PciData
)
555 ULONG HeaderType
, CapPtr
, TargetAgpCapabilityId
;
556 DEVICE_POWER_STATE WakeLevel
;
557 PCI_CAPABILITIES_HEADER AgpCapability
;
558 PCI_PM_CAPABILITY PowerCapabilities
;
561 /* Assume no known wake level */
562 PdoExtension
->PowerState
.DeviceWakeLevel
= PowerDeviceUnspecified
;
564 /* Make sure the device has capabilities */
565 if (!(PciData
->Status
& PCI_STATUS_CAPABILITIES_LIST
))
567 /* If it doesn't, there will be no power management */
568 PdoExtension
->CapabilitiesPtr
= 0;
569 PdoExtension
->HackFlags
|= PCI_HACK_NO_PM_CAPS
;
573 /* There's capabilities, need to figure out where to get the offset */
574 HeaderType
= PCI_CONFIGURATION_TYPE(PciData
);
575 if (HeaderType
== PCI_CARDBUS_BRIDGE_TYPE
)
577 /* Use the bridge's header */
578 CapPtr
= PciData
->u
.type2
.CapabilitiesPtr
;
582 /* Use the device header */
583 ASSERT(HeaderType
<= PCI_CARDBUS_BRIDGE_TYPE
);
584 CapPtr
= PciData
->u
.type0
.CapabilitiesPtr
;
587 /* Make sure the pointer is spec-aligned and located, and save it */
588 DPRINT1("Device has capabilities at: %lx\n", CapPtr
);
589 ASSERT(((CapPtr
& 0x3) == 0) && (CapPtr
>= PCI_COMMON_HDR_LENGTH
));
590 PdoExtension
->CapabilitiesPtr
= CapPtr
;
592 /* Check for PCI-to-PCI Bridges and AGP bridges */
593 if ((PdoExtension
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
594 ((PdoExtension
->SubClass
== PCI_SUBCLASS_BR_HOST
) ||
595 (PdoExtension
->SubClass
== PCI_SUBCLASS_BR_PCI_TO_PCI
)))
597 /* Query either the raw AGP capabilitity, or the Target AGP one */
598 TargetAgpCapabilityId
= (PdoExtension
->SubClass
==
599 PCI_SUBCLASS_BR_PCI_TO_PCI
) ?
600 PCI_CAPABILITY_ID_AGP_TARGET
:
601 PCI_CAPABILITY_ID_AGP
;
602 if (PciReadDeviceCapability(PdoExtension
,
603 PdoExtension
->CapabilitiesPtr
,
604 TargetAgpCapabilityId
,
606 sizeof(PCI_CAPABILITIES_HEADER
)))
608 /* AGP target ID was found, store it */
609 DPRINT1("AGP ID: %lx\n", TargetAgpCapabilityId
);
610 PdoExtension
->TargetAgpCapabilityId
= TargetAgpCapabilityId
;
614 /* Check for devices that are known not to have proper power management */
615 if (!(PdoExtension
->HackFlags
& PCI_HACK_NO_PM_CAPS
))
617 /* Query if this device supports power management */
618 if (!PciReadDeviceCapability(PdoExtension
,
619 PdoExtension
->CapabilitiesPtr
,
620 PCI_CAPABILITY_ID_POWER_MANAGEMENT
,
621 &PowerCapabilities
.Header
,
622 sizeof(PCI_PM_CAPABILITY
)))
624 /* No power management, so act as if it had the hackflag set */
625 DPRINT1("No PM caps, disabling PM\n");
626 PdoExtension
->HackFlags
|= PCI_HACK_NO_PM_CAPS
;
630 /* Otherwise, pick the highest wake level that is supported */
631 WakeLevel
= PowerDeviceUnspecified
;
632 if (PowerCapabilities
.PMC
.Capabilities
.Support
.PMED0
)
633 WakeLevel
= PowerDeviceD0
;
634 if (PowerCapabilities
.PMC
.Capabilities
.Support
.PMED1
)
635 WakeLevel
= PowerDeviceD1
;
636 if (PowerCapabilities
.PMC
.Capabilities
.Support
.PMED2
)
637 WakeLevel
= PowerDeviceD2
;
638 if (PowerCapabilities
.PMC
.Capabilities
.Support
.PMED3Hot
)
639 WakeLevel
= PowerDeviceD3
;
640 if (PowerCapabilities
.PMC
.Capabilities
.Support
.PMED3Cold
)
641 WakeLevel
= PowerDeviceD3
;
642 PdoExtension
->PowerState
.DeviceWakeLevel
= WakeLevel
;
644 /* Convert the PCI power state to the NT power state */
645 PdoExtension
->PowerState
.CurrentDeviceState
=
646 PowerCapabilities
.PMCSR
.ControlStatus
.PowerState
+ 1;
648 /* Save all the power capabilities */
649 PdoExtension
->PowerCapabilities
= PowerCapabilities
.PMC
.Capabilities
;
650 DPRINT1("PM Caps Found! Wake Level: %d Power State: %d\n",
651 WakeLevel
, PdoExtension
->PowerState
.CurrentDeviceState
);
656 /* At the very end of all this, does this device not have power management? */
657 if (PdoExtension
->HackFlags
& PCI_HACK_NO_PM_CAPS
)
659 /* Then guess the current state based on whether the decodes are on */
660 PdoExtension
->PowerState
.CurrentDeviceState
=
661 PciData
->Command
& (PCI_ENABLE_IO_SPACE
|
662 PCI_ENABLE_MEMORY_SPACE
|
663 PCI_ENABLE_BUS_MASTER
) ?
664 PowerDeviceD0
: PowerDeviceD3
;
665 DPRINT1("PM is off, so assumed device is: %d based on enables\n",
666 PdoExtension
->PowerState
.CurrentDeviceState
);
672 PciScanBus(IN PPCI_FDO_EXTENSION DeviceExtension
)
674 ULONG MaxDevice
= PCI_MAX_DEVICES
;
675 BOOLEAN ProcessFlag
= FALSE
;
677 USHORT CapOffset
, TempOffset
;
679 PDEVICE_OBJECT DeviceObject
;
680 UCHAR Buffer
[PCI_COMMON_HDR_LENGTH
];
681 UCHAR BiosBuffer
[PCI_COMMON_HDR_LENGTH
];
682 PPCI_COMMON_HEADER PciData
= (PVOID
)Buffer
;
683 PPCI_COMMON_HEADER BiosData
= (PVOID
)BiosBuffer
;
684 PCI_SLOT_NUMBER PciSlot
;
687 PPCI_PDO_EXTENSION PdoExtension
, NewExtension
;
688 PPCI_PDO_EXTENSION
* BridgeExtension
;
689 PWCHAR DescriptionText
;
690 USHORT SubVendorId
, SubSystemId
;
691 PCI_CAPABILITIES_HEADER CapHeader
, PcixCapHeader
;
692 DPRINT1("PCI Scan Bus: FDO Extension @ 0x%x, Base Bus = 0x%x\n",
693 DeviceExtension
, DeviceExtension
->BaseBus
);
695 /* Is this the root FDO? */
696 if (!PCI_IS_ROOT_FDO(DeviceExtension
))
698 /* Other FDOs are not currently supported */
703 /* Loop every device on the bus */
704 PciSlot
.u
.bits
.Reserved
= 0;
705 i
= DeviceExtension
->BaseBus
;
706 for (j
= 0; j
< MaxDevice
; j
++)
708 /* Loop every function of each device */
709 PciSlot
.u
.bits
.DeviceNumber
= j
;
710 for (k
= 0; k
< PCI_MAX_FUNCTION
; k
++)
712 /* Build the final slot structure */
713 PciSlot
.u
.bits
.FunctionNumber
= k
;
715 /* Read the vendor for this slot */
716 PciReadSlotConfig(DeviceExtension
,
722 /* Skip invalid device */
723 if (PciData
->VendorID
== PCI_INVALID_VENDORID
) continue;
725 /* Now read the whole header */
726 PciReadSlotConfig(DeviceExtension
,
730 PCI_COMMON_HDR_LENGTH
- sizeof(USHORT
));
732 /* Apply any hacks before even analyzing the configuration header */
733 PciApplyHacks(DeviceExtension
,
736 PCI_HACK_FIXUP_BEFORE_CONFIGURATION
,
739 /* Dump device that was found */
740 DPRINT1("Scan Found Device 0x%x (b=0x%x, d=0x%x, f=0x%x)\n",
746 /* Dump the device's header */
747 PciDebugDumpCommonConfig(PciData
);
749 /* Find description for this device for the debugger's sake */
750 DescriptionText
= PciGetDeviceDescriptionMessage(PciData
->BaseClass
,
752 DPRINT1("Device Description \"%S\".\n",
753 DescriptionText
? DescriptionText
: L
"(NULL)");
754 if (DescriptionText
) ExFreePoolWithTag(DescriptionText
, 0);
756 /* Check if there is an ACPI Watchdog Table */
759 /* Check if this PCI device is the ACPI Watchdog Device... */
764 /* Check for non-simple devices */
765 if ((PCI_MULTIFUNCTION_DEVICE(PciData
)) ||
766 (PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
))
768 /* No subsystem data defined for these kinds of bridges */
774 /* Read the subsystem information from the PCI header */
775 SubVendorId
= PciData
->u
.type0
.SubVendorID
;
776 SubSystemId
= PciData
->u
.type0
.SubSystemID
;
779 /* Get any hack flags for this device */
780 HackFlags
= PciGetHackFlags(PciData
->VendorID
,
784 PciData
->RevisionID
);
786 /* Check if this device is considered critical by the OS */
787 if (PciIsCriticalDeviceClass(PciData
->BaseClass
, PciData
->SubClass
))
789 /* Check if normally the decodes would be disabled */
790 if (!(HackFlags
& PCI_HACK_DONT_DISABLE_DECODES
))
792 /* Because this device is critical, don't disable them */
793 DPRINT1("Not allowing PM Because device is critical\n");
794 HackFlags
|= PCI_HACK_CRITICAL_DEVICE
;
798 /* PCI bridges with a VGA card are also considered critical */
799 if ((PciData
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
800 (PciData
->SubClass
== PCI_SUBCLASS_BR_PCI_TO_PCI
) &&
801 (PciData
->u
.type1
.BridgeControl
& PCI_ENABLE_BRIDGE_VGA
) &&
802 !(HackFlags
& PCI_HACK_DONT_DISABLE_DECODES
))
804 /* Do not disable their decodes either */
805 DPRINT1("Not allowing PM because device is VGA\n");
806 HackFlags
|= PCI_HACK_CRITICAL_DEVICE
;
809 /* Check if the device should be skipped for whatever reason */
810 if (PciSkipThisFunction(PciData
,
812 PCI_SKIP_DEVICE_ENUMERATION
,
815 /* Skip this device */
819 /* Check if a PDO has already been created for this device */
820 PdoExtension
= PciFindPdoByFunction(DeviceExtension
,
825 /* Rescan scenarios are not yet implemented */
830 /* Bus processing will need to happen */
833 /* Create the PDO for this device */
834 Status
= PciPdoCreate(DeviceExtension
, PciSlot
, &DeviceObject
);
835 ASSERT(NT_SUCCESS(Status
));
836 NewExtension
= (PPCI_PDO_EXTENSION
)DeviceObject
->DeviceExtension
;
838 /* Check for broken devices with wrong/no class codes */
839 if (HackFlags
& PCI_HACK_FAKE_CLASS_CODE
)
841 /* Setup a default one */
842 PciData
->BaseClass
= PCI_CLASS_BASE_SYSTEM_DEV
;
843 PciData
->SubClass
= PCI_SUBCLASS_SYS_OTHER
;
845 /* Device will behave erratically when reading back data */
846 NewExtension
->ExpectedWritebackFailure
= TRUE
;
849 /* Clone all the information from the header */
850 NewExtension
->VendorId
= PciData
->VendorID
;
851 NewExtension
->DeviceId
= PciData
->DeviceID
;
852 NewExtension
->RevisionId
= PciData
->RevisionID
;
853 NewExtension
->ProgIf
= PciData
->ProgIf
;
854 NewExtension
->SubClass
= PciData
->SubClass
;
855 NewExtension
->BaseClass
= PciData
->BaseClass
;
856 NewExtension
->HeaderType
= PCI_CONFIGURATION_TYPE(PciData
);
858 /* Check for modern bridge types, which are managed by the driver */
859 if ((NewExtension
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
860 ((NewExtension
->SubClass
== PCI_SUBCLASS_BR_PCI_TO_PCI
) ||
861 (NewExtension
->SubClass
== PCI_SUBCLASS_BR_CARDBUS
)))
863 /* Acquire this device's lock */
864 KeEnterCriticalRegion();
865 KeWaitForSingleObject(&DeviceExtension
->ChildListLock
,
871 /* Scan the bridge list until the first free entry */
872 for (BridgeExtension
= &DeviceExtension
->ChildBridgePdoList
;
874 BridgeExtension
= &(*BridgeExtension
)->NextBridge
);
876 /* Add this PDO as a bridge */
877 *BridgeExtension
= NewExtension
;
878 ASSERT(NewExtension
->NextBridge
== NULL
);
880 /* Release this device's lock */
881 KeSetEvent(&DeviceExtension
->ChildListLock
,
884 KeLeaveCriticalRegion();
887 /* Get the PCI BIOS configuration saved in the registry */
888 Status
= PciGetBiosConfig(NewExtension
, BiosData
);
889 if (NT_SUCCESS(Status
))
891 /* This path has not yet been fully tested by eVb */
892 DPRINT1("Have BIOS configuration!\n");
895 /* Check if the PCI BIOS configuration has changed */
896 if (!PcipIsSameDevice(NewExtension
, BiosData
))
898 /* This is considered failure, and new data will be saved */
899 Status
= STATUS_UNSUCCESSFUL
;
903 /* Data is still correct, check for interrupt line change */
904 if (BiosData
->u
.type0
.InterruptLine
!=
905 PciData
->u
.type0
.InterruptLine
)
907 /* Update the current BIOS with the saved interrupt line */
908 PciWriteDeviceConfig(NewExtension
,
909 &BiosData
->u
.type0
.InterruptLine
,
910 FIELD_OFFSET(PCI_COMMON_HEADER
,
911 u
.type0
.InterruptLine
),
915 /* Save the BIOS interrupt line and the initial command */
916 NewExtension
->RawInterruptLine
= BiosData
->u
.type0
.InterruptLine
;
917 NewExtension
->InitialCommand
= BiosData
->Command
;
921 /* Check if no saved data was present or if it was a mismatch */
922 if (!NT_SUCCESS(Status
))
924 /* Save the new data */
925 Status
= PciSaveBiosConfig(NewExtension
, PciData
);
926 ASSERT(NT_SUCCESS(Status
));
928 /* Save the interrupt line and command from the device */
929 NewExtension
->RawInterruptLine
= PciData
->u
.type0
.InterruptLine
;
930 NewExtension
->InitialCommand
= PciData
->Command
;
933 /* Save original command from the device and hack flags */
934 NewExtension
->CommandEnables
= PciData
->Command
;
935 NewExtension
->HackFlags
= HackFlags
;
937 /* Get power, AGP, and other capability data */
938 PciGetEnhancedCapabilities(NewExtension
, PciData
);
940 /* Power up the device */
941 PciSetPowerManagedDevicePowerState(NewExtension
, PowerDeviceD0
, FALSE
);
943 /* Apply any device hacks required for enumeration */
944 PciApplyHacks(DeviceExtension
,
947 PCI_HACK_FIXUP_AFTER_CONFIGURATION
,
950 /* Save interrupt pin */
951 NewExtension
->InterruptPin
= PciData
->u
.type0
.InterruptPin
;
954 * Use either this device's actual IRQ line or, if it's connected on
955 * a master bus whose IRQ line is actually connected to the host, use
956 * the HAL to query the bus' IRQ line and store that as the adjusted
957 * interrupt line instead
959 NewExtension
->AdjustedInterruptLine
= PciGetAdjustedInterruptLine(NewExtension
);
961 /* Check if this device is used for PCI debugger cards */
962 NewExtension
->OnDebugPath
= PciIsDeviceOnDebugPath(NewExtension
);
964 /* Check for devices with invalid/bogus subsystem data */
965 if (HackFlags
& PCI_HACK_NO_SUBSYSTEM
)
967 /* Set the subsystem information to zero instead */
968 NewExtension
->SubsystemVendorId
= 0;
969 NewExtension
->SubsystemId
= 0;
972 /* Scan all capabilities */
973 CapOffset
= NewExtension
->CapabilitiesPtr
;
976 /* Read this header */
977 TempOffset
= PciReadDeviceCapability(NewExtension
,
981 sizeof(PCI_CAPABILITIES_HEADER
));
982 if (TempOffset
!= CapOffset
)
984 /* This is a strange issue that shouldn't happen normally */
985 DPRINT1("PCI - Failed to read PCI capability at offset 0x%02x\n",
987 ASSERT(TempOffset
== CapOffset
);
990 /* Check for capabilities that this driver cares about */
991 switch (CapHeader
.CapabilityID
)
993 /* Power management capability is heavily used by the bus */
994 case PCI_CAPABILITY_ID_POWER_MANAGEMENT
:
996 /* Dump the capability */
998 Size
= sizeof(PCI_PM_CAPABILITY
);
1001 /* AGP capability is required for AGP bus functionality */
1002 case PCI_CAPABILITY_ID_AGP
:
1004 /* Dump the capability */
1006 Size
= sizeof(PCI_AGP_CAPABILITY
);
1009 /* This driver doesn't really use anything other than that */
1012 /* Windows prints this, we could do a translation later */
1013 Name
= "UNKNOWN CAPABILITY";
1018 /* Check if this is a capability that should be dumped */
1021 /* Read the whole capability data */
1022 TempOffset
= PciReadDeviceCapability(NewExtension
,
1024 CapHeader
.CapabilityID
,
1028 if (TempOffset
!= CapOffset
)
1030 /* Again, a strange issue that shouldn't be seen */
1031 DPRINT1("- Failed to read capability data. ***\n");
1032 ASSERT(TempOffset
== CapOffset
);
1036 /* Dump this capability */
1037 DPRINT1("CAP @%02x ID %02x (%s)\n",
1038 CapOffset
, CapHeader
.CapabilityID
, Name
);
1039 for (i
= 0; i
< Size
; i
+= 2)
1040 DPRINT1(" %04x\n", *(PUSHORT
)((ULONG_PTR
)&CapHeader
+ i
));
1043 /* Check the next capability */
1044 CapOffset
= CapHeader
.Next
;
1047 /* Check for IDE controllers */
1048 if ((NewExtension
->BaseClass
== PCI_CLASS_MASS_STORAGE_CTLR
) &&
1049 (NewExtension
->SubClass
== PCI_SUBCLASS_MSC_IDE_CTLR
))
1051 /* Do not allow them to power down completely */
1052 NewExtension
->DisablePowerDown
= TRUE
;
1056 * Check if this is a legacy bridge. Note that the i82375 PCI/EISA
1057 * bridge that is present on certain NT Alpha machines appears as
1058 * non-classified so detect it manually by scanning for its VID/PID.
1060 if (((NewExtension
->BaseClass
== PCI_CLASS_BRIDGE_DEV
) &&
1061 ((NewExtension
->SubClass
== PCI_SUBCLASS_BR_ISA
) ||
1062 (NewExtension
->SubClass
== PCI_SUBCLASS_BR_EISA
) ||
1063 (NewExtension
->SubClass
== PCI_SUBCLASS_BR_MCA
))) ||
1064 ((NewExtension
->VendorId
== 0x8086) &&
1065 (NewExtension
->DeviceId
== 0x482)))
1067 /* Do not allow these legacy bridges to be powered down */
1068 NewExtension
->DisablePowerDown
= TRUE
;
1071 /* Check if the BIOS did not configure a cache line size */
1072 if (!PciData
->CacheLineSize
)
1074 /* Check if the device is disabled */
1075 if (!(NewExtension
->CommandEnables
& (PCI_ENABLE_IO_SPACE
|
1076 PCI_ENABLE_MEMORY_SPACE
|
1077 PCI_ENABLE_BUS_MASTER
)))
1079 /* Check if this is a PCI-X device*/
1080 TempOffset
= PciReadDeviceCapability(NewExtension
,
1081 NewExtension
->CapabilitiesPtr
,
1082 PCI_CAPABILITY_ID_PCIX
,
1084 sizeof(PCI_CAPABILITIES_HEADER
));
1087 * A device with default cache line size and latency timer
1088 * settings is considered to be unconfigured. Note that on
1089 * PCI-X, the reset value of the latency timer field in the
1090 * header is 64, not 0, hence why the check for PCI-X caps
1091 * was required, and the value used here below.
1093 if (!(PciData
->LatencyTimer
) ||
1094 ((TempOffset
) && (PciData
->LatencyTimer
== 64)))
1096 /* Keep track of the fact that it needs configuration */
1097 DPRINT1("PCI - ScanBus, PDOx %x found unconfigured\n",
1099 NewExtension
->NeedsHotPlugConfiguration
= TRUE
;
1104 /* Save latency and cache size information */
1105 NewExtension
->SavedLatencyTimer
= PciData
->LatencyTimer
;
1106 NewExtension
->SavedCacheLineSize
= PciData
->CacheLineSize
;
1108 /* The PDO is now ready to go */
1109 DeviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1113 /* Enumeration is completed */
1114 return STATUS_SUCCESS
;
1119 PciQueryDeviceRelations(IN PPCI_FDO_EXTENSION DeviceExtension
,
1120 IN OUT PDEVICE_RELATIONS
*pDeviceRelations
)
1123 PPCI_PDO_EXTENSION PdoExtension
;
1125 PDEVICE_RELATIONS DeviceRelations
, NewRelations
;
1127 PDEVICE_OBJECT DeviceObject
, *ObjectArray
;
1130 /* Make sure the FDO is started */
1131 ASSERT(DeviceExtension
->DeviceState
== PciStarted
);
1133 /* Synchronize while we enumerate the bus */
1134 Status
= PciBeginStateTransition(DeviceExtension
, PciSynchronizedOperation
);
1135 if (!NT_SUCCESS(Status
)) return Status
;
1137 /* Scan all children PDO */
1138 for (PdoExtension
= DeviceExtension
->ChildPdoList
;
1140 PdoExtension
= PdoExtension
->Next
)
1142 /* Invalidate them */
1143 PdoExtension
->NotPresent
= TRUE
;
1146 /* Scan the PCI Bus */
1147 Status
= PciScanBus(DeviceExtension
);
1148 ASSERT(NT_SUCCESS(Status
));
1150 /* Enumerate all children PDO again */
1151 for (PdoExtension
= DeviceExtension
->ChildPdoList
;
1153 PdoExtension
= PdoExtension
->Next
)
1155 /* Check for PDOs that are still invalidated */
1156 if (PdoExtension
->NotPresent
)
1158 /* This means this PDO existed before, but not anymore */
1159 PdoExtension
->ReportedMissing
= TRUE
;
1160 DPRINT1("PCI - Old device (pdox) %08x not found on rescan.\n",
1165 /* Increase count of detected PDOs */
1170 /* Read the current relations and add the newly discovered relations */
1171 DeviceRelations
= *pDeviceRelations
;
1172 Size
= FIELD_OFFSET(DEVICE_RELATIONS
, Objects
) +
1173 PdoCount
* sizeof(PDEVICE_OBJECT
);
1174 if (DeviceRelations
) Size
+= sizeof(PDEVICE_OBJECT
) * DeviceRelations
->Count
;
1176 /* Allocate the device relations */
1177 NewRelations
= (PDEVICE_RELATIONS
)ExAllocatePoolWithTag(0, Size
, 'BicP');
1180 /* Out of space, cancel the operation */
1181 PciCancelStateTransition(DeviceExtension
, PciSynchronizedOperation
);
1182 return STATUS_INSUFFICIENT_RESOURCES
;
1185 /* Check if there were any older relations */
1186 NewRelations
->Count
= 0;
1187 if (DeviceRelations
)
1189 /* Copy the old relations into the new buffer, then free the old one */
1190 RtlCopyMemory(NewRelations
,
1192 FIELD_OFFSET(DEVICE_RELATIONS
, Objects
) +
1193 DeviceRelations
->Count
* sizeof(PDEVICE_OBJECT
));
1194 ExFreePoolWithTag(DeviceRelations
, 0);
1197 /* Print out that we're ready to dump relations */
1198 DPRINT1("PCI QueryDeviceRelations/BusRelations FDOx %08x (bus 0x%02x)\n",
1200 DeviceExtension
->BaseBus
);
1202 /* Loop the current PDO children and the device relation object array */
1203 PdoExtension
= DeviceExtension
->ChildPdoList
;
1204 ObjectArray
= &NewRelations
->Objects
[NewRelations
->Count
];
1205 while (PdoExtension
)
1207 /* Dump this relation */
1208 DPRINT1(" QDR PDO %08x (x %08x)%s\n",
1209 PdoExtension
->PhysicalDeviceObject
,
1211 PdoExtension
->NotPresent
?
1212 "<Omitted, device flaged not present>" : "");
1214 /* Is this PDO present? */
1215 if (!PdoExtension
->NotPresent
)
1217 /* Reference it and add it to the array */
1218 DeviceObject
= PdoExtension
->PhysicalDeviceObject
;
1219 ObfReferenceObject(DeviceObject
);
1220 *ObjectArray
++ = DeviceObject
;
1223 /* Go to the next PDO */
1224 PdoExtension
= PdoExtension
->Next
;
1227 /* Terminate dumping the relations */
1228 DPRINT1(" QDR Total PDO count = %d (%d already in list)\n",
1229 NewRelations
->Count
+ PdoCount
,
1230 NewRelations
->Count
);
1232 /* Return the final count and the new buffer */
1233 NewRelations
->Count
+= PdoCount
;
1234 *pDeviceRelations
= NewRelations
;
1235 return STATUS_SUCCESS
;