示例#1
0
static ssize_t wdtpci_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
	/*  Can't seek (pwrite) on this device  */
	if (ppos != &file->f_pos)
		return -ESPIPE;

	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 = 1;
			}
		}
		wdtpci_ping();
	}

	return count;
}
示例#2
0
static int wdtpci_release(struct inode *inode, struct file *file)
{

	if (iminor(inode)==WATCHDOG_MINOR) {
		unsigned long flags;
		if (expect_close) {
			spin_lock_irqsave(&wdtpci_lock, flags);
			inb_p(WDT_DC);		/* Disable counters */
			wdtpci_ctr_load(2,0);	/* 0 length reset pulses now */
			spin_unlock_irqrestore(&wdtpci_lock, flags);
		} else {
			printk(KERN_CRIT PFX "Unexpected close, not stopping timer!");
			wdtpci_ping();
		}
		up(&open_sem);
	}
	return 0;
}
示例#3
0
static ssize_t wdtpci_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;
			}
		}
		wdtpci_ping();
	}
	return count;
}
示例#4
0
static long wdtpci_ioctl(struct file *file, unsigned int cmd,
							unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	int new_heartbeat;
	int status;

	struct watchdog_info ident = {
		.options =		WDIOF_SETTIMEOUT|
					WDIOF_MAGICCLOSE|
					WDIOF_KEEPALIVEPING,
		.firmware_version =	1,
		.identity =		"PCI-WDT500/501",
	};

	/* Add options according to the card we have */
	ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2);
	if (type == 501) {
		ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER|
							WDIOF_POWEROVER);
		if (tachometer)
			ident.options |= WDIOF_FANFAULT;
	}

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
	case WDIOC_GETSTATUS:
		wdtpci_get_status(&status);
		return put_user(status, p);
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);
	case WDIOC_KEEPALIVE:
		wdtpci_ping();
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_heartbeat, p))
			return -EFAULT;
		if (wdtpci_set_heartbeat(new_heartbeat))
			return -EINVAL;
		wdtpci_ping();
		/* Fall */
	case WDIOC_GETTIMEOUT:
		return put_user(heartbeat, p);
	default:
		return -ENOTTY;
	}
}


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

	if (nowayout)
		__module_get(THIS_MODULE);
	/*
	 *	Activate
	 */
	wdtpci_start();
	return nonseekable_open(inode, file);
}


static int wdtpci_release(struct inode *inode, struct file *file)
{
	if (expect_close == 42) {
		wdtpci_stop();
	} else {
		printk(KERN_CRIT PFX "Unexpected close, not stopping timer!");
		wdtpci_ping();
	}
	expect_close = 0;
	clear_bit(0, &open_lock);
	return 0;
}


static ssize_t wdtpci_temp_read(struct file *file, char __user *buf,
						size_t count, loff_t *ptr)
{
	int temperature;

	if (wdtpci_get_temperature(&temperature))
		return -EFAULT;

	if (copy_to_user(buf, &temperature, 1))
		return -EFAULT;

	return 1;
}
示例#5
0
static long wdtpci_ioctl(struct file *file, unsigned int cmd,
							unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	int new_heartbeat;
	int status;

	struct watchdog_info ident = {
		.options =		WDIOF_SETTIMEOUT|
					WDIOF_MAGICCLOSE|
					WDIOF_KEEPALIVEPING,
		.firmware_version =	1,
		.identity =		"PCI-WDT500/501",
	};

	/* Add options according to the card we have */
	ident.options |= (WDIOF_EXTERN1|WDIOF_EXTERN2);
	if (type == 501) {
		ident.options |= (WDIOF_OVERHEAT|WDIOF_POWERUNDER|
							WDIOF_POWEROVER);
		if (tachometer)
			ident.options |= WDIOF_FANFAULT;
	}

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
	case WDIOC_GETSTATUS:
		wdtpci_get_status(&status);
		return put_user(status, p);
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, p);
	case WDIOC_KEEPALIVE:
		wdtpci_ping();
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_heartbeat, p))
			return -EFAULT;
		if (wdtpci_set_heartbeat(new_heartbeat))
			return -EINVAL;
		wdtpci_ping();
		/* Fall */
	case WDIOC_GETTIMEOUT:
		return put_user(heartbeat, p);
	default:
		return -ENOTTY;
	}
}

/**
 *	wdtpci_open:
 *	@inode: inode of device
 *	@file: file handle to device
 *
 *	The watchdog device has been opened. The watchdog device is single
 *	open and on opening we load the counters. Counter zero is a 100Hz
 *	cascade, into counter 1 which downcounts to reboot. When the counter
 *	triggers counter 2 downcounts the length of the reset pulse which
 *	set set to be as long as possible.
 */

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

	if (nowayout)
		__module_get(THIS_MODULE);
	/*
	 *	Activate
	 */
	wdtpci_start();
	return nonseekable_open(inode, file);
}

