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.

506 lines
8.7 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. attrib.c
  5. Abstract:
  6. Power management attribute accounting
  7. Author:
  8. Ken Reneris (kenr) 25-Feb-97
  9. Revision History:
  10. --*/
  11. #include "pop.h"
  12. VOID
  13. PopUserPresentSetWorker(
  14. PVOID Context
  15. );
  16. //
  17. // System state structure to track registered settings
  18. //
  19. typedef struct {
  20. ULONG State;
  21. } POP_SYSTEM_STATE, *PPOP_SYSTEM_STATE;
  22. #ifdef ALLOC_PRAGMA
  23. #pragma alloc_text(PAGE, PopUserPresentSetWorker)
  24. #endif
  25. VOID
  26. PoSetSystemState (
  27. IN ULONG Flags
  28. )
  29. /*++
  30. Routine Description:
  31. Used to pulse attribute(s) as busy.
  32. Arguments:
  33. Flags - Attributes to pulse
  34. Return Value:
  35. None.
  36. --*/
  37. {
  38. //
  39. // Verify reserved bits are clear and continous is not set
  40. //
  41. if (Flags & ~(ES_DISPLAY_REQUIRED | ES_SYSTEM_REQUIRED | POP_LOW_LATENCY | ES_USER_PRESENT)) {
  42. PopInternalError (POP_ATTRIB);
  43. }
  44. //
  45. // Apply the attributes
  46. //
  47. PopApplyAttributeState (Flags, 0);
  48. //
  49. // Check for work
  50. //
  51. PopCheckForWork (TRUE);
  52. }
  53. PVOID
  54. PoRegisterSystemState (
  55. IN PVOID StateHandle,
  56. IN ULONG NewFlags
  57. )
  58. /*++
  59. Routine Description:
  60. Used to register or pulse attribute(s) as busy.
  61. Arguments:
  62. StateHandle - If StateHandle is null, then a new registration is allocated, set
  63. accordingly, and returned. If non-null, the pass registeration
  64. is adjusted to its new setting.
  65. NewFlags - Attributes to set or pulse
  66. Return Value:
  67. Handle to unregister when complete
  68. --*/
  69. {
  70. ULONG OldFlags;
  71. PPOP_SYSTEM_STATE SystemState;
  72. //
  73. // Verify reserved bits are clear
  74. //
  75. if (NewFlags & ~(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED |
  76. POP_LOW_LATENCY | ES_USER_PRESENT)) {
  77. PopInternalError (POP_ATTRIB);
  78. }
  79. //
  80. // If there's no state handle allocated, do it now
  81. //
  82. if (!StateHandle) {
  83. StateHandle = ExAllocatePoolWithTag (
  84. NonPagedPool,
  85. sizeof (POP_SYSTEM_STATE),
  86. POP_PSTA_TAG
  87. );
  88. if (!StateHandle) {
  89. return NULL;
  90. }
  91. RtlZeroMemory(StateHandle, sizeof(POP_SYSTEM_STATE));
  92. }
  93. //
  94. // If the continous bit is set, modify current flags
  95. //
  96. SystemState = (PPOP_SYSTEM_STATE) StateHandle;
  97. OldFlags = SystemState->State | ES_CONTINUOUS;
  98. if (NewFlags & ES_CONTINUOUS) {
  99. OldFlags = InterlockedExchange (&SystemState->State, NewFlags);
  100. }
  101. //
  102. // Apply the changes
  103. //
  104. PopApplyAttributeState (NewFlags, OldFlags);
  105. //
  106. // Check for any outstanding work
  107. //
  108. PopCheckForWork (FALSE);
  109. //
  110. // Done
  111. //
  112. return SystemState;
  113. }
  114. VOID
  115. PoUnregisterSystemState (
  116. IN PVOID StateHandle
  117. )
  118. /*++
  119. Routine Description:
  120. Frees a registration allocated by PoRegisterSystemState
  121. Arguments:
  122. StateHandle - If non-null, existing registeration to change
  123. NewFlags - Attributes to set or pulse
  124. Return Value:
  125. Handle to unregister when complete
  126. --*/
  127. {
  128. //
  129. // Make sure current attribute settings are clear
  130. //
  131. PoRegisterSystemState (StateHandle, ES_CONTINUOUS);
  132. //
  133. // Free state structure
  134. //
  135. ExFreePool (StateHandle);
  136. }
  137. VOID
  138. PopApplyAttributeState (
  139. IN ULONG NewFlags,
  140. IN ULONG OldFlags
  141. )
  142. /*++
  143. Routine Description:
  144. Function applies attribute flags to system. If the attributes
  145. are continuous in nature, then a count is updated to reflect
  146. the total number of outstanding settings.
  147. Arguments:
  148. NewFlags - Attributes being set
  149. OldFlags - Current attributes
  150. Return Value:
  151. None.
  152. --*/
  153. {
  154. ULONG i;
  155. ULONG Count;
  156. ULONG Changes;
  157. ULONG Mask;
  158. PPOP_STATE_ATTRIBUTE Attribute;
  159. //
  160. // Get flags which have changed
  161. //
  162. Changes = (NewFlags ^ OldFlags) & ~ES_CONTINUOUS;
  163. //
  164. // Check each flag
  165. //
  166. while (Changes) {
  167. //
  168. // Get change
  169. //
  170. i = KeFindFirstSetRightMember(Changes);
  171. Mask = 1 << i;
  172. Changes &= ~Mask;
  173. Attribute = PopAttributes + i;
  174. //
  175. // If this is a continous change, update the flags
  176. //
  177. if (NewFlags & ES_CONTINUOUS) {
  178. //
  179. // Count the times the attribite is set or cleared
  180. //
  181. if (NewFlags & Mask) {
  182. //
  183. // Being set
  184. //
  185. Count = InterlockedIncrement (&Attribute->Count);
  186. //
  187. // If attributes count is moved from zero, set it
  188. //
  189. if (Count == 1) {
  190. Attribute->Set (Attribute->Arg);
  191. }
  192. } else {
  193. //
  194. // Being cleared
  195. //
  196. Count = InterlockedDecrement (&Attribute->Count);
  197. ASSERT (Count != -1);
  198. //
  199. // If attributes count is now zero, clear it
  200. //
  201. if (Count == 0 && Attribute->NotifyOnClear) {
  202. Attribute->Set (Attribute->Arg);
  203. }
  204. }
  205. } else {
  206. //
  207. // If count is 0, pulse it
  208. //
  209. if (Attribute->Count == 0) {
  210. //
  211. // Pulse the attribute
  212. //
  213. Attribute->Set (Attribute->Arg);
  214. }
  215. }
  216. }
  217. }
  218. VOID
  219. PopAttribNop (
  220. IN ULONG Arg
  221. )
  222. {
  223. }
  224. VOID
  225. PopSystemRequiredSet (
  226. IN ULONG Arg
  227. )
  228. /*++
  229. Routine Description:
  230. System required attribute has been set
  231. Arguments:
  232. None
  233. Return Value:
  234. None.
  235. --*/
  236. {
  237. //
  238. // System is not idle
  239. //
  240. if (PopSIdle.Time) {
  241. PopSIdle.Time = 0;
  242. }
  243. }
  244. #define AllBitsSet(a,b) ( ((a) & (b)) == (b) )
  245. VOID
  246. PopDisplayRequired (
  247. IN ULONG Arg
  248. )
  249. /*++
  250. Routine Description:
  251. Display required attribute has been set/cleared
  252. Arguments:
  253. None
  254. Return Value:
  255. None.
  256. --*/
  257. {
  258. //
  259. // If gdi isn't on, do it now
  260. //
  261. if ( !AnyBitsSet (PopFullWake, PO_GDI_STATUS | PO_GDI_ON_PENDING)) {
  262. InterlockedOr (&PopFullWake, PO_GDI_ON_PENDING);
  263. }
  264. //
  265. // Inform GDI of the display needed change
  266. //
  267. PopSetNotificationWork (PO_NOTIFY_DISPLAY_REQUIRED);
  268. }
  269. VOID
  270. PopUserPresentSet (
  271. IN ULONG Arg
  272. )
  273. /*++
  274. Routine Description:
  275. User presence attribute has been set
  276. Arguments:
  277. None
  278. Return Value:
  279. None.
  280. --*/
  281. {
  282. PULONG runningWorker;
  283. //
  284. // System is not idle
  285. //
  286. if (PopSIdle.Time) {
  287. PopSIdle.Time = 0;
  288. }
  289. //
  290. // If the system isn't fully awake, and the all the wake pending bits
  291. // are not set, set them
  292. //
  293. if (!AllBitsSet (PopFullWake, PO_FULL_WAKE_STATUS | PO_GDI_STATUS)) {
  294. if (!AllBitsSet (PopFullWake, PO_FULL_WAKE_PENDING | PO_GDI_ON_PENDING)) {
  295. InterlockedOr (&PopFullWake, (PO_FULL_WAKE_PENDING | PO_GDI_ON_PENDING));
  296. PopSetNotificationWork (PO_NOTIFY_FULL_WAKE);
  297. }
  298. }
  299. //
  300. // Go to passive level to look for lid switches.
  301. //
  302. runningWorker = InterlockedExchangePointer(&PopUserPresentWorkItem.Parameter,
  303. (PVOID)TRUE);
  304. if (runningWorker) {
  305. return;
  306. }
  307. ExInitializeWorkItem(&PopUserPresentWorkItem,
  308. PopUserPresentSetWorker,
  309. PopUserPresentWorkItem.Parameter);
  310. ExQueueWorkItem(
  311. &PopUserPresentWorkItem,
  312. DelayedWorkQueue
  313. );
  314. }
  315. VOID
  316. PopUserPresentSetWorker(
  317. PVOID Context
  318. )
  319. {
  320. PPOP_SWITCH_DEVICE switchDev;
  321. PAGED_CODE();
  322. //
  323. // We can't always know for sure whether the lid (if there is one)
  324. // is opened or closed. Assume that if the user is present,
  325. // the lid is opened.
  326. //
  327. switchDev = (PPOP_SWITCH_DEVICE)PopSwitches.Flink;
  328. while (switchDev != (PPOP_SWITCH_DEVICE)&PopSwitches) {
  329. if ((switchDev->Caps & SYS_BUTTON_LID) &&
  330. (switchDev->Opened == FALSE)) {
  331. //
  332. // We currently believe that the lid is closed. Set
  333. // it to "opened."
  334. //
  335. switchDev->Opened = TRUE;
  336. //
  337. // Notify the PowerState callback.
  338. //
  339. ExNotifyCallback (
  340. ExCbPowerState,
  341. UIntToPtr(PO_CB_LID_SWITCH_STATE),
  342. UIntToPtr(switchDev->Opened)
  343. );
  344. }
  345. switchDev = (PPOP_SWITCH_DEVICE)switchDev->Link.Flink;
  346. }
  347. InterlockedExchangePointer(&PopUserPresentWorkItem.Parameter,
  348. (PVOID)FALSE);
  349. }