|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
cmhndlr.c
Abstract:
Control Method Battery handlers
Author:
Bob Moore
Environment:
Kernel mode
Revision History:
--*/
#include "CmBattp.h"
VOID CmBattPowerCallBack( IN PVOID CallBackContext, IN PVOID Argument1, IN PVOID Argument2 ) /*++
Routine Description:
This routine is called when the system changes power states
Arguments:
CallBackContext - The device extension for the root device Argument1
--*/ {
PDRIVER_OBJECT CmBattDriver = (PDRIVER_OBJECT) CallBackContext; ULONG action = PtrToUlong( Argument1 ); ULONG value = PtrToUlong( Argument2 ); BOOLEAN timerCanceled; PDEVICE_OBJECT CmBattDevice; PCM_BATT CmBatt;
CmBattPrint (CMBATT_POWER, ("CmBattPowerCallBack: action: %d, value: %d \n", action, value));
//
// We are looking for a PO_CB_SYSTEM_STATE_LOCK
//
if (action != PO_CB_SYSTEM_STATE_LOCK) { return; }
switch (value) { case 0: CmBattPrint (CMBATT_POWER, ("CmBattPowerCallBack: Delaying Notifications\n")); //
// Get the head of the DeviceObject list
//
CmBattDevice = CmBattDriver->DeviceObject;
while (CmBattDevice) { CmBatt = CmBattDevice->DeviceExtension;
//
// Cause all notifications to be delayed.
//
CmBatt->Sleeping = TRUE;
CmBattDevice = CmBattDevice->NextDevice;
} break;
case 1: CmBattPrint (CMBATT_POWER, ("CmBattPowerCallBack: Calling CmBattWakeDpc after 10 seconds.\n")); timerCanceled = KeSetTimer (&CmBattWakeDpcTimerObject, CmBattWakeDpcDelay, &CmBattWakeDpcObject); CmBattPrint (CMBATT_POWER, ("CmBattPowerCallBack: timerCanceled = %d.\n", timerCanceled)); break;
default: CmBattPrint (CMBATT_POWER, ("CmBattPowerCallBack: unknown argument2 = %08x\n", value));
}
}
VOID CmBattWakeDpc ( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ) /*++
Routine Description:
This routine is called X seconds after the system wakes to proces all delayed battery notifications.
Arguments:
CmBattDriver - Driver object
Return Value:
None
--*/
{ PDRIVER_OBJECT CmBattDriver = (PDRIVER_OBJECT) DeferredContext; BOOLEAN notifyAll = FALSE; PDEVICE_OBJECT CmBattDevice; PCM_BATT CmBatt;
CmBattPrint (CMBATT_TRACE, ("CmBattWakeDpc: Entered.\n")); //
// Get the head of the DeviceObject list
//
CmBattDevice = CmBattDriver->DeviceObject;
while (CmBattDevice) { CmBatt = CmBattDevice->DeviceExtension;
//
// We will now process all delayed notifications.
// For effeiciency, we must go through the devices twice:
// first to see if any AC devices have been notified, and
// then to send notifications to all battery devices if necessary.
//
CmBatt->Sleeping = FALSE;
if ((CmBatt->Type == AC_ADAPTER_TYPE) && (CmBatt->ActionRequired & CMBATT_AR_NOTIFY)) {
//
// If any AC adapter devices have notified,
// then we need to notify all battery devices
//
CmBattPrint (CMBATT_PNP, ("CmBattWakeDpc: AC adapter notified\n")); notifyAll = TRUE; CmBatt->ActionRequired = CMBATT_AR_NO_ACTION; }
CmBattDevice = CmBattDevice->NextDevice;
}
//
// Get the head of the DeviceObject list
//
CmBattDevice = CmBattDriver->DeviceObject;
// Walk the list
while (CmBattDevice) { CmBatt = CmBattDevice->DeviceExtension;
if (CmBatt->Type == CM_BATTERY_TYPE) { CmBattPrint (CMBATT_PNP, ("CmBattWakeDpc: Performing delayed ARs: %01x\n", CmBatt->ActionRequired));
if (CmBatt->ActionRequired & CMBATT_AR_INVALIDATE_CACHE) { InterlockedExchange (&CmBatt->CacheState, 0); } if (CmBatt->ActionRequired & CMBATT_AR_INVALIDATE_TAG) { CmBatt->Info.Tag = BATTERY_TAG_INVALID; } if ((CmBatt->ActionRequired & CMBATT_AR_NOTIFY) || notifyAll) { BatteryClassStatusNotify (CmBatt->Class); } }
CmBattDevice = CmBattDevice->NextDevice;
}
}
VOID CmBattNotifyHandler ( IN PVOID Context, IN ULONG NotifyValue ) /*++
Routine Description:
This routine fields battery device notifications from the ACPI driver.
Arguments:
Return Value:
None
--*/ { PCM_BATT CmBatt = Context; PDRIVER_OBJECT CmBatteryDriver; PDEVICE_OBJECT CmBatteryDevice; PCM_BATT CmBatteryExtension;
CmBattPrint ((CMBATT_PNP | CMBATT_BIOS), ("CmBattNotifyHandler: CmBatt 0x%08x Type %d Number %d Notify Value: %x\n", CmBatt, CmBatt->Type, CmBatt->DeviceNumber, NotifyValue));
switch (NotifyValue) {
case BATTERY_DEVICE_CHECK: //
// A new battery was inserted in the system.
//
CmBatt->ActionRequired |= CMBATT_AR_NOTIFY; CmBatt->ActionRequired |= CMBATT_AR_INVALIDATE_CACHE;
//
// This notification is only received when a battery is inserted.
// It also occurs after restart from hibernation on some machines.
// Invalidate battery tag.
//
if (CmBatt->Info.Tag != BATTERY_TAG_INVALID) { CmBattPrint ((CMBATT_ERROR), ("CmBattNotifyHandler: Received battery #%x insertion, but tag was not invalid.\n", CmBatt->DeviceNumber)); }
break;
case BATTERY_EJECT: //
// A battery was removed from the system
//
CmBatt->ActionRequired |= CMBATT_AR_NOTIFY;
//
// Invalidate the battery tag and all cached informaion
// whenever this message is received.
//
CmBatt->ActionRequired |= CMBATT_AR_INVALIDATE_CACHE; CmBatt->ActionRequired |= CMBATT_AR_INVALIDATE_TAG;
break;
case BATTERY_STATUS_CHANGE: // Status change only
CmBatt->ActionRequired |= CMBATT_AR_NOTIFY;
break;
case BATTERY_INFO_CHANGE: // Info & status change
CmBatt->ActionRequired |= CMBATT_AR_NOTIFY; CmBatt->ActionRequired |= CMBATT_AR_INVALIDATE_CACHE; CmBatt->ActionRequired |= CMBATT_AR_INVALIDATE_TAG; break;
default:
CmBattPrint (CMBATT_PNP, ("CmBattNotifyHandler: Unknown Notify Value: %x\n", NotifyValue)); break;
}
if (CmBatt->Sleeping) { CmBattPrint (CMBATT_PNP, ("CmBattNotifyHandler: Notification delayed: ARs = %01x\n", CmBatt->ActionRequired)); } else { CmBattPrint (CMBATT_PNP, ("CmBattNotifyHandler: Performing ARs: %01x\n", CmBatt->ActionRequired)); if (CmBatt->Type == CM_BATTERY_TYPE) { //
// Invalidate last trip point set on battery.
//
CmBatt->Alarm.Setting = CM_ALARM_INVALID; if (CmBatt->ActionRequired & CMBATT_AR_INVALIDATE_CACHE) { InterlockedExchange (&CmBatt->CacheState, 0); } if (CmBatt->ActionRequired & CMBATT_AR_INVALIDATE_TAG) { CmBatt->Info.Tag = BATTERY_TAG_INVALID; } if (CmBatt->ActionRequired & CMBATT_AR_NOTIFY) { CmBatt->ReCheckSta = TRUE; BatteryClassStatusNotify (CmBatt->Class); }
} else if ((CmBatt->Type == AC_ADAPTER_TYPE) && (CmBatt->ActionRequired & CMBATT_AR_NOTIFY)) {
//
// Get the Driver Object
//
CmBatteryDriver = CmBatt->Fdo->DriverObject;
//
// Get the head of the DeviceObject list
//
CmBatteryDevice = CmBatteryDriver->DeviceObject;
//
// Walk the DeviceObject list to notify the class driver on all batteries
//
while (CmBatteryDevice) {
CmBatteryExtension = CmBatteryDevice->DeviceExtension;
if (CmBatteryExtension->Type == CM_BATTERY_TYPE) { CmBatteryExtension->ReCheckSta = TRUE; BatteryClassStatusNotify (CmBatteryExtension->Class); }
CmBatteryDevice = CmBatteryDevice->NextDevice; } }
CmBatt->ActionRequired = CMBATT_AR_NO_ACTION; } }
|