Commit 0950e9cb authored by Wim Van Sebroeck's avatar Wim Van Sebroeck

[WATCHDOG] v2.6.5-rc2 pcwd.c-patch2

* Extracted the get_status code to a seperate function (pcwd_get_status)
* Re-used the pcwd_get_status code for the initial/boot status

Tested on pcwd card with temperature option
parent 4e6e2877
......@@ -44,6 +44,11 @@
* Added timeout module option to override default
*/
/*
* A bells and whistles driver is available from http://www.pcwd.de/
* More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
......@@ -71,7 +76,7 @@
*/
static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
#define WD_VER "1.14 (03/12/2004)"
#define WD_VER "1.14 (03/26/2004)"
/*
* It should be noted that PCWD_REVISION_B was removed because A and B
......@@ -86,7 +91,6 @@ static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
#define WD_TIMEOUT 4 /* 2 seconds for a timeout */
static int timeout_val = WD_TIMEOUT;
static int timeout = 2;
static char expect_close;
module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=2)");
......@@ -102,7 +106,8 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
/*
* These are the defines for the PC Watchdog card, revision A.
* These are the defines that describe the control status bits for the
* PC Watchdog card, revision A.
*/
#define WD_WDRST 0x01 /* Previously reset state */
#define WD_T110 0x02 /* Temperature overheat sense */
......@@ -110,8 +115,17 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
#define WD_RLY2 0x08 /* External relay triggered */
#define WD_SRLY2 0x80 /* Software external relay triggered */
/*
* These are the defines that describe the control status bits for the
* PC Watchdog card, revision C.
*/
#define WD_REVC_WTRP 0x01 /* Watchdog Trip status */
#define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */
#define WD_REVC_TTRP 0x04 /* Temperature Trip status */
static int current_readport, revision, temp_panic;
static atomic_t open_allowed = ATOMIC_INIT(1);
static char expect_close;
static int initial_status, supports_temp, mode_debug;
static spinlock_t io_lock;
......@@ -187,46 +201,6 @@ static int __init pcwd_checkcard(void)
return((found) ? 1 : 0);
}
void pcwd_showprevstate(void)
{
int card_status = 0x0000;
if (revision == PCWD_REVISION_A)
initial_status = card_status = inb(current_readport);
else {
initial_status = card_status = inb(current_readport + 1);
outb_p(0x00, current_readport + 1); /* clear reset status */
}
if (revision == PCWD_REVISION_A) {
if (card_status & WD_WDRST)
printk(KERN_INFO "pcwd: Previous reboot was caused by the card.\n");
if (card_status & WD_T110) {
printk(KERN_EMERG "pcwd: Card senses a CPU Overheat. Panicking!\n");
printk(KERN_EMERG "pcwd: CPU Overheat.\n");
machine_power_off();
}
if ((!(card_status & WD_WDRST)) &&
(!(card_status & WD_T110)))
printk(KERN_INFO "pcwd: Cold boot sense.\n");
} else {
if (card_status & 0x01)
printk(KERN_INFO "pcwd: Previous reboot was caused by the card.\n");
if (card_status & 0x04) {
printk(KERN_EMERG "pcwd: Card senses a CPU Overheat. Panicking!\n");
printk(KERN_EMERG "pcwd: CPU Overheat.\n");
machine_power_off();
}
if ((!(card_status & 0x01)) &&
(!(card_status & 0x04)))
printk(KERN_INFO "pcwd: Cold boot sense.\n");
}
}
static int pcwd_start(void)
{
int stat_reg;
......@@ -281,6 +255,64 @@ static void pcwd_send_heartbeat(void)
outb_p(wdrst_stat, current_readport);
}
static int pcwd_get_status(int *status)
{
int card_status;
*status=0;
spin_lock(&io_lock);
if (revision == PCWD_REVISION_A)
/* Rev A cards return status information from
* the base register, which is used for the
* temperature in other cards. */
card_status = inb(current_readport);
else {
/* Rev C cards return card status in the base
* address + 1 register. And use different bits
* to indicate a card initiated reset, and an
* over-temperature condition. And the reboot
* status can be reset. */
card_status = inb(current_readport + 1);
}
spin_unlock(&io_lock);
if (revision == PCWD_REVISION_A) {
if (card_status & WD_WDRST)
*status |= WDIOF_CARDRESET;
if (card_status & WD_T110) {
*status |= WDIOF_OVERHEAT;
if (temp_panic) {
printk (KERN_INFO "pcwd: Temperature overheat trip!\n");
machine_power_off();
}
}
} else {
if (card_status & WD_REVC_WTRP)
*status |= WDIOF_CARDRESET;
if (card_status & WD_REVC_TTRP) {
*status |= WDIOF_OVERHEAT;
if (temp_panic) {
printk (KERN_INFO "pcwd: Temperature overheat trip!\n");
machine_power_off();
}
}
}
return 0;
}
static int pcwd_clear_status(void)
{
if (revision == PCWD_REVISION_C) {
spin_lock(&io_lock);
outb_p(0x00, current_readport + 1); /* clear reset status */
spin_unlock(&io_lock);
}
return 0;
}
static int pcwd_get_temperature(int *temperature)
{
/* check that port 0 gives temperature info and no command results */
......@@ -309,7 +341,8 @@ static int pcwd_get_temperature(int *temperature)
static int pcwd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
int cdat, rv;
int rv;
int status;
int temperature;
static struct watchdog_info ident=
{
......@@ -330,75 +363,13 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
return 0;
case WDIOC_GETSTATUS:
spin_lock(&io_lock);
if (revision == PCWD_REVISION_A)
cdat = inb(current_readport);
else
cdat = inb(current_readport + 1 );
spin_unlock(&io_lock);
rv = WDIOF_MAGICCLOSE;
if (revision == PCWD_REVISION_A)
{
if (cdat & WD_WDRST)
rv |= WDIOF_CARDRESET;
if (cdat & WD_T110)
{
rv |= WDIOF_OVERHEAT;
if (temp_panic) {
printk (KERN_INFO "pcwd: Temperature overheat trip!\n");
machine_power_off();
}
}
}
else
{
if (cdat & 0x01)
rv |= WDIOF_CARDRESET;
if (cdat & 0x04)
{
rv |= WDIOF_OVERHEAT;
if (temp_panic) {
printk (KERN_INFO "pcwd: Temperature overheat trip!\n");
machine_power_off();
}
}
}
if(put_user(rv, (int *) arg))
return -EFAULT;
return 0;
pcwd_get_status(&status);
return put_user(status, (int *) arg);
case WDIOC_GETBOOTSTATUS:
rv = 0;
if (revision == PCWD_REVISION_A)
{
if (initial_status & WD_WDRST)
rv |= WDIOF_CARDRESET;
if (initial_status & WD_T110)
rv |= WDIOF_OVERHEAT;
}
else
{
if (initial_status & 0x01)
rv |= WDIOF_CARDRESET;
if (initial_status & 0x04)
rv |= WDIOF_OVERHEAT;
}
if(put_user(rv, (int *) arg))
return -EFAULT;
return 0;
return put_user(initial_status, (int *) arg);
case WDIOC_GETTEMP:
if (pcwd_get_temperature(&temperature))
return -EFAULT;
......@@ -483,9 +454,9 @@ static int pcwd_close(struct inode *inode, struct file *file)
if (expect_close == 42) {
pcwd_stop();
atomic_inc( &open_allowed );
} else {
printk(KERN_CRIT "pcwd: Unexpected close, not stopping watchdog!\n");
pcwd_send_heartbeat();
} else {
printk(KERN_CRIT "pcwd: Unexpected close, not stopping watchdog!\n");
pcwd_send_heartbeat();
}
expect_close = 0;
return 0;
......@@ -675,6 +646,12 @@ static int __init pcwatchdog_init(void)
get_support();
revision = get_revision();
/* get the boot_status */
pcwd_get_status(&initial_status);
/* clear the "card caused reboot" flag */
pcwd_clear_status();
if (revision == PCWD_REVISION_A)
printk(KERN_INFO "pcwd: PC Watchdog (REV.A) detected at port 0x%03x\n", current_readport);
else if (revision == PCWD_REVISION_C) {
......@@ -688,12 +665,21 @@ static int __init pcwatchdog_init(void)
return -1;
}
debug_off();
if (supports_temp)
printk(KERN_INFO "pcwd: Temperature Option Detected.\n");
debug_off();
if (initial_status & WDIOF_CARDRESET)
printk(KERN_INFO "pcwd: Previous reboot was caused by the card.\n");
if (initial_status & WDIOF_OVERHEAT) {
printk(KERN_EMERG "pcwd: Card senses a CPU Overheat. Panicking!\n");
printk(KERN_EMERG "pcwd: CPU Overheat.\n");
}
pcwd_showprevstate();
if (initial_status == 0)
printk(KERN_INFO "pcwd: No previous trip detected - Cold boot or reset\n");
/* Disable the board */
if (revision == PCWD_REVISION_C) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment