2  *      Industrial Computer Source WDT500/501 driver
 
   4  *      (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved.
 
   5  *                              http://www.redhat.com
 
   7  *      This program is free software; you can redistribute it and/or
 
   8  *      modify it under the terms of the GNU General Public License
 
   9  *      as published by the Free Software Foundation; either version
 
  10  *      2 of the License, or (at your option) any later version.
 
  12  *      Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
 
  13  *      warranty for any of this software. This material is provided
 
  14  *      "AS-IS" and at no charge.
 
  16  *      (c) Copyright 1995    Alan Cox <alan@lxorguk.ukuu.org.uk>
 
  21  *              Dave Gregorich  :       Modularisation and minor bugs
 
  22  *              Alan Cox        :       Added the watchdog ioctl() stuff
 
  23  *              Alan Cox        :       Fixed the reboot problem (as noted by
 
  25  *              Alan Cox        :       Added wdt= boot option
 
  26  *              Alan Cox        :       Cleaned up copy/user stuff
 
  27  *              Tim Hockin      :       Added insmod parameters, comment cleanup
 
  28  *                                      Parameterized timeout
 
  29  *              Tigran Aivazian :       Restructured wdt_init() to handle failures
 
  30  *              Joel Becker     :       Added WDIOC_GET/SETTIMEOUT
 
  31  *              Matt Domsch     :       Added nowayout module option
 
  34 #include <linux/interrupt.h>
 
  35 #include <linux/module.h>
 
  36 #include <linux/moduleparam.h>
 
  37 #include <linux/types.h>
 
  38 #include <linux/miscdevice.h>
 
  39 #include <linux/watchdog.h>
 
  41 #include <linux/ioport.h>
 
  42 #include <linux/notifier.h>
 
  43 #include <linux/reboot.h>
 
  44 #include <linux/init.h>
 
  47 #include <asm/uaccess.h>
 
  48 #include <asm/system.h>
 
  51 static unsigned long wdt_is_open;
 
  52 static char expect_close;
 
  58 #define WD_TIMO 60                      /* Default heartbeat = 60 seconds */
 
  60 static int heartbeat = WD_TIMO;
 
  61 static int wd_heartbeat;
 
  62 module_param(heartbeat, int, 0);
 
  63 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")");
 
  65 static int nowayout = WATCHDOG_NOWAYOUT;
 
  66 module_param(nowayout, int, 0);
 
  67 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
  69 /* You must set these - there is no sane way to probe for this board. */
 
  73 module_param(io, int, 0);
 
  74 MODULE_PARM_DESC(io, "WDT io port (default=0x240)");
 
  75 module_param(irq, int, 0);
 
  76 MODULE_PARM_DESC(irq, "WDT irq (default=11)");
 
  79 /* Support for the Fan Tachometer on the WDT501-P */
 
  80 static int tachometer;
 
  82 module_param(tachometer, int, 0);
 
  83 MODULE_PARM_DESC(tachometer, "WDT501-P Fan Tachometer support (0=disable, default=0)");
 
  84 #endif /* CONFIG_WDT_501 */
 
  90 static void wdt_ctr_mode(int ctr, int mode)
 
  98 static void wdt_ctr_load(int ctr, int val)
 
 100         outb_p(val&0xFF, WDT_COUNT0+ctr);
 
 101         outb_p(val>>8, WDT_COUNT0+ctr);
 
 107  *      Start the watchdog driver.
 
 110 static int wdt_start(void)
 
 112         inb_p(WDT_DC);                  /* Disable watchdog */
 
 113         wdt_ctr_mode(0,3);              /* Program CTR0 for Mode 3: Square Wave Generator */
 
 114         wdt_ctr_mode(1,2);              /* Program CTR1 for Mode 2: Rate Generator */
 
 115         wdt_ctr_mode(2,0);              /* Program CTR2 for Mode 0: Pulse on Terminal Count */
 
 116         wdt_ctr_load(0, 8948);          /* Count at 100Hz */
 
 117         wdt_ctr_load(1,wd_heartbeat);   /* Heartbeat */
 
 118         wdt_ctr_load(2,65535);          /* Length of reset pulse */
 
 119         outb_p(0, WDT_DC);              /* Enable watchdog */
 
 126  *      Stop the watchdog driver.
 
 129 static int wdt_stop (void)
 
 131         /* Turn the card off */
 
 132         inb_p(WDT_DC);                  /* Disable watchdog */
 
 133         wdt_ctr_load(2,0);              /* 0 length reset pulses now */
 
 140  *      Reload counter one with the watchdog heartbeat. We don't bother reloading
 
 141  *      the cascade counter.
 
 144 static int wdt_ping(void)
 
 146         /* Write a watchdog value */
 
 147         inb_p(WDT_DC);                  /* Disable watchdog */
 
 148         wdt_ctr_mode(1,2);              /* Re-Program CTR1 for Mode 2: Rate Generator */
 
 149         wdt_ctr_load(1,wd_heartbeat);   /* Heartbeat */
 
 150         outb_p(0, WDT_DC);              /* Enable watchdog */
 
 156  *      @t:             the new heartbeat value that needs to be set.
 
 158  *      Set a new heartbeat value for the watchdog device. If the heartbeat value is
 
 159  *      incorrect we keep the old value and return -EINVAL. If successfull we
 
 162 static int wdt_set_heartbeat(int t)
 
 164         if ((t < 1) || (t > 65535))
 
 168         wd_heartbeat = t * 100;
 
 174  *      @status:                the new status.
 
 176  *      Extract the status information from a WDT watchdog device. There are
 
 177  *      several board variants so we have to know which bits are valid. Some
 
 178  *      bits default to one and some to zero in order to be maximally painful.
 
 180  *      we then map the bits onto the status ioctl flags.
 
 183 static int wdt_get_status(int *status)
 
 185         unsigned char new_status=inb_p(WDT_SR);
 
 188         if (new_status & WDC_SR_ISOI0)
 
 189                 *status |= WDIOF_EXTERN1;
 
 190         if (new_status & WDC_SR_ISII1)
 
 191                 *status |= WDIOF_EXTERN2;
 
 192 #ifdef CONFIG_WDT_501
 
 193         if (!(new_status & WDC_SR_TGOOD))
 
 194                 *status |= WDIOF_OVERHEAT;
 
 195         if (!(new_status & WDC_SR_PSUOVER))
 
 196                 *status |= WDIOF_POWEROVER;
 
 197         if (!(new_status & WDC_SR_PSUUNDR))
 
 198                 *status |= WDIOF_POWERUNDER;
 
 200                 if (!(new_status & WDC_SR_FANGOOD))
 
 201                         *status |= WDIOF_FANFAULT;
 
 203 #endif /* CONFIG_WDT_501 */
 
 207 #ifdef CONFIG_WDT_501
 
 209  *      wdt_get_temperature:
 
 211  *      Reports the temperature in degrees Fahrenheit. The API is in
 
 212  *      farenheit. It was designed by an imperial measurement luddite.
 
 215 static int wdt_get_temperature(int *temperature)
 
 217         unsigned short c=inb_p(WDT_RT);
 
 219         *temperature = (c * 11 / 15) + 7;
 
 222 #endif /* CONFIG_WDT_501 */
 
 226  *      @irq:           Interrupt number
 
 227  *      @dev_id:        Unused as we don't allow multiple devices.
 
 229  *      Handle an interrupt from the board. These are raised when the status
 
 230  *      map changes in what the board considers an interesting way. That means
 
 231  *      a failure condition occurring.
 
 234 static irqreturn_t wdt_interrupt(int irq, void *dev_id)
 
 237          *      Read the status register see what is up and
 
 240         unsigned char status=inb_p(WDT_SR);
 
 242         printk(KERN_CRIT "WDT status %d\n", status);
 
 244 #ifdef CONFIG_WDT_501
 
 245         if (!(status & WDC_SR_TGOOD))
 
 246                 printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT));
 
 247         if (!(status & WDC_SR_PSUOVER))
 
 248                 printk(KERN_CRIT "PSU over voltage.\n");
 
 249         if (!(status & WDC_SR_PSUUNDR))
 
 250                 printk(KERN_CRIT "PSU under voltage.\n");
 
 252                 if (!(status & WDC_SR_FANGOOD))
 
 253                         printk(KERN_CRIT "Possible fan fault.\n");
 
 255 #endif /* CONFIG_WDT_501 */
 
 256         if (!(status & WDC_SR_WCCR)) {
 
 257 #ifdef SOFTWARE_REBOOT
 
 259                 printk(KERN_CRIT "Would Reboot.\n");
 
 261                 printk(KERN_CRIT "Initiating system reboot.\n");
 
 265                 printk(KERN_CRIT "Reset in 5ms.\n");
 
 274  *      @file: file handle to the watchdog
 
 275  *      @buf: buffer to write (unused as data does not matter here
 
 276  *      @count: count of bytes
 
 277  *      @ppos: pointer to the position to write. No seeks allowed
 
 279  *      A write to a watchdog device is defined as a keepalive signal. Any
 
 280  *      write of data will do, as we we don't define content meaning.
 
 283 static ssize_t wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
 
 289                         /* In case it was set long ago */
 
 292                         for (i = 0; i != count; i++) {
 
 294                                 if (get_user(c, buf + i))
 
 307  *      @inode: inode of the device
 
 308  *      @file: file handle to the device
 
 309  *      @cmd: watchdog command
 
 310  *      @arg: argument pointer
 
 312  *      The watchdog API defines a common set of functions for all watchdogs
 
 313  *      according to their available features. We only actually usefully support
 
 314  *      querying capabilities and current status.
 
 317 static int wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 
 320         void __user *argp = (void __user *)arg;
 
 321         int __user *p = argp;
 
 325         static struct watchdog_info ident = {
 
 326                 .options =              WDIOF_SETTIMEOUT|
 
 329                 .firmware_version =     1,
 
 330                 .identity =             "WDT500/501",
 
 333         /* Add options according to the card we have */
 
 334         ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2);
 
 335 #ifdef CONFIG_WDT_501
 
 336         ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER);
 
 338                 ident.options |= WDIOF_FANFAULT;
 
 339 #endif /* CONFIG_WDT_501 */
 
 345                 case WDIOC_GETSUPPORT:
 
 346                         return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0;
 
 348                 case WDIOC_GETSTATUS:
 
 349                         wdt_get_status(&status);
 
 350                         return put_user(status, p);
 
 351                 case WDIOC_GETBOOTSTATUS:
 
 352                         return put_user(0, p);
 
 353                 case WDIOC_KEEPALIVE:
 
 356                 case WDIOC_SETTIMEOUT:
 
 357                         if (get_user(new_heartbeat, p))
 
 360                         if (wdt_set_heartbeat(new_heartbeat))
 
 365                 case WDIOC_GETTIMEOUT:
 
 366                         return put_user(heartbeat, p);
 
 372  *      @inode: inode of device
 
 373  *      @file: file handle to device
 
 375  *      The watchdog device has been opened. The watchdog device is single
 
 376  *      open and on opening we load the counters. Counter zero is a 100Hz
 
 377  *      cascade, into counter 1 which downcounts to reboot. When the counter
 
 378  *      triggers counter 2 downcounts the length of the reset pulse which
 
 379  *      set set to be as long as possible.
 
 382 static int wdt_open(struct inode *inode, struct file *file)
 
 384         if(test_and_set_bit(0, &wdt_is_open))
 
 390         return nonseekable_open(inode, file);
 
 395  *      @inode: inode to board
 
 396  *      @file: file handle to board
 
 398  *      The watchdog has a configurable API. There is a religious dispute
 
 399  *      between people who want their watchdog to be able to shut down and
 
 400  *      those who want to be sure if the watchdog manager dies the machine
 
 401  *      reboots. In the former case we disable the counters, in the latter
 
 402  *      case you have to open it again very soon.
 
 405 static int wdt_release(struct inode *inode, struct file *file)
 
 407         if (expect_close == 42) {
 
 409                 clear_bit(0, &wdt_is_open);
 
 411                 printk(KERN_CRIT "wdt: WDT device closed unexpectedly.  WDT will not stop!\n");
 
 418 #ifdef CONFIG_WDT_501
 
 421  *      @file: file handle to the watchdog board
 
 422  *      @buf: buffer to write 1 byte into
 
 423  *      @count: length of buffer
 
 424  *      @ptr: offset (no seek allowed)
 
 426  *      Temp_read reports the temperature in degrees Fahrenheit. The API is in
 
 427  *      farenheit. It was designed by an imperial measurement luddite.
 
 430 static ssize_t wdt_temp_read(struct file *file, char __user *buf, size_t count, loff_t *ptr)
 
 434         if (wdt_get_temperature(&temperature))
 
 437         if (copy_to_user (buf, &temperature, 1))
 
 445  *      @inode: inode of device
 
 446  *      @file: file handle to device
 
 448  *      The temperature device has been opened.
 
 451 static int wdt_temp_open(struct inode *inode, struct file *file)
 
 453         return nonseekable_open(inode, file);
 
 458  *      @inode: inode to board
 
 459  *      @file: file handle to board
 
 461  *      The temperature device has been closed.
 
 464 static int wdt_temp_release(struct inode *inode, struct file *file)
 
 468 #endif /* CONFIG_WDT_501 */
 
 472  *      @this: our notifier block
 
 473  *      @code: the event being reported
 
 476  *      Our notifier is called on system shutdowns. We want to turn the card
 
 477  *      off at reboot otherwise the machine will reboot again during memory
 
 478  *      test or worse yet during the following fsck. This would suck, in fact
 
 479  *      trust me - if it happens it does suck.
 
 482 static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
 
 485         if(code==SYS_DOWN || code==SYS_HALT) {
 
 486                 /* Turn the card off */
 
 497 static const struct file_operations wdt_fops = {
 
 498         .owner          = THIS_MODULE,
 
 503         .release        = wdt_release,
 
 506 static struct miscdevice wdt_miscdev = {
 
 507         .minor  = WATCHDOG_MINOR,
 
 512 #ifdef CONFIG_WDT_501
 
 513 static const struct file_operations wdt_temp_fops = {
 
 514         .owner          = THIS_MODULE,
 
 516         .read           = wdt_temp_read,
 
 517         .open           = wdt_temp_open,
 
 518         .release        = wdt_temp_release,
 
 521 static struct miscdevice temp_miscdev = {
 
 523         .name   = "temperature",
 
 524         .fops   = &wdt_temp_fops,
 
 526 #endif /* CONFIG_WDT_501 */
 
 529  *      The WDT card needs to learn about soft shutdowns in order to
 
 530  *      turn the timebomb registers off.
 
 533 static struct notifier_block wdt_notifier = {
 
 534         .notifier_call = wdt_notify_sys,
 
 540  *      Unload the watchdog. You cannot do this with any file handles open.
 
 541  *      If your watchdog is set to continue ticking on close and you unload
 
 542  *      it, well it keeps ticking. We won't get the interrupt but the board
 
 543  *      will not touch PC memory so all is fine. You just have to load a new
 
 544  *      module in 60 seconds or reboot.
 
 547 static void __exit wdt_exit(void)
 
 549         misc_deregister(&wdt_miscdev);
 
 550 #ifdef CONFIG_WDT_501
 
 551         misc_deregister(&temp_miscdev);
 
 552 #endif /* CONFIG_WDT_501 */
 
 553         unregister_reboot_notifier(&wdt_notifier);
 
 555         release_region(io,8);
 
 561  *      Set up the WDT watchdog board. All we have to do is grab the
 
 562  *      resources we require and bitch if anyone beat us to them.
 
 563  *      The open() function will actually kick the board off.
 
 566 static int __init wdt_init(void)
 
 570         /* Check that the heartbeat value is within it's range ; if not reset to the default */
 
 571         if (wdt_set_heartbeat(heartbeat)) {
 
 572                 wdt_set_heartbeat(WD_TIMO);
 
 573                 printk(KERN_INFO "wdt: heartbeat value must be 0<heartbeat<65536, using %d\n",
 
 577         if (!request_region(io, 8, "wdt501p")) {
 
 578                 printk(KERN_ERR "wdt: I/O address 0x%04x already in use\n", io);
 
 583         ret = request_irq(irq, wdt_interrupt, IRQF_DISABLED, "wdt501p", NULL);
 
 585                 printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq);
 
 589         ret = register_reboot_notifier(&wdt_notifier);
 
 591                 printk(KERN_ERR "wdt: cannot register reboot notifier (err=%d)\n", ret);
 
 595 #ifdef CONFIG_WDT_501
 
 596         ret = misc_register(&temp_miscdev);
 
 598                 printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n",
 
 602 #endif /* CONFIG_WDT_501 */
 
 604         ret = misc_register(&wdt_miscdev);
 
 606                 printk(KERN_ERR "wdt: cannot register miscdev on minor=%d (err=%d)\n",
 
 607                         WATCHDOG_MINOR, ret);
 
 612         printk(KERN_INFO "WDT500/501-P driver 0.10 at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n",
 
 613                 io, irq, heartbeat, nowayout);
 
 614 #ifdef CONFIG_WDT_501
 
 615         printk(KERN_INFO "wdt: Fan Tachometer is %s\n", (tachometer ? "Enabled" : "Disabled"));
 
 616 #endif /* CONFIG_WDT_501 */
 
 622 #ifdef CONFIG_WDT_501
 
 623         misc_deregister(&temp_miscdev);
 
 625 #endif /* CONFIG_WDT_501 */
 
 626         unregister_reboot_notifier(&wdt_notifier);
 
 630         release_region(io,8);
 
 634 module_init(wdt_init);
 
 635 module_exit(wdt_exit);
 
 637 MODULE_AUTHOR("Alan Cox");
 
 638 MODULE_DESCRIPTION("Driver for ISA ICS watchdog cards (WDT500/501)");
 
 639 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
 
 640 MODULE_ALIAS_MISCDEV(TEMP_MINOR);
 
 641 MODULE_LICENSE("GPL");