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
nexedi
linux
Commits
58a2c322
Commit
58a2c322
authored
Oct 08, 2005
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
dcbd39a1
195331d7
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
172 additions
and
67 deletions
+172
-67
drivers/char/watchdog/pcwd_pci.c
drivers/char/watchdog/pcwd_pci.c
+172
-67
No files found.
drivers/char/watchdog/pcwd_pci.c
View file @
58a2c322
...
...
@@ -50,8 +50,8 @@
#include <asm/io.h>
/* For inb/outb/... */
/* Module and version information */
#define WATCHDOG_VERSION "1.0
1
"
#define WATCHDOG_DATE "0
2
Sep 2005"
#define WATCHDOG_VERSION "1.0
2
"
#define WATCHDOG_DATE "0
3
Sep 2005"
#define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog"
#define WATCHDOG_NAME "pcwd_pci"
#define PFX WATCHDOG_NAME ": "
...
...
@@ -70,9 +70,19 @@
* These are the defines that describe the control status bits for the
* PCI-PC Watchdog card.
*/
/* Port 1 : Control Status #1 */
#define WD_PCI_WTRP 0x01
/* Watchdog Trip status */
#define WD_PCI_HRBT 0x02
/* Watchdog Heartbeat */
#define WD_PCI_TTRP 0x04
/* Temperature Trip status */
#define WD_PCI_RL2A 0x08
/* Relay 2 Active */
#define WD_PCI_RL1A 0x10
/* Relay 1 Active */
#define WD_PCI_R2DS 0x40
/* Relay 2 Disable Temperature-trip/reset */
#define WD_PCI_RLY2 0x80
/* Activate Relay 2 on the board */
/* Port 2 : Control Status #2 */
#define WD_PCI_WDIS 0x10
/* Watchdog Disable */
#define WD_PCI_ENTP 0x20
/* Enable Temperature Trip Reset */
#define WD_PCI_WRSP 0x40
/* Watchdog wrote response */
#define WD_PCI_PCMD 0x80
/* PC has sent command */
/* according to documentation max. time to process a command for the pci
* watchdog card is 100 ms, so we give it 150 ms to do it's job */
...
...
@@ -83,6 +93,7 @@
#define CMD_GET_FIRMWARE_VERSION 0x08
#define CMD_READ_WATCHDOG_TIMEOUT 0x18
#define CMD_WRITE_WATCHDOG_TIMEOUT 0x19
#define CMD_GET_CLEAR_RESET_COUNT 0x84
/* We can only use 1 card due to the /dev/watchdog restriction */
static
int
cards_found
;
...
...
@@ -91,15 +102,22 @@ static int cards_found;
static
int
temp_panic
;
static
unsigned
long
is_active
;
static
char
expect_release
;
static
struct
{
static
struct
{
/* this is private data for each PCI-PC watchdog card */
int
supports_temp
;
/* Wether or not the card has a temperature device */
int
boot_status
;
/* The card's boot status */
unsigned
long
io_addr
;
/* The cards I/O address */
spinlock_t
io_lock
;
struct
pci_dev
*
pdev
;
spinlock_t
io_lock
;
/* the lock for io operations */
struct
pci_dev
*
pdev
;
/* the PCI-device */
}
pcipcwd_private
;
/* module parameters */
#define QUIET 0
/* Default */
#define VERBOSE 1
/* Verbose */
#define DEBUG 2
/* print fancy stuff too */
static
int
debug
=
QUIET
;
module_param
(
debug
,
int
,
0
);
MODULE_PARM_DESC
(
debug
,
"Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"
);
#define WATCHDOG_HEARTBEAT 2
/* 2 sec default heartbeat */
static
int
heartbeat
=
WATCHDOG_HEARTBEAT
;
module_param
(
heartbeat
,
int
,
0
);
...
...
@@ -117,6 +135,10 @@ static int send_command(int cmd, int *msb, int *lsb)
{
int
got_response
,
count
;
if
(
debug
>=
DEBUG
)
printk
(
KERN_DEBUG
PFX
"sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x
\n
"
,
cmd
,
*
msb
,
*
lsb
);
spin_lock
(
&
pcipcwd_private
.
io_lock
);
/* If a command requires data it should be written first.
* Data for commands with 8 bits of data should be written to port 4.
...
...
@@ -131,10 +153,19 @@ static int send_command(int cmd, int *msb, int *lsb)
/* wait till the pci card processed the command, signaled by
* the WRSP bit in port 2 and give it a max. timeout of
* PCI_COMMAND_TIMEOUT to process */
got_response
=
inb_p
(
pcipcwd_private
.
io_addr
+
2
)
&
0x40
;
got_response
=
inb_p
(
pcipcwd_private
.
io_addr
+
2
)
&
WD_PCI_WRSP
;
for
(
count
=
0
;
(
count
<
PCI_COMMAND_TIMEOUT
)
&&
(
!
got_response
);
count
++
)
{
mdelay
(
1
);
got_response
=
inb_p
(
pcipcwd_private
.
io_addr
+
2
)
&
0x40
;
got_response
=
inb_p
(
pcipcwd_private
.
io_addr
+
2
)
&
WD_PCI_WRSP
;
}
if
(
debug
>=
DEBUG
)
{
if
(
got_response
)
{
printk
(
KERN_DEBUG
PFX
"time to process command was: %d ms
\n
"
,
count
);
}
else
{
printk
(
KERN_DEBUG
PFX
"card did not respond on command!
\n
"
);
}
}
if
(
got_response
)
{
...
...
@@ -144,12 +175,66 @@ static int send_command(int cmd, int *msb, int *lsb)
/* clear WRSP bit */
inb_p
(
pcipcwd_private
.
io_addr
+
6
);
if
(
debug
>=
DEBUG
)
printk
(
KERN_DEBUG
PFX
"received following data for cmd=0x%02x: msb=0x%02x lsb=0x%02x
\n
"
,
cmd
,
*
msb
,
*
lsb
);
}
spin_unlock
(
&
pcipcwd_private
.
io_lock
);
return
got_response
;
}
static
inline
void
pcipcwd_check_temperature_support
(
void
)
{
if
(
inb_p
(
pcipcwd_private
.
io_addr
)
!=
0xF0
)
pcipcwd_private
.
supports_temp
=
1
;
}
static
int
pcipcwd_get_option_switches
(
void
)
{
int
option_switches
;
option_switches
=
inb_p
(
pcipcwd_private
.
io_addr
+
3
);
return
option_switches
;
}
static
void
pcipcwd_show_card_info
(
void
)
{
int
got_fw_rev
,
fw_rev_major
,
fw_rev_minor
;
char
fw_ver_str
[
20
];
/* The cards firmware version */
int
option_switches
;
got_fw_rev
=
send_command
(
CMD_GET_FIRMWARE_VERSION
,
&
fw_rev_major
,
&
fw_rev_minor
);
if
(
got_fw_rev
)
{
sprintf
(
fw_ver_str
,
"%u.%02u"
,
fw_rev_major
,
fw_rev_minor
);
}
else
{
sprintf
(
fw_ver_str
,
"<card no answer>"
);
}
/* Get switch settings */
option_switches
=
pcipcwd_get_option_switches
();
printk
(
KERN_INFO
PFX
"Found card at port 0x%04x (Firmware: %s) %s temp option
\n
"
,
(
int
)
pcipcwd_private
.
io_addr
,
fw_ver_str
,
(
pcipcwd_private
.
supports_temp
?
"with"
:
"without"
));
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"
));
if
(
pcipcwd_private
.
boot_status
&
WDIOF_CARDRESET
)
printk
(
KERN_INFO
PFX
"Previous reset was caused by the Watchdog card
\n
"
);
if
(
pcipcwd_private
.
boot_status
&
WDIOF_OVERHEAT
)
printk
(
KERN_INFO
PFX
"Card sensed a CPU Overheat
\n
"
);
if
(
pcipcwd_private
.
boot_status
==
0
)
printk
(
KERN_INFO
PFX
"No previous trip detected - Cold boot or reset
\n
"
);
}
static
int
pcipcwd_start
(
void
)
{
int
stat_reg
;
...
...
@@ -161,11 +246,14 @@ static int pcipcwd_start(void)
stat_reg
=
inb_p
(
pcipcwd_private
.
io_addr
+
2
);
spin_unlock
(
&
pcipcwd_private
.
io_lock
);
if
(
stat_reg
&
0x10
)
{
if
(
stat_reg
&
WD_PCI_WDIS
)
{
printk
(
KERN_ERR
PFX
"Card timer not enabled
\n
"
);
return
-
1
;
}
if
(
debug
>=
VERBOSE
)
printk
(
KERN_DEBUG
PFX
"Watchdog started
\n
"
);
return
0
;
}
...
...
@@ -183,18 +271,25 @@ static int pcipcwd_stop(void)
stat_reg
=
inb_p
(
pcipcwd_private
.
io_addr
+
2
);
spin_unlock
(
&
pcipcwd_private
.
io_lock
);
if
(
!
(
stat_reg
&
0x10
))
{
if
(
!
(
stat_reg
&
WD_PCI_WDIS
))
{
printk
(
KERN_ERR
PFX
"Card did not acknowledge disable attempt
\n
"
);
return
-
1
;
}
if
(
debug
>=
VERBOSE
)
printk
(
KERN_DEBUG
PFX
"Watchdog stopped
\n
"
);
return
0
;
}
static
int
pcipcwd_keepalive
(
void
)
{
/* Re-trigger watchdog by writing to port 0 */
outb_p
(
0x42
,
pcipcwd_private
.
io_addr
);
outb_p
(
0x42
,
pcipcwd_private
.
io_addr
);
/* send out any data */
if
(
debug
>=
DEBUG
)
printk
(
KERN_DEBUG
PFX
"Watchdog keepalive signal send
\n
"
);
return
0
;
}
...
...
@@ -210,29 +305,64 @@ static int pcipcwd_set_heartbeat(int t)
send_command
(
CMD_WRITE_WATCHDOG_TIMEOUT
,
&
t_msb
,
&
t_lsb
);
heartbeat
=
t
;
if
(
debug
>=
VERBOSE
)
printk
(
KERN_DEBUG
PFX
"New heartbeat: %d
\n
"
,
heartbeat
);
return
0
;
}
static
int
pcipcwd_get_status
(
int
*
status
)
{
int
new
_status
;
int
control
_status
;
*
status
=
0
;
new
_status
=
inb_p
(
pcipcwd_private
.
io_addr
+
1
);
if
(
new
_status
&
WD_PCI_WTRP
)
control
_status
=
inb_p
(
pcipcwd_private
.
io_addr
+
1
);
if
(
control
_status
&
WD_PCI_WTRP
)
*
status
|=
WDIOF_CARDRESET
;
if
(
new
_status
&
WD_PCI_TTRP
)
{
if
(
control
_status
&
WD_PCI_TTRP
)
{
*
status
|=
WDIOF_OVERHEAT
;
if
(
temp_panic
)
panic
(
PFX
"Temperature overheat trip!
\n
"
);
}
if
(
debug
>=
DEBUG
)
printk
(
KERN_DEBUG
PFX
"Control Status #1: 0x%02x
\n
"
,
control_status
);
return
0
;
}
static
int
pcipcwd_clear_status
(
void
)
{
outb_p
(
0x01
,
pcipcwd_private
.
io_addr
+
1
);
int
control_status
;
int
msb
;
int
reset_counter
;
if
(
debug
>=
VERBOSE
)
printk
(
KERN_INFO
PFX
"clearing watchdog trip status & LED
\n
"
);
control_status
=
inb_p
(
pcipcwd_private
.
io_addr
+
1
);
if
(
debug
>=
DEBUG
)
{
printk
(
KERN_DEBUG
PFX
"status was: 0x%02x
\n
"
,
control_status
);
printk
(
KERN_DEBUG
PFX
"sending: 0x%02x
\n
"
,
(
control_status
&
WD_PCI_R2DS
)
|
WD_PCI_WTRP
);
}
/* clear trip status & LED and keep mode of relay 2 */
outb_p
((
control_status
&
WD_PCI_R2DS
)
|
WD_PCI_WTRP
,
pcipcwd_private
.
io_addr
+
1
);
/* clear reset counter */
msb
=
0
;
reset_counter
=
0xff
;
send_command
(
CMD_GET_CLEAR_RESET_COUNT
,
&
msb
,
&
reset_counter
);
if
(
debug
>=
DEBUG
)
{
printk
(
KERN_DEBUG
PFX
"reset count was: 0x%02x
\n
"
,
reset_counter
);
}
return
0
;
}
...
...
@@ -242,11 +372,18 @@ static int pcipcwd_get_temperature(int *temperature)
if
(
!
pcipcwd_private
.
supports_temp
)
return
-
ENODEV
;
*
temperature
=
inb_p
(
pcipcwd_private
.
io_addr
);
/*
* Convert celsius to fahrenheit, since this was
* the decided 'standard' for this return value.
*/
*
temperature
=
((
inb_p
(
pcipcwd_private
.
io_addr
))
*
9
/
5
)
+
32
;
*
temperature
=
(
*
temperature
*
9
/
5
)
+
32
;
if
(
debug
>=
DEBUG
)
{
printk
(
KERN_DEBUG
PFX
"temperature is: %d F
\n
"
,
*
temperature
);
}
return
0
;
}
...
...
@@ -381,8 +518,11 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file,
static
int
pcipcwd_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
/* /dev/watchdog can only be opened once */
if
(
test_and_set_bit
(
0
,
&
is_active
))
if
(
test_and_set_bit
(
0
,
&
is_active
))
{
if
(
debug
>=
VERBOSE
)
printk
(
KERN_ERR
PFX
"Attempt to open already opened device.
\n
"
);
return
-
EBUSY
;
}
/* Activate */
pcipcwd_start
();
...
...
@@ -492,19 +632,10 @@ static struct notifier_block pcipcwd_notifier = {
* Init & exit routines
*/
static
inline
void
check_temperature_support
(
void
)
{
if
(
inb_p
(
pcipcwd_private
.
io_addr
)
!=
0xF0
)
pcipcwd_private
.
supports_temp
=
1
;
}
static
int
__devinit
pcipcwd_card_init
(
struct
pci_dev
*
pdev
,
const
struct
pci_device_id
*
ent
)
{
int
ret
=
-
EIO
;
int
got_fw_rev
,
fw_rev_major
,
fw_rev_minor
;
char
fw_ver_str
[
20
];
char
option_switches
;
cards_found
++
;
if
(
cards_found
==
1
)
...
...
@@ -546,36 +677,10 @@ static int __devinit pcipcwd_card_init(struct pci_dev *pdev,
pcipcwd_stop
();
/* Check whether or not the card supports the temperature device */
check_temperature_support
();
pcipcwd_
check_temperature_support
();
/* Get the Firmware Version */
got_fw_rev
=
send_command
(
CMD_GET_FIRMWARE_VERSION
,
&
fw_rev_major
,
&
fw_rev_minor
);
if
(
got_fw_rev
)
{
sprintf
(
fw_ver_str
,
"%u.%02u"
,
fw_rev_major
,
fw_rev_minor
);
}
else
{
sprintf
(
fw_ver_str
,
"<card no answer>"
);
}
/* Get switch settings */
option_switches
=
inb_p
(
pcipcwd_private
.
io_addr
+
3
);
printk
(
KERN_INFO
PFX
"Found card at port 0x%04x (Firmware: %s) %s temp option
\n
"
,
(
int
)
pcipcwd_private
.
io_addr
,
fw_ver_str
,
(
pcipcwd_private
.
supports_temp
?
"with"
:
"without"
));
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"
));
if
(
pcipcwd_private
.
boot_status
&
WDIOF_CARDRESET
)
printk
(
KERN_INFO
PFX
"Previous reset was caused by the Watchdog card
\n
"
);
if
(
pcipcwd_private
.
boot_status
&
WDIOF_OVERHEAT
)
printk
(
KERN_INFO
PFX
"Card sensed a CPU Overheat
\n
"
);
if
(
pcipcwd_private
.
boot_status
==
0
)
printk
(
KERN_INFO
PFX
"No previous trip detected - Cold boot or reset
\n
"
);
/* Show info about the card itself */
pcipcwd_show_card_info
();
/* Check that the heartbeat value is within it's range ; if not reset to the default */
if
(
pcipcwd_set_heartbeat
(
heartbeat
))
{
...
...
@@ -656,7 +761,7 @@ static struct pci_driver pcipcwd_driver = {
static
int
__init
pcipcwd_init_module
(
void
)
{
spin_lock_init
(
&
pcipcwd_private
.
io_lock
);
spin_lock_init
(
&
pcipcwd_private
.
io_lock
);
return
pci_register_driver
(
&
pcipcwd_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