Exemplo n.º 1
0
Arquivo: pcwd.c Projeto: 020gzh/linux
static void pcwd_isa_shutdown(struct device *dev, unsigned int id)
{
	if (debug >= DEBUG)
		pr_debug("pcwd_isa_shutdown id=%d\n", id);

	pcwd_stop();
}
Exemplo n.º 2
0
static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id)
{
	if (debug >= DEBUG)
		printk(KERN_DEBUG PFX "pcwd_isa_remove id=%d\n",
			id);

	if (!pcwd_private.io_addr)
		return 1;

	/*  Disable the board  */
	if (!nowayout)
		pcwd_stop();

	/* Deregister */
	misc_deregister(&pcwd_miscdev);
	if (pcwd_private.supports_temp)
		misc_deregister(&temp_miscdev);
	release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
	pcwd_private.io_addr = 0x0000;
	cards_found--;

	return 0;
}
Exemplo n.º 3
0
static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id)
{
	int ret;

	if (debug >= DEBUG)
		printk(KERN_DEBUG PFX "pcwd_isa_probe id=%d\n",
			id);

	cards_found++;
	if (cards_found == 1)
		printk(KERN_INFO PFX "v%s Ken Hollis ([email protected])\n",
							WATCHDOG_VERSION);

	if (cards_found > 1) {
		printk(KERN_ERR PFX "This driver only supports 1 device\n");
		return -ENODEV;
	}

	if (pcwd_ioports[id] == 0x0000) {
		printk(KERN_ERR PFX "No I/O-Address for card detected\n");
		return -ENODEV;
	}
	pcwd_private.io_addr = pcwd_ioports[id];

	spin_lock_init(&pcwd_private.io_lock);

	/* Check card's revision */
	pcwd_private.revision = get_revision();

	if (!request_region(pcwd_private.io_addr,
		(pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) {
		printk(KERN_ERR PFX "I/O address 0x%04x already in use\n",
			pcwd_private.io_addr);
		ret = -EIO;
		goto error_request_region;
	}

	/* Initial variables */
	pcwd_private.supports_temp = 0;
	temp_panic = 0;
	pcwd_private.boot_status = 0x0000;

	/* get the boot_status */
	pcwd_get_status(&pcwd_private.boot_status);

	/* clear the "card caused reboot" flag */
	pcwd_clear_status();

	setup_timer(&pcwd_private.timer, pcwd_timer_ping, 0);

	/*  Disable the board  */
	pcwd_stop();

	/*  Check whether or not the card supports the temperature device */
	pcwd_check_temperature_support();

	/* Show info about the card itself */
	pcwd_show_card_info();

	/* If heartbeat = 0 then we use the heartbeat from the dip-switches */
	if (heartbeat == 0)
		heartbeat = heartbeat_tbl[(pcwd_get_option_switches() & 0x07)];

	/* Check that the heartbeat value is within it's range;
	   if not reset to the default */
	if (pcwd_set_heartbeat(heartbeat)) {
		pcwd_set_heartbeat(WATCHDOG_HEARTBEAT);
		printk(KERN_INFO PFX
		  "heartbeat value must be 2 <= heartbeat <= 7200, using %d\n",
							WATCHDOG_HEARTBEAT);
	}

	if (pcwd_private.supports_temp) {
		ret = misc_register(&temp_miscdev);
		if (ret) {
			printk(KERN_ERR PFX
			    "cannot register miscdev on minor=%d (err=%d)\n",
							TEMP_MINOR, ret);
			goto error_misc_register_temp;
		}
	}

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

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

	return 0;

error_misc_register_watchdog:
	if (pcwd_private.supports_temp)
		misc_deregister(&temp_miscdev);
error_misc_register_temp:
	release_region(pcwd_private.io_addr,
			(pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4);
error_request_region:
	pcwd_private.io_addr = 0x0000;
	cards_found--;
	return ret;
}
Exemplo n.º 4
0
static long pcwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	int rv;
	int status;
	int temperature;
	int new_heartbeat;
	int __user *argp = (int __user *)arg;
	static const struct watchdog_info ident = {
		.options =		WDIOF_OVERHEAT |
					WDIOF_CARDRESET |
					WDIOF_KEEPALIVEPING |
					WDIOF_SETTIMEOUT |
					WDIOF_MAGICCLOSE,
		.firmware_version =	1,
		.identity =		"PCWD",
	};

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

	case WDIOC_GETSTATUS:
		pcwd_get_status(&status);
		return put_user(status, argp);

	case WDIOC_GETBOOTSTATUS:
		return put_user(pcwd_private.boot_status, argp);

	case WDIOC_GETTEMP:
		if (pcwd_get_temperature(&temperature))
			return -EFAULT;

		return put_user(temperature, argp);

	case WDIOC_SETOPTIONS:
		if (pcwd_private.revision == PCWD_REVISION_C) {
			if (get_user(rv, argp))
				return -EFAULT;

			if (rv & WDIOS_DISABLECARD) {
				status = pcwd_stop();
				if (status < 0)
					return status;
			}
			if (rv & WDIOS_ENABLECARD) {
				status = pcwd_start();
				if (status < 0)
					return status;
			}
			if (rv & WDIOS_TEMPPANIC)
				temp_panic = 1;
		}
		return -EINVAL;

	case WDIOC_KEEPALIVE:
		pcwd_keepalive();
		return 0;

	case WDIOC_SETTIMEOUT:
		if (get_user(new_heartbeat, argp))
			return -EFAULT;

		if (pcwd_set_heartbeat(new_heartbeat))
			return -EINVAL;

		pcwd_keepalive();
		/* Fall */

	case WDIOC_GETTIMEOUT:
		return put_user(heartbeat, argp);

	default:
		return -ENOTTY;
	}

	return 0;
}

static ssize_t pcwd_write(struct file *file, const char __user *buf, size_t len,
			  loff_t *ppos)
{
	if (len) {
		if (!nowayout) {
			size_t i;

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

			for (i = 0; i != len; i++) {
				char c;

				if (get_user(c, buf + i))
					return -EFAULT;
				if (c == 'V')
					expect_close = 42;
			}
		}
		pcwd_keepalive();
	}
	return len;
}

static int pcwd_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(0, &open_allowed))
		return -EBUSY;
	if (nowayout)
		__module_get(THIS_MODULE);
	/* Activate */
	pcwd_start();
	pcwd_keepalive();
	return nonseekable_open(inode, file);
}

