Ejemplo n.º 1
0
static ssize_t wafwdt_write(struct file *file, const char __user *buf,
						size_t count, loff_t *ppos)
{
	
	if (count) {
		if (!nowayout) {
			size_t i;

			
			expect_close = 0;

			
			for (i = 0; i != count; i++) {
				char c;
				if (get_user(c, buf + i))
					return -EFAULT;
				if (c == 'V')
					expect_close = 42;
			}
		}
		
		wafwdt_ping();
	}
	return count;
}
Ejemplo n.º 2
0
static ssize_t wafwdt_write(struct file *file, const char __user *buf,
						size_t count, loff_t *ppos)
{
	/* See if we got the magic character 'V' and reload the timer */
	if (count) {
		if (!nowayout) {
			size_t i;

			/* In case it was set long ago */
			expect_close = 0;

			/* scan to see whether or not we got the magic
			   character */
			for (i = 0; i != count; i++) {
				char c;
				if (get_user(c, buf + i))
					return -EFAULT;
				if (c == 'V')
					expect_close = 42;
			}
		}
		/* Well, anyhow someone wrote to us, we should
		   return that favour */
		wafwdt_ping();
	}
	return count;
}
Ejemplo n.º 3
0
static long wafwdt_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 = 1,
		.identity = "Wafer 5823 WDT",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user(argp, &ident, sizeof(ident)))
			return -EFAULT;
		break;

	case WDIOC_GETSTATUS:
	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) {
			wafwdt_start();
			retval = 0;
		}

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

		return retval;
	}

	case WDIOC_KEEPALIVE:
		wafwdt_ping();
		break;

	case WDIOC_SETTIMEOUT:
		if (get_user(new_timeout, p))
			return -EFAULT;
		if ((new_timeout < 1) || (new_timeout > 255))
			return -EINVAL;
		timeout = new_timeout;
		wafwdt_stop();
		wafwdt_start();
		
	case WDIOC_GETTIMEOUT:
		return put_user(timeout, p);

	default:
		return -ENOTTY;
	}
	return 0;
}

static int wafwdt_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(0, &wafwdt_is_open))
		return -EBUSY;

	
	wafwdt_start();
	return nonseekable_open(inode, file);
}

static int wafwdt_close(struct inode *inode, struct file *file)
{
	if (expect_close == 42)
		wafwdt_stop();
	else {
		printk(KERN_CRIT PFX
		    "WDT device closed unexpectedly.  WDT will not stop!\n");
		wafwdt_ping();
	}
	clear_bit(0, &wafwdt_is_open);
	expect_close = 0;
	return 0;
}



static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code,
								void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		wafwdt_stop();
	return NOTIFY_DONE;
}



static const struct file_operations wafwdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= wafwdt_write,
	.unlocked_ioctl	= wafwdt_ioctl,
	.open		= wafwdt_open,
	.release	= wafwdt_close,
};

static struct miscdevice wafwdt_miscdev = {
	.minor	= WATCHDOG_MINOR,
	.name	= "watchdog",
	.fops	= &wafwdt_fops,
};



static struct notifier_block wafwdt_notifier = {
	.notifier_call = wafwdt_notify_sys,
};

static int __init wafwdt_init(void)
{
	int ret;

	printk(KERN_INFO
	  "WDT driver for Wafer 5823 single board computer initialising.\n");

	if (timeout < 1 || timeout > 255) {
		timeout = WD_TIMO;
		printk(KERN_INFO PFX
			"timeout value must be 1 <= x <= 255, using %d\n",
								timeout);
	}

	if (wdt_stop != wdt_start) {
		if (!request_region(wdt_stop, 1, "Wafer 5823 WDT")) {
			printk(KERN_ERR PFX
				"I/O address 0x%04x already in use\n",
								wdt_stop);
			ret = -EIO;
			goto error;
		}
	}

	if (!request_region(wdt_start, 1, "Wafer 5823 WDT")) {
		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
			wdt_start);
		ret = -EIO;
		goto error2;
	}

	ret = register_reboot_notifier(&wafwdt_notifier);
	if (ret != 0) {
		printk(KERN_ERR PFX
			"cannot register reboot notifier (err=%d)\n", ret);
		goto error3;
	}

	ret = misc_register(&wafwdt_miscdev);
	if (ret != 0) {
		printk(KERN_ERR PFX
			"cannot register miscdev on minor=%d (err=%d)\n",
						WATCHDOG_MINOR, ret);
		goto error4;
	}

	printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);

	return ret;
error4:
	unregister_reboot_notifier(&wafwdt_notifier);
error3:
	release_region(wdt_start, 1);
error2:
	if (wdt_stop != wdt_start)
		release_region(wdt_stop, 1);
error:
	return ret;
}

static void __exit wafwdt_exit(void)
{
	misc_deregister(&wafwdt_miscdev);
	unregister_reboot_notifier(&wafwdt_notifier);
	if (wdt_stop != wdt_start)
		release_region(wdt_stop, 1);
	release_region(wdt_start, 1);
}