1/* 2 * Industrial Computer Source WDT500/501 driver for Linux 2.1.x 3 * 4 * (c) Copyright 1996-1997 Alan Cox <alan@redhat.com>, All Rights Reserved. 5 * http://www.redhat.com 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.08. 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 cleanup 28 * Parameterized timeout 29 * JP Nollmann : Added support for PCI wdt501p 30 * Alan Cox : Split ISA and PCI cards into two drivers 31 * Jeff Garzik : PCI cleanups 32 * Tigran Aivazian : Restructured wdtpci_init_one() to handle failures 33 * Joel Becker : Added WDIOC_GET/SETTIMEOUT 34 * Zwane Mwaikambo : Magic char closing, locking changes, cleanups 35 * Matt Domsch : nowayout module option 36 */ 37 38#include <linux/config.h> 39#include <linux/module.h> 40#include <linux/version.h> 41#include <linux/types.h> 42#include <linux/errno.h> 43#include <linux/kernel.h> 44#include <linux/sched.h> 45#include <linux/miscdevice.h> 46#include <linux/watchdog.h> 47#define WDT_IS_PCI 48#include "wd501p.h" 49#include <linux/slab.h> 50#include <linux/ioport.h> 51#include <linux/fcntl.h> 52#include <asm/io.h> 53#include <asm/uaccess.h> 54#include <asm/system.h> 55#include <linux/notifier.h> 56#include <linux/reboot.h> 57#include <linux/init.h> 58#include <linux/spinlock.h> 59#include <asm/semaphore.h> 60 61#include <linux/pci.h> 62 63#define PFX "wdt_pci: " 64 65/* 66 * Until Access I/O gets their application for a PCI vendor ID approved, 67 * I don't think that it's appropriate to move these constants into the 68 * regular pci_ids.h file. -- JPN 2000/01/18 69 */ 70 71#ifndef PCI_VENDOR_ID_ACCESSIO 72#define PCI_VENDOR_ID_ACCESSIO 0x494f 73#endif 74#ifndef PCI_DEVICE_ID_WDG_CSM 75#define PCI_DEVICE_ID_WDG_CSM 0x22c0 76#endif 77 78static struct semaphore open_sem; 79static spinlock_t wdtpci_lock; 80static int expect_close = 0; 81 82static int io; 83static int irq; 84 85/* Default timeout */ 86#define WD_TIMO (100*60) /* 1 minute */ 87#define WD_TIMO_MAX (WD_TIMO*60) /* 1 hour(?) */ 88 89static int wd_margin = WD_TIMO; 90 91#ifdef CONFIG_WATCHDOG_NOWAYOUT 92static int nowayout = 1; 93#else 94static int nowayout = 0; 95#endif 96 97MODULE_PARM(nowayout,"i"); 98MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 99 100/* 101 * Programming support 102 */ 103 104static void wdtpci_ctr_mode(int ctr, int mode) 105{ 106 ctr<<=6; 107 ctr|=0x30; 108 ctr|=(mode<<1); 109 outb_p(ctr, WDT_CR); 110} 111 112static void wdtpci_ctr_load(int ctr, int val) 113{ 114 outb_p(val&0xFF, WDT_COUNT0+ctr); 115 outb_p(val>>8, WDT_COUNT0+ctr); 116} 117 118/* 119 * Kernel methods. 120 */ 121 122 123/** 124 * wdtpci_status: 125 * 126 * Extract the status information from a WDT watchdog device. There are 127 * several board variants so we have to know which bits are valid. Some 128 * bits default to one and some to zero in order to be maximally painful. 129 * 130 * we then map the bits onto the status ioctl flags. 131 */ 132 133static int wdtpci_status(void) 134{ 135 /* 136 * Status register to bit flags 137 */ 138 139 int flag=0; 140 unsigned char status=inb_p(WDT_SR); 141 status|=FEATUREMAP1; 142 status&=~FEATUREMAP2; 143 144 if(!(status&WDC_SR_TGOOD)) 145 flag|=WDIOF_OVERHEAT; 146 if(!(status&WDC_SR_PSUOVER)) 147 flag|=WDIOF_POWEROVER; 148 if(!(status&WDC_SR_PSUUNDR)) 149 flag|=WDIOF_POWERUNDER; 150 if(!(status&WDC_SR_FANGOOD)) 151 flag|=WDIOF_FANFAULT; 152 if(status&WDC_SR_ISOI0) 153 flag|=WDIOF_EXTERN1; 154 if(status&WDC_SR_ISII1) 155 flag|=WDIOF_EXTERN2; 156 return flag; 157} 158 159/** 160 * wdtpci_interrupt: 161 * @irq: Interrupt number 162 * @dev_id: Unused as we don't allow multiple devices. 163 * @regs: Unused. 164 * 165 * Handle an interrupt from the board. These are raised when the status 166 * map changes in what the board considers an interesting way. That means 167 * a failure condition occuring. 168 */ 169 170static void wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs) 171{ 172 /* 173 * Read the status register see what is up and 174 * then printk it. 175 */ 176 177 unsigned char status=inb_p(WDT_SR); 178 179 status|=FEATUREMAP1; 180 status&=~FEATUREMAP2; 181 182 printk(KERN_CRIT "WDT status %d\n", status); 183 184 if(!(status&WDC_SR_TGOOD)) 185 printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT)); 186 if(!(status&WDC_SR_PSUOVER)) 187 printk(KERN_CRIT "PSU over voltage.\n"); 188 if(!(status&WDC_SR_PSUUNDR)) 189 printk(KERN_CRIT "PSU under voltage.\n"); 190 if(!(status&WDC_SR_FANGOOD)) 191 printk(KERN_CRIT "Possible fan fault.\n"); 192 if(!(status&WDC_SR_WCCR)) 193#ifdef SOFTWARE_REBOOT 194#ifdef ONLY_TESTING 195 printk(KERN_CRIT "Would Reboot.\n"); 196#else 197 printk(KERN_CRIT "Initiating system reboot.\n"); 198 machine_restart(NULL); 199#endif 200#else 201 printk(KERN_CRIT "Reset in 5ms.\n"); 202#endif 203} 204 205 206/** 207 * wdtpci_ping: 208 * 209 * Reload counter one with the watchdog timeout. We don't bother reloading 210 * the cascade counter. 211 */ 212 213static void wdtpci_ping(void) 214{ 215 unsigned long flags; 216 217 /* Write a watchdog value */ 218 spin_lock_irqsave(&wdtpci_lock, flags); 219 inb_p(WDT_DC); 220 wdtpci_ctr_mode(1,2); 221 wdtpci_ctr_load(1,wd_margin); /* Timeout */ 222 outb_p(0, WDT_DC); 223 spin_unlock_irqrestore(&wdtpci_lock, flags); 224} 225 226/** 227 * wdtpci_write: 228 * @file: file handle to the watchdog 229 * @buf: buffer to write (unused as data does not matter here 230 * @count: count of bytes 231 * @ppos: pointer to the position to write. No seeks allowed 232 * 233 * A write to a watchdog device is defined as a keepalive signal. Any 234 * write of data will do, as we we don't define content meaning. 235 */ 236 237static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, loff_t *ppos) 238{ 239 /* Can't seek (pwrite) on this device */ 240 if (ppos != &file->f_pos) 241 return -ESPIPE; 242 243 if (count) { 244 if (!nowayout) { 245 size_t i; 246 247 expect_close = 0; 248 249 for (i = 0; i != count; i++) { 250 char c; 251 if(get_user(c, buf+i)) 252 return -EFAULT; 253 if (c == 'V') 254 expect_close = 1; 255 } 256 } 257 wdtpci_ping(); 258 } 259 260 return count; 261} 262 263/** 264 * wdtpci_read: 265 * @file: file handle to the watchdog board 266 * @buf: buffer to write 1 byte into 267 * @count: length of buffer 268 * @ptr: offset (no seek allowed) 269 * 270 * Read reports the temperature in degrees Fahrenheit. The API is in 271 * fahrenheit. It was designed by an imperial measurement luddite. 272 */ 273 274static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *ptr) 275{ 276 unsigned short c=inb_p(WDT_RT); 277 unsigned char cp; 278 279 /* Can't seek (pread) on this device */ 280 if (ptr != &file->f_pos) 281 return -ESPIPE; 282 283 switch(MINOR(file->f_dentry->d_inode->i_rdev)) 284 { 285 case TEMP_MINOR: 286 c*=11; 287 c/=15; 288 cp=c+7; 289 if(copy_to_user(buf,&cp,1)) 290 return -EFAULT; 291 return 1; 292 default: 293 return -EINVAL; 294 } 295} 296 297/** 298 * wdtpci_ioctl: 299 * @inode: inode of the device 300 * @file: file handle to the device 301 * @cmd: watchdog command 302 * @arg: argument pointer 303 * 304 * The watchdog API defines a common set of functions for all watchdogs 305 * according to their available features. We only actually usefully support 306 * querying capabilities and current status. 307 */ 308 309static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, 310 unsigned long arg) 311{ 312 int new_margin; 313 static struct watchdog_info ident= 314 { 315 WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER 316 |WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT 317 |WDIOF_SETTIMEOUT|WDIOF_MAGICCLOSE, 318 1, 319 "WDT500/501PCI" 320 }; 321 322 ident.options&=WDT_OPTION_MASK; /* Mask down to the card we have */ 323 switch(cmd) 324 { 325 default: 326 return -ENOTTY; 327 case WDIOC_GETSUPPORT: 328 return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0; 329 330 case WDIOC_GETSTATUS: 331 return put_user(wdtpci_status(),(int *)arg); 332 case WDIOC_GETBOOTSTATUS: 333 return put_user(0, (int *)arg); 334 case WDIOC_KEEPALIVE: 335 wdtpci_ping(); 336 return 0; 337 case WDIOC_SETTIMEOUT: 338 if (get_user(new_margin, (int *)arg)) 339 return -EFAULT; 340 /* Arbitrary, can't find the card's limits */ 341 new_margin *= 100; 342 if ((new_margin < 0) || (new_margin > WD_TIMO_MAX)) 343 return -EINVAL; 344 wd_margin = new_margin; 345 wdtpci_ping(); 346 /* Fall */ 347 case WDIOC_GETTIMEOUT: 348 return put_user(wd_margin / 100, (int *)arg); 349 } 350} 351 352/** 353 * wdtpci_open: 354 * @inode: inode of device 355 * @file: file handle to device 356 * 357 * One of our two misc devices has been opened. The watchdog device is 358 * single open and on opening we load the counters. Counter zero is a 359 * 100Hz cascade, into counter 1 which downcounts to reboot. When the 360 * counter triggers counter 2 downcounts the length of the reset pulse 361 * which set set to be as long as possible. 362 */ 363 364static int wdtpci_open(struct inode *inode, struct file *file) 365{ 366 unsigned long flags; 367 368 switch(MINOR(inode->i_rdev)) 369 { 370 case WATCHDOG_MINOR: 371 if (down_trylock(&open_sem)) 372 return -EBUSY; 373 374 if (nowayout) { 375 MOD_INC_USE_COUNT; 376 } 377 /* 378 * Activate 379 */ 380 spin_lock_irqsave(&wdtpci_lock, flags); 381 382 inb_p(WDT_DC); /* Disable */ 383 384 /* 385 * "pet" the watchdog, as Access says. 386 * This resets the clock outputs. 387 */ 388 389 wdtpci_ctr_mode(2,0); 390 outb_p(0, WDT_DC); 391 392 inb_p(WDT_DC); 393 394 outb_p(0, WDT_CLOCK); /* 2.0833MHz clock */ 395 inb_p(WDT_BUZZER); /* disable */ 396 inb_p(WDT_OPTONOTRST); /* disable */ 397 inb_p(WDT_OPTORST); /* disable */ 398 inb_p(WDT_PROGOUT); /* disable */ 399 wdtpci_ctr_mode(0,3); 400 wdtpci_ctr_mode(1,2); 401 wdtpci_ctr_mode(2,1); 402 wdtpci_ctr_load(0,20833); /* count at 100Hz */ 403 wdtpci_ctr_load(1,wd_margin);/* Timeout 60 seconds */ 404 /* DO NOT LOAD CTR2 on PCI card! -- JPN */ 405 outb_p(0, WDT_DC); /* Enable */ 406 spin_unlock_irqrestore(&wdtpci_lock, flags); 407 return 0; 408 case TEMP_MINOR: 409 return 0; 410 default: 411 return -ENODEV; 412 } 413} 414 415/** 416 * wdtpci_close: 417 * @inode: inode to board 418 * @file: file handle to board 419 * 420 * The watchdog has a configurable API. There is a religious dispute 421 * between people who want their watchdog to be able to shut down and 422 * those who want to be sure if the watchdog manager dies the machine 423 * reboots. In the former case we disable the counters, in the latter 424 * case you have to open it again very soon. 425 */ 426 427static int wdtpci_release(struct inode *inode, struct file *file) 428{ 429 430 if (MINOR(inode->i_rdev)==WATCHDOG_MINOR) { 431 unsigned long flags; 432 if (expect_close) { 433 spin_lock_irqsave(&wdtpci_lock, flags); 434 inb_p(WDT_DC); /* Disable counters */ 435 wdtpci_ctr_load(2,0); /* 0 length reset pulses now */ 436 spin_unlock_irqrestore(&wdtpci_lock, flags); 437 } else { 438 printk(KERN_CRIT PFX "Unexpected close, not stopping timer!"); 439 wdtpci_ping(); 440 } 441 up(&open_sem); 442 } 443 return 0; 444} 445 446/** 447 * notify_sys: 448 * @this: our notifier block 449 * @code: the event being reported 450 * @unused: unused 451 * 452 * Our notifier is called on system shutdowns. We want to turn the card 453 * off at reboot otherwise the machine will reboot again during memory 454 * test or worse yet during the following fsck. This would suck, in fact 455 * trust me - if it happens it does suck. 456 */ 457 458static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code, 459 void *unused) 460{ 461 unsigned long flags; 462 463 if (code==SYS_DOWN || code==SYS_HALT) { 464 /* Turn the card off */ 465 spin_lock_irqsave(&wdtpci_lock, flags); 466 inb_p(WDT_DC); 467 wdtpci_ctr_load(2,0); 468 spin_unlock_irqrestore(&wdtpci_lock, flags); 469 } 470 return NOTIFY_DONE; 471} 472 473/* 474 * Kernel Interfaces 475 */ 476 477 478static struct file_operations wdtpci_fops = { 479 owner: THIS_MODULE, 480 llseek: no_llseek, 481 read: wdtpci_read, 482 write: wdtpci_write, 483 ioctl: wdtpci_ioctl, 484 open: wdtpci_open, 485 release: wdtpci_release, 486}; 487 488static struct miscdevice wdtpci_miscdev= 489{ 490 WATCHDOG_MINOR, 491 "watchdog", 492 &wdtpci_fops 493}; 494 495#ifdef CONFIG_WDT_501 496static struct miscdevice temp_miscdev= 497{ 498 TEMP_MINOR, 499 "temperature", 500 &wdtpci_fops 501}; 502#endif 503 504/* 505 * The WDT card needs to learn about soft shutdowns in order to 506 * turn the timebomb registers off. 507 */ 508 509static struct notifier_block wdtpci_notifier= 510{ 511 wdtpci_notify_sys, 512 NULL, 513 0 514}; 515 516 517static int __init wdtpci_init_one (struct pci_dev *dev, 518 const struct pci_device_id *ent) 519{ 520 static int dev_count = 0; 521 int ret = -EIO; 522 523 dev_count++; 524 if (dev_count > 1) { 525 printk (KERN_ERR PFX 526 "this driver only supports 1 device\n"); 527 return -ENODEV; 528 } 529 530 sema_init(&open_sem, 1); 531 spin_lock_init(&wdtpci_lock); 532 533 irq = dev->irq; 534 io = pci_resource_start (dev, 2); 535 printk ("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X " 536 "(Interrupt %d)\n", io, irq); 537 538 if (pci_enable_device (dev)) 539 goto out; 540 541 if (request_region (io, 16, "wdt-pci") == NULL) { 542 printk (KERN_ERR PFX "I/O %d is not free.\n", io); 543 goto out; 544 } 545 546 if (request_irq (irq, wdtpci_interrupt, SA_INTERRUPT | SA_SHIRQ, 547 "wdt-pci", &wdtpci_miscdev)) { 548 printk (KERN_ERR PFX "IRQ %d is not free.\n", irq); 549 goto out_reg; 550 } 551 552 ret = misc_register (&wdtpci_miscdev); 553 if (ret) { 554 printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR); 555 goto out_irq; 556 } 557 558 ret = register_reboot_notifier (&wdtpci_notifier); 559 if (ret) { 560 printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR); 561 goto out_misc; 562 } 563#ifdef CONFIG_WDT_501 564 ret = misc_register (&temp_miscdev); 565 if (ret) { 566 printk (KERN_ERR PFX "can't misc_register (temp) on minor=%d\n", TEMP_MINOR); 567 goto out_rbt; 568 } 569#endif 570 571 ret = 0; 572out: 573 return ret; 574 575#ifdef CONFIG_WDT_501 576out_rbt: 577 unregister_reboot_notifier(&wdtpci_notifier); 578#endif 579out_misc: 580 misc_deregister(&wdtpci_miscdev); 581out_irq: 582 free_irq(irq, &wdtpci_miscdev); 583out_reg: 584 release_region (io, 16); 585 goto out; 586} 587 588 589static void __devexit wdtpci_remove_one (struct pci_dev *pdev) 590{ 591 /* here we assume only one device will ever have 592 * been picked up and registered by probe function */ 593 unregister_reboot_notifier(&wdtpci_notifier); 594#ifdef CONFIG_WDT_501_PCI 595 misc_deregister(&temp_miscdev); 596#endif 597 misc_deregister(&wdtpci_miscdev); 598 free_irq(irq, &wdtpci_miscdev); 599 release_region(io, 16); 600} 601 602 603static struct pci_device_id wdtpci_pci_tbl[] __initdata = { 604 { PCI_VENDOR_ID_ACCESSIO, PCI_DEVICE_ID_WDG_CSM, PCI_ANY_ID, PCI_ANY_ID, }, 605 { 0, }, /* terminate list */ 606}; 607MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl); 608 609 610static struct pci_driver wdtpci_driver = { 611 name: "wdt-pci", 612 id_table: wdtpci_pci_tbl, 613 probe: wdtpci_init_one, 614 remove: __devexit_p(wdtpci_remove_one), 615}; 616 617 618/** 619 * wdtpci_cleanup: 620 * 621 * Unload the watchdog. You cannot do this with any file handles open. 622 * If your watchdog is set to continue ticking on close and you unload 623 * it, well it keeps ticking. We won't get the interrupt but the board 624 * will not touch PC memory so all is fine. You just have to load a new 625 * module in 60 seconds or reboot. 626 */ 627 628static void __exit wdtpci_cleanup(void) 629{ 630 pci_unregister_driver (&wdtpci_driver); 631} 632 633 634/** 635 * wdtpci_init: 636 * 637 * Set up the WDT watchdog board. All we have to do is grab the 638 * resources we require and bitch if anyone beat us to them. 639 * The open() function will actually kick the board off. 640 */ 641 642static int __init wdtpci_init(void) 643{ 644 int rc = pci_register_driver (&wdtpci_driver); 645 646 if (rc < 1) 647 return -ENODEV; 648 649 return 0; 650} 651 652 653module_init(wdtpci_init); 654module_exit(wdtpci_cleanup); 655 656MODULE_AUTHOR("JP Nollmann, Alan Cox"); 657MODULE_DESCRIPTION("Driver for the ICS PCI watchdog cards"); 658MODULE_LICENSE("GPL"); 659 660EXPORT_NO_SYMBOLS; 661