📄 pcwd.c
字号:
return -EFAULT; return 0; case WDIOC_SETOPTIONS: if (revision == PCWD_REVISION_C) { if(copy_from_user(&rv, (int*) arg, sizeof(int))) return -EFAULT; if (rv & WDIOS_DISABLECARD) { spin_lock(&io_lock); outb_p(0xA5, current_readport + 3); outb_p(0xA5, current_readport + 3); cdat = inb_p(current_readport + 2); spin_unlock(&io_lock); if ((cdat & 0x10) == 0) { printk("pcwd: Could not disable card.\n"); return -EIO; } return 0; } if (rv & WDIOS_ENABLECARD) { spin_lock(&io_lock); outb_p(0x00, current_readport + 3); cdat = inb_p(current_readport + 2); spin_unlock(&io_lock); if (cdat & 0x10) { printk("pcwd: Could not enable card.\n"); return -EIO; } return 0; } if (rv & WDIOS_TEMPPANIC) { temp_panic = 1; } } return -EINVAL; case WDIOC_KEEPALIVE: pcwd_send_heartbeat(); return 0; } 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) { pcwd_send_heartbeat(); return 1; } return 0;}static int pcwd_open(struct inode *ino, struct file *filep){ switch (MINOR(ino->i_rdev)) { case WATCHDOG_MINOR: if (is_open) return -EBUSY; MOD_INC_USE_COUNT; /* Enable the port */ if (revision == PCWD_REVISION_C) { spin_lock(&io_lock); outb_p(0x00, current_readport + 3); spin_unlock(&io_lock); } is_open = 1; return(0); case TEMP_MINOR: return(0); default: return (-ENODEV); }}static ssize_t pcwd_read(struct file *file, char *buf, size_t count, loff_t *ppos){ unsigned short c; unsigned char cp; /* 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: /* * Convert metric to Fahrenheit, since this was * the decided 'standard' for this return value. */ c = inb(current_readport); cp = (c * 9 / 5) + 32; if(copy_to_user(buf, &cp, 1)) return -EFAULT; return 1; default: return -EINVAL; }}static int pcwd_close(struct inode *ino, struct file *filep){ if (MINOR(ino->i_rdev)==WATCHDOG_MINOR) { lock_kernel(); is_open = 0;#ifndef CONFIG_WATCHDOG_NOWAYOUT /* Disable the board */ if (revision == PCWD_REVISION_C) { spin_lock(&io_lock); outb_p(0xA5, current_readport + 3); outb_p(0xA5, current_readport + 3); spin_unlock(&io_lock); } unlock_kernel();#endif } return 0;}static inline void get_support(void){ if (inb(current_readport) != 0xF0) supports_temp = 1;}static inline int get_revision(void){ int r = PCWD_REVISION_C; spin_lock(&io_lock); if ((inb(current_readport + 2) == 0xFF) || (inb(current_readport + 3) == 0xFF)) r=PCWD_REVISION_A; spin_unlock(&io_lock); return r;}static int __init send_command(int cmd){ int i; outb_p(cmd, current_readport + 2); mdelay(1); i = inb(current_readport); i = inb(current_readport); return(i);}static inline char *get_firmware(void){ int i, found = 0, count = 0, one, ten, hund, minor; char *ret; ret = kmalloc(6, GFP_KERNEL); while((count < 3) && (!found)) { outb_p(0x80, current_readport + 2); i = inb(current_readport); if (i == 0x00) found = 1; else if (i == 0xF3) outb_p(0x00, current_readport + 2); udelay(400L); count++; } if (found) { mode_debug = 1; one = send_command(0x81); ten = send_command(0x82); hund = send_command(0x83); minor = send_command(0x84); } if (found) sprintf(ret, "%c.%c%c%c", one, ten, hund, minor); else sprintf(ret, "ERROR"); return(ret);}static void debug_off(void){ outb_p(0x00, current_readport + 2); mode_debug = 0;}static struct file_operations pcwd_fops = { owner: THIS_MODULE, read: pcwd_read, write: pcwd_write, ioctl: pcwd_ioctl, open: pcwd_open, release: pcwd_close,};static struct miscdevice pcwd_miscdev = { WATCHDOG_MINOR, "watchdog", &pcwd_fops};static struct miscdevice temp_miscdev = { TEMP_MINOR, "temperature", &pcwd_fops}; static int __init pcwatchdog_init(void){ int i, found = 0; spin_lock_init(&io_lock); revision = PCWD_REVISION_A; printk("pcwd: v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER); /* Initial variables */ is_open = 0; supports_temp = 0; mode_debug = 0; temp_panic = 0; initial_status = 0x0000;#ifndef PCWD_BLIND for (i = 0; pcwd_ioports[i] != 0; i++) { current_readport = pcwd_ioports[i]; if (pcwd_checkcard()) { found = 1; break; } } if (!found) { printk("pcwd: No card detected, or port not available.\n"); return(-EIO); }#endif#ifdef PCWD_BLIND current_readport = PCWD_BLIND;#endif get_support(); revision = get_revision(); if (revision == PCWD_REVISION_A) printk("pcwd: PC Watchdog (REV.A) detected at port 0x%03x\n", current_readport); else if (revision == PCWD_REVISION_C) printk("pcwd: PC Watchdog (REV.C) detected at port 0x%03x (Firmware version: %s)\n", current_readport, get_firmware()); else { /* Should NEVER happen, unless get_revision() fails. */ printk("pcwd: Unable to get revision.\n"); return -1; } if (supports_temp) printk("pcwd: Temperature Option Detected.\n"); debug_off(); pcwd_showprevstate(); /* Disable the board */ if (revision == PCWD_REVISION_C) { outb_p(0xA5, current_readport + 3); outb_p(0xA5, current_readport + 3); } if (revision == PCWD_REVISION_A) request_region(current_readport, 2, "PCWD Rev.A (Berkshire)"); else request_region(current_readport, 4, "PCWD Rev.C (Berkshire)"); misc_register(&pcwd_miscdev); if (supports_temp) misc_register(&temp_miscdev); return 0;}static void __exit pcwatchdog_exit(void){ /* Disable the board */ if (revision == PCWD_REVISION_C) { outb_p(0xA5, current_readport + 3); outb_p(0xA5, current_readport + 3); } misc_deregister(&pcwd_miscdev); if (supports_temp) misc_deregister(&temp_miscdev); release_region(current_readport, (revision == PCWD_REVISION_A) ? 2 : 4);}module_init(pcwatchdog_init);module_exit(pcwatchdog_exit);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -