diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/Makefile linux/drivers/char/Makefile
--- linux-2.4.18-pre7/drivers/char/Makefile	Tue Jan 29 12:55:48 2002
+++ linux/drivers/char/Makefile	Tue Jan 29 12:56:20 2002
@@ -235,6 +235,7 @@ obj-$(CONFIG_MACHZ_WDT) += machzwd.o
 obj-$(CONFIG_SH_WDT) += shwdt.o
 obj-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
 obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
+obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o
 
 subdir-$(CONFIG_MWAVE) += mwave
 ifeq ($(CONFIG_MWAVE),y)
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/acquirewdt.c linux/drivers/char/acquirewdt.c
--- linux-2.4.18-pre7/drivers/char/acquirewdt.c	Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/acquirewdt.c	Tue Jan 29 12:56:20 2002
@@ -17,6 +17,9 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
  *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Can't add timeout - driver doesn't allow changing value
  */
 
 #include <linux/config.h>
@@ -50,8 +53,14 @@ static spinlock_t acq_lock;
 #define WDT_STOP 0x43
 #define WDT_START 0x443
 
-#define WD_TIMO (100*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)");
 
 /*
  *	Kernel methods.
@@ -126,10 +135,12 @@ static int acq_open(struct inode *inode,
 				spin_unlock(&acq_lock);
 				return -EBUSY;
 			}
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
-	 
 			acq_is_open=1;
 			inb_p(WDT_START);      
 			spin_unlock(&acq_lock);
@@ -145,9 +156,9 @@ static int acq_close(struct inode *inode
 	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
 	{
 		spin_lock(&acq_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_STOP);
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_STOP);
+		}
 		acq_is_open=0;
 		spin_unlock(&acq_lock);
 	}
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/advantechwdt.c linux/drivers/char/advantechwdt.c
--- linux-2.4.18-pre7/drivers/char/advantechwdt.c	Tue Jan 29 12:55:48 2002
+++ linux/drivers/char/advantechwdt.c	Tue Jan 29 13:12:01 2002
@@ -19,7 +19,10 @@
  *	"AS-IS" and at no charge.	
  *
  *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
- *
+ * 
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Added timeout module option to override default
  */
 
 #include <linux/config.h>
@@ -56,25 +59,45 @@ static spinlock_t advwdt_lock;
  *	the manual says WDT_STOP is 0x43, not 0x443).
  *	(0x43 is also a write-only control register for the 8254 timer!)
  *
- *	TODO: module parameters to set the I/O port addresses and NOWAYOUT
- *	option at load time.
+ *	TODO: module parameters to set the I/O port addresses
  */
  
 #define WDT_STOP 0x443
 #define WDT_START 0x443
 
 #define WD_TIMO 60		/* 1 minute */
-static int wd_margin = WD_TIMO;
+static int timeout = WD_TIMO;	/* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)"); 
+
+#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)");
 
 /*
  *	Kernel methods.
  */
+static int
+advwdt_validate_timeout(void)
+{
+	if (timeout < 1 || timeout > 63) {
+		timeout = WD_TIMO;
+		printk(KERN_INFO "advantechwdt: timeout value must be 1 <= x <= 63, using %d\n", timeout);
+		return -EINVAL;
+	}
+	return 0;
+}
  
 static void
 advwdt_ping(void)
 {
 	/* Write a watchdog value */
-	outb_p(wd_margin, WDT_START);
+	outb_p(timeout, WDT_START);
 }
 
 static ssize_t
@@ -101,7 +124,7 @@ static int
 advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	  unsigned long arg)
 {
-	int new_margin;
+	int rc;
 	static struct watchdog_info ident = {
 		WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, 1, "Advantech WDT"
 	};
@@ -122,16 +145,15 @@ advwdt_ioctl(struct inode *inode, struct
 	  break;
 
 	case WDIOC_SETTIMEOUT:
-	  if (get_user(new_margin, (int *)arg))
+	  if (get_user(timeout, (int *)arg))
 		  return -EFAULT;
-	  if ((new_margin < 1) || (new_margin > 63))
-		  return -EINVAL;
-	  wd_margin = new_margin;
+	  rc = advwdt_validate_timeout();
+	  if (rc) return rc;
 	  advwdt_ping();
 	  /* Fall */
 
 	case WDIOC_GETTIMEOUT:
-	  return put_user(wd_margin, (int *)arg);
+	  return put_user(timeout, (int *)arg);
 	  break;
 
 	default:
@@ -150,6 +172,9 @@ advwdt_open(struct inode *inode, struct 
 				spin_unlock(&advwdt_lock);
 				return -EBUSY;
 			}
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
@@ -169,9 +194,9 @@ advwdt_close(struct inode *inode, struct
 	lock_kernel();
 	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
 		spin_lock(&advwdt_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_STOP);
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_STOP);
+		}
 		advwdt_is_open = 0;
 		spin_unlock(&advwdt_lock);
 	}
