static void sc1200wdt_start(void) { unsigned char reg; sc1200wdt_read_data(WDCF, ®); /* assert WDO when any of the following interrupts are triggered too */ reg |= (KBC_IRQ | MSE_IRQ | UART1_IRQ | UART2_IRQ); sc1200wdt_write_data(WDCF, reg); /* set the timeout and get the ball rolling */ sc1200wdt_write_data(WDTO, timeout); }
/* This returns the status of the WDO signal, inactive high. */ static inline int sc1200wdt_status(void) { unsigned char ret; sc1200wdt_read_data(WDST, &ret); /* If the bit is inactive, the watchdog is enabled, so return * KEEPALIVEPING which is a bit of a kludge because there's nothing * else for enabled/disabled status */ return (ret & 0x01) ? 0 : WDIOF_KEEPALIVEPING; }
static int __init sc1200wdt_probe(void) { /* The probe works by reading the PMC3 register's default value of 0x0e * there is one caveat, if the device disables the parallel port or any * of the UARTs we won't be able to detect it. * Nb. This could be done with accuracy by reading the SID registers, but * we don't have access to those io regions. */ unsigned char reg; sc1200wdt_read_data(PMC3, ®); reg &= 0x0f; /* we don't want the UART busy bits */ return (reg == 0x0e) ? 0 : -ENODEV; }
static long sc1200wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { int new_timeout; void __user *argp = (void __user *)arg; int __user *p = argp; static const struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, .firmware_version = 0, .identity = "PC87307/PC97307", }; switch (cmd) { case WDIOC_GETSUPPORT: if (copy_to_user(argp, &ident, sizeof(ident))) return -EFAULT; return 0; case WDIOC_GETSTATUS: return put_user(sc1200wdt_status(), p); case WDIOC_GETBOOTSTATUS: return put_user(0, p); case WDIOC_SETOPTIONS: { int options, retval = -EINVAL; if (get_user(options, p)) return -EFAULT; if (options & WDIOS_DISABLECARD) { sc1200wdt_stop(); retval = 0; } if (options & WDIOS_ENABLECARD) { sc1200wdt_start(); retval = 0; } return retval; } case WDIOC_KEEPALIVE: sc1200wdt_write_data(WDTO, timeout); return 0; case WDIOC_SETTIMEOUT: if (get_user(new_timeout, p)) return -EFAULT; /* the API states this is given in secs */ new_timeout /= 60; if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) return -EINVAL; timeout = new_timeout; sc1200wdt_write_data(WDTO, timeout); /* fall through and return the new timeout */ case WDIOC_GETTIMEOUT: return put_user(timeout * 60, p); default: return -ENOTTY; } } static int sc1200wdt_release(struct inode *inode, struct file *file) { if (expect_close == 42) { sc1200wdt_stop(); printk(KERN_INFO PFX "Watchdog disabled\n"); } else { sc1200wdt_write_data(WDTO, timeout); printk(KERN_CRIT PFX "Unexpected close!, timeout = %d min(s)\n", timeout); } clear_bit(0, &open_flag); expect_close = 0; return 0; } static ssize_t sc1200wdt_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) { if (len) { if (!nowayout) { size_t i; expect_close = 0; for (i = 0; i != len; i++) { char c; if (get_user(c, data + i)) return -EFAULT; if (c == 'V') expect_close = 42; } } sc1200wdt_write_data(WDTO, timeout); return len; } return 0; } static int sc1200wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) { if (code == SYS_DOWN || code == SYS_HALT) sc1200wdt_stop(); return NOTIFY_DONE; } static struct notifier_block sc1200wdt_notifier = { .notifier_call = sc1200wdt_notify_sys, }; static const struct file_operations sc1200wdt_fops = { .owner = THIS_MODULE, .llseek = no_llseek, .write = sc1200wdt_write, .unlocked_ioctl = sc1200wdt_ioctl, .open = sc1200wdt_open, .release = sc1200wdt_release, }; static struct miscdevice sc1200wdt_miscdev = { .minor = WATCHDOG_MINOR, .name = "watchdog", .fops = &sc1200wdt_fops, }; static int __init sc1200wdt_probe(void) { /* The probe works by reading the PMC3 register's default value of 0x0e * there is one caveat, if the device disables the parallel port or any * of the UARTs we won't be able to detect it. * NB. This could be done with accuracy by reading the SID registers, * but we don't have access to those io regions. */ unsigned char reg; sc1200wdt_read_data(PMC3, ®); reg &= 0x0f; /* we don't want the UART busy bits */ return (reg == 0x0e) ? 0 : -ENODEV; } #if defined CONFIG_PNP static struct pnp_device_id scl200wdt_pnp_devices[] = { /* National Semiconductor PC87307/PC97307 watchdog component */ {.id = "NSC0800", .driver_data = 0}, {.id = ""},