~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/char/acquirewdt.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *      Acquire Single Board Computer Watchdog Timer driver for Linux 2.1.x
  3  *
  4  *      Based on wdt.c. Original copyright messages:
  5  *
  6  *      (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved.
  7  *                              http://www.redhat.com
  8  *
  9  *      This program is free software; you can redistribute it and/or
 10  *      modify it under the terms of the GNU General Public License
 11  *      as published by the Free Software Foundation; either version
 12  *      2 of the License, or (at your option) any later version.
 13  *      
 14  *      Neither Alan Cox nor CymruNet Ltd. admit liability nor provide 
 15  *      warranty for any of this software. This material is provided 
 16  *      "AS-IS" and at no charge.       
 17  *
 18  *      (c) Copyright 1995    Alan Cox <alan@redhat.com>
 19  *
 20  */
 21 
 22 #include <linux/config.h>
 23 #include <linux/module.h>
 24 #include <linux/version.h>
 25 #include <linux/types.h>
 26 #include <linux/errno.h>
 27 #include <linux/kernel.h>
 28 #include <linux/sched.h>
 29 #include <linux/miscdevice.h>
 30 #include <linux/watchdog.h>
 31 #include <linux/malloc.h>
 32 #include <linux/ioport.h>
 33 #include <linux/fcntl.h>
 34 #include <asm/io.h>
 35 #include <asm/uaccess.h>
 36 #include <asm/system.h>
 37 #include <linux/notifier.h>
 38 #include <linux/reboot.h>
 39 #include <linux/init.h>
 40 #include <linux/spinlock.h>
 41 #include <linux/smp_lock.h>
 42 
 43 static int acq_is_open;
 44 static spinlock_t acq_lock;
 45 
 46 /*
 47  *      You must set these - there is no sane way to probe for this board.
 48  */
 49  
 50 #define WDT_STOP 0x43
 51 #define WDT_START 0x443
 52 
 53 #define WD_TIMO (100*60)                /* 1 minute */
 54 
 55 
 56 /*
 57  *      Kernel methods.
 58  */
 59  
 60 
 61 static void acq_ping(void)
 62 {
 63         /* Write a watchdog value */
 64         inb_p(WDT_START);
 65 }
 66 
 67 static ssize_t acq_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
 68 {
 69         /*  Can't seek (pwrite) on this device  */
 70         if (ppos != &file->f_pos)
 71                 return -ESPIPE;
 72 
 73         if(count)
 74         {
 75                 acq_ping();
 76                 return 1;
 77         }
 78         return 0;
 79 }
 80 
 81 static ssize_t acq_read(struct file *file, char *buf, size_t count, loff_t *ppos)
 82 {
 83         return -EINVAL;
 84 }
 85 
 86 
 87 
 88 static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
 89         unsigned long arg)
 90 {
 91         static struct watchdog_info ident=
 92         {
 93                 WDIOF_KEEPALIVEPING, 1, "Acquire WDT"
 94         };
 95         
 96         switch(cmd)
 97         {
 98         case WDIOC_GETSUPPORT:
 99           if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
100             return -EFAULT;
101           break;
102           
103         case WDIOC_GETSTATUS:
104           if (copy_to_user((int *)arg, &acq_is_open,  sizeof(int)))
105             return -EFAULT;
106           break;
107 
108         case WDIOC_KEEPALIVE:
109           acq_ping();
110           break;
111 
112         default:
113           return -ENOIOCTLCMD;
114         }
115         return 0;
116 }
117 
118 static int acq_open(struct inode *inode, struct file *file)
119 {
120         switch(MINOR(inode->i_rdev))
121         {
122                 case WATCHDOG_MINOR:
123                         spin_lock(&acq_lock);
124                         if(acq_is_open)
125                         {
126                                 spin_unlock(&acq_lock);
127                                 return -EBUSY;
128                         }
129                         /*
130                          *      Activate 
131                          */
132          
133                         acq_is_open=1;
134                         inb_p(WDT_START);      
135                         spin_unlock(&acq_lock);
136                         return 0;
137                 default:
138                         return -ENODEV;
139         }
140 }
141 
142 static int acq_close(struct inode *inode, struct file *file)
143 {
144         lock_kernel();
145         if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
146         {
147                 spin_lock(&acq_lock);
148 #ifndef CONFIG_WATCHDOG_NOWAYOUT        
149                 inb_p(WDT_STOP);
150 #endif          
151                 acq_is_open=0;
152                 spin_unlock(&acq_lock);
153         }
154         unlock_kernel();
155         return 0;
156 }
157 
158 /*
159  *      Notifier for system down
160  */
161 
162 static int acq_notify_sys(struct notifier_block *this, unsigned long code,
163         void *unused)
164 {
165         if(code==SYS_DOWN || code==SYS_HALT)
166         {
167                 /* Turn the card off */
168                 inb_p(WDT_STOP);
169         }
170         return NOTIFY_DONE;
171 }
172  
173 /*
174  *      Kernel Interfaces
175  */
176  
177  
178 static struct file_operations acq_fops = {
179         owner:          THIS_MODULE,
180         read:           acq_read,
181         write:          acq_write,
182         ioctl:          acq_ioctl,
183         open:           acq_open,
184         release:        acq_close,
185 };
186 
187 static struct miscdevice acq_miscdev=
188 {
189         WATCHDOG_MINOR,
190         "watchdog",
191         &acq_fops
192 };
193 
194 
195 /*
196  *      The WDT card needs to learn about soft shutdowns in order to
197  *      turn the timebomb registers off. 
198  */
199  
200 static struct notifier_block acq_notifier=
201 {
202         acq_notify_sys,
203         NULL,
204         0
205 };
206 
207 static int __init acq_init(void)
208 {
209         printk("WDT driver for Acquire single board computer initialising.\n");
210 
211         spin_lock_init(&acq_lock);
212         misc_register(&acq_miscdev);
213         request_region(WDT_STOP, 1, "Acquire WDT");
214         request_region(WDT_START, 1, "Acquire WDT");
215         register_reboot_notifier(&acq_notifier);
216         return 0;
217 }
218         
219 static void __exit acq_exit(void)
220 {
221         misc_deregister(&acq_miscdev);
222         unregister_reboot_notifier(&acq_notifier);
223         release_region(WDT_STOP,1);
224         release_region(WDT_START,1);
225 }
226 
227 module_init(acq_init);
228 module_exit(acq_exit);
229 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.