merge trunk rev : 25663 and 25664 to 0.3.1 branch - update freetype, take care of...
[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 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, PoInit)
18 #endif
19
20 extern ULONG ExpInitialiationPhase;
21
22 typedef struct _REQUEST_POWER_ITEM
23 {
24 PREQUEST_POWER_COMPLETE CompletionRoutine;
25 POWER_STATE PowerState;
26 PVOID Context;
27 } REQUEST_POWER_ITEM, *PREQUEST_POWER_ITEM;
28
29 PDEVICE_NODE PopSystemPowerDeviceNode = NULL;
30 BOOLEAN PopAcpiPresent = FALSE;
31
32 /*
33 * @implemented
34 */
35 NTSTATUS
36 STDCALL
37 PoCallDriver(
38 IN PDEVICE_OBJECT DeviceObject,
39 IN OUT PIRP Irp)
40 {
41 NTSTATUS Status;
42
43 Status = IoCallDriver(DeviceObject, Irp);
44
45 return Status;
46 }
47
48 /*
49 * @unimplemented
50 */
51 PULONG
52 STDCALL
53 PoRegisterDeviceForIdleDetection(
54 IN PDEVICE_OBJECT DeviceObject,
55 IN ULONG ConservationIdleTime,
56 IN ULONG PerformanceIdleTime,
57 IN DEVICE_POWER_STATE State)
58 {
59 return NULL;
60 }
61
62 /*
63 * @unimplemented
64 */
65 PVOID
66 STDCALL
67 PoRegisterSystemState(
68 IN PVOID StateHandle,
69 IN EXECUTION_STATE Flags)
70 {
71 return NULL;
72 }
73
74 static
75 NTSTATUS STDCALL
76 PopRequestPowerIrpCompletion(
77 IN PDEVICE_OBJECT DeviceObject,
78 IN PIRP Irp,
79 IN PVOID Context)
80 {
81 PIO_STACK_LOCATION Stack;
82 PREQUEST_POWER_ITEM RequestPowerItem;
83
84 Stack = IoGetNextIrpStackLocation(Irp);
85 RequestPowerItem = (PREQUEST_POWER_ITEM)Context;
86
87 RequestPowerItem->CompletionRoutine(
88 DeviceObject,
89 Stack->MinorFunction,
90 RequestPowerItem->PowerState,
91 RequestPowerItem->Context,
92 &Irp->IoStatus);
93
94 ExFreePool(&Irp->IoStatus);
95 ExFreePool(Context);
96 return STATUS_SUCCESS;
97 }
98
99 /*
100 * @implemented
101 */
102 NTSTATUS
103 STDCALL
104 PoRequestPowerIrp(
105 IN PDEVICE_OBJECT DeviceObject,
106 IN UCHAR MinorFunction,
107 IN POWER_STATE PowerState,
108 IN PREQUEST_POWER_COMPLETE CompletionFunction,
109 IN PVOID Context,
110 OUT PIRP *pIrp OPTIONAL)
111 {
112 PDEVICE_OBJECT TopDeviceObject;
113 PIO_STACK_LOCATION Stack;
114 PIRP Irp;
115 PIO_STATUS_BLOCK IoStatusBlock;
116 PREQUEST_POWER_ITEM RequestPowerItem;
117 NTSTATUS Status;
118
119 if (MinorFunction != IRP_MN_QUERY_POWER
120 && MinorFunction != IRP_MN_SET_POWER
121 && MinorFunction != IRP_MN_WAIT_WAKE)
122 return STATUS_INVALID_PARAMETER_2;
123
124 RequestPowerItem = ExAllocatePool(NonPagedPool, sizeof(REQUEST_POWER_ITEM));
125 if (!RequestPowerItem)
126 return STATUS_INSUFFICIENT_RESOURCES;
127 IoStatusBlock = ExAllocatePool(NonPagedPool, sizeof(IO_STATUS_BLOCK));
128 if (!IoStatusBlock)
129 {
130 ExFreePool(RequestPowerItem);
131 return STATUS_INSUFFICIENT_RESOURCES;
132 }
133
134 /* Always call the top of the device stack */
135 TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
136
137 Irp = IoBuildSynchronousFsdRequest(
138 IRP_MJ_PNP,
139 TopDeviceObject,
140 NULL,
141 0,
142 NULL,
143 NULL,
144 IoStatusBlock);
145 if (!Irp)
146 {
147 ExFreePool(RequestPowerItem);
148 ExFreePool(IoStatusBlock);
149 return STATUS_INSUFFICIENT_RESOURCES;
150 }
151
152 /* POWER IRPs are always initialized with a status code of
153 STATUS_NOT_IMPLEMENTED */
154 Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
155 Irp->IoStatus.Information = 0;
156
157 Stack = IoGetNextIrpStackLocation(Irp);
158 Stack->MinorFunction = MinorFunction;
159 if (MinorFunction == IRP_MN_WAIT_WAKE)
160 Stack->Parameters.WaitWake.PowerState = PowerState.SystemState;
161 else
162 Stack->Parameters.WaitWake.PowerState = PowerState.DeviceState;
163
164 RequestPowerItem->CompletionRoutine = CompletionFunction;
165 RequestPowerItem->PowerState = PowerState;
166 RequestPowerItem->Context = Context;
167
168 if (pIrp != NULL)
169 *pIrp = Irp;
170
171 IoSetCompletionRoutine(Irp, PopRequestPowerIrpCompletion, RequestPowerItem, TRUE, TRUE, TRUE);
172 Status = IoCallDriver(TopDeviceObject, Irp);
173
174 /* Always return STATUS_PENDING. The completion routine
175 * will call CompletionFunction and complete the Irp.
176 */
177 return STATUS_PENDING;
178 }
179
180 #undef PoSetDeviceBusy
181 VOID
182 NTAPI
183 PoSetDeviceBusy(IN PULONG IdlePointer)
184 {
185 *IdlePointer = 0;
186 }
187
188 VOID
189 NTAPI
190 PopCleanupPowerState(IN PPOWER_STATE PowerState)
191 {
192 /* FIXME */
193 }
194
195 /*
196 * @unimplemented
197 */
198 POWER_STATE
199 STDCALL
200 PoSetPowerState(
201 IN PDEVICE_OBJECT DeviceObject,
202 IN POWER_STATE_TYPE Type,
203 IN POWER_STATE State)
204 {
205 POWER_STATE ps;
206
207 ASSERT_IRQL(DISPATCH_LEVEL);
208
209 ps.SystemState = PowerSystemWorking; // Fully on
210 ps.DeviceState = PowerDeviceD0; // Fully on
211
212 return ps;
213 }
214
215 /*
216 * @unimplemented
217 */
218 VOID
219 STDCALL
220 PoSetSystemState(
221 IN EXECUTION_STATE Flags)
222 {
223 }
224
225 /*
226 * @unimplemented
227 */
228 VOID
229 STDCALL
230 PoStartNextPowerIrp(
231 IN PIRP Irp)
232 {
233 }
234
235 /*
236 * @unimplemented
237 */
238 VOID
239 STDCALL
240 PoUnregisterSystemState(
241 IN PVOID StateHandle)
242 {
243 }
244
245 NTSTATUS
246 NTAPI
247 PopSetSystemPowerState(
248 SYSTEM_POWER_STATE PowerState)
249 {
250 IO_STATUS_BLOCK IoStatusBlock;
251 PDEVICE_OBJECT DeviceObject;
252 PIO_STACK_LOCATION IrpSp;
253 PDEVICE_OBJECT Fdo;
254 NTSTATUS Status;
255 KEVENT Event;
256 PIRP Irp;
257
258 if (!PopAcpiPresent) return STATUS_NOT_IMPLEMENTED;
259
260 Status = IopGetSystemPowerDeviceObject(&DeviceObject);
261 if (!NT_SUCCESS(Status)) {
262 CPRINT("No system power driver available\n");
263 return STATUS_UNSUCCESSFUL;
264 }
265
266 Fdo = IoGetAttachedDeviceReference(DeviceObject);
267
268 if (Fdo == DeviceObject)
269 {
270 DPRINT("An FDO was not attached\n");
271 return STATUS_UNSUCCESSFUL;
272 }
273
274 KeInitializeEvent(&Event,
275 NotificationEvent,
276 FALSE);
277
278 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_POWER,
279 Fdo,
280 NULL,
281 0,
282 NULL,
283 &Event,
284 &IoStatusBlock);
285
286 IrpSp = IoGetNextIrpStackLocation(Irp);
287 IrpSp->MinorFunction = IRP_MN_SET_POWER;
288 IrpSp->Parameters.Power.Type = SystemPowerState;
289 IrpSp->Parameters.Power.State.SystemState = PowerState;
290
291 Status = PoCallDriver(Fdo, Irp);
292 if (Status == STATUS_PENDING)
293 {
294 KeWaitForSingleObject(&Event,
295 Executive,
296 KernelMode,
297 FALSE,
298 NULL);
299 Status = IoStatusBlock.Status;
300 }
301
302 ObDereferenceObject(Fdo);
303
304 return Status;
305 }
306
307 VOID
308 INIT_FUNCTION
309 NTAPI
310 PoInit(IN ULONG BootPhase,
311 IN BOOLEAN HaveAcpiTable)
312 {
313 PVOID NotificationEntry;
314 PCHAR CommandLine;
315 BOOLEAN ForceAcpiDisable = FALSE;
316
317 /* Check if this is phase 1 init */
318 if (BootPhase == 1)
319 {
320 /* Registry power button notification */
321 IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange,
322 0, /* The registry has not been initialized yet */
323 (PVOID)&GUID_DEVICE_SYS_BUTTON,
324 IopRootDeviceNode->
325 PhysicalDeviceObject->DriverObject,
326 PopAddRemoveSysCapsCallback,
327 NULL,
328 &NotificationEntry);
329 return;
330 }
331
332 /* Get the Command Line */
333 CommandLine = KeLoaderBlock->LoadOptions;
334
335 /* Upcase it */
336 _strupr(CommandLine);
337
338 /* Check for ACPI disable */
339 if (strstr(CommandLine, "NOACPI")) ForceAcpiDisable = TRUE;
340
341 if (ForceAcpiDisable)
342 {
343 /* Set the ACPI State to False if it's been forced that way */
344 PopAcpiPresent = FALSE;
345 }
346 else
347 {
348 /* Otherwise check the LoaderBlock's Flag */
349 PopAcpiPresent = HaveAcpiTable;
350 }
351 }
352
353 VOID
354 NTAPI
355 PopPerfIdle(PPROCESSOR_POWER_STATE PowerState)
356 {
357 DPRINT1("PerfIdle function: %p\n", PowerState);
358 }
359
360 VOID
361 NTAPI
362 PopPerfIdleDpc(IN PKDPC Dpc,
363 IN PVOID DeferredContext,
364 IN PVOID SystemArgument1,
365 IN PVOID SystemArgument2)
366 {
367 /* Call the Perf Idle function */
368 PopPerfIdle(&((PKPRCB)DeferredContext)->PowerState);
369 }
370
371 VOID
372 FASTCALL
373 PopIdle0(IN PPROCESSOR_POWER_STATE PowerState)
374 {
375 /* FIXME: Extremly naive implementation */
376 HalProcessorIdle();
377 }
378
379 VOID
380 NTAPI
381 PoInitializePrcb(IN PKPRCB Prcb)
382 {
383 /* Initialize the Power State */
384 RtlZeroMemory(&Prcb->PowerState, sizeof(Prcb->PowerState));
385 Prcb->PowerState.Idle0KernelTimeLimit = 0xFFFFFFFF;
386 Prcb->PowerState.CurrentThrottle = 100;
387 Prcb->PowerState.CurrentThrottleIndex = 0;
388 Prcb->PowerState.IdleFunction = PopIdle0;
389
390 /* Initialize the Perf DPC and Timer */
391 KeInitializeDpc(&Prcb->PowerState.PerfDpc, PopPerfIdleDpc, Prcb);
392 KeSetTargetProcessorDpc(&Prcb->PowerState.PerfDpc, Prcb->Number);
393 KeInitializeTimerEx(&Prcb->PowerState.PerfTimer, SynchronizationTimer);
394 }
395
396 /*
397 * @unimplemented
398 */
399 NTSTATUS
400 STDCALL
401 NtInitiatePowerAction (
402 IN POWER_ACTION SystemAction,
403 IN SYSTEM_POWER_STATE MinSystemState,
404 IN ULONG Flags,
405 IN BOOLEAN Asynchronous)
406 {
407 UNIMPLEMENTED;
408 return STATUS_NOT_IMPLEMENTED;
409 }
410
411 /*
412 * @unimplemented
413 */
414 NTSTATUS
415 STDCALL
416 NtPowerInformation(
417 IN POWER_INFORMATION_LEVEL PowerInformationLevel,
418 IN PVOID InputBuffer OPTIONAL,
419 IN ULONG InputBufferLength,
420 OUT PVOID OutputBuffer OPTIONAL,
421 IN ULONG OutputBufferLength
422 )
423 {
424 NTSTATUS Status;
425
426 PAGED_CODE();
427
428 DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%x, "
429 "InputBufferLength 0x%x, OutputBuffer 0x%x, OutputBufferLength 0x%x)\n",
430 PowerInformationLevel,
431 InputBuffer, InputBufferLength,
432 OutputBuffer, OutputBufferLength);
433 switch (PowerInformationLevel)
434 {
435 case SystemBatteryState:
436 {
437 PSYSTEM_BATTERY_STATE BatteryState = (PSYSTEM_BATTERY_STATE)OutputBuffer;
438
439 if (InputBuffer != NULL)
440 return STATUS_INVALID_PARAMETER;
441 if (OutputBufferLength < sizeof(SYSTEM_BATTERY_STATE))
442 return STATUS_BUFFER_TOO_SMALL;
443
444 /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */
445 RtlZeroMemory(BatteryState, sizeof(SYSTEM_BATTERY_STATE));
446 BatteryState->EstimatedTime = (ULONG)-1;
447
448 Status = STATUS_SUCCESS;
449 break;
450 }
451
452 default:
453 Status = STATUS_NOT_IMPLEMENTED;
454 DPRINT1("PowerInformationLevel 0x%x is UNIMPLEMENTED! Have a nice day.\n",
455 PowerInformationLevel);
456 break;
457 }
458
459 return Status;
460 }
461
462
463 NTSTATUS
464 STDCALL
465 PoQueueShutdownWorkItem(
466 IN PWORK_QUEUE_ITEM WorkItem
467 )
468 {
469 PAGED_CODE();
470
471 DPRINT1("PoQueueShutdownWorkItem(%p)\n", WorkItem);
472
473 return STATUS_NOT_IMPLEMENTED;
474 }
475
476 NTSTATUS
477 NTAPI
478 NtGetDevicePowerState(IN HANDLE Device,
479 IN PDEVICE_POWER_STATE PowerState)
480 {
481 UNIMPLEMENTED;
482 return STATUS_NOT_IMPLEMENTED;
483 }
484
485 BOOLEAN
486 NTAPI
487 NtIsSystemResumeAutomatic(VOID)
488 {
489 UNIMPLEMENTED;
490 return FALSE;
491 }
492
493 NTSTATUS
494 NTAPI
495 NtRequestWakeupLatency(IN LATENCY_TIME Latency)
496 {
497 UNIMPLEMENTED;
498 return STATUS_NOT_IMPLEMENTED;
499 }
500
501 NTSTATUS
502 NTAPI
503 NtSetThreadExecutionState(IN EXECUTION_STATE esFlags,
504 OUT EXECUTION_STATE *PreviousFlags)
505 {
506 UNIMPLEMENTED;
507 return STATUS_NOT_IMPLEMENTED;
508 }
509
510 /* EOF */