@@ -229,6 +254,7 @@ advwdt_init(void)
 {
 	printk("WDT driver for Advantech single board computer initialising.\n");
 
+	advwdt_validate_timeout();
 	spin_lock_init(&advwdt_lock);
 	misc_register(&advwdt_miscdev);
 #if WDT_START != WDT_STOP
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/eurotechwdt.c linux/drivers/char/eurotechwdt.c
--- linux-2.4.18-pre7/drivers/char/eurotechwdt.c	Tue Jan 29 12:55:48 2002
+++ linux/drivers/char/eurotechwdt.c	Tue Jan 29 13:16:42 2002
@@ -20,6 +20,10 @@
  *      "AS-IS" and at no charge.
  *
  *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>*
+ *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *          Added timeout module option to override default
  */
 
 #include <linux/config.h>
@@ -45,7 +49,6 @@
 #include <linux/smp_lock.h>
 
 static int eurwdt_is_open;
-static int eurwdt_timeout; 
 static spinlock_t eurwdt_lock;
  
 /*
@@ -58,6 +61,17 @@ static int irq = 10;
 static char *ev = "int";
  
 #define WDT_TIMEOUT		60                /* 1 minute */
+static int timeout = WDT_TIMEOUT;
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Eurotech WDT timeout in seconds (default=60)"); 
+
+#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)");
 
 
 /*
@@ -116,6 +130,18 @@ MODULE_PARM_DESC(ev, "Eurotech WDT event
  *      Programming support
  */
 
+static int
+eurwdt_validate_timeout(void)
+{
+	if (timeout < 0 || timeout > 255) {
+		timeout = WDT_TIMEOUT;
+		printk(KERN_INFO "eurwdt: timeout must be 0 < x < 255, using %d\n",
+		       timeout);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static inline void eurwdt_write_reg(u8 index, u8 data)
 {
    outb(index, io);
@@ -189,7 +215,7 @@ void eurwdt_interrupt(int irq, void *dev
 static void eurwdt_ping(void)
 {
    /* Write the watchdog default value */
-   eurwdt_set_timeout(eurwdt_timeout);
+   eurwdt_set_timeout(timeout);
 }
  
 /**
@@ -238,7 +264,7 @@ static int eurwdt_ioctl(struct inode *in
       identity		: "WDT Eurotech CPU-1220/1410"
    };
 
-   int time;
+   int rc;
  
    switch(cmd) {
       default:
@@ -256,19 +282,16 @@ static int eurwdt_ioctl(struct inode *in
          return 0;
 
       case WDIOC_SETTIMEOUT:
-         if (copy_from_user(&time, (int *) arg, sizeof(int)))
+         if (copy_from_user(&timeout, (int *) arg, sizeof(int)))
             return -EFAULT;
 
-         /* Sanity check */
-         if (time < 0 || time > 255)
-            return -EINVAL;
-
-         eurwdt_timeout = time; 
-         eurwdt_set_timeout(time); 
+	 rc = eurwdt_validate_timeout();
+	 if (rc) return rc;
+         eurwdt_set_timeout(timeout); 
 	 /* Fall */
 
       case WDIOC_GETTIMEOUT:
-	 return put_user(eurwdt_timeout, (int *)arg);
+	 return put_user(timeout, (int *)arg);
    }
 }
 
@@ -290,9 +313,11 @@ static int eurwdt_open(struct inode *ino
             spin_unlock(&eurwdt_lock);
             return -EBUSY;
          }
+	 if (nowayout) {
+		 MOD_INC_USE_COUNT;
+	 }
 
          eurwdt_is_open = 1;
-         eurwdt_timeout = WDT_TIMEOUT;   /* initial timeout */
 
          /* Activate the WDT */
          eurwdt_activate_timer(); 
@@ -326,14 +351,13 @@ static int eurwdt_open(struct inode *ino
 static int eurwdt_release(struct inode *inode, struct file *file)
 {
    if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-      eurwdt_disable_timer();
-#endif
-      eurwdt_is_open = 0;
+	   if (!nowayout) {
+		   eurwdt_disable_timer();
+	   }
+	   eurwdt_is_open = 0;
 
-      MOD_DEC_USE_COUNT;
+	   MOD_DEC_USE_COUNT;
    }
-
    return 0;
 }
  
@@ -425,7 +449,9 @@ static void __exit eurwdt_exit(void)
 static int __init eurwdt_init(void)
 {
    int ret;
- 
+
+   eurwdt_validate_timeout();
+
    ret = misc_register(&eurwdt_miscdev);
    if (ret) {
       printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n",
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/i810-tco.c linux/drivers/char/i810-tco.c
--- linux-2.4.18-pre7/drivers/char/i810-tco.c	Tue Jan 29 12:55:48 2002
+++ linux/drivers/char/i810-tco.c	Tue Jan 29 12:56:20 2002
@@ -1,5 +1,5 @@
 /*
- *	i810-tco 0.02:	TCO timer driver for i810 chipsets
+ *	i810-tco 0.03:	TCO timer driver for i810 chipsets
  *
  *	(c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
  *				http://www.kernelconcepts.de
@@ -28,6 +28,9 @@
  *	Initial Version 0.01
  *  20000728 Nils Faerber
  *      0.02 Fix for SMI_EN->TCO_EN bit, some cleanups
+ *  20011214 Matt Domsch <Matt_Domsch@dell.com>
+ *      0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *           Didn't add timeout option as i810_margin already exists.
  */
  
 #include <linux/module.h>
@@ -60,6 +63,18 @@ static spinlock_t tco_lock;	/* Guards th
 static int i810_margin = TIMER_MARGIN;	/* steps of 0.6sec */
 
 MODULE_PARM (i810_margin, "i");
+MODULE_PARM_DESC(i810_margin, "Watchdog timeout in steps of 0.6sec, 2<n<64. Default = 50 (30 seconds)");
+
+
+#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)");
+
 
 /*
  *	Timer active flag
@@ -167,6 +182,9 @@ static int i810tco_open (struct inode *i
 	if (timer_alive)
 		return -EBUSY;
 
+	if (nowayout) {
+		MOD_INC_USE_COUNT;
+	}
 	/*
 	 *      Reload and activate timer
 	 */
@@ -181,10 +199,10 @@ static int i810tco_release (struct inode
 	/*
 	 *      Shut off the timer.
 	 */
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-	tco_timer_stop ();
-	timer_alive = 0;
-#endif	
+	if (nowayout) {
+		tco_timer_stop ();
+		timer_alive = 0;
+	}
 	return 0;
 }
 
@@ -357,8 +375,8 @@ static int __init watchdog_init (void)
 	tco_timer_reload ();
 
 	printk (KERN_INFO
-		"i810 TCO timer: V0.02, timer margin: %d sec (0x%04x)\n",
-		(int) (i810_margin * 6 / 10), TCOBASE);
+		"i810 TCO timer: V0.03, timer margin: %d sec (0x%04x), nowayout: %d\n",
+		(int) (i810_margin * 6 / 10), TCOBASE, nowayout);
 	return 0;
 }
 
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/ib700wdt.c linux/drivers/char/ib700wdt.c
--- linux-2.4.18-pre7/drivers/char/ib700wdt.c	Tue Jan 29 12:55:48 2002
+++ linux/drivers/char/ib700wdt.c	Tue Jan 29 16:27:18 2002
@@ -25,6 +25,10 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@redhat.com>
  *
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *           Added timeout module option to override default
+ * 
  */
 
 #include <linux/config.h>
@@ -87,43 +91,48 @@ static spinlock_t ibwdt_lock;
  *
  */
 
-static int wd_times[] = {
-	30,	/* 0x0 */
-	28,	/* 0x1 */
-	26,	/* 0x2 */
-	24,	/* 0x3 */
-	22,	/* 0x4 */
-	20,	/* 0x5 */
-	18,	/* 0x6 */
-	16,	/* 0x7 */
-	14,	/* 0x8 */
-	12,	/* 0x9 */
-	10,	/* 0xA */
-	8,	/* 0xB */
-	6,	/* 0xC */
-	4,	/* 0xD */
-	2,	/* 0xE */
-	0,	/* 0xF */
-};
-
 #define WDT_STOP 0x441
 #define WDT_START 0x443
 
 /* Default timeout */
 #define WD_TIMO 0		/* 30 seconds +/- 20%, from table */
 
-static int wd_margin = WD_TIMO;
+static int timeout_val = WD_TIMO;	/* value in table */
+static int timeout = 30;	        /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, 0 < n < 30, must be even (default=30)");
+
+#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)");
 
 /*
  *	Kernel methods.
  */
 
+static int
+ibwdt_validate_timeout(void)
+{
+	timeout_val = (30 - timeout) / 2;
+	if (timeout_val < 0 || timeout_val > 0xF) {
+		timeout_val = WD_TIMO;
+		timeout = 30;
+		printk(KERN_INFO "ib700wdt: timeout must be 0 < x < 30, x even, using %d\n", timeout);
+		return -EINVAL;
+	}
+	return 0;
+}
+
 static void
 ibwdt_ping(void)
 {
 	/* Write a watchdog value */
-	outb_p(wd_times[wd_margin], WDT_START);
+	outb_p(timeout_val, WDT_START);
 }
 
 static ssize_t
@@ -150,7 +159,7 @@ static int
 ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	  unsigned long arg)
 {
-	int i, new_margin;
+	int rc;
 
 	static struct watchdog_info ident = {
 		WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, 1, "IB700 WDT"
@@ -172,19 +181,15 @@ ibwdt_ioctl(struct inode *inode, struct 
 	  break;
 
 	case WDIOC_SETTIMEOUT:
-	  if (get_user(new_margin, (int *)arg))
+	  if (get_user(timeout, (int *)arg))
 		  return -EFAULT;
-	  if ((new_margin < 0) || (new_margin > 30))
-		  return -EINVAL;
-	  for (i = 0x0F; i > -1; i--)
-		  if (wd_times[i] > new_margin)
-			  break;
-	  wd_margin = i;
+	  rc=ibwdt_validate_timeout();
+	  if (rc) return rc;
 	  ibwdt_ping();
 	  /* Fall */
 
 	case WDIOC_GETTIMEOUT:
-	  return put_user(wd_times[wd_margin], (int *)arg);
+	  return put_user(timeout, (int *)arg);
 	  break;
 
 	default:
@@ -203,6 +208,9 @@ ibwdt_open(struct inode *inode, struct f
 				spin_unlock(&ibwdt_lock);
 				return -EBUSY;
 			}
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate
 			 */
@@ -222,9 +230,9 @@ ibwdt_close(struct inode *inode, struct 
 	lock_kernel();
 	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
 		spin_lock(&ibwdt_lock);
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-		outb_p(wd_times[wd_margin], WDT_STOP);
-#endif
+		if (!nowayout) {
+			outb_p(timeout_val, WDT_STOP);
+		}
 		ibwdt_is_open = 0;
 		spin_unlock(&ibwdt_lock);
 	}
@@ -242,7 +250,7 @@ ibwdt_notify_sys(struct notifier_block *
 {
 	if (code == SYS_DOWN || code == SYS_HALT) {
 		/* Turn the WDT off */
-		outb_p(wd_times[wd_margin], WDT_STOP);
+		outb_p(timeout_val, WDT_STOP);
 	}
 	return NOTIFY_DONE;
 }
@@ -282,6 +290,7 @@ ibwdt_init(void)
 {
 	printk("WDT driver for IB700 single board computer initialising.\n");
 
+	ibwdt_validate_timeout();
 	spin_lock_init(&ibwdt_lock);
 	misc_register(&ibwdt_miscdev);
 #if WDT_START != WDT_STOP
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/machzwd.c linux/drivers/char/machzwd.c
--- linux-2.4.18-pre7/drivers/char/machzwd.c	Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/machzwd.c	Tue Jan 29 12:56:20 2002
@@ -24,6 +24,8 @@
  *  a system RESET and it starts wd#2 that unconditionaly will RESET 
  *  the system when the counter reaches zero.
  *
+ *  14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  */
 
 #include <linux/config.h>
@@ -103,6 +105,16 @@ MODULE_LICENSE("GPL");
 MODULE_PARM(action, "i");
 MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*)  1 = SMI  2 = NMI  3 = SCI");
 
+#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)");
+
+
 #define PFX "machzwd"
 
 static struct watchdog_info zf_info = {
@@ -307,23 +319,23 @@ static ssize_t zf_write(struct file *fil
  * no need to check for close confirmation
  * no way to disable watchdog ;)
  */
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-		size_t ofs;
-
-		/* 
-		 * note: just in case someone wrote the magic character
-		 * five months ago...
-		 */
-		zf_expect_close = 0;
-
-		/* now scan */
-		for(ofs = 0; ofs != count; ofs++){
-			if(buf[ofs] == 'V'){
-				zf_expect_close = 1;
-				dprintk("zf_expect_close 1\n");
+		if (!nowayout) {
+			size_t ofs;
+			
+			/* 
+			 * note: just in case someone wrote the magic character
+			 * five months ago...
+			 */
+			zf_expect_close = 0;
+			
+			/* now scan */
+			for(ofs = 0; ofs != count; ofs++){
+				if(buf[ofs] == 'V'){
+					zf_expect_close = 1;
+					dprintk("zf_expect_close 1\n");
+				}
 			}
 		}
-#endif
 		/*
 		 * Well, anyhow someone wrote to us,
 		 * we should return that favour
@@ -386,9 +398,9 @@ static int zf_open(struct inode *inode, 
 				return -EBUSY;
 			}
 
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-			MOD_INC_USE_COUNT;
-#endif
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			zf_is_open = 1;
 
 			spin_unlock(&zf_lock);
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/mixcomwd.c linux/drivers/char/mixcomwd.c
--- linux-2.4.18-pre7/drivers/char/mixcomwd.c	Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/mixcomwd.c	Tue Jan 29 12:56:20 2002
@@ -27,10 +27,13 @@
  *
  * Version 0.4 (99/11/15):
  *		- support for one more type board
+ *
+ * Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com>
+ *              - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  *	
  */
 
-#define VERSION "0.4" 
+#define VERSION "0.5" 
   
 #include <linux/module.h>
 #include <linux/config.h>
@@ -57,26 +60,30 @@ static int mixcomwd_ioports[] = { 0x180,
 static long mixcomwd_opened; /* long req'd for setbit --RR */
 
 static int watchdog_port;
-
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
 static int mixcomwd_timer_alive;
 static struct timer_list mixcomwd_timer;
+
+#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)");
+
 static void mixcomwd_ping(void)
 {
 	outb_p(55,watchdog_port);
 	return;
 }
 
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
 static void mixcomwd_timerfun(unsigned long d)
 {
 	mixcomwd_ping();
 	
 	mod_timer(&mixcomwd_timer,jiffies+ 5*HZ);
 }
-#endif
 
 /*
  *	Allow only one person to hold it open
@@ -89,12 +96,14 @@ static int mixcomwd_open(struct inode *i
 	}
 	mixcomwd_ping();
 	
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-	if(mixcomwd_timer_alive) {
-		del_timer(&mixcomwd_timer);
-		mixcomwd_timer_alive=0;
-	} 
-#endif
+	if (nowayout) {
+		MOD_INC_USE_COUNT;
+	} else {
+		if(mixcomwd_timer_alive) {
+			del_timer(&mixcomwd_timer);
+			mixcomwd_timer_alive=0;
+		}
+	}
 	return 0;
 }
 
@@ -102,19 +111,19 @@ static int mixcomwd_release(struct inode
 {
 
 	lock_kernel();
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-	if(mixcomwd_timer_alive) {
-		printk(KERN_ERR "mixcomwd: release called while internal timer alive");
-		unlock_kernel();
-		return -EBUSY;
+	if (!nowayout) {
+		if(mixcomwd_timer_alive) {
+			printk(KERN_ERR "mixcomwd: release called while internal timer alive");
+			unlock_kernel();
+			return -EBUSY;
+		}
+		init_timer(&mixcomwd_timer);
+		mixcomwd_timer.expires=jiffies + 5 * HZ;
+		mixcomwd_timer.function=mixcomwd_timerfun;
+		mixcomwd_timer.data=0;
+		mixcomwd_timer_alive=1;
+		add_timer(&mixcomwd_timer);
 	}
-	init_timer(&mixcomwd_timer);
-	mixcomwd_timer.expires=jiffies + 5 * HZ;
-	mixcomwd_timer.function=mixcomwd_timerfun;
-	mixcomwd_timer.data=0;
-	mixcomwd_timer_alive=1;
-	add_timer(&mixcomwd_timer);
-#endif
 
 	clear_bit(0,&mixcomwd_opened);
 	unlock_kernel();
@@ -148,9 +157,9 @@ static int mixcomwd_ioctl(struct inode *
 	{
 		case WDIOC_GETSTATUS:
 			status=mixcomwd_opened;
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-			status|=mixcomwd_timer_alive;
-#endif
+			if (!nowayout) {
+				status|=mixcomwd_timer_alive;
+			}
 			if (copy_to_user((int *)arg, &status, sizeof(int))) {
 				return -EFAULT;
 			}
@@ -255,14 +264,14 @@ static int __init mixcomwd_init(void)
 
 static void __exit mixcomwd_exit(void)
 {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-	if(mixcomwd_timer_alive) {
-		printk(KERN_WARNING "mixcomwd: I quit now, hardware will"
-			" probably reboot!\n");
-		del_timer(&mixcomwd_timer);
-		mixcomwd_timer_alive=0;
+	if (!nowayout) {
+		if(mixcomwd_timer_alive) {
+			printk(KERN_WARNING "mixcomwd: I quit now, hardware will"
+			       " probably reboot!\n");
+			del_timer(&mixcomwd_timer);
+			mixcomwd_timer_alive=0;
+		}
 	}
-#endif
 	release_region(watchdog_port,1);
 	misc_deregister(&mixcomwd_miscdev);
 }
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/pcwd.c linux/drivers/char/pcwd.c
--- linux-2.4.18-pre7/drivers/char/pcwd.c	Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/pcwd.c	Tue Jan 29 16:25:25 2002
@@ -40,6 +40,9 @@
  *		fairly useless proc entry.
  * 990610	removed said useless proc code for the merge <alan>
  * 000403	Removed last traces of proc code. <davej>
+ * 011214	Added nowayout module option <Matt_Domsch@dell.com>
+ *              to override CONFIG_WATCHDOG_NOWAYOUT
+ *              Added set/get timeout ioctl handlers (sets not allowed).
  */
 
 #include <linux/module.h>
@@ -76,7 +79,7 @@
  */
 static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
 
-#define WD_VER                  "1.10 (06/05/99)"
+#define WD_VER                  "1.12 (12/14/2001)"
 
 /*
  * It should be noted that PCWD_REVISION_B was removed because A and B
@@ -88,7 +91,17 @@ static int pcwd_ioports[] = { 0x270, 0x3
 #define	PCWD_REVISION_A		1
 #define	PCWD_REVISION_C		2
 
-#define	WD_TIMEOUT		3	/* 1 1/2 seconds for a timeout */
+#define	WD_TIMEOUT		4	/* 2 seconds for a timeout */
+
+#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)");
+
 
 /*
  * These are the defines for the PC Watchdog card, revision A.
@@ -181,7 +194,7 @@ static int __init pcwd_checkcard(void)
 	return((found) ? 1 : 0);
 }
 
-void pcwd_showprevstate(void)
+static void pcwd_showprevstate(void)
 {
 	int card_status = 0x0000;
 
@@ -377,6 +390,12 @@ static int pcwd_ioctl(struct inode *inod
 	case WDIOC_KEEPALIVE:
 		pcwd_send_heartbeat();
 		return 0;
+
+	case WDIOC_SETTIMEOUT:
+		return -ENOTSUPP;
+
+	case WDIOC_GETTIMEOUT:
+		return put_user(WD_TIMEOUT/2, (int *)arg);
 	}
 
 	return 0;
@@ -454,15 +473,15 @@ static int pcwd_close(struct inode *ino,
 	{
 		lock_kernel();
 	        is_open = 0;
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-		/*  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);
+		if (!nowayout) {
+			/*  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);
+			}
 		}
-#endif
 		unlock_kernel();
 	}
 	return 0;
@@ -563,7 +582,7 @@ static struct miscdevice temp_miscdev = 
 	"temperature",
 	&pcwd_fops
 };
- 
+
 static int __init pcwatchdog_init(void)
 {
 	int i, found = 0;
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/sbc60xxwdt.c linux/drivers/char/sbc60xxwdt.c
--- linux-2.4.18-pre7/drivers/char/sbc60xxwdt.c	Thu Sep 13 17:21:32 2001
+++ linux/drivers/char/sbc60xxwdt.c	Tue Jan 29 12:56:20 2002
@@ -109,6 +109,15 @@ static unsigned long next_heartbeat;
 static int wdt_is_open;
 static int wdt_expect_close;
 
+#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)");
+
 /*
  *	Whack the dog
  */
@@ -202,6 +211,9 @@ static int fop_open(struct inode * inode
 			/* Just in case we're already talking to someone... */
 			if(wdt_is_open)
 				return -EBUSY;
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/* Good, fire up the show */
 			wdt_is_open = 1;
 			wdt_startup();
@@ -217,7 +229,7 @@ static int fop_close(struct inode * inod
 	lock_kernel();
 	if(MINOR(inode->i_rdev) == WATCHDOG_MINOR) 
 	{
-		if(wdt_expect_close)
+		if(wdt_expect_close && !nowayout)
 			wdt_turnoff();
 		else {
 			del_timer(&timer);
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/shwdt.c linux/drivers/char/shwdt.c
--- linux-2.4.18-pre7/drivers/char/shwdt.c	Tue Jan 29 12:55:48 2002
+++ linux/drivers/char/shwdt.c	Tue Jan 29 12:56:20 2002
@@ -9,6 +9,9 @@
  * under the terms of the GNU General Public License as published by the
  * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
+ *
+ * 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *     Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -60,6 +63,15 @@
 static int sh_is_open = 0;
 static struct watchdog_info sh_wdt_info;
 
+#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)");
+
 /**
  *	sh_wdt_write_cnt - Write to Counter
  *
@@ -136,6 +148,9 @@ static int sh_wdt_open(struct inode *ino
 			if (sh_is_open) {
 				return -EBUSY;
 			}
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 
 			sh_is_open = 1;
 			sh_wdt_start();
@@ -161,9 +176,9 @@ static int sh_wdt_close(struct inode *in
 	lock_kernel();
 	
 	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-		sh_wdt_stop();
-#endif
+		if (!nowayout) {
+			sh_wdt_stop();
+		}
 		sh_is_open = 0;
 	}
 	
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/softdog.c linux/drivers/char/softdog.c
--- linux-2.4.18-pre7/drivers/char/softdog.c	Tue Jan 29 12:55:48 2002
+++ linux/drivers/char/softdog.c	Tue Jan 29 12:56:20 2002
@@ -1,5 +1,5 @@
 /*
- *	SoftDog	0.05:	A Software Watchdog Device
+ *	SoftDog	0.06:	A Software Watchdog Device
  *
  *	(c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
  *				http://www.redhat.com
@@ -31,6 +31,10 @@
  *	Added soft_noboot; Allows testing the softdog trigger without 
  *	requiring a recompile.
  *	Added WDIOC_GETTIMEOUT and WDIOC_SETTIMOUT.
+ *
+ *  20011214 Matt Domsch <Matt_Domsch@dell.com>
+ *      Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *      Didn't add timeout option, as soft_margin option already exists.
  */
  
 #include <linux/module.h>
@@ -57,6 +61,15 @@ static int soft_noboot = 0;
 
 MODULE_PARM(soft_margin,"i");
 MODULE_PARM(soft_noboot,"i");
+
+#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)");
 MODULE_LICENSE("GPL");
 
 /*
@@ -95,9 +108,9 @@ static int softdog_open(struct inode *in
 {
 	if(timer_alive)
 		return -EBUSY;
-#ifdef CONFIG_WATCHDOG_NOWAYOUT	 
-	MOD_INC_USE_COUNT;
-#endif	
+	if (nowayout) {
+		MOD_INC_USE_COUNT;
+	}
 	/*
 	 *	Activate timer
 	 */
@@ -110,12 +123,12 @@ static int softdog_release(struct inode 
 {
 	/*
 	 *	Shut off the timer.
-	 * 	Lock it in if it's a module and we defined ...NOWAYOUT
+	 * 	Lock it in if it's a module and we set nowayout
 	 */
 	 lock_kernel();
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	 
-	del_timer(&watchdog_ticktock);
-#endif	
+	 if(!nowayout) {
+		 del_timer(&watchdog_ticktock);
+	 }
 	timer_alive=0;
 	unlock_kernel();
 	return 0;
@@ -186,7 +199,7 @@ static struct miscdevice softdog_miscdev
 	fops:		&softdog_fops,
 };
 
-static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.05, timer margin: %d sec\n";
+static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.06, soft_margin: %d sec, nowayout: %d\n";
 
 static int __init watchdog_init(void)
 {
@@ -197,7 +210,7 @@ static int __init watchdog_init(void)
 	if (ret)
 		return ret;
 
-	printk(banner, soft_margin);
+	printk(banner, soft_margin, nowayout);
 
 	return 0;
 }
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/wdt.c linux/drivers/char/wdt.c
--- linux-2.4.18-pre7/drivers/char/wdt.c	Tue Jan 29 12:55:48 2002
+++ linux/drivers/char/wdt.c	Tue Jan 29 16:04:00 2002
@@ -15,7 +15,7 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
- *	Release 0.08.
+ *	Release 0.09.
  *
  *	Fixes
  *		Dave Gregorich	:	Modularisation and minor bugs
@@ -28,6 +28,7 @@
  *					Parameterized timeout
  *		Tigran Aivazian	:	Restructured wdt_init() to handle failures
  *		Joel Becker	:	Added WDIOC_GET/SETTIMEOUT
+ *		Matt Domsch	:	added nowayout and timeout module options
  */
 
 #include <linux/config.h>
@@ -64,7 +65,32 @@ static int irq=11;
 /* Default margin */
 #define WD_TIMO (100*60)		/* 1 minute */
 
-static int wd_margin = WD_TIMO;
+static int timeout_val = WD_TIMO;	/* value passed to card */
+static int timeout = 60;	        /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
+
+#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)");
+
+static int
+wdt_validate_timeout(void)
+{
+	/* Arbitrary, can't find the card's limits */
+	if (timeout < 0 || timeout > 60) {
+		timeout = 60;
+		timeout_val = WD_TIMO;
+		return -EINVAL;
+	}
+	timeout_val = timeout * 100;
+	return 0;
+}
 
 #ifndef MODULE
 
@@ -220,7 +246,7 @@ static void wdt_ping(void)
 	/* Write a watchdog value */
 	inb_p(WDT_DC);
 	wdt_ctr_mode(1,2);
-	wdt_ctr_load(1,wd_margin);		/* Timeout */
+	wdt_ctr_load(1,timeout_val);		/* Timeout */
 	outb_p(0, WDT_DC);
 }
 
@@ -298,7 +324,7 @@ static ssize_t wdt_read(struct file *fil
 static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
-	int new_margin;
+	int rc;
 
 	static struct watchdog_info ident=
 	{
@@ -325,16 +351,14 @@ static int wdt_ioctl(struct inode *inode
 			wdt_ping();
 			return 0;
 		case WDIOC_SETTIMEOUT:
-			if (get_user(new_margin, (int *)arg))
+			if (get_user(timeout, (int *)arg))
 				return -EFAULT;
-			/* Arbitrary, can't find the card's limits */
-			if ((new_margin < 0) || (new_margin > 60))
-				return -EINVAL;
-			wd_margin = new_margin * 100;
+			rc = wdt_validate_timeout();
+			if (rc) return rc;
 			wdt_ping();
 			/* Fall */
 		case WDIOC_GETTIMEOUT:
-			return put_user(wd_margin / 100, (int *)arg);
+			return put_user(timeout, (int *)arg);
 	}
 }
 
@@ -357,6 +381,9 @@ static int wdt_open(struct inode *inode,
 		case WATCHDOG_MINOR:
 			if(wdt_is_open)
 				return -EBUSY;
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
@@ -367,7 +394,7 @@ static int wdt_open(struct inode *inode,
 			wdt_ctr_mode(1,2);
 			wdt_ctr_mode(2,0);
 			wdt_ctr_load(0, 8948);		/* count at 100Hz */
-			wdt_ctr_load(1,wd_margin);	/* Timeout 120 seconds */
+			wdt_ctr_load(1,timeout_val);	/* Timeout */
 			wdt_ctr_load(2,65535);
 			outb_p(0, WDT_DC);	/* Enable */
 			return 0;
@@ -395,10 +422,10 @@ static int wdt_release(struct inode *ino
 	lock_kernel();
 	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
 	{
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_DC);		/* Disable counters */
-		wdt_ctr_load(2,0);	/* 0 length reset pulses now */
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_DC);		/* Disable counters */
+			wdt_ctr_load(2,0);	/* 0 length reset pulses now */
+		}
 		wdt_is_open=0;
 	}
 	unlock_kernel();
@@ -505,6 +532,7 @@ static int __init wdt_init(void)
 {
 	int ret;
 
+	wdt_validate_timeout();
 	ret = misc_register(&wdt_miscdev);
 	if (ret) {
 		printk(KERN_ERR "wdt: can't misc_register on minor=%d\n", WATCHDOG_MINOR);
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/wdt977.c linux/drivers/char/wdt977.c
--- linux-2.4.18-pre7/drivers/char/wdt977.c	Fri Sep  7 11:28:38 2001
+++ linux/drivers/char/wdt977.c	Tue Jan 29 16:05:05 2002
@@ -1,5 +1,5 @@
 /*
- *	Wdt977	0.01:	A Watchdog Device for Netwinder W83977AF chip
+ *	Wdt977	0.02:	A Watchdog Device for Netwinder W83977AF chip
  *
  *	(c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
  *
@@ -11,8 +11,13 @@
  *	2 of the License, or (at your option) any later version.
  *
  *			-----------------------
+ *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
+ *           Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *	19-Dec-2001 Woody Suwalski: Netwinder fixes, ioctl interface
+ *	06-Jan-2002 Woody Suwalski: For compatibility, convert all timeouts
+ *				    from minutes to seconds.
  */
- 
+
 #include <linux/module.h>
 #include <linux/config.h>
 #include <linux/types.h>
@@ -21,56 +26,123 @@
 #include <linux/miscdevice.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
+#include <linux/watchdog.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
 #include <asm/mach-types.h>
+#include <asm/uaccess.h>
 
 #define WATCHDOG_MINOR	130
 
-static	int timeout = 3;
+#define	DEFAULT_TIMEOUT	1	/* default timeout = 1 minute */
+
+static	int timeout = DEFAULT_TIMEOUT*60;	/* TO in seconds from user */
+static	int timeoutM = DEFAULT_TIMEOUT;		/* timeout in minutes */
 static	int timer_alive;
 static	int testmode;
 
+MODULE_PARM(timeout, "i");
+MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=60");
+MODULE_PARM(testmode, "i");
+MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
+
+#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)");
+
+
+/* This is kicking the watchdog by simply re-writing the timeout to reg. 0xF2 */
+static int kick_wdog(void)
+{
+	/*
+	 *	Refresh the timer.
+	 */
+
+	/* unlock the SuperIO chip */
+	outb(0x87,0x370);
+	outb(0x87,0x370);
+
+	/* select device Aux2 (device=8) and kicks watchdog reg F2 */
+	/* F2 has the timeout in minutes */
+
+	outb(0x07,0x370);
+	outb(0x08,0x371);
+	outb(0xF2,0x370);
+	outb(timeoutM,0x371);
+
+	/* lock the SuperIO chip */
+	outb(0xAA,0x370);
+
+	return 0;
+}
+
+
 /*
  *	Allow only one person to hold it open
  */
- 
+
 static int wdt977_open(struct inode *inode, struct file *file)
 {
+
 	if(timer_alive)
 		return -EBUSY;
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-	MOD_INC_USE_COUNT;
-#endif
+
+	/* convert seconds to minutes, rounding up */
+	timeoutM = timeout + 59;
+	timeoutM /= 60;
+
+	if (nowayout)
+	{
+		MOD_INC_USE_COUNT;
+
+		/* do not permit disabling the watchdog by writing 0 to reg. 0xF2 */
+		if (!timeoutM) timeoutM = DEFAULT_TIMEOUT;
+	}
 	timer_alive++;
 
-	//max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
-	if (timeout>255)
-	    timeout = 255;
-
-	printk(KERN_INFO "Watchdog: active, current timeout %d min.\n",timeout);
-
-	// unlock the SuperIO chip
-	outb(0x87,0x370); 
-	outb(0x87,0x370); 
-	
-	//select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
-	//F2 has the timeout in minutes
-	//F3 could be set to the POWER LED blink (with GP17 set to PowerLed)
-	//   at timeout, and to reset timer on kbd/mouse activity (not now)
-	//F4 is used to just clear the TIMEOUT'ed state (bit 0)
-	
+	if (machine_is_netwinder())
+	{
+		/* we have a hw bug somewhere, so each 977 minute is actually only 30sec
+		 *  this limits the max timeout to half of device max of 255 minutes...
+		 */
+		timeoutM += timeoutM;
+	}
+
+	/* max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog. */
+	if (timeoutM > 255) timeoutM = 255;
+
+	/* convert seconds to minutes */
+	printk(KERN_INFO "Wdt977 Watchdog activated: timeout = %d sec, nowayout = %i, testmode = %i.\n",
+		machine_is_netwinder() ? (timeoutM>>1)*60 : timeoutM*60,
+		nowayout, testmode);
+
+	/* unlock the SuperIO chip */
+	outb(0x87,0x370);
+	outb(0x87,0x370);
+
+	/* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4
+	 * F2 has the timeout in minutes
+	 * F3 could be set to the POWER LED blink (with GP17 set to PowerLed)
+	 *   at timeout, and to reset timer on kbd/mouse activity (not impl.)
+	 * F4 is used to just clear the TIMEOUT'ed state (bit 0)
+	 */
 	outb(0x07,0x370);
 	outb(0x08,0x371);
 	outb(0xF2,0x370);
-	outb(timeout,0x371);
+	outb(timeoutM,0x371);
 	outb(0xF3,0x370);
-	outb(0x00,0x371);	//another setting is 0E for kbd/mouse/LED
+	outb(0x00,0x371);	/* another setting is 0E for kbd/mouse/LED */
 	outb(0xF4,0x370);
 	outb(0x00,0x371);
-	
-	//at last select device Aux1 (dev=7) and set GP16 as a watchdog output
+
+	/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
+	/* in test mode watch the bit 1 on F4 to indicate "triggered" */
 	if (!testmode)
 	{
 		outb(0x07,0x370);
@@ -78,9 +150,9 @@ static int wdt977_open(struct inode *ino
 		outb(0xE6,0x370);
 		outb(0x08,0x371);
 	}
-		
-	// lock the SuperIO chip
-	outb(0xAA,0x370); 
+
+	/* lock the SuperIO chip */
+	outb(0xAA,0x370);
 
 	return 0;
 }
@@ -89,82 +161,158 @@ static int wdt977_release(struct inode *
 {
 	/*
 	 *	Shut off the timer.
-	 * 	Lock it in if it's a module and we defined ...NOWAYOUT
+	 * 	Lock it in if it's a module and we set nowayout
 	 */
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-	lock_kernel();
+	if (!nowayout)
+	{
+		lock_kernel();
 
-	// unlock the SuperIO chip
-	outb(0x87,0x370); 
-	outb(0x87,0x370); 
-	
-	//select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
-	//F3 is reset to its default state
-	//F4 can clear the TIMEOUT'ed state (bit 0) - back to default
-	//We can not use GP17 as a PowerLed, as we use its usage as a RedLed
-	
-	outb(0x07,0x370);
-	outb(0x08,0x371);
-	outb(0xF2,0x370);
-	outb(0xFF,0x371);
-	outb(0xF3,0x370);
-	outb(0x00,0x371);
-	outb(0xF4,0x370);
-	outb(0x00,0x371);
-	outb(0xF2,0x370);
-	outb(0x00,0x371);
-	
-	//at last select device Aux1 (dev=7) and set GP16 as a watchdog output
-	outb(0x07,0x370);
-	outb(0x07,0x371);
-	outb(0xE6,0x370);
-	outb(0x08,0x371);
-	
-	// lock the SuperIO chip
-	outb(0xAA,0x370);
+		/* unlock the SuperIO chip */
+		outb(0x87,0x370);
+		outb(0x87,0x370);
+
+		/* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4
+		* F3 is reset to its default state
+		* F4 can clear the TIMEOUT'ed state (bit 0) - back to default
+		* We can not use GP17 as a PowerLed, as we use its usage as a RedLed
+		*/
+		outb(0x07,0x370);
+		outb(0x08,0x371);
+		outb(0xF2,0x370);
+		outb(0xFF,0x371);
+		outb(0xF3,0x370);
+		outb(0x00,0x371);
+		outb(0xF4,0x370);
+		outb(0x00,0x371);
+		outb(0xF2,0x370);
+		outb(0x00,0x371);
 
-	timer_alive=0;
-	unlock_kernel();
+		/* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */
+		outb(0x07,0x370);
+		outb(0x07,0x371);
+		outb(0xE6,0x370);
+		outb(0x08,0x371);
 
-	printk(KERN_INFO "Watchdog: shutdown.\n");
-#endif
+		/* lock the SuperIO chip */
+		outb(0xAA,0x370);
+
+		timer_alive=0;
+		unlock_kernel();
+
+		printk(KERN_INFO "Wdt977 Watchdog: shutdown\n");
+	}
 	return 0;
 }
 
-static ssize_t wdt977_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+
+/*
+ *      wdt977_write:
+ *      @file: file handle to the watchdog
+ *      @buf: buffer to write (unused as data does not matter here
+ *      @count: count of bytes
+ *      @ppos: pointer to the position to write. No seeks allowed
+ *
+ *      A write to a watchdog device is defined as a keepalive signal. Any
+ *      write of data will do, as we we don't define content meaning.
+ */
+
+static ssize_t wdt977_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;
 
-	//max timeout value = 255 minutes (0xFF). Write 0 to disable WatchDog.
-	if (timeout>255)
-	    timeout = 255;
+	if(count)
+	{
+		kick_wdog();
+		return 1;
+	}
+	return 0;
+}
 
-	/*
-	 *	Refresh the timer.
-	 */
-		
-	//we have a hw bug somewhere, so each 977 minute is actually only 30sec
-	//as such limit the max timeout to half of max of 255 minutes...
-//	if (timeout>126)
-//	    timeout = 126;
-	
-	// unlock the SuperIO chip
-	outb(0x87,0x370); 
-	outb(0x87,0x370); 
-	
-	//select device Aux2 (device=8) and kicks watchdog reg F2
-	//F2 has the timeout in minutes
-	
-	outb(0x07,0x370);
-	outb(0x08,0x371);
-	outb(0xF2,0x370);
-	outb(timeout,0x371);
-	
-	// lock the SuperIO chip
-	outb(0xAA,0x370); 
-	
-	return 1;
+/*
+ *      wdt977_ioctl:
+ *      @inode: inode of the device
+ *      @file: file handle to the device
+ *      @cmd: watchdog command
+ *      @arg: argument pointer
+ *
+ *      The watchdog API defines a common set of functions for all watchdogs
+ *      according to their available features.
+ */
+
+static int wdt977_ioctl(struct inode *inode, struct file *file,
+         unsigned int cmd, unsigned long arg)
+{
+static struct watchdog_info ident = {
+	identity	: "Winbond 83977"
+};
+
+int temp;
+
+	switch(cmd)
+	{
+	default:
+		return -ENOTTY;
+
+	case WDIOC_GETSUPPORT:
+	    return copy_to_user((struct watchdog_info *)arg, &ident,
+			sizeof(ident)) ? -EFAULT : 0;
+
+	case WDIOC_GETBOOTSTATUS:
+		return put_user(0, (int *) arg);
+
+	case WDIOC_GETSTATUS:
+		/* unlock the SuperIO chip */
+		outb(0x87,0x370);
+		outb(0x87,0x370);
+
+		/* select device Aux2 (device=8) and read watchdog reg F4 */
+		outb(0x07,0x370);
+		outb(0x08,0x371);
+		outb(0xF4,0x370);
+		temp = inb(0x371);
+
+		/* lock the SuperIO chip */
+		outb(0xAA,0x370);
+
+		/* return info if "expired" in test mode */
+		return put_user(temp & 1, (int *) arg);
+
+	case WDIOC_KEEPALIVE:
+		kick_wdog();
+		return 0;
+
+	case WDIOC_SETTIMEOUT:
+		if (copy_from_user(&temp, (int *) arg, sizeof(int)))
+			return -EFAULT;
+
+		/* convert seconds to minutes, rounding up */
+		temp += 59;
+		temp /= 60;
+
+		/* we have a hw bug somewhere, so each 977 minute is actually only 30sec
+		*  this limits the max timeout to half of device max of 255 minutes...
+		*/
+		if (machine_is_netwinder())
+		{
+		    temp += temp;
+		}
+
+		/* Sanity check */
+		if (temp < 0 || temp > 255)
+			return -EINVAL;
+
+		if (!temp && nowayout)
+			return -EINVAL;
+
+		timeoutM = temp;
+		kick_wdog();
+		return 0;
+	}
 }
 
+
 static struct file_operations wdt977_fops=
 {
 	owner:		THIS_MODULE,
@@ -169,6 +317,7 @@ static struct file_operations wdt977_fop
 {
 	owner:		THIS_MODULE,
 	write:		wdt977_write,
+	ioctl:		wdt977_ioctl,
 	open:		wdt977_open,
 	release:	wdt977_release,
 };
@@ -186,9 +335,9 @@ static int __init nwwatchdog_init(void)
 		return -ENODEV;
 
 	misc_register(&wdt977_miscdev);
-	printk(KERN_INFO "NetWinder Watchdog sleeping.\n");
+	printk(KERN_INFO "Wdt977 Watchdog sleeping.\n");
 	return 0;
-}	
+}
 
 static void __exit nwwatchdog_exit(void)
 {
diff -BurNp --exclude-from=/home/mdomsch/excludes linux-2.4.18-pre7/drivers/char/wdt_pci.c linux/drivers/char/wdt_pci.c
--- linux-2.4.18-pre7/drivers/char/wdt_pci.c	Tue Jan 29 12:55:48 2002
+++ linux/drivers/char/wdt_pci.c	Tue Jan 29 16:06:32 2002
@@ -15,7 +15,7 @@
  *
  *	(c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
  *
- *	Release 0.08.
+ *	Release 0.10.
  *
  *	Fixes
  *		Dave Gregorich	:	Modularisation and minor bugs
@@ -31,6 +31,7 @@
  *		Jeff Garzik	:	PCI cleanups
  *		Tigran Aivazian	:	Restructured wdtpci_init_one() to handle failures
  *		Joel Becker	:	Added WDIOC_GET/SETTIMEOUT
+ *		Matt Domsch	:	added nowayout and timeout module options
  */
 
 #include <linux/config.h>
@@ -85,7 +86,32 @@ static int irq=11;
 /* Default timeout */
 #define WD_TIMO (100*60)		/* 1 minute */
 
-static int wd_margin = WD_TIMO;
+static int timeout_val = WD_TIMO;	/* value passed to card */
+static int timeout = 60;	        /* in seconds */
+MODULE_PARM(timeout,"i");
+MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (default=60)");
+
+#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)");
+
+static int
+wdtpci_validate_timeout(void)
+{
+	/* Arbitrary, can't find the card's limits */
+	if (timeout < 0 || timeout > 60) {
+		timeout = 60;
+		timeout_val = WD_TIMO;
+		return -EINVAL;
+	}
+	timeout_val = timeout * 100;
+	return 0;
+}
 
 #ifndef MODULE
 
@@ -236,7 +262,7 @@ static void wdtpci_ping(void)
 	/* Write a watchdog value */
 	inb_p(WDT_DC);
 	wdtpci_ctr_mode(1,2);
-	wdtpci_ctr_load(1,wd_margin);		/* Timeout */
+	wdtpci_ctr_load(1,timeout_val);		/* Timeout */
 	outb_p(0, WDT_DC);
 }
 
@@ -314,7 +340,7 @@ static ssize_t wdtpci_read(struct file *
 static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 	unsigned long arg)
 {
-	int new_margin;
+	int rc;
 	static struct watchdog_info ident=
 	{
 		WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER
@@ -340,16 +366,14 @@ static int wdtpci_ioctl(struct inode *in
 			wdtpci_ping();
 			return 0;
 		case WDIOC_SETTIMEOUT:
-			if (get_user(new_margin, (int *)arg))
+			if (get_user(timeout, (int *)arg))
 				return -EFAULT;
-			/* Arbitrary, can't find the card's limits */
-			if ((new_margin < 0) || (new_margin > 60))
-				return -EINVAL;
-			wd_margin = new_margin * 100;
+			rc = wdtpci_validate_timeout();
+			if (rc) return rc;
 			wdtpci_ping();
 			/* Fall */
 		case WDIOC_GETTIMEOUT:
-			return put_user(wd_margin, (int *)arg);
+			return put_user(timeout, (int *)arg);
 	}
 }
 
@@ -372,9 +396,9 @@ static int wdtpci_open(struct inode *ino
 		case WATCHDOG_MINOR:
 			if(wdt_is_open)
 				return -EBUSY;
-#ifdef CONFIG_WATCHDOG_NOWAYOUT	
-			MOD_INC_USE_COUNT;
-#endif
+			if (nowayout) {
+				MOD_INC_USE_COUNT;
+			}
 			/*
 			 *	Activate 
 			 */
@@ -402,7 +426,7 @@ static int wdtpci_open(struct inode *ino
 			wdtpci_ctr_mode(1,2);
 			wdtpci_ctr_mode(2,1);
 			wdtpci_ctr_load(0,20833);	/* count at 100Hz */
-			wdtpci_ctr_load(1,wd_margin);/* Timeout 60 seconds */
+			wdtpci_ctr_load(1,timeout_val); /* Timeout */
 			/* DO NOT LOAD CTR2 on PCI card! -- JPN */
 			outb_p(0, WDT_DC);	/* Enable */
 			return 0;
@@ -430,10 +454,10 @@ static int wdtpci_release(struct inode *
 	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
 	{
 		lock_kernel();
-#ifndef CONFIG_WATCHDOG_NOWAYOUT	
-		inb_p(WDT_DC);		/* Disable counters */
-		wdtpci_ctr_load(2,0);	/* 0 length reset pulses now */
-#endif		
+		if (!nowayout) {
+			inb_p(WDT_DC);		/* Disable counters */
+			wdtpci_ctr_load(2,0);	/* 0 length reset pulses now */
+		}
 		wdt_is_open=0;
 		unlock_kernel();
 	}
@@ -636,6 +660,8 @@ static int __init wdtpci_init(void)
 	
 	if (rc < 1)
 		return -ENODEV;
+
+	wdtpci_validate_timeout();
 	
 	return 0;
 }
