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
78 static struct semaphore open_sem;
79 static spinlock_t wdtpci_lock;
80 static int expect_close = 0;
81
82 static int io;
83 static 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
89 static int wd_margin = WD_TIMO;
90
91 #ifdef CONFIG_WATCHDOG_NOWAYOUT
92 static int nowayout = 1;
93 #else
94 static int nowayout = 0;
95 #endif
96
97 MODULE_PARM(nowayout,"i");
98 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
99
100 /*
101 * Programming support
102 */
103
wdtpci_ctr_mode(int ctr,int mode)104 static 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
wdtpci_ctr_load(int ctr,int val)112 static 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
wdtpci_status(void)133 static 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
wdtpci_interrupt(int irq,void * dev_id,struct pt_regs * regs)170 static 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
wdtpci_ping(void)213 static 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
wdtpci_write(struct file * file,const char * buf,size_t count,loff_t * ppos)237 static 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
wdtpci_read(struct file * file,char * buf,size_t count,loff_t * ptr)274 static 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
wdtpci_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg)309 static 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
wdtpci_open(struct inode * inode,struct file * file)364 static 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
wdtpci_release(struct inode * inode,struct file * file)427 static 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
wdtpci_notify_sys(struct notifier_block * this,unsigned long code,void * unused)458 static 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
478 static 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
488 static struct miscdevice wdtpci_miscdev=
489 {
490 WATCHDOG_MINOR,
491 "watchdog",
492 &wdtpci_fops
493 };
494
495 #ifdef CONFIG_WDT_501
496 static 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
509 static struct notifier_block wdtpci_notifier=
510 {
511 wdtpci_notify_sys,
512 NULL,
513 0
514 };
515
516
wdtpci_init_one(struct pci_dev * dev,const struct pci_device_id * ent)517 static 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 register_reboot_notifier 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;
572 out:
573 return ret;
574
575 #ifdef CONFIG_WDT_501
576 out_rbt:
577 unregister_reboot_notifier(&wdtpci_notifier);
578 #endif
579 out_misc:
580 misc_deregister(&wdtpci_miscdev);
581 out_irq:
582 free_irq(irq, &wdtpci_miscdev);
583 out_reg:
584 release_region (io, 16);
585 goto out;
586 }
587
588
wdtpci_remove_one(struct pci_dev * pdev)589 static 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
603 static 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 };
607 MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
608
609
610 static 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
wdtpci_cleanup(void)628 static 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
wdtpci_init(void)642 static 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
653 module_init(wdtpci_init);
654 module_exit(wdtpci_cleanup);
655
656 MODULE_AUTHOR("JP Nollmann, Alan Cox");
657 MODULE_DESCRIPTION("Driver for the ICS PCI watchdog cards");
658 MODULE_LICENSE("GPL");
659
660 EXPORT_NO_SYMBOLS;
661