From: Ralf Baechle <ralf@linux-mips.org>

Forward port of the 2.4 driver with changes required for 2.6.

Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/drivers/char/watchdog/indydog.c |  117 ++++++++++++--------------------
 1 files changed, 45 insertions(+), 72 deletions(-)

diff -puN drivers/char/watchdog/indydog.c~indydog-update drivers/char/watchdog/indydog.c
--- 25/drivers/char/watchdog/indydog.c~indydog-update	2004-06-22 11:09:03.408424560 -0700
+++ 25-akpm/drivers/char/watchdog/indydog.c	2004-06-22 11:09:03.413423800 -0700
@@ -22,16 +22,11 @@
 #include <linux/notifier.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
-#include <linux/moduleparam.h>
 #include <asm/uaccess.h>
-#include <asm/sgi/sgimc.h>
+#include <asm/sgi/mc.h>
 
 #define PFX "indydog: "
-#define WATCHDOG_HEARTBEAT 60
-
-static unsigned long indydog_alive;
-static struct sgimc_misc_ctrl *mcmisc_regs;
-static char expect_close;
+static int indydog_alive;
 
 #ifdef CONFIG_WATCHDOG_NOWAYOUT
 static int nowayout = 1;
@@ -39,96 +34,78 @@ static int nowayout = 1;
 static int nowayout = 0;
 #endif
 
