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

Subversion Repositories or1k

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *      IndyDog 0.2     A Hardware Watchdog Device for SGI IP22
3
 *
4
 *      (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>, All Rights Reserved.
5
 *
6
 *      This program is free software; you can redistribute it and/or
7
 *      modify it under the terms of the GNU General Public License
8
 *      as published by the Free Software Foundation; either version
9
 *      2 of the License, or (at your option) any later version.
10
 *
11
 *      based on softdog.c by Alan Cox <alan@redhat.com>
12
 */
13
 
14
#include <linux/module.h>
15
#include <linux/config.h>
16
#include <linux/types.h>
17
#include <linux/kernel.h>
18
#include <linux/fs.h>
19
#include <linux/mm.h>
20
#include <linux/miscdevice.h>
21
#include <linux/watchdog.h>
22
#include <linux/smp_lock.h>
23
#include <linux/init.h>
24
#include <asm/uaccess.h>
25
#include <asm/sgi/mc.h>
26
 
27
static unsigned long indydog_alive;
28
static int expect_close = 0;
29
 
30
#ifdef CONFIG_WATCHDOG_NOWAYOUT
31
static int nowayout = 1;
32
#else
33
static int nowayout = 0;
34
#endif
35
 
36
MODULE_PARM(nowayout,"i");
37
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
38
 
39
static inline void indydog_ping(void)
40
{
41
        sgimc->watchdogt = 0;
42
}
43
 
44
/*
45
 *      Allow only one person to hold it open
46
 */
47
static int indydog_open(struct inode *inode, struct file *file)
48
{
49
        u32 mc_ctrl0;
50
 
51
        if (test_and_set_bit(0,&indydog_alive))
52
                return -EBUSY;
53
 
54
        if (nowayout) {
55
                MOD_INC_USE_COUNT;
56
        }
57
 
58
        /* Activate timer */
59
        mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG;
60
        sgimc->cpuctrl0 = mc_ctrl0;
61
        indydog_ping();
62
 
63
        indydog_alive = 1;
64
        printk(KERN_INFO "Started watchdog timer.\n");
65
 
66
        return 0;
67
}
68
 
69
static int indydog_release(struct inode *inode, struct file *file)
70
{
71
        /* Shut off the timer.
72
         * Lock it in if it's a module and we set nowayout. */
73
        lock_kernel();
74
        if (expect_close) {
75
                u32 mc_ctrl0 = sgimc->cpuctrl0;
76
                mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG;
77
                sgimc->cpuctrl0 = mc_ctrl0;
78
                printk(KERN_INFO "Stopped watchdog timer.\n");
79
        } else
80
                printk(KERN_CRIT "WDT device closed unexpectedly.  WDT will not stop!\n");
81
        clear_bit(0, &indydog_alive);
82
        unlock_kernel();
83
 
84
        return 0;
85
}
86
 
87
static ssize_t indydog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
88
{
89
        /*  Can't seek (pwrite) on this device  */
90
        if (ppos != &file->f_pos)
91
                return -ESPIPE;
92
 
93
        /*
94
         *      Refresh the timer.
95
         */
96
        if (len) {
97
                if (!nowayout) {
98
                        size_t i;
99
 
100
                        /* In case it was set long ago */
101
                        expect_close = 0;
102
 
103
                        for (i = 0; i != len; i++) {
104
                                char c;
105
                                if (get_user(c, data + i))
106
                                        return -EFAULT;
107
                                if (c == 'V')
108
                                        expect_close = 1;
109
                        }
110
                }
111
                indydog_ping();
112
                return 1;
113
        }
114
        return 0;
115
}
116
 
117
static int indydog_ioctl(struct inode *inode, struct file *file,
118
        unsigned int cmd, unsigned long arg)
119
{
120
        static struct watchdog_info ident = {
121
                options: WDIOF_MAGICCLOSE,
122
                identity: "Hardware Watchdog for SGI IP22",
123
        };
124
        switch (cmd) {
125
                default:
126
                        return -ENOIOCTLCMD;
127
                case WDIOC_GETSUPPORT:
128
                        if(copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident)))
129
                                return -EFAULT;
130
                        return 0;
131
                case WDIOC_GETSTATUS:
132
                case WDIOC_GETBOOTSTATUS:
133
                        return put_user(0,(int *)arg);
134
                case WDIOC_KEEPALIVE:
135
                        indydog_ping();
136
                        return 0;
137
        }
138
}
139
 
140
static struct file_operations indydog_fops = {
141
        owner:          THIS_MODULE,
142
        write:          indydog_write,
143
        ioctl:          indydog_ioctl,
144
        open:           indydog_open,
145
        release:        indydog_release,
146
};
147
 
148
static struct miscdevice indydog_miscdev = {
149
        minor:          WATCHDOG_MINOR,
150
        name:           "watchdog",
151
        fops:           &indydog_fops,
152
};
153
 
154
static const char banner[] __initdata = KERN_INFO "Hardware Watchdog Timer for SGI IP22: 0.2\n";
155
 
156
static int __init watchdog_init(void)
157
{
158
        int ret = misc_register(&indydog_miscdev);
159
 
160
        if (ret)
161
                return ret;
162
 
163
        printk(banner);
164
 
165
        return 0;
166
}
167
 
168
static void __exit watchdog_exit(void)
169
{
170
        misc_deregister(&indydog_miscdev);
171
}
172
 
173
module_init(watchdog_init);
174
module_exit(watchdog_exit);
175
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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