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
bea9b7fa
Commit
bea9b7fa
authored
Aug 31, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
parents
5dbafd23
541aaffb
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
748 additions
and
131 deletions
+748
-131
drivers/char/watchdog/Kconfig
drivers/char/watchdog/Kconfig
+12
-0
drivers/char/watchdog/Makefile
drivers/char/watchdog/Makefile
+1
-0
drivers/char/watchdog/acquirewdt.c
drivers/char/watchdog/acquirewdt.c
+145
-83
drivers/char/watchdog/advantechwdt.c
drivers/char/watchdog/advantechwdt.c
+1
-1
drivers/char/watchdog/alim1535_wdt.c
drivers/char/watchdog/alim1535_wdt.c
+465
-0
drivers/char/watchdog/wafer5823wdt.c
drivers/char/watchdog/wafer5823wdt.c
+124
-47
No files found.
drivers/char/watchdog/Kconfig
View file @
bea9b7fa
...
@@ -346,6 +346,18 @@ config ALIM7101_WDT
...
@@ -346,6 +346,18 @@ config ALIM7101_WDT
module, say M here and read <file:Documentation/modules.txt>. Most
module, say M here and read <file:Documentation/modules.txt>. Most
people will say N.
people will say N.
config ALIM1535_WDT
tristate "ALi M1535 PMU Watchdog Timer"
depends on WATCHDOG
---help---
This is the driver for the hardware watchdog on the ALi M1535 PMU.
This driver is also available as a module ( = code which can be
inserted in and removed from the running kernel whenever you want).
The module is called alim1535_wdt. If you want to compile it as a
module, say M here and read <file:Documentation/modules.txt>. Most
people will say N.
config SC1200_WDT
config SC1200_WDT
tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog"
tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog"
depends on WATCHDOG
depends on WATCHDOG
...
...
drivers/char/watchdog/Makefile
View file @
bea9b7fa
...
@@ -27,6 +27,7 @@ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
...
@@ -27,6 +27,7 @@ obj-$(CONFIG_SOFT_WATCHDOG) += softdog.o
obj-$(CONFIG_W83877F_WDT)
+=
w83877f_wdt.o
obj-$(CONFIG_W83877F_WDT)
+=
w83877f_wdt.o
obj-$(CONFIG_SC520_WDT)
+=
sc520_wdt.o
obj-$(CONFIG_SC520_WDT)
+=
sc520_wdt.o
obj-$(CONFIG_ALIM7101_WDT)
+=
alim7101_wdt.o
obj-$(CONFIG_ALIM7101_WDT)
+=
alim7101_wdt.o
obj-$(CONFIG_ALIM1535_WDT)
+=
alim1535_wdt.o
obj-$(CONFIG_SC1200_WDT)
+=
sc1200wdt.o
obj-$(CONFIG_SC1200_WDT)
+=
sc1200wdt.o
obj-$(CONFIG_WAFER_WDT)
+=
wafer5823wdt.o
obj-$(CONFIG_WAFER_WDT)
+=
wafer5823wdt.o
obj-$(CONFIG_CPU5_WDT)
+=
cpu5wdt.o
obj-$(CONFIG_CPU5_WDT)
+=
cpu5wdt.o
...
...
drivers/char/watchdog/acquirewdt.c
View file @
bea9b7fa
/*
/*
* Acquire Single Board Computer Watchdog Timer driver
for Linux 2.1.x
* Acquire Single Board Computer Watchdog Timer driver
*
*
* Based on wdt.c. Original copyright messages:
* Based on wdt.c. Original copyright messages:
*
*
...
@@ -10,10 +10,10 @@
...
@@ -10,10 +10,10 @@
* modify it under the terms of the GNU General Public License
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* 2 of the License, or (at your option) any later version.
*
*
* Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
* Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
* warranty for any of this software. This material is provided
* warranty for any of this software. This material is provided
* "AS-IS" and at no charge.
* "AS-IS" and at no charge.
*
*
* (c) Copyright 1995 Alan Cox <alan@redhat.com>
* (c) Copyright 1995 Alan Cox <alan@redhat.com>
*
*
...
@@ -22,33 +22,39 @@
...
@@ -22,33 +22,39 @@
* Can't add timeout - driver doesn't allow changing value
* Can't add timeout - driver doesn't allow changing value
*/
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/types.h>
#include <linux/miscdevice.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/watchdog.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/ioport.h>
#include <linux/notifier.h>
#include <linux/notifier.h>
#include <linux/fs.h>
#include <linux/reboot.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <asm/io.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <asm/system.h>
#include <asm/system.h>
static
int
acq_is_open
;
#define WATCHDOG_NAME "Acquire WDT"
static
spinlock_t
acq_lock
;
#define PFX WATCHDOG_NAME ": "
static
int
expect_close
=
0
;
#define WATCHDOG_TIMEOUT 0
/* ??? Is the timeout hardcoded to 1 minute ??? */
static
unsigned
long
acq_is_open
;
static
char
expect_close
;
/*
/*
* You must set these - there is no sane way to probe for this board.
* You must set these - there is no sane way to probe for this board.
*/
*/
#define WDT_STOP 0x43
static
int
wdt_stop
=
0x43
;
#define WDT_START 0x443
module_param
(
wdt_stop
,
int
,
0
);
MODULE_PARM_DESC
(
wdt_stop
,
"Acquire WDT 'stop' io port (default 0x43)"
);
static
int
wdt_start
=
0x443
;
module_param
(
wdt_start
,
int
,
0
);
MODULE_PARM_DESC
(
wdt_start
,
"Acquire WDT 'start' io port (default 0x443)"
);
#ifdef CONFIG_WATCHDOG_NOWAYOUT
#ifdef CONFIG_WATCHDOG_NOWAYOUT
static
int
nowayout
=
1
;
static
int
nowayout
=
1
;
...
@@ -62,38 +68,52 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
...
@@ -62,38 +68,52 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
/*
/*
* Kernel methods.
* Kernel methods.
*/
*/
static
void
acq_ping
(
void
)
static
void
acq_ping
(
void
)
{
{
/* Write a watchdog value */
/* Write a watchdog value */
inb_p
(
WDT_START
);
inb_p
(
wdt_start
);
}
}
static
void
acq_stop
(
void
)
{
/* Turn the card off */
inb_p
(
wdt_stop
);
}
/*
* /dev/watchdog handling.
*/
static
ssize_t
acq_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
acq_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
{
{
/* Can't seek (pwrite) on this device */
/* Can't seek (pwrite) on this device */
if
(
ppos
!=
&
file
->
f_pos
)
if
(
ppos
!=
&
file
->
f_pos
)
return
-
ESPIPE
;
return
-
ESPIPE
;
/* See if we got the magic character 'V' and reload the timer */
if
(
count
)
{
if
(
count
)
{
if
(
!
nowayout
)
{
if
(
!
nowayout
)
{
size_t
i
;
size_t
i
;
/* note: just in case someone wrote the magic character
* five months ago... */
expect_close
=
0
;
expect_close
=
0
;
/* scan to see wether or not we got the magic character */
for
(
i
=
0
;
i
!=
count
;
i
++
)
{
for
(
i
=
0
;
i
!=
count
;
i
++
)
{
char
c
;
char
c
;
if
(
get_user
(
c
,
buf
+
i
))
if
(
get_user
(
c
,
buf
+
i
))
return
-
EFAULT
;
return
-
EFAULT
;
if
(
c
==
'V'
)
if
(
c
==
'V'
)
expect_close
=
1
;
expect_close
=
42
;
}
}
}
}
/* Well, anyhow someone wrote to us, we should return that favour */
acq_ping
();
acq_ping
();
return
1
;
}
}
return
0
;
return
count
;
}
}
static
int
acq_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
static
int
acq_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
...
@@ -103,65 +123,75 @@ static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
...
@@ -103,65 +123,75 @@ static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
{
{
.
options
=
WDIOF_KEEPALIVEPING
|
WDIOF_MAGICCLOSE
,
.
options
=
WDIOF_KEEPALIVEPING
|
WDIOF_MAGICCLOSE
,
.
firmware_version
=
1
,
.
firmware_version
=
1
,
.
identity
=
"Acquire WDT"
.
identity
=
"Acquire WDT"
,
};
};
switch
(
cmd
)
switch
(
cmd
)
{
{
case
WDIOC_GETSUPPORT
:
case
WDIOC_GETSUPPORT
:
if
(
copy_to_user
((
struct
watchdog_info
*
)
arg
,
&
ident
,
sizeof
(
ident
)))
return
copy_to_user
((
struct
watchdog_info
*
)
arg
,
&
ident
,
sizeof
(
ident
))
?
-
EFAULT
:
0
;
return
-
EFAULT
;
break
;
case
WDIOC_GETSTATUS
:
case
WDIOC_GETSTATUS
:
if
(
copy_to_user
((
int
*
)
arg
,
&
acq_is_open
,
sizeof
(
int
)))
case
WDIOC_GETBOOTSTATUS
:
return
-
EFAULT
;
return
put_user
(
0
,
(
int
*
)
arg
);
break
;
case
WDIOC_KEEPALIVE
:
case
WDIOC_KEEPALIVE
:
acq_ping
();
acq_ping
();
break
;
return
0
;
case
WDIOC_GETTIMEOUT
:
return
put_user
(
WATCHDOG_TIMEOUT
,
(
int
*
)
arg
);
case
WDIOC_SETOPTIONS
:
{
int
options
,
retval
=
-
EINVAL
;
if
(
get_user
(
options
,
(
int
*
)
arg
))
return
-
EFAULT
;
if
(
options
&
WDIOS_DISABLECARD
)
{
acq_stop
();
retval
=
0
;
}
if
(
options
&
WDIOS_ENABLECARD
)
{
acq_ping
();
retval
=
0
;
}
return
retval
;
}
default:
default:
return
-
ENO
TTY
;
return
-
ENO
IOCTLCMD
;
}
}
return
0
;
}
}
static
int
acq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
acq_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
{
if
((
iminor
(
inode
)
==
WATCHDOG_MINOR
))
{
if
(
test_and_set_bit
(
0
,
&
acq_is_open
))
spin_lock
(
&
acq_lock
);
return
-
EBUSY
;
if
(
acq_is_open
)
{
spin_unlock
(
&
acq_lock
);
return
-
EBUSY
;
}
if
(
nowayout
)
__module_get
(
THIS_MODULE
);
/* Activate */
if
(
nowayout
)
acq_is_open
=
1
;
__module_get
(
THIS_MODULE
);
inb_p
(
WDT_START
);
spin_unlock
(
&
acq_lock
);
return
0
;
}
else
{
/* Activate */
return
-
ENODEV
;
acq_ping
()
;
}
return
0
;
}
}
static
int
acq_close
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
acq_close
(
struct
inode
*
inode
,
struct
file
*
file
)
{
{
if
(
iminor
(
inode
)
==
WATCHDOG_MINOR
)
{
if
(
expect_close
==
42
)
{
spin_lock
(
&
acq_lock
);
acq_stop
();
if
(
expect_close
)
}
else
{
inb_p
(
WDT_STOP
);
printk
(
KERN_CRIT
PFX
"Unexpected close, not stopping watchdog!
\n
"
);
else
acq_ping
();
printk
(
KERN_CRIT
"WDT closed unexpectedly. WDT will not stop!
\n
"
);
acq_is_open
=
0
;
spin_unlock
(
&
acq_lock
);
}
}
clear_bit
(
0
,
&
acq_is_open
);
expect_close
=
0
;
return
0
;
return
0
;
}
}
...
@@ -172,20 +202,20 @@ static int acq_close(struct inode *inode, struct file *file)
...
@@ -172,20 +202,20 @@ static int acq_close(struct inode *inode, struct file *file)
static
int
acq_notify_sys
(
struct
notifier_block
*
this
,
unsigned
long
code
,
static
int
acq_notify_sys
(
struct
notifier_block
*
this
,
unsigned
long
code
,
void
*
unused
)
void
*
unused
)
{
{
if
(
code
==
SYS_DOWN
||
code
==
SYS_HALT
)
if
(
code
==
SYS_DOWN
||
code
==
SYS_HALT
)
{
/* Turn the
card
off */
/* Turn the
WDT
off */
inb_p
(
WDT_STOP
);
acq_stop
(
);
}
return
NOTIFY_DONE
;
return
NOTIFY_DONE
;
}
}
/*
/*
* Kernel Interfaces
* Kernel Interfaces
*/
*/
static
struct
file_operations
acq_fops
=
{
static
struct
file_operations
acq_fops
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
llseek
=
no_llseek
,
.
write
=
acq_write
,
.
write
=
acq_write
,
.
ioctl
=
acq_ioctl
,
.
ioctl
=
acq_ioctl
,
.
open
=
acq_open
,
.
open
=
acq_open
,
...
@@ -196,52 +226,84 @@ static struct miscdevice acq_miscdev=
...
@@ -196,52 +226,84 @@ static struct miscdevice acq_miscdev=
{
{
.
minor
=
WATCHDOG_MINOR
,
.
minor
=
WATCHDOG_MINOR
,
.
name
=
"watchdog"
,
.
name
=
"watchdog"
,
.
fops
=
&
acq_fops
.
fops
=
&
acq_fops
,
};
};
/*
/*
* The WDT card needs to learn about soft shutdowns in order to
* The WDT card needs to learn about soft shutdowns in order to
* turn the timebomb registers off.
* turn the timebomb registers off.
*/
*/
static
struct
notifier_block
acq_notifier
=
static
struct
notifier_block
acq_notifier
=
{
{
.
notifier_call
=
acq_notify_sys
,
.
notifier_call
=
acq_notify_sys
,
.
next
=
NULL
,
.
next
=
NULL
,
.
priority
=
0
.
priority
=
0
,
};
};
static
int
__init
acq_init
(
void
)
static
int
__init
acq_init
(
void
)
{
{
int
ret
;
printk
(
KERN_INFO
"WDT driver for Acquire single board computer initialising.
\n
"
);
printk
(
KERN_INFO
"WDT driver for Acquire single board computer initialising.
\n
"
);
spin_lock_init
(
&
acq_lock
);
if
(
wdt_stop
!=
wdt_start
)
{
if
(
misc_register
(
&
acq_miscdev
))
if
(
!
request_region
(
wdt_stop
,
1
,
WATCHDOG_NAME
))
{
return
-
ENODEV
;
printk
(
KERN_ERR
PFX
"I/O address 0x%04x already in use
\n
"
,
if
(
!
request_region
(
WDT_STOP
,
1
,
"Acquire WDT"
))
{
wdt_stop
);
misc_deregister
(
&
acq_miscdev
);
ret
=
-
EIO
;
return
-
EIO
;
goto
out
;
}
}
}
if
(
!
request_region
(
WDT_START
,
1
,
"Acquire WDT"
))
{
release_region
(
WDT_STOP
,
1
);
if
(
!
request_region
(
wdt_start
,
1
,
WATCHDOG_NAME
))
{
misc_deregister
(
&
acq_miscdev
);
printk
(
KERN_ERR
PFX
"I/O address 0x%04x already in use
\n
"
,
return
-
EIO
;
wdt_start
);
ret
=
-
EIO
;
goto
unreg_stop
;
}
}
register_reboot_notifier
(
&
acq_notifier
);
ret
=
register_reboot_notifier
(
&
acq_notifier
);
return
0
;
if
(
ret
!=
0
)
{
printk
(
KERN_ERR
PFX
"cannot register reboot notifier (err=%d)
\n
"
,
ret
);
goto
unreg_regions
;
}
ret
=
misc_register
(
&
acq_miscdev
);
if
(
ret
!=
0
)
{
printk
(
KERN_ERR
PFX
"cannot register miscdev on minor=%d (err=%d)
\n
"
,
WATCHDOG_MINOR
,
ret
);
goto
unreg_reboot
;
}
printk
(
KERN_INFO
PFX
"initialized. (nowayout=%d)
\n
"
,
nowayout
);
out:
return
ret
;
unreg_reboot:
unregister_reboot_notifier
(
&
acq_notifier
);
unreg_regions:
release_region
(
wdt_start
,
1
);
unreg_stop:
if
(
wdt_stop
!=
wdt_start
)
release_region
(
wdt_stop
,
1
);
goto
out
;
}
}
static
void
__exit
acq_exit
(
void
)
static
void
__exit
acq_exit
(
void
)
{
{
misc_deregister
(
&
acq_miscdev
);
misc_deregister
(
&
acq_miscdev
);
unregister_reboot_notifier
(
&
acq_notifier
);
unregister_reboot_notifier
(
&
acq_notifier
);
release_region
(
WDT_STOP
,
1
);
if
(
wdt_stop
!=
wdt_start
)
release_region
(
WDT_START
,
1
);
release_region
(
wdt_stop
,
1
);
release_region
(
wdt_start
,
1
);
}
}
module_init
(
acq_init
);
module_init
(
acq_init
);
module_exit
(
acq_exit
);
module_exit
(
acq_exit
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_AUTHOR
(
"Unkown"
);
MODULE_DESCRIPTION
(
"Acquire Single Board Computer Watchdog Timer driver"
);
drivers/char/watchdog/advantechwdt.c
View file @
bea9b7fa
...
@@ -133,7 +133,7 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
...
@@ -133,7 +133,7 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
static
struct
watchdog_info
ident
=
{
static
struct
watchdog_info
ident
=
{
.
options
=
WDIOF_KEEPALIVEPING
|
WDIOF_SETTIMEOUT
|
WDIOF_MAGICCLOSE
,
.
options
=
WDIOF_KEEPALIVEPING
|
WDIOF_SETTIMEOUT
|
WDIOF_MAGICCLOSE
,
.
firmware_version
=
1
,
.
firmware_version
=
1
,
.
identity
=
"Advantech WDT"
.
identity
=
"Advantech WDT"
,
};
};
switch
(
cmd
)
{
switch
(
cmd
)
{
...
...
drivers/char/watchdog/alim1535_wdt.c
0 → 100644
View file @
bea9b7fa
This diff is collapsed.
Click to expand it.
drivers/char/watchdog/wafer5823wdt.c
View file @
bea9b7fa
/*
/*
* ICP Wafer 5823 Single Board Computer WDT driver
for Linux 2.4.x
* ICP Wafer 5823 Single Board Computer WDT driver
* http://www.icpamerica.com/wafer_5823.php
* http://www.icpamerica.com/wafer_5823.php
* May also work on other similar models
* May also work on other similar models
*
*
...
@@ -17,10 +17,10 @@
...
@@ -17,10 +17,10 @@
* modify it under the terms of the GNU General Public License
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* 2 of the License, or (at your option) any later version.
*
*
* Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
* Neither Alan Cox nor CymruNet Ltd. admit liability nor provide
* warranty for any of this software. This material is provided
* warranty for any of this software. This material is provided
* "AS-IS" and at no charge.
* "AS-IS" and at no charge.
*
*
* (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>
* (c) Copyright 1995 Alan Cox <alan@lxorguk.ukuu.org.uk>
*
*
...
@@ -39,9 +39,13 @@
...
@@ -39,9 +39,13 @@
#include <asm/io.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#define WATCHDOG_NAME "Wafer 5823 WDT"
#define PFX WATCHDOG_NAME ": "
#define WD_TIMO 60
/* 60 sec default timeout */
static
unsigned
long
wafwdt_is_open
;
static
unsigned
long
wafwdt_is_open
;
static
char
expect_close
;
static
spinlock_t
wafwdt_lock
;
static
spinlock_t
wafwdt_lock
;
static
int
expect_close
=
0
;
/*
/*
* You must set these - there is no sane way to probe for this board.
* You must set these - there is no sane way to probe for this board.
...
@@ -52,11 +56,17 @@ static int expect_close = 0;
...
@@ -52,11 +56,17 @@ static int expect_close = 0;
* to restart it again.
* to restart it again.
*/
*/
#define WDT_START 0x443
static
int
wdt_stop
=
0x843
;
#define WDT_STOP 0x843
module_param
(
wdt_stop
,
int
,
0
);
MODULE_PARM_DESC
(
wdt_stop
,
"Wafer 5823 WDT 'stop' io port (default 0x843)"
);
static
int
wdt_start
=
0x443
;
module_param
(
wdt_start
,
int
,
0
);
MODULE_PARM_DESC
(
wdt_start
,
"Wafer 5823 WDT 'start' io port (default 0x443)"
);
#define WD_TIMO 60
/* 1 minute */
static
int
timeout
=
WD_TIMO
;
/* in seconds */
static
int
wd_margin
=
WD_TIMO
;
module_param
(
timeout
,
int
,
0
);
MODULE_PARM_DESC
(
timeout
,
"Watchdog timeout in seconds. 1<= timeout <=255, default="
__MODULE_STRING
(
WD_TIMO
)
"."
);
#ifdef CONFIG_WATCHDOG_NOWAYOUT
#ifdef CONFIG_WATCHDOG_NOWAYOUT
static
int
nowayout
=
1
;
static
int
nowayout
=
1
;
...
@@ -70,24 +80,24 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
...
@@ -70,24 +80,24 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON
static
void
wafwdt_ping
(
void
)
static
void
wafwdt_ping
(
void
)
{
{
/* pat watchdog */
/* pat watchdog */
spin_lock
(
&
wafwdt_lock
);
spin_lock
(
&
wafwdt_lock
);
inb_p
(
WDT_STOP
);
inb_p
(
wdt_stop
);
inb_p
(
WDT_START
);
inb_p
(
wdt_start
);
spin_unlock
(
&
wafwdt_lock
);
spin_unlock
(
&
wafwdt_lock
);
}
}
static
void
wafwdt_start
(
void
)
static
void
wafwdt_start
(
void
)
{
{
/* start up watchdog */
/* start up watchdog */
outb_p
(
wd_margin
,
WDT_START
);
outb_p
(
timeout
,
wdt_start
);
inb_p
(
WDT_START
);
inb_p
(
wdt_start
);
}
}
static
void
static
void
wafwdt_stop
(
void
)
wafwdt_stop
(
void
)
{
{
/* stop watchdog */
/* stop watchdog */
inb_p
(
WDT_STOP
);
inb_p
(
wdt_stop
);
}
}
static
ssize_t
wafwdt_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
static
ssize_t
wafwdt_write
(
struct
file
*
file
,
const
char
*
buf
,
size_t
count
,
loff_t
*
ppos
)
...
@@ -96,6 +106,7 @@ static ssize_t wafwdt_write(struct file *file, const char *buf, size_t count, lo
...
@@ -96,6 +106,7 @@ static ssize_t wafwdt_write(struct file *file, const char *buf, size_t count, lo
if
(
ppos
!=
&
file
->
f_pos
)
if
(
ppos
!=
&
file
->
f_pos
)
return
-
ESPIPE
;
return
-
ESPIPE
;
/* See if we got the magic character 'V' and reload the timer */
if
(
count
)
{
if
(
count
)
{
if
(
!
nowayout
)
{
if
(
!
nowayout
)
{
size_t
i
;
size_t
i
;
...
@@ -103,30 +114,30 @@ static ssize_t wafwdt_write(struct file *file, const char *buf, size_t count, lo
...
@@ -103,30 +114,30 @@ static ssize_t wafwdt_write(struct file *file, const char *buf, size_t count, lo
/* In case it was set long ago */
/* In case it was set long ago */
expect_close
=
0
;
expect_close
=
0
;
/* scan to see wether or not we got the magic character */
for
(
i
=
0
;
i
!=
count
;
i
++
)
{
for
(
i
=
0
;
i
!=
count
;
i
++
)
{
char
c
;
char
c
;
if
(
get_user
(
c
,
buf
+
i
))
if
(
get_user
(
c
,
buf
+
i
))
return
-
EFAULT
;
return
-
EFAULT
;
if
(
c
==
'V'
)
if
(
c
==
'V'
)
expect_close
=
1
;
expect_close
=
42
;
}
}
}
}
/* Well, anyhow someone wrote to us, we should return that favour */
wafwdt_ping
();
wafwdt_ping
();
return
1
;
}
}
return
0
;
return
count
;
}
}
static
int
wafwdt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
static
int
wafwdt_ioctl
(
struct
inode
*
inode
,
struct
file
*
file
,
unsigned
int
cmd
,
unsigned
long
arg
)
unsigned
long
arg
)
{
{
int
new_
margin
;
int
new_
timeout
;
static
struct
watchdog_info
ident
=
{
static
struct
watchdog_info
ident
=
{
.
options
=
WDIOF_KEEPALIVEPING
|
WDIOF_SETTIMEOUT
|
WDIOF_MAGICCLOSE
,
.
options
=
WDIOF_KEEPALIVEPING
|
WDIOF_SETTIMEOUT
|
WDIOF_MAGICCLOSE
,
.
firmware_version
=
1
,
.
firmware_version
=
1
,
.
identity
=
"Wafer 5823 WDT"
.
identity
=
"Wafer 5823 WDT"
,
};
};
int
one
=
1
;
switch
(
cmd
)
{
switch
(
cmd
)
{
case
WDIOC_GETSUPPORT
:
case
WDIOC_GETSUPPORT
:
...
@@ -136,25 +147,44 @@ static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd
...
@@ -136,25 +147,44 @@ static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd
break
;
break
;
case
WDIOC_GETSTATUS
:
case
WDIOC_GETSTATUS
:
if
(
copy_to_user
((
int
*
)
arg
,
&
one
,
sizeof
(
int
)))
case
WDIOC_GETBOOTSTATUS
:
return
-
EFAULT
;
return
put_user
(
0
,
(
int
*
)
arg
);
break
;
case
WDIOC_KEEPALIVE
:
case
WDIOC_KEEPALIVE
:
wafwdt_ping
();
wafwdt_ping
();
break
;
break
;
case
WDIOC_SETTIMEOUT
:
case
WDIOC_SETTIMEOUT
:
if
(
get_user
(
new_
margin
,
(
int
*
)
arg
))
if
(
get_user
(
new_
timeout
,
(
int
*
)
arg
))
return
-
EFAULT
;
return
-
EFAULT
;
if
((
new_
margin
<
1
)
||
(
new_margin
>
255
))
if
((
new_
timeout
<
1
)
||
(
new_timeout
>
255
))
return
-
EINVAL
;
return
-
EINVAL
;
wd_margin
=
new_margin
;
timeout
=
new_timeout
;
wafwdt_stop
();
wafwdt_stop
();
wafwdt_start
();
wafwdt_start
();
/* Fall */
/* Fall */
case
WDIOC_GETTIMEOUT
:
case
WDIOC_GETTIMEOUT
:
return
put_user
(
wd_margin
,
(
int
*
)
arg
);
return
put_user
(
timeout
,
(
int
*
)
arg
);
case
WDIOC_SETOPTIONS
:
{
int
options
,
retval
=
-
EINVAL
;
if
(
get_user
(
options
,
(
int
*
)
arg
))
return
-
EFAULT
;
if
(
options
&
WDIOS_DISABLECARD
)
{
wafwdt_start
();
retval
=
0
;
}
if
(
options
&
WDIOS_ENABLECARD
)
{
wafwdt_stop
();
retval
=
0
;
}
return
retval
;
}
default:
default:
return
-
ENOTTY
;
return
-
ENOTTY
;
...
@@ -166,6 +196,10 @@ static int wafwdt_open(struct inode *inode, struct file *file)
...
@@ -166,6 +196,10 @@ static int wafwdt_open(struct inode *inode, struct file *file)
{
{
if
(
test_and_set_bit
(
0
,
&
wafwdt_is_open
))
if
(
test_and_set_bit
(
0
,
&
wafwdt_is_open
))
return
-
EBUSY
;
return
-
EBUSY
;
/*
* Activate
*/
wafwdt_start
();
wafwdt_start
();
return
0
;
return
0
;
}
}
...
@@ -173,12 +207,14 @@ static int wafwdt_open(struct inode *inode, struct file *file)
...
@@ -173,12 +207,14 @@ static int wafwdt_open(struct inode *inode, struct file *file)
static
int
static
int
wafwdt_close
(
struct
inode
*
inode
,
struct
file
*
file
)
wafwdt_close
(
struct
inode
*
inode
,
struct
file
*
file
)
{
{
clear_bit
(
0
,
&
wafwdt_is_open
);
if
(
expect_close
==
42
)
{
if
(
expect_close
)
{
wafwdt_stop
();
wafwdt_stop
();
}
else
{
}
else
{
printk
(
KERN_CRIT
"WDT device closed unexpectedly. WDT will not stop!
\n
"
);
printk
(
KERN_CRIT
PFX
"WDT device closed unexpectedly. WDT will not stop!
\n
"
);
wafwdt_ping
();
}
}
clear_bit
(
0
,
&
wafwdt_is_open
);
expect_close
=
0
;
return
0
;
return
0
;
}
}
...
@@ -201,6 +237,7 @@ static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code, vo
...
@@ -201,6 +237,7 @@ static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code, vo
static
struct
file_operations
wafwdt_fops
=
{
static
struct
file_operations
wafwdt_fops
=
{
.
owner
=
THIS_MODULE
,
.
owner
=
THIS_MODULE
,
.
llseek
=
no_llseek
,
.
write
=
wafwdt_write
,
.
write
=
wafwdt_write
,
.
ioctl
=
wafwdt_ioctl
,
.
ioctl
=
wafwdt_ioctl
,
.
open
=
wafwdt_open
,
.
open
=
wafwdt_open
,
...
@@ -210,53 +247,93 @@ static struct file_operations wafwdt_fops = {
...
@@ -210,53 +247,93 @@ static struct file_operations wafwdt_fops = {
static
struct
miscdevice
wafwdt_miscdev
=
{
static
struct
miscdevice
wafwdt_miscdev
=
{
.
minor
=
WATCHDOG_MINOR
,
.
minor
=
WATCHDOG_MINOR
,
.
name
=
"watchdog"
,
.
name
=
"watchdog"
,
.
fops
=
&
wafwdt_fops
.
fops
=
&
wafwdt_fops
,
};
};
/*
/*
* The WDT needs to learn about soft shutdowns in order to
* The WDT needs to learn about soft shutdowns in order to
* turn the timebomb registers off.
* turn the timebomb registers off.
*/
*/
static
struct
notifier_block
wafwdt_notifier
=
{
static
struct
notifier_block
wafwdt_notifier
=
{
.
notifier_call
=
wafwdt_notify_sys
,
.
notifier_call
=
wafwdt_notify_sys
,
.
next
=
NULL
,
.
next
=
NULL
,
.
priority
=
0
.
priority
=
0
,
};
};
static
int
__init
wafwdt_init
(
void
)
static
int
__init
wafwdt_init
(
void
)
{
{
int
ret
;
printk
(
KERN_INFO
"WDT driver for Wafer 5823 single board computer initialising.
\n
"
);
printk
(
KERN_INFO
"WDT driver for Wafer 5823 single board computer initialising.
\n
"
);
spin_lock_init
(
&
wafwdt_lock
);
spin_lock_init
(
&
wafwdt_lock
);
if
(
!
request_region
(
WDT_STOP
,
1
,
"Wafer 5823 WDT"
))
goto
error
;
if
(
timeout
<
1
||
timeout
>
63
)
{
if
(
!
request_region
(
WDT_START
,
1
,
"Wafer 5823 WDT"
))
timeout
=
WD_TIMO
;
printk
(
KERN_INFO
PFX
"timeout value must be 1<=x<=255, using %d
\n
"
,
timeout
);
}
if
(
wdt_stop
!=
wdt_start
)
{
if
(
!
request_region
(
wdt_stop
,
1
,
"Wafer 5823 WDT"
))
{
printk
(
KERN_ERR
PFX
"I/O address 0x%04x already in use
\n
"
,
wdt_stop
);
ret
=
-
EIO
;
goto
error
;
}
}
if
(
!
request_region
(
wdt_start
,
1
,
"Wafer 5823 WDT"
))
{
printk
(
KERN_ERR
PFX
"I/O address 0x%04x already in use
\n
"
,
wdt_start
);
ret
=
-
EIO
;
goto
error2
;
goto
error2
;
if
(
misc_register
(
&
wafwdt_miscdev
)
<
0
)
}
ret
=
register_reboot_notifier
(
&
wafwdt_notifier
);
if
(
ret
!=
0
)
{
printk
(
KERN_ERR
PFX
"cannot register reboot notifier (err=%d)
\n
"
,
ret
);
goto
error3
;
goto
error3
;
register_reboot_notifier
(
&
wafwdt_notifier
);
}
return
0
;
ret
=
misc_register
(
&
wafwdt_miscdev
);
if
(
ret
!=
0
)
{
printk
(
KERN_ERR
PFX
"cannot register miscdev on minor=%d (err=%d)
\n
"
,
WATCHDOG_MINOR
,
ret
);
goto
error4
;
}
printk
(
KERN_INFO
PFX
"initialized. timeout=%d sec (nowayout=%d)
\n
"
,
timeout
,
nowayout
);
return
ret
;
error4:
unregister_reboot_notifier
(
&
wafwdt_notifier
);
error3:
error3:
release_region
(
WDT_START
,
1
);
release_region
(
wdt_start
,
1
);
error2:
error2:
release_region
(
WDT_STOP
,
1
);
if
(
wdt_stop
!=
wdt_start
)
release_region
(
wdt_stop
,
1
);
error:
error:
return
-
ENODEV
;
return
ret
;
}
}
static
void
__exit
wafwdt_exit
(
void
)
static
void
__exit
wafwdt_exit
(
void
)
{
{
misc_deregister
(
&
wafwdt_miscdev
);
misc_deregister
(
&
wafwdt_miscdev
);
unregister_reboot_notifier
(
&
wafwdt_notifier
);
unregister_reboot_notifier
(
&
wafwdt_notifier
);
release_region
(
WDT_STOP
,
1
);
if
(
wdt_stop
!=
wdt_start
)
release_region
(
WDT_START
,
1
);
release_region
(
wdt_stop
,
1
);
release_region
(
wdt_start
,
1
);
}
}
module_init
(
wafwdt_init
);
module_init
(
wafwdt_init
);
module_exit
(
wafwdt_exit
);
module_exit
(
wafwdt_exit
);
MODULE_AUTHOR
(
"Justin Cormack"
);
MODULE_AUTHOR
(
"Justin Cormack"
);
MODULE_DESCRIPTION
(
"ICP Wafer 5823 Single Board Computer WDT driver"
);
MODULE_LICENSE
(
"GPL"
);
MODULE_LICENSE
(
"GPL"
);
/* end of wafer5823wdt.c */
/* end of wafer5823wdt.c */
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