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?re... ============================================================================== --- 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?rev... ============================================================================== --- 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?r... ============================================================================== --- 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?re... ============================================================================== --- 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 */