1 /* 2 * Berkshire PCI-PC Watchdog Card Driver 3 * 4 * (c) Copyright 2003-2007 Wim Van Sebroeck <wim@iguana.be>. 5 * 6 * Based on source code of the following authors: 7 * Ken Hollis <kenji@bitgate.com>, 8 * Lindsay Harris <lindsay@bluegum.com>, 9 * Alan Cox <alan@lxorguk.ukuu.org.uk>, 10 * Matt Domsch <Matt_Domsch@dell.com>, 11 * Rob Radez <rob@osinvestor.com> 12 * 13 * This program is free software; you can redistribute it and/or 14 * modify it under the terms of the GNU General Public License 15 * as published by the Free Software Foundation; either version 16 * 2 of the License, or (at your option) any later version. 17 * 18 * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor 19 * provide warranty for any of this software. This material is 20 * provided "AS-IS" and at no charge. 21 */ 22 23 /* 24 * A bells and whistles driver is available from: 25 * http://www.kernel.org/pub/linux/kernel/people/wim/pcwd/pcwd_pci/ 26 * 27 * More info available at 28 * http://www.berkprod.com/ or http://www.pcwatchdog.com/ 29 */ 30 31 /* 32 * Includes, defines, variables, module parameters, ... 33 */ 34 35 #include <linux/module.h> /* For module specific items */ 36 #include <linux/moduleparam.h> /* For new moduleparam's */ 37 #include <linux/types.h> /* For standard types (like size_t) */ 38 #include <linux/errno.h> /* For the -ENODEV/... values */ 39 #include <linux/kernel.h> /* For printk/panic/... */ 40 #include <linux/delay.h> /* For mdelay function */ 41 #include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */ 42 #include <linux/watchdog.h> /* For the watchdog specific items */ 43 #include <linux/notifier.h> /* For notifier support */ 44 #include <linux/reboot.h> /* For reboot_notifier stuff */ 45 #include <linux/init.h> /* For __init/__exit/... */ 46 #include <linux/fs.h> /* For file operations */ 47 #include <linux/pci.h> /* For pci functions */ 48 #include <linux/ioport.h> /* For io-port access */ 49 #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ 50 #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ 51 #include <linux/io.h> /* For inb/outb/... */ 52 53 /* Module and version information */ 54 #define WATCHDOG_VERSION "1.03" 55 #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" 56 #define WATCHDOG_NAME "pcwd_pci" 57 #define PFX WATCHDOG_NAME ": " 58 #define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION "\n" 59 60 /* Stuff for the PCI ID's */ 61 #ifndef PCI_VENDOR_ID_QUICKLOGIC 62 #define PCI_VENDOR_ID_QUICKLOGIC 0x11e3 63 #endif 64 65 #ifndef PCI_DEVICE_ID_WATCHDOG_PCIPCWD 66 #define PCI_DEVICE_ID_WATCHDOG_PCIPCWD 0x5030 67 #endif 68 69 /* 70 * These are the defines that describe the control status bits for the 71 * PCI-PC Watchdog card. 72 */ 73 /* Port 1 : Control Status #1 */ 74 #define WD_PCI_WTRP 0x01 /* Watchdog Trip status */ 75 #define WD_PCI_HRBT 0x02 /* Watchdog Heartbeat */ 76 #define WD_PCI_TTRP 0x04 /* Temperature Trip status */ 77 #define WD_PCI_RL2A 0x08 /* Relay 2 Active */ 78 #define WD_PCI_RL1A 0x10 /* Relay 1 Active */ 79 #define WD_PCI_R2DS 0x40 /* Relay 2 Disable Temperature-trip / 80 reset */ 81 #define WD_PCI_RLY2 0x80 /* Activate Relay 2 on the board */ 82 /* Port 2 : Control Status #2 */ 83 #define WD_PCI_WDIS 0x10 /* Watchdog Disable */ 84 #define WD_PCI_ENTP 0x20 /* Enable Temperature Trip Reset */ 85 #define WD_PCI_WRSP 0x40 /* Watchdog wrote response */ 86 #define WD_PCI_PCMD 0x80 /* PC has sent command */ 87 88 /* according to documentation max. time to process a command for the pci 89 * watchdog card is 100 ms, so we give it 150 ms to do it's job */ 90 #define PCI_COMMAND_TIMEOUT 150 91 92 /* Watchdog's internal commands */ 93 #define CMD_GET_STATUS 0x04 94 #define CMD_GET_FIRMWARE_VERSION 0x08 95 #define CMD_READ_WATCHDOG_TIMEOUT 0x18 96 #define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 97 #define CMD_GET_CLEAR_RESET_COUNT 0x84 98 99 /* Watchdog's Dip Switch heartbeat values */ 100 static const int heartbeat_tbl[] = { 101 5, /* OFF-OFF-OFF = 5 Sec */ 102 10, /* OFF-OFF-ON = 10 Sec */ 103 30, /* OFF-ON-OFF = 30 Sec */ 104 60, /* OFF-ON-ON = 1 Min */ 105 300, /* ON-OFF-OFF = 5 Min */ 106 600, /* ON-OFF-ON = 10 Min */ 107 1800, /* ON-ON-OFF = 30 Min */ 108 3600, /* ON-ON-ON = 1 hour */ 109 }; 110 111 /* We can only use 1 card due to the /dev/watchdog restriction */ 112 static int cards_found; 113 114 /* internal variables */ 115 static int temp_panic; 116 static unsigned long is_active; 117 static char expect_release; 118 /* this is private data for each PCI-PC watchdog card */ 119 static struct { 120 /* Wether or not the card has a temperature device */ 121 int supports_temp; 122 /* The card's boot status */ 123 int boot_status; 124 /* The cards I/O address */ 125 unsigned long io_addr; 126 /* the lock for io operations */ 127 spinlock_t io_lock; 128 /* the PCI-device */ 129 struct pci_dev *pdev; 130 } pcipcwd_private; 131 132 /* module parameters */ 133 #define QUIET 0 /* Default */ 134 #define VERBOSE 1 /* Verbose */ 135 #define DEBUG 2 /* print fancy stuff too */ 136 static int debug = QUIET; 137 module_param(debug, int, 0); 138 MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"); 139 140 #define WATCHDOG_HEARTBEAT 0 /* default heartbeat = 141 delay-time from dip-switches */ 142 static int heartbeat = WATCHDOG_HEARTBEAT; 143 module_param(heartbeat, int, 0); 144 MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. " 145 "(0<heartbeat<65536 or 0=delay-time from dip-switches, default=" 146 __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 147 148 static int nowayout = WATCHDOG_NOWAYOUT; 149 module_param(nowayout, int, 0); 150 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 151 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 152 153 /* 154 * Internal functions 155 */ 156 157 static int send_command(int cmd, int *msb, int *lsb) 158 { 159 int got_response, count; 160 161 if (debug >= DEBUG) 162 printk(KERN_DEBUG PFX "sending following data " 163 "cmd=0x%02x msb=0x%02x lsb=0x%02x\n", cmd, *msb, *lsb); 164 165 spin_lock(&pcipcwd_private.io_lock); 166 /* If a command requires data it should be written first. 167 * Data for commands with 8 bits of data should be written to port 4. 168 * Commands with 16 bits of data, should be written as LSB to port 4 169 * and MSB to port 5. 170 * After the required data has been written then write the command to 171 * port 6. */ 172 outb_p(*lsb, pcipcwd_private.io_addr + 4); 173 outb_p(*msb, pcipcwd_private.io_addr + 5); 174 outb_p(cmd, pcipcwd_private.io_addr + 6); 175 176 /* wait till the pci card processed the command, signaled by 177 * the WRSP bit in port 2 and give it a max. timeout of 178 * PCI_COMMAND_TIMEOUT to process */ 179 got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP; 180 for (count = 0; (count < PCI_COMMAND_TIMEOUT) && (!got_response); 181 count++) { 182 mdelay(1); 183 got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP; 184 } 185 186 if (debug >= DEBUG) { 187 if (got_response) { 188 printk(KERN_DEBUG PFX 189 "time to process command was: %d ms\n", 190 count); 191 } else { 192 printk(KERN_DEBUG PFX 193 "card did not respond on command!\n"); 194 } 195 } 196 197 if (got_response) { 198 /* read back response */ 199 *lsb = inb_p(pcipcwd_private.io_addr + 4); 200 *msb = inb_p(pcipcwd_private.io_addr + 5); 201 202 /* clear WRSP bit */ 203 inb_p(pcipcwd_private.io_addr + 6); 204 205 if (debug >= DEBUG) 206 printk(KERN_DEBUG PFX "received following data for " 207 "cmd=0x%02x: msb=0x%02x lsb=0x%02x\n", 208 cmd, *msb, *lsb); 209 } 210 211 spin_unlock(&pcipcwd_private.io_lock); 212 213 return got_response; 214 } 215 216 static inline void pcipcwd_check_temperature_support(void) 217 { 218 if (inb_p(pcipcwd_private.io_addr) != 0xF0) 219 pcipcwd_private.supports_temp = 1; 220 } 221 222 static int pcipcwd_get_option_switches(void) 223 { 224 int option_switches; 225 226 option_switches = inb_p(pcipcwd_private.io_addr + 3); 227 return option_switches; 228 } 229 230 static void pcipcwd_show_card_info(void) 231 { 232 int got_fw_rev, fw_rev_major, fw_rev_minor; 233 char fw_ver_str[20]; /* The cards firmware version */ 234 int option_switches; 235 236 got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, 237 &fw_rev_minor); 238 if (got_fw_rev) 239 sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); 240 else 241 sprintf(fw_ver_str, "<card no answer>"); 242 243 /* Get switch settings */ 244 option_switches = pcipcwd_get_option_switches(); 245 246 printk(KERN_INFO PFX "Found card at port " 247 "0x%04x (Firmware: %s) %s temp option\n", 248 (int) pcipcwd_private.io_addr, fw_ver_str, 249 (pcipcwd_private.supports_temp ? "with" : "without")); 250 251 printk(KERN_INFO PFX "Option switches (0x%02x): " 252 "Temperature Reset Enable=%s, Power On Delay=%s\n", 253 option_switches, 254 ((option_switches & 0x10) ? "ON" : "OFF"), 255 ((option_switches & 0x08) ? "ON" : "OFF")); 256 257 if (pcipcwd_private.boot_status & WDIOF_CARDRESET) 258 printk(KERN_INFO PFX 259 "Previous reset was caused by the Watchdog card\n"); 260 261 if (pcipcwd_private.boot_status & WDIOF_OVERHEAT) 262 printk(KERN_INFO PFX "Card sensed a CPU Overheat\n"); 263 264 if (pcipcwd_private.boot_status == 0) 265 printk(KERN_INFO PFX 266 "No previous trip detected - Cold boot or reset\n"); 267 } 268 269 static int pcipcwd_start(void) 270 { 271 int stat_reg; 272 273 spin_lock(&pcipcwd_private.io_lock); 274 outb_p(0x00, pcipcwd_private.io_addr + 3); 275 udelay(1000); 276 277 stat_reg = inb_p(pcipcwd_private.io_addr + 2); 278 spin_unlock(&pcipcwd_private.io_lock); 279 280 if (stat_reg & WD_PCI_WDIS) { 281 printk(KERN_ERR PFX "Card timer not enabled\n"); 282 return -1; 283 } 284 285 if (debug >= VERBOSE) 286 printk(KERN_DEBUG PFX "Watchdog started\n"); 287 288 return 0; 289 } 290 291 static int pcipcwd_stop(void) 292 { 293 int stat_reg; 294 295 spin_lock(&pcipcwd_private.io_lock); 296 outb_p(0xA5, pcipcwd_private.io_addr + 3); 297 udelay(1000); 298 299 outb_p(0xA5, pcipcwd_private.io_addr + 3); 300 udelay(1000); 301 302 stat_reg = inb_p(pcipcwd_private.io_addr + 2); 303 spin_unlock(&pcipcwd_private.io_lock); 304 305 if (!(stat_reg & WD_PCI_WDIS)) { 306 printk(KERN_ERR PFX 307 "Card did not acknowledge disable attempt\n"); 308 return -1; 309 } 310 311 if (debug >= VERBOSE) 312 printk(KERN_DEBUG PFX "Watchdog stopped\n"); 313 314 return 0; 315 } 316 317 static int pcipcwd_keepalive(void) 318 { 319 /* Re-trigger watchdog by writing to port 0 */ 320 spin_lock(&pcipcwd_private.io_lock); 321 outb_p(0x42, pcipcwd_private.io_addr); /* send out any data */ 322 spin_unlock(&pcipcwd_private.io_lock); 323 324 if (debug >= DEBUG) 325 printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n"); 326 327 return 0; 328 } 329 330 static int pcipcwd_set_heartbeat(int t) 331 { 332 int t_msb = t / 256; 333 int t_lsb = t % 256; 334 335 if ((t < 0x0001) || (t > 0xFFFF)) 336 return -EINVAL; 337 338 /* Write new heartbeat to watchdog */ 339 send_command(CMD_WRITE_WATCHDOG_TIMEOUT, &t_msb, &t_lsb); 340 341 heartbeat = t; 342 if (debug >= VERBOSE) 343 printk(KERN_DEBUG PFX "New heartbeat: %d\n", 344 heartbeat); 345 346 return 0; 347 } 348 349 static int pcipcwd_get_status(int *status) 350 { 351 int control_status; 352 353 *status = 0; 354 control_status = inb_p(pcipcwd_private.io_addr + 1); 355 if (control_status & WD_PCI_WTRP) 356 *status |= WDIOF_CARDRESET; 357 if (control_status & WD_PCI_TTRP) { 358 *status |= WDIOF_OVERHEAT; 359 if (temp_panic) 360 panic(PFX "Temperature overheat trip!\n"); 361 } 362 363 if (debug >= DEBUG) 364 printk(KERN_DEBUG PFX "Control Status #1: 0x%02x\n", 365 control_status); 366 367 return 0; 368 } 369 370 static int pcipcwd_clear_status(void) 371 { 372 int control_status; 373 int msb; 374 int reset_counter; 375 376 if (debug >= VERBOSE) 377 printk(KERN_INFO PFX "clearing watchdog trip status & LED\n"); 378 379 control_status = inb_p(pcipcwd_private.io_addr + 1); 380 381 if (debug >= DEBUG) { 382 printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status); 383 printk(KERN_DEBUG PFX "sending: 0x%02x\n", 384 (control_status & WD_PCI_R2DS) | WD_PCI_WTRP); 385 } 386 387 /* clear trip status & LED and keep mode of relay 2 */ 388 outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, 389 pcipcwd_private.io_addr + 1); 390 391 /* clear reset counter */ 392 msb = 0; 393 reset_counter = 0xff; 394 send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter); 395 396 if (debug >= DEBUG) { 397 printk(KERN_DEBUG PFX "reset count was: 0x%02x\n", 398 reset_counter); 399 } 400 401 return 0; 402 } 403 404 static int pcipcwd_get_temperature(int *temperature) 405 { 406 *temperature = 0; 407 if (!pcipcwd_private.supports_temp) 408 return -ENODEV; 409 410 spin_lock(&pcipcwd_private.io_lock); 411 *temperature = inb_p(pcipcwd_private.io_addr); 412 spin_unlock(&pcipcwd_private.io_lock); 413 414 /* 415 * Convert celsius to fahrenheit, since this was 416 * the decided 'standard' for this return value. 417 */ 418 *temperature = (*temperature * 9 / 5) + 32; 419 420 if (debug >= DEBUG) { 421 printk(KERN_DEBUG PFX "temperature is: %d F\n", 422 *temperature); 423 } 424 425 return 0; 426 } 427 428 static int pcipcwd_get_timeleft(int *time_left) 429 { 430 int msb; 431 int lsb; 432 433 /* Read the time that's left before rebooting */ 434 /* Note: if the board is not yet armed then we will read 0xFFFF */ 435 send_command(CMD_READ_WATCHDOG_TIMEOUT, &msb, &lsb); 436 437 *time_left = (msb << 8) + lsb; 438 439 if (debug >= VERBOSE) 440 printk(KERN_DEBUG PFX "Time left before next reboot: %d\n", 441 *time_left); 442 443 return 0; 444 } 445 446 /* 447 * /dev/watchdog handling 448 */ 449 450 static ssize_t pcipcwd_write(struct file *file, const char __user *data, 451 size_t len, loff_t *ppos) 452 { 453 /* See if we got the magic character 'V' and reload the timer */ 454 if (len) { 455 if (!nowayout) { 456 size_t i; 457 458 /* note: just in case someone wrote the magic character 459 * five months ago... */ 460 expect_release = 0; 461 462 /* scan to see whether or not we got the 463 * magic character */ 464 for (i = 0; i != len; i++) { 465 char c; 466 if (get_user(c, data + i)) 467 return -EFAULT; 468 if (c == 'V') 469 expect_release = 42; 470 } 471 } 472 473 /* someone wrote to us, we should reload the timer */ 474 pcipcwd_keepalive(); 475 } 476 return len; 477 } 478 479 static long pcipcwd_ioctl(struct file *file, unsigned int cmd, 480 unsigned long arg) 481 { 482 void __user *argp = (void __user *)arg; 483 int __user *p = argp; 484 static const struct watchdog_info ident = { 485 .options = WDIOF_OVERHEAT | 486 WDIOF_CARDRESET | 487 WDIOF_KEEPALIVEPING | 488 WDIOF_SETTIMEOUT | 489 WDIOF_MAGICCLOSE, 490 .firmware_version = 1, 491 .identity = WATCHDOG_DRIVER_NAME, 492 }; 493 494 switch (cmd) { 495 case WDIOC_GETSUPPORT: 496 return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; 497 498 case WDIOC_GETSTATUS: 499 { 500 int status; 501 pcipcwd_get_status(&status); 502 return put_user(status, p); 503 } 504 505 case WDIOC_GETBOOTSTATUS: 506 return put_user(pcipcwd_private.boot_status, p); 507 508 case WDIOC_GETTEMP: 509 { 510 int temperature; 511 512 if (pcipcwd_get_temperature(&temperature)) 513 return -EFAULT; 514 515 return put_user(temperature, p); 516 } 517 518 case WDIOC_SETOPTIONS: 519 { 520 int new_options, retval = -EINVAL; 521 522 if (get_user(new_options, p)) 523 return -EFAULT; 524 525 if (new_options & WDIOS_DISABLECARD) { 526 if (pcipcwd_stop()) 527 return -EIO; 528 retval = 0; 529 } 530 531 if (new_options & WDIOS_ENABLECARD) { 532 if (pcipcwd_start()) 533 return -EIO; 534 retval = 0; 535 } 536 537 if (new_options & WDIOS_TEMPPANIC) { 538 temp_panic = 1; 539 retval = 0; 540 } 541 542 return retval; 543 } 544 545 case WDIOC_KEEPALIVE: 546 pcipcwd_keepalive(); 547 return 0; 548 549 case WDIOC_SETTIMEOUT: 550 { 551 int new_heartbeat; 552 553 if (get_user(new_heartbeat, p)) 554 return -EFAULT; 555 556 if (pcipcwd_set_heartbeat(new_heartbeat)) 557 return -EINVAL; 558 559 pcipcwd_keepalive(); 560 /* Fall */ 561 } 562 563 case WDIOC_GETTIMEOUT: 564 return put_user(heartbeat, p); 565 566 case WDIOC_GETTIMELEFT: 567 { 568 int time_left; 569 570 if (pcipcwd_get_timeleft(&time_left)) 571 return -EFAULT; 572 573 return put_user(time_left, p); 574 } 575 576 default: 577 return -ENOTTY; 578 } 579 } 580 581 static int pcipcwd_open(struct inode *inode, struct file *file) 582 { 583 /* /dev/watchdog can only be opened once */ 584 if (test_and_set_bit(0, &is_active)) { 585 if (debug >= VERBOSE) 586 printk(KERN_ERR PFX 587 "Attempt to open already opened device.\n"); 588 return -EBUSY; 589 } 590 591 /* Activate */ 592 pcipcwd_start(); 593 pcipcwd_keepalive(); 594 return nonseekable_open(inode, file); 595 } 596 597 static int pcipcwd_release(struct inode *inode, struct file *file) 598 { 599 /* 600 * Shut off the timer. 601 */ 602 if (expect_release == 42) { 603 pcipcwd_stop(); 604 } else { 605 printk(KERN_CRIT PFX 606 "Unexpected close, not stopping watchdog!\n"); 607 pcipcwd_keepalive(); 608 } 609 expect_release = 0; 610 clear_bit(0, &is_active); 611 return 0; 612 } 613 614 /* 615 * /dev/temperature handling 616 */ 617 618 static ssize_t pcipcwd_temp_read(struct file *file, char __user *data, 619 size_t len, loff_t *ppos) 620 { 621 int temperature; 622 623 if (pcipcwd_get_temperature(&temperature)) 624 return -EFAULT; 625 626 if (copy_to_user(data, &temperature, 1)) 627 return -EFAULT; 628 629 return 1; 630 } 631 632 static int pcipcwd_temp_open(struct inode *inode, struct file *file) 633 { 634 if (!pcipcwd_private.supports_temp) 635 return -ENODEV; 636 637 return nonseekable_open(inode, file); 638 } 639 640 static int pcipcwd_temp_release(struct inode *inode, struct file *file) 641 { 642 return 0; 643 } 644 645 /* 646 * Notify system 647 */ 648 649 static int pcipcwd_notify_sys(struct notifier_block *this, unsigned long code, 650 void *unused) 651 { 652 if (code == SYS_DOWN || code == SYS_HALT) 653 pcipcwd_stop(); /* Turn the WDT off */ 654 655 return NOTIFY_DONE; 656 } 657 658 /* 659 * Kernel Interfaces 660 */ 661 662 static const struct file_operations pcipcwd_fops = { 663 .owner = THIS_MODULE, 664 .llseek = no_llseek, 665 .write = pcipcwd_write, 666 .unlocked_ioctl = pcipcwd_ioctl, 667 .open = pcipcwd_open, 668 .release = pcipcwd_release, 669 }; 670 671 static struct miscdevice pcipcwd_miscdev = { 672 .minor = WATCHDOG_MINOR, 673 .name = "watchdog", 674 .fops = &pcipcwd_fops, 675 }; 676 677 static const struct file_operations pcipcwd_temp_fops = { 678 .owner = THIS_MODULE, 679 .llseek = no_llseek, 680 .read = pcipcwd_temp_read, 681 .open = pcipcwd_temp_open, 682 .release = pcipcwd_temp_release, 683 }; 684 685 static struct miscdevice pcipcwd_temp_miscdev = { 686 .minor = TEMP_MINOR, 687 .name = "temperature", 688 .fops = &pcipcwd_temp_fops, 689 }; 690 691 static struct notifier_block pcipcwd_notifier = { 692 .notifier_call = pcipcwd_notify_sys, 693 }; 694 695 /* 696 * Init & exit routines 697 */ 698 699 static int __devinit pcipcwd_card_init(struct pci_dev *pdev, 700 const struct pci_device_id *ent) 701 { 702 int ret = -EIO; 703 704 cards_found++; 705 if (cards_found == 1) 706 printk(KERN_INFO PFX DRIVER_VERSION); 707 708 if (cards_found > 1) { 709 printk(KERN_ERR PFX "This driver only supports 1 device\n"); 710 return -ENODEV; 711 } 712 713 if (pci_enable_device(pdev)) { 714 printk(KERN_ERR PFX "Not possible to enable PCI Device\n"); 715 return -ENODEV; 716 } 717 718 if (pci_resource_start(pdev, 0) == 0x0000) { 719 printk(KERN_ERR PFX "No I/O-Address for card detected\n"); 720 ret = -ENODEV; 721 goto err_out_disable_device; 722 } 723 724 pcipcwd_private.pdev = pdev; 725 pcipcwd_private.io_addr = pci_resource_start(pdev, 0); 726 727 if (pci_request_regions(pdev, WATCHDOG_NAME)) { 728 printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", 729 (int) pcipcwd_private.io_addr); 730 ret = -EIO; 731 goto err_out_disable_device; 732 } 733 734 /* get the boot_status */ 735 pcipcwd_get_status(&pcipcwd_private.boot_status); 736 737 /* clear the "card caused reboot" flag */ 738 pcipcwd_clear_status(); 739 740 /* disable card */ 741 pcipcwd_stop(); 742 743 /* Check whether or not the card supports the temperature device */ 744 pcipcwd_check_temperature_support(); 745 746 /* Show info about the card itself */ 747 pcipcwd_show_card_info(); 748 749 /* If heartbeat = 0 then we use the heartbeat from the dip-switches */ 750 if (heartbeat == 0) 751 heartbeat = 752 heartbeat_tbl[(pcipcwd_get_option_switches() & 0x07)]; 753 754 /* Check that the heartbeat value is within it's range ; 755 * if not reset to the default */ 756 if (pcipcwd_set_heartbeat(heartbeat)) { 757 pcipcwd_set_heartbeat(WATCHDOG_HEARTBEAT); 758 printk(KERN_INFO PFX 759 "heartbeat value must be 0<heartbeat<65536, using %d\n", 760 WATCHDOG_HEARTBEAT); 761 } 762 763 ret = register_reboot_notifier(&pcipcwd_notifier); 764 if (ret != 0) { 765 printk(KERN_ERR PFX 766 "cannot register reboot notifier (err=%d)\n", ret); 767 goto err_out_release_region; 768 } 769 770 if (pcipcwd_private.supports_temp) { 771 ret = misc_register(&pcipcwd_temp_miscdev); 772 if (ret != 0) { 773 printk(KERN_ERR PFX "cannot register miscdev on " 774 "minor=%d (err=%d)\n", TEMP_MINOR, ret); 775 goto err_out_unregister_reboot; 776 } 777 } 778 779 ret = misc_register(&pcipcwd_miscdev); 780 if (ret != 0) { 781 printk(KERN_ERR PFX 782 "cannot register miscdev on minor=%d (err=%d)\n", 783 WATCHDOG_MINOR, ret); 784 goto err_out_misc_deregister; 785 } 786 787 printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", 788 heartbeat, nowayout); 789 790 return 0; 791 792 err_out_misc_deregister: 793 if (pcipcwd_private.supports_temp) 794 misc_deregister(&pcipcwd_temp_miscdev); 795 err_out_unregister_reboot: 796 unregister_reboot_notifier(&pcipcwd_notifier); 797 err_out_release_region: 798 pci_release_regions(pdev); 799 err_out_disable_device: 800 pci_disable_device(pdev); 801 return ret; 802 } 803 804 static void __devexit pcipcwd_card_exit(struct pci_dev *pdev) 805 { 806 /* Stop the timer before we leave */ 807 if (!nowayout) 808 pcipcwd_stop(); 809 810 /* Deregister */ 811 misc_deregister(&pcipcwd_miscdev); 812 if (pcipcwd_private.supports_temp) 813 misc_deregister(&pcipcwd_temp_miscdev); 814 unregister_reboot_notifier(&pcipcwd_notifier); 815 pci_release_regions(pdev); 816 pci_disable_device(pdev); 817 cards_found--; 818 } 819 820 static struct pci_device_id pcipcwd_pci_tbl[] = { 821 { PCI_VENDOR_ID_QUICKLOGIC, PCI_DEVICE_ID_WATCHDOG_PCIPCWD, 822 PCI_ANY_ID, PCI_ANY_ID, }, 823 { 0 }, /* End of list */ 824 }; 825 MODULE_DEVICE_TABLE(pci, pcipcwd_pci_tbl); 826 827 static struct pci_driver pcipcwd_driver = { 828 .name = WATCHDOG_NAME, 829 .id_table = pcipcwd_pci_tbl, 830 .probe = pcipcwd_card_init, 831 .remove = __devexit_p(pcipcwd_card_exit), 832 }; 833 834 static int __init pcipcwd_init_module(void) 835 { 836 spin_lock_init(&pcipcwd_private.io_lock); 837 838 return pci_register_driver(&pcipcwd_driver); 839 } 840 841 static void __exit pcipcwd_cleanup_module(void) 842 { 843 pci_unregister_driver(&pcipcwd_driver); 844 845 printk(KERN_INFO PFX "Watchdog Module Unloaded.\n"); 846 } 847 848 module_init(pcipcwd_init_module); 849 module_exit(pcipcwd_cleanup_module); 850 851 MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>"); 852 MODULE_DESCRIPTION("Berkshire PCI-PC Watchdog driver"); 853 MODULE_LICENSE("GPL"); 854 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 855 MODULE_ALIAS_MISCDEV(TEMP_MINOR); 856