X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fwatchdog%2Fwdt977.c;h=6253041b235bb2ae0c1260e772f86b659bd799cb;hb=refs%2Fheads%2Fvserver;hp=388c548c255b3cc848cb1823668464c9b71c0991;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c index 388c548c2..6253041b2 100644 --- a/drivers/char/watchdog/wdt977.c +++ b/drivers/char/watchdog/wdt977.c @@ -1,5 +1,5 @@ /* - * Wdt977 0.03: A Watchdog Device for Netwinder W83977AF chip + * Wdt977 0.04: A Watchdog Device for Netwinder W83977AF chip * * (c) Copyright 1998 Rebel.com (Woody Suwalski ) * @@ -18,16 +18,18 @@ * from minutes to seconds. * 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in * nwwatchdog_init. + * 25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks + * remove limitiation to be used on Netwinders only */ #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -37,8 +39,18 @@ #include #include -#define PFX "Wdt977: " -#define WATCHDOG_MINOR 130 +#define WATCHDOG_VERSION "0.04" +#define WATCHDOG_NAME "Wdt977" +#define PFX WATCHDOG_NAME ": " +#define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" + +#define IO_INDEX_PORT 0x370 /* on some systems it can be 0x3F0 */ +#define IO_DATA_PORT (IO_INDEX_PORT+1) + +#define UNLOCK_DATA 0x87 +#define LOCK_DATA 0xAA +#define DEVICE_REGISTER 0x07 + #define DEFAULT_TIMEOUT 60 /* default timeout in seconds */ @@ -47,18 +59,14 @@ static int timeoutM; /* timeout in minutes */ static unsigned long timer_alive; static int testmode; static char expect_close; +static spinlock_t spinlock; module_param(timeout, int, 0); MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); module_param(testmode, int, 0); MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); -#ifdef CONFIG_WATCHDOG_NOWAYOUT -static int nowayout = 1; -#else -static int nowayout = 0; -#endif - +static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); @@ -68,9 +76,13 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CON static int wdt977_start(void) { + unsigned long flags; + + spin_lock_irqsave(&spinlock, flags); + /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); + outb_p(UNLOCK_DATA, IO_INDEX_PORT); + outb_p(UNLOCK_DATA, IO_INDEX_PORT); /* select device Aux2 (device=8) and set watchdog regs F2, F3 and F4 * F2 has the timeout in minutes @@ -78,28 +90,29 @@ static int wdt977_start(void) * at timeout, and to reset timer on kbd/mouse activity (not impl.) * F4 is used to just clear the TIMEOUT'ed state (bit 0) */ - outb(0x07,0x370); - outb(0x08,0x371); - outb(0xF2,0x370); - outb(timeoutM,0x371); - outb(0xF3,0x370); - outb(0x00,0x371); /* another setting is 0E for kbd/mouse/LED */ - outb(0xF4,0x370); - outb(0x00,0x371); + outb_p(DEVICE_REGISTER, IO_INDEX_PORT); + outb_p(0x08, IO_DATA_PORT); + outb_p(0xF2, IO_INDEX_PORT); + outb_p(timeoutM, IO_DATA_PORT); + outb_p(0xF3, IO_INDEX_PORT); + outb_p(0x00, IO_DATA_PORT); /* another setting is 0E for kbd/mouse/LED */ + outb_p(0xF4, IO_INDEX_PORT); + outb_p(0x00, IO_DATA_PORT); /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ /* in test mode watch the bit 1 on F4 to indicate "triggered" */ if (!testmode) { - outb(0x07,0x370); - outb(0x07,0x371); - outb(0xE6,0x370); - outb(0x08,0x371); + outb_p(DEVICE_REGISTER, IO_INDEX_PORT); + outb_p(0x07, IO_DATA_PORT); + outb_p(0xE6, IO_INDEX_PORT); + outb_p(0x08, IO_DATA_PORT); } /* lock the SuperIO chip */ - outb(0xAA,0x370); + outb_p(LOCK_DATA, IO_INDEX_PORT); + spin_unlock_irqrestore(&spinlock, flags); printk(KERN_INFO PFX "activated.\n"); return 0; @@ -111,35 +124,39 @@ static int wdt977_start(void) static int wdt977_stop(void) { + unsigned long flags; + spin_lock_irqsave(&spinlock, flags); + /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); + outb_p(UNLOCK_DATA, IO_INDEX_PORT); + outb_p(UNLOCK_DATA, IO_INDEX_PORT); /* select device Aux2 (device=8) and set watchdog regs F2,F3 and F4 * F3 is reset to its default state * F4 can clear the TIMEOUT'ed state (bit 0) - back to default * We can not use GP17 as a PowerLed, as we use its usage as a RedLed */ - outb(0x07,0x370); - outb(0x08,0x371); - outb(0xF2,0x370); - outb(0xFF,0x371); - outb(0xF3,0x370); - outb(0x00,0x371); - outb(0xF4,0x370); - outb(0x00,0x371); - outb(0xF2,0x370); - outb(0x00,0x371); + outb_p(DEVICE_REGISTER, IO_INDEX_PORT); + outb_p(0x08, IO_DATA_PORT); + outb_p(0xF2, IO_INDEX_PORT); + outb_p(0xFF, IO_DATA_PORT); + outb_p(0xF3, IO_INDEX_PORT); + outb_p(0x00, IO_DATA_PORT); + outb_p(0xF4, IO_INDEX_PORT); + outb_p(0x00, IO_DATA_PORT); + outb_p(0xF2, IO_INDEX_PORT); + outb_p(0x00, IO_DATA_PORT); /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ - outb(0x07,0x370); - outb(0x07,0x371); - outb(0xE6,0x370); - outb(0x08,0x371); + outb_p(DEVICE_REGISTER, IO_INDEX_PORT); + outb_p(0x07, IO_DATA_PORT); + outb_p(0xE6, IO_INDEX_PORT); + outb_p(0x08, IO_DATA_PORT); /* lock the SuperIO chip */ - outb(0xAA,0x370); + outb_p(LOCK_DATA, IO_INDEX_PORT); + spin_unlock_irqrestore(&spinlock, flags); printk(KERN_INFO PFX "shutdown.\n"); return 0; @@ -152,19 +169,23 @@ static int wdt977_stop(void) static int wdt977_keepalive(void) { + unsigned long flags; + spin_lock_irqsave(&spinlock, flags); + /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); + outb_p(UNLOCK_DATA, IO_INDEX_PORT); + outb_p(UNLOCK_DATA, IO_INDEX_PORT); /* select device Aux2 (device=8) and kicks watchdog reg F2 */ /* F2 has the timeout in minutes */ - outb(0x07,0x370); - outb(0x08,0x371); - outb(0xF2,0x370); - outb(timeoutM,0x371); + outb_p(DEVICE_REGISTER, IO_INDEX_PORT); + outb_p(0x08, IO_DATA_PORT); + outb_p(0xF2, IO_INDEX_PORT); + outb_p(timeoutM, IO_DATA_PORT); /* lock the SuperIO chip */ - outb(0xAA,0x370); + outb_p(LOCK_DATA, IO_INDEX_PORT); + spin_unlock_irqrestore(&spinlock, flags); return 0; } @@ -203,22 +224,26 @@ static int wdt977_set_timeout(int t) static int wdt977_get_status(int *status) { int new_status; + unsigned long flags; - *status=0; + spin_lock_irqsave(&spinlock, flags); /* unlock the SuperIO chip */ - outb(0x87,0x370); - outb(0x87,0x370); + outb_p(UNLOCK_DATA, IO_INDEX_PORT); + outb_p(UNLOCK_DATA, IO_INDEX_PORT); /* select device Aux2 (device=8) and read watchdog reg F4 */ - outb(0x07,0x370); - outb(0x08,0x371); - outb(0xF4,0x370); - new_status = inb(0x371); + outb_p(DEVICE_REGISTER, IO_INDEX_PORT); + outb_p(0x08, IO_DATA_PORT); + outb_p(0xF4, IO_INDEX_PORT); + new_status = inb_p(IO_DATA_PORT); /* lock the SuperIO chip */ - outb(0xAA,0x370); + outb_p(LOCK_DATA, IO_INDEX_PORT); + spin_unlock_irqrestore(&spinlock, flags); + + *status=0; if (new_status & 1) *status |= WDIOF_CARDRESET; @@ -254,8 +279,8 @@ static int wdt977_release(struct inode *inode, struct file *file) wdt977_stop(); clear_bit(0,&timer_alive); } else { - printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); wdt977_keepalive(); + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); } expect_close = 0; return 0; @@ -276,14 +301,17 @@ static int wdt977_release(struct inode *inode, struct file *file) static ssize_t wdt977_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - if (count) { - if (!nowayout) { + if (count) + { + if (!nowayout) + { size_t i; /* In case it was set long ago */ expect_close = 0; - for (i = 0; i != count; i++) { + for (i = 0; i != count; i++) + { char c; if (get_user(c, buf + i)) return -EFAULT; @@ -292,6 +320,7 @@ static ssize_t wdt977_write(struct file *file, const char __user *buf, } } + /* someone wrote to us, we should restart timer */ wdt977_keepalive(); } return count; @@ -313,7 +342,7 @@ static struct watchdog_info ident = { WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, .firmware_version = 1, - .identity = "Winbond 83977", + .identity = WATCHDOG_NAME, }; static int wdt977_ioctl(struct inode *inode, struct file *file, @@ -332,7 +361,7 @@ static int wdt977_ioctl(struct inode *inode, struct file *file, switch(cmd) { default: - return -ENOIOCTLCMD; + return -ENOTTY; case WDIOC_GETSUPPORT: return copy_to_user(uarg.ident, &ident, @@ -389,9 +418,10 @@ static int wdt977_notify_sys(struct notifier_block *this, unsigned long code, return NOTIFY_DONE; } -static struct file_operations wdt977_fops= +static const struct file_operations wdt977_fops= { .owner = THIS_MODULE, + .llseek = no_llseek, .write = wdt977_write, .ioctl = wdt977_ioctl, .open = wdt977_open, @@ -409,50 +439,81 @@ static struct notifier_block wdt977_notifier = { .notifier_call = wdt977_notify_sys, }; -static int __init nwwatchdog_init(void) +static int __init wd977_init(void) { - int retval; - if (!machine_is_netwinder()) - return -ENODEV; + int rc; + + //if (!machine_is_netwinder()) + // return -ENODEV; + + printk(KERN_INFO PFX DRIVER_VERSION); + + spin_lock_init(&spinlock); /* Check that the timeout value is within it's range ; if not reset to the default */ - if (wdt977_set_timeout(timeout)) { + if (wdt977_set_timeout(timeout)) + { wdt977_set_timeout(DEFAULT_TIMEOUT); printk(KERN_INFO PFX "timeout value must be 60"); +MODULE_AUTHOR("Woody Suwalski "); MODULE_DESCRIPTION("W83977AF Watchdog driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);