|
|
/*++
Copyright (c) 1991 - 2002 Microsoft Corporation
Module Name:
## ## ### ## # ##### ## ##### ##### #### ##### #####
## ## ### ### # ## ## ## ## ## ## ## # ## ## ## ##
## ## ## ## #### # ## ## ## ## ## ## ## ## ## ## ##
####### ## ## # #### ## ## ## ##### ##### ## ## ## ## ##
## ## ####### # ### ## ## ## ## #### ## ##### #####
## ## ## ## # ## ## ## ## ## ## ## ## ## # ## ##
## ## ## ## # # ##### ##### ##### ## ## ## #### ## ##
Abstract:
This module process the callback from the OS executive.
Author:
Wesley Witt (wesw) 1-Mar-2002
Environment:
Kernel mode only.
Notes:
--*/
#include "internal.h"
void WdHandlerSetTimeoutValue( IN PDEVICE_EXTENSION DeviceExtension, IN ULONG Timeout, IN BOOLEAN PingTimer )
/*++
Routine Description:
This function sets the timeout value for the hardware timer and the software timer. The software timer runs as a frequency that is 25% of the hardware timer. The hardware timer's frequency is set at StartDevice time to the device's reported maximum value, but it can be changed through the NtSetSystemInformation inmterface.
Arguments:
DeviceExtension - Pointer to the watchdog device extension
Timeout - The requested timeout value expressed in the device units.
PingTimer - Specifies if the timer should be pinged after changing the timeout value.
Return Value:
None.
Notes:
--*/
{ DeviceExtension->HardwareTimeout = Timeout; DeviceExtension->DpcTimeout = ConvertTimeoutToMilliseconds( WdTable->Units, DeviceExtension->HardwareTimeout >> 2 ) * 10000; ULONG Control = READ_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress ); SETBITS( Control, WATCHDOG_CONTROL_TRIGGER ); WRITE_REGISTER_ULONG( DeviceExtension->CountRegisterAddress, DeviceExtension->HardwareTimeout ); WRITE_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress, Control ); if (PingTimer) { PingWatchdogTimer( DeviceExtension, FALSE ); } }
ULONG WdHandlerQueryTimeoutValue( IN PDEVICE_EXTENSION DeviceExtension )
/*++
Routine Description:
This function queries the hardware for the current value of the hardware timer. This timer is counting down to zero and this query returns the real-time value of the timer.
Arguments:
DeviceExtension - Pointer to the watchdog device extension
Return Value:
The current timeout value.
Notes:
--*/
{ return READ_REGISTER_ULONG( DeviceExtension->CountRegisterAddress ); }
void WdHandlerResetTimer( IN PDEVICE_EXTENSION DeviceExtension )
/*++
Routine Description:
This function resets the timer to it's previously set maximum value.
Arguments:
DeviceExtension - Pointer to the watchdog device extension
Return Value:
None.
Notes:
--*/
{ ULONG Control = READ_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress ); SETBITS( Control, WATCHDOG_CONTROL_TRIGGER ); WRITE_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress, Control ); PingWatchdogTimer( DeviceExtension, FALSE ); }
void WdHandlerStopTimer( IN PDEVICE_EXTENSION DeviceExtension )
/*++
Routine Description:
This function stops the hardware and software timer.
Arguments:
DeviceExtension - Pointer to the watchdog device extension
Return Value:
None.
Notes:
--*/
{ ULONG Control = READ_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress ); CLEARBITS( Control, WATCHDOG_CONTROL_ENABLE ); WRITE_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress, Control ); KeCancelTimer( &DeviceExtension->Timer ); }
void WdHandlerStartTimer( IN PDEVICE_EXTENSION DeviceExtension )
/*++
Routine Description:
This function starts the hardware and software timer.
Arguments:
DeviceExtension - Pointer to the watchdog device extension
Return Value:
None.
Notes:
--*/
{ ULONG Control = READ_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress ); SETBITS( Control, WATCHDOG_CONTROL_ENABLE ); WRITE_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress, Control ); SETBITS( Control, WATCHDOG_CONTROL_TRIGGER ); WRITE_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress, Control ); PingWatchdogTimer( DeviceExtension, FALSE ); }
void WdHandlerSetTriggerAction( IN PDEVICE_EXTENSION DeviceExtension, IN ULONG TriggerAction )
/*++
Routine Description:
This function sets the trigger action. The trigger action specifies what action takes place when the hardware timer expires. There are 2 possible actions, restart and reboot.
Arguments:
DeviceExtension - Pointer to the watchdog device extension
TriggerAction - Sets the trigger action 0 = Restart system 1 = Reboot system
Return Value:
None.
Notes:
--*/
{ ULONG Control = READ_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress ); if (TriggerAction == 1) { SETBITS( Control, WATCHDOG_CONTROL_TIMER_MODE ); } else { CLEARBITS( Control, WATCHDOG_CONTROL_TIMER_MODE ); } WRITE_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress, Control ); }
ULONG WdHandlerQueryTriggerAction( IN PDEVICE_EXTENSION DeviceExtension )
/*++
Routine Description:
This function queries the current trigger action.
Arguments:
DeviceExtension - Pointer to the watchdog device extension
Return Value:
TriggerAction: 0 = Restart system 1 = Reboot system
Notes:
--*/
{ ULONG Control = READ_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress ); if (Control & WATCHDOG_CONTROL_TIMER_MODE) { return 1; } return 0; }
ULONG WdHandlerQueryState( IN PDEVICE_EXTENSION DeviceExtension, IN BOOLEAN QueryFiredFromDevice )
/*++
Routine Description:
This function queries the device state from the hardware timer.
Arguments:
DeviceExtension - Pointer to the watchdog device extension
QueryFiredFromDevice - Specifies whether the fired state bit should come from the device or from the driver cache.
Return Value:
Device state.
Notes:
--*/
{ ULONG Control = READ_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress ); ULONG StateValue = 0; if (QueryFiredFromDevice) { if (Control & WATCHDOG_CONTROL_FIRED) { SETBITS( StateValue, WDSTATE_FIRED ); } } else { if (DeviceExtension->WdState & WDSTATE_FIRED) { SETBITS( StateValue, WDSTATE_FIRED ); } } if ((Control & WATCHDOG_CONTROL_BIOS_JUMPER) == 0) { SETBITS( StateValue, WDSTATE_HARDWARE_ENABLED ); } if (Control & WATCHDOG_CONTROL_ENABLE) { SETBITS( StateValue, WDSTATE_STARTED ); } SETBITS( StateValue, WDSTATE_HARDWARE_PRESENT ); return StateValue; }
void WdHandlerResetFired( IN PDEVICE_EXTENSION DeviceExtension )
/*++
Routine Description:
This function resets the hardware fired state bit.
Arguments:
DeviceExtension - Pointer to the watchdog device extension
Return Value:
None.
Notes:
--*/
{ ULONG Control = READ_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress ); SETBITS( Control, WATCHDOG_CONTROL_FIRED ); WRITE_REGISTER_ULONG( DeviceExtension->ControlRegisterAddress, Control ); }
NTSTATUS WdHandlerFunction( IN WATCHDOG_HANDLER_ACTION HandlerAction, IN PVOID Context, IN OUT PULONG DataValue, IN BOOLEAN NoLocks )
/*++
Routine Description:
This routine is the hardware specific interface to the watchdog device. All hardware interfaces are here are exposed thru the handler function for use by NtSet/QuerySystemInformation and the other part of the watchdog driver.
Arguments:
HandlerAction - Enumeration specifying the requested action
Context - Always a device extension pointer
DataValue - Action specific data value
NoLocks - Specifies that no lock are to be held during the handler function
Return Value:
If we successfully create a device object, STATUS_SUCCESS is returned. Otherwise, return the appropriate error code.
Notes:
--*/
{ PDEVICE_EXTENSION DeviceExtension = (PDEVICE_EXTENSION) Context; NTSTATUS Status = STATUS_SUCCESS; KLOCK_QUEUE_HANDLE LockHandle; ULONG Timeout;
if (!NoLocks) { KeAcquireInStackQueuedSpinLock( &DeviceExtension->DeviceLock, &LockHandle ); }
switch (HandlerAction) { case WdActionSetTimeoutValue: Timeout = ConvertTimeoutFromMilliseconds( WdTable->Units, *DataValue ); if (Timeout > DeviceExtension->MaxCount || Timeout == 0) { Status = STATUS_INVALID_PARAMETER_1; } else { WdHandlerSetTimeoutValue( DeviceExtension, Timeout, TRUE ); } break;
case WdActionQueryTimeoutValue: *DataValue = WdHandlerQueryTimeoutValue( DeviceExtension ); break;
case WdActionResetTimer: WdHandlerResetTimer( DeviceExtension ); break;
case WdActionStopTimer: WdHandlerStopTimer( DeviceExtension ); break;
case WdActionStartTimer: WdHandlerStartTimer( DeviceExtension ); break;
case WdActionSetTriggerAction: if (*DataValue == 0xbadbadff) { KeCancelTimer( &DeviceExtension->Timer ); } else { if (*DataValue > 1) { Status = STATUS_INVALID_PARAMETER_2; } else { WdHandlerSetTriggerAction( DeviceExtension, *DataValue ); } } break;
case WdActionQueryTriggerAction: *DataValue = WdHandlerQueryTriggerAction( DeviceExtension ); break;
case WdActionQueryState: *DataValue = WdHandlerQueryState( DeviceExtension, FALSE ); break;
default: Status = STATUS_INVALID_PARAMETER_3; }
if (!NoLocks) { KeReleaseInStackQueuedSpinLock( &LockHandle ); }
return Status; }
|