]> git.hungrycats.org Git - linux/commitdiff
Move watchdog drivers to drivers/char/watchdog/
authorDave Jones <davej@codemonkey.org.uk>
Fri, 22 Nov 2002 12:01:27 +0000 (12:01 +0000)
committerDave Jones <davej@codemonkey.org.uk>
Fri, 22 Nov 2002 12:01:27 +0000 (12:01 +0000)
38 files changed:
drivers/char/Kconfig
drivers/char/Makefile
drivers/char/acquirewdt.c [deleted file]
drivers/char/advantechwdt.c [deleted file]
drivers/char/eurotechwdt.c [deleted file]
drivers/char/i810-tco.c [deleted file]
drivers/char/ib700wdt.c [deleted file]
drivers/char/machzwd.c [deleted file]
drivers/char/mixcomwd.c [deleted file]
drivers/char/pcwd.c [deleted file]
drivers/char/sbc60xxwdt.c [deleted file]
drivers/char/scx200_wdt.c [deleted file]
drivers/char/shwdt.c [deleted file]
drivers/char/softdog.c [deleted file]
drivers/char/w83877f_wdt.c [deleted file]
drivers/char/watchdog/Kconfig [new file with mode: 0644]
drivers/char/watchdog/Makefile [new file with mode: 0644]
drivers/char/watchdog/acquirewdt.c [new file with mode: 0644]
drivers/char/watchdog/advantechwdt.c [new file with mode: 0644]
drivers/char/watchdog/eurotechwdt.c [new file with mode: 0644]
drivers/char/watchdog/i810-tco.c [new file with mode: 0644]
drivers/char/watchdog/ib700wdt.c [new file with mode: 0644]
drivers/char/watchdog/machzwd.c [new file with mode: 0644]
drivers/char/watchdog/mixcomwd.c [new file with mode: 0644]
drivers/char/watchdog/pcwd.c [new file with mode: 0644]
drivers/char/watchdog/sbc60xxwdt.c [new file with mode: 0644]
drivers/char/watchdog/scx200_wdt.c [new file with mode: 0644]
drivers/char/watchdog/shwdt.c [new file with mode: 0644]
drivers/char/watchdog/softdog.c [new file with mode: 0644]
drivers/char/watchdog/w83877f_wdt.c [new file with mode: 0644]
drivers/char/watchdog/wdt.c [new file with mode: 0644]
drivers/char/watchdog/wdt285.c [new file with mode: 0644]
drivers/char/watchdog/wdt977.c [new file with mode: 0644]
drivers/char/watchdog/wdt_pci.c [new file with mode: 0644]
drivers/char/wdt.c [deleted file]
drivers/char/wdt285.c [deleted file]
drivers/char/wdt977.c [deleted file]
drivers/char/wdt_pci.c [deleted file]

index ee08a533bf81dd27e29725e6f9dd52b86844c254..2d9e8abdfc28ef58ca3462550be161e05b795f10 100644 (file)
@@ -636,289 +636,7 @@ comment "from the tpqic02-support package.  It is available at"
 comment "metalab.unc.edu or ftp://titus.cfw.com/pub/Linux/util/"
        depends on QIC02_TAPE && QIC02_DYNCONF
 
-
-menu "Watchdog Cards"
-
-config WATCHDOG
-       bool "Watchdog Timer Support"
-       ---help---
-         If you say Y here (and to one of the following options) and create a
-         character special file /dev/watchdog with major number 10 and minor
-         number 130 using mknod ("man mknod"), you will get a watchdog, i.e.:
-         subsequently opening the file and then failing to write to it for
-         longer than 1 minute will result in rebooting the machine. This
-         could be useful for a networked machine that needs to come back
-         online as fast as possible after a lock-up. There's both a watchdog
-         implementation entirely in software (which can sometimes fail to
-         reboot the machine) and a driver for hardware watchdog boards, which
-         are more robust and can also keep track of the temperature inside
-         your computer. For details, read <file:Documentation/watchdog.txt>
-         in the kernel source.
-
-         The watchdog is usually used together with the watchdog daemon
-         which is available from
-         <ftp://ibiblio.org/pub/Linux/system/daemons/watchdog/>. This daemon can
-         also monitor NFS connections and can reboot the machine when the process
-         table is full.
-
-         If unsure, say N.
-
-config WATCHDOG_NOWAYOUT
-       bool "Disable watchdog shutdown on close"
-       depends on WATCHDOG
-       help
-         The default watchdog behaviour (which you get if you say N here) is
-         to stop the timer if the process managing it closes the file
-         /dev/watchdog. It's always remotely possible that this process might
-         get killed. If you say Y here, the watchdog cannot be stopped once
-         it has been started.
-
-config SOFT_WATCHDOG
-       tristate "Software watchdog"
-       depends on WATCHDOG
-       help
-         A software monitoring watchdog. This will fail to reboot your system
-         from some situations that the hardware watchdog will recover
-         from. Equally it's a lot cheaper to install.
-
-         This driver is also available as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you want).
-         If you want to compile it as a module, say M here and read
-         <file:Documentation/modules.txt>. The module will be called
-         softdog.o.
-
-config WDT
-       tristate "WDT Watchdog timer"
-       depends on WATCHDOG
-       ---help---
-         If you have a WDT500P or WDT501P watchdog board, say Y here,
-         otherwise N. It is not possible to probe for this board, which means
-         that you have to inform the kernel about the IO port and IRQ using
-         the "wdt=" kernel option (try "man bootparam" or see the
-         documentation of your boot loader (lilo or loadlin) about how to
-         pass options to the kernel at boot time).
-
-         If you want to compile this as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you want),
-         say M here and read <file:Documentation/modules.txt>.  The module
-         will be called wdt.o.
-
-config WDTPCI
-       tristate "WDT PCI Watchdog timer"
-       depends on WATCHDOG
-       ---help---
-         If you have a PCI WDT500/501 watchdog board, say Y here, otherwise
-         N.  It is not possible to probe for this board, which means that you
-         have to inform the kernel about the IO port and IRQ using the "wdt="
-         kernel option (try "man bootparam" or see the documentation of your
-         boot loader (lilo or loadlin) about how to pass options to the
-         kernel at boot time).
-
-         If you want to compile this as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you want),
-         say M here and read <file:Documentation/modules.txt>.  The module
-         will be called wdt_pci.o.
-
-config WDT_501
-       bool "WDT501 features"
-       depends on WDT
-       help
-         Saying Y here and creating a character special file /dev/temperature
-         with major number 10 and minor number 131 ("man mknod") will give
-         you a thermometer inside your computer: reading from
-         /dev/temperature yields one byte, the temperature in degrees
-         Fahrenheit. This works only if you have a WDT501P watchdog board
-         installed.
-
-config WDT_501_FAN
-       bool "Fan Tachometer"
-       depends on WDT_501
-       help
-         Enable the Fan Tachometer on the WDT501. Only do this if you have a
-         fan tachometer actually set up.
-
-config PCWATCHDOG
-       tristate "Berkshire Products PC Watchdog"
-       depends on WATCHDOG
-       ---help---
-         This is the driver for the Berkshire Products PC Watchdog card.
-         This card simply watches your kernel to make sure it doesn't freeze,
-         and if it does, it reboots your computer after a certain amount of
-         time. This driver is like the WDT501 driver but for different
-         hardware. Please read <file:Documentation/pcwd-watchdog.txt>. The PC
-         watchdog cards can be ordered from <http://www.berkprod.com/>.
-
-         This driver is also available as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you want).
-         The module is called pcwd.o. If you want to compile it as a module,
-         say M here and read <file:Documentation/modules.txt>.
-
-         Most people will say N.
-
-config ACQUIRE_WDT
-       tristate "Acquire SBC Watchdog Timer"
-       depends on WATCHDOG
-       ---help---
-         This is the driver for the hardware watchdog on the PSC-6x86 Single
-         Board Computer produced by Acquire Inc (and others).  This watchdog
-         simply watches your kernel to make sure it doesn't freeze, and if
-         it does, it reboots your computer after a certain amount of time.
-
-         This driver is like the WDT501 driver but for different hardware.
-         This driver is also available as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you want).
-         The module is called pscwdt.o.  If you want to compile it as a
-         module, say M here and read <file:Documentation/modules.txt>.  Most
-         people will say N.
-
-config ADVANTECH_WDT
-       tristate "Advantech SBC Watchdog Timer"
-       depends on WATCHDOG
-       help
-         If you are configuring a Linux kernel for the Advantech single-board
-         computer, say `Y' here to support its built-in watchdog timer
-         feature.  See the help for CONFIG_WATCHDOG for discussion.
-
-config 21285_WATCHDOG
-       tristate "DC21285 watchdog"
-       depends on WATCHDOG && FOOTBRIDGE
-       help
-         The Intel Footbridge chip contains a builtin watchdog circuit. Say Y
-         here if you wish to use this. Alternatively say M to compile the
-         driver as a module, which will be called wdt285.o.
-
-         This driver does not work on all machines. In particular, early CATS
-         boards have hardware problems that will cause the machine to simply
-         lock up if the watchdog fires.
-
-         "If in doubt, leave it out" - say N.
-
-config 977_WATCHDOG
-       tristate "NetWinder WB83C977 watchdog"
-       depends on WATCHDOG && FOOTBRIDGE && ARCH_NETWINDER
-       help
-         Say Y here to include support for the WB977 watchdog included in
-         NetWinder machines. Alternatively say M to compile the driver as
-         a module, which will be called wdt977.o.
-
-         Not sure? It's safe to say N.
-
-config EUROTECH_WDT
-       tristate "Eurotech CPU-1220/1410 Watchdog Timer"
-       depends on WATCHDOG
-       help
-         Enable support for the watchdog timer on the Eurotech CPU-1220 and
-         CPU-1410 cards.  These are PC/104 SBCs. Spec sheets and product
-         information are at <http://www.eurotech.it/>.
-
-config IB700_WDT
-       tristate "IB700 SBC Watchdog Timer"
-       depends on WATCHDOG
-       ---help---
-         This is the driver for the hardware watchdog on the IB700 Single
-         Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog
-         simply watches your kernel to make sure it doesn't freeze, and if
-         it does, it reboots your computer after a certain amount of time.
-
-         This driver is like the WDT501 driver but for slightly different hardware.
-
-         This driver is also available as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you want).
-         The module is called ib700wdt.o. If you want to compile it as a
-         module, say M here and read Documentation/modules.txt. Most people
-         will say N.
-
-config I810_TCO
-       tristate "Intel i810 TCO timer / Watchdog"
-       depends on WATCHDOG
-       ---help---
-         Hardware driver for the TCO timer built into the Intel i810 and i815
-         chipset family.  The TCO (Total Cost of Ownership) timer is a
-         watchdog timer that will reboot the machine after its second
-         expiration. The expiration time can be configured by commandline
-         argument "i810_margin=<n>" where <n> is the counter initial value.
-         It is decremented every 0.6 secs, the default is 50 which gives a
-         timeout of 30 seconds and one minute until reset.
-
-         On some motherboards the driver may fail to reset the chipset's
-         NO_REBOOT flag which prevents the watchdog from rebooting the
-         machine. If this is the case you will get a kernel message like
-         "i810tco init: failed to reset NO_REBOOT flag".
-
-         If you want to compile this as a module, say M and read
-         <file:Documentation/modules.txt>.  The module will be called
-         i810-tco.o.
-
-config MIXCOMWD
-       tristate "Mixcom Watchdog"
-       depends on WATCHDOG
-       ---help---
-         This is a driver for the Mixcom hardware watchdog cards.  This
-         watchdog simply watches your kernel to make sure it doesn't freeze,
-         and if it does, it reboots your computer after a certain amount of
-         time.
-
-         This driver is also available as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you want).
-         The module is called mixcomwd.o.  If you want to compile it as a
-         module, say M here and read <file:Documentation/modules.txt>.  Most
-         people will say N.
-
-config SCx200_WDT
-       tristate "NatSemi SCx200 Watchdog"
-       depends on WATCHDOG
-       help
-         Enable the built-in watchdog timer support on the National 
-         Semiconductor SCx200 processors.
-
-         If compiled as a module, it will be called scx200_watchdog.o.
-
-config 60XX_WDT
-       tristate "SBC-60XX Watchdog Timer"
-       depends on WATCHDOG
-       help
-         This driver can be used with the watchdog timer found on some
-         single board computers, namely the 6010 PII based computer.
-         It may well work with other cards.  It reads port 0x443 to enable
-         and re-set the watchdog timer, and reads port 0x45 to disable
-         the watchdog.  If you have a card that behave in similar ways,
-         you can probably make this driver work with your card as well.
-
-         You can compile this driver directly into the kernel, or use
-         it as a module.  The module will be called sbc60xxwdt.o.
-
-config W83877F_WDT
-       tristate "W83877F (EMACS) Watchdog Timer"
-       depends on WATCHDOG
-       ---help---
-         This is the driver for the hardware watchdog on the W83877F chipset
-         as used in EMACS PC-104 motherboards (and likely others).  This
-         watchdog simply watches your kernel to make sure it doesn't freeze,
-         and if it does, it reboots your computer after a certain amount of
-         time.
-
-         This driver is also available as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you want).
-         The module is called mixcomwd.o.  If you want to compile it as a
-         module, say M here and read <file:Documentation/modules.txt>.  Most
-         people will say N.
-
-config MACHZ_WDT
-       tristate "ZF MachZ Watchdog"
-       depends on WATCHDOG
-       ---help---
-         If you are using a ZF Micro MachZ processor, say Y here, otherwise
-         N.  This is the driver for the watchdog timer builtin on that
-         processor using ZF-Logic interface.  This watchdog simply watches
-         your kernel to make sure it doesn't freeze, and if it does, it
-         reboots your computer after a certain amount of time.
-
-         This driver is also available as a module ( = code which can be
-         inserted in and removed from the running kernel whenever you want).
-         The module is called machzwd.o.  If you want to compile it as a
-         module, say M here and read <file:Documentation/modules.txt>.
-
-endmenu
+source "drivers/char/watchdog/Kconfig"
 
 config DS1620
        tristate "NetWinder thermometer support"
index 2a148fecfc4a66e417bad5145f74a93bd2771ee5..f53358de91ff78b7243dd2594f461101d639036a 100644 (file)
@@ -77,32 +77,13 @@ obj-$(CONFIG_NWBUTTON) += nwbutton.o
 obj-$(CONFIG_NWFLASH) += nwflash.o
 obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
 
-# Only one watchdog can succeed. We probe the hardware watchdog
-# drivers first, then the softdog driver.  This means if your hardware
-# watchdog dies or is 'borrowed' for some reason the software watchdog
-# still gives you some cover.
-
-obj-$(CONFIG_PCWATCHDOG) += pcwd.o
-obj-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
-obj-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
-obj-$(CONFIG_IB700_WDT) += ib700wdt.o
-obj-$(CONFIG_MIXCOMWD) += mixcomwd.o
-obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o
-obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
-obj-$(CONFIG_WDT) += wdt.o
-obj-$(CONFIG_WDTPCI) += wdt_pci.o
-obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
-obj-$(CONFIG_977_WATCHDOG) += wdt977.o
-obj-$(CONFIG_I810_TCO) += i810-tco.o
-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_WATCHDOGS)        += watchdog/
 obj-$(CONFIG_MWAVE) += mwave/
 obj-$(CONFIG_AGP) += agp/
 obj-$(CONFIG_DRM) += drm/
 obj-$(CONFIG_PCMCIA) += pcmcia/
 
+
 # Files generated that shall be removed upon make clean
 clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c
 
diff --git a/drivers/char/acquirewdt.c b/drivers/char/acquirewdt.c
deleted file mode 100644 (file)
index 3a0ecbc..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- *     Acquire Single Board Computer Watchdog Timer driver for Linux 2.1.x
- *
- *      Based on wdt.c. Original copyright messages:
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     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.       
- *
- *     (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>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-
-static int acq_is_open;
-static spinlock_t acq_lock;
-
-/*
- *     You must set these - there is no sane way to probe for this board.
- */
-#define WDT_STOP 0x43
-#define WDT_START 0x443
-
-#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 void acq_ping(void)
-{
-       /* Write a watchdog value */
-       inb_p(WDT_START);
-}
-
-static ssize_t acq_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)
-       {
-               acq_ping();
-               return 1;
-       }
-       return 0;
-}
-
-static ssize_t acq_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-{
-       return -EINVAL;
-}
-
-
-
-static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       static struct watchdog_info ident=
-       {
-               WDIOF_KEEPALIVEPING, 1, "Acquire WDT"
-       };
-       
-       switch(cmd)
-       {
-       case WDIOC_GETSUPPORT:
-         if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
-           return -EFAULT;
-         break;
-         
-       case WDIOC_GETSTATUS:
-         if (copy_to_user((int *)arg, &acq_is_open,  sizeof(int)))
-           return -EFAULT;
-         break;
-
-       case WDIOC_KEEPALIVE:
-         acq_ping();
-         break;
-
-       default:
-         return -ENOTTY;
-       }
-       return 0;
-}
-
-static int acq_open(struct inode *inode, struct file *file)
-{
-       switch(minor(inode->i_rdev))
-       {
-               case WATCHDOG_MINOR:
-                       spin_lock(&acq_lock);
-                       if(acq_is_open)
-                       {
-                               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);
-                       return 0;
-               default:
-                       return -ENODEV;
-       }
-}
-
-static int acq_close(struct inode *inode, struct file *file)
-{
-       if(minor(inode->i_rdev)==WATCHDOG_MINOR)
-       {
-               spin_lock(&acq_lock);
-               if (!nowayout) {
-                       inb_p(WDT_STOP);
-               }
-               acq_is_open=0;
-               spin_unlock(&acq_lock);
-       }
-       return 0;
-}
-
-/*
- *     Notifier for system down
- */
-
-static int acq_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT)
-       {
-               /* Turn the card off */
-               inb_p(WDT_STOP);
-       }
-       return NOTIFY_DONE;
-}
-/*
- *     Kernel Interfaces
- */
-static struct file_operations acq_fops = {
-       .owner          = THIS_MODULE,
-       .read           = acq_read,
-       .write          = acq_write,
-       .ioctl          = acq_ioctl,
-       .open           = acq_open,
-       .release        = acq_close,
-};
-
-static struct miscdevice acq_miscdev=
-{
-       WATCHDOG_MINOR,
-       "watchdog",
-       &acq_fops
-};
-
-
-/*
- *     The WDT card needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off. 
- */
-static struct notifier_block acq_notifier=
-{
-       acq_notify_sys,
-       NULL,
-       0
-};
-
-static int __init acq_init(void)
-{
-       printk("WDT driver for Acquire single board computer initialising.\n");
-
-       spin_lock_init(&acq_lock);
-       if (misc_register(&acq_miscdev))
-               return -ENODEV;
-       if (!request_region(WDT_STOP, 1, "Acquire WDT"))
-               {
-               misc_deregister(&acq_miscdev);
-               return -EIO;
-               }
-       if (!request_region(WDT_START, 1, "Acquire WDT"))
-               {
-               release_region(WDT_STOP, 1);
-               misc_deregister(&acq_miscdev);
-               return -EIO;
-               }
-
-       register_reboot_notifier(&acq_notifier);
-       return 0;
-}
-       
-static void __exit acq_exit(void)
-{
-       misc_deregister(&acq_miscdev);
-       unregister_reboot_notifier(&acq_notifier);
-       release_region(WDT_STOP,1);
-       release_region(WDT_START,1);
-}
-
-module_init(acq_init);
-module_exit(acq_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/advantechwdt.c b/drivers/char/advantechwdt.c
deleted file mode 100644 (file)
index 226e3a7..0000000
+++ /dev/null
@@ -1,280 +0,0 @@
-/*
- *     Advantech Single Board Computer WDT driver for Linux 2.4.x
- *
- *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
- *
- *     Based on acquirewdt.c which is based on wdt.c.
- *     Original copyright messages:
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     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.       
- *
- *     (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>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-
-static int advwdt_is_open;
-static spinlock_t advwdt_lock;
-
-/*
- *     You must set these - there is no sane way to probe for this board.
- *
- *     To enable or restart, write the timeout value in seconds (1 to 63)
- *     to I/O port WDT_START.  To disable, read I/O port WDT_STOP.
- *     Both are 0x443 for most boards (tested on a PCA-6276VE-00B1), but
- *     check your manual (at least the PCA-6159 seems to be different -
- *     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
- */
-#define WDT_STOP 0x443
-#define WDT_START 0x443
-
-#define WD_TIMO 60             /* 1 minute */
-
-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 void
-advwdt_ping(void)
-{
-       /* Write a watchdog value */
-       outb_p(timeout, WDT_START);
-}
-
-static ssize_t
-advwdt_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) {
-               advwdt_ping();
-               return 1;
-       }
-       return 0;
-}
-
-static ssize_t
-advwdt_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-{
-       return -EINVAL;
-}
-
-static int
-advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-         unsigned long arg)
-{
-       static struct watchdog_info ident = {
-               WDIOF_KEEPALIVEPING, 1, "Advantech WDT"
-       };
-       
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-         if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
-           return -EFAULT;
-         break;
-         
-       case WDIOC_GETSTATUS:
-         if (copy_to_user((int *)arg, &advwdt_is_open,  sizeof(int)))
-           return -EFAULT;
-         break;
-
-       case WDIOC_KEEPALIVE:
-         advwdt_ping();
-         break;
-
-       default:
-         return -ENOTTY;
-       }
-       return 0;
-}
-
-static int
-advwdt_open(struct inode *inode, struct file *file)
-{
-       switch (minor(inode->i_rdev)) {
-               case WATCHDOG_MINOR:
-                       spin_lock(&advwdt_lock);
-                       if (advwdt_is_open) {
-                               spin_unlock(&advwdt_lock);
-                               return -EBUSY;
-                       }
-                       if (nowayout) {
-                               MOD_INC_USE_COUNT;
-                       }
-                       /*
-                        *      Activate 
-                        */
-        
-                       advwdt_is_open = 1;
-                       advwdt_ping();
-                       spin_unlock(&advwdt_lock);
-                       return 0;
-               default:
-                       return -ENODEV;
-       }
-}
-
-static int
-advwdt_close(struct inode *inode, struct file *file)
-{
-       if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
-               spin_lock(&advwdt_lock);
-               if (!nowayout) {
-                       inb_p(WDT_STOP);
-               }
-               advwdt_is_open = 0;
-               spin_unlock(&advwdt_lock);
-       }
-       return 0;
-}
-
-/*
- *     Notifier for system down
- */
-
-static int
-advwdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT) {
-               /* Turn the WDT off */
-               inb_p(WDT_STOP);
-       }
-       return NOTIFY_DONE;
-}
-/*
- *     Kernel Interfaces
- */
-static struct file_operations advwdt_fops = {
-       .owner          = THIS_MODULE,
-       .read           = advwdt_read,
-       .write          = advwdt_write,
-       .ioctl          = advwdt_ioctl,
-       .open           = advwdt_open,
-       .release        = advwdt_close,
-};
-
-static struct miscdevice advwdt_miscdev = {
-       WATCHDOG_MINOR,
-       "watchdog",
-       &advwdt_fops
-};
-
-/*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off. 
- */
-static struct notifier_block advwdt_notifier = {
-       advwdt_notify_sys,
-       NULL,
-       0
-};
-
-static void __init
-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);
-       }
-}
-
-static int __init
-advwdt_init(void)
-{
-       printk("WDT driver for Advantech single board computer initialising.\n");
-
-       advwdt_validate_timeout();
-       spin_lock_init(&advwdt_lock);
-       if (misc_register(&advwdt_miscdev))
-               return -ENODEV;
-#if WDT_START != WDT_STOP
-       if (!request_region(WDT_STOP, 1, "Advantech WDT")) {
-               misc_deregister(&advwdt_miscdev);
-               return -EIO;
-       }
-#endif
-       if (!request_region(WDT_START, 1, "Advantech WDT")) {
-               misc_deregister(&advwdt_miscdev);
-#if WDT_START != WDT_STOP
-               release_region(WDT_STOP, 1);
-#endif
-               return -EIO;
-       }
-       register_reboot_notifier(&advwdt_notifier);
-       return 0;
-}
-
-static void __exit
-advwdt_exit(void)
-{
-       misc_deregister(&advwdt_miscdev);
-       unregister_reboot_notifier(&advwdt_notifier);
-#if WDT_START != WDT_STOP
-       release_region(WDT_STOP,1);
-#endif
-       release_region(WDT_START,1);
-}
-
-module_init(advwdt_init);
-module_exit(advwdt_exit);
-
-MODULE_LICENSE("GPL");
-
-/* end of advantechwdt.c */
-
diff --git a/drivers/char/eurotechwdt.c b/drivers/char/eurotechwdt.c
deleted file mode 100644 (file)
index 6ce0e3c..0000000
+++ /dev/null
@@ -1,501 +0,0 @@
-/*
- *     Eurotech CPU-1220/1410 on board WDT driver for Linux 2.4.x
- *
- *     (c) Copyright 2001 Ascensit <support@ascensit.com>
- *     (c) Copyright 2001 Rodolfo Giometti <giometti@ascensit.com>
- *
- *     Based on wdt.c.
- *     Original copyright messages:
- *
- *      (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                              http://www.redhat.com
- *
- *      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.
- *
- *      (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>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-static int eurwdt_is_open;
-static spinlock_t eurwdt_lock;
-/*
- *      You must set these - there is no sane way to probe for this board.
- *      You can use wdt=x,y to set these now.
- */
-static int io = 0x3f0;
-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)");
-
-
-/*
- * Some symbolic names 
- */
-
-#define WDT_CTRL_REG           0x30
-#define WDT_OUTPIN_CFG         0xe2
-   #define WDT_EVENT_INT          0x00
-   #define WDT_EVENT_REBOOT       0x08
-#define WDT_UNIT_SEL           0xf1
-   #define WDT_UNIT_SECS          0x80
-#define WDT_TIMEOUT_VAL                0xf2
-#define WDT_TIMER_CFG          0xf3
-
-#ifndef MODULE
-
-/**
- *      eurwdt_setup:
- *      @str: command line string
- *
- *      Setup options. The board isn't really probe-able so we have to
- *      get the user to tell us the configuration. Sane people build it
- *      modular but the others come here.
- */
-static int __init eurwdt_setup(char *str)
-{
-   int ints[4];
-   str = get_options (str, ARRAY_SIZE(ints), ints);
-   if (ints[0] > 0) {
-      io = ints[1];
-      if (ints[0] > 1)
-         irq = ints[2];
-   }
-   return 1;
-}
-__setup("wdt=", eurwdt_setup);
-
-#endif /* !MODULE */
-MODULE_PARM(io, "i");
-MODULE_PARM_DESC(io, "Eurotech WDT io port (default=0x3f0)");
-MODULE_PARM(irq, "i");
-MODULE_PARM_DESC(irq, "Eurotech WDT irq (default=10)");
-MODULE_PARM(ev, "s");
-MODULE_PARM_DESC(ev, "Eurotech WDT event type (default is `reboot')");
-
-
-/*
- *      Programming support
- */
-
-static void __init 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);
-       }
-}
-
-static inline void eurwdt_write_reg(u8 index, u8 data)
-{
-   outb(index, io);
-   outb(data, io+1);
-}
-
-static inline void eurwdt_lock_chip(void)
-{
-   outb(0xaa, io);
-}
-
-static inline void eurwdt_unlock_chip(void)
-{
-   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);
-}
-
-static inline void eurwdt_disable_timer(void)
-{
-   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) ?
-                                    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);
-
-   eurwdt_write_reg(WDT_UNIT_SEL, WDT_UNIT_SECS);   /* we use seconds */
-   eurwdt_set_timeout(0);                           /* the default timeout */ 
-}
-
-
-/*
- *      Kernel methods.
- */
-void eurwdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-   printk(KERN_CRIT "timeout WDT timeout\n");
-#ifdef ONLY_TESTING
-   printk(KERN_CRIT "Would Reboot.\n");
-#else
-   printk(KERN_CRIT "Initiating system reboot.\n");
-   machine_restart(NULL);
-#endif
-}
-
-
-/**
- *      eurwdt_ping:
- *
- *      Reload counter one with the watchdog timeout.
- */
-static void eurwdt_ping(void)
-{
-   /* Write the watchdog default value */
-   eurwdt_set_timeout(timeout);
-}
-/**
- *      eurwdt_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 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) {
-      eurwdt_ping();   /* the default timeout */
-      return 1;
-   }
-
-   return 0;
-}
-
-/**
- *      eurwdt_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 eurwdt_ioctl(struct inode *inode, struct file *file,
-        unsigned int cmd, unsigned long arg)
-{
-   static struct watchdog_info ident = {
-       .options          = WDIOF_CARDRESET,
-       .firmware_version = 1,
-       .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_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;
-
-         timeout = time; 
-         eurwdt_set_timeout(time); 
-         return 0;
-   }
-}
-
-/**
- *      eurwdt_open:
- *      @inode: inode of device
- *      @file: file handle to device
- *
- *      The misc device has been opened. The watchdog device is single
- *      open and on opening we load the counter.
- */
-static int eurwdt_open(struct inode *inode, struct file *file)
-{
-   switch (minor(inode->i_rdev)) {
-      case WATCHDOG_MINOR:
-         spin_lock(&eurwdt_lock);
-         if (eurwdt_is_open) {
-            spin_unlock(&eurwdt_lock);
-            return -EBUSY;
-         }
-        if (nowayout) {
-                MOD_INC_USE_COUNT;
-        }
-
-         eurwdt_is_open = 1;
-
-         /* Activate the WDT */
-         eurwdt_activate_timer(); 
-            
-         spin_unlock(&eurwdt_lock);
-
-         MOD_INC_USE_COUNT;
-
-         return 0;
-
-         case TEMP_MINOR:
-            return 0;
-
-         default:
-            return -ENODEV;
-   }
-}
-/**
- *      eurwdt_release:
- *      @inode: inode to board
- *      @file: file handle to board
- *
- *      The watchdog has a configurable API. There is a religious dispute
- *      between people who want their watchdog to be able to shut down and
- *      those who want to be sure if the watchdog manager dies the machine
- *      reboots. In the former case we disable the counters, in the latter
- *      case you have to open it again very soon.
- */
-static int eurwdt_release(struct inode *inode, struct file *file)
-{
-   if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
-          if (!nowayout) {
-                  eurwdt_disable_timer();
-          }
-          eurwdt_is_open = 0;
-
-          MOD_DEC_USE_COUNT;
-   }
-
-   return 0;
-}
-/**
- *      eurwdt_notify_sys:
- *      @this: our notifier block
- *      @code: the event being reported
- *      @unused: unused
- *
- *      Our notifier is called on system shutdowns. We want to turn the card
- *      off at reboot otherwise the machine will reboot again during memory
- *      test or worse yet during the following fsck. This would suck, in fact
- *      trust me - if it happens it does suck.
- */
-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;
-}
-/*
- *      Kernel Interfaces
- */
-static struct file_operations eurwdt_fops = {
-        .owner          = THIS_MODULE,
-        .llseek         = no_llseek,
-        .write          = eurwdt_write,
-        .ioctl          = eurwdt_ioctl,
-        .open           = eurwdt_open,
-        .release        = eurwdt_release,
-};
-
-static struct miscdevice eurwdt_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &eurwdt_fops
-};
-/*
- *      The WDT card needs to learn about soft shutdowns in order to
- *      turn the timebomb registers off.
- */
-static struct notifier_block eurwdt_notifier = {
-       .notifier_call = eurwdt_notify_sys,
-};
-/**
- *      cleanup_module:
- *
- *      Unload the watchdog. You cannot do this with any file handles open.
- *      If your watchdog is set to continue ticking on close and you unload
- *      it, well it keeps ticking. We won't get the interrupt but the board
- *      will not touch PC memory so all is fine. You just have to load a new
- *      module in 60 seconds or reboot.
- */
-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_init:
- *
- *      Set up the WDT watchdog board. After grabbing the resources 
- *      we require we need also to unlock the device.
- *      The open() function will actually kick the board off.
- */
-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",
-            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"));
-
-   spin_lock_init(&eurwdt_lock);
-
-   out:
-      return ret;
-   outreg:
-      release_region(io, 2);
-
-   outirq:
-      free_irq(irq, NULL);
-
-   outmisc:
-      misc_deregister(&eurwdt_miscdev);
-      goto out;
-}
-module_init(eurwdt_init);
-module_exit(eurwdt_exit);
-MODULE_AUTHOR("Rodolfo Giometti");
-MODULE_DESCRIPTION("Driver for Eurotech CPU-1220/1410 on board watchdog");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/i810-tco.c b/drivers/char/i810-tco.c
deleted file mode 100644 (file)
index 3697dd0..0000000
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- *     i810-tco 0.05:  TCO timer driver for i8xx chipsets
- *
- *     (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
- *                             http://www.kernelconcepts.de
- *
- *     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 kernel concepts nor Nils Faerber admit liability nor provide
- *     warranty for any of this software. This material is provided
- *     "AS-IS" and at no charge.
- *
- *     (c) Copyright 2000      kernel concepts <nils@kernelconcepts.de>
- *                             developed for
- *                              Jentro AG, Haar/Munich (Germany)
- *
- *     TCO timer driver for i8xx chipsets
- *     based on softdog.c by Alan Cox <alan@redhat.com>
- *
- *     The TCO timer is implemented in the following I/O controller hubs:
- *     (See the intel documentation on http://developer.intel.com.)
- *     82801AA & 82801AB  chip : document number 290655-003, 290677-004,
- *     82801BA & 82801BAM chip : document number 290687-002, 298242-005,
- *     82801CA & 82801CAM chip : document number 290716-001, 290718-001,
- *     82801DB & 82801E   chip : document number 290744-001, 273599-001
- *
- *  20000710 Nils Faerber
- *     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.
- *  20020224 Joel Becker, Wim Van Sebroeck
- *     0.04 Support for 82801CA(M) chipset, timer margin needs to be > 3,
- *          add support for WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT.
- *  20020412 Rob Radez <rob@osinvestor.com>, Wim Van Sebroeck
- *     0.05 Fix possible timer_alive race, add expect close support,
- *          clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and
- *          WDIOC_SETOPTIONS), made i810tco_getdevice __init,
- *          removed boot_status, removed tco_timer_read,
- *          added support for 82801DB and 82801E chipset, general cleanup.
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include "i810-tco.h"
-
-
-/* Module and version information */
-#define TCO_VERSION "0.05"
-#define TCO_MODULE_NAME "i810 TCO timer"
-#define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
-
-/* Default expire timeout */
-#define TIMER_MARGIN   50      /* steps of 0.6sec, 3<n<64. Default is 30 seconds */
-
-static unsigned int ACPIBASE;
-static spinlock_t tco_lock;    /* Guards the hardware */
-
-static int i810_margin = TIMER_MARGIN; /* steps of 0.6sec */
-
-MODULE_PARM(i810_margin, "i");
-MODULE_PARM_DESC(i810_margin, "i810-tco timeout in steps of 0.6sec, 3<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
- */
-
-static unsigned long timer_alive;
-static char tco_expect_close;
-
-/*
- * Some TCO specific functions
- */
-
-
-/*
- * Start the timer countdown
- */
-static int tco_timer_start (void)
-{
-       unsigned char val;
-
-       spin_lock(&tco_lock);
-       val = inb (TCO1_CNT + 1);
-       val &= 0xf7;
-       outb (val, TCO1_CNT + 1);
-       val = inb (TCO1_CNT + 1);
-       spin_unlock(&tco_lock);
-       
-       if (val & 0x08)
-               return -1;
-       return 0;
-}
-
-/*
- * Stop the timer countdown
- */
-static int tco_timer_stop (void)
-{
-       unsigned char val;
-
-       spin_lock(&tco_lock);
-       val = inb (TCO1_CNT + 1);
-       val |= 0x08;
-       outb (val, TCO1_CNT + 1);
-       val = inb (TCO1_CNT + 1);
-       spin_unlock(&tco_lock);
-       
-       if ((val & 0x08) == 0)
-               return -1;
-       return 0;
-}
-
-/*
- * Set the timer reload value
- */
-static int tco_timer_settimer (unsigned char tmrval)
-{
-       unsigned char val;
-
-       /* from the specs: */
-       /* "Values of 0h-3h are ignored and should not be attempted" */
-       if (tmrval > 0x3f || tmrval < 0x04)
-               return -1;
-       
-       spin_lock(&tco_lock);
-       val = inb (TCO1_TMR);
-       val &= 0xc0;
-       val |= tmrval;
-       outb (val, TCO1_TMR);
-       val = inb (TCO1_TMR);
-       spin_unlock(&tco_lock);
-       
-       if ((val & 0x3f) != tmrval)
-               return -1;
-
-       return 0;
-}
-
-/*
- * Reload (trigger) the timer. Lock is needed so we dont reload it during
- * a reprogramming event
- */
-static void tco_timer_reload (void)
-{
-       spin_lock(&tco_lock);
-       outb (0x01, TCO1_RLD);
-       spin_unlock(&tco_lock);
-}
-
-/*
- *     Allow only one person to hold it open
- */
-
-static int i810tco_open (struct inode *inode, struct file *file)
-{
-       if (test_and_set_bit(0, &timer_alive))
-               return -EBUSY;
-
-       /*
-        *      Reload and activate timer
-        */
-       tco_timer_reload ();
-       tco_timer_start ();
-       return 0;
-}
-
-static int i810tco_release (struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer.
-        */
-       if (tco_expect_close == 42 && !nowayout) {
-               tco_timer_stop ();
-       } else {
-               tco_timer_reload ();
-               printk(KERN_CRIT TCO_MODULE_NAME ": Unexpected close, not stopping watchdog!\n");
-       }
-       clear_bit(0, &timer_alive);
-       tco_expect_close = 0;
-       return 0;
-}
-
-static ssize_t i810tco_write (struct file *file, const char *data,
-                             size_t len, loff_t * ppos)
-{
-       /*  Can't seek (pwrite) on this device  */
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-
-       /* See if we got the magic character 'V' and reload the timer */
-       if (len) {
-               size_t i;
-
-               tco_expect_close = 0;
-
-               /* scan to see wether or not we got the magic character */
-               for (i = 0; i != len; i++) {
-                       u8 c;
-                       if(get_user(c, data+i))
-                               return -EFAULT;
-                       if (c == 'V')
-                               tco_expect_close = 42;
-               }
-
-               /* someone wrote to us, we should reload the timer */
-               tco_timer_reload ();
-               return 1;
-       }
-       return 0;
-}
-
-static int i810tco_ioctl (struct inode *inode, struct file *file,
-                         unsigned int cmd, unsigned long arg)
-{
-       int new_margin, u_margin;
-       int options, retval = -EINVAL;
-
-       static struct watchdog_info ident = {
-               .options =              WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
-               .firmware_version =     0,
-               .identity =             "i810 TCO timer",
-       };
-       switch (cmd) {
-               default:
-                       return -ENOTTY;
-               case WDIOC_GETSUPPORT:
-                       if (copy_to_user
-                           ((struct watchdog_info *) arg, &ident, sizeof (ident)))
-                               return -EFAULT;
-                       return 0;
-               case WDIOC_GETSTATUS:
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user (0, (int *) arg);
-               case WDIOC_SETOPTIONS:
-                       if (get_user (options, (int *) arg))
-                               return -EFAULT;
-                       if (options & WDIOS_DISABLECARD) {
-                               tco_timer_stop ();
-                               retval = 0;
-                       }
-                       if (options & WDIOS_ENABLECARD) {
-                               tco_timer_reload ();
-                               tco_timer_start ();
-                               retval = 0;
-                       }
-                       return retval;
-               case WDIOC_KEEPALIVE:
-                       tco_timer_reload ();
-                       return 0;
-               case WDIOC_SETTIMEOUT:
-                       if (get_user (u_margin, (int *) arg))
-                               return -EFAULT;
-                       new_margin = (u_margin * 10 + 5) / 6;
-                       if ((new_margin < 4) || (new_margin > 63))
-                               return -EINVAL;
-                       if (tco_timer_settimer ((unsigned char) new_margin))
-                           return -EINVAL;
-                       i810_margin = new_margin;
-                       tco_timer_reload ();
-                       /* Fall */
-               case WDIOC_GETTIMEOUT:
-                       return put_user ((int)(i810_margin * 6 / 10), (int *) arg);
-       }
-}
-
-/*
- * Data for PCI driver interface
- *
- * This data only exists for exporting the supported
- * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
- * register a pci_driver, because someone else might one day
- * want to register another driver on the same PCI id.
- */
-static struct pci_device_id i810tco_pci_tbl[] __initdata = {
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0,   PCI_ANY_ID, PCI_ANY_ID, },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0,   PCI_ANY_ID, PCI_ANY_ID, },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,   PCI_ANY_ID, PCI_ANY_ID, },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10,  PCI_ANY_ID, PCI_ANY_ID, },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,   PCI_ANY_ID, PCI_ANY_ID, },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,  PCI_ANY_ID, PCI_ANY_ID, },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,   PCI_ANY_ID, PCI_ANY_ID, },
-       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0,    PCI_ANY_ID, PCI_ANY_ID, },
-       { 0, },
-};
-MODULE_DEVICE_TABLE (pci, i810tco_pci_tbl);
-
-static struct pci_dev *i810tco_pci;
-
-static unsigned char __init i810tco_getdevice (void)
-{
-       struct pci_dev *dev;
-       u8 val1, val2;
-       u16 badr;
-       /*
-        *      Find the PCI device
-        */
-
-       pci_for_each_dev(dev) {
-               if (pci_match_device(i810tco_pci_tbl, dev)) {
-                       i810tco_pci = dev;
-                       break;
-               }
-       }
-
-       if (i810tco_pci) {
-               /*
-                *      Find the ACPI base I/O address which is the base
-                *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
-                *      ACPIBASE is bits [15:7] from 0x40-0x43
-                */
-               pci_read_config_byte (i810tco_pci, 0x40, &val1);
-               pci_read_config_byte (i810tco_pci, 0x41, &val2);
-               badr = ((val2 << 1) | (val1 >> 7)) << 7;
-               ACPIBASE = badr;
-               /* Something's wrong here, ACPIBASE has to be set */
-               if (badr == 0x0001 || badr == 0x0000) {
-                       printk (KERN_ERR TCO_MODULE_NAME " init: failed to get TCOBASE address\n");
-                       return 0;
-               }
-               /*
-                * Check chipset's NO_REBOOT bit
-                */
-               pci_read_config_byte (i810tco_pci, 0xd4, &val1);
-               if (val1 & 0x02) {
-                       val1 &= 0xfd;
-                       pci_write_config_byte (i810tco_pci, 0xd4, val1);
-                       pci_read_config_byte (i810tco_pci, 0xd4, &val1);
-                       if (val1 & 0x02) {
-                               printk (KERN_ERR TCO_MODULE_NAME " init: failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
-                               return 0;       /* Cannot reset NO_REBOOT bit */
-                       }
-               }
-               /* Set the TCO_EN bit in SMI_EN register */
-               val1 = inb (SMI_EN + 1);
-               val1 &= 0xdf;
-               outb (val1, SMI_EN + 1);
-               /* Clear out the (probably old) status */
-               outb (0, TCO1_STS);
-               outb (3, TCO2_STS);
-               return 1;
-       }
-       return 0;
-}
-
-static struct file_operations i810tco_fops = {
-       .owner =        THIS_MODULE,
-       .write =        i810tco_write,
-       .ioctl =        i810tco_ioctl,
-       .open =         i810tco_open,
-       .release =      i810tco_release,
-};
-
-static struct miscdevice i810tco_miscdev = {
-       .minor =        WATCHDOG_MINOR,
-       .name =         "watchdog",
-       .fops =         &i810tco_fops,
-};
-
-static int __init watchdog_init (void)
-{
-       spin_lock_init(&tco_lock);
-       if (!i810tco_getdevice () || i810tco_pci == NULL)
-               return -ENODEV;
-       if (!request_region (TCOBASE, 0x10, "i810 TCO")) {
-               printk (KERN_ERR TCO_MODULE_NAME
-                       ": I/O address 0x%04x already in use\n",
-                       TCOBASE);
-               return -EIO;
-       }
-       if (misc_register (&i810tco_miscdev) != 0) {
-               release_region (TCOBASE, 0x10);
-               printk (KERN_ERR TCO_MODULE_NAME ": cannot register miscdev\n");
-               return -EIO;
-       }
-       tco_timer_settimer ((unsigned char) i810_margin);
-       tco_timer_reload ();
-
-       printk (KERN_INFO TCO_DRIVER_NAME
-               ": timer margin: %d sec (0x%04x) (nowayout=%d)\n",
-               (int) (i810_margin * 6 / 10), TCOBASE, nowayout);
-       return 0;
-}
-
-static void __exit watchdog_cleanup (void)
-{
-       u8 val;
-
-       /* Reset the timer before we leave */
-       tco_timer_reload ();
-       /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
-       pci_read_config_byte (i810tco_pci, 0xd4, &val);
-       val |= 0x02;
-       pci_write_config_byte (i810tco_pci, 0xd4, val);
-       release_region (TCOBASE, 0x10);
-       misc_deregister (&i810tco_miscdev);
-}
-
-module_init(watchdog_init);
-module_exit(watchdog_cleanup);
-
-MODULE_AUTHOR("Nils Faerber");
-MODULE_DESCRIPTION("TCO timer driver for i8xx chipsets");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/ib700wdt.c b/drivers/char/ib700wdt.c
deleted file mode 100644 (file)
index 448c7be..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- *     IB700 Single Board Computer WDT driver for Linux 2.4.x
- *
- *     (c) Copyright 2001 Charles Howes <chowes@vsol.net>
- *
- *      Based on advantechwdt.c which is based on acquirewdt.c which
- *       is based on wdt.c.
- *
- *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
- *
- *     Based on acquirewdt.c which is based on wdt.c.
- *     Original copyright messages:
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     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.
- *
- *     (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>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-
-static int ibwdt_is_open;
-static spinlock_t ibwdt_lock;
-
-/*
- *
- * Watchdog Timer Configuration
- *
- * The function of the watchdog timer is to reset the system
- * automatically and is defined at I/O port 0443H.  To enable the
- * watchdog timer and allow the system to reset, write I/O port 0443H.
- * To disable the timer, write I/O port 0441H for the system to stop the
- * watchdog function.  The timer has a tolerance of 20% for its
- * intervals.
- *
- * The following describes how the timer should be programmed.
- *
- * Enabling Watchdog:
- * MOV AX,000FH (Choose the values from 0 to F)
- * MOV DX,0443H
- * OUT DX,AX
- *
- * Disabling Watchdog:
- * MOV AX,000FH (Any value is fine.)
- * MOV DX,0441H
- * OUT DX,AX
- *
- * Watchdog timer control table:
- * Level   Value  Time/sec | Level Value Time/sec
- *   1       F       0     |   9     7      16
- *   2       E       2     |   10    6      18
- *   3       D       4     |   11    5      20
- *   4       C       6     |   12    4      22
- *   5       B       8     |   13    3      24
- *   6       A       10    |   14    2      26
- *   7       9       12    |   15    1      28
- *   8       8       14    |   16    0      30
- *
- */
-
-#define WDT_STOP 0x441
-#define WDT_START 0x443
-
-#define WD_TIMO 0              /* 30 seconds +/- 20%, from table */
-
-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 void __init
-ibwdt_validate_timeout(void)
-{
-       timeout_val = (30 - timeout) / 2;
-       if (timeout_val < 0 || timeout_val > 0xF) timeout_val = WD_TIMO;
-}
-
-static void
-ibwdt_ping(void)
-{
-       /* Write a watchdog value */
-       outb_p(timeout_val, WDT_START);
-}
-
-static ssize_t
-ibwdt_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) {
-               ibwdt_ping();
-               return 1;
-       }
-       return 0;
-}
-
-static ssize_t
-ibwdt_read(struct file *file, char *buf, size_t count, loff_t *ppos)
-{
-       return -EINVAL;
-}
-
-static int
-ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-         unsigned long arg)
-{
-       static struct watchdog_info ident = {
-               WDIOF_KEEPALIVEPING, 1, "IB700 WDT"
-       };
-
-       switch (cmd) {
-       case WDIOC_GETSUPPORT:
-         if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
-           return -EFAULT;
-         break;
-
-       case WDIOC_GETSTATUS:
-         if (copy_to_user((int *)arg, &ibwdt_is_open,  sizeof(int)))
-           return -EFAULT;
-         break;
-
-       case WDIOC_KEEPALIVE:
-         ibwdt_ping();
-         break;
-
-       default:
-         return -ENOTTY;
-       }
-       return 0;
-}
-
-static int
-ibwdt_open(struct inode *inode, struct file *file)
-{
-       switch (minor(inode->i_rdev)) {
-               case WATCHDOG_MINOR:
-                       spin_lock(&ibwdt_lock);
-                       if (ibwdt_is_open) {
-                               spin_unlock(&ibwdt_lock);
-                               return -EBUSY;
-                       }
-                       if (nowayout) {
-                               MOD_INC_USE_COUNT;
-                       }
-                       /*
-                        *      Activate
-                        */
-
-                       ibwdt_is_open = 1;
-                       ibwdt_ping();
-                       spin_unlock(&ibwdt_lock);
-                       return 0;
-               default:
-                       return -ENODEV;
-       }
-}
-
-static int
-ibwdt_close(struct inode *inode, struct file *file)
-{
-       lock_kernel();
-       if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
-               spin_lock(&ibwdt_lock);
-               if (!nowayout) {
-                       outb_p(timeout_val, WDT_STOP);
-               }
-               ibwdt_is_open = 0;
-               spin_unlock(&ibwdt_lock);
-       }
-       unlock_kernel();
-       return 0;
-}
-
-/*
- *     Notifier for system down
- */
-
-static int
-ibwdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT) {
-               /* Turn the WDT off */
-               outb_p(timeout_val, WDT_STOP);
-       }
-       return NOTIFY_DONE;
-}
-
-/*
- *     Kernel Interfaces
- */
-
-static struct file_operations ibwdt_fops = {
-       .owner          = THIS_MODULE,
-       .read           = ibwdt_read,
-       .write          = ibwdt_write,
-       .ioctl          = ibwdt_ioctl,
-       .open           = ibwdt_open,
-       .release        = ibwdt_close,
-};
-
-static struct miscdevice ibwdt_miscdev = {
-       WATCHDOG_MINOR,
-       "watchdog",
-       &ibwdt_fops
-};
-
-/*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off.
- */
-
-static struct notifier_block ibwdt_notifier = {
-       ibwdt_notify_sys,
-       NULL,
-       0
-};
-
-static int __init
-ibwdt_init(void)
-{
-       printk("WDT driver for IB700 single board computer initialising.\n");
-
-       ibwdt_validate_timeout();
-       spin_lock_init(&ibwdt_lock);
-       if (misc_register(&ibwdt_miscdev))
-               return -ENODEV;
-#if WDT_START != WDT_STOP
-       if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
-               misc_deregister(&ibwdt_miscdev);
-               return -EIO;
-       }
-#endif
-       if (!request_region(WDT_START, 1, "IB700 WDT")) {
-#if WDT_START != WDT_STOP
-               release_region(WDT_STOP, 1);
-#endif
-               misc_deregister(&ibwdt_miscdev);
-               return -EIO;
-       }
-       register_reboot_notifier(&ibwdt_notifier);
-       return 0;
-}
-
-static void __exit
-ibwdt_exit(void)
-{
-       misc_deregister(&ibwdt_miscdev);
-       unregister_reboot_notifier(&ibwdt_notifier);
-#if WDT_START != WDT_STOP
-       release_region(WDT_STOP,1);
-#endif
-       release_region(WDT_START,1);
-}
-
-module_init(ibwdt_init);
-module_exit(ibwdt_exit);
-
-MODULE_AUTHOR("Charles Howes <chowes@vsol.net>");
-MODULE_DESCRIPTION("IB700 SBC watchdog driver");
-MODULE_LICENSE("GPL");
-
-/* end of ib700wdt.c */
diff --git a/drivers/char/machzwd.c b/drivers/char/machzwd.c
deleted file mode 100644 (file)
index ab3f538..0000000
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- *  MachZ ZF-Logic Watchdog Timer driver for Linux
- *  
- * 
- *  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.
- *
- *  The author does NOT admit liability nor provide warranty for
- *  any of this software. This material is provided "AS-IS" in
- *  the hope that it may be useful for others.
- *
- *  Author: Fernando Fuganti <fuganti@conectiva.com.br>
- *
- *  Based on sbc60xxwdt.c by Jakob Oestergaard
- * 
- *
- *  We have two timers (wd#1, wd#2) driven by a 32 KHz clock with the 
- *  following periods:
- *      wd#1 - 2 seconds;
- *      wd#2 - 7.2 ms;
- *  After the expiration of wd#1, it can generate a NMI, SCI, SMI, or 
- *  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>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/smp_lock.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-
-
-/* ports */
-#define ZF_IOBASE      0x218
-#define INDEX          0x218
-#define DATA_B         0x219
-#define DATA_W         0x21A
-#define DATA_D         0x21A
-
-/* indexes */                  /* size */
-#define ZFL_VERSION    0x02    /* 16   */
-#define CONTROL        0x10    /* 16   */      
-#define STATUS         0x12    /* 8    */
-#define COUNTER_1      0x0C    /* 16   */
-#define COUNTER_2      0x0E    /* 8    */
-#define PULSE_LEN      0x0F    /* 8    */
-
-/* controls */
-#define ENABLE_WD1     0x0001
-#define ENABLE_WD2     0x0002
-#define RESET_WD1      0x0010
-#define RESET_WD2      0x0020
-#define GEN_SCI                0x0100
-#define GEN_NMI                0x0200
-#define GEN_SMI                0x0400
-#define GEN_RESET      0x0800
-
-
-/* utilities */
-
-#define WD1    0
-#define WD2    1
-
-#define zf_writew(port, data)  { outb(port, INDEX); outw(data, DATA_W); }
-#define zf_writeb(port, data)  { outb(port, INDEX); outb(data, DATA_B); }
-#define zf_get_ZFL_version()   zf_readw(ZFL_VERSION)
-
-
-static unsigned short zf_readw(unsigned char port)
-{
-       outb(port, INDEX);
-       return inw(DATA_W);
-}
-
-static unsigned short zf_readb(unsigned char port)
-{
-       outb(port, INDEX);
-       return inb(DATA_B);
-}
-
-
-MODULE_AUTHOR("Fernando Fuganti <fuganti@conectiva.com.br>");
-MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver");
-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 = {
-       .options                = WDIOF_KEEPALIVEPING, 
-       .firmware_version       = 1, 
-       .identity               = "ZF-Logic watchdog"
-};
-
-
-/*
- * action refers to action taken when watchdog resets
- * 0 = GEN_RESET
- * 1 = GEN_SMI
- * 2 = GEN_NMI
- * 3 = GEN_SCI
- * defaults to GEN_RESET (0)
- */
-static int action = 0;
-static int zf_action = GEN_RESET;
-static int zf_is_open = 0;
-static int zf_expect_close = 0;
-static spinlock_t zf_lock;
-static spinlock_t zf_port_lock;
-static struct timer_list zf_timer;
-static unsigned long next_heartbeat = 0;
-
-
-/* timeout for user land heart beat (10 seconds) */
-#define ZF_USER_TIMEO (HZ*10)
-
-/* timeout for hardware watchdog (~500ms) */
-#define ZF_HW_TIMEO (HZ/2)
-
-/* number of ticks on WD#1 (driven by a 32KHz clock, 2s) */
-#define ZF_CTIMEOUT 0xffff
-
-#ifndef ZF_DEBUG
-#      define dprintk(format, args...)
-#else
-#      define dprintk(format, args...) printk(KERN_DEBUG PFX; ":" __FUNCTION__ ":%d: " format, __LINE__ , ## args)
-#endif
-
-
-/* STATUS register functions */
-
-static inline unsigned char zf_get_status(void)
-{
-       return zf_readb(STATUS);
-}
-
-static inline void zf_set_status(unsigned char new)
-{
-       zf_writeb(STATUS, new);
-}
-
-
-/* CONTROL register functions */
-
-static inline unsigned short zf_get_control(void)
-{
-       return zf_readw(CONTROL);
-}
-
-static inline void zf_set_control(unsigned short new)
-{
-       zf_writew(CONTROL, new);
-}
-
-
-/* WD#? counter functions */
-/*
- *     Just get current counter value
- */
-
-static inline unsigned short zf_get_timer(unsigned char n)
-{
-       switch(n){
-               case WD1:
-                       return zf_readw(COUNTER_1);
-               case WD2:
-                       return zf_readb(COUNTER_2);
-               default:
-                       return 0;
-       }
-}
-
-/*
- *     Just set counter value
- */
-
-static inline void zf_set_timer(unsigned short new, unsigned char n)
-{
-       switch(n){
-               case WD1:
-                       zf_writew(COUNTER_1, new);
-               case WD2:
-                       zf_writeb(COUNTER_2, new > 0xff ? 0xff : new);
-               default:
-                       return;
-       }
-}
-
-/*
- * stop hardware timer
- */
-static void zf_timer_off(void)
-{
-       unsigned int ctrl_reg = 0;
-       unsigned long flags;
-
-       /* stop internal ping */
-       del_timer_sync(&zf_timer);
-
-       spin_lock_irqsave(&zf_port_lock, flags);
-       /* stop watchdog timer */       
-       ctrl_reg = zf_get_control();
-       ctrl_reg |= (ENABLE_WD1|ENABLE_WD2);    /* disable wd1 and wd2 */
-       ctrl_reg &= ~(ENABLE_WD1|ENABLE_WD2);
-       zf_set_control(ctrl_reg);
-       spin_unlock_irqrestore(&zf_port_lock, flags);
-
-       printk(KERN_INFO PFX ": Watchdog timer is now disabled\n");
-}
-
-
-/*
- * start hardware timer 
- */
-static void zf_timer_on(void)
-{
-       unsigned int ctrl_reg = 0;
-       unsigned long flags;
-       
-       spin_lock_irqsave(&zf_port_lock, flags);
-
-       zf_writeb(PULSE_LEN, 0xff);
-
-       zf_set_timer(ZF_CTIMEOUT, WD1);
-
-       /* user land ping */
-       next_heartbeat = jiffies + ZF_USER_TIMEO;
-
-       /* start the timer for internal ping */
-       zf_timer.expires = jiffies + ZF_HW_TIMEO;
-
-       add_timer(&zf_timer);
-
-       /* start watchdog timer */
-       ctrl_reg = zf_get_control();
-       ctrl_reg |= (ENABLE_WD1|zf_action);
-       zf_set_control(ctrl_reg);
-       spin_unlock_irqrestore(&zf_port_lock, flags);
-
-       printk(KERN_INFO PFX ": Watchdog timer is now enabled\n");
-}
-
-
-static void zf_ping(unsigned long data)
-{
-       unsigned int ctrl_reg = 0;
-       unsigned long flags;
-               
-       zf_writeb(COUNTER_2, 0xff);
-
-       if(time_before(jiffies, next_heartbeat)){
-
-               dprintk("time_before: %ld\n", next_heartbeat - jiffies);
-               
-               /* 
-                * reset event is activated by transition from 0 to 1 on
-                * RESET_WD1 bit and we assume that it is already zero...
-                */
-
-               spin_lock_irqsave(&zf_port_lock, flags);
-               ctrl_reg = zf_get_control();    
-               ctrl_reg |= RESET_WD1;          
-               zf_set_control(ctrl_reg);       
-               
-               /* ...and nothing changes until here */
-               ctrl_reg &= ~(RESET_WD1);
-               zf_set_control(ctrl_reg);               
-               spin_unlock_irqrestore(&zf_port_lock, flags);
-
-               zf_timer.expires = jiffies + ZF_HW_TIMEO;
-               add_timer(&zf_timer);
-       }else{
-               printk(KERN_CRIT PFX ": I will reset your machine\n");
-       }
-}
-
-static ssize_t zf_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;
-
-       /* See if we got the magic character */
-       if(count){
-
-/*
- * no need to check for close confirmation
- * no way to disable watchdog ;)
- */
-               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++){
-                               char c;
-                               if (get_user(c, buf + ofs))
-                                       return -EFAULT;
-                               if (c == 'V'){
-                                       zf_expect_close = 1;
-                                       dprintk("zf_expect_close 1\n");
-                               }
-                       }
-               }
-               /*
-                * Well, anyhow someone wrote to us,
-                * we should return that favour
-                */
-               next_heartbeat = jiffies + ZF_USER_TIMEO;
-               dprintk("user ping at %ld\n", jiffies);
-               
-               return 1;
-       }
-
-       return 0;
-}
-
-static ssize_t zf_read(struct file *file, char *buf, size_t count, 
-                                                       loff_t *ppos)
-{
-       return -EINVAL;
-}
-
-
-
-static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       switch(cmd){
-               case WDIOC_GETSUPPORT:
-                       if (copy_to_user((struct watchdog_info *)arg, 
-                                        &zf_info, sizeof(zf_info)))
-                               return -EFAULT;
-                       break;
-         
-               case WDIOC_GETSTATUS:
-                       if (copy_to_user((int *)arg, &zf_is_open, sizeof(int)))
-                               return -EFAULT;
-                       break;
-
-               case WDIOC_KEEPALIVE:
-                       zf_ping(0);
-                       break;
-
-               default:
-                       return -ENOTTY;
-       }
-
-       return 0;
-}
-
-static int zf_open(struct inode *inode, struct file *file)
-{
-       switch(minor(inode->i_rdev)){
-               case WATCHDOG_MINOR:
-                       spin_lock(&zf_lock);
-                       if(zf_is_open){
-                               spin_unlock(&zf_lock);
-                               return -EBUSY;
-                       }
-
-                       if (nowayout) {
-                               MOD_INC_USE_COUNT;
-                       }
-                       zf_is_open = 1;
-
-                       spin_unlock(&zf_lock);
-
-                       zf_timer_on();
-
-                       return 0;
-               default:
-                       return -ENODEV;
-       }
-}
-
-static int zf_close(struct inode *inode, struct file *file)
-{
-       if(minor(inode->i_rdev) == WATCHDOG_MINOR){
-
-               if(zf_expect_close){
-                       zf_timer_off();
-               } else {
-                       del_timer(&zf_timer);
-                       printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n");
-               }
-               
-               spin_lock(&zf_lock);
-               zf_is_open = 0;
-               spin_unlock(&zf_lock);
-
-               zf_expect_close = 0;
-       }
-       
-       return 0;
-}
-
-/*
- * Notifier for system down
- */
-
-static int zf_notify_sys(struct notifier_block *this, unsigned long code,
-                                                               void *unused)
-{
-       if(code == SYS_DOWN || code == SYS_HALT){
-               zf_timer_off();         
-       }
-       
-       return NOTIFY_DONE;
-}
-
-
-
-
-static struct file_operations zf_fops = {
-       .owner          = THIS_MODULE,
-       .read           = zf_read,
-       .write          = zf_write,
-       .ioctl          = zf_ioctl,
-       .open           = zf_open,
-       .release        = zf_close,
-};
-
-static struct miscdevice zf_miscdev = {
-       WATCHDOG_MINOR,
-       "watchdog",
-       &zf_fops
-};
-                                                                        
-
-/*
- * The device needs to learn about soft shutdowns in order to
- * turn the timebomb registers off.
- */
-static struct notifier_block zf_notifier = {
-       zf_notify_sys,
-       NULL,
-       0
-};
-
-static void __init zf_show_action(int act)
-{
-       char *str[] = { "RESET", "SMI", "NMI", "SCI" };
-       
-       printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]);
-}
-
-static int __init zf_init(void)
-{
-       int ret;
-       
-       printk(KERN_INFO PFX ": MachZ ZF-Logic Watchdog driver initializing.\n");
-
-       ret = zf_get_ZFL_version();
-       printk("%#x\n", ret);
-       if((!ret) || (ret != 0xffff)){
-               printk(KERN_WARNING PFX ": no ZF-Logic found\n");
-               return -ENODEV;
-       }
-
-       if((action <= 3) && (action >= 0)){
-               zf_action = zf_action>>action;
-       } else
-               action = 0;
-       
-       zf_show_action(action);
-
-       spin_lock_init(&zf_lock);
-       spin_lock_init(&zf_port_lock);
-       
-       ret = misc_register(&zf_miscdev);
-       if (ret){
-               printk(KERN_ERR "can't misc_register on minor=%d\n",
-                                                       WATCHDOG_MINOR);
-               goto out;
-       }
-
-       if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){
-               printk(KERN_ERR "cannot reserve I/O ports at %d\n",
-                                                       ZF_IOBASE);
-               ret = -EBUSY;
-               goto no_region;
-       }
-
-       ret = register_reboot_notifier(&zf_notifier);
-       if(ret){
-               printk(KERN_ERR "can't register reboot notifier (err=%d)\n",
-                                                                       ret);
-               goto no_reboot;
-       }
-       
-       zf_set_status(0);
-       zf_set_control(0);
-
-       /* this is the timer that will do the hard work */
-       init_timer(&zf_timer);
-       zf_timer.function = zf_ping;
-       zf_timer.data = 0;
-       
-       return 0;
-
-no_reboot:
-       release_region(ZF_IOBASE, 3);
-no_region:
-       misc_deregister(&zf_miscdev);
-out:
-       return ret;
-}
-
-       
-void __exit zf_exit(void)
-{
-       zf_timer_off();
-       
-       misc_deregister(&zf_miscdev);
-       unregister_reboot_notifier(&zf_notifier);
-       release_region(ZF_IOBASE, 3);
-}
-
-module_init(zf_init);
-module_exit(zf_exit);
diff --git a/drivers/char/mixcomwd.c b/drivers/char/mixcomwd.c
deleted file mode 100644 (file)
index 6ee6576..0000000
+++ /dev/null
@@ -1,282 +0,0 @@
-/*
- * MixCom Watchdog: A Simple Hardware Watchdog Device
- * Based on Softdog driver by Alan Cox and PC Watchdog driver by Ken Hollis
- *
- * Author: Gergely Madarasz <gorgo@itc.hu>
- *
- * Copyright (c) 1999 ITConsult-Pro Co. <info@itc.hu>
- *
- * 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.
- *
- * Version 0.1 (99/04/15):
- *             - first version
- *
- * Version 0.2 (99/06/16):
- *             - added kernel timer watchdog ping after close
- *               since the hardware does not support watchdog shutdown
- *
- * Version 0.3 (99/06/21):
- *             - added WDIOC_GETSTATUS and WDIOC_GETSUPPORT ioctl calls
- *
- * Version 0.3.1 (99/06/22):
- *             - allow module removal while internal timer is active,
- *               print warning about probable reset
- *
- * 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.5" 
-  
-#include <linux/module.h>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/ioport.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/smp_lock.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-static int mixcomwd_ioports[] = { 0x180, 0x280, 0x380, 0x000 };
-
-#define MIXCOM_WATCHDOG_OFFSET 0xc10
-#define MIXCOM_ID 0x11
-#define FLASHCOM_WATCHDOG_OFFSET 0x4
-#define FLASHCOM_ID 0x18
-
-static long mixcomwd_opened; /* long req'd for setbit --RR */
-
-static int watchdog_port;
-static int mixcomwd_timer_alive;
-static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 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)");
-
-static void mixcomwd_ping(void)
-{
-       outb_p(55,watchdog_port);
-       return;
-}
-
-static void mixcomwd_timerfun(unsigned long d)
-{
-       mixcomwd_ping();
-       
-       mod_timer(&mixcomwd_timer,jiffies+ 5*HZ);
-}
-
-/*
- *     Allow only one person to hold it open
- */
-static int mixcomwd_open(struct inode *inode, struct file *file)
-{
-       if(test_and_set_bit(0,&mixcomwd_opened)) {
-               return -EBUSY;
-       }
-       mixcomwd_ping();
-       
-       if (nowayout) {
-               MOD_INC_USE_COUNT;
-       } else {
-               if(mixcomwd_timer_alive) {
-                       del_timer(&mixcomwd_timer);
-                       mixcomwd_timer_alive=0;
-               }
-       }
-       return 0;
-}
-
-static int mixcomwd_release(struct inode *inode, struct file *file)
-{
-
-       if (!nowayout) {
-               if(mixcomwd_timer_alive) {
-                       printk(KERN_ERR "mixcomwd: release called while internal timer alive");
-                       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);
-       }
-       clear_bit(0,&mixcomwd_opened);
-       return 0;
-}
-
-
-static ssize_t mixcomwd_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
-       if (ppos != &file->f_pos) {
-               return -ESPIPE;
-       }
-
-       if(len)
-       {
-               mixcomwd_ping();
-               return 1;
-       }
-       return 0;
-}
-
-static int mixcomwd_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       int status;
-        static struct watchdog_info ident = {
-               WDIOF_KEEPALIVEPING, 1, "MixCOM watchdog"
-       };
-                                        
-       switch(cmd)
-       {
-               case WDIOC_GETSTATUS:
-                       status=mixcomwd_opened;
-                       if (!nowayout) {
-                               status|=mixcomwd_timer_alive;
-                       }
-                       if (copy_to_user((int *)arg, &status, sizeof(int))) {
-                               return -EFAULT;
-                       }
-                       break;
-               case WDIOC_GETSUPPORT:
-                       if (copy_to_user((struct watchdog_info *)arg, &ident, 
-                           sizeof(ident))) {
-                               return -EFAULT;
-                       }
-                       break;
-               case WDIOC_KEEPALIVE:
-                       mixcomwd_ping();
-                       break;
-               default:
-                       return -ENOTTY;
-       }
-       return 0;
-}
-
-static struct file_operations mixcomwd_fops=
-{
-       .owner          = THIS_MODULE,
-       .write          = mixcomwd_write,
-       .ioctl          = mixcomwd_ioctl,
-       .open           = mixcomwd_open,
-       .release        = mixcomwd_release,
-};
-
-static struct miscdevice mixcomwd_miscdev=
-{
-       WATCHDOG_MINOR,
-       "watchdog",
-       &mixcomwd_fops
-};
-
-static int __init mixcomwd_checkcard(int port)
-{
-       int id;
-
-       if(check_region(port+MIXCOM_WATCHDOG_OFFSET,1)) {
-               return 0;
-       }
-       
-       id=inb_p(port + MIXCOM_WATCHDOG_OFFSET) & 0x3f;
-       if(id!=MIXCOM_ID) {
-               return 0;
-       }
-       return 1;
-}
-
-static int __init flashcom_checkcard(int port)
-{
-       int id;
-       
-       if(check_region(port + FLASHCOM_WATCHDOG_OFFSET,1)) {
-               return 0;
-       }
-       
-       id=inb_p(port + FLASHCOM_WATCHDOG_OFFSET);
-       if(id!=FLASHCOM_ID) {
-               return 0;
-       }
-       return 1;
- }
-static int __init mixcomwd_init(void)
-{
-       int i;
-       int ret;
-       int found=0;
-
-       for (i = 0; !found && mixcomwd_ioports[i] != 0; i++) {
-               if (mixcomwd_checkcard(mixcomwd_ioports[i])) {
-                       found = 1;
-                       watchdog_port = mixcomwd_ioports[i] + MIXCOM_WATCHDOG_OFFSET;
-               }
-       }
-       
-       /* The FlashCOM card can be set up at 0x300 -> 0x378, in 0x8 jumps */
-       for (i = 0x300; !found && i < 0x380; i+=0x8) {
-               if (flashcom_checkcard(i)) {
-                       found = 1;
-                       watchdog_port = i + FLASHCOM_WATCHDOG_OFFSET;
-               }
-       }
-       
-       if (!found) {
-               printk("mixcomwd: No card detected, or port not available.\n");
-               return -ENODEV;
-       }
-
-       if (!request_region(watchdog_port,1,"MixCOM watchdog"))
-               return -EIO;
-               
-       ret = misc_register(&mixcomwd_miscdev);
-       if (ret)
-       {
-               release_region(watchdog_port, 1);
-               return ret;
-       }
-       
-       printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",VERSION,watchdog_port);
-
-       return 0;
-}      
-
-static void __exit mixcomwd_exit(void)
-{
-       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;
-               }
-       }
-       release_region(watchdog_port,1);
-       misc_deregister(&mixcomwd_miscdev);
-}
-
-module_init(mixcomwd_init);
-module_exit(mixcomwd_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/pcwd.c b/drivers/char/pcwd.c
deleted file mode 100644 (file)
index 4fdd439..0000000
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * PC Watchdog Driver
- * by Ken Hollis (khollis@bitgate.com)
- *
- * Permission granted from Simon Machell (73244.1270@compuserve.com)
- * Written for the Linux Kernel, and GPLed by Ken Hollis
- *
- * 960107      Added request_region routines, modulized the whole thing.
- * 960108      Fixed end-of-file pointer (Thanks to Dan Hollis), added
- *             WD_TIMEOUT define.
- * 960216      Added eof marker on the file, and changed verbose messages.
- * 960716      Made functional and cosmetic changes to the source for
- *             inclusion in Linux 2.0.x kernels, thanks to Alan Cox.
- * 960717      Removed read/seek routines, replaced with ioctl.  Also, added
- *             check_region command due to Alan's suggestion.
- * 960821      Made changes to compile in newer 2.0.x kernels.  Added
- *             "cold reboot sense" entry.
- * 960825      Made a few changes to code, deleted some defines and made
- *             typedefs to replace them.  Made heartbeat reset only available
- *             via ioctl, and removed the write routine.
- * 960828      Added new items for PC Watchdog Rev.C card.
- * 960829      Changed around all of the IOCTLs, added new features,
- *             added watchdog disable/re-enable routines.  Added firmware
- *             version reporting.  Added read routine for temperature.
- *             Removed some extra defines, added an autodetect Revision
- *             routine.
- * 961006       Revised some documentation, fixed some cosmetic bugs.  Made
- *              drivers to panic the system if it's overheating at bootup.
- * 961118      Changed some verbiage on some of the output, tidied up
- *             code bits, and added compatibility to 2.1.x.
- * 970912       Enabled board on open and disable on close.
- * 971107      Took account of recent VFS changes (broke read).
- * 971210       Disable board on initialisation in case board already ticking.
- * 971222       Changed open/close for temperature handling
- *              Michael Meskes <meskes@debian.org>.
- * 980112       Used minor numbers from include/linux/miscdevice.h
- * 990403       Clear reset status after reading control status register in 
- *              pcwd_showprevstate(). [Marc Boucher <marc@mbsi.ca>]
- * 990605      Made changes to code to support Firmware 1.22a, added
- *             fairly useless proc entry.
- * 990610      removed said useless proc code for the merge <alan>
- * 000403      Removed last traces of proc code. <davej>
- */
-
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/tty.h>
-#include <linux/timer.h>
-#include <linux/config.h>
-#include <linux/kernel.h>
-#include <linux/wait.h>
-#include <linux/string.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/watchdog.h>
-#include <linux/init.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/smp_lock.h>
-
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-/*
- * These are the auto-probe addresses available.
- *
- * Revision A only uses ports 0x270 and 0x370.  Revision C introduced 0x350.
- * Revision A has an address range of 2 addresses, while Revision C has 3.
- */
-static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
-
-#define WD_VER                  "1.10 (06/05/99)"
-
-/*
- * It should be noted that PCWD_REVISION_B was removed because A and B
- * are essentially the same types of card, with the exception that B
- * has temperature reporting.  Since I didn't receive a Rev.B card,
- * the Rev.B card is not supported.  (It's a good thing too, as they
- * are no longer in production.)
- */
-#define        PCWD_REVISION_A         1
-#define        PCWD_REVISION_C         2
-
-#define        WD_TIMEOUT              3       /* 1 1/2 seconds for a timeout */
-
-/*
- * These are the defines for the PC Watchdog card, revision A.
- */
-#define WD_WDRST                0x01   /* Previously reset state */
-#define WD_T110                 0x02   /* Temperature overheat sense */
-#define WD_HRTBT                0x04   /* Heartbeat sense */
-#define WD_RLY2                 0x08   /* External relay triggered */
-#define WD_SRLY2                0x80   /* Software external relay triggered */
-
-static int current_readport, revision, temp_panic;
-static atomic_t open_allowed = ATOMIC_INIT(1);
-static int initial_status, supports_temp, mode_debug;
-static spinlock_t io_lock;
-
-/*
- * PCWD_CHECKCARD
- *
- * This routine checks the "current_readport" to see if the card lies there.
- * If it does, it returns accordingly.
- */
-static int __init pcwd_checkcard(void)
-{
-       int card_dat, prev_card_dat, found = 0, count = 0, done = 0;
-
-       card_dat = 0x00;
-       prev_card_dat = 0x00;
-
-       prev_card_dat = inb(current_readport);
-       if (prev_card_dat == 0xFF)
-               return 0;
-
-       while(count < WD_TIMEOUT) {
-
-       /* Read the raw card data from the port, and strip off the
-          first 4 bits */
-
-               card_dat = inb_p(current_readport);
-               card_dat &= 0x000F;
-
-       /* Sleep 1/2 second (or 500000 microseconds :) */
-
-               mdelay(500);
-               done = 0;
-
-       /* If there's a heart beat in both instances, then this means we
-          found our card.  This also means that either the card was
-          previously reset, or the computer was power-cycled. */
-
-               if ((card_dat & WD_HRTBT) && (prev_card_dat & WD_HRTBT) &&
-                       (!done)) {
-                       found = 1;
-                       done = 1;
-                       break;
-               }
-
-       /* If the card data is exactly the same as the previous card data,
-          it's safe to assume that we should check again.  The manual says
-          that the heart beat will change every second (or the bit will
-          toggle), and this can be used to see if the card is there.  If
-          the card was powered up with a cold boot, then the card will
-          not start blinking until 2.5 minutes after a reboot, so this
-          bit will stay at 1. */
-
-               if ((card_dat == prev_card_dat) && (!done)) {
-                       count++;
-                       done = 1;
-               }
-
-       /* If the card data is toggling any bits, this means that the heart
-          beat was detected, or something else about the card is set. */
-
-               if ((card_dat != prev_card_dat) && (!done)) {
-                       done = 1;
-                       found = 1;
-                       break;
-               }
-
-       /* Otherwise something else strange happened. */
-
-               if (!done)
-                       count++;
-       }
-
-       return((found) ? 1 : 0);
-}
-
-void pcwd_showprevstate(void)
-{
-       int card_status = 0x0000;
-
-       if (revision == PCWD_REVISION_A)
-               initial_status = card_status = inb(current_readport);
-       else {
-               initial_status = card_status = inb(current_readport + 1);
-               outb_p(0x00, current_readport + 1); /* clear reset status */
-       }
-
-       if (revision == PCWD_REVISION_A) {
-               if (card_status & WD_WDRST)
-                       printk("pcwd: Previous reboot was caused by the card.\n");
-
-               if (card_status & WD_T110) {
-                       printk("pcwd: Card senses a CPU Overheat.  Panicking!\n");
-                       panic("pcwd: CPU Overheat.\n");
-               }
-
-               if ((!(card_status & WD_WDRST)) &&
-                   (!(card_status & WD_T110)))
-                       printk("pcwd: Cold boot sense.\n");
-       } else {
-               if (card_status & 0x01)
-                       printk("pcwd: Previous reboot was caused by the card.\n");
-
-               if (card_status & 0x04) {
-                       printk("pcwd: Card senses a CPU Overheat.  Panicking!\n");
-                       panic("pcwd: CPU Overheat.\n");
-               }
-
-               if ((!(card_status & 0x01)) &&
-                   (!(card_status & 0x04)))
-                       printk("pcwd: Cold boot sense.\n");
-       }
-}
-
-static void pcwd_send_heartbeat(void)
-{
-       int wdrst_stat;
-
-       wdrst_stat = inb_p(current_readport);
-       wdrst_stat &= 0x0F;
-
-       wdrst_stat |= WD_WDRST;
-
-       if (revision == PCWD_REVISION_A)
-               outb_p(wdrst_stat, current_readport + 1);
-       else
-               outb_p(wdrst_stat, current_readport);
-}
-
-static int pcwd_ioctl(struct inode *inode, struct file *file,
-                     unsigned int cmd, unsigned long arg)
-{
-       int cdat, rv;
-       static struct watchdog_info ident=
-       {
-               WDIOF_OVERHEAT|WDIOF_CARDRESET,
-               1,
-               "PCWD"
-       };
-
-       switch(cmd) {
-       default:
-               return -ENOTTY;
-
-       case WDIOC_GETSUPPORT:
-               if(copy_to_user((void*)arg, &ident, sizeof(ident)))
-                       return -EFAULT;
-               return 0;
-
-       case WDIOC_GETSTATUS:
-               spin_lock(&io_lock);
-               if (revision == PCWD_REVISION_A) 
-                       cdat = inb(current_readport);
-               else
-                       cdat = inb(current_readport + 1 );
-               spin_unlock(&io_lock);
-               rv = 0;
-
-               if (revision == PCWD_REVISION_A) 
-               {
-                       if (cdat & WD_WDRST)
-                               rv |= WDIOF_CARDRESET;
-
-                       if (cdat & WD_T110) 
-                       {
-                               rv |= WDIOF_OVERHEAT;
-
-                               if (temp_panic)
-                                       panic("pcwd: Temperature overheat trip!\n");
-                       }
-               }
-               else 
-               {
-                       if (cdat & 0x01)
-                               rv |= WDIOF_CARDRESET;
-
-                       if (cdat & 0x04) 
-                       {
-                               rv |= WDIOF_OVERHEAT;
-
-                               if (temp_panic)
-                                       panic("pcwd: Temperature overheat trip!\n");
-                       }
-               }
-
-               if(put_user(rv, (int *) arg))
-                       return -EFAULT;
-               return 0;
-
-       case WDIOC_GETBOOTSTATUS:
-               rv = 0;
-
-               if (revision == PCWD_REVISION_A) 
-               {
-                       if (initial_status & WD_WDRST)
-                               rv |= WDIOF_CARDRESET;
-
-                       if (initial_status & WD_T110)
-                               rv |= WDIOF_OVERHEAT;
-               }
-               else
-               {
-                       if (initial_status & 0x01)
-                               rv |= WDIOF_CARDRESET;
-
-                       if (initial_status & 0x04)
-                               rv |= WDIOF_OVERHEAT;
-               }
-
-               if(put_user(rv, (int *) arg))
-                       return -EFAULT;
-               return 0;
-
-       case WDIOC_GETTEMP:
-
-               rv = 0;
-               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;
-               } else if(put_user(rv, (int*) arg))
-                               return -EFAULT;
-               return 0;
-
-       case WDIOC_SETOPTIONS:
-               if (revision == PCWD_REVISION_C) 
-               {
-                       if(copy_from_user(&rv, (int*) arg, sizeof(int)))
-                               return -EFAULT;
-
-                       if (rv & WDIOS_DISABLECARD) 
-                       {
-                               spin_lock(&io_lock);
-                               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("pcwd: Could not disable card.\n");
-                                       return -EIO;
-                               }
-
-                               return 0;
-                       }
-
-                       if (rv & WDIOS_ENABLECARD) 
-                       {
-                               spin_lock(&io_lock);
-                               outb_p(0x00, current_readport + 3);
-                               cdat = inb_p(current_readport + 2);
-                               spin_unlock(&io_lock);
-                               if (cdat & 0x10) 
-                               {
-                                       printk("pcwd: Could not enable card.\n");
-                                       return -EIO;
-                               }
-                               return 0;
-                       }
-
-                       if (rv & WDIOS_TEMPPANIC) 
-                       {
-                               temp_panic = 1;
-                       }
-               }
-               return -EINVAL;
-               
-       case WDIOC_KEEPALIVE:
-               pcwd_send_heartbeat();
-               return 0;
-       }
-
-       return 0;
-}
-
-static ssize_t pcwd_write(struct file *file, const char *buf, size_t len,
-                         loff_t *ppos)
-{
-       /*  Can't seek (pwrite) on this device  */
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-
-       if (len)
-       {
-               pcwd_send_heartbeat();
-               return 1;
-       }
-       return 0;
-}
-
-static int pcwd_open(struct inode *ino, struct file *filep)
-{
-        switch (minor(ino->i_rdev))
-        {
-                case WATCHDOG_MINOR:
-                    if ( !atomic_dec_and_test(&open_allowed) )
-                   {
-                       atomic_inc( &open_allowed );
-                        return -EBUSY;
-                    }
-                   MOD_INC_USE_COUNT;
-                    /*  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:
-                    return(0);
-                default:
-                    return (-ENODEV);
-        }
-}
-
-static ssize_t pcwd_read(struct file *file, char *buf, size_t count,
-                        loff_t *ppos)
-{
-       unsigned short c;
-       unsigned char cp;
-
-       /*  Can't seek (pread) on this device  */
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-       switch(minor(file->f_dentry->d_inode->i_rdev)) 
-       {
-               case TEMP_MINOR:
-                       /*
-                        * Convert metric to Fahrenheit, since this was
-                        * the decided 'standard' for this return value.
-                        */
-                       
-                       c = inb(current_readport);
-                       cp = (c * 9 / 5) + 32;
-                       if(copy_to_user(buf, &cp, 1))
-                               return -EFAULT;
-                       return 1;
-               default:
-                       return -EINVAL;
-       }
-}
-
-static int pcwd_close(struct inode *ino, struct file *filep)
-{
-       if (minor(ino->i_rdev)==WATCHDOG_MINOR)
-       {
-#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);
-               }
-               atomic_inc( &open_allowed );
-#endif
-       }
-       return 0;
-}
-
-static inline void get_support(void)
-{
-       if (inb(current_readport) != 0xF0)
-               supports_temp = 1;
-}
-
-static inline int get_revision(void)
-{
-       int r = PCWD_REVISION_C;
-       
-       spin_lock(&io_lock);
-       if ((inb(current_readport + 2) == 0xFF) ||
-           (inb(current_readport + 3) == 0xFF))
-               r=PCWD_REVISION_A;
-       spin_unlock(&io_lock);
-
-       return r;
-}
-
-static int __init send_command(int cmd)
-{
-       int i;
-
-       outb_p(cmd, current_readport + 2);
-       mdelay(1);
-
-       i = inb(current_readport);
-       i = inb(current_readport);
-
-       return(i);
-}
-
-static inline char *get_firmware(void)
-{
-       int i, found = 0, count = 0, one, ten, hund, minor;
-       char *ret;
-
-       ret = kmalloc(6, GFP_KERNEL);
-       if(ret == NULL)
-               return NULL;
-
-       while((count < 3) && (!found)) {
-               outb_p(0x80, current_readport + 2);
-               i = inb(current_readport);
-
-               if (i == 0x00)
-                       found = 1;
-               else if (i == 0xF3)
-                       outb_p(0x00, current_readport + 2);
-
-               udelay(400L);
-               count++;
-       }
-
-       if (found) {
-               mode_debug = 1;
-
-               one = send_command(0x81);
-               ten = send_command(0x82);
-               hund = send_command(0x83);
-               minor = send_command(0x84);
-               sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
-       }
-       else
-               sprintf(ret, "ERROR");
-
-       return(ret);
-}
-
-static void debug_off(void)
-{
-       outb_p(0x00, current_readport + 2);
-       mode_debug = 0;
-}
-
-static struct file_operations pcwd_fops = {
-       .owner          = THIS_MODULE,
-       .read           = pcwd_read,
-       .write          = pcwd_write,
-       .ioctl          = pcwd_ioctl,
-       .open           = pcwd_open,
-       .release        = pcwd_close,
-};
-
-static struct miscdevice pcwd_miscdev = {
-       WATCHDOG_MINOR,
-       "watchdog",
-       &pcwd_fops
-};
-
-static struct miscdevice temp_miscdev = {
-       TEMP_MINOR,
-       "temperature",
-       &pcwd_fops
-};
-static int __init pcwatchdog_init(void)
-{
-       int i, found = 0;
-       spin_lock_init(&io_lock);
-       
-       revision = PCWD_REVISION_A;
-
-       printk("pcwd: v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER);
-
-       /* Initial variables */
-       supports_temp = 0;
-       mode_debug = 0;
-       temp_panic = 0;
-       initial_status = 0x0000;
-
-#ifndef        PCWD_BLIND
-       for (i = 0; pcwd_ioports[i] != 0; i++) {
-               current_readport = pcwd_ioports[i];
-
-               if (pcwd_checkcard()) {
-                       found = 1;
-                       break;
-               }
-       }
-
-       if (!found) {
-               printk("pcwd: No card detected, or port not available.\n");
-               return(-EIO);
-       }
-#endif
-
-#ifdef PCWD_BLIND
-       current_readport = PCWD_BLIND;
-#endif
-
-       get_support();
-       revision = get_revision();
-
-       if (revision == PCWD_REVISION_A)
-               printk("pcwd: PC Watchdog (REV.A) detected at port 0x%03x\n", current_readport);
-       else if (revision == PCWD_REVISION_C)
-               printk("pcwd: PC Watchdog (REV.C) detected at port 0x%03x (Firmware version: %s)\n",
-                       current_readport, get_firmware());
-       else {
-               /* Should NEVER happen, unless get_revision() fails. */
-               printk("pcwd: Unable to get revision.\n");
-               return -1;
-       }
-
-       if (supports_temp)
-               printk("pcwd: Temperature Option Detected.\n");
-
-       debug_off();
-
-       pcwd_showprevstate();
-
-       /*  Disable the board  */
-       if (revision == PCWD_REVISION_C) {
-               outb_p(0xA5, current_readport + 3);
-               outb_p(0xA5, current_readport + 3);
-       }
-
-       if (misc_register(&pcwd_miscdev))
-               return -ENODEV;
-       
-       if (supports_temp)
-               if (misc_register(&temp_miscdev)) {
-                       misc_deregister(&pcwd_miscdev);
-                       return -ENODEV;         
-               }
-
-
-       if (revision == PCWD_REVISION_A) {
-               if (!request_region(current_readport, 2, "PCWD Rev.A (Berkshire)")) {
-                       misc_deregister(&pcwd_miscdev);
-                       if (supports_temp)
-                               misc_deregister(&pcwd_miscdev);
-                       return -EIO;            
-               }
-       }
-       else 
-               if (!request_region(current_readport, 4, "PCWD Rev.C (Berkshire)")) {
-                       misc_deregister(&pcwd_miscdev);
-                       if (supports_temp)
-                               misc_deregister(&pcwd_miscdev);
-                       return -EIO;
-               }
-
-       return 0;
-}
-
-static void __exit pcwatchdog_exit(void)
-{
-       misc_deregister(&pcwd_miscdev);
-       /*  Disable the board  */
-       if (revision == PCWD_REVISION_C) {
-               outb_p(0xA5, current_readport + 3);
-               outb_p(0xA5, current_readport + 3);
-       }
-       if (supports_temp)
-               misc_deregister(&temp_miscdev);
-
-       release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
-}
-
-module_init(pcwatchdog_init);
-module_exit(pcwatchdog_exit);
-
-MODULE_LICENSE("GPL");
-
diff --git a/drivers/char/sbc60xxwdt.c b/drivers/char/sbc60xxwdt.c
deleted file mode 100644 (file)
index d34380c..0000000
+++ /dev/null
@@ -1,354 +0,0 @@
-/*
- *     60xx Single Board Computer Watchdog Timer driver for Linux 2.2.x
- *
- *      Based on acquirewdt.c by Alan Cox.
- *
- *     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.
- *     
- *     The author does NOT admit liability nor provide warranty for 
- *     any of this software. This material is provided "AS-IS" in 
- *      the hope that it may be useful for others.
- *
- *     (c) Copyright 2000    Jakob Oestergaard <jakob@ostenfeld.dk>
- *
- *           12/4 - 2000      [Initial revision]
- *           25/4 - 2000      Added /dev/watchdog support
- *           09/5 - 2001      [smj@oro.net] fixed fop_write to "return 1" on success
- *
- *
- *  Theory of operation:
- *  A Watchdog Timer (WDT) is a hardware circuit that can 
- *  reset the computer system in case of a software fault.
- *  You probably knew that already.
- *
- *  Usually a userspace daemon will notify the kernel WDT driver
- *  via the /proc/watchdog special device file that userspace is
- *  still alive, at regular intervals.  When such a notification
- *  occurs, the driver will usually tell the hardware watchdog
- *  that everything is in order, and that the watchdog should wait
- *  for yet another little while to reset the system.
- *  If userspace fails (RAM error, kernel bug, whatever), the
- *  notifications cease to occur, and the hardware watchdog will
- *  reset the system (causing a reboot) after the timeout occurs.
- *
- *  This WDT driver is different from the other Linux WDT 
- *  drivers in several ways:
- *  *)  The driver will ping the watchdog by itself, because this
- *      particular WDT has a very short timeout (one second) and it
- *      would be insane to count on any userspace daemon always
- *      getting scheduled within that time frame.
- *  *)  This driver expects the userspace daemon to send a specific
- *      character code ('V') to /dev/watchdog before closing the
- *      /dev/watchdog file.  If the userspace daemon closes the file
- *      without sending this special character, the driver will assume
- *      that the daemon (and userspace in general) died, and will
- *      stop pinging the WDT without disabling it first.  This will
- *      cause a reboot.
- *
- *  Why `V' ?  Well, `V' is the character in ASCII for the value 86,
- *  and we all know that 86 is _the_ most random number in the universe.
- *  Therefore it is the letter that has the slightest chance of occuring
- *  by chance, when the system becomes corrupted.
- *
- */
-
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/smp_lock.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-
-#define OUR_NAME "sbc60xxwdt"
-
-/*
- * You must set these - The driver cannot probe for the settings
- */
-#define WDT_STOP 0x45
-#define WDT_START 0x443
-
-/*
- * The 60xx board can use watchdog timeout values from one second
- * to several minutes.  The default is one second, so if we reset
- * the watchdog every ~250ms we should be safe.
- */
-
-#define WDT_INTERVAL (HZ/4+1)
-
-/*
- * We must not require too good response from the userspace daemon.
- * Here we require the userspace daemon to send us a heartbeat
- * char to /dev/watchdog every 10 seconds.
- * If the daemon pulses us every 5 seconds, we can still afford
- * a 5 second scheduling delay on the (high priority) daemon. That
- * should be sufficient for a box under any load.
- */
-
-#define WDT_HEARTBEAT (HZ * 10)
-
-static void wdt_timer_ping(unsigned long);
-static struct timer_list timer;
-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
- */
-
-static void wdt_timer_ping(unsigned long data)
-{
-       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
-        * we agree to ping the WDT 
-        */
-       if(time_before(jiffies, next_heartbeat)) 
-       {
-               /* Ping the WDT by reading from WDT_START */
-               inb_p(WDT_START);
-               /* Re-set the timer interval */
-               timer.expires = jiffies + WDT_INTERVAL;
-               add_timer(&timer);
-       } else {
-               printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n");
-       }
-}
-
-/* 
- * Utility routines
- */
-
-static void wdt_startup(void)
-{
-       next_heartbeat = jiffies + WDT_HEARTBEAT;
-
-       /* Start the timer */
-       timer.expires = jiffies + WDT_INTERVAL; 
-       add_timer(&timer);
-       printk(OUR_NAME ": Watchdog timer is now enabled.\n");  
-}
-
-static void wdt_turnoff(void)
-{
-       /* Stop the timer */
-       del_timer(&timer);
-       inb_p(WDT_STOP);
-       printk(OUR_NAME ": Watchdog timer is now disabled...\n");
-}
-
-
-/*
- * /dev/watchdog handling
- */
-
-static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos)
-{
-       /* We can't seek */
-       if(ppos != &file->f_pos)
-               return -ESPIPE;
-
-       /* See if we got the magic character */
-       if(count) 
-       {
-               size_t ofs;
-
-               /* note: just in case someone wrote the magic character
-                * five months ago... */
-               wdt_expect_close = 0;
-
-               /* now scan */
-               for(ofs = 0; ofs != count; ofs++) 
-               {
-                       char c;
-                       if(get_user(c, buf+ofs))
-                               return -EFAULT;
-                       if(c == 'V')
-                               wdt_expect_close = 1;
-               }
-               /* Well, anyhow someone wrote to us, we should return that favour */
-               next_heartbeat = jiffies + WDT_HEARTBEAT;
-               return 1;
-       }
-       return 0;
-}
-
-static ssize_t fop_read(struct file * file, char * buf, size_t count, loff_t * ppos)
-{
-       /* No can do */
-       return -EINVAL;
-}
-
-static int fop_open(struct inode * inode, struct file * file)
-{
-       switch(minor(inode->i_rdev)) 
-       {
-               case WATCHDOG_MINOR:
-                       /* 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();
-                       return 0;
-
-               default:
-                       return -ENODEV;
-       }
-}
-
-static int fop_close(struct inode * inode, struct file * file)
-{
-       if(minor(inode->i_rdev) == WATCHDOG_MINOR) 
-       {
-               if(wdt_expect_close && !nowayout)
-                       wdt_turnoff();
-               else {
-                       del_timer(&timer);
-                       printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n");
-               }
-       }
-       wdt_is_open = 0;
-       return 0;
-}
-
-static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       static struct watchdog_info ident=
-       {
-               0,
-               1,
-               "SB60xx"
-       };
-       
-       switch(cmd)
-       {
-               default:
-                       return -ENOTTY;
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
-               case WDIOC_KEEPALIVE:
-                       next_heartbeat = jiffies + WDT_HEARTBEAT;
-                       return 0;
-       }
-}
-
-static struct file_operations wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .read           = fop_read,
-       .write          = fop_write,
-       .open           = fop_open,
-       .release        = fop_close,
-       .ioctl          = fop_ioctl
-};
-
-static struct miscdevice wdt_miscdev = {
-       WATCHDOG_MINOR,
-       "watchdog",
-       &wdt_fops
-};
-
-/*
- *     Notifier for system down
- */
-
-static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT) 
-               wdt_turnoff();
-       return NOTIFY_DONE;
-}
-/*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off. 
- */
-static struct notifier_block wdt_notifier=
-{
-       wdt_notify_sys,
-       0,
-       0
-};
-
-static void __exit sbc60xxwdt_unload(void)
-{
-       wdt_turnoff();
-
-       /* Deregister */
-       misc_deregister(&wdt_miscdev);
-
-       unregister_reboot_notifier(&wdt_notifier);
-       release_region(WDT_START,1);
-       release_region(WDT_STOP,1);
-}
-
-static int __init sbc60xxwdt_init(void)
-{
-       int rc = -EBUSY;
-
-       if (!request_region(WDT_STOP, 1, "SBC 60XX WDT"))
-               goto err_out;
-       if (!request_region(WDT_START, 1, "SBC 60XX WDT"))
-               goto err_out_region1;
-
-       init_timer(&timer);
-       timer.function = wdt_timer_ping;
-       timer.data = 0;
-
-       rc = misc_register(&wdt_miscdev);
-       if (rc)
-               goto err_out_region2;
-
-       rc = register_reboot_notifier(&wdt_notifier);
-       if (rc)
-               goto err_out_miscdev;
-
-       printk(KERN_INFO OUR_NAME ": WDT driver for 60XX single board computer initialised.\n");
-       
-       return 0;
-
-err_out_miscdev:
-       misc_deregister(&wdt_miscdev);
-err_out_region2:
-       release_region(WDT_START,1);
-err_out_region1:
-       release_region(WDT_STOP,1);
-err_out:
-       return rc;
-}
-
-module_init(sbc60xxwdt_init);
-module_exit(sbc60xxwdt_unload);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/scx200_wdt.c b/drivers/char/scx200_wdt.c
deleted file mode 100644 (file)
index 41fa773..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/* linux/drivers/char/scx200_wdt.c 
-
-   National Semiconductor SCx200 Watchdog support
-
-   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
-
-   Som code taken from:
-   National Semiconductor PC87307/PC97307 (ala SC1200) WDT driver
-   (c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com>
-
-   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.
-
-   The author(s) of this software shall not be held liable for damages
-   of any nature resulting due to the use of this software. This
-   software is provided AS-IS with no warranties. */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/pci.h>
-#include <asm/uaccess.h>
-#include <asm/io.h>
-
-#include <linux/scx200.h>
-
-#define NAME "scx200_wdt"
-
-MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
-MODULE_DESCRIPTION("NatSemi SCx200 Watchdog Driver");
-MODULE_LICENSE("GPL");
-
-#ifndef CONFIG_WATCHDOG_NOWAYOUT
-#define CONFIG_WATCHDOG_NOWAYOUT 0
-#endif
-
-static int margin = 60;                /* in seconds */
-MODULE_PARM(margin, "i");
-MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
-
-static int nowayout = CONFIG_WATCHDOG_NOWAYOUT;
-MODULE_PARM(nowayout, "i");
-MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
-
-static u16 wdto_restart;
-static struct semaphore open_semaphore;
-static unsigned expect_close;
-
-/* Bits of the WDCNFG register */
-#define W_ENABLE 0x00fa                /* Enable watchdog */
-#define W_DISABLE 0x0000       /* Disable watchdog */
-
-/* The scaling factor for the timer, this depends on the value of W_ENABLE */
-#define W_SCALE (32768/1024)
-
-static void scx200_wdt_ping(void)
-{
-       outw(wdto_restart, SCx200_CB_BASE + SCx200_WDT_WDTO);
-}
-
-static void scx200_wdt_update_margin(void)
-{
-       printk(KERN_INFO NAME ": timer margin %d seconds\n", margin);
-       wdto_restart = margin * W_SCALE;
-}
-
-static void scx200_wdt_enable(void)
-{
-       printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n", 
-              wdto_restart);
-
-       outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO);
-       outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS);
-       outw(W_ENABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG);
-
-       scx200_wdt_ping();
-}
-
-static void scx200_wdt_disable(void)
-{
-       printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
-               
-       outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO);
-       outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS);
-       outw(W_DISABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG);
-}
-
-static int scx200_wdt_open(struct inode *inode, struct file *file)
-{
-        /* only allow one at a time */
-        if (down_trylock(&open_semaphore))
-                return -EBUSY;
-       scx200_wdt_enable();
-       expect_close = 0;
-
-       return 0;
-}
-
-static int scx200_wdt_release(struct inode *inode, struct file *file)
-{
-       if (!expect_close) {
-               printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n");
-       } else if (!nowayout) {
-               scx200_wdt_disable();
-       }
-        up(&open_semaphore);
-
-       return 0;
-}
-
-static int scx200_wdt_notify_sys(struct notifier_block *this, 
-                                     unsigned long code, void *unused)
-{
-        if (code == SYS_HALT || code == SYS_POWER_OFF)
-               if (!nowayout)
-                       scx200_wdt_disable();
-
-        return NOTIFY_DONE;
-}
-
-static struct notifier_block scx200_wdt_notifier =
-{
-        .notifier_call = scx200_wdt_notify_sys
-};
-
-static ssize_t scx200_wdt_write(struct file *file, const char *data, 
-                                    size_t len, loff_t *ppos)
-{
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-
-       /* check for a magic close character */
-       if (len) 
-       {
-               size_t i;
-
-               scx200_wdt_ping();
-
-               expect_close = 0;
-               for (i = 0; i < len; ++i) {
-                       char c;
-                       if (get_user(c, data+i))
-                               return -EFAULT;
-                       if (c == 'V')
-                               expect_close = 1;
-               }
-
-               return len;
-       }
-
-       return 0;
-}
-
-static int scx200_wdt_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       static struct watchdog_info ident = {
-               .identity = "NatSemi SCx200 Watchdog",
-               .firmware_version = 1, 
-               .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING),
-       };
-       int new_margin;
-       
-       switch (cmd) {
-       default:
-               return -ENOTTY;
-       case WDIOC_GETSUPPORT:
-               if(copy_to_user((struct watchdog_info *)arg, &ident, 
-                               sizeof(ident)))
-                       return -EFAULT;
-               return 0;
-       case WDIOC_GETSTATUS:
-       case WDIOC_GETBOOTSTATUS:
-               if (put_user(0, (int *)arg))
-                       return -EFAULT;
-               return 0;
-       case WDIOC_KEEPALIVE:
-               scx200_wdt_ping();
-               return 0;
-       case WDIOC_SETTIMEOUT:
-               if (get_user(new_margin, (int *)arg))
-                       return -EFAULT;
-               if (new_margin < 1)
-                       return -EINVAL;
-               margin = new_margin;
-               scx200_wdt_update_margin();
-               scx200_wdt_ping();
-       case WDIOC_GETTIMEOUT:
-               if (put_user(margin, (int *)arg))
-                       return -EFAULT;
-               return 0;
-       }
-}
-
-static struct file_operations scx200_wdt_fops = {
-       .owner   = THIS_MODULE,
-       .write   = scx200_wdt_write,
-       .ioctl   = scx200_wdt_ioctl,
-       .open    = scx200_wdt_open,
-       .release = scx200_wdt_release,
-};
-
-static struct miscdevice scx200_wdt_miscdev = {
-       .minor = WATCHDOG_MINOR,
-       .name  = NAME,
-       .fops  = &scx200_wdt_fops,
-};
-
-static int __init scx200_wdt_init(void)
-{
-       int r;
-
-       printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n");
-
-       /* First check that this really is a NatSemi SCx200 CPU */
-       if ((pci_find_device(PCI_VENDOR_ID_NS, 
-                            PCI_DEVICE_ID_NS_SCx200_BRIDGE,
-                            NULL)) == NULL)
-               return -ENODEV;
-
-       /* More sanity checks, verify that the configuration block is there */
-       if (!scx200_cb_probe(SCx200_CB_BASE)) {
-               printk(KERN_WARNING NAME ": no configuration block found\n");
-               return -ENODEV;
-       }
-
-       if (!request_region(SCx200_CB_BASE + SCx200_WDT_OFFSET, 
-                           SCx200_WDT_SIZE, 
-                           "NatSemi SCx200 Watchdog")) {
-               printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
-               return -EBUSY;
-       }
-
-       scx200_wdt_update_margin();
-       scx200_wdt_disable();
-
-       sema_init(&open_semaphore, 1);
-
-       r = misc_register(&scx200_wdt_miscdev);
-       if (r)
-               return r;
-
-       r = register_reboot_notifier(&scx200_wdt_notifier);
-        if (r) {
-                printk(KERN_ERR NAME ": unable to register reboot notifier");
-               misc_deregister(&scx200_wdt_miscdev);
-                return r;
-        }
-
-       return 0;
-}
-
-static void __exit scx200_wdt_cleanup(void)
-{
-        unregister_reboot_notifier(&scx200_wdt_notifier);
-       misc_deregister(&scx200_wdt_miscdev);
-       release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
-                      SCx200_WDT_SIZE);
-}
-
-module_init(scx200_wdt_init);
-module_exit(scx200_wdt_cleanup);
-
-/*
-    Local variables:
-        compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules"
-        c-basic-offset: 8
-    End:
-*/
diff --git a/drivers/char/shwdt.c b/drivers/char/shwdt.c
deleted file mode 100644 (file)
index 8761e4a..0000000
+++ /dev/null
@@ -1,417 +0,0 @@
-/*
- * drivers/char/shwdt.c
- *
- * Watchdog driver for integrated watchdog in the SuperH 3/4 processors.
- *
- * Copyright (C) 2001 Paul Mundt <lethal@chaoticdreams.org>
- *
- * 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.
- *
- * 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>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
-#include <linux/notifier.h>
-#include <linux/ioport.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#if defined(CONFIG_CPU_SH4)
-  #define WTCNT                0xffc00008
-  #define WTCSR                0xffc0000c
-#elif defined(CONFIG_CPU_SH3)
-  #define WTCNT                0xffffff84
-  #define WTCSR                0xffffff86
-#else
-  #error "Can't use SH 3/4 watchdog on non-SH 3/4 processor."
-#endif
-
-#define WTCNT_HIGH     0x5a00
-#define WTCSR_HIGH     0xa500
-
-#define WTCSR_TME      0x80
-#define WTCSR_WT       0x40
-#define WTCSR_RSTS     0x20
-#define WTCSR_WOVF     0x10
-#define WTCSR_IOVF     0x08
-#define WTCSR_CKS2     0x04
-#define WTCSR_CKS1     0x02
-#define WTCSR_CKS0     0x01
-
-/*
- * CKS0-2 supports a number of clock division ratios. At the time the watchdog
- * is enabled, it defaults to a 41 usec overflow period .. we overload this to
- * something a little more reasonable, and really can't deal with anything
- * lower than WTCSR_CKS_1024, else we drop back into the usec range.
- *
- * Clock Division Ratio         Overflow Period
- * --------------------------------------------
- *     1/32 (initial value)       41 usecs
- *     1/64                       82 usecs
- *     1/128                     164 usecs
- *     1/256                     328 usecs
- *     1/512                     656 usecs
- *     1/1024                   1.31 msecs
- *     1/2048                   2.62 msecs
- *     1/4096                   5.25 msecs
- */
-#define WTCSR_CKS_32   0x00
-#define WTCSR_CKS_64   0x01
-#define WTCSR_CKS_128  0x02
-#define WTCSR_CKS_256  0x03
-#define WTCSR_CKS_512  0x04
-#define WTCSR_CKS_1024 0x05
-#define WTCSR_CKS_2048 0x06
-#define WTCSR_CKS_4096 0x07
-
-/*
- * Default clock division ratio is 5.25 msecs. Overload this at module load
- * time. Any value not in the msec range will default to a timeout of one
- * jiffy, which exceeds the usec overflow periods.
- */
-static int clock_division_ratio = WTCSR_CKS_4096;
-
-#define msecs_to_jiffies(msecs)        (jiffies + ((HZ * msecs + 999) / 1000))
-#define next_ping_period(cks)  msecs_to_jiffies(cks - 4)
-#define user_ping_period(cks)  (next_ping_period(cks) * 10)
-
-static unsigned long sh_is_open = 0;
-static struct watchdog_info sh_wdt_info;
-static struct timer_list timer;
-static unsigned long next_heartbeat;
-
-#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
- *
- *     @val: Value to write
- *
- *     Writes the given value @val to the lower byte of the timer counter.
- *     The upper byte is set manually on each write.
- */
-static void sh_wdt_write_cnt(__u8 val)
-{
-       ctrl_outw(WTCNT_HIGH | (__u16)val, WTCNT);
-}
-
-/**
- *     sh_wdt_write_csr - Write to Control/Status Register
- *
- *     @val: Value to write
- *
- *     Writes the given value @val to the lower byte of the control/status
- *     register. The upper byte is set manually on each write.
- */
-static void sh_wdt_write_csr(__u8 val)
-{
-       ctrl_outw(WTCSR_HIGH | (__u16)val, WTCSR);
-}
-
-/**
- *     sh_wdt_start - Start the Watchdog
- *
- *     Starts the watchdog.
- */
-static void sh_wdt_start(void)
-{
-       timer.expires = next_ping_period(clock_division_ratio);
-       next_heartbeat = user_ping_period(clock_division_ratio);
-       add_timer(&timer);
-
-       sh_wdt_write_csr(WTCSR_WT | WTCSR_CKS_4096);
-       sh_wdt_write_cnt(0);
-       sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME));
-}
-
-/**
- *     sh_wdt_stop - Stop the Watchdog
- *
- *     Stops the watchdog.
- */
-static void sh_wdt_stop(void)
-{
-       del_timer(&timer);
-
-       sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_TME));
-}
-
-/**
- *     sh_wdt_ping - Ping the Watchdog
- *
- *     @data: Unused
- *
- *     Clears overflow bit, resets timer counter.
- */
-static void sh_wdt_ping(unsigned long data)
-{
-       if (time_before(jiffies, next_heartbeat)) {
-               sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF));
-               sh_wdt_write_cnt(0);
-
-               timer.expires = next_ping_period(clock_division_ratio);
-               add_timer(&timer);
-       }
-}
-
-/**
- *     sh_wdt_open - Open the Device
- *
- *     @inode: inode of device
- *     @file: file handle of device
- *
- *     Watchdog device is opened and started.
- */
-static int sh_wdt_open(struct inode *inode, struct file *file)
-{
-       switch (minor(inode->i_rdev)) {
-               case WATCHDOG_MINOR:
-                       if (test_and_set_bit(0, &sh_is_open))
-                               return -EBUSY;
-
-                       if (nowayout) {
-                               MOD_INC_USE_COUNT;
-                       }
-
-                       sh_wdt_start();
-
-                       break;
-               default:
-                       return -ENODEV;
-       }
-
-       return 0;
-}
-
-/**
- *     sh_wdt_close - Close the Device
- *
- *     @inode: inode of device
- *     @file: file handle of device
- *
- *     Watchdog device is closed and stopped.
- */
-static int sh_wdt_close(struct inode *inode, struct file *file)
-{
-       if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
-               if (!nowayout) {
-                       sh_wdt_stop();
-               }
-               clear_bit(0, &sh_is_open);
-       }
-       
-       return 0;
-}
-
-/**
- *     sh_wdt_read - Read from Device
- *
- *     @file: file handle of device
- *     @buf: buffer to write to
- *     @count: length of buffer
- *     @ppos: offset
- *
- *     Unsupported.
- */
-static ssize_t sh_wdt_read(struct file *file, char *buf,
-                          size_t count, loff_t *ppos)
-{
-       return -EINVAL;
-}
-
-/**
- *     sh_wdt_write - Write to Device
- *
- *     @file: file handle of device
- *     @buf: buffer to write
- *     @count: length of buffer
- *     @ppos: offset
- *
- *     Pings the watchdog on write.
- */
-static ssize_t sh_wdt_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) {
-               next_heartbeat = user_ping_period(clock_division_ratio);
-               return 1;
-       }
-
-       return 0;
-}
-
-/**
- *     sh_wdt_ioctl - Query Device
- *
- *     @inode: inode of device
- *     @file: file handle of device
- *     @cmd: watchdog command
- *     @arg: argument
- *
- *     Query basic information from the device or ping it, as outlined by the
- *     watchdog API.
- */
-static int sh_wdt_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
-{
-       switch (cmd) {
-               case WDIOC_GETSUPPORT:
-                       if (copy_to_user((struct watchdog_info *)arg,
-                                         &sh_wdt_info,
-                                         sizeof(sh_wdt_info))) {
-                               return -EFAULT;
-                       }
-                       
-                       break;
-               case WDIOC_GETSTATUS:
-                       if (copy_to_user((int *)arg,
-                                        &sh_is_open,
-                                        sizeof(int))) {
-                               return -EFAULT;
-                       }
-
-                       break;
-               case WDIOC_KEEPALIVE:
-                       next_heartbeat = user_ping_period(clock_division_ratio);
-                       
-                       break;
-               default:
-                       return -ENOTTY;
-       }
-
-       return 0;
-}
-
-/**
- *     sh_wdt_notify_sys - Notifier Handler
- *     
- *     @this: notifier block
- *     @code: notifier event
- *     @unused: unused
- *
- *     Handles specific events, such as turning off the watchdog during a
- *     shutdown event.
- */
-static int sh_wdt_notify_sys(struct notifier_block *this,
-                            unsigned long code, void *unused)
-{
-       if (code == SYS_DOWN || code == SYS_HALT) {
-               sh_wdt_stop();
-       }
-
-       return NOTIFY_DONE;
-}
-
-static struct file_operations sh_wdt_fops = {
-       .owner          = THIS_MODULE,
-       .read           = sh_wdt_read,
-       .write          = sh_wdt_write,
-       .ioctl          = sh_wdt_ioctl,
-       .open           = sh_wdt_open,
-       .release        = sh_wdt_close,
-};
-
-static struct watchdog_info sh_wdt_info = {
-       WDIOF_KEEPALIVEPING,
-       1,
-       "SH WDT",
-};
-
-static struct notifier_block sh_wdt_notifier = {
-       sh_wdt_notify_sys,
-       NULL,
-       0
-};
-
-static struct miscdevice sh_wdt_miscdev = {
-       WATCHDOG_MINOR,
-       "watchdog",
-       &sh_wdt_fops,
-};
-
-/**
- *     sh_wdt_init - Initialize module
- *
- *     Registers the device and notifier handler. Actual device
- *     initialization is handled by sh_wdt_open().
- */
-static int __init sh_wdt_init(void)
-{
-       if (misc_register(&sh_wdt_miscdev)) {
-               printk(KERN_ERR "shwdt: Can't register misc device\n");
-               return -EINVAL;
-       }
-
-       if (!request_region(WTCNT, 1, "shwdt")) {
-               printk(KERN_ERR "shwdt: Can't request WTCNT region\n");
-               misc_deregister(&sh_wdt_miscdev);
-               return -ENXIO;
-       }
-
-       if (!request_region(WTCSR, 1, "shwdt")) {
-               printk(KERN_ERR "shwdt: Can't request WTCSR region\n");
-               release_region(WTCNT, 1);
-               misc_deregister(&sh_wdt_miscdev);
-               return -ENXIO;
-       }
-
-       if (register_reboot_notifier(&sh_wdt_notifier)) {
-               printk(KERN_ERR "shwdt: Can't register reboot notifier\n");
-               release_region(WTCSR, 1);
-               release_region(WTCNT, 1);
-               misc_deregister(&sh_wdt_miscdev);
-               return -EINVAL;
-       }
-
-       init_timer(&timer);
-       timer.function = sh_wdt_ping;
-       timer.data = 0;
-
-       return 0;
-}
-
-/**
- *     sh_wdt_exit - Deinitialize module
- *
- *     Unregisters the device and notifier handler. Actual device
- *     deinitialization is handled by sh_wdt_close().
- */
-static void __exit sh_wdt_exit(void)
-{
-       unregister_reboot_notifier(&sh_wdt_notifier);
-       release_region(WTCSR, 1);
-       release_region(WTCNT, 1);
-       misc_deregister(&sh_wdt_miscdev);
-}
-
-MODULE_AUTHOR("Paul Mundt <lethal@chaoticdreams.org>");
-MODULE_DESCRIPTION("SH 3/4 watchdog driver");
-MODULE_LICENSE("GPL");
-MODULE_PARM(clock_division_ratio, "i");
-MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7.");
-
-module_init(sh_wdt_init);
-module_exit(sh_wdt_exit);
-
diff --git a/drivers/char/softdog.c b/drivers/char/softdog.c
deleted file mode 100644 (file)
index de7e133..0000000
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- *     SoftDog 0.06:   A Software Watchdog Device
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     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.       
- *
- *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
- *
- *     Software only watchdog driver. Unlike its big brother the WDT501P
- *     driver this won't always recover a failed machine.
- *
- *  03/96: Angelo Haritsis <ah@doc.ic.ac.uk> :
- *     Modularised.
- *     Added soft_margin; use upon insmod to change the timer delay.
- *     NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate
- *         minors.
- *
- *  19980911 Alan Cox
- *     Made SMP safe for 2.3.x
- *
- *  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>
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
-#include <linux/smp_lock.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-
-#define TIMER_MARGIN   60              /* (secs) Default is 1 minute */
-
-static int soft_margin = TIMER_MARGIN; /* in seconds */
-
-MODULE_PARM(soft_margin,"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");
-
-/*
- *     Our timer
- */
-static void watchdog_fire(unsigned long);
-
-static struct timer_list watchdog_ticktock =
-               TIMER_INITIALIZER(watchdog_fire, 0, 0);
-static int timer_alive;
-
-
-/*
- *     If the timer expires..
- */
-static void watchdog_fire(unsigned long data)
-{
-#ifdef ONLY_TESTING
-               printk(KERN_CRIT "SOFTDOG: Would Reboot.\n");
-#else
-       printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n");
-       machine_restart(NULL);
-       printk("WATCHDOG: Reboot didn't ?????\n");
-#endif
-}
-
-/*
- *     Allow only one person to hold it open
- */
-static int softdog_open(struct inode *inode, struct file *file)
-{
-       if(timer_alive)
-               return -EBUSY;
-       if (nowayout) {
-               MOD_INC_USE_COUNT;
-       }
-       /*
-        *      Activate timer
-        */
-       mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
-       timer_alive=1;
-       return 0;
-}
-
-static int softdog_release(struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer.
-        *      Lock it in if it's a module and we set nowayout
-        */
-       if(!nowayout) {
-               del_timer(&watchdog_ticktock);
-       }
-       timer_alive=0;
-       return 0;
-}
-
-static ssize_t softdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
-       /*  Can't seek (pwrite) on this device  */
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-
-       /*
-        *      Refresh the timer.
-        */
-       if(len) {
-               mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
-               return 1;
-       }
-       return 0;
-}
-
-static int softdog_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       static struct watchdog_info ident = {
-               identity: "Software Watchdog",
-       };
-       switch (cmd) {
-               default:
-                       return -ENOTTY;
-               case WDIOC_GETSUPPORT:
-                       if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
-                               return -EFAULT;
-                       return 0;
-               case WDIOC_GETSTATUS:
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0,(int *)arg);
-               case WDIOC_KEEPALIVE:
-                       mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
-                       return 0;
-       }
-}
-
-static struct file_operations softdog_fops = {
-       owner:          THIS_MODULE,
-       write:          softdog_write,
-       ioctl:          softdog_ioctl,
-       open:           softdog_open,
-       release:        softdog_release,
-};
-
-static struct miscdevice softdog_miscdev = {
-       minor:          WATCHDOG_MINOR,
-       name:           "watchdog",
-       fops:           &softdog_fops,
-};
-
-static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.06, soft_margin: %d sec, nowayout: %d\n";
-
-static int __init watchdog_init(void)
-{
-       int ret;
-
-       ret = misc_register(&softdog_miscdev);
-
-       if (ret)
-               return ret;
-
-       printk(banner, soft_margin, nowayout);
-
-       return 0;
-}
-
-static void __exit watchdog_exit(void)
-{
-       misc_deregister(&softdog_miscdev);
-}
-
-module_init(watchdog_init);
-module_exit(watchdog_exit);
diff --git a/drivers/char/w83877f_wdt.c b/drivers/char/w83877f_wdt.c
deleted file mode 100644 (file)
index 6674967..0000000
+++ /dev/null
@@ -1,366 +0,0 @@
-/*
- *     W83877F Computer Watchdog Timer driver for Linux 2.4.x
- *
- *      Based on acquirewdt.c by Alan Cox,
- *           and sbc60xxwdt.c by Jakob Oestergaard <jakob@ostenfeld.dk>
- *     
- *     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.
- *     
- *     The authors do NOT admit liability nor provide warranty for 
- *     any of this software. This material is provided "AS-IS" in 
- *      the hope that it may be useful for others.
- *
- *     (c) Copyright 2001    Scott Jennings <linuxdrivers@oro.net>
- *
- *           4/19 - 2001      [Initial revision]
- *           9/27 - 2001      Added spinlocking
- *
- *
- *  Theory of operation:
- *  A Watchdog Timer (WDT) is a hardware circuit that can 
- *  reset the computer system in case of a software fault.
- *  You probably knew that already.
- *
- *  Usually a userspace daemon will notify the kernel WDT driver
- *  via the /proc/watchdog special device file that userspace is
- *  still alive, at regular intervals.  When such a notification
- *  occurs, the driver will usually tell the hardware watchdog
- *  that everything is in order, and that the watchdog should wait
- *  for yet another little while to reset the system.
- *  If userspace fails (RAM error, kernel bug, whatever), the
- *  notifications cease to occur, and the hardware watchdog will
- *  reset the system (causing a reboot) after the timeout occurs.
- *
- *  This WDT driver is different from most other Linux WDT
- *  drivers in that the driver will ping the watchdog by itself,
- *  because this particular WDT has a very short timeout (1.6
- *  seconds) and it would be insane to count on any userspace
- *  daemon always getting scheduled within that time frame.
- */
-
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/jiffies.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/smp_lock.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-
-#define OUR_NAME "w83877f_wdt"
-
-#define ENABLE_W83877F_PORT 0x3F0
-#define ENABLE_W83877F 0x87
-#define DISABLE_W83877F 0xAA
-#define WDT_PING 0x443
-#define WDT_REGISTER 0x14
-#define WDT_ENABLE 0x9C
-#define WDT_DISABLE 0x8C
-
-/*
- * The W83877F seems to be fixed at 1.6s timeout (at least on the
- * EMACS PC-104 board I'm using). If we reset the watchdog every
- * ~250ms we should be safe.  */
-
-#define WDT_INTERVAL (HZ/4+1)
-
-/*
- * We must not require too good response from the userspace daemon.
- * Here we require the userspace daemon to send us a heartbeat
- * char to /dev/watchdog every 30 seconds.
- */
-
-#define WDT_HEARTBEAT (HZ * 30)
-
-static void wdt_timer_ping(unsigned long);
-static struct timer_list timer;
-static unsigned long next_heartbeat;
-static unsigned long wdt_is_open;
-static int wdt_expect_close;
-static spinlock_t wdt_spinlock;
-
-/*
- *     Whack the dog
- */
-
-static void wdt_timer_ping(unsigned long data)
-{
-       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
-        * we agree to ping the WDT 
-        */
-       if(time_before(jiffies, next_heartbeat)) 
-       {
-               /* Ping the WDT */
-               spin_lock(&wdt_spinlock);
-
-               /* Ping the WDT by reading from WDT_PING */
-               inb_p(WDT_PING);
-
-               /* Re-set the timer interval */
-               timer.expires = jiffies + WDT_INTERVAL;
-               add_timer(&timer);
-
-               spin_unlock(&wdt_spinlock);
-
-       } else {
-               printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n");
-       }
-}
-
-/* 
- * Utility routines
- */
-
-static void wdt_change(int writeval)
-{
-       unsigned long flags;
-       spin_lock_irqsave(&wdt_spinlock, flags);
-
-       /* buy some time */
-       inb_p(WDT_PING);
-
-       /* make W83877F available */
-       outb_p(ENABLE_W83877F,  ENABLE_W83877F_PORT);
-       outb_p(ENABLE_W83877F,  ENABLE_W83877F_PORT);
-
-       /* enable watchdog */
-       outb_p(WDT_REGISTER,    ENABLE_W83877F_PORT);
-       outb_p(writeval,        ENABLE_W83877F_PORT+1);
-
-       /* lock the W8387FF away */
-       outb_p(DISABLE_W83877F, ENABLE_W83877F_PORT);
-
-       spin_unlock_irqrestore(&wdt_spinlock, flags);
-}
-
-static void wdt_startup(void)
-{
-       next_heartbeat = jiffies + WDT_HEARTBEAT;
-
-       /* Start the timer */
-       timer.expires = jiffies + WDT_INTERVAL; 
-       add_timer(&timer);
-
-       wdt_change(WDT_ENABLE);
-
-       printk(OUR_NAME ": Watchdog timer is now enabled.\n");  
-}
-
-static void wdt_turnoff(void)
-{
-       /* Stop the timer */
-       del_timer(&timer);
-
-       wdt_change(WDT_DISABLE);
-
-       printk(OUR_NAME ": Watchdog timer is now disabled...\n");
-}
-
-
-/*
- * /dev/watchdog handling
- */
-
-static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos)
-{
-       /* We can't seek */
-       if(ppos != &file->f_pos)
-               return -ESPIPE;
-
-       /* See if we got the magic character */
-       if(count) 
-       {
-               size_t ofs;
-
-               /* note: just in case someone wrote the magic character
-                * five months ago... */
-               wdt_expect_close = 0;
-
-               /* now scan */
-               for(ofs = 0; ofs != count; ofs++)
-               {
-                       char c;
-                       if (get_user(c, buf + ofs))
-                               return -EFAULT;
-                       if (c == 'V')
-                               wdt_expect_close = 1;
-               }
-
-               /* someone wrote to us, we should restart timer */
-               next_heartbeat = jiffies + WDT_HEARTBEAT;
-               return 1;
-       };
-       return 0;
-}
-
-static ssize_t fop_read(struct file * file, char * buf, size_t count, loff_t * ppos)
-{
-       /* No can do */
-       return -EINVAL;
-}
-
-static int fop_open(struct inode * inode, struct file * file)
-{
-       switch(minor(inode->i_rdev)) 
-       {
-               case WATCHDOG_MINOR:
-                       /* Just in case we're already talking to someone... */
-                       if(test_and_set_bit(0, &wdt_is_open)) {
-                               return -EBUSY;
-                       }
-                       /* Good, fire up the show */
-                       wdt_startup();
-                       return 0;
-
-               default:
-                       return -ENODEV;
-       }
-}
-
-static int fop_close(struct inode * inode, struct file * file)
-{
-       if(minor(inode->i_rdev) == WATCHDOG_MINOR) 
-       {
-               if(wdt_expect_close)
-                       wdt_turnoff();
-               else {
-                       del_timer(&timer);
-                       printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n");
-               }
-       }
-       wdt_is_open = 0;
-       return 0;
-}
-
-static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       static struct watchdog_info ident=
-       {
-               0,
-               1,
-               "W83877F"
-       };
-       
-       switch(cmd)
-       {
-               default:
-                       return -ENOIOCTLCMD;
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
-               case WDIOC_KEEPALIVE:
-                       next_heartbeat = jiffies + WDT_HEARTBEAT;
-                       return 0;
-       }
-}
-
-static struct file_operations wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .read           = fop_read,
-       .write          = fop_write,
-       .open           = fop_open,
-       .release        = fop_close,
-       .ioctl          = fop_ioctl
-};
-
-static struct miscdevice wdt_miscdev = {
-       WATCHDOG_MINOR,
-       "watchdog",
-       &wdt_fops
-};
-
-/*
- *     Notifier for system down
- */
-
-static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT) 
-               wdt_turnoff();
-       return NOTIFY_DONE;
-}
-/*
- *     The WDT needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off. 
- */
-static struct notifier_block wdt_notifier=
-{
-       wdt_notify_sys,
-       0,
-       0
-};
-
-static void __exit w83877f_wdt_unload(void)
-{
-       wdt_turnoff();
-
-       /* Deregister */
-       misc_deregister(&wdt_miscdev);
-
-       unregister_reboot_notifier(&wdt_notifier);
-       release_region(WDT_PING,1);
-       release_region(ENABLE_W83877F_PORT,2);
-}
-
-static int __init w83877f_wdt_init(void)
-{
-       int rc = -EBUSY;
-
-       spin_lock_init(&wdt_spinlock);
-
-       if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT"))
-               goto err_out;
-       if (!request_region(WDT_PING, 1, "W8387FF WDT"))
-               goto err_out_region1;
-
-       init_timer(&timer);
-       timer.function = wdt_timer_ping;
-       timer.data = 0;
-
-       rc = misc_register(&wdt_miscdev);
-       if (rc)
-               goto err_out_region2;
-
-       rc = register_reboot_notifier(&wdt_notifier);
-       if (rc)
-               goto err_out_miscdev;
-
-       printk(KERN_INFO OUR_NAME ": WDT driver for W83877F initialised.\n");
-       
-       return 0;
-
-err_out_miscdev:
-       misc_deregister(&wdt_miscdev);
-err_out_region2:
-       release_region(WDT_PING,1);
-err_out_region1:
-       release_region(ENABLE_W83877F_PORT,2);
-err_out:
-       return rc;
-}
-
-module_init(w83877f_wdt_init);
-module_exit(w83877f_wdt_unload);
-
-MODULE_AUTHOR("Scott and Bill Jennings");
-MODULE_DESCRIPTION("Driver for watchdog timer in w83877f chip");
-MODULE_LICENSE("GPL");
-EXPORT_NO_SYMBOLS;
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
new file mode 100644 (file)
index 0000000..d329cdc
--- /dev/null
@@ -0,0 +1,286 @@
+#
+# Character device configuration
+#
+
+menu "Watchdog Cards"
+
+config WATCHDOG
+       bool "Watchdog Timer Support"
+       ---help---
+         If you say Y here (and to one of the following options) and create a
+         character special file /dev/watchdog with major number 10 and minor
+         number 130 using mknod ("man mknod"), you will get a watchdog, i.e.:
+         subsequently opening the file and then failing to write to it for
+         longer than 1 minute will result in rebooting the machine. This
+         could be useful for a networked machine that needs to come back
+         online as fast as possible after a lock-up. There's both a watchdog
+         implementation entirely in software (which can sometimes fail to
+         reboot the machine) and a driver for hardware watchdog boards, which
+         are more robust and can also keep track of the temperature inside
+         your computer. For details, read <file:Documentation/watchdog.txt>
+         in the kernel source.
+
+         The watchdog is usually used together with the watchdog daemon
+         which is available from
+         <ftp://ibiblio.org/pub/Linux/system/daemons/watchdog/>. This daemon can
+         also monitor NFS connections and can reboot the machine when the process
+         table is full.
+
+         If unsure, say N.
+
+config WATCHDOG_NOWAYOUT
+       bool "Disable watchdog shutdown on close"
+       depends on WATCHDOG
+       help
+         The default watchdog behaviour (which you get if you say N here) is
+         to stop the timer if the process managing it closes the file
+         /dev/watchdog. It's always remotely possible that this process might
+         get killed. If you say Y here, the watchdog cannot be stopped once
+         it has been started.
+
+config SOFT_WATCHDOG
+       tristate "Software watchdog"
+       depends on WATCHDOG
+       help
+         A software monitoring watchdog. This will fail to reboot your system
+         from some situations that the hardware watchdog will recover
+         from. Equally it's a lot cheaper to install.
+
+         This driver is also available as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want).
+         If you want to compile it as a module, say M here and read
+         <file:Documentation/modules.txt>. The module will be called
+         softdog.o.
+
+config WDT
+       tristate "WDT Watchdog timer"
+       depends on WATCHDOG
+       ---help---
+         If you have a WDT500P or WDT501P watchdog board, say Y here,
+         otherwise N. It is not possible to probe for this board, which means
+         that you have to inform the kernel about the IO port and IRQ using
+         the "wdt=" kernel option (try "man bootparam" or see the
+         documentation of your boot loader (lilo or loadlin) about how to
+         pass options to the kernel at boot time).
+
+         If you want to compile this as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want),
+         say M here and read <file:Documentation/modules.txt>.  The module
+         will be called wdt.o.
+
+config WDTPCI
+       tristate "WDT PCI Watchdog timer"
+       depends on WATCHDOG
+       ---help---
+         If you have a PCI WDT500/501 watchdog board, say Y here, otherwise
+         N.  It is not possible to probe for this board, which means that you
+         have to inform the kernel about the IO port and IRQ using the "wdt="
+         kernel option (try "man bootparam" or see the documentation of your
+         boot loader (lilo or loadlin) about how to pass options to the
+         kernel at boot time).
+
+         If you want to compile this as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want),
+         say M here and read <file:Documentation/modules.txt>.  The module
+         will be called wdt_pci.o.
+
+config WDT_501
+       bool "WDT501 features"
+       depends on WDT
+       help
+         Saying Y here and creating a character special file /dev/temperature
+         with major number 10 and minor number 131 ("man mknod") will give
+         you a thermometer inside your computer: reading from
+         /dev/temperature yields one byte, the temperature in degrees
+         Fahrenheit. This works only if you have a WDT501P watchdog board
+         installed.
+
+config WDT_501_FAN
+       bool "Fan Tachometer"
+       depends on WDT_501
+       help
+         Enable the Fan Tachometer on the WDT501. Only do this if you have a
+         fan tachometer actually set up.
+
+config PCWATCHDOG
+       tristate "Berkshire Products PC Watchdog"
+       depends on WATCHDOG
+       ---help---
+         This is the driver for the Berkshire Products PC Watchdog card.
+         This card simply watches your kernel to make sure it doesn't freeze,
+         and if it does, it reboots your computer after a certain amount of
+         time. This driver is like the WDT501 driver but for different
+         hardware. Please read <file:Documentation/pcwd-watchdog.txt>. The PC
+         watchdog cards can be ordered from <http://www.berkprod.com/>.
+
+         This driver is also available as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want).
+         The module is called pcwd.o. If you want to compile it as a module,
+         say M here and read <file:Documentation/modules.txt>.
+
+         Most people will say N.
+
+config ACQUIRE_WDT
+       tristate "Acquire SBC Watchdog Timer"
+       depends on WATCHDOG
+       ---help---
+         This is the driver for the hardware watchdog on the PSC-6x86 Single
+         Board Computer produced by Acquire Inc (and others).  This watchdog
+         simply watches your kernel to make sure it doesn't freeze, and if
+         it does, it reboots your computer after a certain amount of time.
+
+         This driver is like the WDT501 driver but for different hardware.
+         This driver is also available as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want).
+         The module is called pscwdt.o.  If you want to compile it as a
+         module, say M here and read <file:Documentation/modules.txt>.  Most
+         people will say N.
+
+config ADVANTECH_WDT
+       tristate "Advantech SBC Watchdog Timer"
+       depends on WATCHDOG
+       help
+         If you are configuring a Linux kernel for the Advantech single-board
+         computer, say `Y' here to support its built-in watchdog timer
+         feature.  See the help for CONFIG_WATCHDOG for discussion.
+
+config 21285_WATCHDOG
+       tristate "DC21285 watchdog"
+       depends on WATCHDOG && FOOTBRIDGE
+       help
+         The Intel Footbridge chip contains a builtin watchdog circuit. Say Y
+         here if you wish to use this. Alternatively say M to compile the
+         driver as a module, which will be called wdt285.o.
+
+         This driver does not work on all machines. In particular, early CATS
+         boards have hardware problems that will cause the machine to simply
+         lock up if the watchdog fires.
+
+         "If in doubt, leave it out" - say N.
+
+config 977_WATCHDOG
+       tristate "NetWinder WB83C977 watchdog"
+       depends on WATCHDOG && FOOTBRIDGE && ARCH_NETWINDER
+       help
+         Say Y here to include support for the WB977 watchdog included in
+         NetWinder machines. Alternatively say M to compile the driver as
+         a module, which will be called wdt977.o.
+
+         Not sure? It's safe to say N.
+
+config EUROTECH_WDT
+       tristate "Eurotech CPU-1220/1410 Watchdog Timer"
+       depends on WATCHDOG
+       help
+         Enable support for the watchdog timer on the Eurotech CPU-1220 and
+         CPU-1410 cards.  These are PC/104 SBCs. Spec sheets and product
+         information are at <http://www.eurotech.it/>.
+
+config IB700_WDT
+       tristate "IB700 SBC Watchdog Timer"
+       depends on WATCHDOG
+       ---help---
+         This is the driver for the hardware watchdog on the IB700 Single
+         Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog
+         simply watches your kernel to make sure it doesn't freeze, and if
+         it does, it reboots your computer after a certain amount of time.
+
+         This driver is like the WDT501 driver but for slightly different hardware.
+
+         This driver is also available as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want).
+         The module is called ib700wdt.o. If you want to compile it as a
+         module, say M here and read Documentation/modules.txt. Most people
+         will say N.
+
+config I810_TCO
+       tristate "Intel i810 TCO timer / Watchdog"
+       depends on WATCHDOG
+       ---help---
+         Hardware driver for the TCO timer built into the Intel i810 and i815
+         chipset family.  The TCO (Total Cost of Ownership) timer is a
+         watchdog timer that will reboot the machine after its second
+         expiration. The expiration time can be configured by commandline
+         argument "i810_margin=<n>" where <n> is the counter initial value.
+         It is decremented every 0.6 secs, the default is 50 which gives a
+         timeout of 30 seconds and one minute until reset.
+
+         On some motherboards the driver may fail to reset the chipset's
+         NO_REBOOT flag which prevents the watchdog from rebooting the
+         machine. If this is the case you will get a kernel message like
+         "i810tco init: failed to reset NO_REBOOT flag".
+
+         If you want to compile this as a module, say M and read
+         <file:Documentation/modules.txt>.  The module will be called
+         i810-tco.o.
+
+config MIXCOMWD
+       tristate "Mixcom Watchdog"
+       depends on WATCHDOG
+       ---help---
+         This is a driver for the Mixcom hardware watchdog cards.  This
+         watchdog simply watches your kernel to make sure it doesn't freeze,
+         and if it does, it reboots your computer after a certain amount of
+         time.
+
+         This driver is also available as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want).
+         The module is called mixcomwd.o.  If you want to compile it as a
+         module, say M here and read <file:Documentation/modules.txt>.  Most
+         people will say N.
+
+config SCx200_WDT
+       tristate "NatSemi SCx200 Watchdog"
+       depends on WATCHDOG
+       help
+         Enable the built-in watchdog timer support on the National 
+         Semiconductor SCx200 processors.
+
+         If compiled as a module, it will be called scx200_watchdog.o.
+
+config 60XX_WDT
+       tristate "SBC-60XX Watchdog Timer"
+       depends on WATCHDOG
+       help
+         This driver can be used with the watchdog timer found on some
+         single board computers, namely the 6010 PII based computer.
+         It may well work with other cards.  It reads port 0x443 to enable
+         and re-set the watchdog timer, and reads port 0x45 to disable
+         the watchdog.  If you have a card that behave in similar ways,
+         you can probably make this driver work with your card as well.
+
+         You can compile this driver directly into the kernel, or use
+         it as a module.  The module will be called sbc60xxwdt.o.
+
+config W83877F_WDT
+       tristate "W83877F (EMACS) Watchdog Timer"
+       depends on WATCHDOG
+       ---help---
+         This is the driver for the hardware watchdog on the W83877F chipset
+         as used in EMACS PC-104 motherboards (and likely others).  This
+         watchdog simply watches your kernel to make sure it doesn't freeze,
+         and if it does, it reboots your computer after a certain amount of
+         time.
+
+         This driver is also available as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want).
+         The module is called mixcomwd.o.  If you want to compile it as a
+         module, say M here and read <file:Documentation/modules.txt>.  Most
+         people will say N.
+
+config MACHZ_WDT
+       tristate "ZF MachZ Watchdog"
+       depends on WATCHDOG
+       ---help---
+         If you are using a ZF Micro MachZ processor, say Y here, otherwise
+         N.  This is the driver for the watchdog timer builtin on that
+         processor using ZF-Logic interface.  This watchdog simply watches
+         your kernel to make sure it doesn't freeze, and if it does, it
+         reboots your computer after a certain amount of time.
+
+         This driver is also available as a module ( = code which can be
+         inserted in and removed from the running kernel whenever you want).
+         The module is called machzwd.o.  If you want to compile it as a
+         module, say M here and read <file:Documentation/modules.txt>.
+
+endmenu
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
new file mode 100644 (file)
index 0000000..c1cbf47
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# Makefile for the kernel character device drivers.
+#
+
+# Only one watchdog can succeed. We probe the hardware watchdog
+# drivers first, then the softdog driver.  This means if your hardware
+# watchdog dies or is 'borrowed' for some reason the software watchdog
+# still gives you some cover.
+
+watchdog-$(CONFIG_PCWATCHDOG) += pcwd.o
+watchdog-$(CONFIG_ACQUIRE_WDT) += acquirewdt.o
+watchdog-$(CONFIG_ADVANTECH_WDT) += advantechwdt.o
+watchdog-$(CONFIG_IB700_WDT) += ib700wdt.o
+watchdog-$(CONFIG_MIXCOMWD) += mixcomwd.o
+watchdog-$(CONFIG_SCx200_WDT) += scx200_wdt.o
+watchdog-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
+watchdog-$(CONFIG_WDT) += wdt.o
+watchdog-$(CONFIG_WDTPCI) += wdt_pci.o
+watchdog-$(CONFIG_21285_WATCHDOG) += wdt285.o
+watchdog-$(CONFIG_977_WATCHDOG) += wdt977.o
+watchdog-$(CONFIG_I810_TCO) += i810-tco.o
+watchdog-$(CONFIG_MACHZ_WDT) += machzwd.o
+watchdog-$(CONFIG_SH_WDT) += shwdt.o
+watchdog-$(CONFIG_EUROTECH_WDT) += eurotechwdt.o
+watchdog-$(CONFIG_SOFT_WATCHDOG) += softdog.o
+
+include $(TOPDIR)/Rules.make
diff --git a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c
new file mode 100644 (file)
index 0000000..3a0ecbc
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+ *     Acquire Single Board Computer Watchdog Timer driver for Linux 2.1.x
+ *
+ *      Based on wdt.c. Original copyright messages:
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     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.       
+ *
+ *     (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>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+
+static int acq_is_open;
+static spinlock_t acq_lock;
+
+/*
+ *     You must set these - there is no sane way to probe for this board.
+ */
+#define WDT_STOP 0x43
+#define WDT_START 0x443
+
+#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 void acq_ping(void)
+{
+       /* Write a watchdog value */
+       inb_p(WDT_START);
+}
+
+static ssize_t acq_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)
+       {
+               acq_ping();
+               return 1;
+       }
+       return 0;
+}
+
+static ssize_t acq_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+       return -EINVAL;
+}
+
+
+
+static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       static struct watchdog_info ident=
+       {
+               WDIOF_KEEPALIVEPING, 1, "Acquire WDT"
+       };
+       
+       switch(cmd)
+       {
+       case WDIOC_GETSUPPORT:
+         if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+           return -EFAULT;
+         break;
+         
+       case WDIOC_GETSTATUS:
+         if (copy_to_user((int *)arg, &acq_is_open,  sizeof(int)))
+           return -EFAULT;
+         break;
+
+       case WDIOC_KEEPALIVE:
+         acq_ping();
+         break;
+
+       default:
+         return -ENOTTY;
+       }
+       return 0;
+}
+
+static int acq_open(struct inode *inode, struct file *file)
+{
+       switch(minor(inode->i_rdev))
+       {
+               case WATCHDOG_MINOR:
+                       spin_lock(&acq_lock);
+                       if(acq_is_open)
+                       {
+                               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);
+                       return 0;
+               default:
+                       return -ENODEV;
+       }
+}
+
+static int acq_close(struct inode *inode, struct file *file)
+{
+       if(minor(inode->i_rdev)==WATCHDOG_MINOR)
+       {
+               spin_lock(&acq_lock);
+               if (!nowayout) {
+                       inb_p(WDT_STOP);
+               }
+               acq_is_open=0;
+               spin_unlock(&acq_lock);
+       }
+       return 0;
+}
+
+/*
+ *     Notifier for system down
+ */
+
+static int acq_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT)
+       {
+               /* Turn the card off */
+               inb_p(WDT_STOP);
+       }
+       return NOTIFY_DONE;
+}
+/*
+ *     Kernel Interfaces
+ */
+static struct file_operations acq_fops = {
+       .owner          = THIS_MODULE,
+       .read           = acq_read,
+       .write          = acq_write,
+       .ioctl          = acq_ioctl,
+       .open           = acq_open,
+       .release        = acq_close,
+};
+
+static struct miscdevice acq_miscdev=
+{
+       WATCHDOG_MINOR,
+       "watchdog",
+       &acq_fops
+};
+
+
+/*
+ *     The WDT card needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off. 
+ */
+static struct notifier_block acq_notifier=
+{
+       acq_notify_sys,
+       NULL,
+       0
+};
+
+static int __init acq_init(void)
+{
+       printk("WDT driver for Acquire single board computer initialising.\n");
+
+       spin_lock_init(&acq_lock);
+       if (misc_register(&acq_miscdev))
+               return -ENODEV;
+       if (!request_region(WDT_STOP, 1, "Acquire WDT"))
+               {
+               misc_deregister(&acq_miscdev);
+               return -EIO;
+               }
+       if (!request_region(WDT_START, 1, "Acquire WDT"))
+               {
+               release_region(WDT_STOP, 1);
+               misc_deregister(&acq_miscdev);
+               return -EIO;
+               }
+
+       register_reboot_notifier(&acq_notifier);
+       return 0;
+}
+       
+static void __exit acq_exit(void)
+{
+       misc_deregister(&acq_miscdev);
+       unregister_reboot_notifier(&acq_notifier);
+       release_region(WDT_STOP,1);
+       release_region(WDT_START,1);
+}
+
+module_init(acq_init);
+module_exit(acq_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c
new file mode 100644 (file)
index 0000000..226e3a7
--- /dev/null
@@ -0,0 +1,280 @@
+/*
+ *     Advantech Single Board Computer WDT driver for Linux 2.4.x
+ *
+ *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ *     Based on acquirewdt.c which is based on wdt.c.
+ *     Original copyright messages:
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     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.       
+ *
+ *     (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>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+
+static int advwdt_is_open;
+static spinlock_t advwdt_lock;
+
+/*
+ *     You must set these - there is no sane way to probe for this board.
+ *
+ *     To enable or restart, write the timeout value in seconds (1 to 63)
+ *     to I/O port WDT_START.  To disable, read I/O port WDT_STOP.
+ *     Both are 0x443 for most boards (tested on a PCA-6276VE-00B1), but
+ *     check your manual (at least the PCA-6159 seems to be different -
+ *     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
+ */
+#define WDT_STOP 0x443
+#define WDT_START 0x443
+
+#define WD_TIMO 60             /* 1 minute */
+
+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 void
+advwdt_ping(void)
+{
+       /* Write a watchdog value */
+       outb_p(timeout, WDT_START);
+}
+
+static ssize_t
+advwdt_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) {
+               advwdt_ping();
+               return 1;
+       }
+       return 0;
+}
+
+static ssize_t
+advwdt_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+       return -EINVAL;
+}
+
+static int
+advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+         unsigned long arg)
+{
+       static struct watchdog_info ident = {
+               WDIOF_KEEPALIVEPING, 1, "Advantech WDT"
+       };
+       
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+         if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+           return -EFAULT;
+         break;
+         
+       case WDIOC_GETSTATUS:
+         if (copy_to_user((int *)arg, &advwdt_is_open,  sizeof(int)))
+           return -EFAULT;
+         break;
+
+       case WDIOC_KEEPALIVE:
+         advwdt_ping();
+         break;
+
+       default:
+         return -ENOTTY;
+       }
+       return 0;
+}
+
+static int
+advwdt_open(struct inode *inode, struct file *file)
+{
+       switch (minor(inode->i_rdev)) {
+               case WATCHDOG_MINOR:
+                       spin_lock(&advwdt_lock);
+                       if (advwdt_is_open) {
+                               spin_unlock(&advwdt_lock);
+                               return -EBUSY;
+                       }
+                       if (nowayout) {
+                               MOD_INC_USE_COUNT;
+                       }
+                       /*
+                        *      Activate 
+                        */
+        
+                       advwdt_is_open = 1;
+                       advwdt_ping();
+                       spin_unlock(&advwdt_lock);
+                       return 0;
+               default:
+                       return -ENODEV;
+       }
+}
+
+static int
+advwdt_close(struct inode *inode, struct file *file)
+{
+       if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
+               spin_lock(&advwdt_lock);
+               if (!nowayout) {
+                       inb_p(WDT_STOP);
+               }
+               advwdt_is_open = 0;
+               spin_unlock(&advwdt_lock);
+       }
+       return 0;
+}
+
+/*
+ *     Notifier for system down
+ */
+
+static int
+advwdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT) {
+               /* Turn the WDT off */
+               inb_p(WDT_STOP);
+       }
+       return NOTIFY_DONE;
+}
+/*
+ *     Kernel Interfaces
+ */
+static struct file_operations advwdt_fops = {
+       .owner          = THIS_MODULE,
+       .read           = advwdt_read,
+       .write          = advwdt_write,
+       .ioctl          = advwdt_ioctl,
+       .open           = advwdt_open,
+       .release        = advwdt_close,
+};
+
+static struct miscdevice advwdt_miscdev = {
+       WATCHDOG_MINOR,
+       "watchdog",
+       &advwdt_fops
+};
+
+/*
+ *     The WDT needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off. 
+ */
+static struct notifier_block advwdt_notifier = {
+       advwdt_notify_sys,
+       NULL,
+       0
+};
+
+static void __init
+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);
+       }
+}
+
+static int __init
+advwdt_init(void)
+{
+       printk("WDT driver for Advantech single board computer initialising.\n");
+
+       advwdt_validate_timeout();
+       spin_lock_init(&advwdt_lock);
+       if (misc_register(&advwdt_miscdev))
+               return -ENODEV;
+#if WDT_START != WDT_STOP
+       if (!request_region(WDT_STOP, 1, "Advantech WDT")) {
+               misc_deregister(&advwdt_miscdev);
+               return -EIO;
+       }
+#endif
+       if (!request_region(WDT_START, 1, "Advantech WDT")) {
+               misc_deregister(&advwdt_miscdev);
+#if WDT_START != WDT_STOP
+               release_region(WDT_STOP, 1);
+#endif
+               return -EIO;
+       }
+       register_reboot_notifier(&advwdt_notifier);
+       return 0;
+}
+
+static void __exit
+advwdt_exit(void)
+{
+       misc_deregister(&advwdt_miscdev);
+       unregister_reboot_notifier(&advwdt_notifier);
+#if WDT_START != WDT_STOP
+       release_region(WDT_STOP,1);
+#endif
+       release_region(WDT_START,1);
+}
+
+module_init(advwdt_init);
+module_exit(advwdt_exit);
+
+MODULE_LICENSE("GPL");
+
+/* end of advantechwdt.c */
+
diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c
new file mode 100644 (file)
index 0000000..6ce0e3c
--- /dev/null
@@ -0,0 +1,501 @@
+/*
+ *     Eurotech CPU-1220/1410 on board WDT driver for Linux 2.4.x
+ *
+ *     (c) Copyright 2001 Ascensit <support@ascensit.com>
+ *     (c) Copyright 2001 Rodolfo Giometti <giometti@ascensit.com>
+ *
+ *     Based on wdt.c.
+ *     Original copyright messages:
+ *
+ *      (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                              http://www.redhat.com
+ *
+ *      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.
+ *
+ *      (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>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+static int eurwdt_is_open;
+static spinlock_t eurwdt_lock;
+/*
+ *      You must set these - there is no sane way to probe for this board.
+ *      You can use wdt=x,y to set these now.
+ */
+static int io = 0x3f0;
+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)");
+
+
+/*
+ * Some symbolic names 
+ */
+
+#define WDT_CTRL_REG           0x30
+#define WDT_OUTPIN_CFG         0xe2
+   #define WDT_EVENT_INT          0x00
+   #define WDT_EVENT_REBOOT       0x08
+#define WDT_UNIT_SEL           0xf1
+   #define WDT_UNIT_SECS          0x80
+#define WDT_TIMEOUT_VAL                0xf2
+#define WDT_TIMER_CFG          0xf3
+
+#ifndef MODULE
+
+/**
+ *      eurwdt_setup:
+ *      @str: command line string
+ *
+ *      Setup options. The board isn't really probe-able so we have to
+ *      get the user to tell us the configuration. Sane people build it
+ *      modular but the others come here.
+ */
+static int __init eurwdt_setup(char *str)
+{
+   int ints[4];
+   str = get_options (str, ARRAY_SIZE(ints), ints);
+   if (ints[0] > 0) {
+      io = ints[1];
+      if (ints[0] > 1)
+         irq = ints[2];
+   }
+   return 1;
+}
+__setup("wdt=", eurwdt_setup);
+
+#endif /* !MODULE */
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "Eurotech WDT io port (default=0x3f0)");
+MODULE_PARM(irq, "i");
+MODULE_PARM_DESC(irq, "Eurotech WDT irq (default=10)");
+MODULE_PARM(ev, "s");
+MODULE_PARM_DESC(ev, "Eurotech WDT event type (default is `reboot')");
+
+
+/*
+ *      Programming support
+ */
+
+static void __init 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);
+       }
+}
+
+static inline void eurwdt_write_reg(u8 index, u8 data)
+{
+   outb(index, io);
+   outb(data, io+1);
+}
+
+static inline void eurwdt_lock_chip(void)
+{
+   outb(0xaa, io);
+}
+
+static inline void eurwdt_unlock_chip(void)
+{
+   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);
+}
+
+static inline void eurwdt_disable_timer(void)
+{
+   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) ?
+                                    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);
+
+   eurwdt_write_reg(WDT_UNIT_SEL, WDT_UNIT_SECS);   /* we use seconds */
+   eurwdt_set_timeout(0);                           /* the default timeout */ 
+}
+
+
+/*
+ *      Kernel methods.
+ */
+void eurwdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+   printk(KERN_CRIT "timeout WDT timeout\n");
+#ifdef ONLY_TESTING
+   printk(KERN_CRIT "Would Reboot.\n");
+#else
+   printk(KERN_CRIT "Initiating system reboot.\n");
+   machine_restart(NULL);
+#endif
+}
+
+
+/**
+ *      eurwdt_ping:
+ *
+ *      Reload counter one with the watchdog timeout.
+ */
+static void eurwdt_ping(void)
+{
+   /* Write the watchdog default value */
+   eurwdt_set_timeout(timeout);
+}
+/**
+ *      eurwdt_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 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) {
+      eurwdt_ping();   /* the default timeout */
+      return 1;
+   }
+
+   return 0;
+}
+
+/**
+ *      eurwdt_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 eurwdt_ioctl(struct inode *inode, struct file *file,
+        unsigned int cmd, unsigned long arg)
+{
+   static struct watchdog_info ident = {
+       .options          = WDIOF_CARDRESET,
+       .firmware_version = 1,
+       .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_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;
+
+         timeout = time; 
+         eurwdt_set_timeout(time); 
+         return 0;
+   }
+}
+
+/**
+ *      eurwdt_open:
+ *      @inode: inode of device
+ *      @file: file handle to device
+ *
+ *      The misc device has been opened. The watchdog device is single
+ *      open and on opening we load the counter.
+ */
+static int eurwdt_open(struct inode *inode, struct file *file)
+{
+   switch (minor(inode->i_rdev)) {
+      case WATCHDOG_MINOR:
+         spin_lock(&eurwdt_lock);
+         if (eurwdt_is_open) {
+            spin_unlock(&eurwdt_lock);
+            return -EBUSY;
+         }
+        if (nowayout) {
+                MOD_INC_USE_COUNT;
+        }
+
+         eurwdt_is_open = 1;
+
+         /* Activate the WDT */
+         eurwdt_activate_timer(); 
+            
+         spin_unlock(&eurwdt_lock);
+
+         MOD_INC_USE_COUNT;
+
+         return 0;
+
+         case TEMP_MINOR:
+            return 0;
+
+         default:
+            return -ENODEV;
+   }
+}
+/**
+ *      eurwdt_release:
+ *      @inode: inode to board
+ *      @file: file handle to board
+ *
+ *      The watchdog has a configurable API. There is a religious dispute
+ *      between people who want their watchdog to be able to shut down and
+ *      those who want to be sure if the watchdog manager dies the machine
+ *      reboots. In the former case we disable the counters, in the latter
+ *      case you have to open it again very soon.
+ */
+static int eurwdt_release(struct inode *inode, struct file *file)
+{
+   if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
+          if (!nowayout) {
+                  eurwdt_disable_timer();
+          }
+          eurwdt_is_open = 0;
+
+          MOD_DEC_USE_COUNT;
+   }
+
+   return 0;
+}
+/**
+ *      eurwdt_notify_sys:
+ *      @this: our notifier block
+ *      @code: the event being reported
+ *      @unused: unused
+ *
+ *      Our notifier is called on system shutdowns. We want to turn the card
+ *      off at reboot otherwise the machine will reboot again during memory
+ *      test or worse yet during the following fsck. This would suck, in fact
+ *      trust me - if it happens it does suck.
+ */
+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;
+}
+/*
+ *      Kernel Interfaces
+ */
+static struct file_operations eurwdt_fops = {
+        .owner          = THIS_MODULE,
+        .llseek         = no_llseek,
+        .write          = eurwdt_write,
+        .ioctl          = eurwdt_ioctl,
+        .open           = eurwdt_open,
+        .release        = eurwdt_release,
+};
+
+static struct miscdevice eurwdt_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &eurwdt_fops
+};
+/*
+ *      The WDT card needs to learn about soft shutdowns in order to
+ *      turn the timebomb registers off.
+ */
+static struct notifier_block eurwdt_notifier = {
+       .notifier_call = eurwdt_notify_sys,
+};
+/**
+ *      cleanup_module:
+ *
+ *      Unload the watchdog. You cannot do this with any file handles open.
+ *      If your watchdog is set to continue ticking on close and you unload
+ *      it, well it keeps ticking. We won't get the interrupt but the board
+ *      will not touch PC memory so all is fine. You just have to load a new
+ *      module in 60 seconds or reboot.
+ */
+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_init:
+ *
+ *      Set up the WDT watchdog board. After grabbing the resources 
+ *      we require we need also to unlock the device.
+ *      The open() function will actually kick the board off.
+ */
+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",
+            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"));
+
+   spin_lock_init(&eurwdt_lock);
+
+   out:
+      return ret;
+   outreg:
+      release_region(io, 2);
+
+   outirq:
+      free_irq(irq, NULL);
+
+   outmisc:
+      misc_deregister(&eurwdt_miscdev);
+      goto out;
+}
+module_init(eurwdt_init);
+module_exit(eurwdt_exit);
+MODULE_AUTHOR("Rodolfo Giometti");
+MODULE_DESCRIPTION("Driver for Eurotech CPU-1220/1410 on board watchdog");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/i810-tco.c b/drivers/char/watchdog/i810-tco.c
new file mode 100644 (file)
index 0000000..3697dd0
--- /dev/null
@@ -0,0 +1,431 @@
+/*
+ *     i810-tco 0.05:  TCO timer driver for i8xx chipsets
+ *
+ *     (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
+ *                             http://www.kernelconcepts.de
+ *
+ *     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 kernel concepts nor Nils Faerber admit liability nor provide
+ *     warranty for any of this software. This material is provided
+ *     "AS-IS" and at no charge.
+ *
+ *     (c) Copyright 2000      kernel concepts <nils@kernelconcepts.de>
+ *                             developed for
+ *                              Jentro AG, Haar/Munich (Germany)
+ *
+ *     TCO timer driver for i8xx chipsets
+ *     based on softdog.c by Alan Cox <alan@redhat.com>
+ *
+ *     The TCO timer is implemented in the following I/O controller hubs:
+ *     (See the intel documentation on http://developer.intel.com.)
+ *     82801AA & 82801AB  chip : document number 290655-003, 290677-004,
+ *     82801BA & 82801BAM chip : document number 290687-002, 298242-005,
+ *     82801CA & 82801CAM chip : document number 290716-001, 290718-001,
+ *     82801DB & 82801E   chip : document number 290744-001, 273599-001
+ *
+ *  20000710 Nils Faerber
+ *     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.
+ *  20020224 Joel Becker, Wim Van Sebroeck
+ *     0.04 Support for 82801CA(M) chipset, timer margin needs to be > 3,
+ *          add support for WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT.
+ *  20020412 Rob Radez <rob@osinvestor.com>, Wim Van Sebroeck
+ *     0.05 Fix possible timer_alive race, add expect close support,
+ *          clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and
+ *          WDIOC_SETOPTIONS), made i810tco_getdevice __init,
+ *          removed boot_status, removed tco_timer_read,
+ *          added support for 82801DB and 82801E chipset, general cleanup.
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include "i810-tco.h"
+
+
+/* Module and version information */
+#define TCO_VERSION "0.05"
+#define TCO_MODULE_NAME "i810 TCO timer"
+#define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
+
+/* Default expire timeout */
+#define TIMER_MARGIN   50      /* steps of 0.6sec, 3<n<64. Default is 30 seconds */
+
+static unsigned int ACPIBASE;
+static spinlock_t tco_lock;    /* Guards the hardware */
+
+static int i810_margin = TIMER_MARGIN; /* steps of 0.6sec */
+
+MODULE_PARM(i810_margin, "i");
+MODULE_PARM_DESC(i810_margin, "i810-tco timeout in steps of 0.6sec, 3<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
+ */
+
+static unsigned long timer_alive;
+static char tco_expect_close;
+
+/*
+ * Some TCO specific functions
+ */
+
+
+/*
+ * Start the timer countdown
+ */
+static int tco_timer_start (void)
+{
+       unsigned char val;
+
+       spin_lock(&tco_lock);
+       val = inb (TCO1_CNT + 1);
+       val &= 0xf7;
+       outb (val, TCO1_CNT + 1);
+       val = inb (TCO1_CNT + 1);
+       spin_unlock(&tco_lock);
+       
+       if (val & 0x08)
+               return -1;
+       return 0;
+}
+
+/*
+ * Stop the timer countdown
+ */
+static int tco_timer_stop (void)
+{
+       unsigned char val;
+
+       spin_lock(&tco_lock);
+       val = inb (TCO1_CNT + 1);
+       val |= 0x08;
+       outb (val, TCO1_CNT + 1);
+       val = inb (TCO1_CNT + 1);
+       spin_unlock(&tco_lock);
+       
+       if ((val & 0x08) == 0)
+               return -1;
+       return 0;
+}
+
+/*
+ * Set the timer reload value
+ */
+static int tco_timer_settimer (unsigned char tmrval)
+{
+       unsigned char val;
+
+       /* from the specs: */
+       /* "Values of 0h-3h are ignored and should not be attempted" */
+       if (tmrval > 0x3f || tmrval < 0x04)
+               return -1;
+       
+       spin_lock(&tco_lock);
+       val = inb (TCO1_TMR);
+       val &= 0xc0;
+       val |= tmrval;
+       outb (val, TCO1_TMR);
+       val = inb (TCO1_TMR);
+       spin_unlock(&tco_lock);
+       
+       if ((val & 0x3f) != tmrval)
+               return -1;
+
+       return 0;
+}
+
+/*
+ * Reload (trigger) the timer. Lock is needed so we dont reload it during
+ * a reprogramming event
+ */
+static void tco_timer_reload (void)
+{
+       spin_lock(&tco_lock);
+       outb (0x01, TCO1_RLD);
+       spin_unlock(&tco_lock);
+}
+
+/*
+ *     Allow only one person to hold it open
+ */
+
+static int i810tco_open (struct inode *inode, struct file *file)
+{
+       if (test_and_set_bit(0, &timer_alive))
+               return -EBUSY;
+
+       /*
+        *      Reload and activate timer
+        */
+       tco_timer_reload ();
+       tco_timer_start ();
+       return 0;
+}
+
+static int i810tco_release (struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer.
+        */
+       if (tco_expect_close == 42 && !nowayout) {
+               tco_timer_stop ();
+       } else {
+               tco_timer_reload ();
+               printk(KERN_CRIT TCO_MODULE_NAME ": Unexpected close, not stopping watchdog!\n");
+       }
+       clear_bit(0, &timer_alive);
+       tco_expect_close = 0;
+       return 0;
+}
+
+static ssize_t i810tco_write (struct file *file, const char *data,
+                             size_t len, loff_t * ppos)
+{
+       /*  Can't seek (pwrite) on this device  */
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       /* See if we got the magic character 'V' and reload the timer */
+       if (len) {
+               size_t i;
+
+               tco_expect_close = 0;
+
+               /* scan to see wether or not we got the magic character */
+               for (i = 0; i != len; i++) {
+                       u8 c;
+                       if(get_user(c, data+i))
+                               return -EFAULT;
+                       if (c == 'V')
+                               tco_expect_close = 42;
+               }
+
+               /* someone wrote to us, we should reload the timer */
+               tco_timer_reload ();
+               return 1;
+       }
+       return 0;
+}
+
+static int i810tco_ioctl (struct inode *inode, struct file *file,
+                         unsigned int cmd, unsigned long arg)
+{
+       int new_margin, u_margin;
+       int options, retval = -EINVAL;
+
+       static struct watchdog_info ident = {
+               .options =              WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
+               .firmware_version =     0,
+               .identity =             "i810 TCO timer",
+       };
+       switch (cmd) {
+               default:
+                       return -ENOTTY;
+               case WDIOC_GETSUPPORT:
+                       if (copy_to_user
+                           ((struct watchdog_info *) arg, &ident, sizeof (ident)))
+                               return -EFAULT;
+                       return 0;
+               case WDIOC_GETSTATUS:
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user (0, (int *) arg);
+               case WDIOC_SETOPTIONS:
+                       if (get_user (options, (int *) arg))
+                               return -EFAULT;
+                       if (options & WDIOS_DISABLECARD) {
+                               tco_timer_stop ();
+                               retval = 0;
+                       }
+                       if (options & WDIOS_ENABLECARD) {
+                               tco_timer_reload ();
+                               tco_timer_start ();
+                               retval = 0;
+                       }
+                       return retval;
+               case WDIOC_KEEPALIVE:
+                       tco_timer_reload ();
+                       return 0;
+               case WDIOC_SETTIMEOUT:
+                       if (get_user (u_margin, (int *) arg))
+                               return -EFAULT;
+                       new_margin = (u_margin * 10 + 5) / 6;
+                       if ((new_margin < 4) || (new_margin > 63))
+                               return -EINVAL;
+                       if (tco_timer_settimer ((unsigned char) new_margin))
+                           return -EINVAL;
+                       i810_margin = new_margin;
+                       tco_timer_reload ();
+                       /* Fall */
+               case WDIOC_GETTIMEOUT:
+                       return put_user ((int)(i810_margin * 6 / 10), (int *) arg);
+       }
+}
+
+/*
+ * Data for PCI driver interface
+ *
+ * This data only exists for exporting the supported
+ * PCI ids via MODULE_DEVICE_TABLE.  We do not actually
+ * register a pci_driver, because someone else might one day
+ * want to register another driver on the same PCI id.
+ */
+static struct pci_device_id i810tco_pci_tbl[] __initdata = {
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0,   PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0,   PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,   PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10,  PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,   PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12,  PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0,   PCI_ANY_ID, PCI_ANY_ID, },
+       { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0,    PCI_ANY_ID, PCI_ANY_ID, },
+       { 0, },
+};
+MODULE_DEVICE_TABLE (pci, i810tco_pci_tbl);
+
+static struct pci_dev *i810tco_pci;
+
+static unsigned char __init i810tco_getdevice (void)
+{
+       struct pci_dev *dev;
+       u8 val1, val2;
+       u16 badr;
+       /*
+        *      Find the PCI device
+        */
+
+       pci_for_each_dev(dev) {
+               if (pci_match_device(i810tco_pci_tbl, dev)) {
+                       i810tco_pci = dev;
+                       break;
+               }
+       }
+
+       if (i810tco_pci) {
+               /*
+                *      Find the ACPI base I/O address which is the base
+                *      for the TCO registers (TCOBASE=ACPIBASE + 0x60)
+                *      ACPIBASE is bits [15:7] from 0x40-0x43
+                */
+               pci_read_config_byte (i810tco_pci, 0x40, &val1);
+               pci_read_config_byte (i810tco_pci, 0x41, &val2);
+               badr = ((val2 << 1) | (val1 >> 7)) << 7;
+               ACPIBASE = badr;
+               /* Something's wrong here, ACPIBASE has to be set */
+               if (badr == 0x0001 || badr == 0x0000) {
+                       printk (KERN_ERR TCO_MODULE_NAME " init: failed to get TCOBASE address\n");
+                       return 0;
+               }
+               /*
+                * Check chipset's NO_REBOOT bit
+                */
+               pci_read_config_byte (i810tco_pci, 0xd4, &val1);
+               if (val1 & 0x02) {
+                       val1 &= 0xfd;
+                       pci_write_config_byte (i810tco_pci, 0xd4, val1);
+                       pci_read_config_byte (i810tco_pci, 0xd4, &val1);
+                       if (val1 & 0x02) {
+                               printk (KERN_ERR TCO_MODULE_NAME " init: failed to reset NO_REBOOT flag, reboot disabled by hardware\n");
+                               return 0;       /* Cannot reset NO_REBOOT bit */
+                       }
+               }
+               /* Set the TCO_EN bit in SMI_EN register */
+               val1 = inb (SMI_EN + 1);
+               val1 &= 0xdf;
+               outb (val1, SMI_EN + 1);
+               /* Clear out the (probably old) status */
+               outb (0, TCO1_STS);
+               outb (3, TCO2_STS);
+               return 1;
+       }
+       return 0;
+}
+
+static struct file_operations i810tco_fops = {
+       .owner =        THIS_MODULE,
+       .write =        i810tco_write,
+       .ioctl =        i810tco_ioctl,
+       .open =         i810tco_open,
+       .release =      i810tco_release,
+};
+
+static struct miscdevice i810tco_miscdev = {
+       .minor =        WATCHDOG_MINOR,
+       .name =         "watchdog",
+       .fops =         &i810tco_fops,
+};
+
+static int __init watchdog_init (void)
+{
+       spin_lock_init(&tco_lock);
+       if (!i810tco_getdevice () || i810tco_pci == NULL)
+               return -ENODEV;
+       if (!request_region (TCOBASE, 0x10, "i810 TCO")) {
+               printk (KERN_ERR TCO_MODULE_NAME
+                       ": I/O address 0x%04x already in use\n",
+                       TCOBASE);
+               return -EIO;
+       }
+       if (misc_register (&i810tco_miscdev) != 0) {
+               release_region (TCOBASE, 0x10);
+               printk (KERN_ERR TCO_MODULE_NAME ": cannot register miscdev\n");
+               return -EIO;
+       }
+       tco_timer_settimer ((unsigned char) i810_margin);
+       tco_timer_reload ();
+
+       printk (KERN_INFO TCO_DRIVER_NAME
+               ": timer margin: %d sec (0x%04x) (nowayout=%d)\n",
+               (int) (i810_margin * 6 / 10), TCOBASE, nowayout);
+       return 0;
+}
+
+static void __exit watchdog_cleanup (void)
+{
+       u8 val;
+
+       /* Reset the timer before we leave */
+       tco_timer_reload ();
+       /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
+       pci_read_config_byte (i810tco_pci, 0xd4, &val);
+       val |= 0x02;
+       pci_write_config_byte (i810tco_pci, 0xd4, val);
+       release_region (TCOBASE, 0x10);
+       misc_deregister (&i810tco_miscdev);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_cleanup);
+
+MODULE_AUTHOR("Nils Faerber");
+MODULE_DESCRIPTION("TCO timer driver for i8xx chipsets");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c
new file mode 100644 (file)
index 0000000..448c7be
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ *     IB700 Single Board Computer WDT driver for Linux 2.4.x
+ *
+ *     (c) Copyright 2001 Charles Howes <chowes@vsol.net>
+ *
+ *      Based on advantechwdt.c which is based on acquirewdt.c which
+ *       is based on wdt.c.
+ *
+ *     (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl>
+ *
+ *     Based on acquirewdt.c which is based on wdt.c.
+ *     Original copyright messages:
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     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.
+ *
+ *     (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>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+
+static int ibwdt_is_open;
+static spinlock_t ibwdt_lock;
+
+/*
+ *
+ * Watchdog Timer Configuration
+ *
+ * The function of the watchdog timer is to reset the system
+ * automatically and is defined at I/O port 0443H.  To enable the
+ * watchdog timer and allow the system to reset, write I/O port 0443H.
+ * To disable the timer, write I/O port 0441H for the system to stop the
+ * watchdog function.  The timer has a tolerance of 20% for its
+ * intervals.
+ *
+ * The following describes how the timer should be programmed.
+ *
+ * Enabling Watchdog:
+ * MOV AX,000FH (Choose the values from 0 to F)
+ * MOV DX,0443H
+ * OUT DX,AX
+ *
+ * Disabling Watchdog:
+ * MOV AX,000FH (Any value is fine.)
+ * MOV DX,0441H
+ * OUT DX,AX
+ *
+ * Watchdog timer control table:
+ * Level   Value  Time/sec | Level Value Time/sec
+ *   1       F       0     |   9     7      16
+ *   2       E       2     |   10    6      18
+ *   3       D       4     |   11    5      20
+ *   4       C       6     |   12    4      22
+ *   5       B       8     |   13    3      24
+ *   6       A       10    |   14    2      26
+ *   7       9       12    |   15    1      28
+ *   8       8       14    |   16    0      30
+ *
+ */
+
+#define WDT_STOP 0x441
+#define WDT_START 0x443
+
+#define WD_TIMO 0              /* 30 seconds +/- 20%, from table */
+
+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 void __init
+ibwdt_validate_timeout(void)
+{
+       timeout_val = (30 - timeout) / 2;
+       if (timeout_val < 0 || timeout_val > 0xF) timeout_val = WD_TIMO;
+}
+
+static void
+ibwdt_ping(void)
+{
+       /* Write a watchdog value */
+       outb_p(timeout_val, WDT_START);
+}
+
+static ssize_t
+ibwdt_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) {
+               ibwdt_ping();
+               return 1;
+       }
+       return 0;
+}
+
+static ssize_t
+ibwdt_read(struct file *file, char *buf, size_t count, loff_t *ppos)
+{
+       return -EINVAL;
+}
+
+static int
+ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+         unsigned long arg)
+{
+       static struct watchdog_info ident = {
+               WDIOF_KEEPALIVEPING, 1, "IB700 WDT"
+       };
+
+       switch (cmd) {
+       case WDIOC_GETSUPPORT:
+         if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+           return -EFAULT;
+         break;
+
+       case WDIOC_GETSTATUS:
+         if (copy_to_user((int *)arg, &ibwdt_is_open,  sizeof(int)))
+           return -EFAULT;
+         break;
+
+       case WDIOC_KEEPALIVE:
+         ibwdt_ping();
+         break;
+
+       default:
+         return -ENOTTY;
+       }
+       return 0;
+}
+
+static int
+ibwdt_open(struct inode *inode, struct file *file)
+{
+       switch (minor(inode->i_rdev)) {
+               case WATCHDOG_MINOR:
+                       spin_lock(&ibwdt_lock);
+                       if (ibwdt_is_open) {
+                               spin_unlock(&ibwdt_lock);
+                               return -EBUSY;
+                       }
+                       if (nowayout) {
+                               MOD_INC_USE_COUNT;
+                       }
+                       /*
+                        *      Activate
+                        */
+
+                       ibwdt_is_open = 1;
+                       ibwdt_ping();
+                       spin_unlock(&ibwdt_lock);
+                       return 0;
+               default:
+                       return -ENODEV;
+       }
+}
+
+static int
+ibwdt_close(struct inode *inode, struct file *file)
+{
+       lock_kernel();
+       if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
+               spin_lock(&ibwdt_lock);
+               if (!nowayout) {
+                       outb_p(timeout_val, WDT_STOP);
+               }
+               ibwdt_is_open = 0;
+               spin_unlock(&ibwdt_lock);
+       }
+       unlock_kernel();
+       return 0;
+}
+
+/*
+ *     Notifier for system down
+ */
+
+static int
+ibwdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT) {
+               /* Turn the WDT off */
+               outb_p(timeout_val, WDT_STOP);
+       }
+       return NOTIFY_DONE;
+}
+
+/*
+ *     Kernel Interfaces
+ */
+
+static struct file_operations ibwdt_fops = {
+       .owner          = THIS_MODULE,
+       .read           = ibwdt_read,
+       .write          = ibwdt_write,
+       .ioctl          = ibwdt_ioctl,
+       .open           = ibwdt_open,
+       .release        = ibwdt_close,
+};
+
+static struct miscdevice ibwdt_miscdev = {
+       WATCHDOG_MINOR,
+       "watchdog",
+       &ibwdt_fops
+};
+
+/*
+ *     The WDT needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off.
+ */
+
+static struct notifier_block ibwdt_notifier = {
+       ibwdt_notify_sys,
+       NULL,
+       0
+};
+
+static int __init
+ibwdt_init(void)
+{
+       printk("WDT driver for IB700 single board computer initialising.\n");
+
+       ibwdt_validate_timeout();
+       spin_lock_init(&ibwdt_lock);
+       if (misc_register(&ibwdt_miscdev))
+               return -ENODEV;
+#if WDT_START != WDT_STOP
+       if (!request_region(WDT_STOP, 1, "IB700 WDT")) {
+               misc_deregister(&ibwdt_miscdev);
+               return -EIO;
+       }
+#endif
+       if (!request_region(WDT_START, 1, "IB700 WDT")) {
+#if WDT_START != WDT_STOP
+               release_region(WDT_STOP, 1);
+#endif
+               misc_deregister(&ibwdt_miscdev);
+               return -EIO;
+       }
+       register_reboot_notifier(&ibwdt_notifier);
+       return 0;
+}
+
+static void __exit
+ibwdt_exit(void)
+{
+       misc_deregister(&ibwdt_miscdev);
+       unregister_reboot_notifier(&ibwdt_notifier);
+#if WDT_START != WDT_STOP
+       release_region(WDT_STOP,1);
+#endif
+       release_region(WDT_START,1);
+}
+
+module_init(ibwdt_init);
+module_exit(ibwdt_exit);
+
+MODULE_AUTHOR("Charles Howes <chowes@vsol.net>");
+MODULE_DESCRIPTION("IB700 SBC watchdog driver");
+MODULE_LICENSE("GPL");
+
+/* end of ib700wdt.c */
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
new file mode 100644 (file)
index 0000000..ab3f538
--- /dev/null
@@ -0,0 +1,557 @@
+/*
+ *  MachZ ZF-Logic Watchdog Timer driver for Linux
+ *  
+ * 
+ *  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.
+ *
+ *  The author does NOT admit liability nor provide warranty for
+ *  any of this software. This material is provided "AS-IS" in
+ *  the hope that it may be useful for others.
+ *
+ *  Author: Fernando Fuganti <fuganti@conectiva.com.br>
+ *
+ *  Based on sbc60xxwdt.c by Jakob Oestergaard
+ * 
+ *
+ *  We have two timers (wd#1, wd#2) driven by a 32 KHz clock with the 
+ *  following periods:
+ *      wd#1 - 2 seconds;
+ *      wd#2 - 7.2 ms;
+ *  After the expiration of wd#1, it can generate a NMI, SCI, SMI, or 
+ *  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>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/smp_lock.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+
+/* ports */
+#define ZF_IOBASE      0x218
+#define INDEX          0x218
+#define DATA_B         0x219
+#define DATA_W         0x21A
+#define DATA_D         0x21A
+
+/* indexes */                  /* size */
+#define ZFL_VERSION    0x02    /* 16   */
+#define CONTROL        0x10    /* 16   */      
+#define STATUS         0x12    /* 8    */
+#define COUNTER_1      0x0C    /* 16   */
+#define COUNTER_2      0x0E    /* 8    */
+#define PULSE_LEN      0x0F    /* 8    */
+
+/* controls */
+#define ENABLE_WD1     0x0001
+#define ENABLE_WD2     0x0002
+#define RESET_WD1      0x0010
+#define RESET_WD2      0x0020
+#define GEN_SCI                0x0100
+#define GEN_NMI                0x0200
+#define GEN_SMI                0x0400
+#define GEN_RESET      0x0800
+
+
+/* utilities */
+
+#define WD1    0
+#define WD2    1
+
+#define zf_writew(port, data)  { outb(port, INDEX); outw(data, DATA_W); }
+#define zf_writeb(port, data)  { outb(port, INDEX); outb(data, DATA_B); }
+#define zf_get_ZFL_version()   zf_readw(ZFL_VERSION)
+
+
+static unsigned short zf_readw(unsigned char port)
+{
+       outb(port, INDEX);
+       return inw(DATA_W);
+}
+
+static unsigned short zf_readb(unsigned char port)
+{
+       outb(port, INDEX);
+       return inb(DATA_B);
+}
+
+
+MODULE_AUTHOR("Fernando Fuganti <fuganti@conectiva.com.br>");
+MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver");
+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 = {
+       .options                = WDIOF_KEEPALIVEPING, 
+       .firmware_version       = 1, 
+       .identity               = "ZF-Logic watchdog"
+};
+
+
+/*
+ * action refers to action taken when watchdog resets
+ * 0 = GEN_RESET
+ * 1 = GEN_SMI
+ * 2 = GEN_NMI
+ * 3 = GEN_SCI
+ * defaults to GEN_RESET (0)
+ */
+static int action = 0;
+static int zf_action = GEN_RESET;
+static int zf_is_open = 0;
+static int zf_expect_close = 0;
+static spinlock_t zf_lock;
+static spinlock_t zf_port_lock;
+static struct timer_list zf_timer;
+static unsigned long next_heartbeat = 0;
+
+
+/* timeout for user land heart beat (10 seconds) */
+#define ZF_USER_TIMEO (HZ*10)
+
+/* timeout for hardware watchdog (~500ms) */
+#define ZF_HW_TIMEO (HZ/2)
+
+/* number of ticks on WD#1 (driven by a 32KHz clock, 2s) */
+#define ZF_CTIMEOUT 0xffff
+
+#ifndef ZF_DEBUG
+#      define dprintk(format, args...)
+#else
+#      define dprintk(format, args...) printk(KERN_DEBUG PFX; ":" __FUNCTION__ ":%d: " format, __LINE__ , ## args)
+#endif
+
+
+/* STATUS register functions */
+
+static inline unsigned char zf_get_status(void)
+{
+       return zf_readb(STATUS);
+}
+
+static inline void zf_set_status(unsigned char new)
+{
+       zf_writeb(STATUS, new);
+}
+
+
+/* CONTROL register functions */
+
+static inline unsigned short zf_get_control(void)
+{
+       return zf_readw(CONTROL);
+}
+
+static inline void zf_set_control(unsigned short new)
+{
+       zf_writew(CONTROL, new);
+}
+
+
+/* WD#? counter functions */
+/*
+ *     Just get current counter value
+ */
+
+static inline unsigned short zf_get_timer(unsigned char n)
+{
+       switch(n){
+               case WD1:
+                       return zf_readw(COUNTER_1);
+               case WD2:
+                       return zf_readb(COUNTER_2);
+               default:
+                       return 0;
+       }
+}
+
+/*
+ *     Just set counter value
+ */
+
+static inline void zf_set_timer(unsigned short new, unsigned char n)
+{
+       switch(n){
+               case WD1:
+                       zf_writew(COUNTER_1, new);
+               case WD2:
+                       zf_writeb(COUNTER_2, new > 0xff ? 0xff : new);
+               default:
+                       return;
+       }
+}
+
+/*
+ * stop hardware timer
+ */
+static void zf_timer_off(void)
+{
+       unsigned int ctrl_reg = 0;
+       unsigned long flags;
+
+       /* stop internal ping */
+       del_timer_sync(&zf_timer);
+
+       spin_lock_irqsave(&zf_port_lock, flags);
+       /* stop watchdog timer */       
+       ctrl_reg = zf_get_control();
+       ctrl_reg |= (ENABLE_WD1|ENABLE_WD2);    /* disable wd1 and wd2 */
+       ctrl_reg &= ~(ENABLE_WD1|ENABLE_WD2);
+       zf_set_control(ctrl_reg);
+       spin_unlock_irqrestore(&zf_port_lock, flags);
+
+       printk(KERN_INFO PFX ": Watchdog timer is now disabled\n");
+}
+
+
+/*
+ * start hardware timer 
+ */
+static void zf_timer_on(void)
+{
+       unsigned int ctrl_reg = 0;
+       unsigned long flags;
+       
+       spin_lock_irqsave(&zf_port_lock, flags);
+
+       zf_writeb(PULSE_LEN, 0xff);
+
+       zf_set_timer(ZF_CTIMEOUT, WD1);
+
+       /* user land ping */
+       next_heartbeat = jiffies + ZF_USER_TIMEO;
+
+       /* start the timer for internal ping */
+       zf_timer.expires = jiffies + ZF_HW_TIMEO;
+
+       add_timer(&zf_timer);
+
+       /* start watchdog timer */
+       ctrl_reg = zf_get_control();
+       ctrl_reg |= (ENABLE_WD1|zf_action);
+       zf_set_control(ctrl_reg);
+       spin_unlock_irqrestore(&zf_port_lock, flags);
+
+       printk(KERN_INFO PFX ": Watchdog timer is now enabled\n");
+}
+
+
+static void zf_ping(unsigned long data)
+{
+       unsigned int ctrl_reg = 0;
+       unsigned long flags;
+               
+       zf_writeb(COUNTER_2, 0xff);
+
+       if(time_before(jiffies, next_heartbeat)){
+
+               dprintk("time_before: %ld\n", next_heartbeat - jiffies);
+               
+               /* 
+                * reset event is activated by transition from 0 to 1 on
+                * RESET_WD1 bit and we assume that it is already zero...
+                */
+
+               spin_lock_irqsave(&zf_port_lock, flags);
+               ctrl_reg = zf_get_control();    
+               ctrl_reg |= RESET_WD1;          
+               zf_set_control(ctrl_reg);       
+               
+               /* ...and nothing changes until here */
+               ctrl_reg &= ~(RESET_WD1);
+               zf_set_control(ctrl_reg);               
+               spin_unlock_irqrestore(&zf_port_lock, flags);
+
+               zf_timer.expires = jiffies + ZF_HW_TIMEO;
+               add_timer(&zf_timer);
+       }else{
+               printk(KERN_CRIT PFX ": I will reset your machine\n");
+       }
+}
+
+static ssize_t zf_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;
+
+       /* See if we got the magic character */
+       if(count){
+
+/*
+ * no need to check for close confirmation
+ * no way to disable watchdog ;)
+ */
+               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++){
+                               char c;
+                               if (get_user(c, buf + ofs))
+                                       return -EFAULT;
+                               if (c == 'V'){
+                                       zf_expect_close = 1;
+                                       dprintk("zf_expect_close 1\n");
+                               }
+                       }
+               }
+               /*
+                * Well, anyhow someone wrote to us,
+                * we should return that favour
+                */
+               next_heartbeat = jiffies + ZF_USER_TIMEO;
+               dprintk("user ping at %ld\n", jiffies);
+               
+               return 1;
+       }
+
+       return 0;
+}
+
+static ssize_t zf_read(struct file *file, char *buf, size_t count, 
+                                                       loff_t *ppos)
+{
+       return -EINVAL;
+}
+
+
+
+static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       switch(cmd){
+               case WDIOC_GETSUPPORT:
+                       if (copy_to_user((struct watchdog_info *)arg, 
+                                        &zf_info, sizeof(zf_info)))
+                               return -EFAULT;
+                       break;
+         
+               case WDIOC_GETSTATUS:
+                       if (copy_to_user((int *)arg, &zf_is_open, sizeof(int)))
+                               return -EFAULT;
+                       break;
+
+               case WDIOC_KEEPALIVE:
+                       zf_ping(0);
+                       break;
+
+               default:
+                       return -ENOTTY;
+       }
+
+       return 0;
+}
+
+static int zf_open(struct inode *inode, struct file *file)
+{
+       switch(minor(inode->i_rdev)){
+               case WATCHDOG_MINOR:
+                       spin_lock(&zf_lock);
+                       if(zf_is_open){
+                               spin_unlock(&zf_lock);
+                               return -EBUSY;
+                       }
+
+                       if (nowayout) {
+                               MOD_INC_USE_COUNT;
+                       }
+                       zf_is_open = 1;
+
+                       spin_unlock(&zf_lock);
+
+                       zf_timer_on();
+
+                       return 0;
+               default:
+                       return -ENODEV;
+       }
+}
+
+static int zf_close(struct inode *inode, struct file *file)
+{
+       if(minor(inode->i_rdev) == WATCHDOG_MINOR){
+
+               if(zf_expect_close){
+                       zf_timer_off();
+               } else {
+                       del_timer(&zf_timer);
+                       printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n");
+               }
+               
+               spin_lock(&zf_lock);
+               zf_is_open = 0;
+               spin_unlock(&zf_lock);
+
+               zf_expect_close = 0;
+       }
+       
+       return 0;
+}
+
+/*
+ * Notifier for system down
+ */
+
+static int zf_notify_sys(struct notifier_block *this, unsigned long code,
+                                                               void *unused)
+{
+       if(code == SYS_DOWN || code == SYS_HALT){
+               zf_timer_off();         
+       }
+       
+       return NOTIFY_DONE;
+}
+
+
+
+
+static struct file_operations zf_fops = {
+       .owner          = THIS_MODULE,
+       .read           = zf_read,
+       .write          = zf_write,
+       .ioctl          = zf_ioctl,
+       .open           = zf_open,
+       .release        = zf_close,
+};
+
+static struct miscdevice zf_miscdev = {
+       WATCHDOG_MINOR,
+       "watchdog",
+       &zf_fops
+};
+                                                                        
+
+/*
+ * The device needs to learn about soft shutdowns in order to
+ * turn the timebomb registers off.
+ */
+static struct notifier_block zf_notifier = {
+       zf_notify_sys,
+       NULL,
+       0
+};
+
+static void __init zf_show_action(int act)
+{
+       char *str[] = { "RESET", "SMI", "NMI", "SCI" };
+       
+       printk(KERN_INFO PFX ": Watchdog using action = %s\n", str[act]);
+}
+
+static int __init zf_init(void)
+{
+       int ret;
+       
+       printk(KERN_INFO PFX ": MachZ ZF-Logic Watchdog driver initializing.\n");
+
+       ret = zf_get_ZFL_version();
+       printk("%#x\n", ret);
+       if((!ret) || (ret != 0xffff)){
+               printk(KERN_WARNING PFX ": no ZF-Logic found\n");
+               return -ENODEV;
+       }
+
+       if((action <= 3) && (action >= 0)){
+               zf_action = zf_action>>action;
+       } else
+               action = 0;
+       
+       zf_show_action(action);
+
+       spin_lock_init(&zf_lock);
+       spin_lock_init(&zf_port_lock);
+       
+       ret = misc_register(&zf_miscdev);
+       if (ret){
+               printk(KERN_ERR "can't misc_register on minor=%d\n",
+                                                       WATCHDOG_MINOR);
+               goto out;
+       }
+
+       if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){
+               printk(KERN_ERR "cannot reserve I/O ports at %d\n",
+                                                       ZF_IOBASE);
+               ret = -EBUSY;
+               goto no_region;
+       }
+
+       ret = register_reboot_notifier(&zf_notifier);
+       if(ret){
+               printk(KERN_ERR "can't register reboot notifier (err=%d)\n",
+                                                                       ret);
+               goto no_reboot;
+       }
+       
+       zf_set_status(0);
+       zf_set_control(0);
+
+       /* this is the timer that will do the hard work */
+       init_timer(&zf_timer);
+       zf_timer.function = zf_ping;
+       zf_timer.data = 0;
+       
+       return 0;
+
+no_reboot:
+       release_region(ZF_IOBASE, 3);
+no_region:
+       misc_deregister(&zf_miscdev);
+out:
+       return ret;
+}
+
+       
+void __exit zf_exit(void)
+{
+       zf_timer_off();
+       
+       misc_deregister(&zf_miscdev);
+       unregister_reboot_notifier(&zf_notifier);
+       release_region(ZF_IOBASE, 3);
+}
+
+module_init(zf_init);
+module_exit(zf_exit);
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
new file mode 100644 (file)
index 0000000..6ee6576
--- /dev/null
@@ -0,0 +1,282 @@
+/*
+ * MixCom Watchdog: A Simple Hardware Watchdog Device
+ * Based on Softdog driver by Alan Cox and PC Watchdog driver by Ken Hollis
+ *
+ * Author: Gergely Madarasz <gorgo@itc.hu>
+ *
+ * Copyright (c) 1999 ITConsult-Pro Co. <info@itc.hu>
+ *
+ * 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.
+ *
+ * Version 0.1 (99/04/15):
+ *             - first version
+ *
+ * Version 0.2 (99/06/16):
+ *             - added kernel timer watchdog ping after close
+ *               since the hardware does not support watchdog shutdown
+ *
+ * Version 0.3 (99/06/21):
+ *             - added WDIOC_GETSTATUS and WDIOC_GETSUPPORT ioctl calls
+ *
+ * Version 0.3.1 (99/06/22):
+ *             - allow module removal while internal timer is active,
+ *               print warning about probable reset
+ *
+ * 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.5" 
+  
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/ioport.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+static int mixcomwd_ioports[] = { 0x180, 0x280, 0x380, 0x000 };
+
+#define MIXCOM_WATCHDOG_OFFSET 0xc10
+#define MIXCOM_ID 0x11
+#define FLASHCOM_WATCHDOG_OFFSET 0x4
+#define FLASHCOM_ID 0x18
+
+static long mixcomwd_opened; /* long req'd for setbit --RR */
+
+static int watchdog_port;
+static int mixcomwd_timer_alive;
+static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 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)");
+
+static void mixcomwd_ping(void)
+{
+       outb_p(55,watchdog_port);
+       return;
+}
+
+static void mixcomwd_timerfun(unsigned long d)
+{
+       mixcomwd_ping();
+       
+       mod_timer(&mixcomwd_timer,jiffies+ 5*HZ);
+}
+
+/*
+ *     Allow only one person to hold it open
+ */
+static int mixcomwd_open(struct inode *inode, struct file *file)
+{
+       if(test_and_set_bit(0,&mixcomwd_opened)) {
+               return -EBUSY;
+       }
+       mixcomwd_ping();
+       
+       if (nowayout) {
+               MOD_INC_USE_COUNT;
+       } else {
+               if(mixcomwd_timer_alive) {
+                       del_timer(&mixcomwd_timer);
+                       mixcomwd_timer_alive=0;
+               }
+       }
+       return 0;
+}
+
+static int mixcomwd_release(struct inode *inode, struct file *file)
+{
+
+       if (!nowayout) {
+               if(mixcomwd_timer_alive) {
+                       printk(KERN_ERR "mixcomwd: release called while internal timer alive");
+                       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);
+       }
+       clear_bit(0,&mixcomwd_opened);
+       return 0;
+}
+
+
+static ssize_t mixcomwd_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+       if (ppos != &file->f_pos) {
+               return -ESPIPE;
+       }
+
+       if(len)
+       {
+               mixcomwd_ping();
+               return 1;
+       }
+       return 0;
+}
+
+static int mixcomwd_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       int status;
+        static struct watchdog_info ident = {
+               WDIOF_KEEPALIVEPING, 1, "MixCOM watchdog"
+       };
+                                        
+       switch(cmd)
+       {
+               case WDIOC_GETSTATUS:
+                       status=mixcomwd_opened;
+                       if (!nowayout) {
+                               status|=mixcomwd_timer_alive;
+                       }
+                       if (copy_to_user((int *)arg, &status, sizeof(int))) {
+                               return -EFAULT;
+                       }
+                       break;
+               case WDIOC_GETSUPPORT:
+                       if (copy_to_user((struct watchdog_info *)arg, &ident, 
+                           sizeof(ident))) {
+                               return -EFAULT;
+                       }
+                       break;
+               case WDIOC_KEEPALIVE:
+                       mixcomwd_ping();
+                       break;
+               default:
+                       return -ENOTTY;
+       }
+       return 0;
+}
+
+static struct file_operations mixcomwd_fops=
+{
+       .owner          = THIS_MODULE,
+       .write          = mixcomwd_write,
+       .ioctl          = mixcomwd_ioctl,
+       .open           = mixcomwd_open,
+       .release        = mixcomwd_release,
+};
+
+static struct miscdevice mixcomwd_miscdev=
+{
+       WATCHDOG_MINOR,
+       "watchdog",
+       &mixcomwd_fops
+};
+
+static int __init mixcomwd_checkcard(int port)
+{
+       int id;
+
+       if(check_region(port+MIXCOM_WATCHDOG_OFFSET,1)) {
+               return 0;
+       }
+       
+       id=inb_p(port + MIXCOM_WATCHDOG_OFFSET) & 0x3f;
+       if(id!=MIXCOM_ID) {
+               return 0;
+       }
+       return 1;
+}
+
+static int __init flashcom_checkcard(int port)
+{
+       int id;
+       
+       if(check_region(port + FLASHCOM_WATCHDOG_OFFSET,1)) {
+               return 0;
+       }
+       
+       id=inb_p(port + FLASHCOM_WATCHDOG_OFFSET);
+       if(id!=FLASHCOM_ID) {
+               return 0;
+       }
+       return 1;
+ }
+static int __init mixcomwd_init(void)
+{
+       int i;
+       int ret;
+       int found=0;
+
+       for (i = 0; !found && mixcomwd_ioports[i] != 0; i++) {
+               if (mixcomwd_checkcard(mixcomwd_ioports[i])) {
+                       found = 1;
+                       watchdog_port = mixcomwd_ioports[i] + MIXCOM_WATCHDOG_OFFSET;
+               }
+       }
+       
+       /* The FlashCOM card can be set up at 0x300 -> 0x378, in 0x8 jumps */
+       for (i = 0x300; !found && i < 0x380; i+=0x8) {
+               if (flashcom_checkcard(i)) {
+                       found = 1;
+                       watchdog_port = i + FLASHCOM_WATCHDOG_OFFSET;
+               }
+       }
+       
+       if (!found) {
+               printk("mixcomwd: No card detected, or port not available.\n");
+               return -ENODEV;
+       }
+
+       if (!request_region(watchdog_port,1,"MixCOM watchdog"))
+               return -EIO;
+               
+       ret = misc_register(&mixcomwd_miscdev);
+       if (ret)
+       {
+               release_region(watchdog_port, 1);
+               return ret;
+       }
+       
+       printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",VERSION,watchdog_port);
+
+       return 0;
+}      
+
+static void __exit mixcomwd_exit(void)
+{
+       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;
+               }
+       }
+       release_region(watchdog_port,1);
+       misc_deregister(&mixcomwd_miscdev);
+}
+
+module_init(mixcomwd_init);
+module_exit(mixcomwd_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
new file mode 100644 (file)
index 0000000..4fdd439
--- /dev/null
@@ -0,0 +1,672 @@
+/*
+ * PC Watchdog Driver
+ * by Ken Hollis (khollis@bitgate.com)
+ *
+ * Permission granted from Simon Machell (73244.1270@compuserve.com)
+ * Written for the Linux Kernel, and GPLed by Ken Hollis
+ *
+ * 960107      Added request_region routines, modulized the whole thing.
+ * 960108      Fixed end-of-file pointer (Thanks to Dan Hollis), added
+ *             WD_TIMEOUT define.
+ * 960216      Added eof marker on the file, and changed verbose messages.
+ * 960716      Made functional and cosmetic changes to the source for
+ *             inclusion in Linux 2.0.x kernels, thanks to Alan Cox.
+ * 960717      Removed read/seek routines, replaced with ioctl.  Also, added
+ *             check_region command due to Alan's suggestion.
+ * 960821      Made changes to compile in newer 2.0.x kernels.  Added
+ *             "cold reboot sense" entry.
+ * 960825      Made a few changes to code, deleted some defines and made
+ *             typedefs to replace them.  Made heartbeat reset only available
+ *             via ioctl, and removed the write routine.
+ * 960828      Added new items for PC Watchdog Rev.C card.
+ * 960829      Changed around all of the IOCTLs, added new features,
+ *             added watchdog disable/re-enable routines.  Added firmware
+ *             version reporting.  Added read routine for temperature.
+ *             Removed some extra defines, added an autodetect Revision
+ *             routine.
+ * 961006       Revised some documentation, fixed some cosmetic bugs.  Made
+ *              drivers to panic the system if it's overheating at bootup.
+ * 961118      Changed some verbiage on some of the output, tidied up
+ *             code bits, and added compatibility to 2.1.x.
+ * 970912       Enabled board on open and disable on close.
+ * 971107      Took account of recent VFS changes (broke read).
+ * 971210       Disable board on initialisation in case board already ticking.
+ * 971222       Changed open/close for temperature handling
+ *              Michael Meskes <meskes@debian.org>.
+ * 980112       Used minor numbers from include/linux/miscdevice.h
+ * 990403       Clear reset status after reading control status register in 
+ *              pcwd_showprevstate(). [Marc Boucher <marc@mbsi.ca>]
+ * 990605      Made changes to code to support Firmware 1.22a, added
+ *             fairly useless proc entry.
+ * 990610      removed said useless proc code for the merge <alan>
+ * 000403      Removed last traces of proc code. <davej>
+ */
+
+#include <linux/module.h>
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/tty.h>
+#include <linux/timer.h>
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/miscdevice.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/watchdog.h>
+#include <linux/init.h>
+#include <linux/proc_fs.h>
+#include <linux/spinlock.h>
+#include <linux/smp_lock.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+/*
+ * These are the auto-probe addresses available.
+ *
+ * Revision A only uses ports 0x270 and 0x370.  Revision C introduced 0x350.
+ * Revision A has an address range of 2 addresses, while Revision C has 3.
+ */
+static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 };
+
+#define WD_VER                  "1.10 (06/05/99)"
+
+/*
+ * It should be noted that PCWD_REVISION_B was removed because A and B
+ * are essentially the same types of card, with the exception that B
+ * has temperature reporting.  Since I didn't receive a Rev.B card,
+ * the Rev.B card is not supported.  (It's a good thing too, as they
+ * are no longer in production.)
+ */
+#define        PCWD_REVISION_A         1
+#define        PCWD_REVISION_C         2
+
+#define        WD_TIMEOUT              3       /* 1 1/2 seconds for a timeout */
+
+/*
+ * These are the defines for the PC Watchdog card, revision A.
+ */
+#define WD_WDRST                0x01   /* Previously reset state */
+#define WD_T110                 0x02   /* Temperature overheat sense */
+#define WD_HRTBT                0x04   /* Heartbeat sense */
+#define WD_RLY2                 0x08   /* External relay triggered */
+#define WD_SRLY2                0x80   /* Software external relay triggered */
+
+static int current_readport, revision, temp_panic;
+static atomic_t open_allowed = ATOMIC_INIT(1);
+static int initial_status, supports_temp, mode_debug;
+static spinlock_t io_lock;
+
+/*
+ * PCWD_CHECKCARD
+ *
+ * This routine checks the "current_readport" to see if the card lies there.
+ * If it does, it returns accordingly.
+ */
+static int __init pcwd_checkcard(void)
+{
+       int card_dat, prev_card_dat, found = 0, count = 0, done = 0;
+
+       card_dat = 0x00;
+       prev_card_dat = 0x00;
+
+       prev_card_dat = inb(current_readport);
+       if (prev_card_dat == 0xFF)
+               return 0;
+
+       while(count < WD_TIMEOUT) {
+
+       /* Read the raw card data from the port, and strip off the
+          first 4 bits */
+
+               card_dat = inb_p(current_readport);
+               card_dat &= 0x000F;
+
+       /* Sleep 1/2 second (or 500000 microseconds :) */
+
+               mdelay(500);
+               done = 0;
+
+       /* If there's a heart beat in both instances, then this means we
+          found our card.  This also means that either the card was
+          previously reset, or the computer was power-cycled. */
+
+               if ((card_dat & WD_HRTBT) && (prev_card_dat & WD_HRTBT) &&
+                       (!done)) {
+                       found = 1;
+                       done = 1;
+                       break;
+               }
+
+       /* If the card data is exactly the same as the previous card data,
+          it's safe to assume that we should check again.  The manual says
+          that the heart beat will change every second (or the bit will
+          toggle), and this can be used to see if the card is there.  If
+          the card was powered up with a cold boot, then the card will
+          not start blinking until 2.5 minutes after a reboot, so this
+          bit will stay at 1. */
+
+               if ((card_dat == prev_card_dat) && (!done)) {
+                       count++;
+                       done = 1;
+               }
+
+       /* If the card data is toggling any bits, this means that the heart
+          beat was detected, or something else about the card is set. */
+
+               if ((card_dat != prev_card_dat) && (!done)) {
+                       done = 1;
+                       found = 1;
+                       break;
+               }
+
+       /* Otherwise something else strange happened. */
+
+               if (!done)
+                       count++;
+       }
+
+       return((found) ? 1 : 0);
+}
+
+void pcwd_showprevstate(void)
+{
+       int card_status = 0x0000;
+
+       if (revision == PCWD_REVISION_A)
+               initial_status = card_status = inb(current_readport);
+       else {
+               initial_status = card_status = inb(current_readport + 1);
+               outb_p(0x00, current_readport + 1); /* clear reset status */
+       }
+
+       if (revision == PCWD_REVISION_A) {
+               if (card_status & WD_WDRST)
+                       printk("pcwd: Previous reboot was caused by the card.\n");
+
+               if (card_status & WD_T110) {
+                       printk("pcwd: Card senses a CPU Overheat.  Panicking!\n");
+                       panic("pcwd: CPU Overheat.\n");
+               }
+
+               if ((!(card_status & WD_WDRST)) &&
+                   (!(card_status & WD_T110)))
+                       printk("pcwd: Cold boot sense.\n");
+       } else {
+               if (card_status & 0x01)
+                       printk("pcwd: Previous reboot was caused by the card.\n");
+
+               if (card_status & 0x04) {
+                       printk("pcwd: Card senses a CPU Overheat.  Panicking!\n");
+                       panic("pcwd: CPU Overheat.\n");
+               }
+
+               if ((!(card_status & 0x01)) &&
+                   (!(card_status & 0x04)))
+                       printk("pcwd: Cold boot sense.\n");
+       }
+}
+
+static void pcwd_send_heartbeat(void)
+{
+       int wdrst_stat;
+
+       wdrst_stat = inb_p(current_readport);
+       wdrst_stat &= 0x0F;
+
+       wdrst_stat |= WD_WDRST;
+
+       if (revision == PCWD_REVISION_A)
+               outb_p(wdrst_stat, current_readport + 1);
+       else
+               outb_p(wdrst_stat, current_readport);
+}
+
+static int pcwd_ioctl(struct inode *inode, struct file *file,
+                     unsigned int cmd, unsigned long arg)
+{
+       int cdat, rv;
+       static struct watchdog_info ident=
+       {
+               WDIOF_OVERHEAT|WDIOF_CARDRESET,
+               1,
+               "PCWD"
+       };
+
+       switch(cmd) {
+       default:
+               return -ENOTTY;
+
+       case WDIOC_GETSUPPORT:
+               if(copy_to_user((void*)arg, &ident, sizeof(ident)))
+                       return -EFAULT;
+               return 0;
+
+       case WDIOC_GETSTATUS:
+               spin_lock(&io_lock);
+               if (revision == PCWD_REVISION_A) 
+                       cdat = inb(current_readport);
+               else
+                       cdat = inb(current_readport + 1 );
+               spin_unlock(&io_lock);
+               rv = 0;
+
+               if (revision == PCWD_REVISION_A) 
+               {
+                       if (cdat & WD_WDRST)
+                               rv |= WDIOF_CARDRESET;
+
+                       if (cdat & WD_T110) 
+                       {
+                               rv |= WDIOF_OVERHEAT;
+
+                               if (temp_panic)
+                                       panic("pcwd: Temperature overheat trip!\n");
+                       }
+               }
+               else 
+               {
+                       if (cdat & 0x01)
+                               rv |= WDIOF_CARDRESET;
+
+                       if (cdat & 0x04) 
+                       {
+                               rv |= WDIOF_OVERHEAT;
+
+                               if (temp_panic)
+                                       panic("pcwd: Temperature overheat trip!\n");
+                       }
+               }
+
+               if(put_user(rv, (int *) arg))
+                       return -EFAULT;
+               return 0;
+
+       case WDIOC_GETBOOTSTATUS:
+               rv = 0;
+
+               if (revision == PCWD_REVISION_A) 
+               {
+                       if (initial_status & WD_WDRST)
+                               rv |= WDIOF_CARDRESET;
+
+                       if (initial_status & WD_T110)
+                               rv |= WDIOF_OVERHEAT;
+               }
+               else
+               {
+                       if (initial_status & 0x01)
+                               rv |= WDIOF_CARDRESET;
+
+                       if (initial_status & 0x04)
+                               rv |= WDIOF_OVERHEAT;
+               }
+
+               if(put_user(rv, (int *) arg))
+                       return -EFAULT;
+               return 0;
+
+       case WDIOC_GETTEMP:
+
+               rv = 0;
+               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;
+               } else if(put_user(rv, (int*) arg))
+                               return -EFAULT;
+               return 0;
+
+       case WDIOC_SETOPTIONS:
+               if (revision == PCWD_REVISION_C) 
+               {
+                       if(copy_from_user(&rv, (int*) arg, sizeof(int)))
+                               return -EFAULT;
+
+                       if (rv & WDIOS_DISABLECARD) 
+                       {
+                               spin_lock(&io_lock);
+                               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("pcwd: Could not disable card.\n");
+                                       return -EIO;
+                               }
+
+                               return 0;
+                       }
+
+                       if (rv & WDIOS_ENABLECARD) 
+                       {
+                               spin_lock(&io_lock);
+                               outb_p(0x00, current_readport + 3);
+                               cdat = inb_p(current_readport + 2);
+                               spin_unlock(&io_lock);
+                               if (cdat & 0x10) 
+                               {
+                                       printk("pcwd: Could not enable card.\n");
+                                       return -EIO;
+                               }
+                               return 0;
+                       }
+
+                       if (rv & WDIOS_TEMPPANIC) 
+                       {
+                               temp_panic = 1;
+                       }
+               }
+               return -EINVAL;
+               
+       case WDIOC_KEEPALIVE:
+               pcwd_send_heartbeat();
+               return 0;
+       }
+
+       return 0;
+}
+
+static ssize_t pcwd_write(struct file *file, const char *buf, size_t len,
+                         loff_t *ppos)
+{
+       /*  Can't seek (pwrite) on this device  */
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       if (len)
+       {
+               pcwd_send_heartbeat();
+               return 1;
+       }
+       return 0;
+}
+
+static int pcwd_open(struct inode *ino, struct file *filep)
+{
+        switch (minor(ino->i_rdev))
+        {
+                case WATCHDOG_MINOR:
+                    if ( !atomic_dec_and_test(&open_allowed) )
+                   {
+                       atomic_inc( &open_allowed );
+                        return -EBUSY;
+                    }
+                   MOD_INC_USE_COUNT;
+                    /*  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:
+                    return(0);
+                default:
+                    return (-ENODEV);
+        }
+}
+
+static ssize_t pcwd_read(struct file *file, char *buf, size_t count,
+                        loff_t *ppos)
+{
+       unsigned short c;
+       unsigned char cp;
+
+       /*  Can't seek (pread) on this device  */
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+       switch(minor(file->f_dentry->d_inode->i_rdev)) 
+       {
+               case TEMP_MINOR:
+                       /*
+                        * Convert metric to Fahrenheit, since this was
+                        * the decided 'standard' for this return value.
+                        */
+                       
+                       c = inb(current_readport);
+                       cp = (c * 9 / 5) + 32;
+                       if(copy_to_user(buf, &cp, 1))
+                               return -EFAULT;
+                       return 1;
+               default:
+                       return -EINVAL;
+       }
+}
+
+static int pcwd_close(struct inode *ino, struct file *filep)
+{
+       if (minor(ino->i_rdev)==WATCHDOG_MINOR)
+       {
+#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);
+               }
+               atomic_inc( &open_allowed );
+#endif
+       }
+       return 0;
+}
+
+static inline void get_support(void)
+{
+       if (inb(current_readport) != 0xF0)
+               supports_temp = 1;
+}
+
+static inline int get_revision(void)
+{
+       int r = PCWD_REVISION_C;
+       
+       spin_lock(&io_lock);
+       if ((inb(current_readport + 2) == 0xFF) ||
+           (inb(current_readport + 3) == 0xFF))
+               r=PCWD_REVISION_A;
+       spin_unlock(&io_lock);
+
+       return r;
+}
+
+static int __init send_command(int cmd)
+{
+       int i;
+
+       outb_p(cmd, current_readport + 2);
+       mdelay(1);
+
+       i = inb(current_readport);
+       i = inb(current_readport);
+
+       return(i);
+}
+
+static inline char *get_firmware(void)
+{
+       int i, found = 0, count = 0, one, ten, hund, minor;
+       char *ret;
+
+       ret = kmalloc(6, GFP_KERNEL);
+       if(ret == NULL)
+               return NULL;
+
+       while((count < 3) && (!found)) {
+               outb_p(0x80, current_readport + 2);
+               i = inb(current_readport);
+
+               if (i == 0x00)
+                       found = 1;
+               else if (i == 0xF3)
+                       outb_p(0x00, current_readport + 2);
+
+               udelay(400L);
+               count++;
+       }
+
+       if (found) {
+               mode_debug = 1;
+
+               one = send_command(0x81);
+               ten = send_command(0x82);
+               hund = send_command(0x83);
+               minor = send_command(0x84);
+               sprintf(ret, "%c.%c%c%c", one, ten, hund, minor);
+       }
+       else
+               sprintf(ret, "ERROR");
+
+       return(ret);
+}
+
+static void debug_off(void)
+{
+       outb_p(0x00, current_readport + 2);
+       mode_debug = 0;
+}
+
+static struct file_operations pcwd_fops = {
+       .owner          = THIS_MODULE,
+       .read           = pcwd_read,
+       .write          = pcwd_write,
+       .ioctl          = pcwd_ioctl,
+       .open           = pcwd_open,
+       .release        = pcwd_close,
+};
+
+static struct miscdevice pcwd_miscdev = {
+       WATCHDOG_MINOR,
+       "watchdog",
+       &pcwd_fops
+};
+
+static struct miscdevice temp_miscdev = {
+       TEMP_MINOR,
+       "temperature",
+       &pcwd_fops
+};
+static int __init pcwatchdog_init(void)
+{
+       int i, found = 0;
+       spin_lock_init(&io_lock);
+       
+       revision = PCWD_REVISION_A;
+
+       printk("pcwd: v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER);
+
+       /* Initial variables */
+       supports_temp = 0;
+       mode_debug = 0;
+       temp_panic = 0;
+       initial_status = 0x0000;
+
+#ifndef        PCWD_BLIND
+       for (i = 0; pcwd_ioports[i] != 0; i++) {
+               current_readport = pcwd_ioports[i];
+
+               if (pcwd_checkcard()) {
+                       found = 1;
+                       break;
+               }
+       }
+
+       if (!found) {
+               printk("pcwd: No card detected, or port not available.\n");
+               return(-EIO);
+       }
+#endif
+
+#ifdef PCWD_BLIND
+       current_readport = PCWD_BLIND;
+#endif
+
+       get_support();
+       revision = get_revision();
+
+       if (revision == PCWD_REVISION_A)
+               printk("pcwd: PC Watchdog (REV.A) detected at port 0x%03x\n", current_readport);
+       else if (revision == PCWD_REVISION_C)
+               printk("pcwd: PC Watchdog (REV.C) detected at port 0x%03x (Firmware version: %s)\n",
+                       current_readport, get_firmware());
+       else {
+               /* Should NEVER happen, unless get_revision() fails. */
+               printk("pcwd: Unable to get revision.\n");
+               return -1;
+       }
+
+       if (supports_temp)
+               printk("pcwd: Temperature Option Detected.\n");
+
+       debug_off();
+
+       pcwd_showprevstate();
+
+       /*  Disable the board  */
+       if (revision == PCWD_REVISION_C) {
+               outb_p(0xA5, current_readport + 3);
+               outb_p(0xA5, current_readport + 3);
+       }
+
+       if (misc_register(&pcwd_miscdev))
+               return -ENODEV;
+       
+       if (supports_temp)
+               if (misc_register(&temp_miscdev)) {
+                       misc_deregister(&pcwd_miscdev);
+                       return -ENODEV;         
+               }
+
+
+       if (revision == PCWD_REVISION_A) {
+               if (!request_region(current_readport, 2, "PCWD Rev.A (Berkshire)")) {
+                       misc_deregister(&pcwd_miscdev);
+                       if (supports_temp)
+                               misc_deregister(&pcwd_miscdev);
+                       return -EIO;            
+               }
+       }
+       else 
+               if (!request_region(current_readport, 4, "PCWD Rev.C (Berkshire)")) {
+                       misc_deregister(&pcwd_miscdev);
+                       if (supports_temp)
+                               misc_deregister(&pcwd_miscdev);
+                       return -EIO;
+               }
+
+       return 0;
+}
+
+static void __exit pcwatchdog_exit(void)
+{
+       misc_deregister(&pcwd_miscdev);
+       /*  Disable the board  */
+       if (revision == PCWD_REVISION_C) {
+               outb_p(0xA5, current_readport + 3);
+               outb_p(0xA5, current_readport + 3);
+       }
+       if (supports_temp)
+               misc_deregister(&temp_miscdev);
+
+       release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);
+}
+
+module_init(pcwatchdog_init);
+module_exit(pcwatchdog_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c
new file mode 100644 (file)
index 0000000..d34380c
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ *     60xx Single Board Computer Watchdog Timer driver for Linux 2.2.x
+ *
+ *      Based on acquirewdt.c by Alan Cox.
+ *
+ *     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.
+ *     
+ *     The author does NOT admit liability nor provide warranty for 
+ *     any of this software. This material is provided "AS-IS" in 
+ *      the hope that it may be useful for others.
+ *
+ *     (c) Copyright 2000    Jakob Oestergaard <jakob@ostenfeld.dk>
+ *
+ *           12/4 - 2000      [Initial revision]
+ *           25/4 - 2000      Added /dev/watchdog support
+ *           09/5 - 2001      [smj@oro.net] fixed fop_write to "return 1" on success
+ *
+ *
+ *  Theory of operation:
+ *  A Watchdog Timer (WDT) is a hardware circuit that can 
+ *  reset the computer system in case of a software fault.
+ *  You probably knew that already.
+ *
+ *  Usually a userspace daemon will notify the kernel WDT driver
+ *  via the /proc/watchdog special device file that userspace is
+ *  still alive, at regular intervals.  When such a notification
+ *  occurs, the driver will usually tell the hardware watchdog
+ *  that everything is in order, and that the watchdog should wait
+ *  for yet another little while to reset the system.
+ *  If userspace fails (RAM error, kernel bug, whatever), the
+ *  notifications cease to occur, and the hardware watchdog will
+ *  reset the system (causing a reboot) after the timeout occurs.
+ *
+ *  This WDT driver is different from the other Linux WDT 
+ *  drivers in several ways:
+ *  *)  The driver will ping the watchdog by itself, because this
+ *      particular WDT has a very short timeout (one second) and it
+ *      would be insane to count on any userspace daemon always
+ *      getting scheduled within that time frame.
+ *  *)  This driver expects the userspace daemon to send a specific
+ *      character code ('V') to /dev/watchdog before closing the
+ *      /dev/watchdog file.  If the userspace daemon closes the file
+ *      without sending this special character, the driver will assume
+ *      that the daemon (and userspace in general) died, and will
+ *      stop pinging the WDT without disabling it first.  This will
+ *      cause a reboot.
+ *
+ *  Why `V' ?  Well, `V' is the character in ASCII for the value 86,
+ *  and we all know that 86 is _the_ most random number in the universe.
+ *  Therefore it is the letter that has the slightest chance of occuring
+ *  by chance, when the system becomes corrupted.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/smp_lock.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+#define OUR_NAME "sbc60xxwdt"
+
+/*
+ * You must set these - The driver cannot probe for the settings
+ */
+#define WDT_STOP 0x45
+#define WDT_START 0x443
+
+/*
+ * The 60xx board can use watchdog timeout values from one second
+ * to several minutes.  The default is one second, so if we reset
+ * the watchdog every ~250ms we should be safe.
+ */
+
+#define WDT_INTERVAL (HZ/4+1)
+
+/*
+ * We must not require too good response from the userspace daemon.
+ * Here we require the userspace daemon to send us a heartbeat
+ * char to /dev/watchdog every 10 seconds.
+ * If the daemon pulses us every 5 seconds, we can still afford
+ * a 5 second scheduling delay on the (high priority) daemon. That
+ * should be sufficient for a box under any load.
+ */
+
+#define WDT_HEARTBEAT (HZ * 10)
+
+static void wdt_timer_ping(unsigned long);
+static struct timer_list timer;
+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
+ */
+
+static void wdt_timer_ping(unsigned long data)
+{
+       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
+        * we agree to ping the WDT 
+        */
+       if(time_before(jiffies, next_heartbeat)) 
+       {
+               /* Ping the WDT by reading from WDT_START */
+               inb_p(WDT_START);
+               /* Re-set the timer interval */
+               timer.expires = jiffies + WDT_INTERVAL;
+               add_timer(&timer);
+       } else {
+               printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n");
+       }
+}
+
+/* 
+ * Utility routines
+ */
+
+static void wdt_startup(void)
+{
+       next_heartbeat = jiffies + WDT_HEARTBEAT;
+
+       /* Start the timer */
+       timer.expires = jiffies + WDT_INTERVAL; 
+       add_timer(&timer);
+       printk(OUR_NAME ": Watchdog timer is now enabled.\n");  
+}
+
+static void wdt_turnoff(void)
+{
+       /* Stop the timer */
+       del_timer(&timer);
+       inb_p(WDT_STOP);
+       printk(OUR_NAME ": Watchdog timer is now disabled...\n");
+}
+
+
+/*
+ * /dev/watchdog handling
+ */
+
+static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos)
+{
+       /* We can't seek */
+       if(ppos != &file->f_pos)
+               return -ESPIPE;
+
+       /* See if we got the magic character */
+       if(count) 
+       {
+               size_t ofs;
+
+               /* note: just in case someone wrote the magic character
+                * five months ago... */
+               wdt_expect_close = 0;
+
+               /* now scan */
+               for(ofs = 0; ofs != count; ofs++) 
+               {
+                       char c;
+                       if(get_user(c, buf+ofs))
+                               return -EFAULT;
+                       if(c == 'V')
+                               wdt_expect_close = 1;
+               }
+               /* Well, anyhow someone wrote to us, we should return that favour */
+               next_heartbeat = jiffies + WDT_HEARTBEAT;
+               return 1;
+       }
+       return 0;
+}
+
+static ssize_t fop_read(struct file * file, char * buf, size_t count, loff_t * ppos)
+{
+       /* No can do */
+       return -EINVAL;
+}
+
+static int fop_open(struct inode * inode, struct file * file)
+{
+       switch(minor(inode->i_rdev)) 
+       {
+               case WATCHDOG_MINOR:
+                       /* 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();
+                       return 0;
+
+               default:
+                       return -ENODEV;
+       }
+}
+
+static int fop_close(struct inode * inode, struct file * file)
+{
+       if(minor(inode->i_rdev) == WATCHDOG_MINOR) 
+       {
+               if(wdt_expect_close && !nowayout)
+                       wdt_turnoff();
+               else {
+                       del_timer(&timer);
+                       printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n");
+               }
+       }
+       wdt_is_open = 0;
+       return 0;
+}
+
+static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       static struct watchdog_info ident=
+       {
+               0,
+               1,
+               "SB60xx"
+       };
+       
+       switch(cmd)
+       {
+               default:
+                       return -ENOTTY;
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
+               case WDIOC_KEEPALIVE:
+                       next_heartbeat = jiffies + WDT_HEARTBEAT;
+                       return 0;
+       }
+}
+
+static struct file_operations wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .read           = fop_read,
+       .write          = fop_write,
+       .open           = fop_open,
+       .release        = fop_close,
+       .ioctl          = fop_ioctl
+};
+
+static struct miscdevice wdt_miscdev = {
+       WATCHDOG_MINOR,
+       "watchdog",
+       &wdt_fops
+};
+
+/*
+ *     Notifier for system down
+ */
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT) 
+               wdt_turnoff();
+       return NOTIFY_DONE;
+}
+/*
+ *     The WDT needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off. 
+ */
+static struct notifier_block wdt_notifier=
+{
+       wdt_notify_sys,
+       0,
+       0
+};
+
+static void __exit sbc60xxwdt_unload(void)
+{
+       wdt_turnoff();
+
+       /* Deregister */
+       misc_deregister(&wdt_miscdev);
+
+       unregister_reboot_notifier(&wdt_notifier);
+       release_region(WDT_START,1);
+       release_region(WDT_STOP,1);
+}
+
+static int __init sbc60xxwdt_init(void)
+{
+       int rc = -EBUSY;
+
+       if (!request_region(WDT_STOP, 1, "SBC 60XX WDT"))
+               goto err_out;
+       if (!request_region(WDT_START, 1, "SBC 60XX WDT"))
+               goto err_out_region1;
+
+       init_timer(&timer);
+       timer.function = wdt_timer_ping;
+       timer.data = 0;
+
+       rc = misc_register(&wdt_miscdev);
+       if (rc)
+               goto err_out_region2;
+
+       rc = register_reboot_notifier(&wdt_notifier);
+       if (rc)
+               goto err_out_miscdev;
+
+       printk(KERN_INFO OUR_NAME ": WDT driver for 60XX single board computer initialised.\n");
+       
+       return 0;
+
+err_out_miscdev:
+       misc_deregister(&wdt_miscdev);
+err_out_region2:
+       release_region(WDT_START,1);
+err_out_region1:
+       release_region(WDT_STOP,1);
+err_out:
+       return rc;
+}
+
+module_init(sbc60xxwdt_init);
+module_exit(sbc60xxwdt_unload);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
new file mode 100644 (file)
index 0000000..41fa773
--- /dev/null
@@ -0,0 +1,277 @@
+/* linux/drivers/char/scx200_wdt.c 
+
+   National Semiconductor SCx200 Watchdog support
+
+   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com>
+
+   Som code taken from:
+   National Semiconductor PC87307/PC97307 (ala SC1200) WDT driver
+   (c) Copyright 2002 Zwane Mwaikambo <zwane@commfireservices.com>
+
+   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.
+
+   The author(s) of this software shall not be held liable for damages
+   of any nature resulting due to the use of this software. This
+   software is provided AS-IS with no warranties. */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <asm/uaccess.h>
+#include <asm/io.h>
+
+#include <linux/scx200.h>
+
+#define NAME "scx200_wdt"
+
+MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
+MODULE_DESCRIPTION("NatSemi SCx200 Watchdog Driver");
+MODULE_LICENSE("GPL");
+
+#ifndef CONFIG_WATCHDOG_NOWAYOUT
+#define CONFIG_WATCHDOG_NOWAYOUT 0
+#endif
+
+static int margin = 60;                /* in seconds */
+MODULE_PARM(margin, "i");
+MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
+
+static int nowayout = CONFIG_WATCHDOG_NOWAYOUT;
+MODULE_PARM(nowayout, "i");
+MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
+
+static u16 wdto_restart;
+static struct semaphore open_semaphore;
+static unsigned expect_close;
+
+/* Bits of the WDCNFG register */
+#define W_ENABLE 0x00fa                /* Enable watchdog */
+#define W_DISABLE 0x0000       /* Disable watchdog */
+
+/* The scaling factor for the timer, this depends on the value of W_ENABLE */
+#define W_SCALE (32768/1024)
+
+static void scx200_wdt_ping(void)
+{
+       outw(wdto_restart, SCx200_CB_BASE + SCx200_WDT_WDTO);
+}
+
+static void scx200_wdt_update_margin(void)
+{
+       printk(KERN_INFO NAME ": timer margin %d seconds\n", margin);
+       wdto_restart = margin * W_SCALE;
+}
+
+static void scx200_wdt_enable(void)
+{
+       printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n", 
+              wdto_restart);
+
+       outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO);
+       outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS);
+       outw(W_ENABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG);
+
+       scx200_wdt_ping();
+}
+
+static void scx200_wdt_disable(void)
+{
+       printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
+               
+       outw(0, SCx200_CB_BASE + SCx200_WDT_WDTO);
+       outb(SCx200_WDT_WDSTS_WDOVF, SCx200_CB_BASE + SCx200_WDT_WDSTS);
+       outw(W_DISABLE, SCx200_CB_BASE + SCx200_WDT_WDCNFG);
+}
+
+static int scx200_wdt_open(struct inode *inode, struct file *file)
+{
+        /* only allow one at a time */
+        if (down_trylock(&open_semaphore))
+                return -EBUSY;
+       scx200_wdt_enable();
+       expect_close = 0;
+
+       return 0;
+}
+
+static int scx200_wdt_release(struct inode *inode, struct file *file)
+{
+       if (!expect_close) {
+               printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n");
+       } else if (!nowayout) {
+               scx200_wdt_disable();
+       }
+        up(&open_semaphore);
+
+       return 0;
+}
+
+static int scx200_wdt_notify_sys(struct notifier_block *this, 
+                                     unsigned long code, void *unused)
+{
+        if (code == SYS_HALT || code == SYS_POWER_OFF)
+               if (!nowayout)
+                       scx200_wdt_disable();
+
+        return NOTIFY_DONE;
+}
+
+static struct notifier_block scx200_wdt_notifier =
+{
+        .notifier_call = scx200_wdt_notify_sys
+};
+
+static ssize_t scx200_wdt_write(struct file *file, const char *data, 
+                                    size_t len, loff_t *ppos)
+{
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       /* check for a magic close character */
+       if (len) 
+       {
+               size_t i;
+
+               scx200_wdt_ping();
+
+               expect_close = 0;
+               for (i = 0; i < len; ++i) {
+                       char c;
+                       if (get_user(c, data+i))
+                               return -EFAULT;
+                       if (c == 'V')
+                               expect_close = 1;
+               }
+
+               return len;
+       }
+
+       return 0;
+}
+
+static int scx200_wdt_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       static struct watchdog_info ident = {
+               .identity = "NatSemi SCx200 Watchdog",
+               .firmware_version = 1, 
+               .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING),
+       };
+       int new_margin;
+       
+       switch (cmd) {
+       default:
+               return -ENOTTY;
+       case WDIOC_GETSUPPORT:
+               if(copy_to_user((struct watchdog_info *)arg, &ident, 
+                               sizeof(ident)))
+                       return -EFAULT;
+               return 0;
+       case WDIOC_GETSTATUS:
+       case WDIOC_GETBOOTSTATUS:
+               if (put_user(0, (int *)arg))
+                       return -EFAULT;
+               return 0;
+       case WDIOC_KEEPALIVE:
+               scx200_wdt_ping();
+               return 0;
+       case WDIOC_SETTIMEOUT:
+               if (get_user(new_margin, (int *)arg))
+                       return -EFAULT;
+               if (new_margin < 1)
+                       return -EINVAL;
+               margin = new_margin;
+               scx200_wdt_update_margin();
+               scx200_wdt_ping();
+       case WDIOC_GETTIMEOUT:
+               if (put_user(margin, (int *)arg))
+                       return -EFAULT;
+               return 0;
+       }
+}
+
+static struct file_operations scx200_wdt_fops = {
+       .owner   = THIS_MODULE,
+       .write   = scx200_wdt_write,
+       .ioctl   = scx200_wdt_ioctl,
+       .open    = scx200_wdt_open,
+       .release = scx200_wdt_release,
+};
+
+static struct miscdevice scx200_wdt_miscdev = {
+       .minor = WATCHDOG_MINOR,
+       .name  = NAME,
+       .fops  = &scx200_wdt_fops,
+};
+
+static int __init scx200_wdt_init(void)
+{
+       int r;
+
+       printk(KERN_DEBUG NAME ": NatSemi SCx200 Watchdog Driver\n");
+
+       /* First check that this really is a NatSemi SCx200 CPU */
+       if ((pci_find_device(PCI_VENDOR_ID_NS, 
+                            PCI_DEVICE_ID_NS_SCx200_BRIDGE,
+                            NULL)) == NULL)
+               return -ENODEV;
+
+       /* More sanity checks, verify that the configuration block is there */
+       if (!scx200_cb_probe(SCx200_CB_BASE)) {
+               printk(KERN_WARNING NAME ": no configuration block found\n");
+               return -ENODEV;
+       }
+
+       if (!request_region(SCx200_CB_BASE + SCx200_WDT_OFFSET, 
+                           SCx200_WDT_SIZE, 
+                           "NatSemi SCx200 Watchdog")) {
+               printk(KERN_WARNING NAME ": watchdog I/O region busy\n");
+               return -EBUSY;
+       }
+
+       scx200_wdt_update_margin();
+       scx200_wdt_disable();
+
+       sema_init(&open_semaphore, 1);
+
+       r = misc_register(&scx200_wdt_miscdev);
+       if (r)
+               return r;
+
+       r = register_reboot_notifier(&scx200_wdt_notifier);
+        if (r) {
+                printk(KERN_ERR NAME ": unable to register reboot notifier");
+               misc_deregister(&scx200_wdt_miscdev);
+                return r;
+        }
+
+       return 0;
+}
+
+static void __exit scx200_wdt_cleanup(void)
+{
+        unregister_reboot_notifier(&scx200_wdt_notifier);
+       misc_deregister(&scx200_wdt_miscdev);
+       release_region(SCx200_CB_BASE + SCx200_WDT_OFFSET,
+                      SCx200_WDT_SIZE);
+}
+
+module_init(scx200_wdt_init);
+module_exit(scx200_wdt_cleanup);
+
+/*
+    Local variables:
+        compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules"
+        c-basic-offset: 8
+    End:
+*/
diff --git a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c
new file mode 100644 (file)
index 0000000..8761e4a
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * drivers/char/shwdt.c
+ *
+ * Watchdog driver for integrated watchdog in the SuperH 3/4 processors.
+ *
+ * Copyright (C) 2001 Paul Mundt <lethal@chaoticdreams.org>
+ *
+ * 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.
+ *
+ * 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>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/notifier.h>
+#include <linux/ioport.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#if defined(CONFIG_CPU_SH4)
+  #define WTCNT                0xffc00008
+  #define WTCSR                0xffc0000c
+#elif defined(CONFIG_CPU_SH3)
+  #define WTCNT                0xffffff84
+  #define WTCSR                0xffffff86
+#else
+  #error "Can't use SH 3/4 watchdog on non-SH 3/4 processor."
+#endif
+
+#define WTCNT_HIGH     0x5a00
+#define WTCSR_HIGH     0xa500
+
+#define WTCSR_TME      0x80
+#define WTCSR_WT       0x40
+#define WTCSR_RSTS     0x20
+#define WTCSR_WOVF     0x10
+#define WTCSR_IOVF     0x08
+#define WTCSR_CKS2     0x04
+#define WTCSR_CKS1     0x02
+#define WTCSR_CKS0     0x01
+
+/*
+ * CKS0-2 supports a number of clock division ratios. At the time the watchdog
+ * is enabled, it defaults to a 41 usec overflow period .. we overload this to
+ * something a little more reasonable, and really can't deal with anything
+ * lower than WTCSR_CKS_1024, else we drop back into the usec range.
+ *
+ * Clock Division Ratio         Overflow Period
+ * --------------------------------------------
+ *     1/32 (initial value)       41 usecs
+ *     1/64                       82 usecs
+ *     1/128                     164 usecs
+ *     1/256                     328 usecs
+ *     1/512                     656 usecs
+ *     1/1024                   1.31 msecs
+ *     1/2048                   2.62 msecs
+ *     1/4096                   5.25 msecs
+ */
+#define WTCSR_CKS_32   0x00
+#define WTCSR_CKS_64   0x01
+#define WTCSR_CKS_128  0x02
+#define WTCSR_CKS_256  0x03
+#define WTCSR_CKS_512  0x04
+#define WTCSR_CKS_1024 0x05
+#define WTCSR_CKS_2048 0x06
+#define WTCSR_CKS_4096 0x07
+
+/*
+ * Default clock division ratio is 5.25 msecs. Overload this at module load
+ * time. Any value not in the msec range will default to a timeout of one
+ * jiffy, which exceeds the usec overflow periods.
+ */
+static int clock_division_ratio = WTCSR_CKS_4096;
+
+#define msecs_to_jiffies(msecs)        (jiffies + ((HZ * msecs + 999) / 1000))
+#define next_ping_period(cks)  msecs_to_jiffies(cks - 4)
+#define user_ping_period(cks)  (next_ping_period(cks) * 10)
+
+static unsigned long sh_is_open = 0;
+static struct watchdog_info sh_wdt_info;
+static struct timer_list timer;
+static unsigned long next_heartbeat;
+
+#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
+ *
+ *     @val: Value to write
+ *
+ *     Writes the given value @val to the lower byte of the timer counter.
+ *     The upper byte is set manually on each write.
+ */
+static void sh_wdt_write_cnt(__u8 val)
+{
+       ctrl_outw(WTCNT_HIGH | (__u16)val, WTCNT);
+}
+
+/**
+ *     sh_wdt_write_csr - Write to Control/Status Register
+ *
+ *     @val: Value to write
+ *
+ *     Writes the given value @val to the lower byte of the control/status
+ *     register. The upper byte is set manually on each write.
+ */
+static void sh_wdt_write_csr(__u8 val)
+{
+       ctrl_outw(WTCSR_HIGH | (__u16)val, WTCSR);
+}
+
+/**
+ *     sh_wdt_start - Start the Watchdog
+ *
+ *     Starts the watchdog.
+ */
+static void sh_wdt_start(void)
+{
+       timer.expires = next_ping_period(clock_division_ratio);
+       next_heartbeat = user_ping_period(clock_division_ratio);
+       add_timer(&timer);
+
+       sh_wdt_write_csr(WTCSR_WT | WTCSR_CKS_4096);
+       sh_wdt_write_cnt(0);
+       sh_wdt_write_csr((ctrl_inb(WTCSR) | WTCSR_TME));
+}
+
+/**
+ *     sh_wdt_stop - Stop the Watchdog
+ *
+ *     Stops the watchdog.
+ */
+static void sh_wdt_stop(void)
+{
+       del_timer(&timer);
+
+       sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_TME));
+}
+
+/**
+ *     sh_wdt_ping - Ping the Watchdog
+ *
+ *     @data: Unused
+ *
+ *     Clears overflow bit, resets timer counter.
+ */
+static void sh_wdt_ping(unsigned long data)
+{
+       if (time_before(jiffies, next_heartbeat)) {
+               sh_wdt_write_csr((ctrl_inb(WTCSR) & ~WTCSR_IOVF));
+               sh_wdt_write_cnt(0);
+
+               timer.expires = next_ping_period(clock_division_ratio);
+               add_timer(&timer);
+       }
+}
+
+/**
+ *     sh_wdt_open - Open the Device
+ *
+ *     @inode: inode of device
+ *     @file: file handle of device
+ *
+ *     Watchdog device is opened and started.
+ */
+static int sh_wdt_open(struct inode *inode, struct file *file)
+{
+       switch (minor(inode->i_rdev)) {
+               case WATCHDOG_MINOR:
+                       if (test_and_set_bit(0, &sh_is_open))
+                               return -EBUSY;
+
+                       if (nowayout) {
+                               MOD_INC_USE_COUNT;
+                       }
+
+                       sh_wdt_start();
+
+                       break;
+               default:
+                       return -ENODEV;
+       }
+
+       return 0;
+}
+
+/**
+ *     sh_wdt_close - Close the Device
+ *
+ *     @inode: inode of device
+ *     @file: file handle of device
+ *
+ *     Watchdog device is closed and stopped.
+ */
+static int sh_wdt_close(struct inode *inode, struct file *file)
+{
+       if (minor(inode->i_rdev) == WATCHDOG_MINOR) {
+               if (!nowayout) {
+                       sh_wdt_stop();
+               }
+               clear_bit(0, &sh_is_open);
+       }
+       
+       return 0;
+}
+
+/**
+ *     sh_wdt_read - Read from Device
+ *
+ *     @file: file handle of device
+ *     @buf: buffer to write to
+ *     @count: length of buffer
+ *     @ppos: offset
+ *
+ *     Unsupported.
+ */
+static ssize_t sh_wdt_read(struct file *file, char *buf,
+                          size_t count, loff_t *ppos)
+{
+       return -EINVAL;
+}
+
+/**
+ *     sh_wdt_write - Write to Device
+ *
+ *     @file: file handle of device
+ *     @buf: buffer to write
+ *     @count: length of buffer
+ *     @ppos: offset
+ *
+ *     Pings the watchdog on write.
+ */
+static ssize_t sh_wdt_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) {
+               next_heartbeat = user_ping_period(clock_division_ratio);
+               return 1;
+       }
+
+       return 0;
+}
+
+/**
+ *     sh_wdt_ioctl - Query Device
+ *
+ *     @inode: inode of device
+ *     @file: file handle of device
+ *     @cmd: watchdog command
+ *     @arg: argument
+ *
+ *     Query basic information from the device or ping it, as outlined by the
+ *     watchdog API.
+ */
+static int sh_wdt_ioctl(struct inode *inode, struct file *file,
+                       unsigned int cmd, unsigned long arg)
+{
+       switch (cmd) {
+               case WDIOC_GETSUPPORT:
+                       if (copy_to_user((struct watchdog_info *)arg,
+                                         &sh_wdt_info,
+                                         sizeof(sh_wdt_info))) {
+                               return -EFAULT;
+                       }
+                       
+                       break;
+               case WDIOC_GETSTATUS:
+                       if (copy_to_user((int *)arg,
+                                        &sh_is_open,
+                                        sizeof(int))) {
+                               return -EFAULT;
+                       }
+
+                       break;
+               case WDIOC_KEEPALIVE:
+                       next_heartbeat = user_ping_period(clock_division_ratio);
+                       
+                       break;
+               default:
+                       return -ENOTTY;
+       }
+
+       return 0;
+}
+
+/**
+ *     sh_wdt_notify_sys - Notifier Handler
+ *     
+ *     @this: notifier block
+ *     @code: notifier event
+ *     @unused: unused
+ *
+ *     Handles specific events, such as turning off the watchdog during a
+ *     shutdown event.
+ */
+static int sh_wdt_notify_sys(struct notifier_block *this,
+                            unsigned long code, void *unused)
+{
+       if (code == SYS_DOWN || code == SYS_HALT) {
+               sh_wdt_stop();
+       }
+
+       return NOTIFY_DONE;
+}
+
+static struct file_operations sh_wdt_fops = {
+       .owner          = THIS_MODULE,
+       .read           = sh_wdt_read,
+       .write          = sh_wdt_write,
+       .ioctl          = sh_wdt_ioctl,
+       .open           = sh_wdt_open,
+       .release        = sh_wdt_close,
+};
+
+static struct watchdog_info sh_wdt_info = {
+       WDIOF_KEEPALIVEPING,
+       1,
+       "SH WDT",
+};
+
+static struct notifier_block sh_wdt_notifier = {
+       sh_wdt_notify_sys,
+       NULL,
+       0
+};
+
+static struct miscdevice sh_wdt_miscdev = {
+       WATCHDOG_MINOR,
+       "watchdog",
+       &sh_wdt_fops,
+};
+
+/**
+ *     sh_wdt_init - Initialize module
+ *
+ *     Registers the device and notifier handler. Actual device
+ *     initialization is handled by sh_wdt_open().
+ */
+static int __init sh_wdt_init(void)
+{
+       if (misc_register(&sh_wdt_miscdev)) {
+               printk(KERN_ERR "shwdt: Can't register misc device\n");
+               return -EINVAL;
+       }
+
+       if (!request_region(WTCNT, 1, "shwdt")) {
+               printk(KERN_ERR "shwdt: Can't request WTCNT region\n");
+               misc_deregister(&sh_wdt_miscdev);
+               return -ENXIO;
+       }
+
+       if (!request_region(WTCSR, 1, "shwdt")) {
+               printk(KERN_ERR "shwdt: Can't request WTCSR region\n");
+               release_region(WTCNT, 1);
+               misc_deregister(&sh_wdt_miscdev);
+               return -ENXIO;
+       }
+
+       if (register_reboot_notifier(&sh_wdt_notifier)) {
+               printk(KERN_ERR "shwdt: Can't register reboot notifier\n");
+               release_region(WTCSR, 1);
+               release_region(WTCNT, 1);
+               misc_deregister(&sh_wdt_miscdev);
+               return -EINVAL;
+       }
+
+       init_timer(&timer);
+       timer.function = sh_wdt_ping;
+       timer.data = 0;
+
+       return 0;
+}
+
+/**
+ *     sh_wdt_exit - Deinitialize module
+ *
+ *     Unregisters the device and notifier handler. Actual device
+ *     deinitialization is handled by sh_wdt_close().
+ */
+static void __exit sh_wdt_exit(void)
+{
+       unregister_reboot_notifier(&sh_wdt_notifier);
+       release_region(WTCSR, 1);
+       release_region(WTCNT, 1);
+       misc_deregister(&sh_wdt_miscdev);
+}
+
+MODULE_AUTHOR("Paul Mundt <lethal@chaoticdreams.org>");
+MODULE_DESCRIPTION("SH 3/4 watchdog driver");
+MODULE_LICENSE("GPL");
+MODULE_PARM(clock_division_ratio, "i");
+MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7.");
+
+module_init(sh_wdt_init);
+module_exit(sh_wdt_exit);
+
diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c
new file mode 100644 (file)
index 0000000..de7e133
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ *     SoftDog 0.06:   A Software Watchdog Device
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     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.       
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ *     Software only watchdog driver. Unlike its big brother the WDT501P
+ *     driver this won't always recover a failed machine.
+ *
+ *  03/96: Angelo Haritsis <ah@doc.ic.ac.uk> :
+ *     Modularised.
+ *     Added soft_margin; use upon insmod to change the timer delay.
+ *     NB: uses same minor as wdt (WATCHDOG_MINOR); we could use separate
+ *         minors.
+ *
+ *  19980911 Alan Cox
+ *     Made SMP safe for 2.3.x
+ *
+ *  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>
+#include <linux/config.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/smp_lock.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+
+#define TIMER_MARGIN   60              /* (secs) Default is 1 minute */
+
+static int soft_margin = TIMER_MARGIN; /* in seconds */
+
+MODULE_PARM(soft_margin,"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");
+
+/*
+ *     Our timer
+ */
+static void watchdog_fire(unsigned long);
+
+static struct timer_list watchdog_ticktock =
+               TIMER_INITIALIZER(watchdog_fire, 0, 0);
+static int timer_alive;
+
+
+/*
+ *     If the timer expires..
+ */
+static void watchdog_fire(unsigned long data)
+{
+#ifdef ONLY_TESTING
+               printk(KERN_CRIT "SOFTDOG: Would Reboot.\n");
+#else
+       printk(KERN_CRIT "SOFTDOG: Initiating system reboot.\n");
+       machine_restart(NULL);
+       printk("WATCHDOG: Reboot didn't ?????\n");
+#endif
+}
+
+/*
+ *     Allow only one person to hold it open
+ */
+static int softdog_open(struct inode *inode, struct file *file)
+{
+       if(timer_alive)
+               return -EBUSY;
+       if (nowayout) {
+               MOD_INC_USE_COUNT;
+       }
+       /*
+        *      Activate timer
+        */
+       mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
+       timer_alive=1;
+       return 0;
+}
+
+static int softdog_release(struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer.
+        *      Lock it in if it's a module and we set nowayout
+        */
+       if(!nowayout) {
+               del_timer(&watchdog_ticktock);
+       }
+       timer_alive=0;
+       return 0;
+}
+
+static ssize_t softdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+       /*  Can't seek (pwrite) on this device  */
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       /*
+        *      Refresh the timer.
+        */
+       if(len) {
+               mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
+               return 1;
+       }
+       return 0;
+}
+
+static int softdog_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       static struct watchdog_info ident = {
+               identity: "Software Watchdog",
+       };
+       switch (cmd) {
+               default:
+                       return -ENOTTY;
+               case WDIOC_GETSUPPORT:
+                       if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+                               return -EFAULT;
+                       return 0;
+               case WDIOC_GETSTATUS:
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0,(int *)arg);
+               case WDIOC_KEEPALIVE:
+                       mod_timer(&watchdog_ticktock, jiffies+(soft_margin*HZ));
+                       return 0;
+       }
+}
+
+static struct file_operations softdog_fops = {
+       owner:          THIS_MODULE,
+       write:          softdog_write,
+       ioctl:          softdog_ioctl,
+       open:           softdog_open,
+       release:        softdog_release,
+};
+
+static struct miscdevice softdog_miscdev = {
+       minor:          WATCHDOG_MINOR,
+       name:           "watchdog",
+       fops:           &softdog_fops,
+};
+
+static char banner[] __initdata = KERN_INFO "Software Watchdog Timer: 0.06, soft_margin: %d sec, nowayout: %d\n";
+
+static int __init watchdog_init(void)
+{
+       int ret;
+
+       ret = misc_register(&softdog_miscdev);
+
+       if (ret)
+               return ret;
+
+       printk(banner, soft_margin, nowayout);
+
+       return 0;
+}
+
+static void __exit watchdog_exit(void)
+{
+       misc_deregister(&softdog_miscdev);
+}
+
+module_init(watchdog_init);
+module_exit(watchdog_exit);
diff --git a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c
new file mode 100644 (file)
index 0000000..6674967
--- /dev/null
@@ -0,0 +1,366 @@
+/*
+ *     W83877F Computer Watchdog Timer driver for Linux 2.4.x
+ *
+ *      Based on acquirewdt.c by Alan Cox,
+ *           and sbc60xxwdt.c by Jakob Oestergaard <jakob@ostenfeld.dk>
+ *     
+ *     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.
+ *     
+ *     The authors do NOT admit liability nor provide warranty for 
+ *     any of this software. This material is provided "AS-IS" in 
+ *      the hope that it may be useful for others.
+ *
+ *     (c) Copyright 2001    Scott Jennings <linuxdrivers@oro.net>
+ *
+ *           4/19 - 2001      [Initial revision]
+ *           9/27 - 2001      Added spinlocking
+ *
+ *
+ *  Theory of operation:
+ *  A Watchdog Timer (WDT) is a hardware circuit that can 
+ *  reset the computer system in case of a software fault.
+ *  You probably knew that already.
+ *
+ *  Usually a userspace daemon will notify the kernel WDT driver
+ *  via the /proc/watchdog special device file that userspace is
+ *  still alive, at regular intervals.  When such a notification
+ *  occurs, the driver will usually tell the hardware watchdog
+ *  that everything is in order, and that the watchdog should wait
+ *  for yet another little while to reset the system.
+ *  If userspace fails (RAM error, kernel bug, whatever), the
+ *  notifications cease to occur, and the hardware watchdog will
+ *  reset the system (causing a reboot) after the timeout occurs.
+ *
+ *  This WDT driver is different from most other Linux WDT
+ *  drivers in that the driver will ping the watchdog by itself,
+ *  because this particular WDT has a very short timeout (1.6
+ *  seconds) and it would be insane to count on any userspace
+ *  daemon always getting scheduled within that time frame.
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/smp_lock.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+#define OUR_NAME "w83877f_wdt"
+
+#define ENABLE_W83877F_PORT 0x3F0
+#define ENABLE_W83877F 0x87
+#define DISABLE_W83877F 0xAA
+#define WDT_PING 0x443
+#define WDT_REGISTER 0x14
+#define WDT_ENABLE 0x9C
+#define WDT_DISABLE 0x8C
+
+/*
+ * The W83877F seems to be fixed at 1.6s timeout (at least on the
+ * EMACS PC-104 board I'm using). If we reset the watchdog every
+ * ~250ms we should be safe.  */
+
+#define WDT_INTERVAL (HZ/4+1)
+
+/*
+ * We must not require too good response from the userspace daemon.
+ * Here we require the userspace daemon to send us a heartbeat
+ * char to /dev/watchdog every 30 seconds.
+ */
+
+#define WDT_HEARTBEAT (HZ * 30)
+
+static void wdt_timer_ping(unsigned long);
+static struct timer_list timer;
+static unsigned long next_heartbeat;
+static unsigned long wdt_is_open;
+static int wdt_expect_close;
+static spinlock_t wdt_spinlock;
+
+/*
+ *     Whack the dog
+ */
+
+static void wdt_timer_ping(unsigned long data)
+{
+       /* If we got a heartbeat pulse within the WDT_US_INTERVAL
+        * we agree to ping the WDT 
+        */
+       if(time_before(jiffies, next_heartbeat)) 
+       {
+               /* Ping the WDT */
+               spin_lock(&wdt_spinlock);
+
+               /* Ping the WDT by reading from WDT_PING */
+               inb_p(WDT_PING);
+
+               /* Re-set the timer interval */
+               timer.expires = jiffies + WDT_INTERVAL;
+               add_timer(&timer);
+
+               spin_unlock(&wdt_spinlock);
+
+       } else {
+               printk(OUR_NAME ": Heartbeat lost! Will not ping the watchdog\n");
+       }
+}
+
+/* 
+ * Utility routines
+ */
+
+static void wdt_change(int writeval)
+{
+       unsigned long flags;
+       spin_lock_irqsave(&wdt_spinlock, flags);
+
+       /* buy some time */
+       inb_p(WDT_PING);
+
+       /* make W83877F available */
+       outb_p(ENABLE_W83877F,  ENABLE_W83877F_PORT);
+       outb_p(ENABLE_W83877F,  ENABLE_W83877F_PORT);
+
+       /* enable watchdog */
+       outb_p(WDT_REGISTER,    ENABLE_W83877F_PORT);
+       outb_p(writeval,        ENABLE_W83877F_PORT+1);
+
+       /* lock the W8387FF away */
+       outb_p(DISABLE_W83877F, ENABLE_W83877F_PORT);
+
+       spin_unlock_irqrestore(&wdt_spinlock, flags);
+}
+
+static void wdt_startup(void)
+{
+       next_heartbeat = jiffies + WDT_HEARTBEAT;
+
+       /* Start the timer */
+       timer.expires = jiffies + WDT_INTERVAL; 
+       add_timer(&timer);
+
+       wdt_change(WDT_ENABLE);
+
+       printk(OUR_NAME ": Watchdog timer is now enabled.\n");  
+}
+
+static void wdt_turnoff(void)
+{
+       /* Stop the timer */
+       del_timer(&timer);
+
+       wdt_change(WDT_DISABLE);
+
+       printk(OUR_NAME ": Watchdog timer is now disabled...\n");
+}
+
+
+/*
+ * /dev/watchdog handling
+ */
+
+static ssize_t fop_write(struct file * file, const char * buf, size_t count, loff_t * ppos)
+{
+       /* We can't seek */
+       if(ppos != &file->f_pos)
+               return -ESPIPE;
+
+       /* See if we got the magic character */
+       if(count) 
+       {
+               size_t ofs;
+
+               /* note: just in case someone wrote the magic character
+                * five months ago... */
+               wdt_expect_close = 0;
+
+               /* now scan */
+               for(ofs = 0; ofs != count; ofs++)
+               {
+                       char c;
+                       if (get_user(c, buf + ofs))
+                               return -EFAULT;
+                       if (c == 'V')
+                               wdt_expect_close = 1;
+               }
+
+               /* someone wrote to us, we should restart timer */
+               next_heartbeat = jiffies + WDT_HEARTBEAT;
+               return 1;
+       };
+       return 0;
+}
+
+static ssize_t fop_read(struct file * file, char * buf, size_t count, loff_t * ppos)
+{
+       /* No can do */
+       return -EINVAL;
+}
+
+static int fop_open(struct inode * inode, struct file * file)
+{
+       switch(minor(inode->i_rdev)) 
+       {
+               case WATCHDOG_MINOR:
+                       /* Just in case we're already talking to someone... */
+                       if(test_and_set_bit(0, &wdt_is_open)) {
+                               return -EBUSY;
+                       }
+                       /* Good, fire up the show */
+                       wdt_startup();
+                       return 0;
+
+               default:
+                       return -ENODEV;
+       }
+}
+
+static int fop_close(struct inode * inode, struct file * file)
+{
+       if(minor(inode->i_rdev) == WATCHDOG_MINOR) 
+       {
+               if(wdt_expect_close)
+                       wdt_turnoff();
+               else {
+                       del_timer(&timer);
+                       printk(OUR_NAME ": device file closed unexpectedly. Will not stop the WDT!\n");
+               }
+       }
+       wdt_is_open = 0;
+       return 0;
+}
+
+static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       static struct watchdog_info ident=
+       {
+               0,
+               1,
+               "W83877F"
+       };
+       
+       switch(cmd)
+       {
+               default:
+                       return -ENOIOCTLCMD;
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
+               case WDIOC_KEEPALIVE:
+                       next_heartbeat = jiffies + WDT_HEARTBEAT;
+                       return 0;
+       }
+}
+
+static struct file_operations wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .read           = fop_read,
+       .write          = fop_write,
+       .open           = fop_open,
+       .release        = fop_close,
+       .ioctl          = fop_ioctl
+};
+
+static struct miscdevice wdt_miscdev = {
+       WATCHDOG_MINOR,
+       "watchdog",
+       &wdt_fops
+};
+
+/*
+ *     Notifier for system down
+ */
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT) 
+               wdt_turnoff();
+       return NOTIFY_DONE;
+}
+/*
+ *     The WDT needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off. 
+ */
+static struct notifier_block wdt_notifier=
+{
+       wdt_notify_sys,
+       0,
+       0
+};
+
+static void __exit w83877f_wdt_unload(void)
+{
+       wdt_turnoff();
+
+       /* Deregister */
+       misc_deregister(&wdt_miscdev);
+
+       unregister_reboot_notifier(&wdt_notifier);
+       release_region(WDT_PING,1);
+       release_region(ENABLE_W83877F_PORT,2);
+}
+
+static int __init w83877f_wdt_init(void)
+{
+       int rc = -EBUSY;
+
+       spin_lock_init(&wdt_spinlock);
+
+       if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT"))
+               goto err_out;
+       if (!request_region(WDT_PING, 1, "W8387FF WDT"))
+               goto err_out_region1;
+
+       init_timer(&timer);
+       timer.function = wdt_timer_ping;
+       timer.data = 0;
+
+       rc = misc_register(&wdt_miscdev);
+       if (rc)
+               goto err_out_region2;
+
+       rc = register_reboot_notifier(&wdt_notifier);
+       if (rc)
+               goto err_out_miscdev;
+
+       printk(KERN_INFO OUR_NAME ": WDT driver for W83877F initialised.\n");
+       
+       return 0;
+
+err_out_miscdev:
+       misc_deregister(&wdt_miscdev);
+err_out_region2:
+       release_region(WDT_PING,1);
+err_out_region1:
+       release_region(ENABLE_W83877F_PORT,2);
+err_out:
+       return rc;
+}
+
+module_init(w83877f_wdt_init);
+module_exit(w83877f_wdt_unload);
+
+MODULE_AUTHOR("Scott and Bill Jennings");
+MODULE_DESCRIPTION("Driver for watchdog timer in w83877f chip");
+MODULE_LICENSE("GPL");
+EXPORT_NO_SYMBOLS;
diff --git a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c
new file mode 100644 (file)
index 0000000..33deb30
--- /dev/null
@@ -0,0 +1,565 @@
+/*
+ *     Industrial Computer Source WDT500/501 driver for Linux 2.1.x
+ *
+ *     (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     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.       
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ *     Release 0.09.
+ *
+ *     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
+ *             Alan Cox        :       Cleaned up copy/user stuff
+ *             Tim Hockin      :       Added insmod parameters, comment cleanup
+ *                                     Parameterized timeout
+ *             Tigran Aivazian :       Restructured wdt_init() to handle failures
+ *             Matt Domsch     :       added nowayout and timeout module options
+ */
+
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include "wd501p.h"
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+static unsigned long wdt_is_open;
+
+/*
+ *     You must set these - there is no sane way to probe for this board.
+ *     You can use wdt=x,y to set these now.
+ */
+static int io=0x240;
+static int irq=11;
+
+#define WD_TIMO (100*60)               /* 1 minute */
+
+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 void __init
+wdt_validate_timeout(void)
+{
+       timeout_val = timeout * 100;
+}
+
+#ifndef MODULE
+
+/**
+ *     wdt_setup:
+ *     @str: command line string
+ *
+ *     Setup options. The board isn't really probe-able so we have to
+ *     get the user to tell us the configuration. Sane people build it 
+ *     modular but the others come here.
+ */
+static int __init wdt_setup(char *str)
+{
+       int ints[4];
+
+       str = get_options (str, ARRAY_SIZE(ints), ints);
+
+       if (ints[0] > 0)
+       {
+               io = ints[1];
+               if(ints[0] > 1)
+                       irq = ints[2];
+       }
+
+       return 1;
+}
+
+__setup("wdt=", wdt_setup);
+
+#endif /* !MODULE */
+
+MODULE_PARM(io, "i");
+MODULE_PARM_DESC(io, "WDT io port (default=0x240)");
+MODULE_PARM(irq, "i");
+MODULE_PARM_DESC(irq, "WDT irq (default=11)");
+/*
+ *     Programming support
+ */
+static void wdt_ctr_mode(int ctr, int mode)
+{
+       ctr<<=6;
+       ctr|=0x30;
+       ctr|=(mode<<1);
+       outb_p(ctr, WDT_CR);
+}
+
+static void wdt_ctr_load(int ctr, int val)
+{
+       outb_p(val&0xFF, WDT_COUNT0+ctr);
+       outb_p(val>>8, WDT_COUNT0+ctr);
+}
+
+/*
+ *     Kernel methods.
+ */
+/**
+ *     wdt_status:
+ *     
+ *     Extract the status information from a WDT watchdog device. There are
+ *     several board variants so we have to know which bits are valid. Some
+ *     bits default to one and some to zero in order to be maximally painful.
+ *
+ *     we then map the bits onto the status ioctl flags.
+ */
+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;
+}
+
+/**
+ *     wdt_interrupt:
+ *     @irq:           Interrupt number
+ *     @dev_id:        Unused as we don't allow multiple devices.
+ *     @regs:          Unused.
+ *
+ *     Handle an interrupt from the board. These are raised when the status
+ *     map changes in what the board considers an interesting way. That means
+ *     a failure condition occuring.
+ */
+void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       /*
+        *      Read the status register see what is up and
+        *      then printk it. 
+        */
+        
+       unsigned char status=inb_p(WDT_SR);
+       
+       status|=FEATUREMAP1;
+       status&=~FEATUREMAP2;   
+       
+       printk(KERN_CRIT "WDT status %d\n", status);
+       
+       if(!(status&WDC_SR_TGOOD))
+               printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT));
+       if(!(status&WDC_SR_PSUOVER))
+               printk(KERN_CRIT "PSU over voltage.\n");
+       if(!(status&WDC_SR_PSUUNDR))
+               printk(KERN_CRIT "PSU under voltage.\n");
+       if(!(status&WDC_SR_FANGOOD))
+               printk(KERN_CRIT "Possible fan fault.\n");
+       if(!(status&WDC_SR_WCCR))
+#ifdef SOFTWARE_REBOOT
+#ifdef ONLY_TESTING
+               printk(KERN_CRIT "Would Reboot.\n");
+#else          
+               printk(KERN_CRIT "Initiating system reboot.\n");
+               machine_restart(NULL);
+#endif         
+#else
+               printk(KERN_CRIT "Reset in 5ms.\n");
+#endif         
+}
+
+
+/**
+ *     wdt_ping:
+ *
+ *     Reload counter one with the watchdog timeout. We don't bother reloading
+ *     the cascade counter. 
+ */
+static void wdt_ping(void)
+{
+       /* Write a watchdog value */
+       inb_p(WDT_DC);
+       wdt_ctr_mode(1,2);
+       wdt_ctr_load(1,timeout_val);            /* Timeout */
+       outb_p(0, WDT_DC);
+}
+
+/**
+ *     wdt_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 wdt_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)
+       {
+               wdt_ping();
+               return 1;
+       }
+       return 0;
+}
+
+/**
+ *     wdt_read:
+ *     @file: file handle to the watchdog board
+ *     @buf: buffer to write 1 byte into
+ *     @count: length of buffer
+ *     @ptr: offset (no seek allowed)
+ *
+ *     Read reports the temperature in degrees Fahrenheit. The API is in
+ *     farenheit. It was designed by an imperial measurement luddite.
+ */
+static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr)
+{
+       unsigned short c=inb_p(WDT_RT);
+       unsigned char cp;
+       
+       /*  Can't seek (pread) on this device  */
+       if (ptr != &file->f_pos)
+               return -ESPIPE;
+
+       switch(minor(file->f_dentry->d_inode->i_rdev))
+       {
+               case TEMP_MINOR:
+                       c*=11;
+                       c/=15;
+                       cp=c+7;
+                       if(copy_to_user(buf,&cp,1))
+                               return -EFAULT;
+                       return 1;
+               default:
+                       return -EINVAL;
+       }
+}
+
+/**
+ *     wdt_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. We only actually usefully support
+ *     querying capabilities and current status. 
+ */
+static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       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 -ENOTTY;
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
+
+               case WDIOC_GETSTATUS:
+                       return put_user(wdt_status(),(int *)arg);
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0, (int *)arg);
+               case WDIOC_KEEPALIVE:
+                       wdt_ping();
+                       return 0;
+       }
+}
+
+/**
+ *     wdt_open:
+ *     @inode: inode of device
+ *     @file: file handle to device
+ *
+ *     One of our two misc devices has been opened. The watchdog device is
+ *     single open and on opening we load the counters. Counter zero is a 
+ *     100Hz cascade, into counter 1 which downcounts to reboot. When the
+ *     counter triggers counter 2 downcounts the length of the reset pulse
+ *     which set set to be as long as possible. 
+ */
+static int wdt_open(struct inode *inode, struct file *file)
+{
+       switch(minor(inode->i_rdev))
+       {
+               case WATCHDOG_MINOR:
+                       if(test_and_set_bit(0, &wdt_is_open))
+                               return -EBUSY;
+                       if (nowayout) {
+                               MOD_INC_USE_COUNT;
+                       }
+                       /*
+                        *      Activate 
+                        */
+        
+                       inb_p(WDT_DC);          /* Disable */
+                       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,timeout_val);    /* Timeout */
+                       wdt_ctr_load(2,65535);
+                       outb_p(0, WDT_DC);      /* Enable */
+                       return 0;
+               case TEMP_MINOR:
+                       return 0;
+               default:
+                       return -ENODEV;
+       }
+}
+
+/**
+ *     wdt_close:
+ *     @inode: inode to board
+ *     @file: file handle to board
+ *
+ *     The watchdog has a configurable API. There is a religious dispute 
+ *     between people who want their watchdog to be able to shut down and 
+ *     those who want to be sure if the watchdog manager dies the machine
+ *     reboots. In the former case we disable the counters, in the latter
+ *     case you have to open it again very soon.
+ */
+static int wdt_release(struct inode *inode, struct file *file)
+{
+       if(minor(inode->i_rdev)==WATCHDOG_MINOR)
+       {
+               if (!nowayout) {
+                       inb_p(WDT_DC);          /* Disable counters */
+                       wdt_ctr_load(2,0);      /* 0 length reset pulses now */
+               }
+               clear_bit(0, &wdt_is_open);
+       }
+       return 0;
+}
+
+/**
+ *     notify_sys:
+ *     @this: our notifier block
+ *     @code: the event being reported
+ *     @unused: unused
+ *
+ *     Our notifier is called on system shutdowns. We want to turn the card
+ *     off at reboot otherwise the machine will reboot again during memory
+ *     test or worse yet during the following fsck. This would suck, in fact
+ *     trust me - if it happens it does suck.
+ */
+
+static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT)
+       {
+               /* Turn the card off */
+               inb_p(WDT_DC);
+               wdt_ctr_load(2,0);
+       }
+       return NOTIFY_DONE;
+}
+/*
+ *     Kernel Interfaces
+ */
+static struct file_operations wdt_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .read           = wdt_read,
+       .write          = wdt_write,
+       .ioctl          = wdt_ioctl,
+       .open           = wdt_open,
+       .release        = wdt_release,
+};
+
+static struct miscdevice wdt_miscdev=
+{
+       WATCHDOG_MINOR,
+       "watchdog",
+       &wdt_fops
+};
+
+#ifdef CONFIG_WDT_501
+static struct miscdevice temp_miscdev=
+{
+       TEMP_MINOR,
+       "temperature",
+       &wdt_fops
+};
+#endif
+
+/*
+ *     The WDT card needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off. 
+ */
+static struct notifier_block wdt_notifier=
+{
+       wdt_notify_sys,
+       NULL,
+       0
+};
+
+/**
+ *     cleanup_module:
+ *
+ *     Unload the watchdog. You cannot do this with any file handles open.
+ *     If your watchdog is set to continue ticking on close and you unload
+ *     it, well it keeps ticking. We won't get the interrupt but the board
+ *     will not touch PC memory so all is fine. You just have to load a new
+ *     module in 60 seconds or reboot.
+ */
+static void __exit wdt_exit(void)
+{
+       misc_deregister(&wdt_miscdev);
+#ifdef CONFIG_WDT_501  
+       misc_deregister(&temp_miscdev);
+#endif 
+       unregister_reboot_notifier(&wdt_notifier);
+       release_region(io,8);
+       free_irq(irq, NULL);
+}
+
+/**
+ *     wdt_init:
+ *
+ *     Set up the WDT watchdog board. All we have to do is grab the
+ *     resources we require and bitch if anyone beat us to them.
+ *     The open() function will actually kick the board off.
+ */
+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);
+               goto out;
+       }
+       ret = request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL);
+       if(ret) {
+               printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq);
+               goto outmisc;
+       }
+       if (!request_region(io, 8, "wdt501p")) {
+               printk(KERN_ERR "wdt: IO %X is not free.\n", io);
+               ret = -EBUSY;
+               goto outirq;
+       }
+       ret = register_reboot_notifier(&wdt_notifier);
+       if(ret) {
+               printk(KERN_ERR "wdt: can't register reboot notifier (err=%d)\n", ret);
+               goto outreg;
+       }
+
+#ifdef CONFIG_WDT_501
+       ret = misc_register(&temp_miscdev);
+       if (ret) {
+               printk(KERN_ERR "wdt: can't misc_register (temp) on minor=%d\n", TEMP_MINOR);
+               goto outrbt;
+       }
+#endif
+
+       ret = 0;
+       printk(KERN_INFO "WDT500/501-P driver 0.07 at %X (Interrupt %d)\n", io, irq);
+out:
+       return ret;
+
+#ifdef CONFIG_WDT_501
+outrbt:
+       unregister_reboot_notifier(&wdt_notifier);
+#endif
+
+outreg:
+       release_region(io,8);
+outirq:
+       free_irq(irq, NULL);
+outmisc:
+       misc_deregister(&wdt_miscdev);
+       goto out;
+}
+
+module_init(wdt_init);
+module_exit(wdt_exit);
+
+MODULE_AUTHOR("Alan Cox");
+MODULE_DESCRIPTION("Driver for ISA ICS watchdog cards (WDT500/501)");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/wdt285.c b/drivers/char/watchdog/wdt285.c
new file mode 100644 (file)
index 0000000..639ab2a
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ *     Intel 21285 watchdog driver
+ *     Copyright (c) Phil Blundell <pb@nexus.co.uk>, 1998
+ *
+ *     based on
+ *
+ *     SoftDog 0.05:   A Software Watchdog Device
+ *
+ *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *
+ *     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.
+ *     
+ */
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/smp_lock.h>
+
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/hardware/dec21285.h>
+
+/*
+ * Define this to stop the watchdog actually rebooting the machine.
+ */
+#undef ONLY_TESTING
+
+#define TIMER_MARGIN   60              /* (secs) Default is 1 minute */
+
+#define FCLK   (50*1000*1000)          /* 50MHz */
+
+static int soft_margin = TIMER_MARGIN; /* in seconds */
+static int timer_alive;
+
+#ifdef ONLY_TESTING
+/*
+ *     If the timer expires..
+ */
+
+static void watchdog_fire(int irq, void *dev_id, struct pt_regs *regs)
+{
+       printk(KERN_CRIT "Watchdog: Would Reboot.\n");
+       *CSR_TIMER4_CNTL = 0;
+       *CSR_TIMER4_CLR = 0;
+}
+#endif
+
+static void watchdog_ping(void)
+{
+       /*
+        *      Refresh the timer.
+        */
+       *CSR_TIMER4_LOAD = soft_margin * (FCLK / 256);
+}
+
+/*
+ *     Allow only one person to hold it open
+ */
+static int watchdog_open(struct inode *inode, struct file *file)
+{
+       if(timer_alive)
+               return -EBUSY;
+       /*
+        *      Ahead watchdog factor ten, Mr Sulu
+        */
+       *CSR_TIMER4_CLR = 0;
+       watchdog_ping();
+       *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD 
+               | TIMER_CNTL_DIV256;
+#ifdef ONLY_TESTING
+       request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL);
+#else
+       *CSR_SA110_CNTL |= 1 << 13;
+       MOD_INC_USE_COUNT;
+#endif
+       timer_alive = 1;
+       return 0;
+}
+
+static int watchdog_release(struct inode *inode, struct file *file)
+{
+#ifdef ONLY_TESTING
+       free_irq(IRQ_TIMER4, NULL);
+       timer_alive = 0;
+#else
+       /*
+        *      It's irreversible!
+        */
+#endif
+       return 0;
+}
+
+static ssize_t watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
+{
+       /*  Can't seek (pwrite) on this device  */
+       if (ppos != &file->f_pos)
+               return -ESPIPE;
+
+       /*
+        *      Refresh the timer.
+        */
+       if(len)
+       {
+               watchdog_ping();
+               return 1;
+       }
+       return 0;
+}
+
+static int watchdog_ioctl(struct inode *inode, struct file *file,
+       unsigned int cmd, unsigned long arg)
+{
+       int i;
+       static struct watchdog_info ident=
+       {
+               0,
+               0,
+               "Footbridge Watchdog"
+       };
+       switch(cmd)
+       {
+               default:
+                       return -ENOTTY;
+               case WDIOC_GETSUPPORT:
+                       if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
+                               return -EFAULT;
+                       return 0;
+               case WDIOC_GETSTATUS:
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0,(int *)arg);
+               case WDIOC_KEEPALIVE:
+                       watchdog_ping();
+                       return 0;
+       }
+}
+
+static struct file_operations watchdog_fops=
+{
+       .owner          = THIS_MODULE,
+       .write          = watchdog_write,
+       .ioctl          = watchdog_ioctl,
+       .open           = watchdog_open,
+       .release        = watchdog_release,
+};
+
+static struct miscdevice watchdog_miscdev=
+{
+       WATCHDOG_MINOR,
+       "watchdog",
+       &watchdog_fops
+};
+
+static int __init footbridge_watchdog_init(void)
+{
+       if (machine_is_netwinder())
+               return -ENODEV;
+
+       misc_register(&watchdog_miscdev);
+       printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n", 
+              soft_margin);
+       if (machine_is_cats())
+               printk("Warning: Watchdog reset may not work on this machine.\n");
+       return 0;
+}
+
+static void __exit footbridge_watchdog_exit(void)
+{
+       misc_deregister(&watchdog_miscdev);
+}
+
+MODULE_AUTHOR("Phil Blundell <pb@nexus.co.uk>");
+MODULE_DESCRIPTION("21285 watchdog driver");
+MODULE_LICENSE("GPL");
+
+MODULE_PARM(soft_margin,"i");
+MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds");
+
+module_init(footbridge_watchdog_init);
+module_exit(footbridge_watchdog_exit);
diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
new file mode 100644 (file)
index 0000000..ce522c5
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ *     Wdt977  0.02:   A Watchdog Device for Netwinder W83977AF chip
+ *
+ *     (c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
+ *
+ *                     -----------------------
+ *
+ *     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.
+ *
+ *                     -----------------------
+ *      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>
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#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
+
+#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 unsigned long 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 */
+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( test_and_set_bit(0,&timer_alive) )
+               return -EBUSY;
+
+       /* 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;
+       }
+
+       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(timeoutM,0x371);
+       outb(0xF3,0x370);
+       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 */
+       /* in test mode watch the bit 1 on F4 to indicate "triggered" */
+       if (!testmode)
+       {
+               outb(0x07,0x370);
+               outb(0x07,0x371);
+               outb(0xE6,0x370);
+               outb(0x08,0x371);
+       }
+
+       /* lock the SuperIO chip */
+       outb(0xAA,0x370);
+
+       return 0;
+}
+
+static int wdt977_release(struct inode *inode, struct file *file)
+{
+       /*
+        *      Shut off the timer.
+        *      Lock it in if it's a module and we set nowayout
+        */
+       if (!nowayout)
+       {
+               /* 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);
+
+               clear_bit(0,&timer_alive);
+
+               printk(KERN_INFO "Wdt977 Watchdog: shutdown\n");
+       }
+       return 0;
+}
+
+
+/*
+ *      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;
+
+       if(count)
+       {
+               kick_wdog();
+               return 1;
+       }
+       return 0;
+}
+
+/*
+ *      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,
+       .write          = wdt977_write,
+       .ioctl          = wdt977_ioctl,
+       .open           = wdt977_open,
+       .release        = wdt977_release,
+};
+
+static struct miscdevice wdt977_miscdev=
+{
+       WATCHDOG_MINOR,
+       "watchdog",
+       &wdt977_fops
+};
+
+static int __init nwwatchdog_init(void)
+{
+       if (!machine_is_netwinder())
+               return -ENODEV;
+
+       misc_register(&wdt977_miscdev);
+       printk(KERN_INFO "Wdt977 Watchdog sleeping.\n");
+       return 0;
+}
+
+static void __exit nwwatchdog_exit(void)
+{
+       misc_deregister(&wdt977_miscdev);
+}
+
+module_init(nwwatchdog_init);
+module_exit(nwwatchdog_exit);
+
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
new file mode 100644 (file)
index 0000000..28374dc
--- /dev/null
@@ -0,0 +1,653 @@
+/*
+ *     Industrial Computer Source WDT500/501 driver for Linux 2.1.x
+ *
+ *     (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
+ *                             http://www.redhat.com
+ *
+ *     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.       
+ *
+ *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
+ *
+ *     Release 0.09.
+ *
+ *     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
+ *             Alan Cox        :       Cleaned up copy/user stuff
+ *             Tim Hockin      :       Added insmod parameters, comment cleanup
+ *                                     Parameterized timeout
+ *             JP Nollmann     :       Added support for PCI wdt501p
+ *             Alan Cox        :       Split ISA and PCI cards into two drivers
+ *             Jeff Garzik     :       PCI cleanups
+ *             Tigran Aivazian :       Restructured wdtpci_init_one() to handle failures
+ *             Matt Domsch     :       added nowayout and timeout module options
+ */
+
+#include <linux/config.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/fcntl.h>
+#include <linux/notifier.h>
+#include <linux/reboot.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/system.h>
+
+#define WDT_IS_PCI
+#include "wd501p.h"
+
+#define PFX "wdt_pci: "
+
+/*
+ * Until Access I/O gets their application for a PCI vendor ID approved,
+ * I don't think that it's appropriate to move these constants into the
+ * regular pci_ids.h file. -- JPN 2000/01/18
+ */
+
+#ifndef PCI_VENDOR_ID_ACCESSIO
+#define PCI_VENDOR_ID_ACCESSIO 0x494f
+#endif
+#ifndef PCI_DEVICE_ID_WDG_CSM
+#define PCI_DEVICE_ID_WDG_CSM 0x22c0
+#endif
+
+static unsigned long wdt_is_open;
+
+/*
+ *     You must set these - there is no sane way to probe for this board.
+ *     You can use wdt=x,y to set these now.
+ */
+static int io=0x240;
+static int irq=11;
+
+#define WD_TIMO (100*60)               /* 1 minute */
+
+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 void __init
+wdtpci_validate_timeout(void)
+{
+       timeout_val = timeout * 100;
+}
+
+#ifndef MODULE
+
+/**
+ *     wdtpci_setup:
+ *     @str: command line string
+ *
+ *     Setup options. The board isn't really probe-able so we have to
+ *     get the user to tell us the configuration. Sane people build it 
+ *     modular but the others come here.
+ */
+static int __init wdtpci_setup(char *str)
+{
+       int ints[4];
+
+       str = get_options (str, ARRAY_SIZE(ints), ints);
+
+       if (ints[0] > 0)
+       {
+               io = ints[1];
+               if(ints[0] > 1)
+                       irq = ints[2];
+       }
+
+       return 1;
+}
+
+__setup("wdt=", wdtpci_setup);
+
+#endif /* !MODULE */
+/*
+ *     Programming support
+ */
+static void wdtpci_ctr_mode(int ctr, int mode)
+{
+       ctr<<=6;
+       ctr|=0x30;
+       ctr|=(mode<<1);
+       outb_p(ctr, WDT_CR);
+}
+
+static void wdtpci_ctr_load(int ctr, int val)
+{
+       outb_p(val&0xFF, WDT_COUNT0+ctr);
+       outb_p(val>>8, WDT_COUNT0+ctr);
+}
+
+/*
+ *     Kernel methods.
+ */
+/**
+ *     wdtpci_status:
+ *     
+ *     Extract the status information from a WDT watchdog device. There are
+ *     several board variants so we have to know which bits are valid. Some
+ *     bits default to one and some to zero in order to be maximally painful.
+ *
+ *     we then map the bits onto the status ioctl flags.
+ */
+static int wdtpci_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;
+}
+
+/**
+ *     wdtpci_interrupt:
+ *     @irq:           Interrupt number
+ *     @dev_id:        Unused as we don't allow multiple devices.
+ *     @regs:          Unused.
+ *
+ *     Handle an interrupt from the board. These are raised when the status
+ *     map changes in what the board considers an interesting way. That means
+ *     a failure condition occuring.
+ */
+static void wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+       /*
+        *      Read the status register see what is up and
+        *      then printk it. 
+        */
+        
+       unsigned char status=inb_p(WDT_SR);
+       
+       status|=FEATUREMAP1;
+       status&=~FEATUREMAP2;   
+       
+       printk(KERN_CRIT "WDT status %d\n", status);
+       
+       if(!(status&WDC_SR_TGOOD))
+               printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT));
+       if(!(status&WDC_SR_PSUOVER))
+               printk(KERN_CRIT "PSU over voltage.\n");
+       if(!(status&WDC_SR_PSUUNDR))
+               printk(KERN_CRIT "PSU under voltage.\n");
+       if(!(status&WDC_SR_FANGOOD))
+               printk(KERN_CRIT "Possible fan fault.\n");
+       if(!(status&WDC_SR_WCCR))
+#ifdef SOFTWARE_REBOOT
+#ifdef ONLY_TESTING
+               printk(KERN_CRIT "Would Reboot.\n");
+#else          
+               printk(KERN_CRIT "Initiating system reboot.\n");
+               machine_restart(NULL);
+#endif         
+#else
+               printk(KERN_CRIT "Reset in 5ms.\n");
+#endif         
+}
+
+
+/**
+ *     wdtpci_ping:
+ *
+ *     Reload counter one with the watchdog timeout. We don't bother reloading
+ *     the cascade counter. 
+ */
+static void wdtpci_ping(void)
+{
+       /* Write a watchdog value */
+       inb_p(WDT_DC);
+       wdtpci_ctr_mode(1,2);
+       wdtpci_ctr_load(1,timeout_val);         /* Timeout */
+       outb_p(0, WDT_DC);
+}
+
+/**
+ *     wdtpci_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 wdtpci_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)
+       {
+               wdtpci_ping();
+               return 1;
+       }
+       return 0;
+}
+
+/**
+ *     wdtpci_read:
+ *     @file: file handle to the watchdog board
+ *     @buf: buffer to write 1 byte into
+ *     @count: length of buffer
+ *     @ptr: offset (no seek allowed)
+ *
+ *     Read reports the temperature in degrees Fahrenheit. The API is in
+ *     fahrenheit. It was designed by an imperial measurement luddite.
+ */
+static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *ptr)
+{
+       unsigned short c=inb_p(WDT_RT);
+       unsigned char cp;
+       
+       /*  Can't seek (pread) on this device  */
+       if (ptr != &file->f_pos)
+               return -ESPIPE;
+
+       switch(minor(file->f_dentry->d_inode->i_rdev))
+       {
+               case TEMP_MINOR:
+                       c*=11;
+                       c/=15;
+                       cp=c+7;
+                       if(copy_to_user(buf,&cp,1))
+                               return -EFAULT;
+                       return 1;
+               default:
+                       return -EINVAL;
+       }
+}
+
+/**
+ *     wdtpci_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. We only actually usefully support
+ *     querying capabilities and current status. 
+ */
+static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+       unsigned long arg)
+{
+       static struct watchdog_info ident = {
+               .options          = WDIOF_OVERHEAT  | WDIOF_POWERUNDER |
+                                   WDIOF_POWEROVER | WDIOF_EXTERN1 |
+                                   WDIOF_EXTERN2   | WDIOF_FANFAULT,
+               .firmware_version = 1,
+               .identity         = "WDT500/501PCI",
+       };
+       
+       ident.options&=WDT_OPTION_MASK; /* Mask down to the card we have */
+       switch(cmd)
+       {
+               default:
+                       return -ENOTTY;
+               case WDIOC_GETSUPPORT:
+                       return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
+
+               case WDIOC_GETSTATUS:
+                       return put_user(wdtpci_status(),(int *)arg);
+               case WDIOC_GETBOOTSTATUS:
+                       return put_user(0, (int *)arg);
+               case WDIOC_KEEPALIVE:
+                       wdtpci_ping();
+                       return 0;
+       }
+}
+
+/**
+ *     wdtpci_open:
+ *     @inode: inode of device
+ *     @file: file handle to device
+ *
+ *     One of our two misc devices has been opened. The watchdog device is
+ *     single open and on opening we load the counters. Counter zero is a 
+ *     100Hz cascade, into counter 1 which downcounts to reboot. When the
+ *     counter triggers counter 2 downcounts the length of the reset pulse
+ *     which set set to be as long as possible. 
+ */
+static int wdtpci_open(struct inode *inode, struct file *file)
+{
+       switch(minor(inode->i_rdev))
+       {
+               case WATCHDOG_MINOR:
+                       if( test_and_set_bit(0,&wdt_is_open) ) 
+                       {
+                               return -EBUSY;
+                       }
+                       if (nowayout) {
+                               MOD_INC_USE_COUNT;
+                       }
+                       /*
+                        *      Activate 
+                        */
+
+                       inb_p(WDT_DC);          /* Disable */
+
+                       /*
+                        * "pet" the watchdog, as Access says.
+                        * This resets the clock outputs.
+                        */
+                               
+                       wdtpci_ctr_mode(2,0);
+                       outb_p(0, WDT_DC);
+
+                       inb_p(WDT_DC);
+
+                       outb_p(0, WDT_CLOCK);   /* 2.0833MHz clock */
+                       inb_p(WDT_BUZZER);      /* disable */
+                       inb_p(WDT_OPTONOTRST);  /* disable */
+                       inb_p(WDT_OPTORST);     /* disable */
+                       inb_p(WDT_PROGOUT);     /* disable */
+                       wdtpci_ctr_mode(0,3);
+                       wdtpci_ctr_mode(1,2);
+                       wdtpci_ctr_mode(2,1);
+                       wdtpci_ctr_load(0,20833);       /* count at 100Hz */
+                       wdtpci_ctr_load(1,timeout_val); /* Timeout */
+                       /* DO NOT LOAD CTR2 on PCI card! -- JPN */
+                       outb_p(0, WDT_DC);      /* Enable */
+                       return 0;
+               case TEMP_MINOR:
+                       return 0;
+               default:
+                       return -ENODEV;
+       }
+}
+
+/**
+ *     wdtpci_close:
+ *     @inode: inode to board
+ *     @file: file handle to board
+ *
+ *     The watchdog has a configurable API. There is a religious dispute 
+ *     between people who want their watchdog to be able to shut down and 
+ *     those who want to be sure if the watchdog manager dies the machine
+ *     reboots. In the former case we disable the counters, in the latter
+ *     case you have to open it again very soon.
+ */
+static int wdtpci_release(struct inode *inode, struct file *file)
+{
+       if(minor(inode->i_rdev)==WATCHDOG_MINOR)
+       {
+               if (!nowayout) {
+                       inb_p(WDT_DC);          /* Disable counters */
+                       wdtpci_ctr_load(2,0);   /* 0 length reset pulses now */
+               }
+               clear_bit(0, &wdt_is_open );
+       }
+       return 0;
+}
+
+/**
+ *     notify_sys:
+ *     @this: our notifier block
+ *     @code: the event being reported
+ *     @unused: unused
+ *
+ *     Our notifier is called on system shutdowns. We want to turn the card
+ *     off at reboot otherwise the machine will reboot again during memory
+ *     test or worse yet during the following fsck. This would suck, in fact
+ *     trust me - if it happens it does suck.
+ */
+
+static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
+       void *unused)
+{
+       if(code==SYS_DOWN || code==SYS_HALT)
+       {
+               /* Turn the card off */
+               inb_p(WDT_DC);
+               wdtpci_ctr_load(2,0);
+       }
+       return NOTIFY_DONE;
+}
+/*
+ *     Kernel Interfaces
+ */
+static struct file_operations wdtpci_fops = {
+       .owner          = THIS_MODULE,
+       .llseek         = no_llseek,
+       .read           = wdtpci_read,
+       .write          = wdtpci_write,
+       .ioctl          = wdtpci_ioctl,
+       .open           = wdtpci_open,
+       .release        = wdtpci_release,
+};
+
+static struct miscdevice wdtpci_miscdev = {
+       .minor  = WATCHDOG_MINOR,
+       .name   = "watchdog",
+       .fops   = &wdtpci_fops,
+};
+
+#ifdef CONFIG_WDT_501
+static struct miscdevice temp_miscdev = {
+       .minor  = TEMP_MINOR,
+       .name   = "temperature",
+       .fops   = &wdtpci_fops,
+};
+#endif
+
+/*
+ *     The WDT card needs to learn about soft shutdowns in order to
+ *     turn the timebomb registers off. 
+ */
+static struct notifier_block wdtpci_notifier = {
+       .notifier_call = wdtpci_notify_sys,
+};
+
+
+static int __init wdtpci_init_one (struct pci_dev *dev,
+                                  const struct pci_device_id *ent)
+{
+       static int dev_count = 0;
+       int ret = -EIO;
+
+       dev_count++;
+       if (dev_count > 1) {
+               printk (KERN_ERR PFX
+                       "this driver only supports 1 device\n");
+               return -ENODEV;
+       }
+
+       if (pci_enable_device (dev))
+               goto out;
+
+       irq = dev->irq;
+       io = pci_resource_start (dev, 2);
+       printk ("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X "
+               "(Interrupt %d)\n", io, irq);
+
+       if (request_region (io, 16, "wdt-pci") == NULL) {
+               printk (KERN_ERR PFX "I/O %d is not free.\n", io);
+               goto out;
+       }
+
+       if (request_irq (irq, wdtpci_interrupt, SA_INTERRUPT | SA_SHIRQ,
+                        "wdt-pci", &wdtpci_miscdev)) {
+               printk (KERN_ERR PFX "IRQ %d is not free.\n", irq);
+               goto out_reg;
+       }
+
+       ret = misc_register (&wdtpci_miscdev);
+       if (ret) {
+               printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR);
+               goto out_irq;
+       }
+
+       ret = register_reboot_notifier (&wdtpci_notifier);
+       if (ret) {
+               printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR);
+               goto out_misc;
+       }
+#ifdef CONFIG_WDT_501
+       ret = misc_register (&temp_miscdev);
+       if (ret) {
+               printk (KERN_ERR PFX "can't misc_register (temp) on minor=%d\n", TEMP_MINOR);
+               goto out_rbt;
+       }
+#endif
+
+       ret = 0;
+out:
+       return ret;
+
+#ifdef CONFIG_WDT_501
+out_rbt:
+       unregister_reboot_notifier(&wdtpci_notifier);
+#endif
+out_misc:
+       misc_deregister(&wdtpci_miscdev);
+out_irq:
+       free_irq(irq, &wdtpci_miscdev);
+out_reg:
+       release_region (io, 16);
+       goto out;
+}
+
+
+static void __devexit wdtpci_remove_one (struct pci_dev *pdev)
+{
+       /* here we assume only one device will ever have
+        * been picked up and registered by probe function */
+       unregister_reboot_notifier(&wdtpci_notifier);
+#ifdef CONFIG_WDT_501_PCI
+       misc_deregister(&temp_miscdev);
+#endif 
+       misc_deregister(&wdtpci_miscdev);
+       free_irq(irq, &wdtpci_miscdev);
+       release_region(io, 16);
+}
+
+
+static struct pci_device_id wdtpci_pci_tbl[] __initdata = {
+       {
+               .vendor    = PCI_VENDOR_ID_ACCESSIO,
+               .device    = PCI_DEVICE_ID_WDG_CSM,
+               .subvendor = PCI_ANY_ID,
+               .subdevice = PCI_ANY_ID,
+       },
+       { 0, }, /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
+
+
+static struct pci_driver wdtpci_driver = {
+       .name           = "wdt-pci",
+       .id_table       = wdtpci_pci_tbl,
+       .probe          = wdtpci_init_one,
+       .remove         = __devexit_p(wdtpci_remove_one),
+};
+
+
+/**
+ *     wdtpci_cleanup:
+ *
+ *     Unload the watchdog. You cannot do this with any file handles open.
+ *     If your watchdog is set to continue ticking on close and you unload
+ *     it, well it keeps ticking. We won't get the interrupt but the board
+ *     will not touch PC memory so all is fine. You just have to load a new
+ *     module in 60 seconds or reboot.
+ */
+static void __exit wdtpci_cleanup(void)
+{
+       pci_unregister_driver (&wdtpci_driver);
+}
+
+
+/**
+ *     wdtpci_init:
+ *
+ *     Set up the WDT watchdog board. All we have to do is grab the
+ *     resources we require and bitch if anyone beat us to them.
+ *     The open() function will actually kick the board off.
+ */
+static int __init wdtpci_init(void)
+{
+       int rc = pci_register_driver (&wdtpci_driver);
+       
+       if (rc < 1)
+               return -ENODEV;
+
+       wdtpci_validate_timeout();
+       
+       return 0;
+}
+
+
+module_init(wdtpci_init);
+module_exit(wdtpci_cleanup);
+
+MODULE_AUTHOR("JP Nollmann, Alan Cox");
+MODULE_DESCRIPTION("Driver for the ICS PCI watchdog cards");
+MODULE_LICENSE("GPL");
diff --git a/drivers/char/wdt.c b/drivers/char/wdt.c
deleted file mode 100644 (file)
index 33deb30..0000000
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- *     Industrial Computer Source WDT500/501 driver for Linux 2.1.x
- *
- *     (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     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.       
- *
- *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
- *
- *     Release 0.09.
- *
- *     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
- *             Alan Cox        :       Cleaned up copy/user stuff
- *             Tim Hockin      :       Added insmod parameters, comment cleanup
- *                                     Parameterized timeout
- *             Tigran Aivazian :       Restructured wdt_init() to handle failures
- *             Matt Domsch     :       added nowayout and timeout module options
- */
-
-#include <linux/config.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include "wd501p.h"
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-static unsigned long wdt_is_open;
-
-/*
- *     You must set these - there is no sane way to probe for this board.
- *     You can use wdt=x,y to set these now.
- */
-static int io=0x240;
-static int irq=11;
-
-#define WD_TIMO (100*60)               /* 1 minute */
-
-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 void __init
-wdt_validate_timeout(void)
-{
-       timeout_val = timeout * 100;
-}
-
-#ifndef MODULE
-
-/**
- *     wdt_setup:
- *     @str: command line string
- *
- *     Setup options. The board isn't really probe-able so we have to
- *     get the user to tell us the configuration. Sane people build it 
- *     modular but the others come here.
- */
-static int __init wdt_setup(char *str)
-{
-       int ints[4];
-
-       str = get_options (str, ARRAY_SIZE(ints), ints);
-
-       if (ints[0] > 0)
-       {
-               io = ints[1];
-               if(ints[0] > 1)
-                       irq = ints[2];
-       }
-
-       return 1;
-}
-
-__setup("wdt=", wdt_setup);
-
-#endif /* !MODULE */
-
-MODULE_PARM(io, "i");
-MODULE_PARM_DESC(io, "WDT io port (default=0x240)");
-MODULE_PARM(irq, "i");
-MODULE_PARM_DESC(irq, "WDT irq (default=11)");
-/*
- *     Programming support
- */
-static void wdt_ctr_mode(int ctr, int mode)
-{
-       ctr<<=6;
-       ctr|=0x30;
-       ctr|=(mode<<1);
-       outb_p(ctr, WDT_CR);
-}
-
-static void wdt_ctr_load(int ctr, int val)
-{
-       outb_p(val&0xFF, WDT_COUNT0+ctr);
-       outb_p(val>>8, WDT_COUNT0+ctr);
-}
-
-/*
- *     Kernel methods.
- */
-/**
- *     wdt_status:
- *     
- *     Extract the status information from a WDT watchdog device. There are
- *     several board variants so we have to know which bits are valid. Some
- *     bits default to one and some to zero in order to be maximally painful.
- *
- *     we then map the bits onto the status ioctl flags.
- */
-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;
-}
-
-/**
- *     wdt_interrupt:
- *     @irq:           Interrupt number
- *     @dev_id:        Unused as we don't allow multiple devices.
- *     @regs:          Unused.
- *
- *     Handle an interrupt from the board. These are raised when the status
- *     map changes in what the board considers an interesting way. That means
- *     a failure condition occuring.
- */
-void wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       /*
-        *      Read the status register see what is up and
-        *      then printk it. 
-        */
-        
-       unsigned char status=inb_p(WDT_SR);
-       
-       status|=FEATUREMAP1;
-       status&=~FEATUREMAP2;   
-       
-       printk(KERN_CRIT "WDT status %d\n", status);
-       
-       if(!(status&WDC_SR_TGOOD))
-               printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT));
-       if(!(status&WDC_SR_PSUOVER))
-               printk(KERN_CRIT "PSU over voltage.\n");
-       if(!(status&WDC_SR_PSUUNDR))
-               printk(KERN_CRIT "PSU under voltage.\n");
-       if(!(status&WDC_SR_FANGOOD))
-               printk(KERN_CRIT "Possible fan fault.\n");
-       if(!(status&WDC_SR_WCCR))
-#ifdef SOFTWARE_REBOOT
-#ifdef ONLY_TESTING
-               printk(KERN_CRIT "Would Reboot.\n");
-#else          
-               printk(KERN_CRIT "Initiating system reboot.\n");
-               machine_restart(NULL);
-#endif         
-#else
-               printk(KERN_CRIT "Reset in 5ms.\n");
-#endif         
-}
-
-
-/**
- *     wdt_ping:
- *
- *     Reload counter one with the watchdog timeout. We don't bother reloading
- *     the cascade counter. 
- */
-static void wdt_ping(void)
-{
-       /* Write a watchdog value */
-       inb_p(WDT_DC);
-       wdt_ctr_mode(1,2);
-       wdt_ctr_load(1,timeout_val);            /* Timeout */
-       outb_p(0, WDT_DC);
-}
-
-/**
- *     wdt_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 wdt_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)
-       {
-               wdt_ping();
-               return 1;
-       }
-       return 0;
-}
-
-/**
- *     wdt_read:
- *     @file: file handle to the watchdog board
- *     @buf: buffer to write 1 byte into
- *     @count: length of buffer
- *     @ptr: offset (no seek allowed)
- *
- *     Read reports the temperature in degrees Fahrenheit. The API is in
- *     farenheit. It was designed by an imperial measurement luddite.
- */
-static ssize_t wdt_read(struct file *file, char *buf, size_t count, loff_t *ptr)
-{
-       unsigned short c=inb_p(WDT_RT);
-       unsigned char cp;
-       
-       /*  Can't seek (pread) on this device  */
-       if (ptr != &file->f_pos)
-               return -ESPIPE;
-
-       switch(minor(file->f_dentry->d_inode->i_rdev))
-       {
-               case TEMP_MINOR:
-                       c*=11;
-                       c/=15;
-                       cp=c+7;
-                       if(copy_to_user(buf,&cp,1))
-                               return -EFAULT;
-                       return 1;
-               default:
-                       return -EINVAL;
-       }
-}
-
-/**
- *     wdt_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. We only actually usefully support
- *     querying capabilities and current status. 
- */
-static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       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 -ENOTTY;
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
-
-               case WDIOC_GETSTATUS:
-                       return put_user(wdt_status(),(int *)arg);
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0, (int *)arg);
-               case WDIOC_KEEPALIVE:
-                       wdt_ping();
-                       return 0;
-       }
-}
-
-/**
- *     wdt_open:
- *     @inode: inode of device
- *     @file: file handle to device
- *
- *     One of our two misc devices has been opened. The watchdog device is
- *     single open and on opening we load the counters. Counter zero is a 
- *     100Hz cascade, into counter 1 which downcounts to reboot. When the
- *     counter triggers counter 2 downcounts the length of the reset pulse
- *     which set set to be as long as possible. 
- */
-static int wdt_open(struct inode *inode, struct file *file)
-{
-       switch(minor(inode->i_rdev))
-       {
-               case WATCHDOG_MINOR:
-                       if(test_and_set_bit(0, &wdt_is_open))
-                               return -EBUSY;
-                       if (nowayout) {
-                               MOD_INC_USE_COUNT;
-                       }
-                       /*
-                        *      Activate 
-                        */
-        
-                       inb_p(WDT_DC);          /* Disable */
-                       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,timeout_val);    /* Timeout */
-                       wdt_ctr_load(2,65535);
-                       outb_p(0, WDT_DC);      /* Enable */
-                       return 0;
-               case TEMP_MINOR:
-                       return 0;
-               default:
-                       return -ENODEV;
-       }
-}
-
-/**
- *     wdt_close:
- *     @inode: inode to board
- *     @file: file handle to board
- *
- *     The watchdog has a configurable API. There is a religious dispute 
- *     between people who want their watchdog to be able to shut down and 
- *     those who want to be sure if the watchdog manager dies the machine
- *     reboots. In the former case we disable the counters, in the latter
- *     case you have to open it again very soon.
- */
-static int wdt_release(struct inode *inode, struct file *file)
-{
-       if(minor(inode->i_rdev)==WATCHDOG_MINOR)
-       {
-               if (!nowayout) {
-                       inb_p(WDT_DC);          /* Disable counters */
-                       wdt_ctr_load(2,0);      /* 0 length reset pulses now */
-               }
-               clear_bit(0, &wdt_is_open);
-       }
-       return 0;
-}
-
-/**
- *     notify_sys:
- *     @this: our notifier block
- *     @code: the event being reported
- *     @unused: unused
- *
- *     Our notifier is called on system shutdowns. We want to turn the card
- *     off at reboot otherwise the machine will reboot again during memory
- *     test or worse yet during the following fsck. This would suck, in fact
- *     trust me - if it happens it does suck.
- */
-
-static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT)
-       {
-               /* Turn the card off */
-               inb_p(WDT_DC);
-               wdt_ctr_load(2,0);
-       }
-       return NOTIFY_DONE;
-}
-/*
- *     Kernel Interfaces
- */
-static struct file_operations wdt_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .read           = wdt_read,
-       .write          = wdt_write,
-       .ioctl          = wdt_ioctl,
-       .open           = wdt_open,
-       .release        = wdt_release,
-};
-
-static struct miscdevice wdt_miscdev=
-{
-       WATCHDOG_MINOR,
-       "watchdog",
-       &wdt_fops
-};
-
-#ifdef CONFIG_WDT_501
-static struct miscdevice temp_miscdev=
-{
-       TEMP_MINOR,
-       "temperature",
-       &wdt_fops
-};
-#endif
-
-/*
- *     The WDT card needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off. 
- */
-static struct notifier_block wdt_notifier=
-{
-       wdt_notify_sys,
-       NULL,
-       0
-};
-
-/**
- *     cleanup_module:
- *
- *     Unload the watchdog. You cannot do this with any file handles open.
- *     If your watchdog is set to continue ticking on close and you unload
- *     it, well it keeps ticking. We won't get the interrupt but the board
- *     will not touch PC memory so all is fine. You just have to load a new
- *     module in 60 seconds or reboot.
- */
-static void __exit wdt_exit(void)
-{
-       misc_deregister(&wdt_miscdev);
-#ifdef CONFIG_WDT_501  
-       misc_deregister(&temp_miscdev);
-#endif 
-       unregister_reboot_notifier(&wdt_notifier);
-       release_region(io,8);
-       free_irq(irq, NULL);
-}
-
-/**
- *     wdt_init:
- *
- *     Set up the WDT watchdog board. All we have to do is grab the
- *     resources we require and bitch if anyone beat us to them.
- *     The open() function will actually kick the board off.
- */
-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);
-               goto out;
-       }
-       ret = request_irq(irq, wdt_interrupt, SA_INTERRUPT, "wdt501p", NULL);
-       if(ret) {
-               printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq);
-               goto outmisc;
-       }
-       if (!request_region(io, 8, "wdt501p")) {
-               printk(KERN_ERR "wdt: IO %X is not free.\n", io);
-               ret = -EBUSY;
-               goto outirq;
-       }
-       ret = register_reboot_notifier(&wdt_notifier);
-       if(ret) {
-               printk(KERN_ERR "wdt: can't register reboot notifier (err=%d)\n", ret);
-               goto outreg;
-       }
-
-#ifdef CONFIG_WDT_501
-       ret = misc_register(&temp_miscdev);
-       if (ret) {
-               printk(KERN_ERR "wdt: can't misc_register (temp) on minor=%d\n", TEMP_MINOR);
-               goto outrbt;
-       }
-#endif
-
-       ret = 0;
-       printk(KERN_INFO "WDT500/501-P driver 0.07 at %X (Interrupt %d)\n", io, irq);
-out:
-       return ret;
-
-#ifdef CONFIG_WDT_501
-outrbt:
-       unregister_reboot_notifier(&wdt_notifier);
-#endif
-
-outreg:
-       release_region(io,8);
-outirq:
-       free_irq(irq, NULL);
-outmisc:
-       misc_deregister(&wdt_miscdev);
-       goto out;
-}
-
-module_init(wdt_init);
-module_exit(wdt_exit);
-
-MODULE_AUTHOR("Alan Cox");
-MODULE_DESCRIPTION("Driver for ISA ICS watchdog cards (WDT500/501)");
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/wdt285.c b/drivers/char/wdt285.c
deleted file mode 100644 (file)
index 639ab2a..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- *     Intel 21285 watchdog driver
- *     Copyright (c) Phil Blundell <pb@nexus.co.uk>, 1998
- *
- *     based on
- *
- *     SoftDog 0.05:   A Software Watchdog Device
- *
- *     (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *
- *     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.
- *     
- */
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/smp_lock.h>
-
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-#include <asm/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/hardware/dec21285.h>
-
-/*
- * Define this to stop the watchdog actually rebooting the machine.
- */
-#undef ONLY_TESTING
-
-#define TIMER_MARGIN   60              /* (secs) Default is 1 minute */
-
-#define FCLK   (50*1000*1000)          /* 50MHz */
-
-static int soft_margin = TIMER_MARGIN; /* in seconds */
-static int timer_alive;
-
-#ifdef ONLY_TESTING
-/*
- *     If the timer expires..
- */
-
-static void watchdog_fire(int irq, void *dev_id, struct pt_regs *regs)
-{
-       printk(KERN_CRIT "Watchdog: Would Reboot.\n");
-       *CSR_TIMER4_CNTL = 0;
-       *CSR_TIMER4_CLR = 0;
-}
-#endif
-
-static void watchdog_ping(void)
-{
-       /*
-        *      Refresh the timer.
-        */
-       *CSR_TIMER4_LOAD = soft_margin * (FCLK / 256);
-}
-
-/*
- *     Allow only one person to hold it open
- */
-static int watchdog_open(struct inode *inode, struct file *file)
-{
-       if(timer_alive)
-               return -EBUSY;
-       /*
-        *      Ahead watchdog factor ten, Mr Sulu
-        */
-       *CSR_TIMER4_CLR = 0;
-       watchdog_ping();
-       *CSR_TIMER4_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD 
-               | TIMER_CNTL_DIV256;
-#ifdef ONLY_TESTING
-       request_irq(IRQ_TIMER4, watchdog_fire, 0, "watchdog", NULL);
-#else
-       *CSR_SA110_CNTL |= 1 << 13;
-       MOD_INC_USE_COUNT;
-#endif
-       timer_alive = 1;
-       return 0;
-}
-
-static int watchdog_release(struct inode *inode, struct file *file)
-{
-#ifdef ONLY_TESTING
-       free_irq(IRQ_TIMER4, NULL);
-       timer_alive = 0;
-#else
-       /*
-        *      It's irreversible!
-        */
-#endif
-       return 0;
-}
-
-static ssize_t watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
-{
-       /*  Can't seek (pwrite) on this device  */
-       if (ppos != &file->f_pos)
-               return -ESPIPE;
-
-       /*
-        *      Refresh the timer.
-        */
-       if(len)
-       {
-               watchdog_ping();
-               return 1;
-       }
-       return 0;
-}
-
-static int watchdog_ioctl(struct inode *inode, struct file *file,
-       unsigned int cmd, unsigned long arg)
-{
-       int i;
-       static struct watchdog_info ident=
-       {
-               0,
-               0,
-               "Footbridge Watchdog"
-       };
-       switch(cmd)
-       {
-               default:
-                       return -ENOTTY;
-               case WDIOC_GETSUPPORT:
-                       if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
-                               return -EFAULT;
-                       return 0;
-               case WDIOC_GETSTATUS:
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0,(int *)arg);
-               case WDIOC_KEEPALIVE:
-                       watchdog_ping();
-                       return 0;
-       }
-}
-
-static struct file_operations watchdog_fops=
-{
-       .owner          = THIS_MODULE,
-       .write          = watchdog_write,
-       .ioctl          = watchdog_ioctl,
-       .open           = watchdog_open,
-       .release        = watchdog_release,
-};
-
-static struct miscdevice watchdog_miscdev=
-{
-       WATCHDOG_MINOR,
-       "watchdog",
-       &watchdog_fops
-};
-
-static int __init footbridge_watchdog_init(void)
-{
-       if (machine_is_netwinder())
-               return -ENODEV;
-
-       misc_register(&watchdog_miscdev);
-       printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n", 
-              soft_margin);
-       if (machine_is_cats())
-               printk("Warning: Watchdog reset may not work on this machine.\n");
-       return 0;
-}
-
-static void __exit footbridge_watchdog_exit(void)
-{
-       misc_deregister(&watchdog_miscdev);
-}
-
-MODULE_AUTHOR("Phil Blundell <pb@nexus.co.uk>");
-MODULE_DESCRIPTION("21285 watchdog driver");
-MODULE_LICENSE("GPL");
-
-MODULE_PARM(soft_margin,"i");
-MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds");
-
-module_init(footbridge_watchdog_init);
-module_exit(footbridge_watchdog_exit);
diff --git a/drivers/char/wdt977.c b/drivers/char/wdt977.c
deleted file mode 100644 (file)
index ce522c5..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- *     Wdt977  0.02:   A Watchdog Device for Netwinder W83977AF chip
- *
- *     (c) Copyright 1998 Rebel.com (Woody Suwalski <woody@netwinder.org>)
- *
- *                     -----------------------
- *
- *     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.
- *
- *                     -----------------------
- *      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>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#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
-
-#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 unsigned long 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 */
-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( test_and_set_bit(0,&timer_alive) )
-               return -EBUSY;
-
-       /* 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;
-       }
-
-       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(timeoutM,0x371);
-       outb(0xF3,0x370);
-       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 */
-       /* in test mode watch the bit 1 on F4 to indicate "triggered" */
-       if (!testmode)
-       {
-               outb(0x07,0x370);
-               outb(0x07,0x371);
-               outb(0xE6,0x370);
-               outb(0x08,0x371);
-       }
-
-       /* lock the SuperIO chip */
-       outb(0xAA,0x370);
-
-       return 0;
-}
-
-static int wdt977_release(struct inode *inode, struct file *file)
-{
-       /*
-        *      Shut off the timer.
-        *      Lock it in if it's a module and we set nowayout
-        */
-       if (!nowayout)
-       {
-               /* 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);
-
-               clear_bit(0,&timer_alive);
-
-               printk(KERN_INFO "Wdt977 Watchdog: shutdown\n");
-       }
-       return 0;
-}
-
-
-/*
- *      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;
-
-       if(count)
-       {
-               kick_wdog();
-               return 1;
-       }
-       return 0;
-}
-
-/*
- *      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,
-       .write          = wdt977_write,
-       .ioctl          = wdt977_ioctl,
-       .open           = wdt977_open,
-       .release        = wdt977_release,
-};
-
-static struct miscdevice wdt977_miscdev=
-{
-       WATCHDOG_MINOR,
-       "watchdog",
-       &wdt977_fops
-};
-
-static int __init nwwatchdog_init(void)
-{
-       if (!machine_is_netwinder())
-               return -ENODEV;
-
-       misc_register(&wdt977_miscdev);
-       printk(KERN_INFO "Wdt977 Watchdog sleeping.\n");
-       return 0;
-}
-
-static void __exit nwwatchdog_exit(void)
-{
-       misc_deregister(&wdt977_miscdev);
-}
-
-module_init(nwwatchdog_init);
-module_exit(nwwatchdog_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/char/wdt_pci.c b/drivers/char/wdt_pci.c
deleted file mode 100644 (file)
index 28374dc..0000000
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- *     Industrial Computer Source WDT500/501 driver for Linux 2.1.x
- *
- *     (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
- *                             http://www.redhat.com
- *
- *     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.       
- *
- *     (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
- *
- *     Release 0.09.
- *
- *     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
- *             Alan Cox        :       Cleaned up copy/user stuff
- *             Tim Hockin      :       Added insmod parameters, comment cleanup
- *                                     Parameterized timeout
- *             JP Nollmann     :       Added support for PCI wdt501p
- *             Alan Cox        :       Split ISA and PCI cards into two drivers
- *             Jeff Garzik     :       PCI cleanups
- *             Tigran Aivazian :       Restructured wdtpci_init_one() to handle failures
- *             Matt Domsch     :       added nowayout and timeout module options
- */
-
-#include <linux/config.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/miscdevice.h>
-#include <linux/watchdog.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/fcntl.h>
-#include <linux/notifier.h>
-#include <linux/reboot.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <asm/system.h>
-
-#define WDT_IS_PCI
-#include "wd501p.h"
-
-#define PFX "wdt_pci: "
-
-/*
- * Until Access I/O gets their application for a PCI vendor ID approved,
- * I don't think that it's appropriate to move these constants into the
- * regular pci_ids.h file. -- JPN 2000/01/18
- */
-
-#ifndef PCI_VENDOR_ID_ACCESSIO
-#define PCI_VENDOR_ID_ACCESSIO 0x494f
-#endif
-#ifndef PCI_DEVICE_ID_WDG_CSM
-#define PCI_DEVICE_ID_WDG_CSM 0x22c0
-#endif
-
-static unsigned long wdt_is_open;
-
-/*
- *     You must set these - there is no sane way to probe for this board.
- *     You can use wdt=x,y to set these now.
- */
-static int io=0x240;
-static int irq=11;
-
-#define WD_TIMO (100*60)               /* 1 minute */
-
-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 void __init
-wdtpci_validate_timeout(void)
-{
-       timeout_val = timeout * 100;
-}
-
-#ifndef MODULE
-
-/**
- *     wdtpci_setup:
- *     @str: command line string
- *
- *     Setup options. The board isn't really probe-able so we have to
- *     get the user to tell us the configuration. Sane people build it 
- *     modular but the others come here.
- */
-static int __init wdtpci_setup(char *str)
-{
-       int ints[4];
-
-       str = get_options (str, ARRAY_SIZE(ints), ints);
-
-       if (ints[0] > 0)
-       {
-               io = ints[1];
-               if(ints[0] > 1)
-                       irq = ints[2];
-       }
-
-       return 1;
-}
-
-__setup("wdt=", wdtpci_setup);
-
-#endif /* !MODULE */
-/*
- *     Programming support
- */
-static void wdtpci_ctr_mode(int ctr, int mode)
-{
-       ctr<<=6;
-       ctr|=0x30;
-       ctr|=(mode<<1);
-       outb_p(ctr, WDT_CR);
-}
-
-static void wdtpci_ctr_load(int ctr, int val)
-{
-       outb_p(val&0xFF, WDT_COUNT0+ctr);
-       outb_p(val>>8, WDT_COUNT0+ctr);
-}
-
-/*
- *     Kernel methods.
- */
-/**
- *     wdtpci_status:
- *     
- *     Extract the status information from a WDT watchdog device. There are
- *     several board variants so we have to know which bits are valid. Some
- *     bits default to one and some to zero in order to be maximally painful.
- *
- *     we then map the bits onto the status ioctl flags.
- */
-static int wdtpci_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;
-}
-
-/**
- *     wdtpci_interrupt:
- *     @irq:           Interrupt number
- *     @dev_id:        Unused as we don't allow multiple devices.
- *     @regs:          Unused.
- *
- *     Handle an interrupt from the board. These are raised when the status
- *     map changes in what the board considers an interesting way. That means
- *     a failure condition occuring.
- */
-static void wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
-       /*
-        *      Read the status register see what is up and
-        *      then printk it. 
-        */
-        
-       unsigned char status=inb_p(WDT_SR);
-       
-       status|=FEATUREMAP1;
-       status&=~FEATUREMAP2;   
-       
-       printk(KERN_CRIT "WDT status %d\n", status);
-       
-       if(!(status&WDC_SR_TGOOD))
-               printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT));
-       if(!(status&WDC_SR_PSUOVER))
-               printk(KERN_CRIT "PSU over voltage.\n");
-       if(!(status&WDC_SR_PSUUNDR))
-               printk(KERN_CRIT "PSU under voltage.\n");
-       if(!(status&WDC_SR_FANGOOD))
-               printk(KERN_CRIT "Possible fan fault.\n");
-       if(!(status&WDC_SR_WCCR))
-#ifdef SOFTWARE_REBOOT
-#ifdef ONLY_TESTING
-               printk(KERN_CRIT "Would Reboot.\n");
-#else          
-               printk(KERN_CRIT "Initiating system reboot.\n");
-               machine_restart(NULL);
-#endif         
-#else
-               printk(KERN_CRIT "Reset in 5ms.\n");
-#endif         
-}
-
-
-/**
- *     wdtpci_ping:
- *
- *     Reload counter one with the watchdog timeout. We don't bother reloading
- *     the cascade counter. 
- */
-static void wdtpci_ping(void)
-{
-       /* Write a watchdog value */
-       inb_p(WDT_DC);
-       wdtpci_ctr_mode(1,2);
-       wdtpci_ctr_load(1,timeout_val);         /* Timeout */
-       outb_p(0, WDT_DC);
-}
-
-/**
- *     wdtpci_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 wdtpci_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)
-       {
-               wdtpci_ping();
-               return 1;
-       }
-       return 0;
-}
-
-/**
- *     wdtpci_read:
- *     @file: file handle to the watchdog board
- *     @buf: buffer to write 1 byte into
- *     @count: length of buffer
- *     @ptr: offset (no seek allowed)
- *
- *     Read reports the temperature in degrees Fahrenheit. The API is in
- *     fahrenheit. It was designed by an imperial measurement luddite.
- */
-static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *ptr)
-{
-       unsigned short c=inb_p(WDT_RT);
-       unsigned char cp;
-       
-       /*  Can't seek (pread) on this device  */
-       if (ptr != &file->f_pos)
-               return -ESPIPE;
-
-       switch(minor(file->f_dentry->d_inode->i_rdev))
-       {
-               case TEMP_MINOR:
-                       c*=11;
-                       c/=15;
-                       cp=c+7;
-                       if(copy_to_user(buf,&cp,1))
-                               return -EFAULT;
-                       return 1;
-               default:
-                       return -EINVAL;
-       }
-}
-
-/**
- *     wdtpci_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. We only actually usefully support
- *     querying capabilities and current status. 
- */
-static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
-       unsigned long arg)
-{
-       static struct watchdog_info ident = {
-               .options          = WDIOF_OVERHEAT  | WDIOF_POWERUNDER |
-                                   WDIOF_POWEROVER | WDIOF_EXTERN1 |
-                                   WDIOF_EXTERN2   | WDIOF_FANFAULT,
-               .firmware_version = 1,
-               .identity         = "WDT500/501PCI",
-       };
-       
-       ident.options&=WDT_OPTION_MASK; /* Mask down to the card we have */
-       switch(cmd)
-       {
-               default:
-                       return -ENOTTY;
-               case WDIOC_GETSUPPORT:
-                       return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
-
-               case WDIOC_GETSTATUS:
-                       return put_user(wdtpci_status(),(int *)arg);
-               case WDIOC_GETBOOTSTATUS:
-                       return put_user(0, (int *)arg);
-               case WDIOC_KEEPALIVE:
-                       wdtpci_ping();
-                       return 0;
-       }
-}
-
-/**
- *     wdtpci_open:
- *     @inode: inode of device
- *     @file: file handle to device
- *
- *     One of our two misc devices has been opened. The watchdog device is
- *     single open and on opening we load the counters. Counter zero is a 
- *     100Hz cascade, into counter 1 which downcounts to reboot. When the
- *     counter triggers counter 2 downcounts the length of the reset pulse
- *     which set set to be as long as possible. 
- */
-static int wdtpci_open(struct inode *inode, struct file *file)
-{
-       switch(minor(inode->i_rdev))
-       {
-               case WATCHDOG_MINOR:
-                       if( test_and_set_bit(0,&wdt_is_open) ) 
-                       {
-                               return -EBUSY;
-                       }
-                       if (nowayout) {
-                               MOD_INC_USE_COUNT;
-                       }
-                       /*
-                        *      Activate 
-                        */
-
-                       inb_p(WDT_DC);          /* Disable */
-
-                       /*
-                        * "pet" the watchdog, as Access says.
-                        * This resets the clock outputs.
-                        */
-                               
-                       wdtpci_ctr_mode(2,0);
-                       outb_p(0, WDT_DC);
-
-                       inb_p(WDT_DC);
-
-                       outb_p(0, WDT_CLOCK);   /* 2.0833MHz clock */
-                       inb_p(WDT_BUZZER);      /* disable */
-                       inb_p(WDT_OPTONOTRST);  /* disable */
-                       inb_p(WDT_OPTORST);     /* disable */
-                       inb_p(WDT_PROGOUT);     /* disable */
-                       wdtpci_ctr_mode(0,3);
-                       wdtpci_ctr_mode(1,2);
-                       wdtpci_ctr_mode(2,1);
-                       wdtpci_ctr_load(0,20833);       /* count at 100Hz */
-                       wdtpci_ctr_load(1,timeout_val); /* Timeout */
-                       /* DO NOT LOAD CTR2 on PCI card! -- JPN */
-                       outb_p(0, WDT_DC);      /* Enable */
-                       return 0;
-               case TEMP_MINOR:
-                       return 0;
-               default:
-                       return -ENODEV;
-       }
-}
-
-/**
- *     wdtpci_close:
- *     @inode: inode to board
- *     @file: file handle to board
- *
- *     The watchdog has a configurable API. There is a religious dispute 
- *     between people who want their watchdog to be able to shut down and 
- *     those who want to be sure if the watchdog manager dies the machine
- *     reboots. In the former case we disable the counters, in the latter
- *     case you have to open it again very soon.
- */
-static int wdtpci_release(struct inode *inode, struct file *file)
-{
-       if(minor(inode->i_rdev)==WATCHDOG_MINOR)
-       {
-               if (!nowayout) {
-                       inb_p(WDT_DC);          /* Disable counters */
-                       wdtpci_ctr_load(2,0);   /* 0 length reset pulses now */
-               }
-               clear_bit(0, &wdt_is_open );
-       }
-       return 0;
-}
-
-/**
- *     notify_sys:
- *     @this: our notifier block
- *     @code: the event being reported
- *     @unused: unused
- *
- *     Our notifier is called on system shutdowns. We want to turn the card
- *     off at reboot otherwise the machine will reboot again during memory
- *     test or worse yet during the following fsck. This would suck, in fact
- *     trust me - if it happens it does suck.
- */
-
-static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
-       void *unused)
-{
-       if(code==SYS_DOWN || code==SYS_HALT)
-       {
-               /* Turn the card off */
-               inb_p(WDT_DC);
-               wdtpci_ctr_load(2,0);
-       }
-       return NOTIFY_DONE;
-}
-/*
- *     Kernel Interfaces
- */
-static struct file_operations wdtpci_fops = {
-       .owner          = THIS_MODULE,
-       .llseek         = no_llseek,
-       .read           = wdtpci_read,
-       .write          = wdtpci_write,
-       .ioctl          = wdtpci_ioctl,
-       .open           = wdtpci_open,
-       .release        = wdtpci_release,
-};
-
-static struct miscdevice wdtpci_miscdev = {
-       .minor  = WATCHDOG_MINOR,
-       .name   = "watchdog",
-       .fops   = &wdtpci_fops,
-};
-
-#ifdef CONFIG_WDT_501
-static struct miscdevice temp_miscdev = {
-       .minor  = TEMP_MINOR,
-       .name   = "temperature",
-       .fops   = &wdtpci_fops,
-};
-#endif
-
-/*
- *     The WDT card needs to learn about soft shutdowns in order to
- *     turn the timebomb registers off. 
- */
-static struct notifier_block wdtpci_notifier = {
-       .notifier_call = wdtpci_notify_sys,
-};
-
-
-static int __init wdtpci_init_one (struct pci_dev *dev,
-                                  const struct pci_device_id *ent)
-{
-       static int dev_count = 0;
-       int ret = -EIO;
-
-       dev_count++;
-       if (dev_count > 1) {
-               printk (KERN_ERR PFX
-                       "this driver only supports 1 device\n");
-               return -ENODEV;
-       }
-
-       if (pci_enable_device (dev))
-               goto out;
-
-       irq = dev->irq;
-       io = pci_resource_start (dev, 2);
-       printk ("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X "
-               "(Interrupt %d)\n", io, irq);
-
-       if (request_region (io, 16, "wdt-pci") == NULL) {
-               printk (KERN_ERR PFX "I/O %d is not free.\n", io);
-               goto out;
-       }
-
-       if (request_irq (irq, wdtpci_interrupt, SA_INTERRUPT | SA_SHIRQ,
-                        "wdt-pci", &wdtpci_miscdev)) {
-               printk (KERN_ERR PFX "IRQ %d is not free.\n", irq);
-               goto out_reg;
-       }
-
-       ret = misc_register (&wdtpci_miscdev);
-       if (ret) {
-               printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR);
-               goto out_irq;
-       }
-
-       ret = register_reboot_notifier (&wdtpci_notifier);
-       if (ret) {
-               printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR);
-               goto out_misc;
-       }
-#ifdef CONFIG_WDT_501
-       ret = misc_register (&temp_miscdev);
-       if (ret) {
-               printk (KERN_ERR PFX "can't misc_register (temp) on minor=%d\n", TEMP_MINOR);
-               goto out_rbt;
-       }
-#endif
-
-       ret = 0;
-out:
-       return ret;
-
-#ifdef CONFIG_WDT_501
-out_rbt:
-       unregister_reboot_notifier(&wdtpci_notifier);
-#endif
-out_misc:
-       misc_deregister(&wdtpci_miscdev);
-out_irq:
-       free_irq(irq, &wdtpci_miscdev);
-out_reg:
-       release_region (io, 16);
-       goto out;
-}
-
-
-static void __devexit wdtpci_remove_one (struct pci_dev *pdev)
-{
-       /* here we assume only one device will ever have
-        * been picked up and registered by probe function */
-       unregister_reboot_notifier(&wdtpci_notifier);
-#ifdef CONFIG_WDT_501_PCI
-       misc_deregister(&temp_miscdev);
-#endif 
-       misc_deregister(&wdtpci_miscdev);
-       free_irq(irq, &wdtpci_miscdev);
-       release_region(io, 16);
-}
-
-
-static struct pci_device_id wdtpci_pci_tbl[] __initdata = {
-       {
-               .vendor    = PCI_VENDOR_ID_ACCESSIO,
-               .device    = PCI_DEVICE_ID_WDG_CSM,
-               .subvendor = PCI_ANY_ID,
-               .subdevice = PCI_ANY_ID,
-       },
-       { 0, }, /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
-
-
-static struct pci_driver wdtpci_driver = {
-       .name           = "wdt-pci",
-       .id_table       = wdtpci_pci_tbl,
-       .probe          = wdtpci_init_one,
-       .remove         = __devexit_p(wdtpci_remove_one),
-};
-
-
-/**
- *     wdtpci_cleanup:
- *
- *     Unload the watchdog. You cannot do this with any file handles open.
- *     If your watchdog is set to continue ticking on close and you unload
- *     it, well it keeps ticking. We won't get the interrupt but the board
- *     will not touch PC memory so all is fine. You just have to load a new
- *     module in 60 seconds or reboot.
- */
-static void __exit wdtpci_cleanup(void)
-{
-       pci_unregister_driver (&wdtpci_driver);
-}
-
-
-/**
- *     wdtpci_init:
- *
- *     Set up the WDT watchdog board. All we have to do is grab the
- *     resources we require and bitch if anyone beat us to them.
- *     The open() function will actually kick the board off.
- */
-static int __init wdtpci_init(void)
-{
-       int rc = pci_register_driver (&wdtpci_driver);
-       
-       if (rc < 1)
-               return -ENODEV;
-
-       wdtpci_validate_timeout();
-       
-       return 0;
-}
-
-
-module_init(wdtpci_init);
-module_exit(wdtpci_cleanup);
-
-MODULE_AUTHOR("JP Nollmann, Alan Cox");
-MODULE_DESCRIPTION("Driver for the ICS PCI watchdog cards");
-MODULE_LICENSE("GPL");