windows-nt/Source/XPSP1/NT/base/busdrv/acpi/smbus/smbali/smbpoll.c
2020-09-26 16:20:57 +08:00

176 lines
4.8 KiB
C

/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
smbpoll.c
Abstract:
Device polling for
SMB Host Controller Driver for ALI chipset
Author:
Michael Hills
Environment:
Notes:
Revision History:
--*/
#include "smbalip.h"
VOID
SmbAliPollDpc (
IN struct _KDPC *Dpc,
IN struct _SMB_CLASS* SmbClass,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
);
VOID
SmbAliPollWorker (
IN PDEVICE_OBJECT DeviceObject,
IN struct _SMB_CLASS* SmbClass
);
//LARGE_INTEGER SmbAlertPollRate = {-1*SECONDS, -1}; // 1 second poll rate
LARGE_INTEGER SmbDevicePollRate = {-5*SECONDS, -1}; // 5 second poll rate
LONG SmbDevicePollPeriod = 5000; // 5000 ms = 5 sec
// address, command, protocol, valid_data, last_data
SMB_ALI_POLL_ENTRY SmbDevicePollList [2] = {
{0x0b, 0x16, SMB_READ_WORD, FALSE, 0}, // battery, BatteryStatus()
{0x09, 0x13, SMB_READ_WORD, FALSE, 0} // charger, ChargerStatus()
};
VOID
SmbAliStartDevicePolling (
IN struct _SMB_CLASS* SmbClass
)
{
PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport);
AliData->PollList = SmbDevicePollList;
AliData->PollListCount = sizeof (SmbDevicePollList)/sizeof(SMB_ALI_POLL_ENTRY);
AliData->PollWorker = IoAllocateWorkItem (SmbClass->DeviceObject);
KeInitializeTimer (&AliData->PollTimer);
KeInitializeDpc (&AliData->PollDpc,
SmbAliPollDpc,
SmbClass);
KeInitializeEvent (&AliData->PollWorkerActive, NotificationEvent, TRUE);
KeSetTimerEx (&AliData->PollTimer,
SmbDevicePollRate,
SmbDevicePollPeriod,
&AliData->PollDpc);
}
VOID
SmbAliStopDevicePolling (
IN struct _SMB_CLASS* SmbClass
)
{
PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport);
KeCancelTimer (&AliData->PollTimer);
if (KeResetEvent(&AliData->PollWorkerActive) == 0) {
KeWaitForSingleObject (&AliData->PollWorkerActive,
Executive, KernelMode, FALSE, NULL);
}
}
VOID
SmbAliPollDpc (
IN struct _KDPC *Dpc,
IN struct _SMB_CLASS* SmbClass,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
)
{
PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport);
if (KeResetEvent(&AliData->PollWorkerActive) != 0) {
IoQueueWorkItem (AliData->PollWorker, SmbAliPollWorker, DelayedWorkQueue, SmbClass);
}
}
VOID
SmbAliPollWorker (
IN PDEVICE_OBJECT DeviceObject,
IN struct _SMB_CLASS* SmbClass
)
{
PSMB_ALI_DATA AliData = (PSMB_ALI_DATA)(SmbClass->Miniport);
PIRP irp;
SMB_REQUEST smbRequest;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
ULONG i;
KeInitializeEvent (&event, SynchronizationEvent, FALSE);
SmbPrint(SMB_TRACE, ("SmbAliPollWorker: Entered\n"));
for (i = 0; i < AliData->PollListCount; i++) {
smbRequest.Protocol = AliData->PollList[i].Protocol;
smbRequest.Address = AliData->PollList[i].Address;
smbRequest.Command = AliData->PollList[i].Command;
irp = IoBuildDeviceIoControlRequest (
SMB_BUS_REQUEST,
SmbClass->DeviceObject,
&smbRequest,
sizeof (smbRequest),
&smbRequest,
sizeof (smbRequest),
TRUE,
&event,
&ioStatus);
if (!irp) {
continue;
}
IoCallDriver (SmbClass->DeviceObject, irp);
KeWaitForSingleObject (&event, Executive, KernelMode, FALSE, NULL);
if (!NT_SUCCESS(ioStatus.Status)) {
continue;
}
if (smbRequest.Status != SMB_STATUS_OK) {
if (AliData->PollList[i].ValidData) {
AliData->PollList[i].ValidData = FALSE;
}
} else {
//BUGBUG: only supports word protocols
if ((!AliData->PollList[i].ValidData) ||
(AliData->PollList[i].LastData != *((PUSHORT)smbRequest.Data))) {
AliData->PollList[i].ValidData = TRUE;
AliData->PollList[i].LastData = *((PUSHORT)smbRequest.Data);
SmbPrint(SMB_TRACE, ("SmbAliPollWorker: Alarm: Address 0x%02x Data 0x%04x\n", AliData->PollList[i].Address, AliData->PollList[i].LastData));
SmbClassLockDevice (SmbClass);
SmbClassAlarm (SmbClass,
AliData->PollList[i].Address,
AliData->PollList[i].LastData);
SmbClassUnlockDevice (SmbClass);
}
SmbPrint(SMB_TRACE, ("SmbAliPollWorker: AlarmData: Address 0x%02x Data 0x%04x\n", AliData->PollList[i].Address, AliData->PollList[i].LastData));
}
}
KeSetEvent (&AliData->PollWorkerActive, 0, FALSE);
}