/**
 *	wdtpci_release:
 *	@inode: inode to board
 *	@file: file handle to board
 *
 *	The watchdog has a configurable API. There is a religious dispute
 *	between people who want their watchdog to be able to shut down and
 *	those who want to be sure if the watchdog manager dies the machine
 *	reboots. In the former case we disable the counters, in the latter
 *	case you have to open it again very soon.
 */

static int wdtpci_release(struct inode *inode, struct file *file)
{
	if (expect_close == 42) {
		wdtpci_stop();
	} else {
		pr_crit("Unexpected close, not stopping timer!\n");
		wdtpci_ping();
	}
	expect_close = 0;
	clear_bit(0, &open_lock);
	return 0;
}

/**
 *	wdtpci_temp_read:
 *	@file: file handle to the watchdog board
 *	@buf: buffer to write 1 byte into
 *	@count: length of buffer
 *	@ptr: offset (no seek allowed)
 *
 *	Read reports the temperature in degrees Fahrenheit. The API is in
 *	fahrenheit. It was designed by an imperial measurement luddite.
 */

static ssize_t wdtpci_temp_read(struct file *file, char __user *buf,
						size_t count, loff_t *ptr)
{
	int temperature;

	if (wdtpci_get_temperature(&temperature))
		return -EFAULT;

	if (copy_to_user(buf, &temperature, 1))
		return -EFAULT;

	return 1;
}
示例#6
0
static int wdtpci_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	unsigned long arg)
{
	int new_margin;
	static struct watchdog_info ident = {
		.options	= WDIOF_OVERHEAT  | WDIOF_POWERUNDER |
				  WDIOF_POWEROVER | WDIOF_EXTERN1 |
				  WDIOF_EXTERN2   | WDIOF_FANFAULT |
				  WDIOF_SETTIMEOUT|WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity	  = "WDT500/501PCI",
	};
	
	ident.options&=WDT_OPTION_MASK;	/* Mask down to the card we have */
	switch(cmd)
	{
		default:
			return -ENOTTY;
		case WDIOC_GETSUPPORT:
			return copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))?-EFAULT:0;

		case WDIOC_GETSTATUS:
			return put_user(wdtpci_status(),(int *)arg);
		case WDIOC_GETBOOTSTATUS:
			return put_user(0, (int *)arg);
		case WDIOC_KEEPALIVE:
			wdtpci_ping();
			return 0;
		case WDIOC_SETTIMEOUT:
			if (get_user(new_margin, (int *)arg))
				return -EFAULT;
			/* Arbitrary, can't find the card's limits */
			new_margin *= 100;
			if ((new_margin < 0) || (new_margin > WD_TIMO_MAX))
				return -EINVAL;
			wd_margin = new_margin;
			wdtpci_ping();
			/* Fall */
		case WDIOC_GETTIMEOUT:
			return put_user(wd_margin / 100, (int *)arg);
	}
}

/**
 *	wdtpci_open:
 *	@inode: inode of device
 *	@file: file handle to device
 *
 *	One of our two misc devices has been opened. The watchdog device is
 *	single open and on opening we load the counters. Counter zero is a 
 *	100Hz cascade, into counter 1 which downcounts to reboot. When the
 *	counter triggers counter 2 downcounts the length of the reset pulse
 *	which set set to be as long as possible. 
 */
 
static int wdtpci_open(struct inode *inode, struct file *file)
{
	unsigned long flags;

	switch(iminor(inode))
	{
		case WATCHDOG_MINOR:
			if (down_trylock(&open_sem))
				return -EBUSY;

			if (nowayout) {
				__module_get(THIS_MODULE);
			}
			/*
			 *	Activate 
			 */
			spin_lock_irqsave(&wdtpci_lock, flags);
			
			inb_p(WDT_DC);		/* Disable */

			/*
			 * "pet" the watchdog, as Access says.
			 * This resets the clock outputs.
			 */
				
			wdtpci_ctr_mode(2,0);
			outb_p(0, WDT_DC);

			inb_p(WDT_DC);

			outb_p(0, WDT_CLOCK);	/* 2.0833MHz clock */
			inb_p(WDT_BUZZER);	/* disable */
			inb_p(WDT_OPTONOTRST);	/* disable */
			inb_p(WDT_OPTORST);	/* disable */
			inb_p(WDT_PROGOUT);	/* disable */
			wdtpci_ctr_mode(0,3);
			wdtpci_ctr_mode(1,2);
			wdtpci_ctr_mode(2,1);
			wdtpci_ctr_load(0,20833);	/* count at 100Hz */
			wdtpci_ctr_load(1,wd_margin);/* Timeout 60 seconds */
			/* DO NOT LOAD CTR2 on PCI card! -- JPN */
			outb_p(0, WDT_DC);	/* Enable */
			spin_unlock_irqrestore(&wdtpci_lock, flags);
			return 0;
		case TEMP_MINOR:
			return 0;
		default:
			return -ENODEV;
	}
}