patches to back-port 2.1.x wdt driver to 2.0.33

Larry M. Augustin (lma@varesearch.com)
Tue, 10 Feb 1998 23:20:45 -0800


Here's a patch that back-ports most of the latest wdt driver to
2.0.33. I didn't put the ioctls in. Sorry. I may do them too if I
have time.

Larry

diff -u --recursive --new-file linux/drivers/char/watchdog.h linux.new/drivers/char/watchdog.h
--- linux/drivers/char/watchdog.h Wed Dec 31 16:00:00 1969
+++ linux.new/drivers/char/watchdog.h Tue Feb 10 00:03:58 1998
@@ -0,0 +1,40 @@
+/*
+ * Generic watchdog defines. Derived from..
+ *
+ * Berkshire PC Watchdog Defines
+ * by Ken Hollis <khollis@bitgate.com>
+ *
+ */
+
+#include <linux/ioctl.h>
+
+#define WATCHDOG_IOCTL_BASE 'W'
+
+struct watchdog_info {
+ u32 options; /* Options the card/driver supports */
+ u32 firmware_version; /* Firmware version of the card */
+ u8 identity[32]; /* Identity of the board */
+};
+
+#define WDIOC_GETSUPPORT _IOR(WATCHDOG_IOCTL_BASE, 0, struct watchdog_info)
+#define WDIOC_GETSTATUS _IOR(WATCHDOG_IOCTL_BASE, 1, int)
+#define WDIOC_GETBOOTSTATUS _IOR(WATCHDOG_IOCTL_BASE, 2, int)
+#define WDIOC_GETTEMP _IOR(WATCHDOG_IOCTL_BASE, 3, int)
+#define WDIOC_SETOPTIONS _IOR(WATCHDOG_IOCTL_BASE, 4, int)
+#define WDIOC_KEEPALIVE _IOR(WATCHDOG_IOCTL_BASE, 5, int)
+
+#define WDIOF_UNKNOWN -1 /* Unknown flag error */
+#define WDIOS_UNKNOWN -1 /* Unknown status error */
+
+#define WDIOF_OVERHEAT 0x0001 /* Reset due to CPU overheat */
+#define WDIOF_FANFAULT 0x0002 /* Fan failed */
+#define WDIOF_EXTERN1 0x0004 /* External relay 1 */
+#define WDIOF_EXTERN2 0x0008 /* External relay 2 */
+#define WDIOF_POWERUNDER 0x0010 /* Power bad/power fault */
+#define WDIOF_CARDRESET 0x0020 /* Card previously reset the CPU */
+#define WDIOF_POWEROVER 0x0040 /* Power over voltage */
+#define WDIOF_KEEPALIVEPING 0x8000 /* Keep alive ping reply */
+
+#define WDIOS_DISABLECARD 0x0001 /* Turn off the watchdog timer */
+#define WDIOS_ENABLECARD 0x0002 /* Turn on the watchdog timer */
+#define WDIOS_TEMPPANIC 0x0004 /* Kernel panic on temperature trip */
diff -u --recursive --new-file linux/drivers/char/wd501p.h linux.new/drivers/char/wd501p.h
--- linux/drivers/char/wd501p.h Wed Oct 15 15:22:46 1997
+++ linux.new/drivers/char/wd501p.h Tue Feb 10 11:33:21 1998
@@ -20,7 +20,7 @@
*/

#include <linux/config.h>
-
+
#define WATCHDOG_MINOR 130 /* Watchdog timer */
#define TEMP_MINOR 131 /* Temperature Sensor */

@@ -51,8 +51,10 @@

#ifdef CONFIG_WDT501_FAN /* Full board, Fan has no tachometer */
#define FEATUREMAP1 0
+#define WDT_OPTION_MASK (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER|WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT)
#else
#define FEATUREMAP1 WDC_SR_FANGOOD
+#define WDT_OPTION_MASK (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER|WDIOF_EXTERN1|WDIOF_EXTERN2)
#endif

#define FEATUREMAP2 0
@@ -65,6 +67,7 @@
#ifdef CONFIG_WDT_500 /* Minimal board */
#define FEATUREMAP1 (WDC_SR_TGOOD|WDC_SR_FANGOOD)
#define FEATUREMAP2 (WDC_SR_PSUOVER|WDC_SR_PSUUNDR)
+#define WDT_OPTION_MASK (WDIOF_OVERHEAT)
#endif

