1/* 2 * Industrial Computer Source WDT501 driver 3 * 4 * (c) Copyright 1996-1997 Alan Cox <alan@lxorguk.ukuu.org.uk>, 5 * All Rights Reserved. 6 * 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. 11 * 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. 15 * 16 * (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk> 17 * 18 * Release 0.10. 19 * 20 * Fixes 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 24 * Matt Crocker). 25 * Alan Cox : Added wdt= boot option 26 * Alan Cox : Cleaned up copy/user stuff 27 * Tim Hockin : Added insmod parameters, comment 28 * cleanup, parameterized timeout 29 * Tigran Aivazian : Restructured wdt_init() to handle 30 * failures 31 * Joel Becker : Added WDIOC_GET/SETTIMEOUT 32 * Matt Domsch : Added nowayout module option 33 */ 34 35#include <linux/interrupt.h> 36#include <linux/module.h> 37#include <linux/moduleparam.h> 38#include <linux/types.h> 39#include <linux/miscdevice.h> 40#include <linux/watchdog.h> 41#include <linux/fs.h> 42#include <linux/ioport.h> 43#include <linux/notifier.h> 44#include <linux/reboot.h> 45#include <linux/init.h> 46#include <linux/io.h> 47#include <linux/uaccess.h> 48 49#include <asm/system.h> 50#include "wd501p.h" 51 52static unsigned long wdt_is_open; 53static char expect_close; 54 55/* 56 * Module parameters 57 */ 58 59#define WD_TIMO 60 /* Default heartbeat = 60 seconds */ 60 61static int heartbeat = WD_TIMO; 62static int wd_heartbeat; 63module_param(heartbeat, int, 0); 64MODULE_PARM_DESC(heartbeat, 65 "Watchdog heartbeat in seconds. (0 < heartbeat < 65536, default=" 66 __MODULE_STRING(WD_TIMO) ")"); 67 68static int nowayout = WATCHDOG_NOWAYOUT; 69module_param(nowayout, int, 0); 70MODULE_PARM_DESC(nowayout, 71 "Watchdog cannot be stopped once started (default=" 72 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 73 74/* You must set these - there is no sane way to probe for this board. */ 75static int io = 0x240; 76static int irq = 11; 77 78static DEFINE_SPINLOCK(wdt_lock); 79 80module_param(io, int, 0); 81MODULE_PARM_DESC(io, "WDT io port (default=0x240)"); 82module_param(irq, int, 0); 83MODULE_PARM_DESC(irq, "WDT irq (default=11)"); 84 85/* Support for the Fan Tachometer on the WDT501-P */ 86static int tachometer; 87module_param(tachometer, int, 0); 88MODULE_PARM_DESC(tachometer, 89 "WDT501-P Fan Tachometer support (0=disable, default=0)"); 90 91static int type = 500; 92module_param(type, int, 0); 93MODULE_PARM_DESC(type, 94 "WDT501-P Card type (500 or 501, default=500)"); 95 96/* 97 * Programming support 98 */ 99 100static void wdt_ctr_mode(int ctr, int mode) 101{ 102 ctr <<= 6; 103 ctr |= 0x30; 104 ctr |= (mode << 1); 105 outb_p(ctr, WDT_CR); 106} 107 108static void wdt_ctr_load(int ctr, int val) 109{ 110 outb_p(val&0xFF, WDT_COUNT0+ctr); 111 outb_p(val>>8, WDT_COUNT0+ctr); 112} 113 114/** 115 * wdt_start: 116 * 117 * Start the watchdog driver. 118 */ 119 120static int wdt_start(void) 121{ 122 unsigned long flags; 123 spin_lock_irqsave(&wdt_lock, flags); 124 inb_p(WDT_DC); /* Disable watchdog */ 125 wdt_ctr_mode(0, 3); /* Program CTR0 for Mode 3: 126 Square Wave Generator */ 127 wdt_ctr_mode(1, 2); /* Program CTR1 for Mode 2: 128 Rate Generator */ 129 wdt_ctr_mode(2, 0); /* Program CTR2 for Mode 0: 130 Pulse on Terminal Count */ 131 wdt_ctr_load(0, 8948); /* Count at 100Hz */ 132 wdt_ctr_load(1, wd_heartbeat); /* Heartbeat */ 133 wdt_ctr_load(2, 65535); /* Length of reset pulse */ 134 outb_p(0, WDT_DC); /* Enable watchdog */ 135 spin_unlock_irqrestore(&wdt_lock, flags); 136 return 0; 137} 138 139/** 140 * wdt_stop: 141 * 142 * Stop the watchdog driver. 143 */ 144 145static int wdt_stop(void) 146{ 147 unsigned long flags; 148 spin_lock_irqsave(&wdt_lock, flags); 149 /* Turn the card off */ 150 inb_p(WDT_DC); /* Disable watchdog */ 151 wdt_ctr_load(2, 0); /* 0 length reset pulses now */ 152 spin_unlock_irqrestore(&wdt_lock, flags); 153 return 0; 154} 155 156/** 157 * wdt_ping: 158 * 159 * Reload counter one with the watchdog heartbeat. We don't bother 160 * reloading the cascade counter. 161 */ 162 163static void wdt_ping(void) 164{ 165 unsigned long flags; 166 spin_lock_irqsave(&wdt_lock, flags); 167 /* Write a watchdog value */ 168 inb_p(WDT_DC); /* Disable watchdog */ 169 wdt_ctr_mode(1, 2); /* Re-Program CTR1 for Mode 2: 170 Rate Generator */ 171 wdt_ctr_load(1, wd_heartbeat); /* Heartbeat */ 172 outb_p(0, WDT_DC); /* Enable watchdog */ 173 spin_unlock_irqrestore(&wdt_lock, flags); 174} 175 176/** 177 * wdt_set_heartbeat: 178 * @t: the new heartbeat value that needs to be set. 179 * 180 * Set a new heartbeat value for the watchdog device. If the heartbeat 181 * value is incorrect we keep the old value and return -EINVAL. If 182 * successful we return 0. 183 */ 184 185static int wdt_set_heartbeat(int t) 186{ 187 if (t < 1 || t > 65535) 188 return -EINVAL; 189 190 heartbeat = t; 191 wd_heartbeat = t * 100; 192 return 0; 193} 194 195/** 196 * wdt_get_status: 197 * 198 * Extract the status information from a WDT watchdog device. There are 199 * several board variants so we have to know which bits are valid. Some 200 * bits default to one and some to zero in order to be maximally painful. 201 * 202 * we then map the bits onto the status ioctl flags. 203 */ 204 205static int wdt_get_status(void) 206{ 207 unsigned char new_status; 208 int status = 0; 209 unsigned long flags; 210 211 spin_lock_irqsave(&wdt_lock, flags); 212 new_status = inb_p(WDT_SR); 213 spin_unlock_irqrestore(&wdt_lock, flags); 214 215 if (new_status & WDC_SR_ISOI0) 216 status |= WDIOF_EXTERN1; 217 if (new_status & WDC_SR_ISII1) 218 status |= WDIOF_EXTERN2; 219 if (type == 501) { 220 if (!(new_status & WDC_SR_TGOOD)) 221 status |= WDIOF_OVERHEAT; 222 if (!(new_status & WDC_SR_PSUOVER)) 223 status |= WDIOF_POWEROVER; 224 if (!(new_status & WDC_SR_PSUUNDR)) 225 status |= WDIOF_POWERUNDER; 226 if (tachometer) { 227 if (!(new_status & WDC_SR_FANGOOD)) 228 status |= WDIOF_FANFAULT; 229 } 230 } 231 return status; 232} 233 234/** 235 * wdt_get_temperature: 236 * 237 * Reports the temperature in degrees Fahrenheit. The API is in 238 * farenheit. It was designed by an imperial measurement luddite. 239 */ 240 241static int wdt_get_temperature(void) 242{ 243 unsigned short c; 244 unsigned long flags; 245 246 spin_lock_irqsave(&wdt_lock, flags); 247 c = inb_p(WDT_RT); 248 spin_unlock_irqrestore(&wdt_lock, flags); 249 return (c * 11 / 15) + 7; 250} 251 252static void wdt_decode_501(int status) 253{ 254 if (!(status & WDC_SR_TGOOD)) 255 printk(KERN_CRIT "Overheat alarm.(%d)\n", inb_p(WDT_RT)); 256 if (!(status & WDC_SR_PSUOVER)) 257 printk(KERN_CRIT "PSU over voltage.\n"); 258 if (!(status & WDC_SR_PSUUNDR)) 259 printk(KERN_CRIT "PSU under voltage.\n"); 260} 261 262/** 263 * wdt_interrupt: 264 * @irq: Interrupt number 265 * @dev_id: Unused as we don't allow multiple devices. 266 * 267 * Handle an interrupt from the board. These are raised when the status 268 * map changes in what the board considers an interesting way. That means 269 * a failure condition occurring. 270 */ 271 272static irqreturn_t wdt_interrupt(int irq, void *dev_id) 273{ 274 /* 275 * Read the status register see what is up and 276 * then printk it. 277 */ 278 unsigned char status; 279 280 spin_lock(&wdt_lock); 281 status = inb_p(WDT_SR); 282 283 printk(KERN_CRIT "WDT status %d\n", status); 284 285 if (type == 501) { 286 wdt_decode_501(status); 287 if (tachometer) { 288 if (!(status & WDC_SR_FANGOOD)) 289 printk(KERN_CRIT "Possible fan fault.\n"); 290 } 291 } 292 if (!(status & WDC_SR_WCCR)) { 293#ifdef SOFTWARE_REBOOT 294#ifdef ONLY_TESTING 295 printk(KERN_CRIT "Would Reboot.\n"); 296#else 297 printk(KERN_CRIT "Initiating system reboot.\n"); 298 emergency_restart(); 299#endif 300#else 301 printk(KERN_CRIT "Reset in 5ms.\n"); 302#endif 303 } 304 spin_unlock(&wdt_lock); 305 return IRQ_HANDLED; 306} 307 308 309/** 310 * wdt_write: 311 * @file: file handle to the watchdog 312 * @buf: buffer to write (unused as data does not matter here 313 * @count: count of bytes 314 * @ppos: pointer to the position to write. No seeks allowed 315 * 316 * A write to a watchdog device is defined as a keepalive signal. Any 317 * write of data will do, as we we don't define content meaning. 318 */ 319 320static ssize_t wdt_write(struct file *file, const char __user *buf, 321 size_t count, loff_t *ppos) 322{ 323 if (count) { 324 if (!nowayout) { 325 size_t i; 326 327 /* In case it was set long ago */ 328 expect_close = 0; 329 330 for (i = 0; i != count; i++) { 331 char c; 332 if (get_user(c, buf + i)) 333 return -EFAULT; 334 if (c == 'V') 335 expect_close = 42; 336 } 337 } 338 wdt_ping(); 339 } 340 return count; 341} 342 343/** 344 * wdt_ioctl: 345 * @file: file handle to the device 346 * @cmd: watchdog command 347 * @arg: argument pointer 348 * 349 * The watchdog API defines a common set of functions for all watchdogs 350 * according to their available features. We only actually usefully support 351 * querying capabilities and current status. 352 */ 353 354static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 355{ 356 void __user *argp = (void __user *)arg; 357 int __user *p = argp; 358 int new_heartbeat; 359 int status; 360 361 struct watchdog_info ident = { 362 .options = WDIOF_SETTIMEOUT| 363 WDIOF_MAGICCLOSE| 364 WDIOF_KEEPALIVEPING, 365 .firmware_version = 1, 366 .identity = "WDT500/501", 367 }; 368 369 /* Add options according to the card we have */ 370 ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2); 371 if (type == 501) { 372 ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER| 373 WDIOF_POWEROVER); 374 if (tachometer) 375 ident.options |= WDIOF_FANFAULT; 376 } 377 378 switch (cmd) { 379 case WDIOC_GETSUPPORT: 380 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 381 case WDIOC_GETSTATUS: 382 status = wdt_get_status(); 383 return put_user(status, p); 384 case WDIOC_GETBOOTSTATUS: 385 return put_user(0, p); 386 case WDIOC_KEEPALIVE: 387 wdt_ping(); 388 return 0; 389 case WDIOC_SETTIMEOUT: 390 if (get_user(new_heartbeat, p)) 391 return -EFAULT; 392 if (wdt_set_heartbeat(new_heartbeat)) 393 return -EINVAL; 394 wdt_ping(); 395 /* Fall */ 396 case WDIOC_GETTIMEOUT: 397 return put_user(heartbeat, p); 398 default: 399 return -ENOTTY; 400 } 401} 402 403/** 404 * wdt_open: 405 * @inode: inode of device 406 * @file: file handle to device 407 * 408 * The watchdog device has been opened. The watchdog device is single 409 * open and on opening we load the counters. Counter zero is a 100Hz 410 * cascade, into counter 1 which downcounts to reboot. When the counter 411 * triggers counter 2 downcounts the length of the reset pulse which 412 * set set to be as long as possible. 413 */ 414 415static int wdt_open(struct inode *inode, struct file *file) 416{ 417 if (test_and_set_bit(0, &wdt_is_open)) 418 return -EBUSY; 419 /* 420 * Activate 421 */ 422 wdt_start(); 423 return nonseekable_open(inode, file); 424} 425 426/** 427 * wdt_release: 428 * @inode: inode to board 429 * @file: file handle to board 430 * 431 * The watchdog has a configurable API. There is a religious dispute 432 * between people who want their watchdog to be able to shut down and 433 * those who want to be sure if the watchdog manager dies the machine 434 * reboots. In the former case we disable the counters, in the latter 435 * case you have to open it again very soon. 436 */ 437 438static int wdt_release(struct inode *inode, struct file *file) 439{ 440 if (expect_close == 42) { 441 wdt_stop(); 442 clear_bit(0, &wdt_is_open); 443 } else { 444 printk(KERN_CRIT 445 "wdt: WDT device closed unexpectedly. WDT will not stop!\n"); 446 wdt_ping(); 447 } 448 expect_close = 0; 449 return 0; 450} 451 452/** 453 * wdt_temp_read: 454 * @file: file handle to the watchdog board 455 * @buf: buffer to write 1 byte into 456 * @count: length of buffer 457 * @ptr: offset (no seek allowed) 458 * 459 * Temp_read reports the temperature in degrees Fahrenheit. The API is in 460 * farenheit. It was designed by an imperial measurement luddite. 461 */ 462 463static ssize_t wdt_temp_read(struct file *file, char __user *buf, 464 size_t count, loff_t *ptr) 465{ 466 int temperature = wdt_get_temperature(); 467 468 if (copy_to_user(buf, &temperature, 1)) 469 return -EFAULT; 470 471 return 1; 472} 473 474/** 475 * wdt_temp_open: 476 * @inode: inode of device 477 * @file: file handle to device 478 * 479 * The temperature device has been opened. 480 */ 481 482static int wdt_temp_open(struct inode *inode, struct file *file) 483{ 484 return nonseekable_open(inode, file); 485} 486 487/** 488 * wdt_temp_release: 489 * @inode: inode to board 490 * @file: file handle to board 491 * 492 * The temperature device has been closed. 493 */ 494 495static int wdt_temp_release(struct inode *inode, struct file *file) 496{ 497 return 0; 498} 499 500/** 501 * notify_sys: 502 * @this: our notifier block 503 * @code: the event being reported 504 * @unused: unused 505 * 506 * Our notifier is called on system shutdowns. We want to turn the card 507 * off at reboot otherwise the machine will reboot again during memory 508 * test or worse yet during the following fsck. This would suck, in fact 509 * trust me - if it happens it does suck. 510 */ 511 512static int wdt_notify_sys(struct notifier_block *this, unsigned long code, 513 void *unused) 514{ 515 if (code == SYS_DOWN || code == SYS_HALT) 516 wdt_stop(); 517 return NOTIFY_DONE; 518} 519 520/* 521 * Kernel Interfaces 522 */ 523 524 525static const struct file_operations wdt_fops = { 526 .owner = THIS_MODULE, 527 .llseek = no_llseek, 528 .write = wdt_write, 529 .unlocked_ioctl = wdt_ioctl, 530 .open = wdt_open, 531 .release = wdt_release, 532}; 533 534static struct miscdevice wdt_miscdev = { 535 .minor = WATCHDOG_MINOR, 536 .name = "watchdog", 537 .fops = &wdt_fops, 538}; 539 540static const struct file_operations wdt_temp_fops = { 541 .owner = THIS_MODULE, 542 .llseek = no_llseek, 543 .read = wdt_temp_read, 544 .open = wdt_temp_open, 545 .release = wdt_temp_release, 546}; 547 548static struct miscdevice temp_miscdev = { 549 .minor = TEMP_MINOR, 550 .name = "temperature", 551 .fops = &wdt_temp_fops, 552}; 553 554/* 555 * The WDT card needs to learn about soft shutdowns in order to 556 * turn the timebomb registers off. 557 */ 558 559static struct notifier_block wdt_notifier = { 560 .notifier_call = wdt_notify_sys, 561}; 562 563/** 564 * cleanup_module: 565 * 566 * Unload the watchdog. You cannot do this with any file handles open. 567 * If your watchdog is set to continue ticking on close and you unload 568 * it, well it keeps ticking. We won't get the interrupt but the board 569 * will not touch PC memory so all is fine. You just have to load a new 570 * module in 60 seconds or reboot. 571 */ 572 573static void __exit wdt_exit(void) 574{ 575 misc_deregister(&wdt_miscdev); 576 if (type == 501) 577 misc_deregister(&temp_miscdev); 578 unregister_reboot_notifier(&wdt_notifier); 579 free_irq(irq, NULL); 580 release_region(io, 8); 581} 582 583/** 584 * wdt_init: 585 * 586 * Set up the WDT watchdog board. All we have to do is grab the 587 * resources we require and bitch if anyone beat us to them. 588 * The open() function will actually kick the board off. 589 */ 590 591static int __init wdt_init(void) 592{ 593 int ret; 594 595 if (type != 500 && type != 501) { 596 printk(KERN_ERR "wdt: unknown card type '%d'.\n", type); 597 return -ENODEV; 598 } 599 600 /* Check that the heartbeat value is within it's range; 601 if not reset to the default */ 602 if (wdt_set_heartbeat(heartbeat)) { 603 wdt_set_heartbeat(WD_TIMO); 604 printk(KERN_INFO "wdt: heartbeat value must be " 605 "0 < heartbeat < 65536, using %d\n", WD_TIMO); 606 } 607 608 if (!request_region(io, 8, "wdt501p")) { 609 printk(KERN_ERR 610 "wdt: I/O address 0x%04x already in use\n", io); 611 ret = -EBUSY; 612 goto out; 613 } 614 615 ret = request_irq(irq, wdt_interrupt, IRQF_DISABLED, "wdt501p", NULL); 616 if (ret) { 617 printk(KERN_ERR "wdt: IRQ %d is not free.\n", irq); 618 goto outreg; 619 } 620 621 ret = register_reboot_notifier(&wdt_notifier); 622 if (ret) { 623 printk(KERN_ERR 624 "wdt: cannot register reboot notifier (err=%d)\n", ret); 625 goto outirq; 626 } 627 628 if (type == 501) { 629 ret = misc_register(&temp_miscdev); 630 if (ret) { 631 printk(KERN_ERR "wdt: cannot register miscdev " 632 "on minor=%d (err=%d)\n", TEMP_MINOR, ret); 633 goto outrbt; 634 } 635 } 636 637 ret = misc_register(&wdt_miscdev); 638 if (ret) { 639 printk(KERN_ERR 640 "wdt: cannot register miscdev on minor=%d (err=%d)\n", 641 WATCHDOG_MINOR, ret); 642 goto outmisc; 643 } 644 645 printk(KERN_INFO "WDT500/501-P driver 0.10 " 646 "at 0x%04x (Interrupt %d). heartbeat=%d sec (nowayout=%d)\n", 647 io, irq, heartbeat, nowayout); 648 if (type == 501) 649 printk(KERN_INFO "wdt: Fan Tachometer is %s\n", 650 (tachometer ? "Enabled" : "Disabled")); 651 return 0; 652 653outmisc: 654 if (type == 501) 655 misc_deregister(&temp_miscdev); 656outrbt: 657 unregister_reboot_notifier(&wdt_notifier); 658outirq: 659 free_irq(irq, NULL); 660outreg: 661 release_region(io, 8); 662out: 663 return ret; 664} 665 666module_init(wdt_init); 667module_exit(wdt_exit); 668 669MODULE_AUTHOR("Alan Cox"); 670MODULE_DESCRIPTION("Driver for ISA ICS watchdog cards (WDT500/501)"); 671MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 672MODULE_ALIAS_MISCDEV(TEMP_MINOR); 673MODULE_LICENSE("GPL"); 674