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 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, PoInit)
21 typedef struct _REQUEST_POWER_ITEM
23 PREQUEST_POWER_COMPLETE CompletionRoutine
;
24 POWER_STATE PowerState
;
26 } REQUEST_POWER_ITEM
, *PREQUEST_POWER_ITEM
;
28 PDEVICE_NODE PopSystemPowerDeviceNode
= NULL
;
29 BOOLEAN PopAcpiPresent
= FALSE
;
37 IN PDEVICE_OBJECT DeviceObject
,
42 Status
= IoCallDriver(DeviceObject
, Irp
);
52 PoRegisterDeviceForIdleDetection(
53 IN PDEVICE_OBJECT DeviceObject
,
54 IN ULONG ConservationIdleTime
,
55 IN ULONG PerformanceIdleTime
,
56 IN DEVICE_POWER_STATE State
)
66 PoRegisterSystemState(
68 IN EXECUTION_STATE Flags
)
75 PopRequestPowerIrpCompletion(
76 IN PDEVICE_OBJECT DeviceObject
,
80 PIO_STACK_LOCATION Stack
;
81 PREQUEST_POWER_ITEM RequestPowerItem
;
83 Stack
= IoGetNextIrpStackLocation(Irp
);
84 RequestPowerItem
= (PREQUEST_POWER_ITEM
)Context
;
86 RequestPowerItem
->CompletionRoutine(
89 RequestPowerItem
->PowerState
,
90 RequestPowerItem
->Context
,
93 ExFreePool(&Irp
->IoStatus
);
95 return STATUS_SUCCESS
;
104 IN PDEVICE_OBJECT DeviceObject
,
105 IN UCHAR MinorFunction
,
106 IN POWER_STATE PowerState
,
107 IN PREQUEST_POWER_COMPLETE CompletionFunction
,
109 OUT PIRP
*pIrp OPTIONAL
)
111 PDEVICE_OBJECT TopDeviceObject
;
112 PIO_STACK_LOCATION Stack
;
114 PIO_STATUS_BLOCK IoStatusBlock
;
115 PREQUEST_POWER_ITEM RequestPowerItem
;
118 if (MinorFunction
!= IRP_MN_QUERY_POWER
119 && MinorFunction
!= IRP_MN_SET_POWER
120 && MinorFunction
!= IRP_MN_WAIT_WAKE
)
121 return STATUS_INVALID_PARAMETER_2
;
123 RequestPowerItem
= ExAllocatePool(NonPagedPool
, sizeof(REQUEST_POWER_ITEM
));
124 if (!RequestPowerItem
)
125 return STATUS_INSUFFICIENT_RESOURCES
;
126 IoStatusBlock
= ExAllocatePool(NonPagedPool
, sizeof(IO_STATUS_BLOCK
));
129 ExFreePool(RequestPowerItem
);
130 return STATUS_INSUFFICIENT_RESOURCES
;
133 /* Always call the top of the device stack */
134 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
136 Irp
= IoBuildSynchronousFsdRequest(
146 ExFreePool(RequestPowerItem
);
147 ExFreePool(IoStatusBlock
);
148 return STATUS_INSUFFICIENT_RESOURCES
;
151 /* POWER IRPs are always initialized with a status code of
152 STATUS_NOT_IMPLEMENTED */
153 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
154 Irp
->IoStatus
.Information
= 0;
156 Stack
= IoGetNextIrpStackLocation(Irp
);
157 Stack
->MinorFunction
= MinorFunction
;
158 if (MinorFunction
== IRP_MN_WAIT_WAKE
)
159 Stack
->Parameters
.WaitWake
.PowerState
= PowerState
.SystemState
;
161 Stack
->Parameters
.WaitWake
.PowerState
= PowerState
.DeviceState
;
163 RequestPowerItem
->CompletionRoutine
= CompletionFunction
;
164 RequestPowerItem
->PowerState
= PowerState
;
165 RequestPowerItem
->Context
= Context
;
170 IoSetCompletionRoutine(Irp
, PopRequestPowerIrpCompletion
, RequestPowerItem
, TRUE
, TRUE
, TRUE
);
171 Status
= IoCallDriver(TopDeviceObject
, Irp
);
173 /* Always return STATUS_PENDING. The completion routine
174 * will call CompletionFunction and complete the Irp.
176 return STATUS_PENDING
;
192 IN PDEVICE_OBJECT DeviceObject
,
193 IN POWER_STATE_TYPE Type
,
194 IN POWER_STATE State
)
198 ASSERT_IRQL(DISPATCH_LEVEL
);
200 ps
.SystemState
= PowerSystemWorking
; // Fully on
201 ps
.DeviceState
= PowerDeviceD0
; // Fully on
212 IN EXECUTION_STATE Flags
)
231 PoUnregisterSystemState(
232 IN PVOID StateHandle
)
238 PopSetSystemPowerState(
239 SYSTEM_POWER_STATE PowerState
)
241 IO_STATUS_BLOCK IoStatusBlock
;
242 PDEVICE_OBJECT DeviceObject
;
243 PIO_STACK_LOCATION IrpSp
;
249 if (!PopAcpiPresent
) return STATUS_NOT_IMPLEMENTED
;
251 Status
= IopGetSystemPowerDeviceObject(&DeviceObject
);
252 if (!NT_SUCCESS(Status
)) {
253 CPRINT("No system power driver available\n");
254 return STATUS_UNSUCCESSFUL
;
257 Fdo
= IoGetAttachedDeviceReference(DeviceObject
);
259 if (Fdo
== DeviceObject
)
261 DPRINT("An FDO was not attached\n");
262 return STATUS_UNSUCCESSFUL
;
265 KeInitializeEvent(&Event
,
269 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_POWER
,
277 IrpSp
= IoGetNextIrpStackLocation(Irp
);
278 IrpSp
->MinorFunction
= IRP_MN_SET_POWER
;
279 IrpSp
->Parameters
.Power
.Type
= SystemPowerState
;
280 IrpSp
->Parameters
.Power
.State
.SystemState
= PowerState
;
282 Status
= PoCallDriver(Fdo
, Irp
);
283 if (Status
== STATUS_PENDING
)
285 KeWaitForSingleObject(&Event
,
290 Status
= IoStatusBlock
.Status
;
293 ObDereferenceObject(Fdo
);
301 PoInit(PLOADER_PARAMETER_BLOCK LoaderBlock
,
302 BOOLEAN ForceAcpiDisable
)
304 if (ForceAcpiDisable
)
306 /* Set the ACPI State to False if it's been forced that way */
307 PopAcpiPresent
= FALSE
;
311 /* Otherwise check the LoaderBlock's Flag */
312 PopAcpiPresent
= (LoaderBlock
->Flags
& MB_FLAGS_ACPI_TABLE
) ? TRUE
: FALSE
;
321 NtInitiatePowerAction (
322 IN POWER_ACTION SystemAction
,
323 IN SYSTEM_POWER_STATE MinSystemState
,
325 IN BOOLEAN Asynchronous
)
328 return STATUS_NOT_IMPLEMENTED
;
337 IN POWER_INFORMATION_LEVEL PowerInformationLevel
,
338 IN PVOID InputBuffer OPTIONAL
,
339 IN ULONG InputBufferLength
,
340 OUT PVOID OutputBuffer OPTIONAL
,
341 IN ULONG OutputBufferLength
348 DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%x, "
349 "InputBufferLength 0x%x, OutputBuffer 0x%x, OutputBufferLength 0x%x)\n",
350 PowerInformationLevel
,
351 InputBuffer
, InputBufferLength
,
352 OutputBuffer
, OutputBufferLength
);
353 switch (PowerInformationLevel
)
355 case SystemBatteryState
:
357 PSYSTEM_BATTERY_STATE BatteryState
= (PSYSTEM_BATTERY_STATE
)OutputBuffer
;
359 if (InputBuffer
!= NULL
)
360 return STATUS_INVALID_PARAMETER
;
361 if (OutputBufferLength
< sizeof(SYSTEM_BATTERY_STATE
))
362 return STATUS_BUFFER_TOO_SMALL
;
364 /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */
365 RtlZeroMemory(BatteryState
, sizeof(SYSTEM_BATTERY_STATE
));
366 BatteryState
->EstimatedTime
= (ULONG
)-1;
368 Status
= STATUS_SUCCESS
;
373 Status
= STATUS_NOT_IMPLEMENTED
;
374 DPRINT1("PowerInformationLevel 0x%x is UNIMPLEMENTED! Have a nice day.\n",
375 PowerInformationLevel
);
386 PoQueueShutdownWorkItem(
387 IN PWORK_QUEUE_ITEM WorkItem
392 DPRINT1("PoQueueShutdownWorkItem(%p)\n", WorkItem
);
394 return STATUS_NOT_IMPLEMENTED
;