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.

593 lines
17 KiB

  1. /*++
  2. Copyright (c) 1990 Microsoft Corporation
  3. Module Name:
  4. poinit.c
  5. Abstract:
  6. Initialize power management component
  7. Author:
  8. Ken Reneris (kenr) 19-July-1994
  9. Revision History:
  10. --*/
  11. #include "pop.h"
  12. VOID
  13. PopRegisterForDeviceNotification (
  14. IN LPGUID Guid,
  15. IN POP_POLICY_DEVICE_TYPE DeviceType
  16. );
  17. #ifdef ALLOC_PRAGMA
  18. #pragma alloc_text(INIT, PoInitSystem)
  19. #pragma alloc_text(INIT, PopRegisterForDeviceNotification)
  20. #pragma alloc_text(INIT, PoInitDriverServices)
  21. #pragma alloc_text(PAGE, PoInitHiberServices)
  22. #pragma alloc_text(PAGE, PopDefaultPolicy)
  23. #pragma alloc_text(PAGE, PopDefaultProcessorPolicy)
  24. #endif
  25. BOOLEAN
  26. PoInitSystem(
  27. IN ULONG Phase
  28. )
  29. /*++
  30. Routine Description:
  31. This routine initializes the Power Manager.
  32. Arguments:
  33. None
  34. Return Value:
  35. The function value is a BOOLEAN indicating whether or not the Power Manager
  36. was successfully initialized.
  37. --*/
  38. {
  39. HANDLE handle;
  40. ULONG Length, i;
  41. UNICODE_STRING UnicodeString;
  42. NTSTATUS Status;
  43. PADMINISTRATOR_POWER_POLICY AdminPolicy;
  44. PPOP_HEURISTICS HeuristicData;
  45. struct {
  46. KEY_VALUE_PARTIAL_INFORMATION Inf;
  47. union {
  48. POP_HEURISTICS Heuristics;
  49. ADMINISTRATOR_POWER_POLICY AdminPolicy;
  50. } Data;
  51. } PartialInformation;
  52. if (Phase == 0) {
  53. //
  54. // irp serialization, notify network, etc.
  55. //
  56. KeInitializeSpinLock(&PopIrpSerialLock);
  57. KeInitializeSpinLock(&PopThermalLock);
  58. InitializeListHead(&PopIrpSerialList);
  59. InitializeListHead(&PopRequestedIrps);
  60. ExInitializeResourceLite(&PopNotifyLock);
  61. PopInvalidNotifyBlockCount = 0;
  62. PopIrpSerialListLength = 0;
  63. PopInrushPending = FALSE;
  64. PopInrushIrpPointer = NULL;
  65. PopInrushIrpReferenceCount = 0;
  66. KeInitializeSpinLock(&PopWorkerLock);
  67. PopCallSystemState = 0;
  68. ExInitializeWorkItem(&PopUnlockAfterSleepWorkItem,PopUnlockAfterSleepWorker,NULL);
  69. KeInitializeEvent(&PopUnlockComplete, SynchronizationEvent, TRUE);
  70. //
  71. // poshtdwn.c
  72. //
  73. PopInitShutdownList();
  74. //
  75. // idle.c
  76. //
  77. KeInitializeSpinLock(&PopDopeGlobalLock);
  78. InitializeListHead(&PopIdleDetectList);
  79. //
  80. // sidle.c
  81. //
  82. KeInitializeTimer(&PoSystemIdleTimer);
  83. KeQueryPerformanceCounter(&PopPerfCounterFrequency);
  84. //
  85. // policy workers
  86. //
  87. KeInitializeSpinLock (&PopWorkerSpinLock);
  88. InitializeListHead (&PopPolicyIrpQueue);
  89. ExInitializeWorkItem (&PopPolicyWorker, PopPolicyWorkerThread, UIntToPtr(PO_WORKER_STATUS));
  90. PopWorkerStatus = 0xffffffff;
  91. //
  92. // Policy manager
  93. //
  94. ExInitializeResourceLite (&PopPolicyLock);
  95. ExInitializeFastMutex (&PopVolumeLock);
  96. InitializeListHead (&PopVolumeDevices);
  97. InitializeListHead (&PopSwitches);
  98. InitializeListHead (&PopThermal);
  99. InitializeListHead (&PopActionWaiters);
  100. ExInitializeNPagedLookasideList(
  101. &PopIdleHandlerLookAsideList,
  102. NULL,
  103. NULL,
  104. 0,
  105. (sizeof(POP_IDLE_HANDLER) * MAX_IDLE_HANDLERS),
  106. POP_IDLE_TAG,
  107. (sizeof(POP_IDLE_HANDLER) * MAX_IDLE_HANDLERS * 3)
  108. );
  109. PopAction.Action = PowerActionNone;
  110. PopDefaultPolicy (&PopAcPolicy);
  111. PopDefaultPolicy (&PopDcPolicy);
  112. PopPolicy = &PopAcPolicy;
  113. PopDefaultProcessorPolicy( &PopAcProcessorPolicy );
  114. PopDefaultProcessorPolicy( &PopDcProcessorPolicy );
  115. PopProcessorPolicy = &PopAcProcessorPolicy;
  116. PopAdminPolicy.MinSleep = PowerSystemSleeping1;
  117. PopAdminPolicy.MaxSleep = PowerSystemHibernate;
  118. PopAdminPolicy.MinVideoTimeout = 0;
  119. PopAdminPolicy.MaxVideoTimeout = (ULONG) -1;
  120. PopAdminPolicy.MinSpindownTimeout = 0;
  121. PopAdminPolicy.MaxSpindownTimeout = (ULONG) -1;
  122. PopFullWake = PO_FULL_WAKE_STATUS | PO_GDI_STATUS;
  123. PopCoolingMode = PO_TZ_ACTIVE;
  124. //
  125. // Initialize composite battery status
  126. //
  127. KeInitializeEvent(&PopCB.Event, NotificationEvent, FALSE);
  128. for (i=0; i < PO_NUM_POWER_LEVELS; i++) {
  129. PopCB.Trigger[i].Type = PolicyDeviceBattery;
  130. }
  131. //
  132. // Note the code overloads some POP flags into an ES flags
  133. // Verify there's no overlap
  134. //
  135. ASSERT (!( (ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED | ES_USER_PRESENT) &
  136. (POP_LOW_LATENCY | POP_DISK_SPINDOWN)
  137. ) );
  138. //
  139. // Set the default shutdown handler just in case there's hal out there
  140. // that never registers a shutdown handler of his own. This will avoid
  141. // the possible scenario where someone asks the machine to shutdown and
  142. // it fails to call a shutdown handler (there isn't one), so it simply
  143. // reboots instead.
  144. //
  145. PopPowerStateHandlers[PowerStateShutdownOff].Type = PowerStateShutdownOff;
  146. PopPowerStateHandlers[PowerStateShutdownOff].RtcWake = FALSE;
  147. PopPowerStateHandlers[PowerStateShutdownOff].Handler = PopShutdownHandler;
  148. }
  149. if (Phase == 1) {
  150. //
  151. // Reload PopSimulate to pick up any overrides
  152. //
  153. PopInitializePowerPolicySimulate();
  154. //
  155. // For testing, if simulate flag is set turn on
  156. //
  157. if (PopSimulate & POP_SIM_CAPABILITIES) {
  158. PopCapabilities.SystemBatteriesPresent = TRUE;
  159. PopCapabilities.BatteryScale[0].Granularity = 100;
  160. PopCapabilities.BatteryScale[0].Capacity = 400;
  161. PopCapabilities.BatteryScale[1].Granularity = 10;
  162. PopCapabilities.BatteryScale[1].Capacity = 0xFFFF;
  163. PopCapabilities.RtcWake = PowerSystemSleeping3;
  164. PopCapabilities.DefaultLowLatencyWake = PowerSystemSleeping1;
  165. }
  166. //
  167. // For testing, if super simulate flag set turn all the capabilities
  168. // we can on
  169. //
  170. if (PopSimulate & POP_SIM_ALL_CAPABILITIES) {
  171. PopCapabilities.PowerButtonPresent = TRUE;
  172. PopCapabilities.SleepButtonPresent = TRUE;
  173. PopCapabilities.LidPresent = TRUE;
  174. PopCapabilities.SystemS1 = TRUE;
  175. PopCapabilities.SystemS2 = TRUE;
  176. PopCapabilities.SystemS3 = TRUE;
  177. PopCapabilities.SystemS4 = TRUE;
  178. PopAttributes[POP_DISK_SPINDOWN_ATTRIBUTE].Count += 1;
  179. }
  180. //
  181. // Load current status and policie information
  182. //
  183. PopAcquirePolicyLock ();
  184. Status = PopOpenPowerKey (&handle);
  185. if (NT_SUCCESS(Status)) {
  186. //
  187. // Read heuristics structure
  188. //
  189. RtlInitUnicodeString (&UnicodeString, PopHeuristicsRegName);
  190. Status = ZwQueryValueKey (
  191. handle,
  192. &UnicodeString,
  193. KeyValuePartialInformation,
  194. &PartialInformation,
  195. sizeof (PartialInformation),
  196. &Length
  197. );
  198. Length -= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
  199. HeuristicData = (PPOP_HEURISTICS) PartialInformation.Inf.Data;
  200. if (NT_SUCCESS(Status) &&
  201. Length == sizeof(PopHeuristics)) {
  202. //
  203. // If we see a version 2 heuristics field, it probably has a
  204. // bogus IoTransferWeight. So restart the sampling by setting
  205. // the number of samples to zero and update the version to the
  206. // current one. This little hack was put into place approx
  207. // build 1920 and can be probably be removed sometime after
  208. // shipping NT5 beta3
  209. //
  210. if (HeuristicData->Version <= POP_HEURISTICS_VERSION_CLEAR_TRANSFER) {
  211. HeuristicData->Version = POP_HEURISTICS_VERSION;
  212. HeuristicData->IoTransferSamples = 0;
  213. }
  214. if (HeuristicData->Version == POP_HEURISTICS_VERSION) {
  215. //
  216. // Restore values
  217. //
  218. RtlCopyMemory (&PopHeuristics, HeuristicData, sizeof(*HeuristicData));
  219. }
  220. }
  221. //
  222. // Verify sane values
  223. //
  224. PopHeuristics.Version = POP_HEURISTICS_VERSION;
  225. if (!PopHeuristics.IoTransferWeight) {
  226. PopHeuristics.IoTransferWeight = 999999;
  227. PopHeuristics.IoTransferSamples = 0;
  228. PopHeuristics.IoTransferTotal = 0;
  229. }
  230. //
  231. // Read administrator policy
  232. //
  233. RtlInitUnicodeString (&UnicodeString, PopAdminRegName);
  234. Status = ZwQueryValueKey (
  235. handle,
  236. &UnicodeString,
  237. KeyValuePartialInformation,
  238. &PartialInformation,
  239. sizeof (PartialInformation),
  240. &Length
  241. );
  242. Length -= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
  243. AdminPolicy = (PADMINISTRATOR_POWER_POLICY) PartialInformation.Inf.Data;
  244. if (NT_SUCCESS(Status)) {
  245. try {
  246. PopApplyAdminPolicy (FALSE, AdminPolicy, Length);
  247. } except (EXCEPTION_EXECUTE_HANDLER) {
  248. ASSERT (GetExceptionCode());
  249. }
  250. }
  251. NtClose (handle);
  252. }
  253. //
  254. // Read and apply the current policies
  255. //
  256. PopResetCurrentPolicies ();
  257. PopReleasePolicyLock (FALSE);
  258. //
  259. // Turn on idle detection
  260. //
  261. PopIdleScanTime.HighPart = 0;
  262. PopIdleScanTime.LowPart = 10*1000*1000 * PO_IDLE_SCAN_INTERVAL;
  263. KeInitializeTimer(&PopIdleScanTimer);
  264. KeSetTimerEx(
  265. &PopIdleScanTimer,
  266. PopIdleScanTime,
  267. PO_IDLE_SCAN_INTERVAL*1000, // call wants milliseconds
  268. &PopIdleScanDpc
  269. );
  270. }
  271. //
  272. // Success
  273. //
  274. return TRUE;
  275. }
  276. VOID
  277. PopDefaultPolicy (
  278. IN OUT PSYSTEM_POWER_POLICY Policy
  279. )
  280. {
  281. ULONG i;
  282. RtlZeroMemory (Policy, sizeof(SYSTEM_POWER_POLICY));
  283. Policy->Revision = 1;
  284. Policy->PowerButton.Action = PowerActionShutdownOff;
  285. Policy->SleepButton.Action = PowerActionSleep;
  286. Policy->LidClose.Action = PowerActionNone;
  287. Policy->LidOpenWake = PowerSystemWorking;
  288. Policy->MinSleep = PowerSystemSleeping1;
  289. Policy->MaxSleep = PowerSystemSleeping3;
  290. Policy->ReducedLatencySleep = PowerSystemSleeping1;
  291. Policy->WinLogonFlags = 0;
  292. Policy->FanThrottleTolerance = PO_NO_FAN_THROTTLE;
  293. Policy->ForcedThrottle = PO_NO_FORCED_THROTTLE;
  294. Policy->OverThrottled.Action = PowerActionNone;
  295. Policy->BroadcastCapacityResolution = 25;
  296. for (i=0; i < NUM_DISCHARGE_POLICIES; i++) {
  297. Policy->DischargePolicy[i].MinSystemState = PowerSystemSleeping1;
  298. }
  299. }
  300. VOID
  301. PopDefaultProcessorPolicy(
  302. IN OUT PPROCESSOR_POWER_POLICY Policy
  303. )
  304. {
  305. int i;
  306. RtlZeroMemory(Policy, sizeof(PROCESSOR_POWER_POLICY));
  307. Policy->Revision = 1;
  308. Policy->PolicyCount = 3;
  309. for (i = 0; i < 3; i++) {
  310. //
  311. // Initialize the entries to some common values
  312. //
  313. Policy->Policy[i].TimeCheck = PopIdleTimeCheck;
  314. Policy->Policy[i].PromoteLimit = PopIdleDefaultPromoteTime;
  315. Policy->Policy[i].DemoteLimit = PopIdleDefaultDemoteTime;
  316. Policy->Policy[i].PromotePercent = (UCHAR) PopIdleDefaultPromotePercent;
  317. Policy->Policy[i].DemotePercent = (UCHAR) PopIdleDefaultDemotePercent;
  318. Policy->Policy[i].AllowDemotion = 1;
  319. Policy->Policy[i].AllowPromotion = 1;
  320. //
  321. // Special cases
  322. //
  323. if (i == 0) {
  324. Policy->Policy[i].PromoteLimit = PopIdleDefaultPromoteFromC1Time;
  325. Policy->Policy[i].PromotePercent = (UCHAR) PopIdleDefaultPromoteFromC1Percent;
  326. Policy->Policy[i].TimeCheck = PopIdle0TimeCheck;
  327. //
  328. // Do Something special if we are a multiprocessor machine..
  329. //
  330. if (KeNumberProcessors > 1) {
  331. Policy->Policy[i].DemotePercent = (UCHAR) PopIdleTo0Percent;
  332. } else {
  333. Policy->Policy[i].DemotePercent = 0;
  334. Policy->Policy[i].AllowDemotion = 0;
  335. }
  336. } else if (i == 1) {
  337. Policy->Policy[i].DemoteLimit = PopIdleDefaultDemoteToC1Time;
  338. Policy->Policy[i].DemotePercent = (UCHAR) PopIdleDefaultDemoteToC1Percent;
  339. } else if (i == 2) {
  340. Policy->Policy[i].AllowPromotion = 0;
  341. Policy->Policy[i].PromoteLimit = (ULONG) -1;
  342. Policy->Policy[i].PromotePercent = 0;
  343. }
  344. }
  345. }
  346. VOID
  347. PoInitDriverServices (
  348. IN ULONG Phase
  349. )
  350. {
  351. ULONG TickRate;
  352. LARGE_INTEGER PerfRate;
  353. if (Phase == 0) {
  354. TickRate = KeQueryTimeIncrement();
  355. KeQueryPerformanceCounter (&PerfRate);
  356. //
  357. // Connect to any policy devices which arrive
  358. //
  359. PopRegisterForDeviceNotification (
  360. (LPGUID) &GUID_CLASS_INPUT,
  361. PolicyDeviceSystemButton
  362. );
  363. PopRegisterForDeviceNotification (
  364. (LPGUID) &GUID_DEVICE_THERMAL_ZONE,
  365. PolicyDeviceThermalZone
  366. );
  367. PopRegisterForDeviceNotification (
  368. (LPGUID) &GUID_DEVICE_SYS_BUTTON,
  369. PolicyDeviceSystemButton
  370. );
  371. PopRegisterForDeviceNotification (
  372. (LPGUID) &GUID_DEVICE_BATTERY,
  373. PolicyDeviceBattery
  374. );
  375. //
  376. // Initialize global idle values
  377. //
  378. PopIdle0PromoteTicks = PopIdleFrom0Delay * US2TIME / TickRate + 1;
  379. PopIdle0PromoteLimit = (PopIdleFrom0Delay * US2TIME / TickRate) * 100 /
  380. PopIdleFrom0IdlePercent;
  381. //
  382. // Initialize global perf values
  383. //
  384. PopPerfTimeTicks = PopPerfTimeDelta * US2TIME / TickRate + 1;
  385. PopPerfCriticalTimeTicks = PopPerfCriticalTimeDelta * US2TIME / TickRate + 1;
  386. //
  387. // Initialize DPC for idle device timer
  388. //
  389. KeInitializeDpc(&PopIdleScanDpc, PopScanIdleList, NULL);
  390. return ;
  391. }
  392. }
  393. VOID
  394. PopRegisterForDeviceNotification (
  395. IN LPGUID Guid,
  396. IN POP_POLICY_DEVICE_TYPE DeviceType
  397. )
  398. {
  399. NTSTATUS Status;
  400. PVOID junk;
  401. Status = IoRegisterPlugPlayNotification (
  402. EventCategoryDeviceInterfaceChange,
  403. 0,
  404. Guid,
  405. IoPnpDriverObject,
  406. PopNotifyPolicyDevice,
  407. (PVOID) DeviceType,
  408. &junk
  409. );
  410. ASSERT (NT_SUCCESS(Status));
  411. }
  412. VOID
  413. PoInitHiberServices (
  414. IN BOOLEAN Setup
  415. )
  416. /*++
  417. Routine Description:
  418. This routine reserves the hiberfile if the function has been enabled.
  419. It is called after autocheck (chkdsk) has run and the paging files
  420. have been opened. (as performing IO to the hiberfil before this
  421. time will mark the volume as dirty causing chkdsk to be required)
  422. N.B. Caller's pervious mode must be kernel mode
  423. Arguments:
  424. SetupBoot - if TRUE this is text mode setup boot
  425. if FALSE this is normal system boot
  426. Return Value:
  427. none
  428. --*/
  429. {
  430. NTSTATUS Status;
  431. SYSTEM_POWER_CAPABILITIES PowerCapabilities;
  432. //
  433. // If a hiber file was reserved before then try to reserve one this
  434. // time too.
  435. //
  436. Status = ZwPowerInformation(SystemPowerCapabilities,
  437. NULL,
  438. 0,
  439. &PowerCapabilities,
  440. sizeof(SYSTEM_POWER_CAPABILITIES));
  441. ASSERT(NT_SUCCESS(Status));
  442. if (PopHeuristics.HiberFileEnabled) {
  443. PopAcquirePolicyLock();
  444. PopEnableHiberFile(TRUE);
  445. //
  446. // If the system does not support S4 anymore (because someone enabled PAE
  447. // or installed a legacy driver) then delete the hiberfile now. Note we have
  448. // to enable it before disabling it or the file doesn't get deleted.
  449. //
  450. // Also force HiberFileEnabled back to TRUE in PopHeuristics. This is so we
  451. // will try and reenable hibernation on the next boot. So if someone boots to
  452. // safe mode, hibernation will still be enabled after they reboot.
  453. //
  454. if (!PowerCapabilities.SystemS4) {
  455. PopEnableHiberFile(FALSE);
  456. PopHeuristics.HiberFileEnabled = TRUE;
  457. PopHeuristics.Dirty = TRUE;
  458. PopSaveHeuristics();
  459. }
  460. PopReleasePolicyLock(TRUE);
  461. }
  462. //
  463. // Base drivers are loaded, start dispatching policy irps
  464. //
  465. PopDispatchPolicyIrps = TRUE;
  466. PopGetPolicyWorker (PO_WORKER_MAIN);
  467. PopCheckForWork (TRUE);
  468. }