180 lines
3.7 KiB
C
180 lines
3.7 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
state.c
|
||
|
||
Abstract:
|
||
|
||
Maintains state changes for power management power states
|
||
for device objects
|
||
|
||
Author:
|
||
|
||
Ken Reneris (kenr) 19-July-1994
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "pop.h"
|
||
|
||
|
||
|
||
// sync rules - only PoSetPowerState ever writes to the
|
||
// StateValue entries in the psb.
|
||
//
|
||
|
||
NTKERNELAPI
|
||
POWER_STATE
|
||
PoSetPowerState (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN POWER_STATE_TYPE Type,
|
||
IN POWER_STATE State
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine stores the new power state for a device object,
|
||
calling notification routines, if any, first.
|
||
|
||
If the new state and old state are the same, this procedure
|
||
is a noop
|
||
|
||
A note on synchronization:
|
||
|
||
No lock is acquire just to set the values. This is because
|
||
it is assumed that only this routine writes them, so locking
|
||
is not necessary.
|
||
|
||
If the notify list is to be run, a lock will be acquired.
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - pointer to the device object to set the power
|
||
state for and to issue any notifications for
|
||
|
||
Type - indicates whether System or Device state is being set
|
||
|
||
State - the System or Device state to set
|
||
|
||
Return Value:
|
||
|
||
The Old power state.
|
||
|
||
--*/
|
||
{
|
||
PDEVOBJ_EXTENSION doe;
|
||
PDEVICE_OBJECT_POWER_EXTENSION dope;
|
||
POWER_STATE OldState;
|
||
BOOLEAN change;
|
||
ULONG notificationmask;
|
||
KIRQL OldIrql, OldIrql2;
|
||
|
||
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
||
|
||
|
||
PoPowerTrace(POWERTRACE_SETSTATE,DeviceObject,(ULONG)Type,(ULONG)State.SystemState);
|
||
|
||
doe = DeviceObject->DeviceObjectExtension;
|
||
dope = doe->Dope;
|
||
|
||
PopLockIrpSerialList(&OldIrql2);
|
||
|
||
notificationmask = 0L;
|
||
change = FALSE;
|
||
|
||
switch (Type) {
|
||
|
||
case SystemPowerState:
|
||
OldState.SystemState = PopGetDoSystemPowerState(doe);
|
||
if (OldState.SystemState != State.SystemState) {
|
||
change = TRUE;
|
||
}
|
||
break;
|
||
|
||
case DevicePowerState:
|
||
OldState.DeviceState = PopGetDoDevicePowerState(doe);
|
||
if (OldState.DeviceState != State.DeviceState) {
|
||
change = TRUE;
|
||
if (OldState.DeviceState == PowerDeviceD0) {
|
||
notificationmask = PO_NOTIFY_TRANSITIONING_FROM_D0;
|
||
} else if (State.DeviceState == PowerDeviceD0) {
|
||
notificationmask = PO_NOTIFY_D0;
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
if (! change) {
|
||
PopUnlockIrpSerialList(OldIrql2);
|
||
return OldState;
|
||
}
|
||
|
||
//
|
||
// We know what is going to happen. Always store the changed
|
||
// state first, so we can drop the lock and do the notification.
|
||
//
|
||
|
||
switch (Type) {
|
||
|
||
case SystemPowerState:
|
||
PopSetDoSystemPowerState(doe, State.SystemState);
|
||
break;
|
||
|
||
case DevicePowerState:
|
||
PopSetDoDevicePowerState(doe, State.DeviceState);
|
||
break;
|
||
}
|
||
|
||
PopUnlockIrpSerialList(OldIrql2);
|
||
|
||
//
|
||
// If anything to notify...
|
||
//
|
||
if (notificationmask && dope) {
|
||
PopStateChangeNotify(DeviceObject, notificationmask);
|
||
}
|
||
|
||
return OldState;
|
||
}
|
||
|
||
|
||
DEVICE_POWER_STATE
|
||
PopLockGetDoDevicePowerState(
|
||
IN PDEVOBJ_EXTENSION Doe
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Function which returns the power state of the specified device.
|
||
Unlike PopGetDoDevicePowerState, this routine also acquires and
|
||
releases the appropriate spinlock.
|
||
|
||
Arguments:
|
||
|
||
Doe - Supplies the devobj_extension of the device.
|
||
|
||
Return Value:
|
||
|
||
DEVICE_POWER_STATE
|
||
|
||
--*/
|
||
|
||
{
|
||
KIRQL OldIrql;
|
||
DEVICE_POWER_STATE State;
|
||
|
||
PopLockIrpSerialList(&OldIrql);
|
||
State = PopGetDoDevicePowerState(Doe);
|
||
PopUnlockIrpSerialList(OldIrql);
|
||
|
||
return(State);
|
||
}
|
||
|