Author: sir_richard
Date: Sun Mar 21 22:07:01 2010
New Revision: 46324
URL:
http://svn.reactos.org/svn/reactos?rev=46324&view=rev
Log:
[CMBATT]: Implement CmBattPowerCallback and CmBattWakeDpc to handle S0 entry/exit
transitions which determine if we delay ACPI battery notifications to avoid wake, and the
queuing of a DPC to handle processing the delayed ARs when we return to S0.
Modified:
trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c
Modified: trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/acpi/cmbatt/cm…
==============================================================================
--- trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/acpi/cmbatt/cmbatt.c [iso-8859-1] Sun Mar 21 22:07:01 2010
@@ -19,26 +19,120 @@
KTIMER CmBattWakeDpcTimerObject;
KDPC CmBattWakeDpcObject;
PDEVICE_OBJECT AcAdapterPdo;
+LARGE_INTEGER CmBattWakeDpcDelay;
/* FUNCTIONS ******************************************************************/
VOID
NTAPI
-CmBattPowerCallBack(PCMBATT_DEVICE_EXTENSION DeviceExtension,
- PVOID Argument1,
- PVOID Argument2)
-{
- UNIMPLEMENTED;
+CmBattPowerCallBack(IN PCMBATT_DEVICE_EXTENSION DeviceExtension,
+ IN ULONG Action,
+ IN ULONG Value)
+{
+ BOOLEAN Cancelled;
+ PDEVICE_OBJECT DeviceObject;
+ if (CmBattDebug & 0x10)
+ DbgPrint("CmBattPowerCallBack: action: %d, value: %d \n", Action,
Value);
+
+ /* Check if a transition is going to happen */
+ if (Action == PO_CB_SYSTEM_STATE_LOCK)
+ {
+ /* We have just re-entered S0: call the wake DPC in 10 seconds */
+ if (Value == 0)
+ {
+ if (CmBattDebug & 0x10)
+ DbgPrint("CmBattPowerCallBack: Calling CmBattWakeDpc after 10
seconds.\n");
+ Cancelled = KeSetTimer(&CmBattWakeDpcTimerObject, CmBattWakeDpcDelay,
&CmBattWakeDpcObject);
+ if (CmBattDebug & 0x10)
+ DbgPrint("CmBattPowerCallBack: timerCanceled = %d.\n",
Cancelled);
+ }
+ else if (Value == 0)
+ {
+ /* We are exiting the S0 state: loop all devices to set the delay flag */
+ if (CmBattDebug & 0x10)
+ DbgPrint("CmBattPowerCallBack: Delaying Notifications\n");
+ for (DeviceObject = DeviceExtension->DeviceObject;
+ DeviceObject;
+ DeviceObject = DeviceObject->NextDevice)
+ {
+ /* Set the delay flag */
+ DeviceExtension = DeviceObject->DeviceExtension;
+ DeviceExtension->DelayNotification = TRUE;
+ }
+ }
+ else if (CmBattDebug & 0x10)
+ {
+ /* Unknown value */
+ DbgPrint("CmBattPowerCallBack: unknown argument2 = %08x\n");
+ }
+ }
}
VOID
NTAPI
-CmBattWakeDpc(PKDPC Dpc,
- PCMBATT_DEVICE_EXTENSION FdoExtension,
- PVOID SystemArgument1,
- PVOID SystemArgument2)
-{
-
+CmBattWakeDpc(IN PKDPC Dpc,
+ IN PCMBATT_DEVICE_EXTENSION FdoExtension,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2)
+{
+ PDEVICE_OBJECT CurrentObject;
+ BOOLEAN AcNotify = FALSE;
+ PCMBATT_DEVICE_EXTENSION DeviceExtension;
+ ULONG ArFlag;
+ if (CmBattDebug & 2) DbgPrint("CmBattWakeDpc: Entered.\n");
+
+ /* Loop all device objects */
+ for (CurrentObject = FdoExtension->DeviceObject;
+ CurrentObject;
+ CurrentObject = CurrentObject->NextDevice)
+ {
+ /* Turn delay flag off, we're back in S0 */
+ DeviceExtension = CurrentObject->DeviceExtension;
+ DeviceExtension->DelayNotification = 0;
+
+ /* Check if this is an AC adapter */
+ if (DeviceExtension->FdoType == CmBattAcAdapter)
+ {
+ /* Was there a pending notify? */
+ if (DeviceExtension->ArFlag & CMBATT_AR_NOTIFY)
+ {
+ /* We'll send a notify on the next pass */
+ AcNotify = TRUE;
+ DeviceExtension->ArFlag = 0;
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattWakeDpc: AC adapter notified\n");
+ }
+ }
+ }
+
+ /* Loop the device objects again */
+ for (CurrentObject = FdoExtension->DeviceObject;
+ CurrentObject;
+ CurrentObject = CurrentObject->NextDevice)
+ {
+ /* Check if this is a battery */
+ DeviceExtension = CurrentObject->DeviceExtension;
+ if (DeviceExtension->FdoType == CmBattBattery)
+ {
+ /* Check what ARs are pending */
+ ArFlag = DeviceExtension->ArFlag;
+ if (CmBattDebug & 0x20)
+ DbgPrint("CmBattWakeDpc: Performing delayed ARs: %01x\n",
ArFlag);
+
+ /* Insert notification, clear the lock value */
+ if (ArFlag & CMBATT_AR_INSERT)
InterlockedExchange(&DeviceExtension->ArLockValue, 0);
+
+ /* Removal, clear the battery tag */
+ if (ArFlag & CMBATT_AR_REMOVE) DeviceExtension->Tag = 0;
+
+ /* Notification (or AC/DC adapter change from first pass above) */
+ if ((ArFlag & CMBATT_AR_NOTIFY) || (AcNotify))
+ {
+ /* Notify the class driver */
+ BatteryClassStatusNotify(DeviceExtension->ClassData);
+ }
+ }
+ }
}
VOID