Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
watchdog
sbc_epx_c3.c
Go to the documentation of this file.
1
/*
2
* SBC EPX C3 0.1 A Hardware Watchdog Device for the Winsystems EPX-C3
3
* single board computer
4
*
5
* (c) Copyright 2006 Calin A. Culianu <
[email protected]
>, All Rights
6
* Reserved.
7
*
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public License
10
* as published by the Free Software Foundation; either version
11
* 2 of the License, or (at your option) any later version.
12
*
13
* based on softdog.c by Alan Cox <
[email protected]
>
14
*/
15
16
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17
18
#include <linux/module.h>
19
#include <
linux/moduleparam.h
>
20
#include <linux/types.h>
21
#include <linux/kernel.h>
22
#include <linux/fs.h>
23
#include <
linux/mm.h
>
24
#include <
linux/miscdevice.h
>
25
#include <linux/watchdog.h>
26
#include <
linux/notifier.h
>
27
#include <linux/reboot.h>
28
#include <
linux/init.h
>
29
#include <
linux/ioport.h
>
30
#include <
linux/uaccess.h
>
31
#include <
linux/io.h
>
32
33
static
int
epx_c3_alive;
34
35
#define WATCHDOG_TIMEOUT 1
/* 1 sec default timeout */
36
37
static
bool
nowayout =
WATCHDOG_NOWAYOUT
;
38
module_param
(nowayout,
bool
, 0);
39
MODULE_PARM_DESC
(nowayout,
"Watchdog cannot be stopped once started (default="
40
__MODULE_STRING
(
WATCHDOG_NOWAYOUT
)
")"
);
41
42
#define EPXC3_WATCHDOG_CTL_REG 0x1ee
/* write 1 to enable, 0 to disable */
43
#define EPXC3_WATCHDOG_PET_REG 0x1ef
/* write anything to pet once enabled */
44
45
static
void
epx_c3_start(
void
)
46
{
47
outb
(1,
EPXC3_WATCHDOG_CTL_REG
);
48
}
49
50
static
void
epx_c3_stop(
void
)
51
{
52
53
outb
(0,
EPXC3_WATCHDOG_CTL_REG
);
54
55
pr_info
(
"Stopped watchdog timer\n"
);
56
}
57
58
static
void
epx_c3_pet(
void
)
59
{
60
outb
(1,
EPXC3_WATCHDOG_PET_REG
);
61
}
62
63
/*
64
* Allow only one person to hold it open
65
*/
66
static
int
epx_c3_open(
struct
inode
*
inode
,
struct
file
*
file
)
67
{
68
if
(epx_c3_alive)
69
return
-
EBUSY
;
70
71
if
(nowayout)
72
__module_get(
THIS_MODULE
);
73
74
/* Activate timer */
75
epx_c3_start();
76
epx_c3_pet();
77
78
epx_c3_alive = 1;
79
pr_info
(
"Started watchdog timer\n"
);
80
81
return
nonseekable_open
(inode, file);
82
}
83
84
static
int
epx_c3_release(
struct
inode *inode,
struct
file *file)
85
{
86
/* Shut off the timer.
87
* Lock it in if it's a module and we defined ...NOWAYOUT */
88
if
(!nowayout)
89
epx_c3_stop();
/* Turn the WDT off */
90
91
epx_c3_alive = 0;
92
93
return
0;
94
}
95
96
static
ssize_t
epx_c3_write(
struct
file *file,
const
char
__user *
data
,
97
size_t
len, loff_t *ppos)
98
{
99
/* Refresh the timer. */
100
if
(len)
101
epx_c3_pet();
102
return
len;
103
}
104
105
static
long
epx_c3_ioctl(
struct
file *file,
unsigned
int
cmd
,
106
unsigned
long
arg
)
107
{
108
int
options
,
retval
= -
EINVAL
;
109
int
__user
*
argp
= (
void
__user
*)arg;
110
static
const
struct
watchdog_info
ident
= {
111
.options =
WDIOF_KEEPALIVEPING
,
112
.firmware_version = 0,
113
.identity =
"Winsystems EPX-C3 H/W Watchdog"
,
114
};
115
116
switch
(cmd) {
117
case
WDIOC_GETSUPPORT
:
118
if
(
copy_to_user
(argp, &ident,
sizeof
(ident)))
119
return
-
EFAULT
;
120
return
0;
121
case
WDIOC_GETSTATUS
:
122
case
WDIOC_GETBOOTSTATUS
:
123
return
put_user
(0, argp);
124
case
WDIOC_SETOPTIONS
:
125
if
(
get_user
(options, argp))
126
return
-
EFAULT
;
127
128
if
(options &
WDIOS_DISABLECARD
) {
129
epx_c3_stop();
130
retval = 0;
131
}
132
133
if
(options &
WDIOS_ENABLECARD
) {
134
epx_c3_start();
135
retval = 0;
136
}
137
138
return
retval
;
139
case
WDIOC_KEEPALIVE
:
140
epx_c3_pet();
141
return
0;
142
case
WDIOC_GETTIMEOUT
:
143
return
put_user
(
WATCHDOG_TIMEOUT
, argp);
144
default
:
145
return
-
ENOTTY
;
146
}
147
}
148
149
static
int
epx_c3_notify_sys(
struct
notifier_block
*
this
,
unsigned
long
code
,
150
void
*
unused
)
151
{
152
if
(code ==
SYS_DOWN
|| code ==
SYS_HALT
)
153
epx_c3_stop();
/* Turn the WDT off */
154
155
return
NOTIFY_DONE;
156
}
157
158
static
const
struct
file_operations
epx_c3_fops = {
159
.owner =
THIS_MODULE
,
160
.llseek =
no_llseek
,
161
.write = epx_c3_write,
162
.unlocked_ioctl = epx_c3_ioctl,
163
.open = epx_c3_open,
164
.release = epx_c3_release,
165
};
166
167
static
struct
miscdevice
epx_c3_miscdev = {
168
.minor =
WATCHDOG_MINOR
,
169
.name =
"watchdog"
,
170
.fops = &epx_c3_fops,
171
};
172
173
static
struct
notifier_block
epx_c3_notifier = {
174
.notifier_call = epx_c3_notify_sys,
175
};
176
177
static
int
__init
watchdog_init(
void
)
178
{
179
int
ret
;
180
181
if
(!
request_region
(
EPXC3_WATCHDOG_CTL_REG
, 2,
"epxc3_watchdog"
))
182
return
-
EBUSY
;
183
184
ret =
register_reboot_notifier
(&epx_c3_notifier);
185
if
(ret) {
186
pr_err
(
"cannot register reboot notifier (err=%d)\n"
, ret);
187
goto
out
;
188
}
189
190
ret =
misc_register
(&epx_c3_miscdev);
191
if
(ret) {
192
pr_err
(
"cannot register miscdev on minor=%d (err=%d)\n"
,
193
WATCHDOG_MINOR
, ret);
194
unregister_reboot_notifier
(&epx_c3_notifier);
195
goto
out
;
196
}
197
198
pr_info
(
"Hardware Watchdog Timer for Winsystems EPX-C3 SBC: 0.1\n"
);
199
200
return
0;
201
202
out
:
203
release_region
(
EPXC3_WATCHDOG_CTL_REG
, 2);
204
return
ret
;
205
}
206
207
static
void
__exit
watchdog_exit(
void
)
208
{
209
misc_deregister
(&epx_c3_miscdev);
210
unregister_reboot_notifier
(&epx_c3_notifier);
211
release_region
(
EPXC3_WATCHDOG_CTL_REG
, 2);
212
}
213
214
module_init
(watchdog_init);
215
module_exit
(watchdog_exit);
216
217
MODULE_AUTHOR
(
"Calin A. Culianu <
[email protected]
>"
);
218
MODULE_DESCRIPTION
(
"Hardware Watchdog Device for Winsystems EPX-C3 SBC. "
219
"Note that there is no way to probe for this device -- "
220
"so only use it if you are *sure* you are running on this specific "
221
"SBC system from Winsystems! It writes to IO ports 0x1ee and 0x1ef!"
);
222
MODULE_LICENSE
(
"GPL"
);
223
MODULE_ALIAS_MISCDEV
(
WATCHDOG_MINOR
);
Generated on Thu Jan 10 2013 14:43:16 for Linux Kernel by
1.8.2