Author: cgutman Date: Sun Jun 19 04:25:33 2011 New Revision: 52358
URL: http://svn.reactos.org/svn/reactos?rev=52358&view=rev Log: [NTOSKRNL] - Send IRP_MN_QUERY_POWER and IRP_MN_SET_POWER to all enumerated devices prior to a system power state change - We don't mind failure right now since our drivers suck
Modified: trunk/reactos/ntoskrnl/include/internal/io.h trunk/reactos/ntoskrnl/include/internal/po.h trunk/reactos/ntoskrnl/po/poshtdwn.c trunk/reactos/ntoskrnl/po/power.c
Modified: trunk/reactos/ntoskrnl/include/internal/io.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/i... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/io.h [iso-8859-1] Sun Jun 19 04:25:33 2011 @@ -696,6 +696,11 @@ OUT PULONG Disposition OPTIONAL );
+ +NTSTATUS +IopTraverseDeviceTree( + PDEVICETREE_TRAVERSE_CONTEXT Context); + // // PnP Routines //
Modified: trunk/reactos/ntoskrnl/include/internal/po.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/p... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/po.h [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/include/internal/po.h [iso-8859-1] Sun Jun 19 04:25:33 2011 @@ -291,7 +291,8 @@ NTSTATUS NTAPI PopSetSystemPowerState( - SYSTEM_POWER_STATE PowerState + SYSTEM_POWER_STATE PowerState, + POWER_ACTION PowerAction );
VOID
Modified: trunk/reactos/ntoskrnl/po/poshtdwn.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/po/poshtdwn.c?rev=... ============================================================================== --- trunk/reactos/ntoskrnl/po/poshtdwn.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/po/poshtdwn.c [iso-8859-1] Sun Jun 19 04:25:33 2011 @@ -84,6 +84,7 @@
/* Try platform driver first, then legacy */ //PopInvokeSystemStateHandler(PowerStateShutdownReset, NULL); + PopSetSystemPowerState(PowerSystemShutdown, SystemAction); HalReturnToFirmware(HalRebootRoutine); break;
@@ -102,7 +103,7 @@ //PopInvokeSystemStateHandler(PowerStateShutdownOff, NULL);
/* ReactOS Hack */ - PopSetSystemPowerState(PowerSystemShutdown); + PopSetSystemPowerState(PowerSystemShutdown, SystemAction); PopShutdownHandler();
/* If that didn't work, call the HAL */
Modified: trunk/reactos/ntoskrnl/po/power.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/po/power.c?rev=523... ============================================================================== --- trunk/reactos/ntoskrnl/po/power.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/po/power.c [iso-8859-1] Sun Jun 19 04:25:33 2011 @@ -23,6 +23,13 @@ PVOID Context; } REQUEST_POWER_ITEM, *PREQUEST_POWER_ITEM;
+typedef struct _POWER_STATE_TRAVERSE_CONTEXT +{ + SYSTEM_POWER_STATE SystemPowerState; + POWER_ACTION PowerAction; + PDEVICE_OBJECT PowerDevice; +} POWER_STATE_TRAVERSE_CONTEXT, *PPOWER_STATE_TRAVERSE_CONTEXT; + PDEVICE_NODE PopSystemPowerDeviceNode = NULL; BOOLEAN PopAcpiPresent = FALSE; POP_POWER_ACTION PopAction; @@ -64,53 +71,33 @@ }
NTSTATUS -NTAPI -PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState) -{ +PopSendQuerySystemPowerState(PDEVICE_OBJECT DeviceObject, SYSTEM_POWER_STATE SystemState, POWER_ACTION PowerAction) +{ + KEVENT Event; IO_STATUS_BLOCK IoStatusBlock; - PDEVICE_OBJECT DeviceObject; PIO_STACK_LOCATION IrpSp; - PDEVICE_OBJECT Fdo; + PIRP Irp; NTSTATUS Status; - KEVENT Event; - PIRP Irp; - - if (!PopAcpiPresent) return STATUS_NOT_IMPLEMENTED; - - Status = IopGetSystemPowerDeviceObject(&DeviceObject); - if (!NT_SUCCESS(Status)) - { - DPRINT1("No system power driver available\n"); - return STATUS_UNSUCCESSFUL; - } - - Fdo = IoGetAttachedDeviceReference(DeviceObject); - - if (Fdo == DeviceObject) - { - DPRINT("An FDO was not attached\n"); - return STATUS_UNSUCCESSFUL; - } - + KeInitializeEvent(&Event, NotificationEvent, FALSE); - + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_POWER, - Fdo, + DeviceObject, NULL, 0, NULL, &Event, &IoStatusBlock); - + IrpSp = IoGetNextIrpStackLocation(Irp); - IrpSp->MinorFunction = IRP_MN_SET_POWER; + IrpSp->MinorFunction = IRP_MN_QUERY_POWER; IrpSp->Parameters.Power.Type = SystemPowerState; - IrpSp->Parameters.Power.State.SystemState = PowerState; - - DPRINT("Calling ACPI driver"); - Status = PoCallDriver(Fdo, Irp); + IrpSp->Parameters.Power.State.SystemState = SystemState; + IrpSp->Parameters.Power.ShutdownType = PowerAction; + + Status = PoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { KeWaitForSingleObject(&Event, @@ -118,10 +105,176 @@ KernelMode, FALSE, NULL); - Status = IoStatusBlock.Status; - } - - ObDereferenceObject(Fdo); + Status = IoStatusBlock.Status; + } + + return Status; +} + +NTSTATUS +PopSendSetSystemPowerState(PDEVICE_OBJECT DeviceObject, SYSTEM_POWER_STATE SystemState, POWER_ACTION PowerAction) +{ + KEVENT Event; + IO_STATUS_BLOCK IoStatusBlock; + PIO_STACK_LOCATION IrpSp; + PIRP Irp; + NTSTATUS Status; + + KeInitializeEvent(&Event, + NotificationEvent, + FALSE); + + Irp = IoBuildSynchronousFsdRequest(IRP_MJ_POWER, + DeviceObject, + NULL, + 0, + NULL, + &Event, + &IoStatusBlock); + + IrpSp = IoGetNextIrpStackLocation(Irp); + IrpSp->MinorFunction = IRP_MN_SET_POWER; + IrpSp->Parameters.Power.Type = SystemPowerState; + IrpSp->Parameters.Power.State.SystemState = SystemState; + IrpSp->Parameters.Power.ShutdownType = PowerAction; + + Status = PoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + return Status; +} + +NTSTATUS +PopQuerySystemPowerStateTraverse(PDEVICE_NODE DeviceNode, + PVOID Context) +{ + PPOWER_STATE_TRAVERSE_CONTEXT PowerStateContext = Context; + NTSTATUS Status; + + DPRINT("PopQuerySystemPowerStateTraverse(%p, %p)\n", DeviceNode, Context); + + if (DeviceNode == IopRootDeviceNode) + return STATUS_SUCCESS; + + if (DeviceNode->Flags & DNF_LEGACY_DRIVER) + return STATUS_SUCCESS; + + Status = PopSendQuerySystemPowerState(DeviceNode->PhysicalDeviceObject, + PowerStateContext->SystemPowerState, + PowerStateContext->PowerAction); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Device '%wZ' failed IRP_MN_QUERY_POWER\n", &DeviceNode->InstancePath); + } + +#if 0 + return Status; +#else + return STATUS_SUCCESS; +#endif +} + +NTSTATUS +PopSetSystemPowerStateTraverse(PDEVICE_NODE DeviceNode, + PVOID Context) +{ + PPOWER_STATE_TRAVERSE_CONTEXT PowerStateContext = Context; + NTSTATUS Status; + + DPRINT("PopSetSystemPowerStateTraverse(%p, %p)\n", DeviceNode, Context); + + if (DeviceNode == IopRootDeviceNode) + return STATUS_SUCCESS; + + if (DeviceNode->PhysicalDeviceObject == PowerStateContext->PowerDevice) + return STATUS_SUCCESS; + + if (DeviceNode->Flags & DNF_LEGACY_DRIVER) + return STATUS_SUCCESS; + + Status = PopSendSetSystemPowerState(DeviceNode->PhysicalDeviceObject, + PowerStateContext->SystemPowerState, + PowerStateContext->PowerAction); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Device '%wZ' failed IRP_MN_SET_POWER\n", &DeviceNode->InstancePath); + } + +#if 0 + return Status; +#else + return STATUS_SUCCESS; +#endif +} + +NTSTATUS +NTAPI +PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState, POWER_ACTION PowerAction) +{ + PDEVICE_OBJECT DeviceObject; + PDEVICE_OBJECT Fdo; + NTSTATUS Status; + DEVICETREE_TRAVERSE_CONTEXT Context; + POWER_STATE_TRAVERSE_CONTEXT PowerContext; + + Status = IopGetSystemPowerDeviceObject(&DeviceObject); + if (!NT_SUCCESS(Status)) + { + DPRINT1("No system power driver available\n"); + Fdo = NULL; + } + else + { + Fdo = IoGetAttachedDeviceReference(DeviceObject); + if (Fdo == DeviceObject) + { + DPRINT("An FDO was not attached\n"); + return STATUS_UNSUCCESSFUL; + } + } + + /* Set up context */ + PowerContext.PowerAction = PowerAction; + PowerContext.SystemPowerState = PowerState; + PowerContext.PowerDevice = Fdo; + + /* Query for system power change */ + IopInitDeviceTreeTraverseContext(&Context, + IopRootDeviceNode, + PopQuerySystemPowerStateTraverse, + &PowerContext); + + Status = IopTraverseDeviceTree(&Context); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Query system power state failed; changing state anyway\n"); + } + + /* Set system power change */ + IopInitDeviceTreeTraverseContext(&Context, + IopRootDeviceNode, + PopSetSystemPowerStateTraverse, + &PowerContext); + + IopTraverseDeviceTree(&Context); + + if (!PopAcpiPresent) return STATUS_NOT_IMPLEMENTED; + + if (Fdo != NULL) + { + if (PowerAction != PowerActionShutdownReset) + PopSendSetSystemPowerState(Fdo, PowerState, PowerAction); + + ObDereferenceObject(Fdo); + }
return Status; }