+#define WATCHDOG_TIMEOUT 30		/* 30 sec default timeout */
+
 module_param(nowayout, int, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
 
 static void indydog_start(void)
 {
-	u32 mc_ctrl0 = mcmisc_regs->cpuctrl0;
+	u32 mc_ctrl0 = sgimc->cpuctrl0;
 
-	mc_ctrl0 |= SGIMC_CCTRL0_WDOG;
-	mcmisc_regs->cpuctrl0 = mc_ctrl0;
-
-	printk(KERN_INFO PFX "Started watchdog timer.\n");
+	mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG;
+	sgimc->cpuctrl0 = mc_ctrl0;
 }
 
 static void indydog_stop(void)
 {
-	u32 mc_ctrl0 = mcmisc_regs->cpuctrl0;
+	u32 mc_ctrl0 = sgimc->cpuctrl0;
 
 	mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG;
-	mcmisc_regs->cpuctrl0 = mc_ctrl0;
+	sgimc->cpuctrl0 = mc_ctrl0;
 
 	printk(KERN_INFO PFX "Stopped watchdog timer.\n");
 }
 
 static void indydog_ping(void)
 {
-	mcmisc_regs->watchdogt = 0;
+	sgimc->watchdogt = 0;
 }
 
 /*
  *	Allow only one person to hold it open
  */
-
 static int indydog_open(struct inode *inode, struct file *file)
 {
-	if( test_and_set_bit(0,&indydog_alive) )
+	if (indydog_alive)
 		return -EBUSY;
 
 	if (nowayout)
 		__module_get(THIS_MODULE);
 
-	/*
-	 *	Activate timer
-	 */
+	/* Activate timer */
 	indydog_start();
 	indydog_ping();
 
+	indydog_alive = 1;
+	printk(KERN_INFO "Started watchdog timer.\n");
+
 	return 0;
 }
 
 static int indydog_release(struct inode *inode, struct file *file)
 {
-	/*
-	 *	Shut off the timer.
-	 * 	Lock it in if it's a module and we set nowayout
-	 */
-
-	if (expect_close == 42) {
-		indydog_stop();
-	} else {
-		printk(KERN_CRIT PFX "WDT device closed unexpectedly.  WDT will not stop!\n");
-		indydog_ping();
+	/* Shut off the timer.
+	 * Lock it in if it's a module and we defined ...NOWAYOUT */
+	if (!nowayout) {
+		u32 mc_ctrl0 = sgimc->cpuctrl0;
+		mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG;
+		sgimc->cpuctrl0 = mc_ctrl0;
+		printk(KERN_INFO "Stopped watchdog timer.\n");
 	}
-	clear_bit(0,&indydog_alive);
-	expect_close = 0;
+	indydog_alive = 0;
+
 	return 0;
 }
 
 static ssize_t indydog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
 {
-	/*  Can't seek (pwrite) on this device  */
+	/* Can't seek (pwrite) on this device */
 	if (ppos != &file->f_pos)
 		return -ESPIPE;
 
 	/* Refresh the timer. */
 	if (len) {
-		if (!nowayout) {
-			size_t i;
-
-			/* In case it was set long ago */
-			expect_close = 0;
-
-			for (i = 0; i != len; i++) {
-				char c;
-
-				if (get_user(c, data + i))
-					return -EFAULT;
-				if (c == 'V')
-					expect_close = 42;
-			}
-		}
 		indydog_ping();
 	}
 	return len;
@@ -139,17 +116,18 @@ static int indydog_ioctl(struct inode *i
 {
 	int options, retval = -EINVAL;
 	static struct watchdog_info ident = {
-		.options =		WDIOF_KEEPALIVEPING |
-					WDIOF_MAGICCLOSE,
-		.firmware_version =	0,
-		.identity =		"Hardware Watchdog for SGI IP22",
+		.options		= WDIOF_KEEPALIVEPING |
+					  WDIOF_MAGICCLOSE,
+		.firmware_version	= 0,
+		.identity		= "Hardware Watchdog for SGI IP22",
 	};
 
 	switch (cmd) {
 		default:
 			return -ENOIOCTLCMD;
 		case WDIOC_GETSUPPORT:
-			if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+			if (copy_to_user((struct watchdog_info *)arg,
+					 &ident, sizeof(ident)))
 				return -EFAULT;
 			return 0;
 		case WDIOC_GETSTATUS:
@@ -165,14 +143,12 @@ static int indydog_ioctl(struct inode *i
 			if (get_user(options, (int *)arg))
 				return -EFAULT;
 
-			if (options & WDIOS_DISABLECARD)
-			{
+			if (options & WDIOS_DISABLECARD) {
 				indydog_stop();
 				retval = 0;
 			}
 
-			if (options & WDIOS_ENABLECARD)
-			{
+			if (options & WDIOS_ENABLECARD) {
 				indydog_start();
 				retval = 0;
 			}
@@ -184,40 +160,37 @@ static int indydog_ioctl(struct inode *i
 
 static int indydog_notify_sys(struct notifier_block *this, unsigned long code, void *unused)
 {
-	if (code==SYS_DOWN || code==SYS_HALT) {
-		/* Turn the WDT off */
-		indydog_stop();
-	}
+	if (code == SYS_DOWN || code == SYS_HALT)
+		indydog_stop();		/* Turn the WDT off */
 
 	return NOTIFY_DONE;
 }
 
 static struct file_operations indydog_fops = {
-	.owner	= THIS_MODULE,
-	.write	= indydog_write,
-	.ioctl	= indydog_ioctl,
-	.open	= indydog_open,
-	.release= indydog_release,
+	.owner		= THIS_MODULE,
+	.write		= indydog_write,
+	.ioctl		= indydog_ioctl,
+	.open		= indydog_open,
+	.release	= indydog_release,
 };
 
 static struct miscdevice indydog_miscdev = {
-	.minor	= WATCHDOG_MINOR,
-	.name	= "watchdog",
-	.fops	= &indydog_fops,
+	.minor		= WATCHDOG_MINOR,
+	.name		= "watchdog",
+	.fops		= &indydog_fops,
 };
 
 static struct notifier_block indydog_notifier = {
 	.notifier_call = indydog_notify_sys,
 };
 
-static char banner[] __initdata = KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n";
+static char banner[] __initdata =
+	KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n";
 
 static int __init watchdog_init(void)
 {
 	int ret;
 
-	mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000);
-
 	ret = register_reboot_notifier(&indydog_notifier);
 	if (ret) {
 		printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
_