b813944efc10901fcc526509d29d96a8e1af3647
[reactos.git] / reactos / ntoskrnl / po / power.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/po/power.c
6 * PURPOSE: Power Manager
7 *
8 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
9 * Hervé Poussineau (hpoussin@reactos.com)
10 */
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <internal/debug.h>
15
16 typedef struct _REQUEST_POWER_ITEM
17 {
18 PREQUEST_POWER_COMPLETE CompletionRoutine;
19 POWER_STATE PowerState;
20 PVOID Context;
21 } REQUEST_POWER_ITEM, *PREQUEST_POWER_ITEM;
22
23 PDEVICE_NODE PopSystemPowerDeviceNode = NULL;
24 BOOLEAN PopAcpiPresent = FALSE;
25
26 /*
27 * @implemented
28 */
29 NTSTATUS
30 STDCALL
31 PoCallDriver(
32 IN PDEVICE_OBJECT DeviceObject,
33 IN OUT PIRP Irp)
34 {
35 NTSTATUS Status;
36
37 Status = IoCallDriver(DeviceObject, Irp);
38
39 return Status;
40 }
41
42 /*
43 * @unimplemented
44 */
45 PULONG
46 STDCALL
47 PoRegisterDeviceForIdleDetection(
48 IN PDEVICE_OBJECT DeviceObject,
49 IN ULONG ConservationIdleTime,
50 IN ULONG PerformanceIdleTime,
51 IN DEVICE_POWER_STATE State)
52 {
53 return NULL;
54 }
55
56 /*
57 * @unimplemented
58 */
59 PVOID
60 STDCALL
61 PoRegisterSystemState(
62 IN PVOID StateHandle,
63 IN EXECUTION_STATE Flags)
64 {
65 return NULL;
66 }
67
68 static
69 NTSTATUS STDCALL
70 PopRequestPowerIrpCompletion(
71 IN PDEVICE_OBJECT DeviceObject,
72 IN PIRP Irp,
73 IN PVOID Context)
74 {
75 PIO_STACK_LOCATION Stack;
76 PREQUEST_POWER_ITEM RequestPowerItem;
77
78 Stack = IoGetNextIrpStackLocation(Irp);
79 RequestPowerItem = (PREQUEST_POWER_ITEM)Context;
80
81 RequestPowerItem->CompletionRoutine(
82 DeviceObject,
83 Stack->MinorFunction,
84 RequestPowerItem->PowerState,
85 RequestPowerItem->Context,
86 &Irp->IoStatus);
87
88 ExFreePool(&Irp->IoStatus);
89 ExFreePool(Context);
90 return STATUS_SUCCESS;
91 }
92
93 /*
94 * @implemented
95 */
96 NTSTATUS
97 STDCALL
98 PoRequestPowerIrp(
99 IN PDEVICE_OBJECT DeviceObject,
100 IN UCHAR MinorFunction,
101 IN POWER_STATE PowerState,
102 IN PREQUEST_POWER_COMPLETE CompletionFunction,
103 IN PVOID Context,
104 OUT PIRP *pIrp OPTIONAL)
105 {
106 PDEVICE_OBJECT TopDeviceObject;
107 PIO_STACK_LOCATION Stack;
108 PIRP Irp;
109 PIO_STATUS_BLOCK IoStatusBlock;
110 PREQUEST_POWER_ITEM RequestPowerItem;
111 NTSTATUS Status;
112
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;
117
118 RequestPowerItem = ExAllocatePool(NonPagedPool, sizeof(REQUEST_POWER_ITEM));
119 if (!RequestPowerItem)
120 return STATUS_INSUFFICIENT_RESOURCES;
121 IoStatusBlock = ExAllocatePool(NonPagedPool, sizeof(IO_STATUS_BLOCK));
122 if (!IoStatusBlock)
123 {
124 ExFreePool(RequestPowerItem);
125 return STATUS_INSUFFICIENT_RESOURCES;
126 }
127
128 /* Always call the top of the device stack */
129 TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
130
131 Irp = IoBuildSynchronousFsdRequest(
132 IRP_MJ_PNP,
133 TopDeviceObject,
134 NULL,
135 0,
136 NULL,
137 NULL,
138 IoStatusBlock);
139 if (!Irp)
140 {
141 ExFreePool(RequestPowerItem);
142 ExFreePool(IoStatusBlock);
143 return STATUS_INSUFFICIENT_RESOURCES;
144 }
145
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;
150
151 Stack = IoGetNextIrpStackLocation(Irp);
152 Stack->MinorFunction = MinorFunction;
153 if (MinorFunction == IRP_MN_WAIT_WAKE)
154 Stack->Parameters.WaitWake.PowerState = PowerState.SystemState;
155 else
156 Stack->Parameters.WaitWake.PowerState = PowerState.DeviceState;
157
158 RequestPowerItem->CompletionRoutine = CompletionFunction;
159 RequestPowerItem->PowerState = PowerState;
160 RequestPowerItem->Context = Context;
161
162 if (pIrp != NULL)
163 *pIrp = Irp;
164
165 IoSetCompletionRoutine(Irp, PopRequestPowerIrpCompletion, RequestPowerItem, TRUE, TRUE, TRUE);
166 Status = IoCallDriver(TopDeviceObject, Irp);
167
168 /* Always return STATUS_PENDING. The completion routine
169 * will call CompletionFunction and complete the Irp.
170 */
171 return STATUS_PENDING;
172 }
173
174 VOID
175 STDCALL
176 PoSetDeviceBusy(
177 PULONG IdlePointer)
178 {
179 }
180
181 /*
182 * @unimplemented
183 */
184 POWER_STATE
185 STDCALL
186 PoSetPowerState(
187 IN PDEVICE_OBJECT DeviceObject,
188 IN POWER_STATE_TYPE Type,
189 IN POWER_STATE State)
190 {
191 POWER_STATE ps;
192
193 ASSERT_IRQL(DISPATCH_LEVEL);
194
195 ps.SystemState = PowerSystemWorking; // Fully on
196 ps.DeviceState = PowerDeviceD0; // Fully on
197
198 return ps;
199 }
200
201 /*
202 * @unimplemented
203 */
204 VOID
205 STDCALL
206 PoSetSystemState(
207 IN EXECUTION_STATE Flags)
208 {
209 }
210
211 /*
212 * @unimplemented
213 */
214 VOID
215 STDCALL
216 PoStartNextPowerIrp(
217 IN PIRP Irp)
218 {
219 }
220
221 /*
222 * @unimplemented
223 */
224 VOID
225 STDCALL
226 PoUnregisterSystemState(
227 IN PVOID StateHandle)
228 {
229 }
230
231 NTSTATUS
232 PopSetSystemPowerState(
233 SYSTEM_POWER_STATE PowerState)
234 {
235 IO_STATUS_BLOCK IoStatusBlock;
236 PDEVICE_OBJECT DeviceObject;
237 PIO_STACK_LOCATION IrpSp;
238 PDEVICE_OBJECT Fdo;
239 NTSTATUS Status;
240 KEVENT Event;
241 PIRP Irp;
242
243 if (!PopAcpiPresent) return STATUS_NOT_IMPLEMENTED;
244
245 Status = IopGetSystemPowerDeviceObject(&DeviceObject);
246 if (!NT_SUCCESS(Status)) {
247 CPRINT("No system power driver available\n");
248 return STATUS_UNSUCCESSFUL;
249 }
250
251 Fdo = IoGetAttachedDeviceReference(DeviceObject);
252
253 if (Fdo == DeviceObject)
254 {
255 DPRINT("An FDO was not attached\n");
256 return STATUS_UNSUCCESSFUL;
257 }
258
259 KeInitializeEvent(&Event,
260 NotificationEvent,
261 FALSE);
262
263 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_POWER,
264 Fdo,
265 NULL,
266 0,
267 NULL,
268 &Event,
269 &IoStatusBlock);
270
271 IrpSp = IoGetNextIrpStackLocation(Irp);
272 IrpSp->MinorFunction = IRP_MN_SET_POWER;
273 IrpSp->Parameters.Power.Type = SystemPowerState;
274 IrpSp->Parameters.Power.State.SystemState = PowerState;
275
276 Status = PoCallDriver(Fdo, Irp);
277 if (Status == STATUS_PENDING)
278 {
279 KeWaitForSingleObject(&Event,
280 Executive,
281 KernelMode,
282 FALSE,
283 NULL);
284 Status = IoStatusBlock.Status;
285 }
286
287 ObDereferenceObject(Fdo);
288
289 return Status;
290 }
291
292 VOID
293 INIT_FUNCTION
294 PoInit(PLOADER_PARAMETER_BLOCK LoaderBlock,
295 BOOLEAN ForceAcpiDisable)
296 {
297 if (ForceAcpiDisable)
298 {
299 /* Set the ACPI State to False if it's been forced that way */
300 PopAcpiPresent = FALSE;
301 }
302 else
303 {
304 /* Otherwise check the LoaderBlock's Flag */
305 PopAcpiPresent = (LoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
306 }
307 }
308
309 /*
310 * @unimplemented
311 */
312 NTSTATUS
313 STDCALL
314 NtInitiatePowerAction (
315 IN POWER_ACTION SystemAction,
316 IN SYSTEM_POWER_STATE MinSystemState,
317 IN ULONG Flags,
318 IN BOOLEAN Asynchronous)
319 {
320 UNIMPLEMENTED;
321 return STATUS_NOT_IMPLEMENTED;
322 }
323
324 /*
325 * @unimplemented
326 */
327 NTSTATUS
328 STDCALL
329 NtPowerInformation(
330 IN POWER_INFORMATION_LEVEL PowerInformationLevel,
331 IN PVOID InputBuffer OPTIONAL,
332 IN ULONG InputBufferLength,
333 OUT PVOID OutputBuffer OPTIONAL,
334 IN ULONG OutputBufferLength
335 )
336 {
337 NTSTATUS Status;
338
339 PAGED_CODE();
340
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)
347 {
348 case SystemBatteryState:
349 {
350 PSYSTEM_BATTERY_STATE BatteryState = (PSYSTEM_BATTERY_STATE)OutputBuffer;
351
352 if (InputBuffer != NULL)
353 return STATUS_INVALID_PARAMETER;
354 if (OutputBufferLength < sizeof(SYSTEM_BATTERY_STATE))
355 return STATUS_BUFFER_TOO_SMALL;
356
357 /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */
358 RtlZeroMemory(BatteryState, sizeof(SYSTEM_BATTERY_STATE));
359 BatteryState->EstimatedTime = (ULONG)-1;
360
361 Status = STATUS_SUCCESS;
362 break;
363 }
364
365 default:
366 Status = STATUS_NOT_IMPLEMENTED;
367 DPRINT1("PowerInformationLevel 0x%x is UNIMPLEMENTED! Have a nice day.\n",
368 PowerInformationLevel);
369 for (;;);
370 break;
371 }
372
373 return Status;
374 }
375
376
377 NTSTATUS
378 STDCALL
379 PoQueueShutdownWorkItem(
380 IN PWORK_QUEUE_ITEM WorkItem
381 )
382 {
383 PAGED_CODE();
384
385 DPRINT1("PoQueueShutdownWorkItem(%p)\n", WorkItem);
386
387 return STATUS_NOT_IMPLEMENTED;
388 }
389
390
391 /* EOF */