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/cmb... ============================================================================== --- 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