#ifndef FEATUREMAP1
diff -u --recursive --new-file linux/drivers/char/wdt.c linux.new/drivers/char/wdt.c
--- linux/drivers/char/wdt.c Fri Apr 12 00:33:25 1996
+++ linux.new/drivers/char/wdt.c Tue Feb 10 14:14:57 1998
@@ -1,23 +1,30 @@
/*
- * Industrial Computer Source WDT500/501 driver for Linux 1.3.x
+ * Industrial Computer Source WDT500/501 driver for Linux 2.1.x
*
- * (c) Copyright 1995 CymruNET Ltd
- * Innovation Centre
- * Singleton Park
- * Swansea
- * Wales
- * UK
- * SA2 8PP
+ * (c) Copyright 1996-1997 Alan Cox <alan@cymru.net>, All Rights Reserved.
+ * http://www.cymru.net
*
- * http://www.cymru.net
+ * This program is free software; you can redistribute it and/or
+ * modify it 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.
+ *
+ * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
+ * warranty for any of this software. This material is provided
+ * "AS-IS" and at no charge.
*
- * This driver is provided under the GNU public license, incorporated
- * herein by reference. The driver is provided without warranty or
- * support.
+ * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>
*
- * Release 0.05.
+ * Based on Alan Cox's Release 0.07 ported from 2.1.x back to 2.0.33
+ * by Larry M. Augustin <lma@varesearch.com>
*
- * Some changes by Dave Gregorich to fix modularisation and minor bugs.
+ * Fixes
+ * Dave Gregorich : Modularisation and minor bugs
+ * Alan Cox : Added the watchdog ioctl() stuff
+ * Alan Cox : Fixed the reboot problem (as noted by
+ * Matt Crocker).
+ * Alan Cox : Added wdt= boot option
+ * Larry M. Augustin : Back ported to 2.0.x.
*/

#include <linux/config.h>
@@ -29,6 +36,7 @@
#include <linux/sched.h>
#include <linux/miscdevice.h>
#include "wd501p.h"
+#include "watchdog.h"
#include <linux/malloc.h>
#include <linux/ioport.h>
#include <linux/fcntl.h>
@@ -36,18 +44,45 @@
#include <asm/segment.h>
#include <asm/system.h>

+#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
+#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,35)
+#include <linux/init.h>
+#else
+#ifndef __initdata
+#define __initdata
+#endif
+#ifndef __initfunc
+#define __initfunc(__arginit) __arginit
+#endif
+#endif
+
static int wdt_is_open=0;

/*
* You must set these - there is no sane way to probe for this board.
+ * You can use wdt=x,y to set these now.
*/

-int io=0x240;
-int irq=14;
+static int io=0x240;
+static int irq=11;

#define WD_TIMO (100*60) /* 1 minute */

/*
+ * Setup options
+ */
+
+__initfunc(void wdt_setup(char *str, int *ints))
+{
+ if(ints[0]>0)
+ {
+ io=ints[1];
+ if(ints[0]>1)
+ irq=ints[2];
+ }
+}
+
+/*
* Programming support
*/

@@ -68,8 +103,36 @@
/*
* Kernel methods.
*/
-
-static void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+
+#if 0
+static int wdt_status(void)
+{
+ /*
+ * Status register to bit flags
+ */
+
+ int flag=0;
+ unsigned char status=inb_p(WDT_SR);
+ status|=FEATUREMAP1;
+ status&=~FEATUREMAP2;
+
+ if(!(status&WDC_SR_TGOOD))
+ flag|=WDIOF_OVERHEAT;
+ if(!(status&WDC_SR_PSUOVER))
+ flag|=WDIOF_POWEROVER;
+ if(!(status&WDC_SR_PSUUNDR))
+ flag|=WDIOF_POWERUNDER;
+ if(!(status&WDC_SR_FANGOOD))
+ flag|=WDIOF_FANFAULT;
+ if(status&WDC_SR_ISOI0)
+ flag|=WDIOF_EXTERN1;
+ if(status&WDC_SR_ISII1)
+ flag|=WDIOF_EXTERN2;
+ return flag;
+}
+#endif
+
+void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
/*
* Read the status register see what is up and
@@ -97,7 +160,7 @@
printk(KERN_CRIT "Would Reboot.\n");
#else
printk(KERN_CRIT "Initiating system reboot.\n");
- hard_reset_now();
+ machine_restart(NULL);
#endif
#else
printk(KERN_CRIT "Reset in 5ms.\n");
@@ -105,27 +168,35 @@
}


-static int wdt_lseek(struct inode *inode, struct file *file, off_t offset,
- int origin)
+static int wdt_lseek(struct inode *inode, struct file *file, off_t offset, int origin)
{
return -ESPIPE;
}

-static int wdt_write(struct inode *inode, struct file *file, const char *buf, int count)
+static void wdt_ping(void)
{
/* Write a watchdog value */
inb_p(WDT_DC);
wdt_ctr_mode(1,2);
wdt_ctr_load(1,WD_TIMO); /* Timeout */
outb_p(0, WDT_DC);
- return count;
+}
+
+static ssize_t wdt_write(struct inode *inode, struct file *file, const char *buf, int count)
+{
+ if(count)
+ {
+ wdt_ping();
+ return 1;
+ }
+ return 0;
}

