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