Author: evb
Date: Sat Aug 14 17:09:20 2010
New Revision: 48548
URL:
http://svn.reactos.org/svn/reactos?rev=48548&view=rev
Log:
- Add support for PnP IRP to PDO: IRP_MN_QUERY_BUS_INFORMATION (PciQueryBusInformation),
IRP_MN_QUERY_ID (PciQueryId), IRP_MN_QUERY_DEVICE_TEXT (PciQueryDeviceText),
IRP_MN_QUERY_CAPABILITIES (PciQueryCapabilities), IRP_MN_QUERY_DEVICE_RELATIONS
(PciQueryTargetDeviceRelations implement, PciQueryEjectionRelations, stub)
- Stub support for PnP IRP to PDO: IRP_MN_QUERY_RESOURCE_REQUIREMENTS
(PciQueryRequirements), IRP_MN_QUERY_RESOURCES(PciQueryResources)
- Add support for PnP IRP to FDO: IRP_MN_QUERY_CAPABILITIES (handle in
PciFdoIrpQueryDeviceCapabilities)
- Build device capability UI number (PciDetermineSlotNumber), use PIR$ (seem support
broken, need to check loader) or device property for bus not root
- Use parent attachee device and this PDO for build device/system wake states, latency,
device/system power mappings
- PCI-ID manage support: PciInitIdBuffer, PciIdPrintf, PciIdPrintfAppend
- Debug helper: PciDebugDumpQueryCapabilities
- Thanks richard for advise + beer
PCI-X driver now pass 10000 codes lines!
Modified:
trunk/reactos/drivers/bus/pcix/debug.c
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/pci/id.c
trunk/reactos/drivers/bus/pcix/pdo.c
trunk/reactos/drivers/bus/pcix/utils.c
Modified: trunk/reactos/drivers/bus/pcix/debug.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/debug.c?r…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/debug.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/debug.c [iso-8859-1] Sat Aug 14 17:09:20 2010
@@ -49,6 +49,26 @@
"QUERY_POWER",
};
+PCHAR SystemPowerStates[] =
+{
+ "Unspecified",
+ "Working",
+ "Sleeping1",
+ "Sleeping2",
+ "Sleeping3",
+ "Hibernate",
+ "Shutdown"
+};
+
+PCHAR DevicePowerStates[] =
+{
+ "Unspecified",
+ "D0",
+ "D1",
+ "D2",
+ "D3"
+};
+
ULONG PciBreakOnPdoPowerIrp, PciBreakOnFdoPowerIrp;
ULONG PciBreakOnPdoPnpIrp, PciBreakOnFdoPnpIrp;
@@ -194,4 +214,41 @@
}
}
+VOID
+NTAPI
+PciDebugDumpQueryCapabilities(IN PDEVICE_CAPABILITIES DeviceCaps)
+{
+ ULONG i;
+
+ /* Dump the capabilities */
+ DPRINT1("Capabilities\n Lock:%d, Eject:%d, Remove:%d, Dock:%d,
UniqueId:%d\n",
+ DeviceCaps->LockSupported,
+ DeviceCaps->EjectSupported,
+ DeviceCaps->Removable,
+ DeviceCaps->DockDevice,
+ DeviceCaps->UniqueID);
+ DbgPrint(" SilentInstall:%d, RawOk:%d, SurpriseOk:%d\n",
+ DeviceCaps->SilentInstall,
+ DeviceCaps->RawDeviceOK,
+ DeviceCaps->SurpriseRemovalOK);
+ DbgPrint(" Address %08x, UINumber %08x, Latencies D1 %d, D2 %d, D3 %d\n",
+ DeviceCaps->Address,
+ DeviceCaps->UINumber,
+ DeviceCaps->D1Latency,
+ DeviceCaps->D2Latency,
+ DeviceCaps->D3Latency);
+
+ /* Dump and convert the wake levels */
+ DbgPrint(" System Wake: %s, Device Wake: %s\n DeviceState[PowerState]
[",
+ SystemPowerStates[min(DeviceCaps->SystemWake, PowerSystemMaximum)],
+ DevicePowerStates[min(DeviceCaps->DeviceWake, PowerDeviceMaximum)]);
+
+ /* Dump and convert the power state mappings */
+ for (i = PowerSystemWorking; i < PowerSystemMaximum; i++)
+ DbgPrint(" %s", DevicePowerStates[DeviceCaps->DeviceState[i]]);
+
+ /* Finish the dump */
+ DbgPrint(" ]\n");
+}
+
/* EOF */
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 Aug 14 17:09:20 2010
@@ -13,6 +13,8 @@
#include <debug.h>
/* GLOBALS ********************************************************************/
+
+PIO_RESOURCE_REQUIREMENTS_LIST PciZeroIoResourceRequirements;
PCI_CONFIGURATOR PciConfigurators[] =
{
@@ -46,6 +48,65 @@
};
/* FUNCTIONS ******************************************************************/
+
+NTSTATUS
+NTAPI
+PciQueryResources(IN PPCI_PDO_EXTENSION PdoExtension,
+ OUT PCM_RESOURCE_LIST *Buffer)
+{
+ /* Not yet implemented */
+ UNIMPLEMENTED;
+ while (TRUE);
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+PciQueryTargetDeviceRelations(IN PPCI_PDO_EXTENSION PdoExtension,
+ IN OUT PDEVICE_RELATIONS *pDeviceRelations)
+{
+ PDEVICE_RELATIONS DeviceRelations;
+ PAGED_CODE();
+
+ /* If there were existing relations, free them */
+ if (*pDeviceRelations) ExFreePoolWithTag(*pDeviceRelations, 0);
+
+ /* Allocate a new structure for the relations */
+ DeviceRelations = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(DEVICE_RELATIONS),
+ 'BicP');
+ if (!DeviceRelations) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Only one relation: the PDO */
+ DeviceRelations->Count = 1;
+ DeviceRelations->Objects[0] = PdoExtension->PhysicalDeviceObject;
+ ObReferenceObject(DeviceRelations->Objects[0]);
+
+ /* Return the new relations */
+ *pDeviceRelations = DeviceRelations;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+PciQueryEjectionRelations(IN PPCI_PDO_EXTENSION PdoExtension,
+ IN OUT PDEVICE_RELATIONS *pDeviceRelations)
+{
+ /* Not yet implemented */
+ UNIMPLEMENTED;
+ while (TRUE);
+}
+
+NTSTATUS
+NTAPI
+PciQueryRequirements(IN PPCI_PDO_EXTENSION PdoExtension,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *RequirementsList)
+{
+ /* Not yet implemented */
+ UNIMPLEMENTED;
+ while (TRUE);
+ return STATUS_SUCCESS;
+}
/*
* 7. The IO/MEM/Busmaster decodes are disabled for the device.
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 Aug 14 17:09:20 2010
@@ -295,9 +295,23 @@
IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_FDO_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_NOT_SUPPORTED;
+ PDEVICE_CAPABILITIES Capabilities;
+ PAGED_CODE();
+ ASSERT_FDO(DeviceExtension);
+
+ /* Get the capabilities */
+ Capabilities = IoStackLocation->Parameters.DeviceCapabilities.Capabilities;
+
+ /* Inherit wake levels and power mappings from the higher-up capabilities */
+ DeviceExtension->PowerState.SystemWakeLevel = Capabilities->SystemWake;
+ DeviceExtension->PowerState.DeviceWakeLevel = Capabilities->DeviceWake;
+ RtlCopyMemory(DeviceExtension->PowerState.SystemStateMapping,
+ Capabilities->DeviceState,
+ sizeof(DeviceExtension->PowerState.SystemStateMapping));
+
+ /* Dump the capabilities and return success */
+ PciDebugDumpQueryCapabilities(Capabilities);
+ return STATUS_SUCCESS;
}
NTSTATUS
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 Aug 14 17:09:20 2010
@@ -78,6 +78,11 @@
// PCI Driver Verifier Failures
//
#define PCI_VERIFIER_CODES 0x04
+
+//
+// PCI ID Buffer ANSI Strings
+//
+#define MAX_ANSI_STRINGS 0x08
//
// Device Extension, Interface, Translator and Arbiter Signatures
@@ -411,6 +416,19 @@
} PCI_VERIFIER_DATA, *PPCI_VERIFIER_DATA;
//
+// PCI ID Buffer Descriptor
+//
+typedef struct _PCI_ID_BUFFER
+{
+ ULONG Count;
+ ANSI_STRING Strings[MAX_ANSI_STRINGS];
+ ULONG StringSize[MAX_ANSI_STRINGS];
+ ULONG TotalLength;
+ PCHAR CharBuffer;
+ CHAR BufferData[256];
+} PCI_ID_BUFFER, *PPCI_ID_BUFFER;
+
+//
// PCI Configuration Callbacks
//
struct _PCI_CONFIGURATOR_CONTEXT;
@@ -1111,6 +1129,20 @@
OUT PUSHORT Command
);
+NTSTATUS
+NTAPI
+PciQueryBusInformation(
+ IN PPCI_PDO_EXTENSION PdoExtension,
+ IN PPNP_BUS_INFORMATION* Buffer
+);
+
+NTSTATUS
+NTAPI
+PciQueryCapabilities(
+ IN PPCI_PDO_EXTENSION PdoExtension,
+ IN OUT PDEVICE_CAPABILITIES DeviceCapability
+);
+
//
// Configuration Routines
//
@@ -1215,6 +1247,12 @@
NTAPI
PciDebugDumpCommonConfig(
IN PPCI_COMMON_HEADER PciData
+);
+
+VOID
+NTAPI
+PciDebugDumpQueryCapabilities(
+ IN PDEVICE_CAPABILITIES DeviceCaps
);
//
@@ -1452,6 +1490,34 @@
IN OUT PDEVICE_RELATIONS *pDeviceRelations
);
+NTSTATUS
+NTAPI
+PciQueryResources(
+ IN PPCI_PDO_EXTENSION PdoExtension,
+ OUT PCM_RESOURCE_LIST *Buffer
+);
+
+NTSTATUS
+NTAPI
+PciQueryTargetDeviceRelations(
+ IN PPCI_PDO_EXTENSION PdoExtension,
+ IN OUT PDEVICE_RELATIONS *pDeviceRelations
+);
+
+NTSTATUS
+NTAPI
+PciQueryEjectionRelations(
+ IN PPCI_PDO_EXTENSION PdoExtension,
+ IN OUT PDEVICE_RELATIONS *pDeviceRelations
+);
+
+NTSTATUS
+NTAPI
+PciQueryRequirements(
+ IN PPCI_PDO_EXTENSION PdoExtension,
+ IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *RequirementsList
+);
+
//
// Identification Functions
//
@@ -1460,6 +1526,23 @@
PciGetDeviceDescriptionMessage(
IN UCHAR BaseClass,
IN UCHAR SubClass
+);
+
+NTSTATUS
+NTAPI
+PciQueryDeviceText(
+ IN PPCI_PDO_EXTENSION PdoExtension,
+ IN DEVICE_TEXT_TYPE QueryType,
+ IN ULONG Locale,
+ OUT PWCHAR *Buffer
+);
+
+NTSTATUS
+NTAPI
+PciQueryId(
+ IN PPCI_PDO_EXTENSION DeviceExtension,
+ IN BUS_QUERY_ID_TYPE QueryType,
+ OUT PWCHAR *Buffer
);
//
@@ -1627,6 +1710,8 @@
extern PPCI_HACK_ENTRY PciHackTable;
extern BOOLEAN PciAssignBusNumbers;
extern BOOLEAN PciEnableNativeModeATA;
+extern PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable;
+extern BOOLEAN PciRunningDatacenter;
/* Exported by NTOS, should this go in the NDK? */
extern NTSYSAPI BOOLEAN InitSafeBootMode;
Modified: trunk/reactos/drivers/bus/pcix/pci/id.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci/id.c?…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pci/id.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pci/id.c [iso-8859-1] Sat Aug 14 17:09:20 2010
@@ -11,6 +11,7 @@
#include <pci.h>
#define NDEBUG
#include <debug.h>
+#include "stdio.h"
/* GLOBALS ********************************************************************/
@@ -107,4 +108,354 @@
return Message;
}
+VOID
+NTAPI
+PciInitIdBuffer(IN PPCI_ID_BUFFER IdBuffer)
+{
+ /* Initialize the sizes to zero and the pointer to the start of the buffer */
+ IdBuffer->TotalLength = 0;
+ IdBuffer->Count = 0;
+ IdBuffer->CharBuffer = IdBuffer->BufferData;
+}
+
+ULONG
+NTAPI
+PciIdPrintf(IN PPCI_ID_BUFFER IdBuffer,
+ IN PCCH Format,
+ ...)
+{
+ ULONG Size, Length;
+ PANSI_STRING AnsiString;
+ va_list va;
+ va_start(va, Format);
+ ASSERT(IdBuffer->Count < MAX_ANSI_STRINGS);
+
+ /* Do the actual string formatting into the character buffer */
+ vsprintf(IdBuffer->CharBuffer, Format, va);
+
+ /* Initialize the ANSI_STRING that will hold this string buffer */
+ AnsiString = &IdBuffer->Strings[IdBuffer->Count];
+ RtlInitAnsiString(AnsiString, IdBuffer->CharBuffer);
+
+ /* Calculate the final size of the string, in Unicode */
+ Size = RtlAnsiStringToUnicodeSize(AnsiString);
+
+ /* Update hte buffer with the size,and update the character pointer */
+ IdBuffer->StringSize[IdBuffer->Count] = Size;
+ IdBuffer->TotalLength += Size;
+ Length = AnsiString->Length + sizeof(ANSI_NULL);
+ IdBuffer->CharBuffer += Length;
+
+ /* Move to the next string for next time */
+ IdBuffer->Count++;
+
+ /* Return the length */
+ return Length;
+}
+
+ULONG
+NTAPI
+PciIdPrintfAppend(IN PPCI_ID_BUFFER IdBuffer,
+ IN PCCH Format,
+ ...)
+{
+ ULONG NextId, Size, Length, MaxLength;
+ PANSI_STRING AnsiString;
+ va_list va;
+ va_start(va, Format);
+ ASSERT(IdBuffer->Count);
+
+ /* Choose the next static ANSI_STRING to use */
+ NextId = IdBuffer->Count - 1;
+
+ /* Max length is from the end of the buffer up until the current pointer */
+ MaxLength = (PCHAR)(IdBuffer + 1) - IdBuffer->CharBuffer;
+
+ /* Do the actual append, and return the length this string took */
+ Length = vsprintf(IdBuffer->CharBuffer - 1, Format, va);
+ ASSERT(Length < MaxLength);
+
+ /* Select the static ANSI_STRING, and update its length information */
+ AnsiString = &IdBuffer->Strings[NextId];
+ AnsiString->Length += Length;
+ AnsiString->MaximumLength += Length;
+
+ /* Calculate the final size of the string, in Unicode */
+ Size = RtlAnsiStringToUnicodeSize(AnsiString);
+
+ /* Update the buffer with the size, and update the character pointer */
+ IdBuffer->StringSize[NextId] = Size;
+ IdBuffer->TotalLength += Size;
+ IdBuffer->CharBuffer += Length;
+
+ /* Return the size */
+ return Size;
+}
+
+NTSTATUS
+NTAPI
+PciQueryId(IN PPCI_PDO_EXTENSION DeviceExtension,
+ IN BUS_QUERY_ID_TYPE QueryType,
+ OUT PWCHAR *Buffer)
+{
+ ULONG SubsysId;
+ CHAR VendorString[22];
+ PPCI_PDO_EXTENSION PdoExtension;
+ PPCI_FDO_EXTENSION ParentExtension;
+ PWCHAR StringBuffer;
+ ULONG i, Size;
+ NTSTATUS Status;
+ PANSI_STRING NextString;
+ UNICODE_STRING DestinationString;
+ PCI_ID_BUFFER IdBuffer;
+ PAGED_CODE();
+
+ /* Assume failure */
+ Status = STATUS_SUCCESS;
+ *Buffer = NULL;
+
+ /* Start with the genric vendor string, which is the vendor ID + device ID */
+ sprintf(VendorString,
+ "PCI\\VEN_%04X&DEV_%04X",
+ DeviceExtension->VendorId,
+ DeviceExtension->DeviceId);
+
+ /* Initialize the PCI ID Buffer */
+ PciInitIdBuffer(&IdBuffer);
+
+ /* Build the subsystem ID as shown in PCI ID Strings */
+ SubsysId = DeviceExtension->SubsystemVendorId | (DeviceExtension->SubsystemId
<< 16);
+
+ /* Check what the caller is requesting */
+ switch (QueryType)
+ {
+ case BusQueryDeviceID:
+
+ /* A single ID, the vendor string + the revision ID */
+ PciIdPrintf(&IdBuffer,
+ "%s&SUBSYS_%08X&REV_%02X",
+ VendorString,
+ SubsysId,
+ DeviceExtension->RevisionId);
+ break;
+
+ case BusQueryHardwareIDs:
+
+ /* First the vendor string + the subsystem ID + the revision ID */
+ PciIdPrintf(&IdBuffer,
+ "%s&SUBSYS_%08X&REV_%02X",
+ VendorString,
+ SubsysId,
+ DeviceExtension->RevisionId);
+
+ /* Next, without the revision */
+ PciIdPrintf(&IdBuffer,
+ "%s&SUBSYS_%08X",
+ VendorString,
+ SubsysId);
+
+ /* Next, the vendor string + the base class + sub class + progif */
+ PciIdPrintf(&IdBuffer,
+ "%s&CC_%02X%02X%02X",
+ VendorString,
+ DeviceExtension->BaseClass,
+ DeviceExtension->SubClass,
+ DeviceExtension->ProgIf);
+
+ /* Next, without the progif */
+ PciIdPrintf(&IdBuffer,
+ "%s&CC_%02X%02X",
+ VendorString,
+ DeviceExtension->BaseClass,
+ DeviceExtension->SubClass);
+
+ /* And finally, a terminator */
+ PciIdPrintf(&IdBuffer, "\0");
+ break;
+
+ case BusQueryCompatibleIDs:
+
+ /* First, the vendor + revision ID only */
+ PciIdPrintf(&IdBuffer,
+ "%s&REV_%02X",
+ VendorString,
+ DeviceExtension->RevisionId);
+
+ /* Next, the vendor string alone */
+ PciIdPrintf(&IdBuffer, "%s", VendorString);
+
+ /* Next, the vendor ID + the base class + the sub class + progif */
+ PciIdPrintf(&IdBuffer,
+ "PCI\\VEN_%04X&CC_%02X%02X%02X",
+ DeviceExtension->VendorId,
+ DeviceExtension->BaseClass,
+ DeviceExtension->SubClass,
+ DeviceExtension->ProgIf);
+
+ /* Now without the progif */
+ PciIdPrintf(&IdBuffer,
+ "PCI\\VEN_%04X&CC_%02X%02X",
+ DeviceExtension->VendorId,
+ DeviceExtension->BaseClass,
+ DeviceExtension->SubClass);
+
+ /* And then just the vendor ID itself */
+ PciIdPrintf(&IdBuffer,
+ "PCI\\VEN_%04X",
+ DeviceExtension->VendorId);
+
+ /* Then the base class + subclass + progif, without any vendor */
+ PciIdPrintf(&IdBuffer,
+ "PCI\\CC_%02X%02X%02X",
+ DeviceExtension->BaseClass,
+ DeviceExtension->SubClass,
+ DeviceExtension->ProgIf);
+
+ /* Next, without the progif */
+ PciIdPrintf(&IdBuffer,
+ "PCI\\CC_%02X%02X",
+ DeviceExtension->BaseClass,
+ DeviceExtension->SubClass);
+
+ /* And finally, a terminator */
+ PciIdPrintf(&IdBuffer, "\0");
+ break;
+
+ case BusQueryInstanceID:
+
+ /* Start with a terminator */
+ PciIdPrintf(&IdBuffer, "\0");
+
+ /* And then encode the device and function number */
+ PciIdPrintfAppend(&IdBuffer,
+ "%02X",
+ (DeviceExtension->Slot.u.bits.DeviceNumber << 3)
|
+ DeviceExtension->Slot.u.bits.FunctionNumber);
+
+ /* Loop every parent until the root */
+ ParentExtension = DeviceExtension->ParentFdoExtension;
+ while (!PCI_IS_ROOT_FDO(ParentExtension))
+ {
+ /* And encode the parent's device and function number as well */
+ PdoExtension =
ParentExtension->PhysicalDeviceObject->DeviceExtension;
+ PciIdPrintfAppend(&IdBuffer,
+ "%02X",
+ (PdoExtension->Slot.u.bits.DeviceNumber << 3)
|
+ PdoExtension->Slot.u.bits.FunctionNumber);
+ }
+ break;
+
+ default:
+
+ /* Unknown query type */
+ DPRINT1("PciQueryId expected ID type = %d\n", QueryType);
+ return STATUS_NOT_SUPPORTED;
+ }
+
+ /* Something should've been generated if this has been reached */
+ ASSERT(IdBuffer.Count > 0);
+
+ /* Allocate the final string buffer to hold the ID */
+ StringBuffer = ExAllocatePoolWithTag(PagedPool, IdBuffer.TotalLength,
'BicP');
+ if (!StringBuffer) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Build the UNICODE_STRING structure for it */
+ DPRINT1("PciQueryId(%d)\n", QueryType);
+ DestinationString.Buffer = StringBuffer;
+ DestinationString.MaximumLength = IdBuffer.TotalLength;
+
+ /* Loop every ID in the buffer */
+ for (i = 0; i < IdBuffer.Count; i++)
+ {
+ /* Select the ANSI_STRING for the ID */
+ NextString = &IdBuffer.Strings[i];
+ DPRINT1(" <- \"%s\"\n", NextString->Buffer);
+
+ /* Convert it to a UNICODE_STRING */
+ Status = RtlAnsiStringToUnicodeString(&DestinationString, NextString,
FALSE);
+ ASSERT(NT_SUCCESS(Status));
+
+ /* Add it into the final destination buffer */
+ Size = IdBuffer.StringSize[i];
+ DestinationString.MaximumLength -= Size;
+ DestinationString.Buffer += (Size / sizeof(WCHAR));
+ }
+
+ /* Return the buffer to the caller and return status (should be success) */
+ *Buffer = StringBuffer;
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+PciQueryDeviceText(IN PPCI_PDO_EXTENSION PdoExtension,
+ IN DEVICE_TEXT_TYPE QueryType,
+ IN ULONG Locale,
+ OUT PWCHAR *Buffer)
+{
+ PWCHAR MessageBuffer, LocationBuffer;
+ ULONG Length;
+ NTSTATUS Status;
+
+ /* Check what the caller is requesting */
+ switch (QueryType)
+ {
+ case DeviceTextDescription:
+
+ /* Get the message from the resource section */
+ MessageBuffer = PciGetDeviceDescriptionMessage(PdoExtension->BaseClass,
+ PdoExtension->SubClass);
+
+ /* Return it to the caller, and select proper status code */
+ *Buffer = MessageBuffer;
+ Status = MessageBuffer ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
+ break;
+
+ case DeviceTextLocationInformation:
+
+ /* Get the message from the resource section */
+ MessageBuffer = PciGetDescriptionMessage(0x10000, &Length);
+ if (!MessageBuffer)
+ {
+ /* It should be there, but fail if it wasn't found for some reason
*/
+ Status = STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ /* Add space for a null-terminator, and allocate the buffer */
+ Length += 2 * sizeof(UNICODE_NULL);
+ LocationBuffer = ExAllocatePoolWithTag(PagedPool,
+ Length * sizeof(WCHAR),
+ 'BicP');
+ *Buffer = LocationBuffer;
+
+ /* Check if the allocation succeeded */
+ if (LocationBuffer)
+ {
+ /* Build the location string based on bus, function, and device */
+ swprintf(LocationBuffer,
+ MessageBuffer,
+ PdoExtension->ParentFdoExtension->BaseBus,
+ PdoExtension->Slot.u.bits.FunctionNumber,
+ PdoExtension->Slot.u.bits.DeviceNumber);
+ }
+
+ /* Free the original string from the resource section */
+ ExFreePoolWithTag(MessageBuffer, 0);
+
+ /* Select the correct status */
+ Status = LocationBuffer ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES;
+ break;
+
+ default:
+
+ /* Anything else is unsupported */
+ Status = STATUS_NOT_SUPPORTED;
+ break;
+ }
+
+ /* Return whether or not a device text string was indeed found */
+ return Status;
+}
+
/* EOF */
Modified: trunk/reactos/drivers/bus/pcix/pdo.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pdo.c?rev…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pdo.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pdo.c [iso-8859-1] Sat Aug 14 17:09:20 2010
@@ -200,9 +200,32 @@
IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_PDO_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_NOT_SUPPORTED;
+ NTSTATUS Status;
+ PAGED_CODE();
+
+ /* Are ejection relations being queried? */
+ if (IoStackLocation->Parameters.QueryDeviceRelations.Type == EjectionRelations)
+ {
+ /* Call the worker function */
+ Status = PciQueryEjectionRelations(DeviceExtension,
+ (PDEVICE_RELATIONS*)&Irp->
+ IoStatus.Information);
+ }
+ else if (IoStackLocation->Parameters.QueryDeviceRelations.Type ==
TargetDeviceRelation)
+ {
+ /* The only other relation supported is the target device relation */
+ Status = PciQueryTargetDeviceRelations(DeviceExtension,
+ (PDEVICE_RELATIONS*)&Irp->
+ IoStatus.Information);
+ }
+ else
+ {
+ /* All other relations are unsupported */
+ Status = STATUS_NOT_SUPPORTED;
+ }
+
+ /* Return either the result of the worker function, or unsupported status */
+ return Status;
}
NTSTATUS
@@ -211,9 +234,12 @@
IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_PDO_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_NOT_SUPPORTED;
+ PAGED_CODE();
+
+ /* Call the worker function */
+ return PciQueryCapabilities(DeviceExtension,
+ IoStackLocation->
+ Parameters.DeviceCapabilities.Capabilities);
}
NTSTATUS
@@ -222,9 +248,11 @@
IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_PDO_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_NOT_SUPPORTED;
+ PAGED_CODE();
+
+ /* Call the worker function */
+ return PciQueryResources(DeviceExtension,
+ (PCM_RESOURCE_LIST*)&Irp->IoStatus.Information);
}
NTSTATUS
@@ -233,9 +261,12 @@
IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_PDO_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_NOT_SUPPORTED;
+ PAGED_CODE();
+
+ /* Call the worker function */
+ return PciQueryRequirements(DeviceExtension,
+ (PIO_RESOURCE_REQUIREMENTS_LIST*)&Irp->
+ IoStatus.Information);
}
NTSTATUS
@@ -244,9 +275,15 @@
IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_PDO_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_NOT_SUPPORTED;
+ PAGED_CODE();
+
+ /* Call the worker function */
+ return PciQueryDeviceText(DeviceExtension,
+ IoStackLocation->
+ Parameters.QueryDeviceText.DeviceTextType,
+ IoStackLocation->
+ Parameters.QueryDeviceText.LocaleId,
+ (PWCHAR*)&Irp->IoStatus.Information);
}
NTSTATUS
@@ -255,9 +292,12 @@
IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_PDO_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_NOT_SUPPORTED;
+ PAGED_CODE();
+
+ /* Call the worker function */
+ return PciQueryId(DeviceExtension,
+ IoStackLocation->Parameters.QueryId.IdType,
+ (PWCHAR*)&Irp->IoStatus.Information);
}
NTSTATUS
@@ -266,9 +306,12 @@
IN PIO_STACK_LOCATION IoStackLocation,
IN PPCI_PDO_EXTENSION DeviceExtension)
{
- UNIMPLEMENTED;
- while (TRUE);
- return STATUS_NOT_SUPPORTED;
+ PAGED_CODE();
+
+ /* Call the worker function */
+ return PciQueryBusInformation(DeviceExtension,
+ (PPNP_BUS_INFORMATION*)&Irp->
+ IoStatus.Information);
}
NTSTATUS
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 Aug 14 17:09:20 2010
@@ -1306,4 +1306,455 @@
}
}
+NTSTATUS
+NTAPI
+PciQueryBusInformation(IN PPCI_PDO_EXTENSION PdoExtension,
+ IN PPNP_BUS_INFORMATION* Buffer)
+{
+ PPNP_BUS_INFORMATION BusInfo;
+
+ /* Allocate a structure for the bus information */
+ BusInfo = ExAllocatePoolWithTag(PagedPool,
+ sizeof(PNP_BUS_INFORMATION),
+ 'BicP');
+ if (!BusInfo) return STATUS_INSUFFICIENT_RESOURCES;
+
+ /* Write the correct GUID and bus type identifier, and fill the bus number */
+ BusInfo->BusTypeGuid = GUID_BUS_TYPE_PCI;
+ BusInfo->LegacyBusType = PCIBus;
+ BusInfo->BusNumber = PdoExtension->ParentFdoExtension->BaseBus;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+PciDetermineSlotNumber(IN PPCI_PDO_EXTENSION PdoExtension,
+ OUT PULONG SlotNumber)
+{
+ PPCI_FDO_EXTENSION ParentExtension;
+ ULONG ResultLength;
+ NTSTATUS Status;
+ PSLOT_INFO SlotInfo;
+
+ /* Check if a $PIR from the BIOS is used (legacy IRQ routing) */
+ ParentExtension = PdoExtension->ParentFdoExtension;
+ DPRINT1("Slot lookup for %d.%d.%d\n",
+ ParentExtension ? ParentExtension->BaseBus : -1,
+ PdoExtension->Slot.u.bits.DeviceNumber,
+ PdoExtension->Slot.u.bits.FunctionNumber);
+ if ((PciIrqRoutingTable) && (ParentExtension))
+ {
+ /* Read every slot information entry */
+ SlotInfo = &PciIrqRoutingTable->Slot[0];
+ DPRINT1("PIR$ %p is %lx bytes, slot 0 is at: %lx\n",
+ PciIrqRoutingTable, PciIrqRoutingTable->TableSize, SlotInfo);
+ while (SlotInfo < (PSLOT_INFO)((ULONG_PTR)PciIrqRoutingTable +
+ PciIrqRoutingTable->TableSize))
+ {
+ DPRINT1("Slot Info: %d.%d->#%d\n",
+ SlotInfo->BusNumber,
+ SlotInfo->DeviceNumber,
+ SlotInfo->SlotNumber);
+
+ /* Check if this slot information matches the PDO being queried */
+ if ((ParentExtension->BaseBus == SlotInfo->BusNumber) &&
+ (PdoExtension->Slot.u.bits.DeviceNumber == SlotInfo->DeviceNumber
>> 3) &&
+ (SlotInfo->SlotNumber))
+ {
+ /* We found it, return it and return success */
+ *SlotNumber = SlotInfo->SlotNumber;
+ return STATUS_SUCCESS;
+ }
+
+ /* Try the next slot */
+ SlotInfo++;
+ }
+ }
+
+ /* Otherwise, grab the parent FDO and check if it's the root */
+ if (PCI_IS_ROOT_FDO(ParentExtension))
+ {
+ /* The root FDO doesn't have a slot number */
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ /* Otherwise, query the slot/UI address/number as a device property */
+ Status = IoGetDeviceProperty(ParentExtension->PhysicalDeviceObject,
+ DevicePropertyUINumber,
+ sizeof(ULONG),
+ SlotNumber,
+ &ResultLength);
+ }
+
+ /* Return the status of this endeavour */
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+PciGetDeviceCapabilities(IN PDEVICE_OBJECT DeviceObject,
+ IN OUT PDEVICE_CAPABILITIES DeviceCapability)
+{
+ PIRP Irp;
+ NTSTATUS Status;
+ KEVENT Event;
+ PDEVICE_OBJECT AttachedDevice;
+ PIO_STACK_LOCATION IoStackLocation;
+ IO_STATUS_BLOCK IoStatusBlock;
+ PAGED_CODE();
+
+ /* Zero out capabilities and set undefined values to start with */
+ RtlZeroMemory(DeviceCapability, sizeof(DEVICE_CAPABILITIES));
+ DeviceCapability->Size = sizeof(DEVICE_CAPABILITIES);
+ DeviceCapability->Version = 1;
+ DeviceCapability->Address = -1;
+ DeviceCapability->UINumber = -1;
+
+ /* Build the wait event for the IOCTL */
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+
+ /* Find the device the PDO is attached to */
+ AttachedDevice = IoGetAttachedDeviceReference(DeviceObject);
+
+ /* And build an IRP for it */
+ Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
+ AttachedDevice,
+ NULL,
+ 0,
+ NULL,
+ &Event,
+ &IoStatusBlock);
+ if (!Irp)
+ {
+ /* The IRP failed, fail the request as well */
+ ObDereferenceObject(AttachedDevice);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Set default status */
+ Irp->IoStatus.Information = 0;
+ Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
+
+ /* Get a stack location in this IRP */
+ IoStackLocation = IoGetNextIrpStackLocation(Irp);
+ ASSERT(IoStackLocation);
+
+ /* Initialize it as a query capabilities IRP, with no completion routine */
+ RtlZeroMemory(IoStackLocation, sizeof(IO_STACK_LOCATION));
+ IoStackLocation->MajorFunction = IRP_MJ_PNP;
+ IoStackLocation->MinorFunction = IRP_MN_QUERY_CAPABILITIES;
+ IoStackLocation->Parameters.DeviceCapabilities.Capabilities = DeviceCapability;
+ IoSetCompletionRoutine(Irp, NULL, NULL, FALSE, FALSE, FALSE);
+
+ /* Send the IOCTL to the driver */
+ Status = IoCallDriver(AttachedDevice, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait for a response and update the actual status */
+ KeWaitForSingleObject(&Event,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ Status = Irp->IoStatus.Status;
+ }
+
+ /* Done, dereference the attached device and return the final result */
+ ObDereferenceObject(AttachedDevice);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+PciQueryPowerCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
+ IN PDEVICE_CAPABILITIES DeviceCapability)
+{
+ PDEVICE_OBJECT DeviceObject;
+ NTSTATUS Status;
+ DEVICE_CAPABILITIES AttachedCaps;
+ DEVICE_POWER_STATE NewPowerState, DevicePowerState, DeviceWakeLevel,
DeviceWakeState;
+ SYSTEM_POWER_STATE SystemWakeState, DeepestWakeState, CurrentState;
+
+ /* Nothing is known at first */
+ DeviceWakeState = PowerDeviceUnspecified;
+ SystemWakeState = DeepestWakeState = PowerSystemUnspecified;
+
+ /* Get the PCI capabilities for the parent PDO */
+ DeviceObject = PdoExtension->ParentFdoExtension->PhysicalDeviceObject;
+ Status = PciGetDeviceCapabilities(DeviceObject, &AttachedCaps);
+ ASSERT(NT_SUCCESS(Status));
+ if (!NT_SUCCESS(Status)) return Status;
+
+ /* Check if there's not an existing device state for S0 */
+ if (!AttachedCaps.DeviceState[PowerSystemWorking])
+ {
+ /* Set D0<->S0 mapping */
+ AttachedCaps.DeviceState[PowerSystemWorking] = PowerDeviceD0;
+ }
+
+ /* Check if there's not an existing device state for S3 */
+ if (!AttachedCaps.DeviceState[PowerSystemShutdown])
+ {
+ /* Set D3<->S3 mapping */
+ AttachedCaps.DeviceState[PowerSystemShutdown] = PowerDeviceD3;
+ }
+
+ /* Check for a PDO with broken, or no, power capabilities */
+ if (PdoExtension->HackFlags & PCI_HACK_NO_PM_CAPS)
+ {
+ /* Unknown wake device states */
+ DeviceCapability->DeviceWake = PowerDeviceUnspecified;
+ DeviceCapability->SystemWake = PowerSystemUnspecified;
+
+ /* No device state support */
+ DeviceCapability->DeviceD1 = FALSE;
+ DeviceCapability->DeviceD2 = FALSE;
+
+ /* No waking from any low-power device state is supported */
+ DeviceCapability->WakeFromD0 = FALSE;
+ DeviceCapability->WakeFromD1 = FALSE;
+ DeviceCapability->WakeFromD2 = FALSE;
+ DeviceCapability->WakeFromD3 = FALSE;
+
+ /* For the rest, copy whatever the parent PDO had */
+ RtlCopyMemory(DeviceCapability->DeviceState,
+ AttachedCaps.DeviceState,
+ sizeof(DeviceCapability->DeviceState));
+ return STATUS_SUCCESS;
+ }
+
+ /* The PCI Device has power capabilities, so read which ones are supported */
+ DeviceCapability->DeviceD1 = PdoExtension->PowerCapabilities.Support.D1;
+ DeviceCapability->DeviceD2 = PdoExtension->PowerCapabilities.Support.D2;
+ DeviceCapability->WakeFromD0 = PdoExtension->PowerCapabilities.Support.PMED0;
+ DeviceCapability->WakeFromD1 = PdoExtension->PowerCapabilities.Support.PMED1;
+ DeviceCapability->WakeFromD2 = PdoExtension->PowerCapabilities.Support.PMED2;
+
+ /* Can the attached device wake from D3? */
+ if (AttachedCaps.DeviceWake != PowerDeviceD3)
+ {
+ /* It can't, so check if this PDO supports hot D3 wake */
+ DeviceCapability->WakeFromD3 =
PdoExtension->PowerCapabilities.Support.PMED3Hot;
+ }
+ else
+ {
+ /* It can, is this the root bus? */
+ if (PCI_IS_ROOT_FDO(PdoExtension->ParentFdoExtension))
+ {
+ /* This is the root bus, so just check if it supports hot D3 wake */
+ DeviceCapability->WakeFromD3 =
PdoExtension->PowerCapabilities.Support.PMED3Hot;
+ }
+ else
+ {
+ /* Take the minimums? -- need to check with briang at work */
+ UNIMPLEMENTED;
+ }
+ }
+
+ /* Now loop each system power state to determine its device state mapping */
+ for (CurrentState = PowerSystemWorking;
+ CurrentState < PowerSystemMaximum;
+ CurrentState++)
+ {
+ /* Read the current mapping from the attached device */
+ DevicePowerState = AttachedCaps.DeviceState[CurrentState];
+ NewPowerState = DevicePowerState;
+
+ /* The attachee suports D1, but this PDO does not */
+ if ((NewPowerState == PowerDeviceD1) &&
+ !(PdoExtension->PowerCapabilities.Support.D1))
+ {
+ /* Fall back to D2 */
+ NewPowerState = PowerDeviceD2;
+ }
+
+ /* The attachee supports D2, but this PDO does not */
+ if ((NewPowerState == PowerDeviceD2) &&
+ !(PdoExtension->PowerCapabilities.Support.D2))
+ {
+ /* Fall back to D3 */
+ NewPowerState = PowerDeviceD3;
+ }
+
+ /* Set the mapping based on the best state supported */
+ DeviceCapability->DeviceState[CurrentState] = NewPowerState;
+
+ /* Check if sleep states are being processed, and a mapping was found */
+ if ((CurrentState < PowerSystemHibernate) &&
+ (NewPowerState != PowerDeviceUnspecified))
+ {
+ /* Save this state as being the deepest one found until now */
+ DeepestWakeState = CurrentState;
+ }
+
+ /*
+ * Finally, check if the computed sleep state is within the states that
+ * this device can wake the system from, and if it's higher or equal to
+ * the sleep state mapping that came from the attachee, assuming that it
+ * had a valid mapping to begin with.
+ *
+ * It this is the case, then make sure that the computed sleep state is
+ * matched by the device's ability to actually wake from that state.
+ *
+ * For devices that support D3, the PCI device only needs Hot D3 as long
+ * as the attachee's state is less than D3. Otherwise, if the attachee
+ * might also be at D3, this would require a Cold D3 wake, so check that
+ * the device actually support this.
+ */
+ if ((CurrentState < AttachedCaps.SystemWake) &&
+ (NewPowerState >= DevicePowerState) &&
+ (DevicePowerState != PowerDeviceUnspecified) &&
+ (((NewPowerState == PowerDeviceD0) &&
(DeviceCapability->WakeFromD0)) ||
+ ((NewPowerState == PowerDeviceD1) &&
(DeviceCapability->WakeFromD1)) ||
+ ((NewPowerState == PowerDeviceD2) &&
(DeviceCapability->WakeFromD2)) ||
+ ((NewPowerState == PowerDeviceD3) &&
+ (PdoExtension->PowerCapabilities.Support.PMED3Hot) &&
+ ((DevicePowerState < PowerDeviceD3) ||
+ (PdoExtension->PowerCapabilities.Support.PMED3Cold)))))
+ {
+ /* The mapping is valid, so this will be the lowest wake state */
+ SystemWakeState = CurrentState;
+ DeviceWakeState = NewPowerState;
+ }
+ }
+
+ /* Read the current wake level */
+ DeviceWakeLevel = PdoExtension->PowerState.DeviceWakeLevel;
+
+ /* Check if the attachee's wake levels are valid, and the PDO's is higher */
+ if ((AttachedCaps.SystemWake != PowerSystemUnspecified) &&
+ (AttachedCaps.DeviceWake != PowerDeviceUnspecified) &&
+ (DeviceWakeLevel != PowerDeviceUnspecified) &&
+ (DeviceWakeLevel >= AttachedCaps.DeviceWake))
+ {
+ /* Inherit the system wake from the attachee, and this PDO's wake level */
+ DeviceCapability->SystemWake = AttachedCaps.SystemWake;
+ DeviceCapability->DeviceWake = DeviceWakeLevel;
+
+ /* Now check if the wake level is D0, but the PDO doesn't support it */
+ if ((DeviceCapability->DeviceWake == PowerDeviceD0) &&
+ !(DeviceCapability->WakeFromD0))
+ {
+ /* Bump to D1 */
+ DeviceCapability->DeviceWake = PowerDeviceD1;
+ }
+
+ /* Now check if the wake level is D1, but the PDO doesn't support it */
+ if ((DeviceCapability->DeviceWake == PowerDeviceD1) &&
+ !(DeviceCapability->WakeFromD1))
+ {
+ /* Bump to D2 */
+ DeviceCapability->DeviceWake = PowerDeviceD2;
+ }
+
+ /* Now check if the wake level is D2, but the PDO doesn't support it */
+ if ((DeviceCapability->DeviceWake == PowerDeviceD2) &&
+ !(DeviceCapability->WakeFromD2))
+ {
+ /* Bump it to D3 */
+ DeviceCapability->DeviceWake = PowerDeviceD3;
+ }
+
+ /* Now check if the wake level is D3, but the PDO doesn't support it */
+ if ((DeviceCapability->DeviceWake == PowerDeviceD3) &&
+ !(DeviceCapability->WakeFromD3))
+ {
+ /* Then no valid wake state exists */
+ DeviceCapability->DeviceWake = PowerDeviceUnspecified;
+ DeviceCapability->SystemWake = PowerSystemUnspecified;
+ }
+
+ /* Check if no valid wake state was found */
+ if ((DeviceCapability->DeviceWake == PowerDeviceUnspecified) ||
+ (DeviceCapability->SystemWake == PowerSystemUnspecified))
+ {
+ /* Check if one was computed earlier */
+ if ((SystemWakeState != PowerSystemUnspecified) &&
+ (DeviceWakeState != PowerDeviceUnspecified))
+ {
+ /* Use the wake state that had been computed earlier */
+ DeviceCapability->DeviceWake = DeviceWakeState;
+ DeviceCapability->SystemWake = SystemWakeState;
+
+ /* If that state was D3, then the device supports Hot/Cold D3 */
+ if (DeviceWakeState == PowerDeviceD3) DeviceCapability->WakeFromD3 =
TRUE;
+ }
+ }
+
+ /*
+ * Finally, check for off states (lower than S3, such as hibernate) and
+ * make sure that the device both supports waking from D3 as well as
+ * supports a Cold wake
+ */
+ if ((DeviceCapability->SystemWake > PowerSystemSleeping3) &&
+ ((DeviceCapability->DeviceWake != PowerDeviceD3) ||
+ !(PdoExtension->PowerCapabilities.Support.PMED3Cold)))
+ {
+ /* It doesn't, so pick the computed lowest wake state from earlier */
+ DeviceCapability->SystemWake = DeepestWakeState;
+ }
+
+ /* Set the PCI Specification mandated maximum latencies for transitions */
+ DeviceCapability->D1Latency = 0;
+ DeviceCapability->D2Latency = 2;
+ DeviceCapability->D3Latency = 100;
+
+ /* Sanity check */
+ ASSERT(DeviceCapability->DeviceState[PowerSystemWorking] == PowerDeviceD0);
+ }
+ else
+ {
+ /* No valid sleep states, no latencies to worry about */
+ DeviceCapability->D1Latency = 0;
+ DeviceCapability->D2Latency = 0;
+ DeviceCapability->D3Latency = 0;
+ }
+
+ /* This function always succeeds, even without power management support */
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+PciQueryCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
+ IN OUT PDEVICE_CAPABILITIES DeviceCapability)
+{
+ NTSTATUS Status;
+
+ /* A PDO ID is never unique, and its address is its function and device */
+ DeviceCapability->UniqueID = FALSE;
+ DeviceCapability->Address = PdoExtension->Slot.u.bits.FunctionNumber |
+ (PdoExtension->Slot.u.bits.DeviceNumber << 16);
+
+ /* Check for host bridges */
+ if ((PdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
+ (PdoExtension->SubClass == PCI_SUBCLASS_BR_HOST))
+ {
+ /* Raw device opens to a host bridge are acceptable */
+ DeviceCapability->RawDeviceOK = TRUE;
+ }
+ else
+ {
+ /* Otherwise, other PDOs cannot be directly opened */
+ DeviceCapability->RawDeviceOK = FALSE;
+ }
+
+ /* PCI PDOs are pretty fixed things */
+ DeviceCapability->LockSupported = FALSE;
+ DeviceCapability->EjectSupported = FALSE;
+ DeviceCapability->Removable = FALSE;
+ DeviceCapability->DockDevice = FALSE;
+
+ /* The slot number is stored as a device property, go query it */
+ PciDetermineSlotNumber(PdoExtension, &DeviceCapability->UINumber);
+
+ /* Finally, query and power capabilities and convert them for PnP usage */
+ Status = PciQueryPowerCapabilities(PdoExtension, DeviceCapability);
+
+ /* Dump the capabilities if it all worked, and return the status */
+ if (NT_SUCCESS(Status)) PciDebugDumpQueryCapabilities(DeviceCapability);
+ return Status;
+}
+
/* EOF */