Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog

+172 -67
+172 -67
drivers/char/watchdog/pcwd_pci.c
··· 50 50 #include <asm/io.h> /* For inb/outb/... */ 51 51 52 52 /* Module and version information */ 53 - #define WATCHDOG_VERSION "1.01" 54 - #define WATCHDOG_DATE "02 Sep 2005" 53 + #define WATCHDOG_VERSION "1.02" 54 + #define WATCHDOG_DATE "03 Sep 2005" 55 55 #define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" 56 56 #define WATCHDOG_NAME "pcwd_pci" 57 57 #define PFX WATCHDOG_NAME ": " ··· 70 70 * These are the defines that describe the control status bits for the 71 71 * PCI-PC Watchdog card. 72 72 */ 73 - #define WD_PCI_WTRP 0x01 /* Watchdog Trip status */ 74 - #define WD_PCI_HRBT 0x02 /* Watchdog Heartbeat */ 75 - #define WD_PCI_TTRP 0x04 /* Temperature Trip status */ 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/reset */ 80 + #define WD_PCI_RLY2 0x80 /* Activate Relay 2 on the board */ 81 + /* Port 2 : Control Status #2 */ 82 + #define WD_PCI_WDIS 0x10 /* Watchdog Disable */ 83 + #define WD_PCI_ENTP 0x20 /* Enable Temperature Trip Reset */ 84 + #define WD_PCI_WRSP 0x40 /* Watchdog wrote response */ 85 + #define WD_PCI_PCMD 0x80 /* PC has sent command */ 76 86 77 87 /* according to documentation max. time to process a command for the pci 78 88 * watchdog card is 100 ms, so we give it 150 ms to do it's job */ 79 89 #define PCI_COMMAND_TIMEOUT 150 80 90 81 91 /* Watchdog's internal commands */ 82 - #define CMD_GET_STATUS 0x04 83 - #define CMD_GET_FIRMWARE_VERSION 0x08 84 - #define CMD_READ_WATCHDOG_TIMEOUT 0x18 85 - #define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 92 + #define CMD_GET_STATUS 0x04 93 + #define CMD_GET_FIRMWARE_VERSION 0x08 94 + #define CMD_READ_WATCHDOG_TIMEOUT 0x18 95 + #define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 96 + #define CMD_GET_CLEAR_RESET_COUNT 0x84 86 97 87 98 /* We can only use 1 card due to the /dev/watchdog restriction */ 88 99 static int cards_found; ··· 102 91 static int temp_panic; 103 92 static unsigned long is_active; 104 93 static char expect_release; 105 - static struct { 106 - int supports_temp; /* Wether or not the card has a temperature device */ 107 - int boot_status; /* The card's boot status */ 108 - unsigned long io_addr; /* The cards I/O address */ 109 - spinlock_t io_lock; 110 - struct pci_dev *pdev; 94 + static struct { /* this is private data for each PCI-PC watchdog card */ 95 + int supports_temp; /* Wether or not the card has a temperature device */ 96 + int boot_status; /* The card's boot status */ 97 + unsigned long io_addr; /* The cards I/O address */ 98 + spinlock_t io_lock; /* the lock for io operations */ 99 + struct pci_dev *pdev; /* the PCI-device */ 111 100 } pcipcwd_private; 112 101 113 102 /* module parameters */ 103 + #define QUIET 0 /* Default */ 104 + #define VERBOSE 1 /* Verbose */ 105 + #define DEBUG 2 /* print fancy stuff too */ 106 + static int debug = QUIET; 107 + module_param(debug, int, 0); 108 + MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"); 109 + 114 110 #define WATCHDOG_HEARTBEAT 2 /* 2 sec default heartbeat */ 115 111 static int heartbeat = WATCHDOG_HEARTBEAT; 116 112 module_param(heartbeat, int, 0); ··· 135 117 { 136 118 int got_response, count; 137 119 120 + if (debug >= DEBUG) 121 + printk(KERN_DEBUG PFX "sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x\n", 122 + cmd, *msb, *lsb); 123 + 138 124 spin_lock(&pcipcwd_private.io_lock); 139 125 /* If a command requires data it should be written first. 140 126 * Data for commands with 8 bits of data should be written to port 4. ··· 153 131 /* wait till the pci card processed the command, signaled by 154 132 * the WRSP bit in port 2 and give it a max. timeout of 155 133 * PCI_COMMAND_TIMEOUT to process */ 156 - got_response = inb_p(pcipcwd_private.io_addr + 2) & 0x40; 134 + got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP; 157 135 for (count = 0; (count < PCI_COMMAND_TIMEOUT) && (!got_response); count++) { 158 136 mdelay(1); 159 - got_response = inb_p(pcipcwd_private.io_addr + 2) & 0x40; 137 + got_response = inb_p(pcipcwd_private.io_addr + 2) & WD_PCI_WRSP; 138 + } 139 + 140 + if (debug >= DEBUG) { 141 + if (got_response) { 142 + printk(KERN_DEBUG PFX "time to process command was: %d ms\n", 143 + count); 144 + } else { 145 + printk(KERN_DEBUG PFX "card did not respond on command!\n"); 146 + } 160 147 } 161 148 162 149 if (got_response) { ··· 175 144 176 145 /* clear WRSP bit */ 177 146 inb_p(pcipcwd_private.io_addr + 6); 147 + 148 + if (debug >= DEBUG) 149 + printk(KERN_DEBUG PFX "received following data for cmd=0x%02x: msb=0x%02x lsb=0x%02x\n", 150 + cmd, *msb, *lsb); 178 151 } 152 + 179 153 spin_unlock(&pcipcwd_private.io_lock); 180 154 181 155 return got_response; 156 + } 157 + 158 + static inline void pcipcwd_check_temperature_support(void) 159 + { 160 + if (inb_p(pcipcwd_private.io_addr) != 0xF0) 161 + pcipcwd_private.supports_temp = 1; 162 + } 163 + 164 + static int pcipcwd_get_option_switches(void) 165 + { 166 + int option_switches; 167 + 168 + option_switches = inb_p(pcipcwd_private.io_addr + 3); 169 + return option_switches; 170 + } 171 + 172 + static void pcipcwd_show_card_info(void) 173 + { 174 + int got_fw_rev, fw_rev_major, fw_rev_minor; 175 + char fw_ver_str[20]; /* The cards firmware version */ 176 + int option_switches; 177 + 178 + got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); 179 + if (got_fw_rev) { 180 + sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); 181 + } else { 182 + sprintf(fw_ver_str, "<card no answer>"); 183 + } 184 + 185 + /* Get switch settings */ 186 + option_switches = pcipcwd_get_option_switches(); 187 + 188 + printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n", 189 + (int) pcipcwd_private.io_addr, fw_ver_str, 190 + (pcipcwd_private.supports_temp ? "with" : "without")); 191 + 192 + printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", 193 + option_switches, 194 + ((option_switches & 0x10) ? "ON" : "OFF"), 195 + ((option_switches & 0x08) ? "ON" : "OFF")); 196 + 197 + if (pcipcwd_private.boot_status & WDIOF_CARDRESET) 198 + printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n"); 199 + 200 + if (pcipcwd_private.boot_status & WDIOF_OVERHEAT) 201 + printk(KERN_INFO PFX "Card sensed a CPU Overheat\n"); 202 + 203 + if (pcipcwd_private.boot_status == 0) 204 + printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); 182 205 } 183 206 184 207 static int pcipcwd_start(void) ··· 246 161 stat_reg = inb_p(pcipcwd_private.io_addr + 2); 247 162 spin_unlock(&pcipcwd_private.io_lock); 248 163 249 - if (stat_reg & 0x10) { 164 + if (stat_reg & WD_PCI_WDIS) { 250 165 printk(KERN_ERR PFX "Card timer not enabled\n"); 251 166 return -1; 252 167 } 168 + 169 + if (debug >= VERBOSE) 170 + printk(KERN_DEBUG PFX "Watchdog started\n"); 253 171 254 172 return 0; 255 173 } ··· 271 183 stat_reg = inb_p(pcipcwd_private.io_addr + 2); 272 184 spin_unlock(&pcipcwd_private.io_lock); 273 185 274 - if (!(stat_reg & 0x10)) { 186 + if (!(stat_reg & WD_PCI_WDIS)) { 275 187 printk(KERN_ERR PFX "Card did not acknowledge disable attempt\n"); 276 188 return -1; 277 189 } 190 + 191 + if (debug >= VERBOSE) 192 + printk(KERN_DEBUG PFX "Watchdog stopped\n"); 278 193 279 194 return 0; 280 195 } ··· 285 194 static int pcipcwd_keepalive(void) 286 195 { 287 196 /* Re-trigger watchdog by writing to port 0 */ 288 - outb_p(0x42, pcipcwd_private.io_addr); 197 + outb_p(0x42, pcipcwd_private.io_addr); /* send out any data */ 198 + 199 + if (debug >= DEBUG) 200 + printk(KERN_DEBUG PFX "Watchdog keepalive signal send\n"); 201 + 289 202 return 0; 290 203 } 291 204 ··· 305 210 send_command(CMD_WRITE_WATCHDOG_TIMEOUT, &t_msb, &t_lsb); 306 211 307 212 heartbeat = t; 213 + if (debug >= VERBOSE) 214 + printk(KERN_DEBUG PFX "New heartbeat: %d\n", 215 + heartbeat); 216 + 308 217 return 0; 309 218 } 310 219 311 220 static int pcipcwd_get_status(int *status) 312 221 { 313 - int new_status; 222 + int control_status; 314 223 315 224 *status=0; 316 - new_status = inb_p(pcipcwd_private.io_addr + 1); 317 - if (new_status & WD_PCI_WTRP) 225 + control_status = inb_p(pcipcwd_private.io_addr + 1); 226 + if (control_status & WD_PCI_WTRP) 318 227 *status |= WDIOF_CARDRESET; 319 - if (new_status & WD_PCI_TTRP) { 228 + if (control_status & WD_PCI_TTRP) { 320 229 *status |= WDIOF_OVERHEAT; 321 230 if (temp_panic) 322 231 panic(PFX "Temperature overheat trip!\n"); 323 232 } 233 + 234 + if (debug >= DEBUG) 235 + printk(KERN_DEBUG PFX "Control Status #1: 0x%02x\n", 236 + control_status); 324 237 325 238 return 0; 326 239 } 327 240 328 241 static int pcipcwd_clear_status(void) 329 242 { 330 - outb_p(0x01, pcipcwd_private.io_addr + 1); 243 + int control_status; 244 + int msb; 245 + int reset_counter; 246 + 247 + if (debug >= VERBOSE) 248 + printk(KERN_INFO PFX "clearing watchdog trip status & LED\n"); 249 + 250 + control_status = inb_p(pcipcwd_private.io_addr + 1); 251 + 252 + if (debug >= DEBUG) { 253 + printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status); 254 + printk(KERN_DEBUG PFX "sending: 0x%02x\n", 255 + (control_status & WD_PCI_R2DS) | WD_PCI_WTRP); 256 + } 257 + 258 + /* clear trip status & LED and keep mode of relay 2 */ 259 + outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1); 260 + 261 + /* clear reset counter */ 262 + msb=0; 263 + reset_counter=0xff; 264 + send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter); 265 + 266 + if (debug >= DEBUG) { 267 + printk(KERN_DEBUG PFX "reset count was: 0x%02x\n", 268 + reset_counter); 269 + } 270 + 331 271 return 0; 332 272 } 333 273 ··· 372 242 if (!pcipcwd_private.supports_temp) 373 243 return -ENODEV; 374 244 245 + *temperature = inb_p(pcipcwd_private.io_addr); 246 + 375 247 /* 376 248 * Convert celsius to fahrenheit, since this was 377 249 * the decided 'standard' for this return value. 378 250 */ 379 - *temperature = ((inb_p(pcipcwd_private.io_addr)) * 9 / 5) + 32; 251 + *temperature = (*temperature * 9 / 5) + 32; 252 + 253 + if (debug >= DEBUG) { 254 + printk(KERN_DEBUG PFX "temperature is: %d F\n", 255 + *temperature); 256 + } 380 257 381 258 return 0; 382 259 } ··· 393 256 */ 394 257 395 258 static ssize_t pcipcwd_write(struct file *file, const char __user *data, 396 - size_t len, loff_t *ppos) 259 + size_t len, loff_t *ppos) 397 260 { 398 261 /* See if we got the magic character 'V' and reload the timer */ 399 262 if (len) { ··· 518 381 static int pcipcwd_open(struct inode *inode, struct file *file) 519 382 { 520 383 /* /dev/watchdog can only be opened once */ 521 - if (test_and_set_bit(0, &is_active)) 384 + if (test_and_set_bit(0, &is_active)) { 385 + if (debug >= VERBOSE) 386 + printk(KERN_ERR PFX "Attempt to open already opened device.\n"); 522 387 return -EBUSY; 388 + } 523 389 524 390 /* Activate */ 525 391 pcipcwd_start(); ··· 632 492 * Init & exit routines 633 493 */ 634 494 635 - static inline void check_temperature_support(void) 636 - { 637 - if (inb_p(pcipcwd_private.io_addr) != 0xF0) 638 - pcipcwd_private.supports_temp = 1; 639 - } 640 - 641 495 static int __devinit pcipcwd_card_init(struct pci_dev *pdev, 642 496 const struct pci_device_id *ent) 643 497 { 644 498 int ret = -EIO; 645 - int got_fw_rev, fw_rev_major, fw_rev_minor; 646 - char fw_ver_str[20]; 647 - char option_switches; 648 499 649 500 cards_found++; 650 501 if (cards_found == 1) ··· 677 546 pcipcwd_stop(); 678 547 679 548 /* Check whether or not the card supports the temperature device */ 680 - check_temperature_support(); 549 + pcipcwd_check_temperature_support(); 681 550 682 - /* Get the Firmware Version */ 683 - got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); 684 - if (got_fw_rev) { 685 - sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); 686 - } else { 687 - sprintf(fw_ver_str, "<card no answer>"); 688 - } 689 - 690 - /* Get switch settings */ 691 - option_switches = inb_p(pcipcwd_private.io_addr + 3); 692 - 693 - printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n", 694 - (int) pcipcwd_private.io_addr, fw_ver_str, 695 - (pcipcwd_private.supports_temp ? "with" : "without")); 696 - 697 - printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", 698 - option_switches, 699 - ((option_switches & 0x10) ? "ON" : "OFF"), 700 - ((option_switches & 0x08) ? "ON" : "OFF")); 701 - 702 - if (pcipcwd_private.boot_status & WDIOF_CARDRESET) 703 - printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n"); 704 - 705 - if (pcipcwd_private.boot_status & WDIOF_OVERHEAT) 706 - printk(KERN_INFO PFX "Card sensed a CPU Overheat\n"); 707 - 708 - if (pcipcwd_private.boot_status == 0) 709 - printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); 551 + /* Show info about the card itself */ 552 + pcipcwd_show_card_info(); 710 553 711 554 /* Check that the heartbeat value is within it's range ; if not reset to the default */ 712 555 if (pcipcwd_set_heartbeat(heartbeat)) { ··· 761 656 762 657 static int __init pcipcwd_init_module(void) 763 658 { 764 - spin_lock_init (&pcipcwd_private.io_lock); 659 + spin_lock_init(&pcipcwd_private.io_lock); 765 660 766 661 return pci_register_driver(&pcipcwd_driver); 767 662 }