示例#1
0
文件: sc1200wdt.c 项目: cilynx/dd-wrt
static void sc1200wdt_start(void)
{
	unsigned char reg;

	sc1200wdt_read_data(WDCF, &reg);
	/* 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);
}
示例#2
0
/* 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;
}
示例#3
0
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);
	reg &= 0x0f;				/* we don't want the UART busy bits */
	return (reg == 0x0e) ? 0 : -ENODEV;
}
示例#4
0
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);
	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 = ""},