3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/po/power.c
6 * PURPOSE: Power Manager
8 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * Hervé Poussineau (hpoussin@reactos.com)
14 #include <internal/debug.h>
16 extern ULONG ExpInitialiationPhase
;
18 typedef struct _REQUEST_POWER_ITEM
20 PREQUEST_POWER_COMPLETE CompletionRoutine
;
21 POWER_STATE PowerState
;
23 } REQUEST_POWER_ITEM
, *PREQUEST_POWER_ITEM
;
25 PDEVICE_NODE PopSystemPowerDeviceNode
= NULL
;
26 BOOLEAN PopAcpiPresent
= FALSE
;
34 IN PDEVICE_OBJECT DeviceObject
,
39 Status
= IoCallDriver(DeviceObject
, Irp
);
49 PoRegisterDeviceForIdleDetection(
50 IN PDEVICE_OBJECT DeviceObject
,
51 IN ULONG ConservationIdleTime
,
52 IN ULONG PerformanceIdleTime
,
53 IN DEVICE_POWER_STATE State
)
63 PoRegisterSystemState(
65 IN EXECUTION_STATE Flags
)
72 PopRequestPowerIrpCompletion(
73 IN PDEVICE_OBJECT DeviceObject
,
77 PIO_STACK_LOCATION Stack
;
78 PREQUEST_POWER_ITEM RequestPowerItem
;
80 Stack
= IoGetNextIrpStackLocation(Irp
);
81 RequestPowerItem
= (PREQUEST_POWER_ITEM
)Context
;
83 RequestPowerItem
->CompletionRoutine(
86 RequestPowerItem
->PowerState
,
87 RequestPowerItem
->Context
,
90 ExFreePool(&Irp
->IoStatus
);
92 return STATUS_SUCCESS
;
101 IN PDEVICE_OBJECT DeviceObject
,
102 IN UCHAR MinorFunction
,
103 IN POWER_STATE PowerState
,
104 IN PREQUEST_POWER_COMPLETE CompletionFunction
,
106 OUT PIRP
*pIrp OPTIONAL
)
108 PDEVICE_OBJECT TopDeviceObject
;
109 PIO_STACK_LOCATION Stack
;
111 PIO_STATUS_BLOCK IoStatusBlock
;
112 PREQUEST_POWER_ITEM RequestPowerItem
;
115 if (MinorFunction
!= IRP_MN_QUERY_POWER
116 && MinorFunction
!= IRP_MN_SET_POWER
117 && MinorFunction
!= IRP_MN_WAIT_WAKE
)
118 return STATUS_INVALID_PARAMETER_2
;
120 RequestPowerItem
= ExAllocatePool(NonPagedPool
, sizeof(REQUEST_POWER_ITEM
));
121 if (!RequestPowerItem
)
122 return STATUS_INSUFFICIENT_RESOURCES
;
123 IoStatusBlock
= ExAllocatePool(NonPagedPool
, sizeof(IO_STATUS_BLOCK
));
126 ExFreePool(RequestPowerItem
);
127 return STATUS_INSUFFICIENT_RESOURCES
;
130 /* Always call the top of the device stack */
131 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
133 Irp
= IoBuildSynchronousFsdRequest(
143 ExFreePool(RequestPowerItem
);
144 ExFreePool(IoStatusBlock
);
145 return STATUS_INSUFFICIENT_RESOURCES
;
148 /* POWER IRPs are always initialized with a status code of
149 STATUS_NOT_IMPLEMENTED */
150 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
151 Irp
->IoStatus
.Information
= 0;
153 Stack
= IoGetNextIrpStackLocation(Irp
);
154 Stack
->MinorFunction
= MinorFunction
;
155 if (MinorFunction
== IRP_MN_WAIT_WAKE
)
156 Stack
->Parameters
.WaitWake
.PowerState
= PowerState
.SystemState
;
158 Stack
->Parameters
.WaitWake
.PowerState
= PowerState
.DeviceState
;
160 RequestPowerItem
->CompletionRoutine
= CompletionFunction
;
161 RequestPowerItem
->PowerState
= PowerState
;
162 RequestPowerItem
->Context
= Context
;
167 IoSetCompletionRoutine(Irp
, PopRequestPowerIrpCompletion
, RequestPowerItem
, TRUE
, TRUE
, TRUE
);
168 Status
= IoCallDriver(TopDeviceObject
, Irp
);
170 /* Always return STATUS_PENDING. The completion routine
171 * will call CompletionFunction and complete the Irp.
173 return STATUS_PENDING
;
176 #undef PoSetDeviceBusy
179 PoSetDeviceBusy(IN PULONG IdlePointer
)
186 PopCleanupPowerState(IN PPOWER_STATE PowerState
)
197 IN PDEVICE_OBJECT DeviceObject
,
198 IN POWER_STATE_TYPE Type
,
199 IN POWER_STATE State
)
203 ASSERT_IRQL(DISPATCH_LEVEL
);
205 ps
.SystemState
= PowerSystemWorking
; // Fully on
206 ps
.DeviceState
= PowerDeviceD0
; // Fully on
217 IN EXECUTION_STATE Flags
)
236 PoUnregisterSystemState(
237 IN PVOID StateHandle
)
243 PopSetSystemPowerState(
244 SYSTEM_POWER_STATE PowerState
)
246 IO_STATUS_BLOCK IoStatusBlock
;
247 PDEVICE_OBJECT DeviceObject
;
248 PIO_STACK_LOCATION IrpSp
;
254 if (!PopAcpiPresent
) return STATUS_NOT_IMPLEMENTED
;
256 Status
= IopGetSystemPowerDeviceObject(&DeviceObject
);
257 if (!NT_SUCCESS(Status
)) {
258 CPRINT("No system power driver available\n");
259 return STATUS_UNSUCCESSFUL
;
262 Fdo
= IoGetAttachedDeviceReference(DeviceObject
);
264 if (Fdo
== DeviceObject
)
266 DPRINT("An FDO was not attached\n");
267 return STATUS_UNSUCCESSFUL
;
270 KeInitializeEvent(&Event
,
274 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_POWER
,
282 IrpSp
= IoGetNextIrpStackLocation(Irp
);
283 IrpSp
->MinorFunction
= IRP_MN_SET_POWER
;
284 IrpSp
->Parameters
.Power
.Type
= SystemPowerState
;
285 IrpSp
->Parameters
.Power
.State
.SystemState
= PowerState
;
287 Status
= PoCallDriver(Fdo
, Irp
);
288 if (Status
== STATUS_PENDING
)
290 KeWaitForSingleObject(&Event
,
295 Status
= IoStatusBlock
.Status
;
298 ObDereferenceObject(Fdo
);
305 PoInitSystem(IN ULONG BootPhase
,
306 IN BOOLEAN HaveAcpiTable
)
308 PVOID NotificationEntry
;
310 BOOLEAN ForceAcpiDisable
= FALSE
;
312 /* Check if this is phase 1 init */
315 /* Registry power button notification */
316 IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange
,
317 0, /* The registry has not been initialized yet */
318 (PVOID
)&GUID_DEVICE_SYS_BUTTON
,
320 PhysicalDeviceObject
->DriverObject
,
321 PopAddRemoveSysCapsCallback
,
327 /* Get the Command Line */
328 CommandLine
= KeLoaderBlock
->LoadOptions
;
331 _strupr(CommandLine
);
333 /* Check for ACPI disable */
334 if (strstr(CommandLine
, "NOACPI")) ForceAcpiDisable
= TRUE
;
336 if (ForceAcpiDisable
)
338 /* Set the ACPI State to False if it's been forced that way */
339 PopAcpiPresent
= FALSE
;
343 /* Otherwise check the LoaderBlock's Flag */
344 PopAcpiPresent
= HaveAcpiTable
;
352 PopPerfIdle(PPROCESSOR_POWER_STATE PowerState
)
354 DPRINT1("PerfIdle function: %p\n", PowerState
);
359 PopPerfIdleDpc(IN PKDPC Dpc
,
360 IN PVOID DeferredContext
,
361 IN PVOID SystemArgument1
,
362 IN PVOID SystemArgument2
)
364 /* Call the Perf Idle function */
365 PopPerfIdle(&((PKPRCB
)DeferredContext
)->PowerState
);
370 PopIdle0(IN PPROCESSOR_POWER_STATE PowerState
)
372 /* FIXME: Extremly naive implementation */
378 PoInitializePrcb(IN PKPRCB Prcb
)
380 /* Initialize the Power State */
381 RtlZeroMemory(&Prcb
->PowerState
, sizeof(Prcb
->PowerState
));
382 Prcb
->PowerState
.Idle0KernelTimeLimit
= 0xFFFFFFFF;
383 Prcb
->PowerState
.CurrentThrottle
= 100;
384 Prcb
->PowerState
.CurrentThrottleIndex
= 0;
385 Prcb
->PowerState
.IdleFunction
= PopIdle0
;
387 /* Initialize the Perf DPC and Timer */
388 KeInitializeDpc(&Prcb
->PowerState
.PerfDpc
, PopPerfIdleDpc
, Prcb
);
389 KeSetTargetProcessorDpc(&Prcb
->PowerState
.PerfDpc
, Prcb
->Number
);
390 KeInitializeTimerEx(&Prcb
->PowerState
.PerfTimer
, SynchronizationTimer
);
398 NtInitiatePowerAction (
399 IN POWER_ACTION SystemAction
,
400 IN SYSTEM_POWER_STATE MinSystemState
,
402 IN BOOLEAN Asynchronous
)
405 return STATUS_NOT_IMPLEMENTED
;
414 IN POWER_INFORMATION_LEVEL PowerInformationLevel
,
415 IN PVOID InputBuffer OPTIONAL
,
416 IN ULONG InputBufferLength
,
417 OUT PVOID OutputBuffer OPTIONAL
,
418 IN ULONG OutputBufferLength
425 DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%x, "
426 "InputBufferLength 0x%x, OutputBuffer 0x%x, OutputBufferLength 0x%x)\n",
427 PowerInformationLevel
,
428 InputBuffer
, InputBufferLength
,
429 OutputBuffer
, OutputBufferLength
);
430 switch (PowerInformationLevel
)
432 case SystemBatteryState
:
434 PSYSTEM_BATTERY_STATE BatteryState
= (PSYSTEM_BATTERY_STATE
)OutputBuffer
;
436 if (InputBuffer
!= NULL
)
437 return STATUS_INVALID_PARAMETER
;
438 if (OutputBufferLength
< sizeof(SYSTEM_BATTERY_STATE
))
439 return STATUS_BUFFER_TOO_SMALL
;
441 /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */
442 RtlZeroMemory(BatteryState
, sizeof(SYSTEM_BATTERY_STATE
));
443 BatteryState
->EstimatedTime
= (ULONG
)-1;
445 Status
= STATUS_SUCCESS
;
450 Status
= STATUS_NOT_IMPLEMENTED
;
451 DPRINT1("PowerInformationLevel 0x%x is UNIMPLEMENTED! Have a nice day.\n",
452 PowerInformationLevel
);
462 PoQueueShutdownWorkItem(
463 IN PWORK_QUEUE_ITEM WorkItem
468 DPRINT1("PoQueueShutdownWorkItem(%p)\n", WorkItem
);
470 return STATUS_NOT_IMPLEMENTED
;
475 NtGetDevicePowerState(IN HANDLE Device
,
476 IN PDEVICE_POWER_STATE PowerState
)
479 return STATUS_NOT_IMPLEMENTED
;
484 NtIsSystemResumeAutomatic(VOID
)
492 NtRequestWakeupLatency(IN LATENCY_TIME Latency
)
495 return STATUS_NOT_IMPLEMENTED
;
500 NtSetThreadExecutionState(IN EXECUTION_STATE esFlags
,
501 OUT EXECUTION_STATE
*PreviousFlags
)
504 return STATUS_NOT_IMPLEMENTED
;