/*
* Read reports the temperature in farenheit
*/

-static int wdt_read(struct inode *inode, struct file *file, char *buf, int count)
+static ssize_t wdt_read(struct inode *inode, struct file *file, char *buf, int count)
{
unsigned short c=inb_p(WDT_RT);
unsigned char cp;
@@ -150,6 +221,45 @@
static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
unsigned long arg)
{
+#if 0
+ int i;
+ static struct watchdog_info ident=
+ {
+ WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER
+ |WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT,
+ 1,
+ "WDT500/501"
+ };
+
+ ident.options&=WDT_OPTION_MASK; /* Mask down to the card we have */
+ switch(cmd)
+ {
+ default:
+ return -ENOIOCTLCMD;
+ case WDIOC_GETSUPPORT:
+ i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(struct watchdog_info));
+ if (i)
+ return i;
+ else {
+ memcpy_tofs((struct watchdog_info *)arg, &ident, sizeof(ident));
+ return sizeof(ident);
+ }
+
+ case WDIOC_GETSTATUS:
+ i = verify_area(VERIFY_WRITE, (void*) arg, sizeof(int));
+ if (i)
+ return i;
+ else
+ {
+ return put_user(wdt_status(),(int *)arg);
+ }
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, (int *)arg);
+ case WDIOC_KEEPALIVE:
+ wdt_ping();
+ return 0;
+ }
+#endif
return -EINVAL;
}

@@ -170,8 +280,8 @@
wdt_ctr_mode(0,3);
wdt_ctr_mode(1,2);
wdt_ctr_mode(2,0);
- wdt_ctr_load(0, 8948); /* count at 100Hz */
- wdt_ctr_load(1,WD_TIMO); /* Timeout 120 seconds */
+ wdt_ctr_load(0, 8948); /* count at 100Hz */
+ wdt_ctr_load(1,WD_TIMO); /* Timeout 60 seconds */
wdt_ctr_load(2,65535);
outb_p(0, WDT_DC); /* Enable */
return 0;
@@ -195,7 +305,7 @@
}
MOD_DEC_USE_COUNT;
}
-
+
/*
* Kernel Interfaces
*/
@@ -216,7 +326,7 @@
static struct miscdevice wdt_miscdev=
{
WATCHDOG_MINOR,
- "wdt",
+ "watchdog",
&wdt_fops
};

@@ -231,21 +341,7 @@

#ifdef MODULE

-int init_module(void)
-{
- printk("WDT501-P module at %X(Interrupt %d)\n", io,irq);
- if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL))
- {
- printk("IRQ %d is not free.\n", irq);
- return -EIO;
- }
- misc_register(&wdt_miscdev);
-#ifdef CONFIG_WDT_501
- misc_register(&temp_miscdev);
-#endif
- request_region(io, 8, "wdt501");
- return 0;
-}
+#define wdt_init init_module

void cleanup_module(void)
{
@@ -257,11 +353,11 @@
free_irq(irq, NULL);
}

-#else
+#endif

-int wdt_init(void)
+__initfunc(int wdt_init(void))
{
- printk("WDT500/501-P driver at %X(Interrupt %d)\n", io,irq);
+ printk("WDT500/501-P driver 0.07 at %X (Interrupt %d)\n", io,irq);
if(request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL))
{
printk("IRQ %d is not free.\n", irq);
@@ -271,8 +367,7 @@
#ifdef CONFIG_WDT_501
misc_register(&temp_miscdev);
#endif
- request_region(io, 8, "wdt501");
+ request_region(io, 8, "wdt501p");
return 0;
}

-#endif
diff -u --recursive --new-file linux/init/main.c linux.new/init/main.c
--- linux/init/main.c Thu Aug 14 10:30:08 1997
+++ linux.new/init/main.c Mon Feb 9 23:31:41 1998
@@ -180,6 +180,9 @@
#ifdef CONFIG_BAYCOM
extern void baycom_setup(char *str, int *ints);
#endif
+#ifdef CONFIG_WDT
+extern void wdt_setup(char *str, int *ints);
+#endif


#if defined(CONFIG_SYSVIPC) || defined(CONFIG_KERNELD)
@@ -438,6 +441,9 @@
#endif
#ifdef CONFIG_BAYCOM
{ "baycom=", baycom_setup },
+#endif
+#ifdef CONFIG_WDT
+ { "wdt=", wdt_setup },
#endif
{ 0, 0 }
};

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu