File: /usr/src/linux/drivers/char/wdt_pci.c

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      */
34     
35     #include <linux/config.h>
36     #include <linux/module.h>
37     #include <linux/version.h>
38     #include <linux/types.h>
39     #include <linux/errno.h>
40     #include <linux/kernel.h>
41     #include <linux/sched.h>
42     #include <linux/miscdevice.h>
43     #include <linux/watchdog.h>
44     #define WDT_IS_PCI
45     #include "wd501p.h"
46     #include <linux/slab.h>
47     #include <linux/ioport.h>
48     #include <linux/fcntl.h>
49     #include <asm/io.h>
50     #include <asm/uaccess.h>
51     #include <asm/system.h>
52     #include <linux/notifier.h>
53     #include <linux/reboot.h>
54     #include <linux/init.h>
55     #include <linux/smp_lock.h>
56     
57     #include <linux/pci.h>
58     
59     #define PFX "wdt_pci: "
60     
61     /*
62      * Until Access I/O gets their application for a PCI vendor ID approved,
63      * I don't think that it's appropriate to move these constants into the
64      * regular pci_ids.h file. -- JPN 2000/01/18
65      */
66     
67     #ifndef PCI_VENDOR_ID_ACCESSIO
68     #define PCI_VENDOR_ID_ACCESSIO 0x494f
69     #endif
70     #ifndef PCI_DEVICE_ID_WDG_CSM
71     #define PCI_DEVICE_ID_WDG_CSM 0x22c0
72     #endif
73     
74     static int wdt_is_open;
75     
76     /*
77      *	You must set these - there is no sane way to probe for this board.
78      *	You can use wdt=x,y to set these now.
79      */
80      
81     static int io=0x240;
82     static int irq=11;
83     
84     #define WD_TIMO (100*60)		/* 1 minute */
85     
86     #ifndef MODULE
87     
88     /**
89      *	wdtpci_setup:
90      *	@str: command line string
91      *
92      *	Setup options. The board isn't really probe-able so we have to
93      *	get the user to tell us the configuration. Sane people build it 
94      *	modular but the others come here.
95      */
96      
97     static int __init wdtpci_setup(char *str)
98     {
99     	int ints[4];
100     
101     	str = get_options (str, ARRAY_SIZE(ints), ints);
102     
103     	if (ints[0] > 0)
104     	{
105     		io = ints[1];
106     		if(ints[0] > 1)
107     			irq = ints[2];
108     	}
109     
110     	return 1;
111     }
112     
113     __setup("wdt=", wdtpci_setup);
114     
115     #endif /* !MODULE */
116      
117     /*
118      *	Programming support
119      */
120      
121     static void wdtpci_ctr_mode(int ctr, int mode)
122     {
123     	ctr<<=6;
124     	ctr|=0x30;
125     	ctr|=(mode<<1);
126     	outb_p(ctr, WDT_CR);
127     }
128     
129     static void wdtpci_ctr_load(int ctr, int val)
130     {
131     	outb_p(val&0xFF, WDT_COUNT0+ctr);
132     	outb_p(val>>8, WDT_COUNT0+ctr);
133     }
134     
135     /*
136      *	Kernel methods.
137      */
138      
139      
140     /**
141      *	wdtpci_status:
142      *	
143      *	Extract the status information from a WDT watchdog device. There are
144      *	several board variants so we have to know which bits are valid. Some
145      *	bits default to one and some to zero in order to be maximally painful.
146      *
147      *	we then map the bits onto the status ioctl flags.
148      */
149      
150     static int wdtpci_status(void)
151     {
152     	/*
153     	 *	Status register to bit flags
154     	 */
155     	 
156     	int flag=0;
157     	unsigned char status=inb_p(WDT_SR);
158     	status|=FEATUREMAP1;
159     	status&=~FEATUREMAP2;	
160     	
161     	if(!(status&WDC_SR_TGOOD))
162     		flag|=WDIOF_OVERHEAT;
163     	if(!(status&WDC_SR_PSUOVER))
164     		flag|=WDIOF_POWEROVER;
165     	if(!(status&WDC_SR_PSUUNDR))
166     		flag|=WDIOF_POWERUNDER;
167     	if(!(status&WDC_SR_FANGOOD))
168     		flag|=WDIOF_FANFAULT;
169     	if(status&WDC_SR_ISOI0)
170     		flag|=WDIOF_EXTERN1;
171     	if(status&WDC_SR_ISII1)
172     		flag|=WDIOF_EXTERN2;
173     	return flag;
174     }
175     
176     /**
177      *	wdtpci_interrupt:
178      *	@irq:		Interrupt number
179      *	@dev_id:	Unused as we don't allow multiple devices.
180      *	@regs:		Unused.
181      *
182      *	Handle an interrupt from the board. These are raised when the status
183      *	map changes in what the board considers an interesting way. That means
184      *	a failure condition occuring.
185      */
186      
187     static void wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
188     {
189     	/*
190     	 *	Read the status register see what is up and
191     	 *	then printk it. 
192     	 */
193     	 
194     	unsigned char status=inb_p(WDT_SR);
195     	
196     	status|=FEATUREMAP1;
197     	status&=~FEATUREMAP2;	
198     	
199     	printk(KERN_CRIT "WDT status %d\n", status);
200     	
201     	if(!(status&WDC_SR_TGOOD))
202     		printk(KERN_CRIT "Overheat alarm.(%d)\n",inb_p(WDT_RT));
203     	if(!(status&WDC_SR_PSUOVER))
204     		printk(KERN_CRIT "PSU over voltage.\n");
205     	if(!(status&WDC_SR_PSUUNDR))
206     		printk(KERN_CRIT "PSU under voltage.\n");
207     	if(!(status&WDC_SR_FANGOOD))
208     		printk(KERN_CRIT "Possible fan fault.\n");
209     	if(!(status&WDC_SR_WCCR))
210     #ifdef SOFTWARE_REBOOT
211     #ifdef ONLY_TESTING
212     		printk(KERN_CRIT "Would Reboot.\n");
213     #else		
214     		printk(KERN_CRIT "Initiating system reboot.\n");
215     		machine_restart(NULL);
216     #endif		
217     #else
218     		printk(KERN_CRIT "Reset in 5ms.\n");
219     #endif		
220     }
221     
222     
223     /**
224      *	wdtpci_ping:
225      *
226      *	Reload counter one with the watchdog timeout. We don't bother reloading
227      *	the cascade counter. 
228      */
229      
230     static void wdtpci_ping(void)
231     {
232     	/* Write a watchdog value */
233     	inb_p(WDT_DC);
234     	wdtpci_ctr_mode(1,2);
235     	wdtpci_ctr_load(1,WD_TIMO);		/* Timeout */
236     	outb_p(0, WDT_DC);
237     }
238     
239     /**
240      *	wdtpci_write:
241      *	@file: file handle to the watchdog
242      *	@buf: buffer to write (unused as data does not matter here 
243      *	@count: count of bytes
244      *	@ppos: pointer to the position to write. No seeks allowed
245      *
246      *	A write to a watchdog device is defined as a keepalive signal. Any
247      *	write of data will do, as we we don't define content meaning.
248      */
249      
250     static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
251     {
252     	/*  Can't seek (pwrite) on this device  */
253     	if (ppos != &file->f_pos)
254     		return -ESPIPE;
255     
256     	if(count)
257     	{
258     		wdtpci_ping();
259     		return 1;
260     	}
261     	return 0;
262     }
263     
264     /**
265      *	wdtpci_read:
266      *	@file: file handle to the watchdog board
267      *	@buf: buffer to write 1 byte into
268      *	@count: length of buffer
269      *	@ptr: offset (no seek allowed)
270      *
271      *	Read reports the temperature in degrees Fahrenheit. The API is in
272      *	fahrenheit. It was designed by an imperial measurement luddite.
273      */
274      
275     static ssize_t wdtpci_read(struct file *file, char *buf, size_t count, loff_t *ptr)
276     {
277     	unsigned short c=inb_p(WDT_RT);
278     	unsigned char cp;
279     	
280     	/*  Can't seek (pread) on this device  */
281     	if (ptr != &file->f_pos)
282     		return -ESPIPE;
283     
284     	switch(MINOR(file->f_dentry->d_inode->i_rdev))
285     	{
286     		case TEMP_MINOR:
287     			c*=11;
288     			c/=15;
289     			cp=c+7;
290     			if(copy_to_user(buf,&cp,1))
291     				return -EFAULT;
292     			return 1;
293     		default:
294     			return -EINVAL;
295     	}
296     }
297     
298     /**
299      *	wdtpci_ioctl:
300      *	@inode: inode of the device
301      *	@file: file handle to the device
302      *	@cmd: watchdog command
303      *	@arg: argument pointer
304      *
305      *	The watchdog API defines a common set of functions for all watchdogs
306      *	according to their available features. We only actually usefully support
307      *	querying capabilities and current status. 
308      */
309      
310     static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
311     	unsigned long arg)
312     {
313     	static struct watchdog_info ident=
314     	{
315     		WDIOF_OVERHEAT|WDIOF_POWERUNDER|WDIOF_POWEROVER
316     			|WDIOF_EXTERN1|WDIOF_EXTERN2|WDIOF_FANFAULT,
317     		1,
318     		"WDT500/501PCI"
319     	};
320     	
321     	ident.options&=WDT_OPTION_MASK;	/* Mask down to the card we have */
322     	switch(cmd)
323     	{
324     		default:
325     			return -ENOTTY;
326     		case WDIOC_GETSUPPORT:
327     			return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;
328     
329     		case WDIOC_GETSTATUS:
330     			return put_user(wdtpci_status(),(int *)arg);
331     		case WDIOC_GETBOOTSTATUS:
332     			return put_user(0, (int *)arg);
333     		case WDIOC_KEEPALIVE:
334     			wdtpci_ping();
335     			return 0;
336     	}
337     }
338     
339     /**
340      *	wdtpci_open:
341      *	@inode: inode of device
342      *	@file: file handle to device
343      *
344      *	One of our two misc devices has been opened. The watchdog device is
345      *	single open and on opening we load the counters. Counter zero is a 
346      *	100Hz cascade, into counter 1 which downcounts to reboot. When the
347      *	counter triggers counter 2 downcounts the length of the reset pulse
348      *	which set set to be as long as possible. 
349      */
350      
351     static int wdtpci_open(struct inode *inode, struct file *file)
352     {
353     	switch(MINOR(inode->i_rdev))
354     	{
355     		case WATCHDOG_MINOR:
356     			if(wdt_is_open)
357     				return -EBUSY;
358     #ifdef CONFIG_WATCHDOG_NOWAYOUT	
359     			MOD_INC_USE_COUNT;
360     #endif
361     			/*
362     			 *	Activate 
363     			 */
364     	 
365     			wdt_is_open=1;
366     
367     			inb_p(WDT_DC);		/* Disable */
368     
369     			/*
370     			 * "pet" the watchdog, as Access says.
371     			 * This resets the clock outputs.
372     			 */
373     				
374     			wdtpci_ctr_mode(2,0);
375     			outb_p(0, WDT_DC);
376     
377     			inb_p(WDT_DC);
378     
379     			outb_p(0, WDT_CLOCK);	/* 2.0833MHz clock */
380     			inb_p(WDT_BUZZER);	/* disable */
381     			inb_p(WDT_OPTONOTRST);	/* disable */
382     			inb_p(WDT_OPTORST);	/* disable */
383     			inb_p(WDT_PROGOUT);	/* disable */
384     			wdtpci_ctr_mode(0,3);
385     			wdtpci_ctr_mode(1,2);
386     			wdtpci_ctr_mode(2,1);
387     			wdtpci_ctr_load(0,20833);	/* count at 100Hz */
388     			wdtpci_ctr_load(1,WD_TIMO);/* Timeout 60 seconds */
389     			/* DO NOT LOAD CTR2 on PCI card! -- JPN */
390     			outb_p(0, WDT_DC);	/* Enable */
391     			return 0;
392     		case TEMP_MINOR:
393     			return 0;
394     		default:
395     			return -ENODEV;
396     	}
397     }
398     
399     /**
400      *	wdtpci_close:
401      *	@inode: inode to board
402      *	@file: file handle to board
403      *
404      *	The watchdog has a configurable API. There is a religious dispute 
405      *	between people who want their watchdog to be able to shut down and 
406      *	those who want to be sure if the watchdog manager dies the machine
407      *	reboots. In the former case we disable the counters, in the latter
408      *	case you have to open it again very soon.
409      */
410      
411     static int wdtpci_release(struct inode *inode, struct file *file)
412     {
413     	if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
414     	{
415     		lock_kernel();
416     #ifndef CONFIG_WATCHDOG_NOWAYOUT	
417     		inb_p(WDT_DC);		/* Disable counters */
418     		wdtpci_ctr_load(2,0);	/* 0 length reset pulses now */
419     #endif		
420     		wdt_is_open=0;
421     		unlock_kernel();
422     	}
423     	return 0;
424     }
425     
426     /**
427      *	notify_sys:
428      *	@this: our notifier block
429      *	@code: the event being reported
430      *	@unused: unused
431      *
432      *	Our notifier is called on system shutdowns. We want to turn the card
433      *	off at reboot otherwise the machine will reboot again during memory
434      *	test or worse yet during the following fsck. This would suck, in fact
435      *	trust me - if it happens it does suck.
436      */
437     
438     static int wdtpci_notify_sys(struct notifier_block *this, unsigned long code,
439     	void *unused)
440     {
441     	if(code==SYS_DOWN || code==SYS_HALT)
442     	{
443     		/* Turn the card off */
444     		inb_p(WDT_DC);
445     		wdtpci_ctr_load(2,0);
446     	}
447     	return NOTIFY_DONE;
448     }
449      
450     /*
451      *	Kernel Interfaces
452      */
453      
454      
455     static struct file_operations wdtpci_fops = {
456     	owner:		THIS_MODULE,
457     	llseek:		no_llseek,
458     	read:		wdtpci_read,
459     	write:		wdtpci_write,
460     	ioctl:		wdtpci_ioctl,
461     	open:		wdtpci_open,
462     	release:	wdtpci_release,
463     };
464     
465     static struct miscdevice wdtpci_miscdev=
466     {
467     	WATCHDOG_MINOR,
468     	"watchdog",
469     	&wdtpci_fops
470     };
471     
472     #ifdef CONFIG_WDT_501
473     static struct miscdevice temp_miscdev=
474     {
475     	TEMP_MINOR,
476     	"temperature",
477     	&wdtpci_fops
478     };
479     #endif
480     
481     /*
482      *	The WDT card needs to learn about soft shutdowns in order to
483      *	turn the timebomb registers off. 
484      */
485      
486     static struct notifier_block wdtpci_notifier=
487     {
488     	wdtpci_notify_sys,
489     	NULL,
490     	0
491     };
492     
493     
494     static int __init wdtpci_init_one (struct pci_dev *dev,
495     				   const struct pci_device_id *ent)
496     {
497     	static int dev_count = 0;
498     	int ret = -EIO;
499     
500     	dev_count++;
501     	if (dev_count > 1) {
502     		printk (KERN_ERR PFX
503     			"this driver only supports 1 device\n");
504     		return -ENODEV;
505     	}
506     
507     	irq = dev->irq;
508     	io = pci_resource_start (dev, 2);
509     	printk ("WDT501-P(PCI-WDG-CSM) driver 0.07 at %X "
510     		"(Interrupt %d)\n", io, irq);
511     
512     	if (pci_enable_device (dev))
513     		goto out;
514     
515     	if (request_region (io, 16, "wdt-pci") == NULL) {
516     		printk (KERN_ERR PFX "I/O %d is not free.\n", io);
517     		goto out;
518     	}
519     
520     	if (request_irq (irq, wdtpci_interrupt, SA_INTERRUPT | SA_SHIRQ,
521     			 "wdt-pci", &wdtpci_miscdev)) {
522     		printk (KERN_ERR PFX "IRQ %d is not free.\n", irq);
523     		goto out_reg;
524     	}
525     
526     	ret = misc_register (&wdtpci_miscdev);
527     	if (ret) {
528     		printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR);
529     		goto out_irq;
530     	}
531     
532     	ret = register_reboot_notifier (&wdtpci_notifier);
533     	if (ret) {
534     		printk (KERN_ERR PFX "can't misc_register on minor=%d\n", WATCHDOG_MINOR);
535     		goto out_misc;
536     	}
537     #ifdef CONFIG_WDT_501
538     	ret = misc_register (&temp_miscdev);
539     	if (ret) {
540     		printk (KERN_ERR PFX "can't misc_register (temp) on minor=%d\n", TEMP_MINOR);
541     		goto out_rbt;
542     	}
543     #endif
544     
545     	ret = 0;
546     out:
547     	return ret;
548     
549     #ifdef CONFIG_WDT_501
550     out_rbt:
551     	unregister_reboot_notifier(&wdtpci_notifier);
552     #endif
553     out_misc:
554     	misc_deregister(&wdtpci_miscdev);
555     out_irq:
556     	free_irq(irq, &wdtpci_miscdev);
557     out_reg:
558     	release_region (io, 16);
559     	goto out;
560     }
561     
562     
563     static void __exit wdtpci_remove_one (struct pci_dev *pdev)
564     {
565     	/* here we assume only one device will ever have
566     	 * been picked up and registered by probe function */
567     	unregister_reboot_notifier(&wdtpci_notifier);
568     #ifdef CONFIG_WDT_501_PCI
569     	misc_deregister(&temp_miscdev);
570     #endif	
571     	misc_deregister(&wdtpci_miscdev);
572     	free_irq(irq, &wdtpci_miscdev);
573     	release_region(io, 16);
574     }
575     
576     
577     static struct pci_device_id wdtpci_pci_tbl[] __initdata = {
578     	{ PCI_VENDOR_ID_ACCESSIO, PCI_DEVICE_ID_WDG_CSM, PCI_ANY_ID, PCI_ANY_ID, },
579     	{ 0, }, /* terminate list */
580     };
581     MODULE_DEVICE_TABLE(pci, wdtpci_pci_tbl);
582     
583     
584     static struct pci_driver wdtpci_driver = {
585     	name:		"wdt-pci",
586     	id_table:	wdtpci_pci_tbl,
587     	probe:		wdtpci_init_one,
588     	remove:		wdtpci_remove_one,
589     };
590     
591     
592     /**
593      *	wdtpci_cleanup:
594      *
595      *	Unload the watchdog. You cannot do this with any file handles open.
596      *	If your watchdog is set to continue ticking on close and you unload
597      *	it, well it keeps ticking. We won't get the interrupt but the board
598      *	will not touch PC memory so all is fine. You just have to load a new
599      *	module in 60 seconds or reboot.
600      */
601      
602     static void __exit wdtpci_cleanup(void)
603     {
604     	pci_unregister_driver (&wdtpci_driver);
605     }
606     
607     
608     /**
609      * 	wdtpci_init:
610      *
611      *	Set up the WDT watchdog board. All we have to do is grab the
612      *	resources we require and bitch if anyone beat us to them.
613      *	The open() function will actually kick the board off.
614      */
615      
616     static int __init wdtpci_init(void)
617     {
618     	int rc = pci_register_driver (&wdtpci_driver);
619     	
620     	if (rc < 1)
621     		return -ENODEV;
622     	
623     	return 0;
624     }
625     
626     
627     module_init(wdtpci_init);
628     module_exit(wdtpci_cleanup);
629     
630     MODULE_AUTHOR("JP Nollmann, Alan Cox");
631     MODULE_DESCRIPTION("Driver for the ICS PCI watchdog cards");
632     MODULE_LICENSE("GPL");
633     
634     EXPORT_NO_SYMBOLS;
635