Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
2ac7e7a9
Commit
2ac7e7a9
authored
Jan 14, 2003
by
Dave Jones
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[WATCHDOG] Final 2.4 bits for advantechwdt
parent
d75013dd
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
111 additions
and
84 deletions
+111
-84
drivers/char/watchdog/advantechwdt.c
drivers/char/watchdog/advantechwdt.c
+111
-84
No files found.
drivers/char/watchdog/advantechwdt.c
View file @
2ac7e7a9
...
...
@@ -13,16 +13,15 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
* warranty for any of this software. This material is provided
* "AS-IS" and at no charge.
*
* Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
* warranty for any of this software. This material is provided
* "AS-IS" and at no charge.
*
* (c) Copyright 1995 Alan Cox <alan@redhat.com>
*
* 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
* Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
* Added timeout module option to override default
* 14-Dec-2001 Matt Domsch <Matt_Domsch@dell.com>
* Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
*/
#include <linux/config.h>
...
...
@@ -40,31 +39,24 @@
#include <asm/uaccess.h>
#include <asm/system.h>
static
int
advwdt_is_open
;
static
unsigned
long
advwdt_is_open
;
static
char
adv_expect_close
;
static
spinlock_t
advwdt_lock
;
/*
* You must set these - there is no sane way to probe for this board.
*
* To enable or restart, write the timeout value in seconds (1 to 63)
* to I/O port
WDT_START. To disable, read I/O port WDT_STOP
.
* to I/O port
wdt_start. To disable, read I/O port wdt_stop
.
* Both are 0x443 for most boards (tested on a PCA-6276VE-00B1), but
* check your manual (at least the PCA-6159 seems to be different -
* the manual says
WDT_STOP
is 0x43, not 0x443).
* the manual says
wdt_stop
is 0x43, not 0x443).
* (0x43 is also a write-only control register for the 8254 timer!)
*
* TODO: module parameters to set the I/O port addresses
*/
#define WDT_STOP 0x443
#define WDT_START 0x443
static
int
wdt_stop
=
0x443
;
static
int
wdt_start
=
0x443
;
#define WD_TIMO 60
/* 1 minute */
static
int
timeout
=
WD_TIMO
;
/* in seconds */
MODULE_PARM
(
timeout
,
"i"
);
MODULE_PARM_DESC
(
timeout
,
"Watchdog timeout in seconds (default=60)"
);
static
int
wd_margin
=
60
;
/* 60 sec default timeout */
#ifdef CONFIG_WATCHDOG_NOWAYOUT
static
int
nowayout
=
1
;
...
...
@@ -78,12 +70,44 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
/*
* Kernel methods.
*/
#ifndef MODULE
static
int
__init
adv_setup
(
char
*
str
)
{
int
ints
[
4
];
str
=
get_options
(
str
,
ARRAY_SIZE
(
ints
),
ints
);
if
(
ints
[
0
]
>
0
){
wdt_stop
=
ints
[
1
];
if
(
ints
[
0
]
>
1
)
wdt_start
=
ints
[
2
];
}
return
1
;
}
__setup
(
"advwdt="
,
adv_setup
);
#endif
/* !MODULE */
MODULE_PARM
(
wdt_stop
,
"i"
);
MODULE_PARM_DESC
(
wdt_stop
,
"Advantech WDT 'stop' io port (default 0x443)"
);
MODULE_PARM
(
wdt_start
,
"i"
);
MODULE_PARM_DESC
(
wdt_start
,
"Advantech WDT 'start' io port (default 0x443)"
);
static
void
advwdt_ping
(
void
)
{
/* Write a watchdog value */
outb_p
(
timeout
,
WDT_START
);
outb_p
(
wd_margin
,
wdt_start
);
}
static
void
advwdt_disable
(
void
)
{
inb_p
(
wdt_stop
);
}
static
ssize_t
...
...
@@ -112,16 +136,11 @@ advwdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
return
count
;
}
static
ssize_t
advwdt_read
(
struct
file
*
file
,
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
return
-
EINVAL
;
}
static
int
advwdt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
{
int
new_margin
;
static
struct
watchdog_info
ident
=
{
.
options
=
WDIOF_KEEPALIVEPING
|
WDIOF_SETTIMEOUT
|
WDIOF_MAGICCLOSE
,
.
firmware_version
=
1
,
...
...
@@ -133,16 +152,47 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
if
(
copy_to_user
((
struct
watchdog_info
*
)
arg
,
&
ident
,
sizeof
(
ident
)))
return
-
EFAULT
;
break
;
case
WDIOC_GETSTATUS
:
if
(
copy_to_user
((
int
*
)
arg
,
&
advwdt_is_open
,
sizeof
(
int
)))
return
-
EFAULT
;
break
;
case
WDIOC_GETBOOTSTATUS
:
return
put_user
(
0
,
(
int
*
)
arg
);
case
WDIOC_KEEPALIVE
:
advwdt_ping
();
break
;
case
WDIOC_SETTIMEOUT
:
if
(
get_user
(
new_margin
,
(
int
*
)
arg
))
return
-
EFAULT
;
if
((
new_margin
<
1
)
||
(
new_margin
>
63
))
return
-
EINVAL
;
wd_margin
=
new_margin
;
advwdt_ping
();
/* Fall */
case
WDIOC_GETTIMEOUT
:
return
put_user
(
wd_margin
,
(
int
*
)
arg
);
case
WDIOC_SETOPTIONS
:
{
int
options
,
retval
=
-
EINVAL
;
if
(
get_user
(
options
,
(
int
*
)
arg
))
return
-
EFAULT
;
if
(
options
&
WDIOS_DISABLECARD
)
{
advwdt_disable
();
retval
=
0
;
}
if
(
options
&
WDIOS_ENABLECARD
)
{
advwdt_ping
();
retval
=
0
;
}
return
retval
;
}
default:
return
-
ENOTTY
;
}
...
...
@@ -152,37 +202,27 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
static
int
advwdt_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
minor
(
inode
->
i_rdev
)
==
WATCHDOG_MINOR
)
{
spin_lock
(
&
advwdt_lock
);
if
(
advwdt_is_open
)
{
spin_unlock
(
&
advwdt_lock
);
return
-
EBUSY
;
}
if
(
test_and_set_bit
(
0
,
&
advwdt_is_open
))
return
-
EBUSY
;
/*
* Activate
*/
if
(
nowayout
)
MOD_INC_USE_COUNT
;
/* Activate */
advwdt_is_open
=
1
;
advwdt_ping
();
spin_unlock
(
&
advwdt_lock
);
return
0
;
}
else
{
return
-
ENODEV
;
}
advwdt_ping
();
return
0
;
}
static
int
advwdt_close
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
minor
(
inode
->
i_rdev
)
==
WATCHDOG_MINOR
)
{
spin_lock
(
&
advwdt_lock
);
if
(
!
nowayout
)
inb_p
(
WDT_STOP
);
advwdt_is_open
=
0
;
spin_unlock
(
&
advwdt_lock
);
if
(
adv_expect_close
==
42
)
{
advwdt_disable
();
}
else
{
printk
(
KERN_CRIT
"advancetechwdt: Unexpected close, not stopping watchdog!
\n
"
);
advwdt_ping
();
}
clear_bit
(
0
,
&
advwdt_is_open
);
adv_expect_close
=
0
;
return
0
;
}
...
...
@@ -194,10 +234,10 @@ static int
advwdt_notify_sys
(
struct
notifier_block
*
this
,
unsigned
long
code
,
void
*
unused
)
{
if
(
code
==
SYS_DOWN
||
code
==
SYS_HALT
)
if
(
code
==
SYS_DOWN
||
code
==
SYS_HALT
)
{
/* Turn the WDT off */
inb_p
(
WDT_STOP
);
advwdt_disable
(
);
}
return
NOTIFY_DONE
;
}
...
...
@@ -207,7 +247,6 @@ advwdt_notify_sys(struct notifier_block *this, unsigned long code,
static
struct
file_operations
advwdt_fops
=
{
.
owner
=
THIS_MODULE
,
.
read
=
advwdt_read
,
.
write
=
advwdt_write
,
.
ioctl
=
advwdt_ioctl
,
.
open
=
advwdt_open
,
...
...
@@ -231,35 +270,22 @@ static struct notifier_block advwdt_notifier = {
.
priority
=
0
};
static
void
__init
advwdt_validate_timeout
(
void
)
{
if
(
timeout
<
1
||
timeout
>
63
)
{
timeout
=
WD_TIMO
;
printk
(
KERN_INFO
"advantechwdt: timeout value must be 1 <= x <= 63, using %d
\n
"
,
timeout
);
}
}
static
int
__init
advwdt_init
(
void
)
{
printk
(
"WDT driver for Advantech single board computer initialising.
\n
"
);
printk
(
KERN_INFO
"WDT driver for Advantech single board computer initialising.
\n
"
);
advwdt_validate_timeout
();
spin_lock_init
(
&
advwdt_lock
);
if
(
misc_register
(
&
advwdt_miscdev
))
return
-
ENODEV
;
#if WDT_START != WDT_STOP
if
(
!
request_region
(
WDT_STOP
,
1
,
"Advantech WDT"
))
{
misc_deregister
(
&
advwdt_miscdev
);
if
(
wdt_stop
!=
wdt_start
)
if
(
!
request_region
(
wdt_stop
,
1
,
"Advantech WDT"
))
{
misc_deregister
(
&
advwdt_miscdev
);
return
-
EIO
;
}
#endif
if
(
!
request_region
(
WDT_START
,
1
,
"Advantech WDT"
))
{
if
(
!
request_region
(
wdt_start
,
1
,
"Advantech WDT"
))
{
misc_deregister
(
&
advwdt_miscdev
);
#if WDT_START != WDT_STOP
release_region
(
WDT_STOP
,
1
);
#endif
if
(
wdt_stop
!=
wdt_start
)
release_region
(
wdt_stop
,
1
);
return
-
EIO
;
}
register_reboot_notifier
(
&
advwdt_notifier
);
...
...
@@ -271,14 +297,15 @@ advwdt_exit(void)
{
misc_deregister
(
&
advwdt_miscdev
);
unregister_reboot_notifier
(
&
advwdt_notifier
);
#if WDT_START != WDT_STOP
release_region
(
WDT_STOP
,
1
);
#endif
release_region
(
WDT_START
,
1
);
if
(
wdt_stop
!=
wdt_start
)
release_region
(
wdt_stop
,
1
);
release_region
(
wdt_start
,
1
);
}
module_init
(
advwdt_init
);
module_exit
(
advwdt_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Marek Michalkiewicz <marekm@linux.org.pl>"
);
MODULE_DESCRIPTION
(
"Advantech Single Board Computer WDT driver"
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment