Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

179 lines
3.7 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. state.c
  5. Abstract:
  6. Maintains state changes for power management power states
  7. for device objects
  8. Author:
  9. Ken Reneris (kenr) 19-July-1994
  10. Revision History:
  11. --*/
  12. #include "pop.h"
  13. // sync rules - only PoSetPowerState ever writes to the
  14. // StateValue entries in the psb.
  15. //
  16. NTKERNELAPI
  17. POWER_STATE
  18. PoSetPowerState (
  19. IN PDEVICE_OBJECT DeviceObject,
  20. IN POWER_STATE_TYPE Type,
  21. IN POWER_STATE State
  22. )
  23. /*++
  24. Routine Description:
  25. This routine stores the new power state for a device object,
  26. calling notification routines, if any, first.
  27. If the new state and old state are the same, this procedure
  28. is a noop
  29. A note on synchronization:
  30. No lock is acquire just to set the values. This is because
  31. it is assumed that only this routine writes them, so locking
  32. is not necessary.
  33. If the notify list is to be run, a lock will be acquired.
  34. Arguments:
  35. DeviceObject - pointer to the device object to set the power
  36. state for and to issue any notifications for
  37. Type - indicates whether System or Device state is being set
  38. State - the System or Device state to set
  39. Return Value:
  40. The Old power state.
  41. --*/
  42. {
  43. PDEVOBJ_EXTENSION doe;
  44. PDEVICE_OBJECT_POWER_EXTENSION dope;
  45. POWER_STATE OldState;
  46. BOOLEAN change;
  47. ULONG notificationmask;
  48. KIRQL OldIrql, OldIrql2;
  49. ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
  50. PoPowerTrace(POWERTRACE_SETSTATE,DeviceObject,(ULONG)Type,(ULONG)State.SystemState);
  51. doe = DeviceObject->DeviceObjectExtension;
  52. dope = doe->Dope;
  53. PopLockIrpSerialList(&OldIrql2);
  54. notificationmask = 0L;
  55. change = FALSE;
  56. switch (Type) {
  57. case SystemPowerState:
  58. OldState.SystemState = PopGetDoSystemPowerState(doe);
  59. if (OldState.SystemState != State.SystemState) {
  60. change = TRUE;
  61. }
  62. break;
  63. case DevicePowerState:
  64. OldState.DeviceState = PopGetDoDevicePowerState(doe);
  65. if (OldState.DeviceState != State.DeviceState) {
  66. change = TRUE;
  67. if (OldState.DeviceState == PowerDeviceD0) {
  68. notificationmask = PO_NOTIFY_TRANSITIONING_FROM_D0;
  69. } else if (State.DeviceState == PowerDeviceD0) {
  70. notificationmask = PO_NOTIFY_D0;
  71. }
  72. }
  73. break;
  74. }
  75. if (! change) {
  76. PopUnlockIrpSerialList(OldIrql2);
  77. return OldState;
  78. }
  79. //
  80. // We know what is going to happen. Always store the changed
  81. // state first, so we can drop the lock and do the notification.
  82. //
  83. switch (Type) {
  84. case SystemPowerState:
  85. PopSetDoSystemPowerState(doe, State.SystemState);
  86. break;
  87. case DevicePowerState:
  88. PopSetDoDevicePowerState(doe, State.DeviceState);
  89. break;
  90. }
  91. PopUnlockIrpSerialList(OldIrql2);
  92. //
  93. // If anything to notify...
  94. //
  95. if (notificationmask && dope) {
  96. PopStateChangeNotify(DeviceObject, notificationmask);
  97. }
  98. return OldState;
  99. }
  100. DEVICE_POWER_STATE
  101. PopLockGetDoDevicePowerState(
  102. IN PDEVOBJ_EXTENSION Doe
  103. )
  104. /*++
  105. Routine Description:
  106. Function which returns the power state of the specified device.
  107. Unlike PopGetDoDevicePowerState, this routine also acquires and
  108. releases the appropriate spinlock.
  109. Arguments:
  110. Doe - Supplies the devobj_extension of the device.
  111. Return Value:
  112. DEVICE_POWER_STATE
  113. --*/
  114. {
  115. KIRQL OldIrql;
  116. DEVICE_POWER_STATE State;
  117. PopLockIrpSerialList(&OldIrql);
  118. State = PopGetDoDevicePowerState(Doe);
  119. PopUnlockIrpSerialList(OldIrql);
  120. return(State);
  121. }