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
d524c5e2
Commit
d524c5e2
authored
Feb 12, 2006
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge master.kernel.org:/pub/scm/linux/kernel/git/wim/linux-2.6-watchdog
parents
19bf9cbf
a7122f91
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
239 additions
and
223 deletions
+239
-223
drivers/char/watchdog/pcwd.c
drivers/char/watchdog/pcwd.c
+232
-218
drivers/char/watchdog/sa1100_wdt.c
drivers/char/watchdog/sa1100_wdt.c
+7
-5
No files found.
drivers/char/watchdog/pcwd.c
View file @
d524c5e2
...
...
@@ -49,29 +49,37 @@
* More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/
*/
#include <linux/
module.h>
#include <linux/module
param.h>
#include <linux/
types.h>
#include <linux/t
imer.h>
#include <linux/
jiffies.h>
#include <linux/
config.h>
#include <linux/
wait.h>
#include <linux/
slab.h>
#include <linux/
ioport.h>
#include <linux/
delay.h>
#include <linux/
fs.h>
#include <linux/
miscdevice.h>
#include <linux/
watchdog.h>
#include <linux/
notifier.h>
#include <linux/
init.h>
#include <linux/
spinlock.h>
#include <linux/
reboot.h>
#include <linux/
config.h>
/* For CONFIG_WATCHDOG_NOWAYOUT/... */
#include <linux/module
.h>
/* For module specific items */
#include <linux/
moduleparam.h>
/* For new moduleparam's */
#include <linux/t
ypes.h>
/* For standard types (like size_t) */
#include <linux/
errno.h>
/* For the -ENODEV/... values */
#include <linux/
kernel.h>
/* For printk/panic/... */
#include <linux/
delay.h>
/* For mdelay function */
#include <linux/
timer.h>
/* For timer related operations */
#include <linux/
jiffies.h>
/* For jiffies stuff */
#include <linux/
miscdevice.h>
/* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
#include <linux/
watchdog.h>
/* For the watchdog specific items */
#include <linux/
notifier.h>
/* For notifier support */
#include <linux/
reboot.h>
/* For reboot_notifier stuff */
#include <linux/
init.h>
/* For __init/__exit/... */
#include <linux/
fs.h>
/* For file operations */
#include <linux/
ioport.h>
/* For io-port access */
#include <linux/
spinlock.h>
/* For spin_lock/spin_unlock/... */
#include <linux/sched.h>
/* TASK_INTERRUPTIBLE, set_current_state() and friends */
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/slab.h>
/* For kmalloc */
#define WD_VER "1.16 (06/12/2004)"
#define PFX "pcwd: "
#include <asm/uaccess.h>
/* For copy_to_user/put_user/... */
#include <asm/io.h>
/* For inb/outb/... */
/* Module and version information */
#define WATCHDOG_VERSION "1.16"
#define WATCHDOG_DATE "03 Jan 2006"
#define WATCHDOG_DRIVER_NAME "ISA-PC Watchdog"
#define WATCHDOG_NAME "pcwd"
#define PFX WATCHDOG_NAME ": "
#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n"
#define WD_VER WATCHDOG_VERSION " (" WATCHDOG_DATE ")"
/*
* It should be noted that PCWD_REVISION_B was removed because A and B
...
...
@@ -85,21 +93,23 @@
/*
* These are the defines that describe the control status bits for the
* PC Watchdog card, revision A.
*/
* PCI-PC Watchdog card.
*/
/* Port 1 : Control Status #1 for the PC Watchdog card, revision A. */
#define WD_WDRST 0x01
/* Previously reset state */
#define WD_T110 0x02
/* Temperature overheat sense */
#define WD_HRTBT 0x04
/* Heartbeat sense */
#define WD_RLY2 0x08
/* External relay triggered */
#define WD_SRLY2 0x80
/* Software external relay triggered */
/*
* These are the defines that describe the control status bits for the
* PC Watchdog card, revision C.
*/
/* Port 1 : Control Status #1 for the PC Watchdog card, revision C. */
#define WD_REVC_WTRP 0x01
/* Watchdog Trip status */
#define WD_REVC_HRBT 0x02
/* Watchdog Heartbeat */
#define WD_REVC_TTRP 0x04
/* Temperature Trip status */
/* Port 2 : Control Status #2 */
#define WD_WDIS 0x10
/* Watchdog Disabled */
#define WD_ENTP 0x20
/* Watchdog Enable Temperature Trip */
#define WD_SSEL 0x40
/* Watchdog Switch Select (1:SW1 <-> 0:SW2) */
#define WD_WCMD 0x80
/* Watchdog Command Mode */
/* max. time we give an ISA watchdog card to process a command */
/* 500ms for each 4 bit response (according to spec.) */
...
...
@@ -130,15 +140,17 @@ static int cards_found;
/* internal variables */
static
atomic_t
open_allowed
=
ATOMIC_INIT
(
1
);
static
char
expect_close
;
static
struct
timer_list
timer
;
static
unsigned
long
next_heartbeat
;
static
int
temp_panic
;
static
int
revision
;
/* The card's revision */
static
int
supports_temp
;
/* Wether or not the card has a temperature device */
static
int
command_mode
;
/* Wether or not the card is in command mode */
static
int
initial_status
;
/* The card's boot status */
static
int
current_readport
;
/* The cards I/O address */
static
spinlock_t
io_lock
;
static
struct
{
/* this is private data for each ISA-PC watchdog card */
int
revision
;
/* The card's revision */
int
supports_temp
;
/* Wether or not the card has a temperature device */
int
command_mode
;
/* Wether or not the card is in command mode */
int
boot_status
;
/* The card's boot status */
int
io_addr
;
/* The cards I/O address */
spinlock_t
io_lock
;
/* the lock for io operations */
struct
timer_list
timer
;
/* The timer that pings the watchdog */
unsigned
long
next_heartbeat
;
/* the next_heartbeat for the timer */
}
pcwd_private
;
/* module parameters */
#define WATCHDOG_HEARTBEAT 60
/* 60 sec default heartbeat */
...
...
@@ -161,14 +173,14 @@ static int send_isa_command(int cmd)
int
port0
,
last_port0
;
/* Double read for stabilising */
/* The WCMD bit must be 1 and the command is only 4 bits in size */
control_status
=
(
cmd
&
0x0F
)
|
0x80
;
outb_p
(
control_status
,
current_readport
+
2
);
control_status
=
(
cmd
&
0x0F
)
|
WD_WCMD
;
outb_p
(
control_status
,
pcwd_private
.
io_addr
+
2
);
udelay
(
ISA_COMMAND_TIMEOUT
);
port0
=
inb_p
(
current_readport
);
port0
=
inb_p
(
pcwd_private
.
io_addr
);
for
(
i
=
0
;
i
<
25
;
++
i
)
{
last_port0
=
port0
;
port0
=
inb_p
(
current_readport
);
port0
=
inb_p
(
pcwd_private
.
io_addr
);
if
(
port0
==
last_port0
)
break
;
/* Data is stable */
...
...
@@ -184,7 +196,7 @@ static int set_command_mode(void)
int
i
,
found
=
0
,
count
=
0
;
/* Set the card into command mode */
spin_lock
(
&
io_lock
);
spin_lock
(
&
pcwd_private
.
io_lock
);
while
((
!
found
)
&&
(
count
<
3
))
{
i
=
send_isa_command
(
CMD_ISA_IDLE
);
...
...
@@ -192,15 +204,15 @@ static int set_command_mode(void)
found
=
1
;
else
if
(
i
==
0xF3
)
{
/* Card does not like what we've done to it */
outb_p
(
0x00
,
current_readport
+
2
);
outb_p
(
0x00
,
pcwd_private
.
io_addr
+
2
);
udelay
(
1200
);
/* Spec says wait 1ms */
outb_p
(
0x00
,
current_readport
+
2
);
outb_p
(
0x00
,
pcwd_private
.
io_addr
+
2
);
udelay
(
ISA_COMMAND_TIMEOUT
);
}
count
++
;
}
spin_unlock
(
&
io_lock
);
command_mode
=
found
;
spin_unlock
(
&
pcwd_private
.
io_lock
);
pcwd_private
.
command_mode
=
found
;
return
(
found
);
}
...
...
@@ -208,12 +220,95 @@ static int set_command_mode(void)
static
void
unset_command_mode
(
void
)
{
/* Set the card into normal mode */
spin_lock
(
&
io_lock
);
outb_p
(
0x00
,
current_readport
+
2
);
spin_lock
(
&
pcwd_private
.
io_lock
);
outb_p
(
0x00
,
pcwd_private
.
io_addr
+
2
);
udelay
(
ISA_COMMAND_TIMEOUT
);
spin_unlock
(
&
io_lock
);
spin_unlock
(
&
pcwd_private
.
io_lock
);
pcwd_private
.
command_mode
=
0
;
}
static
inline
void
pcwd_check_temperature_support
(
void
)
{
if
(
inb
(
pcwd_private
.
io_addr
)
!=
0xF0
)
pcwd_private
.
supports_temp
=
1
;
}
static
inline
char
*
get_firmware
(
void
)
{
int
one
,
ten
,
hund
,
minor
;
char
*
ret
;
ret
=
kmalloc
(
6
,
GFP_KERNEL
);
if
(
ret
==
NULL
)
return
NULL
;
if
(
set_command_mode
())
{
one
=
send_isa_command
(
CMD_ISA_VERSION_INTEGER
);
ten
=
send_isa_command
(
CMD_ISA_VERSION_TENTH
);
hund
=
send_isa_command
(
CMD_ISA_VERSION_HUNDRETH
);
minor
=
send_isa_command
(
CMD_ISA_VERSION_MINOR
);
sprintf
(
ret
,
"%c.%c%c%c"
,
one
,
ten
,
hund
,
minor
);
}
else
sprintf
(
ret
,
"ERROR"
);
unset_command_mode
();
return
(
ret
);
}
static
inline
int
pcwd_get_option_switches
(
void
)
{
int
option_switches
=
0
;
if
(
set_command_mode
())
{
/* Get switch settings */
option_switches
=
send_isa_command
(
CMD_ISA_SWITCH_SETTINGS
);
}
unset_command_mode
();
return
(
option_switches
);
}
static
void
pcwd_show_card_info
(
void
)
{
char
*
firmware
;
int
option_switches
;
/* Get some extra info from the hardware (in command/debug/diag mode) */
if
(
pcwd_private
.
revision
==
PCWD_REVISION_A
)
printk
(
KERN_INFO
PFX
"ISA-PC Watchdog (REV.A) detected at port 0x%04x
\n
"
,
pcwd_private
.
io_addr
);
else
if
(
pcwd_private
.
revision
==
PCWD_REVISION_C
)
{
firmware
=
get_firmware
();
printk
(
KERN_INFO
PFX
"ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)
\n
"
,
pcwd_private
.
io_addr
,
firmware
);
kfree
(
firmware
);
option_switches
=
pcwd_get_option_switches
();
printk
(
KERN_INFO
PFX
"Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s
\n
"
,
option_switches
,
((
option_switches
&
0x10
)
?
"ON"
:
"OFF"
),
((
option_switches
&
0x08
)
?
"ON"
:
"OFF"
));
/* Reprogram internal heartbeat to 2 seconds */
if
(
set_command_mode
())
{
send_isa_command
(
CMD_ISA_DELAY_TIME_2SECS
);
unset_command_mode
();
}
}
if
(
pcwd_private
.
supports_temp
)
printk
(
KERN_INFO
PFX
"Temperature Option Detected
\n
"
);
if
(
pcwd_private
.
boot_status
&
WDIOF_CARDRESET
)
printk
(
KERN_INFO
PFX
"Previous reboot was caused by the card
\n
"
);
if
(
pcwd_private
.
boot_status
&
WDIOF_OVERHEAT
)
{
printk
(
KERN_EMERG
PFX
"Card senses a CPU Overheat. Panicking!
\n
"
);
printk
(
KERN_EMERG
PFX
"CPU Overheat
\n
"
);
}
command_mode
=
0
;
if
(
pcwd_private
.
boot_status
==
0
)
printk
(
KERN_INFO
PFX
"No previous trip detected - Cold boot or reset
\n
"
);
}
static
void
pcwd_timer_ping
(
unsigned
long
data
)
...
...
@@ -222,25 +317,25 @@ static void pcwd_timer_ping(unsigned long data)
/* If we got a heartbeat pulse within the WDT_INTERVAL
* we agree to ping the WDT */
if
(
time_before
(
jiffies
,
next_heartbeat
))
{
if
(
time_before
(
jiffies
,
pcwd_private
.
next_heartbeat
))
{
/* Ping the watchdog */
spin_lock
(
&
io_lock
);
if
(
revision
==
PCWD_REVISION_A
)
{
spin_lock
(
&
pcwd_private
.
io_lock
);
if
(
pcwd_private
.
revision
==
PCWD_REVISION_A
)
{
/* Rev A cards are reset by setting the WD_WDRST bit in register 1 */
wdrst_stat
=
inb_p
(
current_readport
);
wdrst_stat
=
inb_p
(
pcwd_private
.
io_addr
);
wdrst_stat
&=
0x0F
;
wdrst_stat
|=
WD_WDRST
;
outb_p
(
wdrst_stat
,
current_readport
+
1
);
outb_p
(
wdrst_stat
,
pcwd_private
.
io_addr
+
1
);
}
else
{
/* Re-trigger watchdog by writing to port 0 */
outb_p
(
0x00
,
current_readport
);
outb_p
(
0x00
,
pcwd_private
.
io_addr
);
}
/* Re-set the timer interval */
mod_timer
(
&
timer
,
jiffies
+
WDT_INTERVAL
);
mod_timer
(
&
pcwd_private
.
timer
,
jiffies
+
WDT_INTERVAL
);
spin_unlock
(
&
io_lock
);
spin_unlock
(
&
pcwd_private
.
io_lock
);
}
else
{
printk
(
KERN_WARNING
PFX
"Heartbeat lost! Will not ping the watchdog
\n
"
);
}
...
...
@@ -250,19 +345,19 @@ static int pcwd_start(void)
{
int
stat_reg
;
next_heartbeat
=
jiffies
+
(
heartbeat
*
HZ
);
pcwd_private
.
next_heartbeat
=
jiffies
+
(
heartbeat
*
HZ
);
/* Start the timer */
mod_timer
(
&
timer
,
jiffies
+
WDT_INTERVAL
);
mod_timer
(
&
pcwd_private
.
timer
,
jiffies
+
WDT_INTERVAL
);
/* Enable the port */
if
(
revision
==
PCWD_REVISION_C
)
{
spin_lock
(
&
io_lock
);
outb_p
(
0x00
,
current_readport
+
3
);
if
(
pcwd_private
.
revision
==
PCWD_REVISION_C
)
{
spin_lock
(
&
pcwd_private
.
io_lock
);
outb_p
(
0x00
,
pcwd_private
.
io_addr
+
3
);
udelay
(
ISA_COMMAND_TIMEOUT
);
stat_reg
=
inb_p
(
current_readport
+
2
);
spin_unlock
(
&
io_lock
);
if
(
stat_reg
&
0x10
)
{
stat_reg
=
inb_p
(
pcwd_private
.
io_addr
+
2
);
spin_unlock
(
&
pcwd_private
.
io_lock
);
if
(
stat_reg
&
WD_WDIS
)
{
printk
(
KERN_INFO
PFX
"Could not start watchdog
\n
"
);
return
-
EIO
;
}
...
...
@@ -275,18 +370,18 @@ static int pcwd_stop(void)
int
stat_reg
;
/* Stop the timer */
del_timer
(
&
timer
);
del_timer
(
&
pcwd_private
.
timer
);
/* Disable the board */
if
(
revision
==
PCWD_REVISION_C
)
{
spin_lock
(
&
io_lock
);
outb_p
(
0xA5
,
current_readport
+
3
);
if
(
pcwd_private
.
revision
==
PCWD_REVISION_C
)
{
spin_lock
(
&
pcwd_private
.
io_lock
);
outb_p
(
0xA5
,
pcwd_private
.
io_addr
+
3
);
udelay
(
ISA_COMMAND_TIMEOUT
);
outb_p
(
0xA5
,
current_readport
+
3
);
outb_p
(
0xA5
,
pcwd_private
.
io_addr
+
3
);
udelay
(
ISA_COMMAND_TIMEOUT
);
stat_reg
=
inb_p
(
current_readport
+
2
);
spin_unlock
(
&
io_lock
);
if
((
stat_reg
&
0x10
)
==
0
)
{
stat_reg
=
inb_p
(
pcwd_private
.
io_addr
+
2
);
spin_unlock
(
&
pcwd_private
.
io_lock
);
if
((
stat_reg
&
WD_WDIS
)
==
0
)
{
printk
(
KERN_INFO
PFX
"Could not stop watchdog
\n
"
);
return
-
EIO
;
}
...
...
@@ -297,7 +392,7 @@ static int pcwd_stop(void)
static
int
pcwd_keepalive
(
void
)
{
/* user land ping */
next_heartbeat
=
jiffies
+
(
heartbeat
*
HZ
);
pcwd_private
.
next_heartbeat
=
jiffies
+
(
heartbeat
*
HZ
);
return
0
;
}
...
...
@@ -315,23 +410,23 @@ static int pcwd_get_status(int *status)
int
card_status
;
*
status
=
0
;
spin_lock
(
&
io_lock
);
if
(
revision
==
PCWD_REVISION_A
)
spin_lock
(
&
pcwd_private
.
io_lock
);
if
(
pcwd_private
.
revision
==
PCWD_REVISION_A
)
/* Rev A cards return status information from
* the base register, which is used for the
* temperature in other cards. */
card_status
=
inb
(
current_readport
);
card_status
=
inb
(
pcwd_private
.
io_addr
);
else
{
/* Rev C cards return card status in the base
* address + 1 register. And use different bits
* to indicate a card initiated reset, and an
* over-temperature condition. And the reboot
* status can be reset. */
card_status
=
inb
(
current_readport
+
1
);
card_status
=
inb
(
pcwd_private
.
io_addr
+
1
);
}
spin_unlock
(
&
io_lock
);
spin_unlock
(
&
pcwd_private
.
io_lock
);
if
(
revision
==
PCWD_REVISION_A
)
{
if
(
pcwd_private
.
revision
==
PCWD_REVISION_A
)
{
if
(
card_status
&
WD_WDRST
)
*
status
|=
WDIOF_CARDRESET
;
...
...
@@ -360,10 +455,10 @@ static int pcwd_get_status(int *status)
static
int
pcwd_clear_status
(
void
)
{
if
(
revision
==
PCWD_REVISION_C
)
{
spin_lock
(
&
io_lock
);
outb_p
(
0x00
,
current_readport
+
1
);
/* clear reset status */
spin_unlock
(
&
io_lock
);
if
(
pcwd_private
.
revision
==
PCWD_REVISION_C
)
{
spin_lock
(
&
pcwd_private
.
io_lock
);
outb_p
(
0x00
,
pcwd_private
.
io_addr
+
1
);
/* clear reset status */
spin_unlock
(
&
pcwd_private
.
io_lock
);
}
return
0
;
}
...
...
@@ -371,20 +466,20 @@ static int pcwd_clear_status(void)
static
int
pcwd_get_temperature
(
int
*
temperature
)
{
/* check that port 0 gives temperature info and no command results */
if
(
command_mode
)
if
(
pcwd_private
.
command_mode
)
return
-
1
;
*
temperature
=
0
;
if
(
!
supports_temp
)
if
(
!
pcwd_private
.
supports_temp
)
return
-
ENODEV
;
/*
* Convert celsius to fahrenheit, since this was
* the decided 'standard' for this return value.
*/
spin_lock
(
&
io_lock
);
*
temperature
=
((
inb
(
current_readport
))
*
9
/
5
)
+
32
;
spin_unlock
(
&
io_lock
);
spin_lock
(
&
pcwd_private
.
io_lock
);
*
temperature
=
((
inb
(
pcwd_private
.
io_addr
))
*
9
/
5
)
+
32
;
spin_unlock
(
&
pcwd_private
.
io_lock
);
return
0
;
}
...
...
@@ -425,7 +520,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
return
put_user
(
status
,
argp
);
case
WDIOC_GETBOOTSTATUS
:
return
put_user
(
initial
_status
,
argp
);
return
put_user
(
pcwd_private
.
boot
_status
,
argp
);
case
WDIOC_GETTEMP
:
if
(
pcwd_get_temperature
(
&
temperature
))
...
...
@@ -434,7 +529,7 @@ static int pcwd_ioctl(struct inode *inode, struct file *file,
return
put_user
(
temperature
,
argp
);
case
WDIOC_SETOPTIONS
:
if
(
revision
==
PCWD_REVISION_C
)
if
(
pcwd_private
.
revision
==
PCWD_REVISION_C
)
{
if
(
copy_from_user
(
&
rv
,
argp
,
sizeof
(
int
)))
return
-
EFAULT
;
...
...
@@ -550,7 +645,7 @@ static ssize_t pcwd_temp_read(struct file *file, char __user *buf, size_t count,
static
int
pcwd_temp_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
!
supports_temp
)
if
(
!
pcwd_private
.
supports_temp
)
return
-
ENODEV
;
return
nonseekable_open
(
inode
,
file
);
...
...
@@ -616,68 +711,24 @@ static struct notifier_block pcwd_notifier = {
* Init & exit routines
*/
static
inline
void
get_support
(
void
)
{
if
(
inb
(
current_readport
)
!=
0xF0
)
supports_temp
=
1
;
}
static
inline
int
get_revision
(
void
)
{
int
r
=
PCWD_REVISION_C
;
spin_lock
(
&
io_lock
);
spin_lock
(
&
pcwd_private
.
io_lock
);
/* REV A cards use only 2 io ports; test
* presumes a floating bus reads as 0xff. */
if
((
inb
(
current_readport
+
2
)
==
0xFF
)
||
(
inb
(
current_readport
+
3
)
==
0xFF
))
if
((
inb
(
pcwd_private
.
io_addr
+
2
)
==
0xFF
)
||
(
inb
(
pcwd_private
.
io_addr
+
3
)
==
0xFF
))
r
=
PCWD_REVISION_A
;
spin_unlock
(
&
io_lock
);
spin_unlock
(
&
pcwd_private
.
io_lock
);
return
r
;
}
static
inline
char
*
get_firmware
(
void
)
{
int
one
,
ten
,
hund
,
minor
;
char
*
ret
;
ret
=
kmalloc
(
6
,
GFP_KERNEL
);
if
(
ret
==
NULL
)
return
NULL
;
if
(
set_command_mode
())
{
one
=
send_isa_command
(
CMD_ISA_VERSION_INTEGER
);
ten
=
send_isa_command
(
CMD_ISA_VERSION_TENTH
);
hund
=
send_isa_command
(
CMD_ISA_VERSION_HUNDRETH
);
minor
=
send_isa_command
(
CMD_ISA_VERSION_MINOR
);
sprintf
(
ret
,
"%c.%c%c%c"
,
one
,
ten
,
hund
,
minor
);
}
else
sprintf
(
ret
,
"ERROR"
);
unset_command_mode
();
return
(
ret
);
}
static
inline
int
get_option_switches
(
void
)
{
int
rv
=
0
;
if
(
set_command_mode
())
{
/* Get switch settings */
rv
=
send_isa_command
(
CMD_ISA_SWITCH_SETTINGS
);
}
unset_command_mode
();
return
(
rv
);
}
static
int
__devinit
pcwatchdog_init
(
int
base_addr
)
{
int
ret
;
char
*
firmware
;
int
option_switches
;
cards_found
++
;
if
(
cards_found
==
1
)
...
...
@@ -692,79 +743,41 @@ static int __devinit pcwatchdog_init(int base_addr)
printk
(
KERN_ERR
PFX
"No I/O-Address for card detected
\n
"
);
return
-
ENODEV
;
}
current_readport
=
base_addr
;
pcwd_private
.
io_addr
=
base_addr
;
/* Check card's revision */
revision
=
get_revision
();
pcwd_private
.
revision
=
get_revision
();
if
(
!
request_region
(
current_readport
,
(
revision
==
PCWD_REVISION_A
)
?
2
:
4
,
"PCWD"
))
{
if
(
!
request_region
(
pcwd_private
.
io_addr
,
(
pcwd_private
.
revision
==
PCWD_REVISION_A
)
?
2
:
4
,
"PCWD"
))
{
printk
(
KERN_ERR
PFX
"I/O address 0x%04x already in use
\n
"
,
current_readport
);
current_readport
=
0x0000
;
pcwd_private
.
io_addr
);
pcwd_private
.
io_addr
=
0x0000
;
return
-
EIO
;
}
/* Initial variables */
supports_temp
=
0
;
pcwd_private
.
supports_temp
=
0
;
temp_panic
=
0
;
initial
_status
=
0x0000
;
pcwd_private
.
boot
_status
=
0x0000
;
/* get the boot_status */
pcwd_get_status
(
&
initial
_status
);
pcwd_get_status
(
&
pcwd_private
.
boot
_status
);
/* clear the "card caused reboot" flag */
pcwd_clear_status
();
init_timer
(
&
timer
);
timer
.
function
=
pcwd_timer_ping
;
timer
.
data
=
0
;
init_timer
(
&
pcwd_private
.
timer
);
pcwd_private
.
timer
.
function
=
pcwd_timer_ping
;
pcwd_private
.
timer
.
data
=
0
;
/* Disable the board */
pcwd_stop
();
/* Check whether or not the card supports the temperature device */
get_support
();
/* Get some extra info from the hardware (in command/debug/diag mode) */
if
(
revision
==
PCWD_REVISION_A
)
printk
(
KERN_INFO
PFX
"ISA-PC Watchdog (REV.A) detected at port 0x%04x
\n
"
,
current_readport
);
else
if
(
revision
==
PCWD_REVISION_C
)
{
firmware
=
get_firmware
();
printk
(
KERN_INFO
PFX
"ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)
\n
"
,
current_readport
,
firmware
);
kfree
(
firmware
);
option_switches
=
get_option_switches
();
printk
(
KERN_INFO
PFX
"Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s
\n
"
,
option_switches
,
((
option_switches
&
0x10
)
?
"ON"
:
"OFF"
),
((
option_switches
&
0x08
)
?
"ON"
:
"OFF"
));
/* Reprogram internal heartbeat to 2 seconds */
if
(
set_command_mode
())
{
send_isa_command
(
CMD_ISA_DELAY_TIME_2SECS
);
unset_command_mode
();
}
}
else
{
/* Should NEVER happen, unless get_revision() fails. */
printk
(
KERN_INFO
PFX
"Unable to get revision
\n
"
);
release_region
(
current_readport
,
(
revision
==
PCWD_REVISION_A
)
?
2
:
4
);
current_readport
=
0x0000
;
return
-
1
;
}
pcwd_check_temperature_support
();
if
(
supports_temp
)
printk
(
KERN_INFO
PFX
"Temperature Option Detected
\n
"
);
if
(
initial_status
&
WDIOF_CARDRESET
)
printk
(
KERN_INFO
PFX
"Previous reboot was caused by the card
\n
"
);
if
(
initial_status
&
WDIOF_OVERHEAT
)
{
printk
(
KERN_EMERG
PFX
"Card senses a CPU Overheat. Panicking!
\n
"
);
printk
(
KERN_EMERG
PFX
"CPU Overheat
\n
"
);
}
if
(
initial_status
==
0
)
printk
(
KERN_INFO
PFX
"No previous trip detected - Cold boot or reset
\n
"
);
/* Show info about the card itself */
pcwd_show_card_info
();
/* Check that the heartbeat value is within it's range ; if not reset to the default */
if
(
pcwd_set_heartbeat
(
heartbeat
))
{
...
...
@@ -777,19 +790,19 @@ static int __devinit pcwatchdog_init(int base_addr)
if
(
ret
)
{
printk
(
KERN_ERR
PFX
"cannot register reboot notifier (err=%d)
\n
"
,
ret
);
release_region
(
current_readport
,
(
revision
==
PCWD_REVISION_A
)
?
2
:
4
);
current_readport
=
0x0000
;
release_region
(
pcwd_private
.
io_addr
,
(
pcwd_private
.
revision
==
PCWD_REVISION_A
)
?
2
:
4
);
pcwd_private
.
io_addr
=
0x0000
;
return
ret
;
}
if
(
supports_temp
)
{
if
(
pcwd_private
.
supports_temp
)
{
ret
=
misc_register
(
&
temp_miscdev
);
if
(
ret
)
{
printk
(
KERN_ERR
PFX
"cannot register miscdev on minor=%d (err=%d)
\n
"
,
TEMP_MINOR
,
ret
);
unregister_reboot_notifier
(
&
pcwd_notifier
);
release_region
(
current_readport
,
(
revision
==
PCWD_REVISION_A
)
?
2
:
4
);
current_readport
=
0x0000
;
release_region
(
pcwd_private
.
io_addr
,
(
pcwd_private
.
revision
==
PCWD_REVISION_A
)
?
2
:
4
);
pcwd_private
.
io_addr
=
0x0000
;
return
ret
;
}
}
...
...
@@ -798,11 +811,11 @@ static int __devinit pcwatchdog_init(int base_addr)
if
(
ret
)
{
printk
(
KERN_ERR
PFX
"cannot register miscdev on minor=%d (err=%d)
\n
"
,
WATCHDOG_MINOR
,
ret
);
if
(
supports_temp
)
if
(
pcwd_private
.
supports_temp
)
misc_deregister
(
&
temp_miscdev
);
unregister_reboot_notifier
(
&
pcwd_notifier
);
release_region
(
current_readport
,
(
revision
==
PCWD_REVISION_A
)
?
2
:
4
);
current_readport
=
0x0000
;
release_region
(
pcwd_private
.
io_addr
,
(
pcwd_private
.
revision
==
PCWD_REVISION_A
)
?
2
:
4
);
pcwd_private
.
io_addr
=
0x0000
;
return
ret
;
}
...
...
@@ -820,11 +833,12 @@ static void __devexit pcwatchdog_exit(void)
/* Deregister */
misc_deregister
(
&
pcwd_miscdev
);
if
(
supports_temp
)
if
(
pcwd_private
.
supports_temp
)
misc_deregister
(
&
temp_miscdev
);
unregister_reboot_notifier
(
&
pcwd_notifier
);
release_region
(
current_readport
,
(
revision
==
PCWD_REVISION_A
)
?
2
:
4
);
current_readport
=
0x0000
;
release_region
(
pcwd_private
.
io_addr
,
(
pcwd_private
.
revision
==
PCWD_REVISION_A
)
?
2
:
4
);
pcwd_private
.
io_addr
=
0x0000
;
cards_found
--
;
}
/*
...
...
@@ -887,7 +901,7 @@ static int __init pcwd_init_module(void)
{
int
i
,
found
=
0
;
spin_lock_init
(
&
io_lock
);
spin_lock_init
(
&
pcwd_private
.
io_lock
);
for
(
i
=
0
;
pcwd_ioports
[
i
]
!=
0
;
i
++
)
{
if
(
pcwd_checkcard
(
pcwd_ioports
[
i
]))
{
...
...
@@ -906,7 +920,7 @@ static int __init pcwd_init_module(void)
static
void
__exit
pcwd_cleanup_module
(
void
)
{
if
(
current_readport
)
if
(
pcwd_private
.
io_addr
)
pcwatchdog_exit
();
return
;
}
...
...
drivers/char/watchdog/sa1100_wdt.c
View file @
d524c5e2
...
...
@@ -93,23 +93,25 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
{
int
ret
=
-
ENOIOCTLCMD
;
int
time
;
void
__user
*
argp
=
(
void
__user
*
)
arg
;
int
__user
*
p
=
argp
;
switch
(
cmd
)
{
case
WDIOC_GETSUPPORT
:
ret
=
copy_to_user
(
(
struct
watchdog_info
__user
*
)
arg
,
&
ident
,
ret
=
copy_to_user
(
argp
,
&
ident
,
sizeof
(
ident
))
?
-
EFAULT
:
0
;
break
;
case
WDIOC_GETSTATUS
:
ret
=
put_user
(
0
,
(
int
__user
*
)
arg
);
ret
=
put_user
(
0
,
p
);
break
;
case
WDIOC_GETBOOTSTATUS
:
ret
=
put_user
(
boot_status
,
(
int
__user
*
)
arg
);
ret
=
put_user
(
boot_status
,
p
);
break
;
case
WDIOC_SETTIMEOUT
:
ret
=
get_user
(
time
,
(
int
__user
*
)
arg
);
ret
=
get_user
(
time
,
p
);
if
(
ret
)
break
;
...
...
@@ -123,7 +125,7 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file,
/*fall through*/
case
WDIOC_GETTIMEOUT
:
ret
=
put_user
(
pre_margin
/
OSCR_FREQ
,
(
int
__user
*
)
arg
);
ret
=
put_user
(
pre_margin
/
OSCR_FREQ
,
p
);
break
;
case
WDIOC_KEEPALIVE
:
...
...
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