Commit 84d1e7b7 authored by Wim Van Sebroeck's avatar Wim Van Sebroeck

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

Version 1.14 of pcwd.c - Changes that were made are:
* Extract the start code in a seperate function (pcwd_start)
* Extract the stop code in a seperate function (pcwd_stop)
* Extract the get_temperature code in a seperate function (pcwd_get_temperature)
* Make /dev/watchdog and /dev/temperature to different misc devices with their own fops
* Small clean-up's

Tested on pcwd card with temperature option.
parent 6582e43d
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
*/ */
static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 }; static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
#define WD_VER "1.12 (12/14/2001)" #define WD_VER "1.14 (03/12/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
...@@ -227,6 +227,45 @@ void pcwd_showprevstate(void) ...@@ -227,6 +227,45 @@ void pcwd_showprevstate(void)
} }
} }
static int pcwd_start(void)
{
int stat_reg;
/* Enable the port */
if (revision == PCWD_REVISION_C) {
spin_lock(&io_lock);
outb_p(0x00, current_readport + 3);
stat_reg = inb_p(current_readport + 2);
spin_unlock(&io_lock);
if (stat_reg & 0x10)
{
printk(KERN_INFO "pcwd: Could not start watchdog.\n");
return -EIO;
}
}
return 0;
}
static int pcwd_stop(void)
{
int stat_reg;
/* Disable the board */
if (revision == PCWD_REVISION_C) {
spin_lock(&io_lock);
outb_p(0xA5, current_readport + 3);
outb_p(0xA5, current_readport + 3);
stat_reg = inb_p(current_readport + 2);
spin_unlock(&io_lock);
if ((stat_reg & 0x10) == 0)
{
printk(KERN_INFO "pcwd: Could not stop watchdog.\n");
return -EIO;
}
}
return 0;
}
static void pcwd_send_heartbeat(void) static void pcwd_send_heartbeat(void)
{ {
int wdrst_stat; int wdrst_stat;
...@@ -242,13 +281,41 @@ static void pcwd_send_heartbeat(void) ...@@ -242,13 +281,41 @@ static void pcwd_send_heartbeat(void)
outb_p(wdrst_stat, current_readport); outb_p(wdrst_stat, current_readport);
} }
static int pcwd_get_temperature(int *temperature)
{
/* check that port 0 gives temperature info and no command results */
if (mode_debug)
return -1;
*temperature = 0;
if (!supports_temp)
return -ENODEV;
/*
* Convert celsius to fahrenheit, since this was
* the decided 'standard' for this return value.
*/
spin_lock(&io_lock);
*temperature = ((inb(current_readport)) * 9 / 5) + 32;
spin_unlock(&io_lock);
return 0;
}
/*
* /dev/watchdog handling
*/
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 cdat, rv;
int temperature;
static struct watchdog_info ident= static struct watchdog_info ident=
{ {
.options = WDIOF_OVERHEAT|WDIOF_CARDRESET, .options = WDIOF_OVERHEAT |
WDIOF_CARDRESET |
WDIOF_MAGICCLOSE,
.firmware_version = 1, .firmware_version = 1,
.identity = "PCWD", .identity = "PCWD",
}; };
...@@ -332,17 +399,10 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, ...@@ -332,17 +399,10 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
case WDIOC_GETTEMP: case WDIOC_GETTEMP:
rv = 0; if (pcwd_get_temperature(&temperature))
if ((supports_temp) && (mode_debug == 0))
{
spin_lock(&io_lock);
rv = inb(current_readport);
spin_unlock(&io_lock);
if(put_user(rv, (int*) arg))
return -EFAULT; return -EFAULT;
} else if(put_user(rv, (int*) arg))
return -EFAULT; return put_user(temperature, (int *) arg);
return 0;
case WDIOC_SETOPTIONS: case WDIOC_SETOPTIONS:
if (revision == PCWD_REVISION_C) if (revision == PCWD_REVISION_C)
...@@ -352,32 +412,12 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, ...@@ -352,32 +412,12 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
if (rv & WDIOS_DISABLECARD) if (rv & WDIOS_DISABLECARD)
{ {
spin_lock(&io_lock); return pcwd_stop();
outb_p(0xA5, current_readport + 3);
outb_p(0xA5, current_readport + 3);
cdat = inb_p(current_readport + 2);
spin_unlock(&io_lock);
if ((cdat & 0x10) == 0)
{
printk(KERN_INFO "pcwd: Could not disable card.\n");
return -EIO;
}
return 0;
} }
if (rv & WDIOS_ENABLECARD) if (rv & WDIOS_ENABLECARD)
{ {
spin_lock(&io_lock); return pcwd_start();
outb_p(0x00, current_readport + 3);
cdat = inb_p(current_readport + 2);
spin_unlock(&io_lock);
if (cdat & 0x10)
{
printk(KERN_INFO "pcwd: Could not enable card.\n");
return -EIO;
}
return 0;
} }
if (rv & WDIOS_TEMPPANIC) if (rv & WDIOS_TEMPPANIC)
...@@ -423,72 +463,66 @@ static ssize_t pcwd_write(struct file *file, const char *buf, size_t len, ...@@ -423,72 +463,66 @@ static ssize_t pcwd_write(struct file *file, const char *buf, size_t len,
return len; return len;
} }
static int pcwd_open(struct inode *ino, struct file *filep) static int pcwd_open(struct inode *inode, struct file *file)
{ {
switch (iminor(ino)) {
case WATCHDOG_MINOR:
if (!atomic_dec_and_test(&open_allowed) ) { if (!atomic_dec_and_test(&open_allowed) ) {
atomic_inc( &open_allowed ); atomic_inc( &open_allowed );
return -EBUSY; return -EBUSY;
} }
if (nowayout)
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
/* Enable the port */
if (revision == PCWD_REVISION_C) {
spin_lock(&io_lock);
outb_p(0x00, current_readport + 3);
spin_unlock(&io_lock);
}
return(0);
case TEMP_MINOR: /* Activate */
pcwd_start();
return(0); return(0);
default: }
return (-ENODEV);
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();
} }
expect_close = 0;
return 0;
} }
static ssize_t pcwd_read(struct file *file, char *buf, size_t count, /*
* /dev/temperature handling
*/
static ssize_t pcwd_temp_read(struct file *file, char *buf, size_t count,
loff_t *ppos) loff_t *ppos)
{ {
unsigned short c; int temperature;
unsigned char cp;
/* Can't seek (pread) on this device */ /* Can't seek (pread) on this device */
if (ppos != &file->f_pos) if (ppos != &file->f_pos)
return -ESPIPE; return -ESPIPE;
switch(iminor(file->f_dentry->d_inode))
{
case TEMP_MINOR:
/*
* Convert metric to Fahrenheit, since this was
* the decided 'standard' for this return value.
*/
c = inb(current_readport); if (pcwd_get_temperature(&temperature))
cp = (c * 9 / 5) + 32; return -EFAULT;
if(copy_to_user(buf, &cp, 1))
if (copy_to_user(buf, &temperature, 1))
return -EFAULT; return -EFAULT;
return 1; return 1;
default:
return -EINVAL;
}
} }
static int pcwd_close(struct inode *ino, struct file *filep) static int pcwd_temp_open(struct inode *inode, struct file *file)
{
if (!supports_temp)
return -ENODEV;
return 0;
}
static int pcwd_temp_close(struct inode *inode, struct file *file)
{ {
if (iminor(ino)==WATCHDOG_MINOR) {
if (expect_close == 42) {
/* Disable the board */
if (revision == PCWD_REVISION_C) {
spin_lock(&io_lock);
outb_p(0xA5, current_readport + 3);
outb_p(0xA5, current_readport + 3);
spin_unlock(&io_lock);
}
atomic_inc( &open_allowed );
}
}
expect_close = 0;
return 0; return 0;
} }
...@@ -569,7 +603,7 @@ static void debug_off(void) ...@@ -569,7 +603,7 @@ static void debug_off(void)
static struct file_operations pcwd_fops = { static struct file_operations pcwd_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.read = pcwd_read, .llseek = no_llseek,
.write = pcwd_write, .write = pcwd_write,
.ioctl = pcwd_ioctl, .ioctl = pcwd_ioctl,
.open = pcwd_open, .open = pcwd_open,
...@@ -582,10 +616,18 @@ static struct miscdevice pcwd_miscdev = { ...@@ -582,10 +616,18 @@ static struct miscdevice pcwd_miscdev = {
.fops = &pcwd_fops, .fops = &pcwd_fops,
}; };
static struct file_operations pcwd_temp_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.read = pcwd_temp_read,
.open = pcwd_temp_open,
.release = pcwd_temp_close,
};
static struct miscdevice temp_miscdev = { static struct miscdevice temp_miscdev = {
.minor = TEMP_MINOR, .minor = TEMP_MINOR,
.name = "temperature", .name = "temperature",
.fops = &pcwd_fops, .fops = &pcwd_temp_fops,
}; };
static void __init pcwd_validate_timeout(void) static void __init pcwd_validate_timeout(void)
......
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