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