summaryrefslogtreecommitdiff
path: root/drivers/char/watchdog/mixcomwd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char/watchdog/mixcomwd.c')
-rw-r--r--drivers/char/watchdog/mixcomwd.c132
1 files changed, 81 insertions, 51 deletions
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
index f35e2848aa3e..1adf1d56027d 100644
--- a/drivers/char/watchdog/mixcomwd.c
+++ b/drivers/char/watchdog/mixcomwd.c
@@ -29,11 +29,18 @@
* - support for one more type board
*
* Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com>
- * - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ * - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT
+ *
+ * Version 0.6 (2002/04/12): Rob Radez <rob@osinvestor.com>
+ * - make mixcomwd_opened unsigned,
+ * removed lock_kernel/unlock_kernel from mixcomwd_release,
+ * modified ioctl a bit to conform to API
*
*/
-#define VERSION "0.5"
+#define VERSION "0.6"
+#define WATCHDOG_NAME "mixcomwd"
+#define PFX WATCHDOG_NAME ": "
#include <linux/module.h>
#include <linux/moduleparam.h>
@@ -49,12 +56,46 @@
#include <asm/uaccess.h>
#include <asm/io.h>
-static int mixcomwd_ioports[] = { 0x180, 0x280, 0x380, 0x000 };
-
-#define MIXCOM_WATCHDOG_OFFSET 0xc10
+/*
+ * We have two types of cards that can be probed:
+ * 1) The Mixcom cards: these cards can be found at addresses
+ * 0x180, 0x280, 0x380 with an additional offset of 0xc10.
+ * (Or 0xd90, 0xe90, 0xf90).
+ * 2) The FlashCOM cards: these cards can be set up at
+ * 0x300 -> 0x378, in 0x8 jumps with an offset of 0x04.
+ * (Or 0x304 -> 0x37c in 0x8 jumps).
+ * Each card has it's own ID.
+ */
#define MIXCOM_ID 0x11
-#define FLASHCOM_WATCHDOG_OFFSET 0x4
#define FLASHCOM_ID 0x18
+static struct {
+ int ioport;
+ int id;
+} mixcomwd_io_info[] __devinitdata = {
+ /* The Mixcom cards */
+ {0x0d90, MIXCOM_ID},
+ {0x0e90, MIXCOM_ID},
+ {0x0f90, MIXCOM_ID},
+ /* The FlashCOM cards */
+ {0x0304, FLASHCOM_ID},
+ {0x030c, FLASHCOM_ID},
+ {0x0314, FLASHCOM_ID},
+ {0x031c, FLASHCOM_ID},
+ {0x0324, FLASHCOM_ID},
+ {0x032c, FLASHCOM_ID},
+ {0x0334, FLASHCOM_ID},
+ {0x033c, FLASHCOM_ID},
+ {0x0344, FLASHCOM_ID},
+ {0x034c, FLASHCOM_ID},
+ {0x0354, FLASHCOM_ID},
+ {0x035c, FLASHCOM_ID},
+ {0x0364, FLASHCOM_ID},
+ {0x036c, FLASHCOM_ID},
+ {0x0374, FLASHCOM_ID},
+ {0x037c, FLASHCOM_ID},
+ /* The end of the list */
+ {0x0000, 0},
+};
static void mixcomwd_timerfun(unsigned long d);
@@ -113,13 +154,13 @@ static int mixcomwd_release(struct inode *inode, struct file *file)
{
if (expect_close == 42) {
if(mixcomwd_timer_alive) {
- printk(KERN_ERR "mixcomwd: release called while internal timer alive");
+ printk(KERN_ERR PFX "release called while internal timer alive");
return -EBUSY;
}
mixcomwd_timer_alive=1;
mod_timer(&mixcomwd_timer, jiffies + 5 * HZ);
} else {
- printk(KERN_CRIT "mixcomwd: WDT device closed unexpectedly. WDT will not stop!\n");
+ printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n");
}
clear_bit(0,&mixcomwd_opened);
@@ -174,6 +215,11 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
}
break;
+ case WDIOC_GETBOOTSTATUS:
+ if (copy_to_user(p, &status, sizeof(int))) {
+ return -EFAULT;
+ }
+ break;
case WDIOC_GETSUPPORT:
if (copy_to_user(argp, &ident, sizeof(ident))) {
return -EFAULT;
@@ -188,8 +234,7 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file,
return 0;
}
-static const struct file_operations mixcomwd_fops=
-{
+static const struct file_operations mixcomwd_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = mixcomwd_write,
@@ -198,46 +243,30 @@ static const struct file_operations mixcomwd_fops=
.release = mixcomwd_release,
};
-static struct miscdevice mixcomwd_miscdev=
-{
+static struct miscdevice mixcomwd_miscdev = {
.minor = WATCHDOG_MINOR,
.name = "watchdog",
.fops = &mixcomwd_fops,
};
-static int __init mixcomwd_checkcard(int port)
+static int __init checkcard(int port, int card_id)
{
int id;
- port += MIXCOM_WATCHDOG_OFFSET;
- if (!request_region(port, 1, "MixCOM watchdog")) {
- return 0;
- }
-
- id=inb_p(port) & 0x3f;
- if(id!=MIXCOM_ID) {
- release_region(port, 1);
- return 0;
- }
- return port;
-}
-
-static int __init flashcom_checkcard(int port)
-{
- int id;
-
- port += FLASHCOM_WATCHDOG_OFFSET;
if (!request_region(port, 1, "MixCOM watchdog")) {
return 0;
}
id=inb_p(port);
- if(id!=FLASHCOM_ID) {
+ if (card_id==MIXCOM_ID)
+ id &= 0x3f;
+
+ if (id!=card_id) {
release_region(port, 1);
return 0;
}
- return port;
- }
+ return 1;
+}
static int __init mixcomwd_init(void)
{
@@ -245,50 +274,50 @@ static int __init mixcomwd_init(void)
int ret;
int found=0;
- for (i = 0; !found && mixcomwd_ioports[i] != 0; i++) {
- watchdog_port = mixcomwd_checkcard(mixcomwd_ioports[i]);
- if (watchdog_port) {
- found = 1;
- }
- }
-
- /* The FlashCOM card can be set up at 0x300 -> 0x378, in 0x8 jumps */
- for (i = 0x300; !found && i < 0x380; i+=0x8) {
- watchdog_port = flashcom_checkcard(i);
- if (watchdog_port) {
+ for (i = 0; !found && mixcomwd_io_info[i].ioport != 0; i++) {
+ if (checkcard(mixcomwd_io_info[i].ioport,
+ mixcomwd_io_info[i].id)) {
found = 1;
+ watchdog_port = mixcomwd_io_info[i].ioport;
}
}
if (!found) {
- printk("mixcomwd: No card detected, or port not available.\n");
+ printk(KERN_ERR PFX "No card detected, or port not available.\n");
return -ENODEV;
}
ret = misc_register(&mixcomwd_miscdev);
if (ret)
{
- release_region(watchdog_port, 1);
- return ret;
+ printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+ WATCHDOG_MINOR, ret);
+ goto error_misc_register_watchdog;
}
- printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",VERSION,watchdog_port);
+ printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n",
+ VERSION, watchdog_port);
return 0;
+
+error_misc_register_watchdog:
+ release_region(watchdog_port, 1);
+ watchdog_port = 0x0000;
+ return ret;
}
static void __exit mixcomwd_exit(void)
{
if (!nowayout) {
if(mixcomwd_timer_alive) {
- printk(KERN_WARNING "mixcomwd: I quit now, hardware will"
+ printk(KERN_WARNING PFX "I quit now, hardware will"
" probably reboot!\n");
del_timer_sync(&mixcomwd_timer);
mixcomwd_timer_alive=0;
}
}
- release_region(watchdog_port,1);
misc_deregister(&mixcomwd_miscdev);
+ release_region(watchdog_port,1);
}
module_init(mixcomwd_init);
@@ -296,5 +325,6 @@ module_exit(mixcomwd_exit);
MODULE_AUTHOR("Gergely Madarasz <gorgo@itc.hu>");
MODULE_DESCRIPTION("MixCom Watchdog driver");
+MODULE_VERSION(VERSION);
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);