Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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);
	}
	up(&open_sem);
	expect_close = 0;

	return 0;
}
Ejemplo n.º 3
0
static ssize_t sc1200wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
{
	if (ppos != &file->f_pos)
		return -ESPIPE;
	
	if (len) {
#ifndef CONFIG_WATCHDOG_NOWAYOUT
		size_t i;

		expect_close = 0;

		for (i = 0; i != len; i++)
		{
			if (data[i] == 'V')
				expect_close = 42;
		}
#endif
		sc1200wdt_write_data(WDTO, timeout);
		return len;
	}

	return 0;
}
Ejemplo n.º 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 = ""},
Ejemplo n.º 5
0
static void sc1200wdt_stop(void)
{
	sc1200wdt_write_data(WDTO, 0);
}
Ejemplo n.º 6
0
static int sc1200wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	int new_timeout;
	static struct watchdog_info ident = {
		options:		WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT,
		firmware_version:	0,
		identity:		"PC87307/PC97307"
	};

	switch (cmd) {
		default:
			return -ENOTTY;	/* Keep Pavel Machek amused ;) */

		case WDIOC_GETSUPPORT:
			if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof ident))
				return -EFAULT;
			return 0;

		case WDIOC_GETSTATUS:
			return put_user(sc1200wdt_status(), (int *)arg);

		case WDIOC_GETBOOTSTATUS:
			return put_user(0, (int *)arg);

		case WDIOC_KEEPALIVE:
			sc1200wdt_write_data(WDTO, timeout);
			return 0;

		case WDIOC_SETTIMEOUT:
			if (get_user(new_timeout, (int *)arg))
				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, (int *)arg);

		case WDIOC_SETOPTIONS:
		{
			int options, retval = -EINVAL;

			if (get_user(options, (int *)arg))
				return -EFAULT;

			if (options & WDIOS_DISABLECARD) {
				sc1200wdt_stop();
				retval = 0;
			}

			if (options & WDIOS_ENABLECARD) {
				sc1200wdt_start();
				retval = 0;
			}

			return retval;
		}
	}
}
Ejemplo n.º 7
0
static int sc1200wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
	int new_timeout;
	static struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
		.firmware_version = 0,
		.identity = "PC87307/PC97307"
	};

	switch (cmd) {
		default:
			return -ENOTTY;	/* Keep Pavel Machek amused ;) */

		case WDIOC_GETSUPPORT:
			if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof ident))
				return -EFAULT;
			return 0;

		case WDIOC_GETSTATUS:
			return put_user(sc1200wdt_status(), (int *)arg);

		case WDIOC_GETBOOTSTATUS:
			return put_user(0, (int *)arg);

		case WDIOC_KEEPALIVE:
			sc1200wdt_write_data(WDTO, timeout);
			return 0;

		case WDIOC_SETTIMEOUT:
			if (get_user(new_timeout, (int *)arg))
				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, (int *)arg);

		case WDIOC_SETOPTIONS:
		{
			int options, retval = -EINVAL;

			if (get_user(options, (int *)arg))
				return -EFAULT;

			if (options & WDIOS_DISABLECARD) {
				sc1200wdt_stop();
				retval = 0;
			}

			if (options & WDIOS_ENABLECARD) {
				sc1200wdt_start();
				retval = 0;
			}

			return retval;
		}
	}
}


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);
	}
	up(&open_sem);
	expect_close = 0;

	return 0;
}


static ssize_t sc1200wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos)
{
	if (ppos != &file->f_pos)
		return -ESPIPE;
	
	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
};