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 @@ ...@@ -44,6 +44,11 @@
* Added timeout module option to override default * 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/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/types.h> #include <linux/types.h>
...@@ -71,7 +76,7 @@ ...@@ -71,7 +76,7 @@
*/ */
static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 }; 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 * 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 }; ...@@ -86,7 +91,6 @@ static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
#define WD_TIMEOUT 4 /* 2 seconds for a timeout */ #define WD_TIMEOUT 4 /* 2 seconds for a timeout */
static int timeout_val = WD_TIMEOUT; static int timeout_val = WD_TIMEOUT;
static int timeout = 2; static int timeout = 2;
static char expect_close;
module_param(timeout, int, 0); module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=2)"); 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 ...@@ -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_WDRST 0x01 /* Previously reset state */
#define WD_T110 0x02 /* Temperature overheat sense */ #define WD_T110 0x02 /* Temperature overheat sense */
...@@ -110,8 +115,17 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON ...@@ -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_RLY2 0x08 /* External relay triggered */
#define WD_SRLY2 0x80 /* Software 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 int current_readport, revision, temp_panic;
static atomic_t open_allowed = ATOMIC_INIT(1); static atomic_t open_allowed = ATOMIC_INIT(1);
static char expect_close;
static int initial_status, supports_temp, mode_debug; static int initial_status, supports_temp, mode_debug;
static spinlock_t io_lock; static spinlock_t io_lock;
...@@ -187,46 +201,6 @@ static int __init pcwd_checkcard(void) ...@@ -187,46 +201,6 @@ static int __init pcwd_checkcard(void)
return((found) ? 1 : 0); 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) static int pcwd_start(void)
{ {
int stat_reg; int stat_reg;
...@@ -281,6 +255,64 @@ static void pcwd_send_heartbeat(void) ...@@ -281,6 +255,64 @@ static void pcwd_send_heartbeat(void)
outb_p(wdrst_stat, current_readport); 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) static int pcwd_get_temperature(int *temperature)
{ {
/* check that port 0 gives temperature info and no command results */ /* check that port 0 gives temperature info and no command results */
...@@ -309,7 +341,8 @@ static int pcwd_get_temperature(int *temperature) ...@@ -309,7 +341,8 @@ static int pcwd_get_temperature(int *temperature)
static int pcwd_ioctl(struct inode *inode, struct file *file, static int pcwd_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg) unsigned int cmd, unsigned long arg)
{ {
int cdat, rv; int rv;
int status;
int temperature; int temperature;
static struct watchdog_info ident= static struct watchdog_info ident=
{ {
...@@ -330,75 +363,13 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, ...@@ -330,75 +363,13 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
return 0; return 0;
case WDIOC_GETSTATUS: case WDIOC_GETSTATUS:
spin_lock(&io_lock); pcwd_get_status(&status);
if (revision == PCWD_REVISION_A) return put_user(status, (int *) arg);
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;
case WDIOC_GETBOOTSTATUS: case WDIOC_GETBOOTSTATUS:
rv = 0; return put_user(initial_status, (int *) arg);
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;
case WDIOC_GETTEMP: case WDIOC_GETTEMP:
if (pcwd_get_temperature(&temperature)) if (pcwd_get_temperature(&temperature))
return -EFAULT; return -EFAULT;
...@@ -675,6 +646,12 @@ static int __init pcwatchdog_init(void) ...@@ -675,6 +646,12 @@ static int __init pcwatchdog_init(void)
get_support(); get_support();
revision = get_revision(); 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) if (revision == PCWD_REVISION_A)
printk(KERN_INFO "pcwd: PC Watchdog (REV.A) detected at port 0x%03x\n", current_readport); printk(KERN_INFO "pcwd: PC Watchdog (REV.A) detected at port 0x%03x\n", current_readport);
else if (revision == PCWD_REVISION_C) { else if (revision == PCWD_REVISION_C) {
...@@ -688,12 +665,21 @@ static int __init pcwatchdog_init(void) ...@@ -688,12 +665,21 @@ static int __init pcwatchdog_init(void)
return -1; return -1;
} }
debug_off();
if (supports_temp) if (supports_temp)
printk(KERN_INFO "pcwd: Temperature Option Detected.\n"); 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 */ /* Disable the board */
if (revision == PCWD_REVISION_C) { 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