diff options
Diffstat (limited to 'drivers/char/watchdog/mixcomwd.c')
-rw-r--r-- | drivers/char/watchdog/mixcomwd.c | 127 |
1 files changed, 76 insertions, 51 deletions
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c index f35e2848aa3..db2ccb86441 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); @@ -188,8 +229,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 +238,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 +269,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 +320,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); |