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