⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcwd.c

📁 PC watch dog driver
💻 C
📖 第 1 页 / 共 3 页
字号:
static voidpcwd_get_fw_string(void){	if (revision == PCWD_PCI) {		int firmware_revision;		firmware_revision = send_command_ret16(0x08, 0, 0);		pcwd_fw_rev_major = firmware_revision / 256;		pcwd_fw_rev_minor = firmware_revision % 256;		sprintf(pcwd_fw_string, "%u.%02u", pcwd_fw_rev_major,			pcwd_fw_rev_minor);	} else {		if (pcwd_set_diag() == ENABLED) {			int one, ten, hund, minor;			one = send_diag_command(0x81);			ten = send_diag_command(0x82);			hund = send_diag_command(0x83);			minor = send_diag_command(0x84);			sprintf(pcwd_fw_string, "%c.%c%c%c", one, ten, hund,				minor);		} else {			sprintf(pcwd_fw_string, "ERROR");		}	}}static voidpcwd_show_card_stats(void){	switch (revision) {	case PCWD_REVISION_A:		printk(KERN_INFO		       "pcwd: PC Watchdog Card at 0x%x: REV.A %s temp option.\n",		       (int) card_ioport, (supports_temp ? "with" : "without"));		break;	case PCWD_REVISION_C:		printk(KERN_INFO		       "pcwd: PC Watchdog Card at 0x%x: REV.C (Firmware: %s) %s temp option.\n",		       (int) card_ioport, pcwd_fw_string,		       (supports_temp ? "with" : "without"));		break;	case PCWD_PCI:		printk(KERN_INFO		       "pcwd: PCI PC Watchdog Card at 0x%x: (Firmware: %s) %s temp option.\n",		       (int) card_ioport, pcwd_fw_string,		       (supports_temp ? "with" : "without"));		break;	default:		printk(KERN_ERR		       "pcwd: Unknown or unsupported card or revision.\n");	}	pcwd_get_trip_status();	if (initial_status & 0x01)		printk(KERN_INFO		       "pcwd: Previous reset was caused by the Watchdog card.\n");	if (initial_status & 0x04)		printk(KERN_INFO "pcwd: Card sensed a CPU Overheat.\n");	if (!(initial_status & 0x01))		printk(KERN_INFO		       "pcwd: No previous trip detected - Cold boot or reset.\n");}static voidpcwd_ping(void){	if (revision == PCWD_PCI) {		spin_lock(&pcwd_io_lock);		outb_p(0xfc, card_ioport);	/* send out any data */		spin_unlock(&pcwd_io_lock);	} else {		int wdrst_stat;		spin_lock(&pcwd_io_lock);		wdrst_stat = inb_p(card_ioport);		wdrst_stat &= 0x0F;		wdrst_stat |= 0x01;	/* Previously reset state */		if (revision == PCWD_REVISION_A)			outb_p(wdrst_stat, card_ioport + 1);		else			outb_p(wdrst_stat, card_ioport);		spin_unlock(&pcwd_io_lock);	}	if (card_status == ENABLED)		ping_counter++;}/* The file operation functions for user access to /dev/watchdog */static intpcwd_open(struct inode *inode, struct file *file){	switch (MINOR(inode->i_rdev)) {	case WATCHDOG_MINOR:		spin_lock(&pcwd_lock);		if (in_use) {			spin_unlock(&pcwd_lock);			printk(KERN_ERR			       "pcwd: Attempt to open already opened device.\n");			return -EBUSY;		}		MOD_INC_USE_COUNT;		in_use++;		spin_unlock(&pcwd_lock);		return 0;	case TEMP_MINOR:		MOD_INC_USE_COUNT;		return 0;	default:		return -ENODEV;	}}static intpcwd_release(struct inode *inode, struct file *file){	lock_kernel();	MOD_DEC_USE_COUNT;	if (MINOR(inode->i_rdev) == WATCHDOG_MINOR) {		spin_lock(&pcwd_lock);		if (!nowayout)			pcwd_disable_card();		in_use--;		spin_unlock(&pcwd_lock);	}	unlock_kernel();	return 0;}/*static long longpcwd_llseek(struct file *file, long long offset, int origin){	return -ESPIPE;}*/static ssize_tpcwd_read(struct file *file, char *buf, size_t len, loff_t * ppos){	unsigned short temp;	temp = pcwd_get_temperature();	/*  Can't seek (pread) on this device */	if (ppos != &file->f_pos)		return -ESPIPE;	switch (MINOR(file->f_dentry->d_inode->i_rdev)) {	case TEMP_MINOR:	case WATCHDOG_MINOR:		if (copy_to_user(buf, &temp, 1))			return -EFAULT;		return 0;	default:		return -EINVAL;	}}static ssize_tpcwd_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) {		pcwd_ping();		return 1;	}	return 0;}static intpcwd_ioctl(struct inode *inode, struct file *file,	   unsigned int cmd, unsigned long arg){	int rv;	int retval;	static struct watchdog_info ident = {		WDIOF_OVERHEAT | WDIOF_CARDRESET,		1,		"PCWD"	};	switch (cmd) {	case WDIOC_GETSUPPORT:		rv = copy_to_user((void *) arg, &ident, sizeof (ident));		return rv ? -EFAULT : 0;	case WDIOC_GETSTATUS:		if (initial_status & WDIOF_OVERHEAT) {			if (pcwd_temp_panic == ENABLED)				panic("pcwd: Temperature overheat trip!\n");		}		if (put_user(initial_status, (int *) arg))			return -EFAULT;		return 0;	case WDIOC_GETBOOTSTATUS:		if (put_user(initial_status, (int *) arg))			return -EFAULT;		return 0;	case WDIOC_GETTEMP:		rv = 0;		if (supports_temp)			rv = pcwd_get_temperature();		if (put_user(rv, (int *) arg))			return -EFAULT;		return 0;	case WDIOC_SETOPTIONS:		if (copy_from_user(&rv, (int *) arg, sizeof (int)))			return -EFAULT;		retval = -EINVAL;		if (rv & WDIOS_DISABLECARD) {			if (!pcwd_disable_card())				return -EIO;			retval = 0;		}		if (rv & WDIOS_ENABLECARD) {			if (!pcwd_enable_card())				return -EIO;			retval = 0;		}		if (rv & WDIOS_TEMPPANIC) {			pcwd_temp_panic = ENABLED;			retval = 0;		}		return retval;	case WDIOC_KEEPALIVE:		pcwd_ping();		return 0;	default:		return -ENOTTY;	}}#ifdef CONFIG_PROC_FSstatic intpcwd_set_relay(char *sub_command){	char *new_sub_command = sub_command;	int i;	while (*sub_command == ' ')		sub_command++;	if (sub_command == new_sub_command) {		printk("relay value: %d\n", send_command_ret8(0x50, 0, 0));		return 0;	}	i = send_command_ret8(0x50, 0, 0);	// read the relays	if (strcmp(sub_command, "1on") == 0) {		i = send_command_ret8(0x51, 0, (i | 1) & (0xff - 4));		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: relay 1on\n");	} else if (strcmp(sub_command, "1off") == 0) {		i = send_command_ret8(0x51, 0, (i | 4) & (0xff - 1));		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: relay 1off\n");	} else if (strcmp(sub_command, "2on") == 0) {		i = send_command_ret8(0x51, 0, (i | 2) & (0xff - 8));		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: relay 2on\n");	} else if (strcmp(sub_command, "2off") == 0) {		i = send_command_ret8(0x51, 0, (i | 8) & (0xff - 2));		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: relay 2off\n");	} else if (strcmp(sub_command, "1invert") == 0) {		if (pcwd_verbose >= DEBUG) {			printk(KERN_DEBUG "pcwd: before: 0x%02x\n", i);			printk(KERN_DEBUG "pcwd: sending: 0x%02x\n", i | 0x10);		}		i = send_command_ret8(0x51, 0, i | 0x10);		if (pcwd_verbose >= DEBUG) {			i = send_command_ret8(0x50, 0, 0);	// read the relays			printk(KERN_DEBUG "pcwd: after: 0x%02x\n", i);		}		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: relay 1invert\n");	} else if (strcmp(sub_command, "1noinvert") == 0) {		if (pcwd_verbose >= DEBUG) {			printk(KERN_DEBUG "pcwd: before: 0x%02x\n", i);			printk(KERN_DEBUG "pcwd: sending: 0x%02x\n",			       i & (0xff - 0x10));		}		i = send_command_ret8(0x51, 0, i & (0xff - 0x10));		if (pcwd_verbose >= DEBUG) {			i = send_command_ret8(0x50, 0, 0);	// read the relays			printk(KERN_DEBUG "pcwd: after: 0x%2x\n", i);		}		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: relay 1noinvert\n");	} else if (strcmp(sub_command, "1nvinvert") == 0) {		if (pcwd_verbose >= DEBUG) {			printk(KERN_DEBUG "pcwd: before: 0x%02x\n", i);			printk(KERN_DEBUG "pcwd: sending: 0x%02x\n", i | 0x80);		}		i = send_command_ret8(0x51, 0, i | 0x80);		if (pcwd_verbose >= DEBUG) {			i = send_command_ret8(0x50, 0, 0);	// read the relays			printk(KERN_DEBUG "pcwd: after: 0x%02x\n", i);		}		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: relay 1nvinvert\n");	} else if (strcmp(sub_command, "1nvnoinvert") == 0) {		if (pcwd_verbose >= DEBUG) {			printk(KERN_DEBUG "pcwd: before: 0x%02x\n", i);			printk(KERN_DEBUG "pcwd: sending: 0x%02x\n",			       i & (0xff - 0x80));		}		i = send_command_ret8(0x51, 0, i & (0xff - 0x80));		if (pcwd_verbose >= DEBUG) {			i = send_command_ret8(0x50, 0, 0);	// read the relays			printk(KERN_DEBUG "pcwd: after: 0x%02x\n", i);		}		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: relay 1nvnoinvert\n");	} else if (strcmp(sub_command, "2notemp") == 0) {		outb_p(0x40, card_ioport + 1);		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: relay 2notemp\n");		pcwd_get_relay2_mode();	} else if (strcmp(sub_command, "2temp") == 0) {		outb_p(0x00, card_ioport + 1);		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: relay 2temp\n");		pcwd_get_relay2_mode();	} else {		printk(KERN_ERR		       "pcwd: illegal relay argument '%s', should be 1on, 1off, 2on, 2off, 1invert, 1noinvert, 1nvinvert, 1nvnoinvert, 2temp or 2notemp\n",		       sub_command);		return 1;	}	return 0;}static intpcwd_set_dio(char *sub_command){	char *new_sub_command = sub_command;	int i;	while (*sub_command == ' ')		sub_command++;	if (sub_command == new_sub_command) {		printk("dio value: %d\n", (inb(card_ioport + 7) / 16) & 15);		return 0;	}	i = simple_strtoul(sub_command, NULL, 0);	if ((i >= 0) && (i < 16)) {		outb_p(i, card_ioport + 7);		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: dio %d\n", i);	} else {		printk(KERN_ERR		       "pcwd: illegal dio argument '%s', should be a number between 0 and 15\n",		       sub_command);		return 1;	}	return 0;}static intpcwd_set_nv_timeout_pci(char *sub_command){	char *new_sub_command = sub_command;	int i;	while (*sub_command == ' ')		sub_command++;	if (sub_command == new_sub_command) {		printk("nvtimeout value: %d\n", send_command_ret16(0x1C, 0, 0));		return 0;	}	i = simple_strtoul(sub_command, NULL, 0);	if (i == 0)		printk("returning to default DIP switch settings.\n");	if ((i >= 0) && (i <= 0xffff)) {		send_command(0x1D, i / 256, i % 256);		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: nvtimeout %d\n", i);	} else {		printk(KERN_ERR		       "pcwd: illegal nvtimeout argument '%s', should be a number between 0 and 65535\n",		       sub_command);		return 1;	}	return 0;}static intpcwd_set_timeout_pci(char *sub_command){	char *new_sub_command = sub_command;	int i;	while (*sub_command == ' ')		sub_command++;	if (sub_command == new_sub_command) {		printk("timeout value: %d\n", send_command_ret16(0x18, 0, 0));		return 0;	}	i = simple_strtoul(sub_command, NULL, 0);	if ((i >= 0) && (i <= 0xffff)) {		send_command(0x19, i / 256, i % 256);		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: timeout %d\n", i);	} else {		printk(KERN_ERR		       "pcwd: illegal timeout argument '%s', should be a number between 0 and 65535\n",		       sub_command);		return 1;	}	return 0;}static intpcwd_set_timeout(char *sub_command){	char *new_sub_command = sub_command;	while (*sub_command == ' ')		sub_command++;	if (sub_command == new_sub_command) {		printk(KERN_ERR		       "pcwd: illegal timeout argument '%s', should be 2, 4 or 8\n",		       sub_command);		return 1;	}	/* FIXME: show new timeouts also in proc */	if (strcmp(sub_command, "2") == 0) {		if (send_diag_command(0x8A) == 0x8A) {			if (pcwd_verbose >= VERBOSE)				printk(KERN_INFO "pcwd: timeout 2s\n");			return 0;		}	} else if (strcmp(sub_command, "4") == 0) {		if (send_diag_command(0x8B) == 0x8b) {			if (pcwd_verbose >= VERBOSE)				printk(KERN_INFO "pcwd: timeout 4s\n");			return 0;		}	} else if (strcmp(sub_command, "8") == 0) {		if (send_diag_command(0x8C) == 0x8C) {			if (pcwd_verbose >= VERBOSE)				printk(KERN_INFO "pcwd: timeout 8s\n");			return 0;		}	} else {		printk(KERN_ERR		       "pcwd: illegal timeout argument '%s', should be 2, 4 or 8\n",		       sub_command);		return 1;	}	return 0;}static intpcwd_set_nv_arm_pci(char *sub_command){	char *new_sub_command = sub_command;	int i;	while (*sub_command == ' ')		sub_command++;	if (sub_command == new_sub_command) {		printk("nvarm value: %d\n", send_command_ret16(0x14, 0, 0));		return 0;	}	i = simple_strtoul(sub_command, NULL, 0);	if ((i >= 0) && (i <= 0xffff)) {		send_command(0x15, i / 256, i % 256);		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: nvarm %d\n", i);	} else {		printk(KERN_ERR		       "pcwd: illegal nvarm argument '%s', should be a number between 0 and 65535\n",		       sub_command);		return 1;	}	return 0;}static intpcwd_set_arm_pci(char *sub_command){	char *new_sub_command = sub_command;	int i;	while (*sub_command == ' ')		sub_command++;	if (sub_command == new_sub_command) {		printk("arm value: %d\n", send_command_ret16(0x10, 0, 0));		return 0;	}	i = simple_strtoul(sub_command, NULL, 0);	if ((i >= 0) && (i <= 0xffff)) {		if (send_command_ret8(0x11, i / 256, i % 256) == 0) {			printk(KERN_INFO			       "pcwd: arm failed, board already armed!\n");			return 1;		}		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: arm %d\n", i);	} else {		printk(KERN_ERR		       "pcwd: illegal arm argument '%s', should be a number between 0 and 65535\n",		       sub_command);		return 1;	}	return 0;}static intpcwd_set_arm(char *sub_command){	char *new_sub_command = sub_command;	int i = 0;	while (*sub_command == ' ')		sub_command++;	if (sub_command == new_sub_command) {		printk(KERN_ERR		       "pcwd: illegal arm argument '%s', should be 0, 30 or 60\n",		       sub_command);		return 1;	}	pcwd_set_diag();	if ((strcmp(sub_command, "0") == 0)	    || (strcmp(sub_command, "immediately") == 0)) {		if ((i = send_diag_command(0x87)) == 0x87) {			if (pcwd_verbose >= VERBOSE)				printk(KERN_INFO "pcwd: arm immediately\n");			return 0;		}	} else if (strcmp(sub_command, "30") == 0) {		if ((i = send_diag_command(0x88)) == 0x88) {			if (pcwd_verbose >= VERBOSE)				printk(KERN_INFO "pcwd: arm after 30s more\n");			return 0;		}	} else if (strcmp(sub_command, "60") == 0) {		if ((i = send_diag_command(0x89)) != 0x89) {			if (pcwd_verbose >= VERBOSE)				printk(KERN_INFO "pcwd: arm after 60s more\n");			return 0;		}	} else {		printk(KERN_ERR		       "pcwd: illegal arm argument '%s', should be 0, 30 or 60\n",		       sub_command);		return 1;	}	if (i == 0xF5)		printk(KERN_INFO "pcwd: already armed\n");	return 0;}static intpcwd_set_tempoffset_pci(char *sub_command){	char *new_sub_command = sub_command;	int i;	while (*sub_command == ' ')		sub_command++;	if (sub_command == new_sub_command) {		printk("tempoffset value: %d\n", (inb(card_ioport + 2) & 15));		return 0;	}	i = simple_strtoul(sub_command, NULL, 0);	if ((i >= 0) && (i < 16)) {		outb_p(i, card_ioport + 2);		if (pcwd_verbose >= VERBOSE)			printk(KERN_INFO "pcwd: tempoffset %d\n", i);	} else {		printk(KERN_ERR		       "pcwd: illegal tempoffset argument '%s', should be a number between 0 and 15\n",		       sub_command);		return 1;	}	return 0;}static voidpcwd_user_help(void)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -