2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/po/power.c
5 * PURPOSE: Power Manager
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Hervé Poussineau (hpoussin@reactos.com)
10 /* INCLUDES ******************************************************************/
16 /* GLOBALS *******************************************************************/
18 extern ULONG ExpInitialiationPhase
;
20 typedef struct _REQUEST_POWER_ITEM
22 PREQUEST_POWER_COMPLETE CompletionRoutine
;
23 POWER_STATE PowerState
;
25 } REQUEST_POWER_ITEM
, *PREQUEST_POWER_ITEM
;
27 PDEVICE_NODE PopSystemPowerDeviceNode
= NULL
;
28 BOOLEAN PopAcpiPresent
= FALSE
;
30 /* PRIVATE FUNCTIONS *********************************************************/
35 PopRequestPowerIrpCompletion(IN PDEVICE_OBJECT DeviceObject
,
39 PIO_STACK_LOCATION Stack
;
40 PREQUEST_POWER_ITEM RequestPowerItem
;
42 Stack
= IoGetNextIrpStackLocation(Irp
);
43 RequestPowerItem
= (PREQUEST_POWER_ITEM
)Context
;
45 RequestPowerItem
->CompletionRoutine(DeviceObject
,
47 RequestPowerItem
->PowerState
,
48 RequestPowerItem
->Context
,
51 ExFreePool(&Irp
->IoStatus
);
54 return STATUS_SUCCESS
;
59 PopCleanupPowerState(IN PPOWER_STATE PowerState
)
66 PopSetSystemPowerState(SYSTEM_POWER_STATE PowerState
)
68 IO_STATUS_BLOCK IoStatusBlock
;
69 PDEVICE_OBJECT DeviceObject
;
70 PIO_STACK_LOCATION IrpSp
;
76 if (!PopAcpiPresent
) return STATUS_NOT_IMPLEMENTED
;
78 Status
= IopGetSystemPowerDeviceObject(&DeviceObject
);
79 if (!NT_SUCCESS(Status
))
81 DPRINT1("No system power driver available\n");
82 return STATUS_UNSUCCESSFUL
;
85 Fdo
= IoGetAttachedDeviceReference(DeviceObject
);
87 if (Fdo
== DeviceObject
)
89 DPRINT("An FDO was not attached\n");
90 return STATUS_UNSUCCESSFUL
;
93 KeInitializeEvent(&Event
,
97 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_POWER
,
105 IrpSp
= IoGetNextIrpStackLocation(Irp
);
106 IrpSp
->MinorFunction
= IRP_MN_SET_POWER
;
107 IrpSp
->Parameters
.Power
.Type
= SystemPowerState
;
108 IrpSp
->Parameters
.Power
.State
.SystemState
= PowerState
;
110 DPRINT("Calling ACPI driver");
111 Status
= PoCallDriver(Fdo
, Irp
);
112 if (Status
== STATUS_PENDING
)
114 KeWaitForSingleObject(&Event
,
119 Status
= IoStatusBlock
.Status
;
122 ObDereferenceObject(Fdo
);
129 PoInitSystem(IN ULONG BootPhase
,
130 IN BOOLEAN HaveAcpiTable
)
132 PVOID NotificationEntry
;
134 BOOLEAN ForceAcpiDisable
= FALSE
;
136 /* Check if this is phase 1 init */
139 /* Registry power button notification */
140 IoRegisterPlugPlayNotification(EventCategoryDeviceInterfaceChange
,
141 0, /* The registry has not been initialized yet */
142 (PVOID
)&GUID_DEVICE_SYS_BUTTON
,
144 PhysicalDeviceObject
->DriverObject
,
145 PopAddRemoveSysCapsCallback
,
151 /* Get the Command Line */
152 CommandLine
= KeLoaderBlock
->LoadOptions
;
155 _strupr(CommandLine
);
157 /* Check for ACPI disable */
158 if (strstr(CommandLine
, "NOACPI")) ForceAcpiDisable
= TRUE
;
160 if (ForceAcpiDisable
)
162 /* Set the ACPI State to False if it's been forced that way */
163 PopAcpiPresent
= FALSE
;
167 /* Otherwise check the LoaderBlock's Flag */
168 PopAcpiPresent
= HaveAcpiTable
;
176 PopPerfIdle(PPROCESSOR_POWER_STATE PowerState
)
178 DPRINT1("PerfIdle function: %p\n", PowerState
);
183 PopPerfIdleDpc(IN PKDPC Dpc
,
184 IN PVOID DeferredContext
,
185 IN PVOID SystemArgument1
,
186 IN PVOID SystemArgument2
)
188 /* Call the Perf Idle function */
189 PopPerfIdle(&((PKPRCB
)DeferredContext
)->PowerState
);
194 PopIdle0(IN PPROCESSOR_POWER_STATE PowerState
)
196 /* FIXME: Extremly naive implementation */
202 PoInitializePrcb(IN PKPRCB Prcb
)
204 /* Initialize the Power State */
205 RtlZeroMemory(&Prcb
->PowerState
, sizeof(Prcb
->PowerState
));
206 Prcb
->PowerState
.Idle0KernelTimeLimit
= 0xFFFFFFFF;
207 Prcb
->PowerState
.CurrentThrottle
= 100;
208 Prcb
->PowerState
.CurrentThrottleIndex
= 0;
209 Prcb
->PowerState
.IdleFunction
= PopIdle0
;
211 /* Initialize the Perf DPC and Timer */
212 KeInitializeDpc(&Prcb
->PowerState
.PerfDpc
, PopPerfIdleDpc
, Prcb
);
213 KeSetTargetProcessorDpc(&Prcb
->PowerState
.PerfDpc
, Prcb
->Number
);
214 KeInitializeTimerEx(&Prcb
->PowerState
.PerfTimer
, SynchronizationTimer
);
217 /* PUBLIC FUNCTIONS **********************************************************/
224 PoCallDriver(IN PDEVICE_OBJECT DeviceObject
,
229 /* Forward to Io -- FIXME! */
230 Status
= IoCallDriver(DeviceObject
, Irp
);
241 PoRegisterDeviceForIdleDetection(IN PDEVICE_OBJECT DeviceObject
,
242 IN ULONG ConservationIdleTime
,
243 IN ULONG PerformanceIdleTime
,
244 IN DEVICE_POWER_STATE State
)
255 PoRegisterSystemState(IN PVOID StateHandle
,
256 IN EXECUTION_STATE Flags
)
267 PoRequestPowerIrp(IN PDEVICE_OBJECT DeviceObject
,
268 IN UCHAR MinorFunction
,
269 IN POWER_STATE PowerState
,
270 IN PREQUEST_POWER_COMPLETE CompletionFunction
,
272 OUT PIRP
*pIrp OPTIONAL
)
274 PDEVICE_OBJECT TopDeviceObject
;
275 PIO_STACK_LOCATION Stack
;
277 PIO_STATUS_BLOCK IoStatusBlock
;
278 PREQUEST_POWER_ITEM RequestPowerItem
;
281 if (MinorFunction
!= IRP_MN_QUERY_POWER
282 && MinorFunction
!= IRP_MN_SET_POWER
283 && MinorFunction
!= IRP_MN_WAIT_WAKE
)
284 return STATUS_INVALID_PARAMETER_2
;
286 RequestPowerItem
= ExAllocatePool(NonPagedPool
, sizeof(REQUEST_POWER_ITEM
));
287 if (!RequestPowerItem
)
288 return STATUS_INSUFFICIENT_RESOURCES
;
289 IoStatusBlock
= ExAllocatePool(NonPagedPool
, sizeof(IO_STATUS_BLOCK
));
292 ExFreePool(RequestPowerItem
);
293 return STATUS_INSUFFICIENT_RESOURCES
;
296 /* Always call the top of the device stack */
297 TopDeviceObject
= IoGetAttachedDeviceReference(DeviceObject
);
299 Irp
= IoBuildSynchronousFsdRequest(IRP_MJ_PNP
,
308 ExFreePool(RequestPowerItem
);
309 ExFreePool(IoStatusBlock
);
310 return STATUS_INSUFFICIENT_RESOURCES
;
313 /* POWER IRPs are always initialized with a status code of
314 STATUS_NOT_IMPLEMENTED */
315 Irp
->IoStatus
.Status
= STATUS_NOT_IMPLEMENTED
;
316 Irp
->IoStatus
.Information
= 0;
318 Stack
= IoGetNextIrpStackLocation(Irp
);
319 Stack
->MinorFunction
= MinorFunction
;
320 if (MinorFunction
== IRP_MN_WAIT_WAKE
)
321 Stack
->Parameters
.WaitWake
.PowerState
= PowerState
.SystemState
;
323 Stack
->Parameters
.WaitWake
.PowerState
= PowerState
.DeviceState
;
325 RequestPowerItem
->CompletionRoutine
= CompletionFunction
;
326 RequestPowerItem
->PowerState
= PowerState
;
327 RequestPowerItem
->Context
= Context
;
332 IoSetCompletionRoutine(Irp
, PopRequestPowerIrpCompletion
, RequestPowerItem
, TRUE
, TRUE
, TRUE
);
333 Status
= IoCallDriver(TopDeviceObject
, Irp
);
335 /* Always return STATUS_PENDING. The completion routine
336 * will call CompletionFunction and complete the Irp.
338 return STATUS_PENDING
;
346 PoSetPowerState(IN PDEVICE_OBJECT DeviceObject
,
347 IN POWER_STATE_TYPE Type
,
348 IN POWER_STATE State
)
352 ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL
);
354 ps
.SystemState
= PowerSystemWorking
; // Fully on
355 ps
.DeviceState
= PowerDeviceD0
; // Fully on
365 PoSetSystemState(IN EXECUTION_STATE Flags
)
375 PoStartNextPowerIrp(IN PIRP Irp
)
385 PoUnregisterSystemState(IN PVOID StateHandle
)
395 PoQueueShutdownWorkItem(IN PWORK_QUEUE_ITEM WorkItem
)
400 return STATUS_NOT_IMPLEMENTED
;
408 NtInitiatePowerAction (IN POWER_ACTION SystemAction
,
409 IN SYSTEM_POWER_STATE MinSystemState
,
411 IN BOOLEAN Asynchronous
)
414 return STATUS_NOT_IMPLEMENTED
;
422 NtPowerInformation(IN POWER_INFORMATION_LEVEL PowerInformationLevel
,
423 IN PVOID InputBuffer OPTIONAL
,
424 IN ULONG InputBufferLength
,
425 OUT PVOID OutputBuffer OPTIONAL
,
426 IN ULONG OutputBufferLength
)
432 DPRINT("NtPowerInformation(PowerInformationLevel 0x%x, InputBuffer 0x%x, "
433 "InputBufferLength 0x%x, OutputBuffer 0x%x, OutputBufferLength 0x%x)\n",
434 PowerInformationLevel
,
435 InputBuffer
, InputBufferLength
,
436 OutputBuffer
, OutputBufferLength
);
438 switch (PowerInformationLevel
)
440 case SystemBatteryState
:
442 PSYSTEM_BATTERY_STATE BatteryState
= (PSYSTEM_BATTERY_STATE
)OutputBuffer
;
444 if (InputBuffer
!= NULL
)
445 return STATUS_INVALID_PARAMETER
;
446 if (OutputBufferLength
< sizeof(SYSTEM_BATTERY_STATE
))
447 return STATUS_BUFFER_TOO_SMALL
;
449 /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */
450 RtlZeroMemory(BatteryState
, sizeof(SYSTEM_BATTERY_STATE
));
451 BatteryState
->EstimatedTime
= (ULONG
)-1;
453 Status
= STATUS_SUCCESS
;
456 case SystemPowerCapabilities
:
458 PSYSTEM_POWER_CAPABILITIES PowerCapabilities
= (PSYSTEM_POWER_CAPABILITIES
)OutputBuffer
;
460 if (InputBuffer
!= NULL
)
461 return STATUS_INVALID_PARAMETER
;
462 if (OutputBufferLength
< sizeof(SYSTEM_POWER_CAPABILITIES
))
463 return STATUS_BUFFER_TOO_SMALL
;
465 /* Just zero the struct (and thus set BatteryState->BatteryPresent = FALSE) */
466 RtlZeroMemory(PowerCapabilities
, sizeof(SYSTEM_POWER_CAPABILITIES
));
467 //PowerCapabilities->SystemBatteriesPresent = 0;
469 Status
= STATUS_SUCCESS
;
474 Status
= STATUS_NOT_IMPLEMENTED
;
475 DPRINT1("PowerInformationLevel 0x%x is UNIMPLEMENTED! Have a nice day.\n",
476 PowerInformationLevel
);
485 NtGetDevicePowerState(IN HANDLE Device
,
486 IN PDEVICE_POWER_STATE PowerState
)
489 return STATUS_NOT_IMPLEMENTED
;
494 NtIsSystemResumeAutomatic(VOID
)
502 NtRequestWakeupLatency(IN LATENCY_TIME Latency
)
505 return STATUS_NOT_IMPLEMENTED
;
510 NtSetThreadExecutionState(IN EXECUTION_STATE esFlags
,
511 OUT EXECUTION_STATE
*PreviousFlags
)
514 return STATUS_NOT_IMPLEMENTED
;