Fix splitting of cells (noticed by Hartmut).
[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 NTAPI
233 PopSetSystemPowerState(
234 SYSTEM_POWER_STATE PowerState)
235 {
236 IO_STATUS_BLOCK IoStatusBlock;
237 PDEVICE_OBJECT DeviceObject;
238 PIO_STACK_LOCATION IrpSp;
239 PDEVICE_OBJECT Fdo;
240 NTSTATUS Status;
241 KEVENT Event;
242 PIRP Irp;
243
244 if (!PopAcpiPresent) return STATUS_NOT_IMPLEMENTED;
245
246 Status = IopGetSystemPowerDeviceObject(&DeviceObject);
247 if (!NT_SUCCESS(Status)) {
248 CPRINT("No system power driver available\n");
249 return STATUS_UNSUCCESSFUL;
250 }
251
252 Fdo = IoGetAttachedDeviceReference(DeviceObject);
253
254 if (Fdo == DeviceObject)
255 {
256 DPRINT("An FDO was not attached\n");
257 return STATUS_UNSUCCESSFUL;
258 }
259
260 KeInitializeEvent(&Event,
261 NotificationEvent,
262 FALSE);
263
264 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_POWER,
265 Fdo,
266 NULL,
267 0,
268 NULL,
269 &Event,
270 &IoStatusBlock);
271
272 IrpSp = IoGetNextIrpStackLocation(Irp);
273 IrpSp->MinorFunction = IRP_MN_SET_POWER;
274 IrpSp->Parameters.Power.Type = SystemPowerState;
275 IrpSp->Parameters.Power.State.SystemState = PowerState;
276
277 Status = PoCallDriver(Fdo, Irp);
278 if (Status == STATUS_PENDING)
279 {
280 KeWaitForSingleObject(&Event,
281 Executive,
282 KernelMode,
283 FALSE,
284 NULL);
285 Status = IoStatusBlock.Status;
286 }
287
288 ObDereferenceObject(Fdo);
289
290 return Status;
291 }
292
293 VOID
294 INIT_FUNCTION
295 NTAPI
296 PoInit(PLOADER_PARAMETER_BLOCK LoaderBlock,
297 BOOLEAN ForceAcpiDisable)
298 {
299 if (ForceAcpiDisable)
300 {
301 /* Set the ACPI State to False if it's been forced that way */
302 PopAcpiPresent = FALSE;
303 }
304 else
305 {
306 /* Otherwise check the LoaderBlock's Flag */
307 PopAcpiPresent = (LoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
308 }
309 }
310
311 /*
312 * @unimplemented
313 */
314 NTSTATUS
315 STDCALL
316 NtInitiatePowerAction (
317 IN POWER_ACTION SystemAction,
318 IN SYSTEM_POWER_STATE MinSystemState,
319 IN ULONG Flags,
320 IN BOOLEAN Asynchronous)
321 {
322 UNIMPLEMENTED;
323 return STATUS_NOT_IMPLEMENTED;
324 }
325
326 /*
327 * @unimplemented
328 */
329 NTSTATUS
330 STDCALL
331 NtPowerInformation(
332 IN POWER_INFORMATION_LEVEL PowerInformationLevel,
333 IN PVOID InputBuffer OPTIONAL,
334 IN ULONG InputBufferLength,
335 OUT PVOID OutputBuffer OPTIONAL,
336 IN ULONG OutputBufferLength
337 )
338 {
339 NTSTATUS Status;
340
341 PAGED_CODE();
342
343 DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%x, "
344 "InputBufferLength 0x%x, OutputBuffer 0x%x, OutputBufferLength 0x%x)\n",
345 PowerInformationLevel,
346 InputBuffer, InputBufferLength,
347 OutputBuffer, OutputBufferLength);
348 switch (PowerInformationLevel)
349 {
350 case SystemBatteryState:
351 {
352 PSYSTEM_BATTERY_STATE BatteryState = (PSYSTEM_BATTERY_STATE)OutputBuffer;
353
354 if (InputBuffer != NULL)
355 return STATUS_INVALID_PARAMETER;
356 if (OutputBufferLength < sizeof(SYSTEM_BATTERY_STATE))
357 return STATUS_BUFFER_TOO_SMALL;
358
359 /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */
360 RtlZeroMemory(BatteryState, sizeof(SYSTEM_BATTERY_STATE));
361 BatteryState->EstimatedTime = (ULONG)-1;
362
363 Status = STATUS_SUCCESS;
364 break;
365 }
366
367 default:
368 Status = STATUS_NOT_IMPLEMENTED;
369 DPRINT1("PowerInformationLevel 0x%x is UNIMPLEMENTED! Have a nice day.\n",
370 PowerInformationLevel);
371 for (;;);
372 break;
373 }
374
375 return Status;
376 }
377
378
379 NTSTATUS
380 STDCALL
381 PoQueueShutdownWorkItem(
382 IN PWORK_QUEUE_ITEM WorkItem
383 )
384 {
385 PAGED_CODE();
386
387 DPRINT1("PoQueueShutdownWorkItem(%p)\n", WorkItem);
388
389 return STATUS_NOT_IMPLEMENTED;
390 }
391
392
393 /* EOF */