Leaked source code of windows server 2003
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.

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