static int pcwd_close(struct inode *inode, struct file *file)
{
	if (expect_close == 42)
		pcwd_stop();
	else {
		printk(KERN_CRIT PFX
			"Unexpected close, not stopping watchdog!\n");
		pcwd_keepalive();
	}
	expect_close = 0;
	clear_bit(0, &open_allowed);
	return 0;
}

/*
 *	/dev/temperature handling
 */

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

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

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

	return 1;
}
Exemplo n.º 5
0
Arquivo: pcwd.c Projeto: wxlong/Test
static int pcwd_ioctl(struct inode *inode, struct file *file,
		      unsigned int cmd, unsigned long arg)
{
	int rv;
	int status;
	int temperature;
	int new_heartbeat;
	static struct watchdog_info ident = {
		.options =		WDIOF_OVERHEAT |
					WDIOF_CARDRESET |
					WDIOF_KEEPALIVEPING |
					WDIOF_SETTIMEOUT |
					WDIOF_MAGICCLOSE,
		.firmware_version =	1,
		.identity =		"PCWD",
	};

	switch(cmd) {
	default:
		return -ENOIOCTLCMD;

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

	case WDIOC_GETSTATUS:
		pcwd_get_status(&status);
		return put_user(status, (int *) arg);

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

	case WDIOC_GETTEMP:
		if (pcwd_get_temperature(&temperature))
			return -EFAULT;

		return put_user(temperature, (int *) arg);

	case WDIOC_SETOPTIONS:
		if (revision == PCWD_REVISION_C)
		{
			if(copy_from_user(&rv, (int*) arg, sizeof(int)))
				return -EFAULT;

			if (rv & WDIOS_DISABLECARD)
			{
				return pcwd_stop();
			}

			if (rv & WDIOS_ENABLECARD)
			{
				return pcwd_start();
			}

			if (rv & WDIOS_TEMPPANIC)
			{
				temp_panic = 1;
			}
		}
		return -EINVAL;

	case WDIOC_KEEPALIVE:
		pcwd_keepalive();
		return 0;

	case WDIOC_SETTIMEOUT:
		if (get_user(new_heartbeat, (int *) arg))
			return -EFAULT;

		if (pcwd_set_heartbeat(new_heartbeat))
			return -EINVAL;

		pcwd_keepalive();
		/* Fall */

	case WDIOC_GETTIMEOUT:
		return put_user(heartbeat, (int *)arg);
	}

	return 0;
}

static ssize_t pcwd_write(struct file *file, const char *buf, size_t len,
			  loff_t *ppos)
{
	/*  Can't seek (pwrite) on this device  */
	if (ppos != &file->f_pos)
		return -ESPIPE;

	if (len) {
		if (!nowayout) {
			size_t i;

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

			for (i = 0; i != len; i++) {
				char c;

				if (get_user(c, buf + i))
					return -EFAULT;
				if (c == 'V')
					expect_close = 42;
			}
		}
		pcwd_keepalive();
	}
	return len;
}

static int pcwd_open(struct inode *inode, struct file *file)
{
	if (!atomic_dec_and_test(&open_allowed) ) {
		atomic_inc( &open_allowed );
		return -EBUSY;
	}

	if (nowayout)
		__module_get(THIS_MODULE);

	/* Activate */
	pcwd_start();
	pcwd_keepalive();
	return(0);
}

static int pcwd_close(struct inode *inode, struct file *file)
{
	if (expect_close == 42) {
		pcwd_stop();
		atomic_inc( &open_allowed );
	} else {
		printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n");
		pcwd_keepalive();
	}
	expect_close = 0;
	return 0;
}

/*
 *	/dev/temperature handling
 */

static ssize_t pcwd_temp_read(struct file *file, char *buf, size_t count,
			 loff_t *ppos)
{
	int temperature;

	/* Can't seek (pread) on this device */
	if (ppos != &file->f_pos)
		return -ESPIPE;

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

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

	return 1;
}