OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [char/] [acquirewdt.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
 *      14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
21
 *          Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
22
 *          Can't add timeout - driver doesn't allow changing value
23
 */
24
 
25
#include <linux/config.h>
26
#include <linux/module.h>
27
#include <linux/version.h>
28
#include <linux/types.h>
29
#include <linux/errno.h>
30
#include <linux/kernel.h>
31
#include <linux/sched.h>
32
#include <linux/miscdevice.h>
33
#include <linux/watchdog.h>
34
#include <linux/slab.h>
35
#include <linux/ioport.h>
36
#include <linux/fcntl.h>
37
#include <asm/io.h>
38
#include <asm/uaccess.h>
39
#include <asm/system.h>
40
#include <linux/notifier.h>
41
#include <linux/reboot.h>
42
#include <linux/init.h>
43
#include <linux/spinlock.h>
44
#include <linux/smp_lock.h>
45
 
46
static int acq_is_open;
47
static spinlock_t acq_lock;
48
static int expect_close = 0;
49
 
50
/*
51
 *      You must set these - there is no sane way to probe for this board.
52
 */
53
 
54
#define WDT_STOP 0x43
55
#define WDT_START 0x443
56
 
57
#ifdef CONFIG_WATCHDOG_NOWAYOUT
58
static int nowayout = 1;
59
#else
60
static int nowayout = 0;
61
#endif
62
 
63
MODULE_PARM(nowayout,"i");
64
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
65
 
66
/*
67
 *      Kernel methods.
68
 */
69
 
70
 
71
static void acq_ping(void)
72
{
73
        /* Write a watchdog value */
74
        inb_p(WDT_START);
75
}
76
 
77
static ssize_t acq_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
78
{
79
        /*  Can't seek (pwrite) on this device  */
80
        if (ppos != &file->f_pos)
81
                return -ESPIPE;
82
 
83
        if(count)
84
        {
85
                if (!nowayout)
86
                {
87
                        size_t i;
88
 
89
                        expect_close = 0;
90
 
91
                        for (i = 0; i != count; i++) {
92
                                char c;
93
                                if (get_user(c, buf + i))
94
                                        return -EFAULT;
95
                                if (c == 'V')
96
                                        expect_close = 1;
97
                        }
98
                }
99
 
100
                acq_ping();
101
                return 1;
102
        }
103
        return 0;
104
}
105
 
106
static ssize_t acq_read(struct file *file, char *buf, size_t count, loff_t *ppos)
107
{
108
        return -EINVAL;
109
}
110
 
111
 
112
 
113
static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
114
        unsigned long arg)
115
{
116
        static struct watchdog_info ident=
117
        {
118
                WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, 1, "Acquire WDT"
119
        };
120
 
121
        switch(cmd)
122
        {
123
        case WDIOC_GETSUPPORT:
124
          if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
125
            return -EFAULT;
126
          break;
127
 
128
        case WDIOC_GETSTATUS:
129
          if (copy_to_user((int *)arg, &acq_is_open,  sizeof(int)))
130
            return -EFAULT;
131
          break;
132
 
133
        case WDIOC_KEEPALIVE:
134
          acq_ping();
135
          break;
136
 
137
        default:
138
          return -ENOTTY;
139
        }
140
        return 0;
141
}
142
 
143
static int acq_open(struct inode *inode, struct file *file)
144
{
145
        switch(MINOR(inode->i_rdev))
146
        {
147
                case WATCHDOG_MINOR:
148
                        spin_lock(&acq_lock);
149
                        if(acq_is_open)
150
                        {
151
                                spin_unlock(&acq_lock);
152
                                return -EBUSY;
153
                        }
154
                        if (nowayout) {
155
                                MOD_INC_USE_COUNT;
156
                        }
157
                        /*
158
                         *      Activate
159
                         */
160
                        acq_is_open=1;
161
                        inb_p(WDT_START);
162
                        spin_unlock(&acq_lock);
163
                        return 0;
164
                default:
165
                        return -ENODEV;
166
        }
167
}
168
 
169
static int acq_close(struct inode *inode, struct file *file)
170
{
171
        lock_kernel();
172
        if(MINOR(inode->i_rdev)==WATCHDOG_MINOR)
173
        {
174
                spin_lock(&acq_lock);
175
                if (expect_close)
176
                {
177
                        inb_p(WDT_STOP);
178
                }
179
                else
180
                {
181
                        printk(KERN_CRIT "WDT closed unexpectedly.  WDT will not stop!\n");
182
                }
183
                acq_is_open=0;
184
                spin_unlock(&acq_lock);
185
        }
186
        unlock_kernel();
187
        return 0;
188
}
189
 
190
/*
191
 *      Notifier for system down
192
 */
193
 
194
static int acq_notify_sys(struct notifier_block *this, unsigned long code,
195
        void *unused)
196
{
197
        if(code==SYS_DOWN || code==SYS_HALT)
198
        {
199
                /* Turn the card off */
200
                inb_p(WDT_STOP);
201
        }
202
        return NOTIFY_DONE;
203
}
204
 
205
/*
206
 *      Kernel Interfaces
207
 */
208
 
209
 
210
static struct file_operations acq_fops = {
211
        owner:          THIS_MODULE,
212
        read:           acq_read,
213
        write:          acq_write,
214
        ioctl:          acq_ioctl,
215
        open:           acq_open,
216
        release:        acq_close,
217
};
218
 
219
static struct miscdevice acq_miscdev=
220
{
221
        WATCHDOG_MINOR,
222
        "watchdog",
223
        &acq_fops
224
};
225
 
226
 
227
/*
228
 *      The WDT card needs to learn about soft shutdowns in order to
229
 *      turn the timebomb registers off.
230
 */
231
 
232
static struct notifier_block acq_notifier=
233
{
234
        acq_notify_sys,
235
        NULL,
236
 
237
};
238
 
239
static int __init acq_init(void)
240
{
241
        printk("WDT driver for Acquire single board computer initialising.\n");
242
 
243
        spin_lock_init(&acq_lock);
244
        if (misc_register(&acq_miscdev))
245
                return -ENODEV;
246
        request_region(WDT_STOP, 1, "Acquire WDT");
247
        request_region(WDT_START, 1, "Acquire WDT");
248
        register_reboot_notifier(&acq_notifier);
249
        return 0;
250
}
251
 
252
static void __exit acq_exit(void)
253
{
254
        misc_deregister(&acq_miscdev);
255
        unregister_reboot_notifier(&acq_notifier);
256
        release_region(WDT_STOP,1);
257
        release_region(WDT_START,1);
258
}
259
 
260
module_init(acq_init);
261
module_exit(acq_exit);
262
 
263
MODULE_LICENSE("GPL");
264
EXPORT_NO_SYMBOLS;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.