patch-2.4.20 linux-2.4.20/drivers/char/eurotechwdt.c
Next file: linux-2.4.20/drivers/char/ftape/Config.in
Previous file: linux-2.4.20/drivers/char/efirtc.c
Back to the patch index
Back to the overall index
- Lines: 464
- Date:
Thu Nov 28 15:53:12 2002
- Orig file:
linux-2.4.19/drivers/char/eurotechwdt.c
- Orig date:
Fri Aug 2 17:39:43 2002
diff -urN linux-2.4.19/drivers/char/eurotechwdt.c linux-2.4.20/drivers/char/eurotechwdt.c
@@ -35,6 +35,9 @@
*
* 2001 - Rodolfo Giometti
* Initial release
+ *
+ * 2002.05.30 - Joel Becker <joel.becker@oracle.com>
+ * Added Matt Domsch's nowayout module option.
*/
#include <linux/config.h>
@@ -68,6 +71,14 @@
#define WDT_TIMEOUT 60 /* 1 minute */
+#ifdef CONFIG_WATCHDOG_NOWAYOUT
+static int nowayout = 1;
+#else
+static int nowayout = 0;
+#endif
+
+MODULE_PARM(nowayout,"i");
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
/*
* Some symbolic names
@@ -127,48 +138,48 @@
static inline void eurwdt_write_reg(u8 index, u8 data)
{
- outb(index, io);
- outb(data, io+1);
+ outb(index, io);
+ outb(data, io+1);
}
static inline void eurwdt_lock_chip(void)
{
- outb(0xaa, io);
+ outb(0xaa, io);
}
static inline void eurwdt_unlock_chip(void)
{
- outb(0x55, io);
- eurwdt_write_reg(0x07, 0x08); /* set the logical device */
+ outb(0x55, io);
+ eurwdt_write_reg(0x07, 0x08); /* set the logical device */
}
static inline void eurwdt_set_timeout(int timeout)
{
- eurwdt_write_reg(WDT_TIMEOUT_VAL, (u8) timeout);
+ eurwdt_write_reg(WDT_TIMEOUT_VAL, (u8) timeout);
}
static inline void eurwdt_disable_timer(void)
{
- eurwdt_set_timeout(0);
+ eurwdt_set_timeout(0);
}
static void eurwdt_activate_timer(void)
{
- eurwdt_disable_timer();
- eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */
- eurwdt_write_reg(WDT_OUTPIN_CFG, !strcmp("int", ev) ?
+ eurwdt_disable_timer();
+ eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */
+ eurwdt_write_reg(WDT_OUTPIN_CFG, !strcmp("int", ev) ?
WDT_EVENT_INT : WDT_EVENT_REBOOT);
- /* Setting interrupt line */
- if (irq == 2 || irq > 15 || irq < 0) {
- printk(KERN_ERR ": invalid irq number\n");
- irq = 0; /* if invalid we disable interrupt */
- }
- if (irq == 0)
- printk(KERN_INFO ": interrupt disabled\n");
- eurwdt_write_reg(WDT_TIMER_CFG, irq<<4);
+ /* Setting interrupt line */
+ if (irq == 2 || irq > 15 || irq < 0) {
+ printk(KERN_ERR ": invalid irq number\n");
+ irq = 0; /* if invalid we disable interrupt */
+ }
+ if (irq == 0)
+ printk(KERN_INFO ": interrupt disabled\n");
+ eurwdt_write_reg(WDT_TIMER_CFG, irq<<4);
- eurwdt_write_reg(WDT_UNIT_SEL, WDT_UNIT_SECS); /* we use seconds */
- eurwdt_set_timeout(0); /* the default timeout */
+ eurwdt_write_reg(WDT_UNIT_SEL, WDT_UNIT_SECS); /* we use seconds */
+ eurwdt_set_timeout(0); /* the default timeout */
}
@@ -178,13 +189,13 @@
void eurwdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
- printk(KERN_CRIT "timeout WDT timeout\n");
+ printk(KERN_CRIT "timeout WDT timeout\n");
#ifdef ONLY_TESTING
- printk(KERN_CRIT "Would Reboot.\n");
+ printk(KERN_CRIT "Would Reboot.\n");
#else
- printk(KERN_CRIT "Initiating system reboot.\n");
- machine_restart(NULL);
+ printk(KERN_CRIT "Initiating system reboot.\n");
+ machine_restart(NULL);
#endif
}
@@ -197,8 +208,8 @@
static void eurwdt_ping(void)
{
- /* Write the watchdog default value */
- eurwdt_set_timeout(eurwdt_timeout);
+ /* Write the watchdog default value */
+ eurwdt_set_timeout(eurwdt_timeout);
}
/**
@@ -212,28 +223,29 @@
* write of data will do, as we we don't define content meaning.
*/
-static ssize_t eurwdt_write(struct file *file, const char *buf, size_t count,
-loff_t *ppos)
+static ssize_t eurwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
- /* Can't seek (pwrite) on this device */
- if (ppos != &file->f_pos)
- return -ESPIPE;
-
- if (count) {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
- size_t i;
-
- eur_expect_close = 0;
-
- for (i = 0; i != count; i++) {
- if (buf[i] == 'V')
- eur_expect_close = 42;
- }
-#endif
- eurwdt_ping(); /* the default timeout */
- }
-
- return count;
+ /* Can't seek (pwrite) on this device */
+ if (ppos != &file->f_pos)
+ return -ESPIPE;
+
+ if (count) {
+ if (!nowayout) {
+ size_t i;
+
+ eur_expect_close = 0;
+
+ for (i = 0; i != count; i++) {
+ char c;
+ if(get_user(c, buf+i))
+ return -EFAULT;
+ if (c == 'V')
+ eur_expect_close = 42;
+ }
+ }
+ eurwdt_ping(); /* the default timeout */
+ }
+ return count;
}
/**
@@ -250,66 +262,54 @@
static int eurwdt_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
- static struct watchdog_info ident = {
- options : WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
- firmware_version : 0,
- identity : "WDT Eurotech CPU-1220/1410"
- };
-
- int time;
-
- switch(cmd) {
- default:
- return -ENOTTY;
-
- case WDIOC_GETSUPPORT:
- return copy_to_user((struct watchdog_info *)arg, &ident,
- sizeof(ident)) ? -EFAULT : 0;
-
- case WDIOC_GETSTATUS:
- case WDIOC_GETBOOTSTATUS:
- return put_user(0, (int *) arg);
-
- case WDIOC_KEEPALIVE:
- eurwdt_ping();
- return 0;
-
- case WDIOC_SETTIMEOUT:
- if (copy_from_user(&time, (int *) arg, sizeof(int)))
- return -EFAULT;
-
- /* Sanity check */
- if (time < 0 || time > 255)
- return -EINVAL;
-
- eurwdt_timeout = time;
- eurwdt_set_timeout(time);
- /* Fall */
-
- case WDIOC_GETTIMEOUT:
- return put_user(eurwdt_timeout, (int *)arg);
-
- case WDIOC_SETOPTIONS:
- {
- int options, retval = -EINVAL;
-
- if (get_user(options, (int *)arg))
- return -EFAULT;
-
- if (options & WDIOS_DISABLECARD) {
- eurwdt_disable_timer();
- retval = 0;
- }
-
- if (options & WDIOS_ENABLECARD) {
- eurwdt_activate_timer();
- eurwdt_ping();
- retval = 0;
- }
-
- return retval;
- }
- }
+ static struct watchdog_info ident = {
+ options : WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+ firmware_version : 0,
+ identity : "WDT Eurotech CPU-1220/1410"
+ };
+ int time;
+
+ switch(cmd) {
+ default:
+ return -ENOTTY;
+ case WDIOC_GETSUPPORT:
+ return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)) ? -EFAULT : 0;
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, (int *) arg);
+ case WDIOC_KEEPALIVE:
+ eurwdt_ping();
+ return 0;
+ case WDIOC_SETTIMEOUT:
+ if (copy_from_user(&time, (int *) arg, sizeof(int)))
+ return -EFAULT;
+ /* Sanity check */
+ if (time < 0 || time > 255)
+ return -EINVAL;
+ eurwdt_timeout = time;
+ eurwdt_set_timeout(time);
+ /* Fall */
+ case WDIOC_GETTIMEOUT:
+ return put_user(eurwdt_timeout, (int *)arg);
+ case WDIOC_SETOPTIONS:
+ {
+ int options, retval = -EINVAL;
+
+ if (get_user(options, (int *)arg))
+ return -EFAULT;
+ if (options & WDIOS_DISABLECARD) {
+ eurwdt_disable_timer();
+ retval = 0;
+ }
+
+ if (options & WDIOS_ENABLECARD) {
+ eurwdt_activate_timer();
+ eurwdt_ping();
+ retval = 0;
+ }
+ return retval;
+ }
+ }
}
/**
@@ -323,15 +323,15 @@
static int eurwdt_open(struct inode *inode, struct file *file)
{
- if (test_and_set_bit(0, &eurwdt_is_open))
- return -EBUSY;
+ if (test_and_set_bit(0, &eurwdt_is_open))
+ return -EBUSY;
- eurwdt_timeout = WDT_TIMEOUT; /* initial timeout */
+ eurwdt_timeout = WDT_TIMEOUT; /* initial timeout */
- /* Activate the WDT */
- eurwdt_activate_timer();
+ /* Activate the WDT */
+ eurwdt_activate_timer();
- return 0;
+ return 0;
}
/**
@@ -348,16 +348,15 @@
static int eurwdt_release(struct inode *inode, struct file *file)
{
- if (eur_expect_close == 42) {
- eurwdt_disable_timer();
- } else {
- printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n");
- eurwdt_ping();
- }
- clear_bit(0, &eurwdt_is_open);
- eur_expect_close = 0;
-
- return 0;
+ if (eur_expect_close == 42) {
+ eurwdt_disable_timer();
+ } else {
+ printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n");
+ eurwdt_ping();
+ }
+ clear_bit(0, &eurwdt_is_open);
+ eur_expect_close = 0;
+ return 0;
}
/**
@@ -375,12 +374,11 @@
static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code,
void *unused)
{
- if (code == SYS_DOWN || code == SYS_HALT) {
- /* Turn the card off */
- eurwdt_disable_timer();
- }
-
- return NOTIFY_DONE;
+ if (code == SYS_DOWN || code == SYS_HALT) {
+ /* Turn the card off */
+ eurwdt_disable_timer();
+ }
+ return NOTIFY_DONE;
}
/*
@@ -428,13 +426,11 @@
static void __exit eurwdt_exit(void)
{
- eurwdt_lock_chip();
-
- misc_deregister(&eurwdt_miscdev);
-
- unregister_reboot_notifier(&eurwdt_notifier);
- release_region(io, 2);
- free_irq(irq, NULL);
+ eurwdt_lock_chip();
+ misc_deregister(&eurwdt_miscdev);
+ unregister_reboot_notifier(&eurwdt_notifier);
+ release_region(io, 2);
+ free_irq(irq, NULL);
}
/**
@@ -447,52 +443,44 @@
static int __init eurwdt_init(void)
{
- int ret;
-
- ret = misc_register(&eurwdt_miscdev);
- if (ret) {
- printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
- WATCHDOG_MINOR);
- goto out;
- }
-
- ret = request_irq(irq, eurwdt_interrupt, SA_INTERRUPT, "eurwdt", NULL);
- if(ret) {
- printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
- goto outmisc;
- }
-
- if (!request_region(io, 2, "eurwdt")) {
- printk(KERN_ERR "eurwdt: IO %X is not free.\n", io);
- ret = -EBUSY;
- goto outirq;
- }
-
- ret = register_reboot_notifier(&eurwdt_notifier);
- if (ret) {
- printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret);
- goto outreg;
- }
-
- eurwdt_unlock_chip();
+ int ret;
- ret = 0;
- printk(KERN_INFO "Eurotech WDT driver 0.01 at %X (Interrupt %d)"
- " - timeout event: %s\n",
- io, irq, (!strcmp("int", ev) ? "int" : "reboot"));
-
- out:
- return ret;
-
- outreg:
- release_region(io, 2);
-
- outirq:
- free_irq(irq, NULL);
-
- outmisc:
- misc_deregister(&eurwdt_miscdev);
- goto out;
+ ret = misc_register(&eurwdt_miscdev);
+ if (ret) {
+ printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", WATCHDOG_MINOR);
+ goto out;
+ }
+ ret = request_irq(irq, eurwdt_interrupt, SA_INTERRUPT, "eurwdt", NULL);
+ if(ret) {
+ printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq);
+ goto outmisc;
+ }
+
+ if (!request_region(io, 2, "eurwdt")) {
+ printk(KERN_ERR "eurwdt: IO %X is not free.\n", io);
+ ret = -EBUSY;
+ goto outirq;
+ }
+
+ ret = register_reboot_notifier(&eurwdt_notifier);
+ if (ret) {
+ printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret);
+ goto outreg;
+ }
+ eurwdt_unlock_chip();
+
+ ret = 0;
+ printk(KERN_INFO "Eurotech WDT driver 0.01 at %X (Interrupt %d)"
+ " - timeout event: %s\n", io, irq, (!strcmp("int", ev) ? "int" : "reboot"));
+ return ret;
+outreg:
+ release_region(io, 2);
+outirq:
+ free_irq(irq, NULL);
+outmisc:
+ misc_deregister(&eurwdt_miscdev);
+out:
+ return ret;
}
module_init(eurwdt_init);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)