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