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 typedef struct _REQUEST_POWER_ITEM
18 PREQUEST_POWER_COMPLETE CompletionRoutine
;
19 POWER_STATE PowerState
;
21 } REQUEST_POWER_ITEM
, *PREQUEST_POWER_ITEM
;
23 PDEVICE_NODE PopSystemPowerDeviceNode
= NULL
;
24 BOOLEAN PopAcpiPresent
= FALSE
;
32 IN PDEVICE_OBJECT DeviceObject
,
37 Status
= IoCallDriver(DeviceObject
, Irp
);
47 PoRegisterDeviceForIdleDetection(
48 IN PDEVICE_OBJECT DeviceObject
,
49 IN ULONG ConservationIdleTime
,
50 IN ULONG PerformanceIdleTime
,
51 IN DEVICE_POWER_STATE State
)
61 PoRegisterSystemState(
63 IN EXECUTION_STATE Flags
)
70 PopRequestPowerIrpCompletion(
71 IN PDEVICE_OBJECT DeviceObject
,
75 PIO_STACK_LOCATION Stack
;
76 PREQUEST_POWER_ITEM RequestPowerItem
;
78 Stack
= IoGetNextIrpStackLocation(Irp
);
79 RequestPowerItem
= (PREQUEST_POWER_ITEM
)Context
;
81 RequestPowerItem
->CompletionRoutine(
84 RequestPowerItem
->PowerState
,
85 RequestPowerItem
->Context
,
88 ExFreePool(&Irp
->IoStatus
);
90 return STATUS_SUCCESS
;
99 IN PDEVICE_OBJECT DeviceObject
,
100 IN UCHAR MinorFunction
,
101 IN POWER_STATE PowerState
,
102 IN PREQUEST_POWER_COMPLETE CompletionFunction
,
104 OUT PIRP
*pIrp OPTIONAL
)
106 PDEVICE_OBJECT TopDeviceObject
;
107 PIO_STACK_LOCATION Stack
;
109 PIO_STATUS_BLOCK IoStatusBlock
;
110 PREQUEST_POWER_ITEM RequestPowerItem
;
113 if (MinorFunction
!= IRP_MN_QUERY_POWER
114 && MinorFunction
!= IRP_MN_SET_POWER
115 && MinorFunction
!= IRP_MN_WAIT_WAKE
)
116 return STATUS_INVALID_PARAMETER_2
;
118 RequestPowerItem
= ExAllocatePool(NonPagedPool
, sizeof(REQUEST_POWER_ITEM
));
119 if (!RequestPowerItem
)
120 return STATUS_INSUFFICIENT_RESOURCES
;
121 IoStatusBlock
= ExAllocatePool(NonPagedPool
, sizeof(IO_STATUS_BLOCK
));
124 ExFreePool(RequestPowerItem
);
125 return STATUS_INSUFFICIENT_RESOURCES
;
128 /* Always call the top of the device stack */
129 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
131 Irp
= IoBuildSynchronousFsdRequest(
141 ExFreePool(RequestPowerItem
);
142 ExFreePool(IoStatusBlock
);
143 return STATUS_INSUFFICIENT_RESOURCES
;
146 /* POWER IRPs are always initialized with a status code of
147 STATUS_NOT_IMPLEMENTED */
148 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
149 Irp
->IoStatus
.Information
= 0;
151 Stack
= IoGetNextIrpStackLocation(Irp
);
152 Stack
->MinorFunction
= MinorFunction
;
153 if (MinorFunction
== IRP_MN_WAIT_WAKE
)
154 Stack
->Parameters
.WaitWake
.PowerState
= PowerState
.SystemState
;
156 Stack
->Parameters
.WaitWake
.PowerState
= PowerState
.DeviceState
;
158 RequestPowerItem
->CompletionRoutine
= CompletionFunction
;
159 RequestPowerItem
->PowerState
= PowerState
;
160 RequestPowerItem
->Context
= Context
;
165 IoSetCompletionRoutine(Irp
, PopRequestPowerIrpCompletion
, RequestPowerItem
, TRUE
, TRUE
, TRUE
);
166 Status
= IoCallDriver(TopDeviceObject
, Irp
);
168 /* Always return STATUS_PENDING. The completion routine
169 * will call CompletionFunction and complete the Irp.
171 return STATUS_PENDING
;
187 IN PDEVICE_OBJECT DeviceObject
,
188 IN POWER_STATE_TYPE Type
,
189 IN POWER_STATE State
)
193 ASSERT_IRQL(DISPATCH_LEVEL
);
195 ps
.SystemState
= PowerSystemWorking
; // Fully on
196 ps
.DeviceState
= PowerDeviceD0
; // Fully on
207 IN EXECUTION_STATE Flags
)
226 PoUnregisterSystemState(
227 IN PVOID StateHandle
)
232 PopSetSystemPowerState(
233 SYSTEM_POWER_STATE PowerState
)
235 IO_STATUS_BLOCK IoStatusBlock
;
236 PDEVICE_OBJECT DeviceObject
;
237 PIO_STACK_LOCATION IrpSp
;
243 if (!PopAcpiPresent
) return STATUS_NOT_IMPLEMENTED
;
245 Status
= IopGetSystemPowerDeviceObject(&DeviceObject
);
246 if (!NT_SUCCESS(Status
)) {
247 CPRINT("No system power driver available\n");
248 return STATUS_UNSUCCESSFUL
;
251 Fdo
= IoGetAttachedDeviceReference(DeviceObject
);
253 if (Fdo
== DeviceObject
)
255 DPRINT("An FDO was not attached\n");
256 return STATUS_UNSUCCESSFUL
;
259 KeInitializeEvent(&Event
,
263 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_POWER
,
271 IrpSp
= IoGetNextIrpStackLocation(Irp
);
272 IrpSp
->MinorFunction
= IRP_MN_SET_POWER
;
273 IrpSp
->Parameters
.Power
.Type
= SystemPowerState
;
274 IrpSp
->Parameters
.Power
.State
.SystemState
= PowerState
;
276 Status
= PoCallDriver(Fdo
, Irp
);
277 if (Status
== STATUS_PENDING
)
279 KeWaitForSingleObject(&Event
,
284 Status
= IoStatusBlock
.Status
;
287 ObDereferenceObject(Fdo
);
294 PoInit(PLOADER_PARAMETER_BLOCK LoaderBlock
,
295 BOOLEAN ForceAcpiDisable
)
297 if (ForceAcpiDisable
)
299 /* Set the ACPI State to False if it's been forced that way */
300 PopAcpiPresent
= FALSE
;
304 /* Otherwise check the LoaderBlock's Flag */
305 PopAcpiPresent
= (LoaderBlock
->Flags
& MB_FLAGS_ACPI_TABLE
) ? TRUE
: FALSE
;
314 NtInitiatePowerAction (
315 IN POWER_ACTION SystemAction
,
316 IN SYSTEM_POWER_STATE MinSystemState
,
318 IN BOOLEAN Asynchronous
)
321 return STATUS_NOT_IMPLEMENTED
;
330 IN POWER_INFORMATION_LEVEL PowerInformationLevel
,
331 IN PVOID InputBuffer OPTIONAL
,
332 IN ULONG InputBufferLength
,
333 OUT PVOID OutputBuffer OPTIONAL
,
334 IN ULONG OutputBufferLength
341 DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%x, "
342 "InputBufferLength 0x%x, OutputBuffer 0x%x, OutputBufferLength 0x%x)\n",
343 PowerInformationLevel
,
344 InputBuffer
, InputBufferLength
,
345 OutputBuffer
, OutputBufferLength
);
346 switch (PowerInformationLevel
)
348 case SystemBatteryState
:
350 PSYSTEM_BATTERY_STATE BatteryState
= (PSYSTEM_BATTERY_STATE
)OutputBuffer
;
352 if (InputBuffer
!= NULL
)
353 return STATUS_INVALID_PARAMETER
;
354 if (OutputBufferLength
< sizeof(SYSTEM_BATTERY_STATE
))
355 return STATUS_BUFFER_TOO_SMALL
;
357 /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */
358 RtlZeroMemory(BatteryState
, sizeof(SYSTEM_BATTERY_STATE
));
359 BatteryState
->EstimatedTime
= (ULONG
)-1;
361 Status
= STATUS_SUCCESS
;
366 Status
= STATUS_NOT_IMPLEMENTED
;
367 DPRINT1("PowerInformationLevel 0x%x is UNIMPLEMENTED! Have a nice day.\n",
368 PowerInformationLevel
);
379 PoQueueShutdownWorkItem(
380 IN PWORK_QUEUE_ITEM WorkItem
385 DPRINT1("PoQueueShutdownWorkItem(%p)\n", WorkItem
);
387 return STATUS_NOT_IMPLEMENTED
;