Author: evb
Date: Sat Jul 17 16:53:18 2010
New Revision: 48100
URL: http://svn.reactos.org/svn/reactos?rev=48100&view=rev
Log:
More PciScanBus codes now to check saved PCI BIOS config header saved in registry (PciGetBiosConfig, PciSaveBiosConfig) and support load save compare (PcipIsSameDevice) if change in interrupt line
Also for interrupt line use HAL to get parent bus IRQ# if device connected (PciGetAdjustedInterruptLine)
For PCI debug HW PciIsDeviceOnDebugPath to detect, but have not real machine with this kind of device to test
Support PCI_HACK_NO_SUBSYSTEM and PCI_HACK_NO_SUBSYSTEM/REVISION_AFTER_D3 for when compareing
New config function required PciWriteDeviceConfig to update IRQ line from BIOS registry data
Save initial, current Command enables to PDO extension, interrupt data too
Modified:
trunk/reactos/drivers/bus/pcix/enum.c
trunk/reactos/drivers/bus/pcix/pci.h
trunk/reactos/drivers/bus/pcix/pci/config.c
trunk/reactos/drivers/bus/pcix/utils.c
Modified: trunk/reactos/drivers/bus/pcix/enum.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/enum.c?re…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/enum.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/enum.c [iso-8859-1] Sat Jul 17 16:53:18 2010
@@ -15,6 +15,40 @@
/* GLOBALS ********************************************************************/
/* FUNCTIONS ******************************************************************/
+
+BOOLEAN
+NTAPI
+PcipIsSameDevice(IN PPCI_PDO_EXTENSION DeviceExtension,
+ IN PPCI_COMMON_HEADER PciData)
+{
+ BOOLEAN IdMatch, RevMatch, SubsysMatch;
+ ULONGLONG HackFlags = DeviceExtension->HackFlags;
+
+ /* Check if the IDs match */
+ IdMatch = (PciData->VendorID == DeviceExtension->VendorId) &&
+ (PciData->DeviceID == DeviceExtension->DeviceId);
+ if (!IdMatch) return FALSE;
+
+ /* If the device has a valid revision, check if it matches */
+ RevMatch = (HackFlags & PCI_HACK_NO_REVISION_AFTER_D3) ||
+ (PciData->RevisionID == DeviceExtension->RevisionId);
+ if (!RevMatch) return FALSE;
+
+ /* For multifunction devices, this is enough to assume they're the same */
+ if (PCI_MULTIFUNCTION_DEVICE(PciData)) return TRUE;
+
+ /* For bridge devices, there's also nothing else that can be checked */
+ if (DeviceExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) return TRUE;
+
+ /* Devices, on the other hand, have subsystem data that can be compared */
+ SubsysMatch = (HackFlags & (PCI_HACK_NO_SUBSYSTEM |
+ PCI_HACK_NO_SUBSYSTEM_AFTER_D3)) ||
+ ((DeviceExtension->SubsystemVendorId ==
+ PciData->u.type0.SubVendorID) &&
+ (DeviceExtension->SubsystemId ==
+ PciData->u.type0.SubSystemID));
+ return SubsysMatch;
+}
BOOLEAN
NTAPI
@@ -100,7 +134,9 @@
LONGLONG HackFlags;
PDEVICE_OBJECT DeviceObject;
UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
+ UCHAR BiosBuffer[PCI_COMMON_HDR_LENGTH];
PPCI_COMMON_HEADER PciData = (PVOID)Buffer;
+ PPCI_COMMON_HEADER BiosData = (PVOID)BiosBuffer;
PCI_SLOT_NUMBER PciSlot;
NTSTATUS Status;
PPCI_PDO_EXTENSION PdoExtension, NewExtension;
@@ -160,7 +196,8 @@
/* Find description for this device for the debugger's sake */
DescriptionText = PciGetDeviceDescriptionMessage(PciData->BaseClass,
PciData->SubClass);
- DPRINT1("Device Description \"%S\".\n", DescriptionText ? DescriptionText : L"(NULL)");
+ DPRINT1("Device Description \"%S\".\n",
+ DescriptionText ? DescriptionText : L"(NULL)");
if (DescriptionText) ExFreePoolWithTag(DescriptionText, 0);
/* Check if there is an ACPI Watchdog Table */
@@ -258,7 +295,7 @@
NewExtension->BaseClass = PciData->BaseClass;
NewExtension->HeaderType = PCI_CONFIGURATION_TYPE(PciData);
- /* Check for PCI or Cardbus bridges, which are supported by this driver */
+ /* Check for modern bridge types, which are managed by the driver */
if ((NewExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
((NewExtension->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI) ||
(NewExtension->SubClass == PCI_SUBCLASS_BR_CARDBUS)))
@@ -281,10 +318,84 @@
ASSERT(NewExtension->NextBridge == NULL);
/* Release this device's lock */
- KeSetEvent(&DeviceExtension->ChildListLock, IO_NO_INCREMENT, FALSE);
+ KeSetEvent(&DeviceExtension->ChildListLock,
+ IO_NO_INCREMENT,
+ FALSE);
KeLeaveCriticalRegion();
}
-
+
+ /* Get the PCI BIOS configuration saved in the registry */
+ Status = PciGetBiosConfig(NewExtension, BiosData);
+ if (NT_SUCCESS(Status))
+ {
+ /* This path has not yet been fully tested by eVb */
+ DPRINT1("Have BIOS configuration!\n");
+ UNIMPLEMENTED;
+
+ /* Check if the PCI BIOS configuration has changed */
+ if (!PcipIsSameDevice(NewExtension, BiosData))
+ {
+ /* This is considered failure, and new data will be saved */
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ /* Data is still correct, check for interrupt line change */
+ if (BiosData->u.type0.InterruptLine !=
+ PciData->u.type0.InterruptLine)
+ {
+ /* Update the current BIOS with the saved interrupt line */
+ PciWriteDeviceConfig(NewExtension,
+ &BiosData->u.type0.InterruptLine,
+ FIELD_OFFSET(PCI_COMMON_HEADER,
+ u.type0.InterruptLine),
+ sizeof(UCHAR));
+ }
+
+ /* Save the BIOS interrupt line and the initial command */
+ NewExtension->RawInterruptLine = BiosData->u.type0.InterruptLine;
+ NewExtension->InitialCommand = BiosData->Command;
+ }
+ }
+
+ /* Check if no saved data was present or if it was a mismatch */
+ if (!NT_SUCCESS(Status))
+ {
+ /* Save the new data */
+ Status = PciSaveBiosConfig(NewExtension, PciData);
+ ASSERT(NT_SUCCESS(Status));
+
+ /* Save the interrupt line and command from the device */
+ NewExtension->RawInterruptLine = PciData->u.type0.InterruptLine;
+ NewExtension->InitialCommand = PciData->Command;
+ }
+
+ /* Save original command from the device and hack flags */
+ NewExtension->CommandEnables = PciData->Command;
+ NewExtension->HackFlags = HackFlags;
+
+ /* Save interrupt pin */
+ NewExtension->InterruptPin = PciData->u.type0.InterruptPin;
+
+ /*
+ * Use either this device's actual IRQ line or, if it's connected on
+ * a master bus whose IRQ line is actually connected to the host, use
+ * the HAL to query the bus' IRQ line and store that as the adjusted
+ * interrupt line instead
+ */
+ NewExtension->AdjustedInterruptLine = PciGetAdjustedInterruptLine(NewExtension);
+
+ /* Check if this device is used for PCI debugger cards */
+ NewExtension->OnDebugPath = PciIsDeviceOnDebugPath(NewExtension);
+
+ /* Check for devices with invalid/bogus subsystem data */
+ if (HackFlags & PCI_HACK_NO_SUBSYSTEM)
+ {
+ /* Set the subsystem information to zero instead */
+ NewExtension->SubsystemVendorId = 0;
+ NewExtension->SubsystemId = 0;
+ }
+
/* Check for IDE controllers */
if ((NewExtension->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
(NewExtension->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
@@ -292,26 +403,27 @@
/* Do not allow them to power down completely */
NewExtension->DisablePowerDown = TRUE;
}
-
+
/*
* Check if this is a legacy bridge. Note that the i82375 PCI/EISA
- * bridge that is present on certain NT Alpha machines appears as
+ * bridge that is present on certain NT Alpha machines appears as
* non-classified so detect it manually by scanning for its VID/PID.
*/
if (((NewExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
((NewExtension->SubClass == PCI_SUBCLASS_BR_ISA) ||
(NewExtension->SubClass == PCI_SUBCLASS_BR_EISA) ||
(NewExtension->SubClass == PCI_SUBCLASS_BR_MCA))) ||
- ((NewExtension->VendorId == 0x8086) && (NewExtension->DeviceId == 0x482)))
+ ((NewExtension->VendorId == 0x8086) &&
+ (NewExtension->DeviceId == 0x482)))
{
/* Do not allow these legacy bridges to be powered down */
NewExtension->DisablePowerDown = TRUE;
}
-
+
/* Save latency and cache size information */
NewExtension->SavedLatencyTimer = PciData->LatencyTimer;
NewExtension->SavedCacheLineSize = PciData->CacheLineSize;
-
+
/* The PDO is now ready to go */
DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
}
Modified: trunk/reactos/drivers/bus/pcix/pci.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci.h?rev…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] Sat Jul 17 16:53:18 2010
@@ -57,10 +57,15 @@
#define PCI_INTERFACE_ROOT 0x04
//
-// PCI Skip Function FLags
+// PCI Skip Function Flags
//
#define PCI_SKIP_DEVICE_ENUMERATION 0x01
#define PCI_SKIP_RESOURCE_ENUMERATION 0x02
+
+//
+// PCI Debugging Device Support
+//
+#define MAX_DEBUGGING_DEVICES_SUPPORTED 0x04
//
// Device Extension, Interface, Translator and Arbiter Signatures
@@ -900,6 +905,26 @@
IN UCHAR SubClass
);
+BOOLEAN
+NTAPI
+PciIsDeviceOnDebugPath(
+ IN PPCI_PDO_EXTENSION DeviceExtension
+);
+
+NTSTATUS
+NTAPI
+PciGetBiosConfig(
+ IN PPCI_PDO_EXTENSION DeviceExtension,
+ OUT PPCI_COMMON_HEADER PciData
+);
+
+NTSTATUS
+NTAPI
+PciSaveBiosConfig(
+ IN PPCI_PDO_EXTENSION DeviceExtension,
+ OUT PPCI_COMMON_HEADER PciData
+);
+
//
// Configuration Routines
//
@@ -917,6 +942,21 @@
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length
+);
+
+VOID
+NTAPI
+PciWriteDeviceConfig(
+ IN PPCI_PDO_EXTENSION DeviceExtension,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length
+);
+
+UCHAR
+NTAPI
+PciGetAdjustedInterruptLine(
+ IN PPCI_PDO_EXTENSION PdoExtension
);
//
Modified: trunk/reactos/drivers/bus/pcix/pci/config.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci/confi…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pci/config.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pci/config.c [iso-8859-1] Sat Jul 17 16:53:18 2010
@@ -18,6 +18,31 @@
/* FUNCTIONS ******************************************************************/
+UCHAR
+NTAPI
+PciGetAdjustedInterruptLine(IN PPCI_PDO_EXTENSION PdoExtension)
+{
+ UCHAR InterruptLine = 0, PciInterruptLine;
+ ULONG Length;
+
+ /* Does the device have an interrupt pin? */
+ if (PdoExtension->InterruptPin)
+ {
+ /* Find the associated line on the parent bus */
+ Length = HalGetBusDataByOffset(PCIConfiguration,
+ PdoExtension->ParentFdoExtension->BaseBus,
+ PdoExtension->Slot.u.AsULONG,
+ &PciInterruptLine,
+ FIELD_OFFSET(PCI_COMMON_HEADER,
+ u.type0.InterruptLine),
+ sizeof(UCHAR));
+ if (Length) InterruptLine = PciInterruptLine;
+ }
+
+ /* Either keep the original interrupt line, or the one on the master bus */
+ return InterruptLine ? PdoExtension->RawInterruptLine : InterruptLine;
+}
+
VOID
NTAPI
PciReadWriteConfigSpace(IN PPCI_FDO_EXTENSION DeviceExtension,
@@ -59,6 +84,22 @@
HalFunction = Read ? BusData->ReadConfig : BusData->WriteConfig;
HalFunction(BusHandler, Slot, Buffer, Offset, Length);
}
+}
+
+VOID
+NTAPI
+PciWriteDeviceConfig(IN PPCI_PDO_EXTENSION DeviceExtension,
+ IN PVOID Buffer,
+ IN ULONG Offset,
+ IN ULONG Length)
+{
+ /* Call the generic worker function */
+ PciReadWriteConfigSpace(DeviceExtension->ParentFdoExtension,
+ DeviceExtension->Slot,
+ Buffer,
+ Offset,
+ Length,
+ FALSE);
}
VOID
Modified: trunk/reactos/drivers/bus/pcix/utils.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/utils.c?r…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] Sat Jul 17 16:53:18 2010
@@ -13,6 +13,8 @@
#include <debug.h>
/* GLOBALS ********************************************************************/
+
+ULONG PciDebugPortsCount;
RTL_RANGE_LIST PciIsaBitExclusionList;
RTL_RANGE_LIST PciVgaAndIsaBitExclusionList;
@@ -741,4 +743,137 @@
return PdoExtension;
}
+BOOLEAN
+NTAPI
+PciIsDeviceOnDebugPath(IN PPCI_PDO_EXTENSION DeviceExtension)
+{
+ PAGED_CODE();
+
+ /* Check for too many, or no, debug ports */
+ ASSERT(PciDebugPortsCount <= MAX_DEBUGGING_DEVICES_SUPPORTED);
+ if (!PciDebugPortsCount) return FALSE;
+
+ /* eVb has not been able to test such devices yet */
+ UNIMPLEMENTED;
+ while (TRUE);
+}
+
+NTSTATUS
+NTAPI
+PciGetBiosConfig(IN PPCI_PDO_EXTENSION DeviceExtension,
+ OUT PPCI_COMMON_HEADER PciData)
+{
+ HANDLE KeyHandle, SubKeyHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName, KeyValue;
+ WCHAR Buffer[32];
+ WCHAR DataBuffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + PCI_COMMON_HDR_LENGTH];
+ PKEY_VALUE_PARTIAL_INFORMATION PartialInfo = (PVOID)DataBuffer;
+ NTSTATUS Status;
+ ULONG ResultLength;
+ PAGED_CODE();
+
+ /* Open the PCI key */
+ Status = IoOpenDeviceRegistryKey(DeviceExtension->ParentFdoExtension->
+ PhysicalDeviceObject,
+ TRUE,
+ KEY_ALL_ACCESS,
+ &KeyHandle);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Create a volatile BIOS configuration key */
+ RtlInitUnicodeString(&KeyName, L"BiosConfig");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_KERNEL_HANDLE,
+ KeyHandle,
+ NULL);
+ Status = ZwCreateKey(&SubKeyHandle,
+ KEY_READ,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ NULL);
+ ZwClose(KeyHandle);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Create the key value based on the device and function number */
+ swprintf(Buffer,
+ L"DEV_%02x&FUN_%02x",
+ DeviceExtension->Slot.u.bits.DeviceNumber,
+ DeviceExtension->Slot.u.bits.FunctionNumber);
+ RtlInitUnicodeString(&KeyValue, Buffer);
+
+ /* Query the value information (PCI BIOS configuration header) */
+ Status = ZwQueryValueKey(SubKeyHandle,
+ &KeyValue,
+ KeyValuePartialInformation,
+ PartialInfo,
+ sizeof(DataBuffer),
+ &ResultLength);
+ ZwClose(SubKeyHandle);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* If any information was returned, go ahead and copy its data */
+ ASSERT(PartialInfo->DataLength == PCI_COMMON_HDR_LENGTH);
+ RtlCopyMemory(PciData, PartialInfo->Data, PCI_COMMON_HDR_LENGTH);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+PciSaveBiosConfig(IN PPCI_PDO_EXTENSION DeviceExtension,
+ IN PPCI_COMMON_HEADER PciData)
+{
+ HANDLE KeyHandle, SubKeyHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName, KeyValue;
+ WCHAR Buffer[32];
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ /* Open the PCI key */
+ Status = IoOpenDeviceRegistryKey(DeviceExtension->ParentFdoExtension->
+ PhysicalDeviceObject,
+ TRUE,
+ KEY_READ | KEY_WRITE,
+ &KeyHandle);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Create a volatile BIOS configuration key */
+ RtlInitUnicodeString(&KeyName, L"BiosConfig");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_KERNEL_HANDLE,
+ KeyHandle,
+ NULL);
+ Status = ZwCreateKey(&SubKeyHandle,
+ KEY_READ | KEY_WRITE,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ NULL);
+ ZwClose(KeyHandle);
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Create the key value based on the device and function number */
+ swprintf(Buffer,
+ L"DEV_%02x&FUN_%02x",
+ DeviceExtension->Slot.u.bits.DeviceNumber,
+ DeviceExtension->Slot.u.bits.FunctionNumber);
+ RtlInitUnicodeString(&KeyValue, Buffer);
+
+ /* Set the value data (the PCI BIOS configuration header) */
+ Status = ZwSetValueKey(SubKeyHandle,
+ &KeyValue,
+ 0,
+ REG_BINARY,
+ PciData,
+ PCI_COMMON_HDR_LENGTH);
+ ZwClose(SubKeyHandle);
+ return Status;
+}
+
/* EOF */
Author: evb
Date: Sat Jul 17 15:09:19 2010
New Revision: 48098
URL: http://svn.reactos.org/svn/reactos?rev=48098&view=rev
Log:
More implement of PciScanBus, now read hack flags from table (PciGetHAckFlags), and check for critical device (PciIsCriticalDeviceClass) and VGA device on PCI bridge
Do check for skipping some function (double decker ghost, Intel Alder SMP Pentium Pro machine, hacl flag, more), PciSkipThisfunction
Do check for PDO already exist for function (PciFindPdoByFunction)
Finish impement PciFindParentPciFdoExtension
Modified:
trunk/reactos/drivers/bus/pcix/enum.c
trunk/reactos/drivers/bus/pcix/fdo.c
trunk/reactos/drivers/bus/pcix/pci.h
trunk/reactos/drivers/bus/pcix/utils.c
Modified: trunk/reactos/drivers/bus/pcix/enum.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/enum.c?re…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/enum.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/enum.c [iso-8859-1] Sat Jul 17 15:09:19 2010
@@ -16,16 +16,93 @@
/* FUNCTIONS ******************************************************************/
+BOOLEAN
+NTAPI
+PciSkipThisFunction(IN PPCI_COMMON_HEADER PciData,
+ IN PCI_SLOT_NUMBER Slot,
+ IN UCHAR OperationType,
+ IN ULONGLONG HackFlags)
+{
+ do
+ {
+ /* Check if this is device enumeration */
+ if (OperationType == PCI_SKIP_DEVICE_ENUMERATION)
+ {
+ /* Check if there's a hackflag saying not to enumerate this device */
+ if (HackFlags & PCI_HACK_NO_ENUM_AT_ALL) break;
+
+ /* Check if this is the high end of a double decker device */
+ if ((HackFlags & PCI_HACK_DOUBLE_DECKER) &&
+ (Slot.u.bits.DeviceNumber >= 16))
+ {
+ /* It belongs to the same device, so skip it */
+ DPRINT1(" Device (Ven %04x Dev %04x (d=0x%x, f=0x%x)) is a ghost.\n",
+ PciData->VendorID,
+ PciData->DeviceID,
+ Slot.u.bits.DeviceNumber,
+ Slot.u.bits.FunctionNumber);
+ break;
+ }
+ }
+ else if (OperationType == PCI_SKIP_RESOURCE_ENUMERATION)
+ {
+ /* Resource enumeration, check for a hackflag saying not to do it */
+ if (HackFlags & PCI_HACK_ENUM_NO_RESOURCE) break;
+ }
+ else
+ {
+ /* Logic error in the driver */
+ ASSERTMSG(FALSE, "PCI Skip Function - Operation type unknown.");
+ }
+
+ /* Check for legacy bridges during resource enumeration */
+ if ((PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
+ (PciData->SubClass <= PCI_SUBCLASS_BR_MCA) &&
+ (OperationType == PCI_SKIP_RESOURCE_ENUMERATION))
+ {
+ /* Their resources are not enumerated, only PCI and Cardbus/PCMCIA */
+ break;
+ }
+ else if (PciData->BaseClass == PCI_CLASS_NOT_DEFINED)
+ {
+ /* Undefined base class (usually a PCI BIOS/ROM bug) */
+ DPRINT1(" Vendor %04x, Device %04x has class code of PCI_CLASS_NOT_DEFINED\n",
+ PciData->VendorID,
+ PciData->DeviceID);
+
+ /*
+ * The Alder has an Intel Extended Express System Support Controller
+ * which presents apparently spurious BARs. When the PCI resource
+ * code tries to reassign these BARs, the second IO-APIC gets
+ * disabled (with disastrous consequences). The first BAR is the
+ * actual IO-APIC, the remaining five bars seem to be spurious
+ * resources, so ignore this device completely.
+ */
+ if ((PciData->VendorID == 0x8086) && (PciData->DeviceID == 8)) break;
+ }
+
+ /* Other normal PCI cards and bridges are enumerated */
+ if (PCI_CONFIGURATION_TYPE(PciData) <= PCI_CARDBUS_BRIDGE_TYPE) return FALSE;
+ } while (FALSE);
+
+ /* Hit one of the known bugs/hackflags, or this is a new kind of PCI unit */
+ DPRINT1(" Device skipped (not enumerated).\n");
+ return TRUE;
+}
+
NTSTATUS
NTAPI
PciScanBus(IN PPCI_FDO_EXTENSION DeviceExtension)
{
ULONG MaxDevice = PCI_MAX_DEVICES;
ULONG i, j, k;
+ LONGLONG HackFlags;
UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
PPCI_COMMON_HEADER PciData = (PVOID)Buffer;
PCI_SLOT_NUMBER PciSlot;
PWCHAR DescriptionText;
+ USHORT SubVendorId, SubSystemId;
+ PPCI_PDO_EXTENSION PdoExtension;
DPRINT1("PCI Scan Bus: FDO Extension @ 0x%x, Base Bus = 0x%x\n",
DeviceExtension, DeviceExtension->BaseBus);
@@ -86,6 +163,65 @@
if (WdTable)
{
/* Check if this PCI device is the ACPI Watchdog Device... */
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
+
+ /* Check for non-simple devices */
+ if ((PCI_MULTIFUNCTION_DEVICE(PciData)) ||
+ (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV))
+ {
+ /* No subsystem data defined for these kinds of bridges */
+ SubVendorId = 0;
+ SubSystemId = 0;
+ }
+ else
+ {
+ /* Read the subsystem information from the PCI header */
+ SubVendorId = PciData->u.type0.SubVendorID;
+ SubSystemId = PciData->u.type0.SubSystemID;
+ }
+
+ /* Get any hack flags for this device */
+ HackFlags = PciGetHackFlags(PciData->VendorID,
+ PciData->DeviceID,
+ SubVendorId,
+ SubSystemId,
+ PciData->RevisionID);
+
+ /* Check if this device is considered critical by the OS */
+ if (PciIsCriticalDeviceClass(PciData->BaseClass, PciData->SubClass))
+ {
+ /* Check if normally the decodes would be disabled */
+ if (!(HackFlags & PCI_HACK_DONT_DISABLE_DECODES))
+ {
+ /* Because this device is critical, don't disable them */
+ DPRINT1("Not allowing PM Because device is critical\n");
+ HackFlags |= PCI_HACK_CRITICAL_DEVICE;
+ }
+ }
+
+ /* PCI bridges with a VGA card are also considered critical */
+ if ((PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
+ (PciData->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI) &&
+ (PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) &&
+ !(HackFlags & PCI_HACK_DONT_DISABLE_DECODES))
+ {
+ /* Do not disable their decodes either */
+ DPRINT1("Not allowing PM because device is VGA\n");
+ HackFlags |= PCI_HACK_CRITICAL_DEVICE;
+ }
+
+ /* Also skip devices that should not be enumerated */
+ if (PciSkipThisFunction(PciData, PciSlot, 1, HackFlags)) continue;
+
+ /* Check if a PDO has already been created for this device */
+ PdoExtension = PciFindPdoByFunction(DeviceExtension,
+ PciSlot.u.bits.FunctionNumber,
+ PciData);
+ if (PdoExtension)
+ {
+ /* Rescan scenarios are not yet implemented */
UNIMPLEMENTED;
while (TRUE);
}
Modified: trunk/reactos/drivers/bus/pcix/fdo.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/fdo.c?rev…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/fdo.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/fdo.c [iso-8859-1] Sat Jul 17 15:09:19 2010
@@ -506,11 +506,15 @@
if (PciBreakOnDefault)
{
/* If a second bus is found and there's still no data, crash */
+ #if 0 // ros bug?
KeBugCheckEx(PCI_BUS_DRIVER_INTERNAL,
0xDEAD0010u,
(ULONG_PTR)DeviceObject,
0,
0);
+ #else
+ DPRINT1("Windows would crash!\n");
+ #endif
}
/* Warn that a default configuration will be used, and set bus 0 */
Modified: trunk/reactos/drivers/bus/pcix/pci.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci.h?rev…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] Sat Jul 17 15:09:19 2010
@@ -55,6 +55,12 @@
#define PCI_INTERFACE_PDO 0x01
#define PCI_INTERFACE_FDO 0x02
#define PCI_INTERFACE_ROOT 0x04
+
+//
+// PCI Skip Function FLags
+//
+#define PCI_SKIP_DEVICE_ENUMERATION 0x01
+#define PCI_SKIP_RESOURCE_ENUMERATION 0x02
//
// Device Extension, Interface, Translator and Arbiter Signatures
@@ -657,6 +663,31 @@
IN PCI_SIGNATURE ExtensionType
);
+ULONGLONG
+NTAPI
+PciGetHackFlags(
+ IN USHORT VendorId,
+ IN USHORT DeviceId,
+ IN USHORT SubVendorId,
+ IN USHORT SubSystemId,
+ IN UCHAR RevisionId
+);
+
+PPCI_PDO_EXTENSION
+NTAPI
+PciFindPdoByFunction(
+ IN PPCI_FDO_EXTENSION DeviceExtension,
+ IN ULONG FunctionNumber,
+ IN PPCI_COMMON_HEADER PciData
+);
+
+BOOLEAN
+NTAPI
+PciIsCriticalDeviceClass(
+ IN UCHAR BaseClass,
+ IN UCHAR SubClass
+);
+
//
// Configuration Routines
//
@@ -1000,5 +1031,6 @@
extern PCI_INTERFACE TranslatorInterfaceInterrupt;
extern PDRIVER_OBJECT PciDriverObject;
extern PWATCHDOG_TABLE WdTable;
+extern PPCI_HACK_ENTRY PciHackTable;
/* EOF */
Modified: trunk/reactos/drivers/bus/pcix/utils.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/utils.c?r…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] Sat Jul 17 15:09:19 2010
@@ -338,9 +338,11 @@
PciFindParentPciFdoExtension(IN PDEVICE_OBJECT DeviceObject,
IN PKEVENT Lock)
{
- PPCI_FDO_EXTENSION FoundExtension;
+ PPCI_FDO_EXTENSION DeviceExtension;
+ PPCI_PDO_EXTENSION SearchExtension, FoundExtension;
/* Assume we'll find nothing */
+ SearchExtension = DeviceObject->DeviceExtension;
FoundExtension = NULL;
/* Check if a lock was specified */
@@ -352,11 +354,31 @@
}
/* Now search for the extension */
- if (PciFdoExtensionListHead.Next)
- {
- /* This case should not be hit yet */
- UNIMPLEMENTED;
- while (TRUE);
+ DeviceExtension = (PPCI_FDO_EXTENSION)PciFdoExtensionListHead.Next;
+ while (DeviceExtension)
+ {
+ /* Acquire this device's lock */
+ KeEnterCriticalRegion();
+ KeWaitForSingleObject(&DeviceExtension->ChildListLock,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+
+ /* Scan all children PDO, stop when no more PDOs, or found it */
+ for (FoundExtension = DeviceExtension->ChildPdoList;
+ FoundExtension && (FoundExtension != SearchExtension);
+ FoundExtension = FoundExtension->Next);
+
+ /* If we found it, break out */
+ if (FoundExtension) break;
+
+ /* Release this device's lock */
+ KeSetEvent(&DeviceExtension->ChildListLock, IO_NO_INCREMENT, FALSE);
+ KeLeaveCriticalRegion();
+
+ /* Move to the next device */
+ DeviceExtension = (PPCI_FDO_EXTENSION)DeviceExtension->List.Next;
}
/* Check if we had acquired a lock previously */
@@ -368,7 +390,7 @@
}
/* Return which extension was found, if any */
- return FoundExtension;
+ return DeviceExtension;
}
VOID
@@ -575,4 +597,148 @@
return NULL;
}
+ULONGLONG
+NTAPI
+PciGetHackFlags(IN USHORT VendorId,
+ IN USHORT DeviceId,
+ IN USHORT SubVendorId,
+ IN USHORT SubSystemId,
+ IN UCHAR RevisionId)
+{
+ PPCI_HACK_ENTRY HackEntry;
+ ULONGLONG HackFlags;
+ ULONG LastWeight, MatchWeight;
+ ULONG EntryFlags;
+
+ /* Initialize the variables before looping */
+ LastWeight = 0;
+ HackFlags = 0;
+ ASSERT(PciHackTable);
+
+ /* Scan the hack table */
+ for (HackEntry = PciHackTable;
+ HackEntry->VendorID != PCI_INVALID_VENDORID;
+ ++HackEntry)
+ {
+ /* Check if there's an entry for this device */
+ if ((HackEntry->DeviceID == DeviceId) &&
+ (HackEntry->VendorID == VendorId))
+ {
+ /* This is a basic match */
+ EntryFlags = HackEntry->Flags;
+ MatchWeight = 1;
+
+ /* Does the entry have revision information? */
+ if (EntryFlags & PCI_HACK_HAS_REVISION_INFO)
+ {
+ /* Check if the revision matches, if so, this is a better match */
+ if (HackEntry->RevisionID != RevisionId) continue;
+ MatchWeight = 3;
+ }
+
+ /* Does the netry have subsystem information? */
+ if (EntryFlags & PCI_HACK_HAS_SUBSYSTEM_INFO)
+ {
+ /* Check if it matches, if so, this is the best possible match */
+ if ((HackEntry->SubVendorID != SubVendorId) ||
+ (HackEntry->SubSystemID != SubSystemId))
+ {
+ continue;
+ }
+ MatchWeight += 4;
+ }
+
+ /* Is this the best match yet? */
+ if (MatchWeight > LastWeight)
+ {
+ /* This is the best match for now, use this as the hack flags */
+ HackFlags = HackEntry->HackFlags;
+ LastWeight = MatchWeight;
+ }
+ }
+ }
+
+ /* Return the best match */
+ return HackFlags;
+}
+
+BOOLEAN
+NTAPI
+PciIsCriticalDeviceClass(IN UCHAR BaseClass,
+ IN UCHAR SubClass)
+{
+ /* Check for system or bridge devices */
+ if (BaseClass == PCI_CLASS_BASE_SYSTEM_DEV)
+ {
+ /* Interrupt controlers are critical */
+ return SubClass == PCI_SUBCLASS_SYS_INTERRUPT_CTLR;
+ }
+ else if (BaseClass == PCI_CLASS_BRIDGE_DEV)
+ {
+ /* ISA Bridges are critical */
+ return SubClass == PCI_SUBCLASS_BR_ISA;
+ }
+ else
+ {
+ /* All display controllers are critical */
+ return BaseClass == PCI_CLASS_DISPLAY_CTLR;
+ }
+}
+
+PPCI_PDO_EXTENSION
+NTAPI
+PciFindPdoByFunction(IN PPCI_FDO_EXTENSION DeviceExtension,
+ IN ULONG FunctionNumber,
+ IN PPCI_COMMON_HEADER PciData)
+{
+ KIRQL Irql;
+ PPCI_PDO_EXTENSION PdoExtension;
+
+ /* Get the current IRQL when this call was made */
+ Irql = KeGetCurrentIrql();
+
+ /* Is this a low-IRQL call? */
+ if (Irql < DISPATCH_LEVEL)
+ {
+ /* Acquire this device's lock */
+ KeEnterCriticalRegion();
+ KeWaitForSingleObject(&DeviceExtension->ChildListLock,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ }
+
+ /* Loop every child PDO */
+ for (PdoExtension = DeviceExtension->ChildPdoList;
+ PdoExtension;
+ PdoExtension = PdoExtension->Next)
+ {
+ /* Find only enumerated PDOs */
+ if (!PdoExtension->ReportedMissing)
+ {
+ /* Check if the function number and header data matches */
+ if ((FunctionNumber == PdoExtension->Slot.u.bits.FunctionNumber) &&
+ (PdoExtension->VendorId == PciData->VendorID) &&
+ (PdoExtension->DeviceId == PciData->DeviceID) &&
+ (PdoExtension->RevisionId == PciData->RevisionID))
+ {
+ /* This is considered to be the same PDO */
+ break;
+ }
+ }
+ }
+
+ /* Was this a low-IRQL call? */
+ if (Irql < DISPATCH_LEVEL)
+ {
+ /* Release this device's lock */
+ KeSetEvent(&DeviceExtension->ChildListLock, IO_NO_INCREMENT, FALSE);
+ KeLeaveCriticalRegion();
+ }
+
+ /* If the search found something, this is non-NULL, otherwise it's NULL */
+ return PdoExtension;
+}
+
/* EOF */