📄 pcwd.c
字号:
{ printk(" pcwd proc command interface help:\n"); printk(" ping, pong, tickle - tickle the timer\n"); printk(" hardreset - reset pc\n"); printk(" disable, enable - set watchdog mode\n"); printk(" clear - clear trip status and led - pci card only\n"); printk(" verbose, debug, quiet - command reponse\n"); printk(" fahrenheit, celsius - display temp in\n"); printk(" extended commands:\n"); printk(" arm [val] - isa [30,60,90], pci [any]\n"); printk(" nvarm [val] - pci card only\n"); printk(" timeout [val] - isa [2,4,8], pci [any]\n"); printk(" nvtimeout [val] - pci card only\n"); printk(" dio [val] - pci card only\n"); printk(" relay [1on,1off,2on,2off,1invert,1noinvert,\n"); printk (" 1nvinvert,1nvnoinvert,2temp,2notemp] - pci card only\n"); printk(" tempoffset [val] - pci card only\n");}static intpcwd_user_command(char *user_command){ if ((strcmp(user_command, "ping") == 0) || (strcmp(user_command, "pong") == 0) || (strcmp(user_command, "tickle") == 0)) { pcwd_ping(); if (pcwd_verbose >= VERBOSE) printk(KERN_INFO "pcwd: ping...\n"); } else if (strcmp(user_command, "disable") == 0) { if (pcwd_disable_card()) { if (pcwd_verbose >= VERBOSE) printk(KERN_INFO "pcwd: watchdog disabled!\n"); } else { printk(KERN_ERR "pcwd: disable watchdog FAILED!\n"); } } else if (strcmp(user_command, "enable") == 0) { if (pcwd_enable_card()) { if (pcwd_verbose >= VERBOSE) printk(KERN_INFO "pcwd: watchdog enabled.\n"); } else { printk(KERN_ERR "pcwd: enable watchdog FAILED.\n"); } } else if (strcmp(user_command, "clear") == 0) { pcwd_clear_status(); if (pcwd_verbose >= VERBOSE) printk(KERN_INFO "pcwd: cleared trip status\n"); } else if (strcmp(user_command, "hardreset") == 0) { pcwd_reset_pc(); if (pcwd_verbose >= VERBOSE) printk(KERN_INFO "pcwd: hardreset PC!\n"); } else if (strcmp(user_command, "verbose") == 0) { printk(KERN_INFO "pcwd: verbose mode on.\n"); pcwd_verbose = VERBOSE; } else if (strcmp(user_command, "debug") == 0) { printk(KERN_INFO "pcwd: debug mode on.\n"); pcwd_verbose = DEBUG; } else if (strcmp(user_command, "quiet") == 0) { pcwd_verbose = QUIET; } else if (strcmp(user_command, "celsius") == 0) { pcwd_temp_mode = CELSIUS; if (pcwd_verbose >= VERBOSE) printk(KERN_INFO "pcwd: display temp in Celsius.\n"); } else if (strcmp(user_command, "fahrenheit") == 0) { pcwd_temp_mode = FAHRENHEIT; if (pcwd_verbose >= VERBOSE) printk(KERN_INFO "pcwd: display temp in Fahrenheit.\n"); } else if (strcmp(user_command, "help") == 0) { pcwd_user_help(); } else if (strncmp(user_command, "arm", 3) == 0) { if (revision == PCWD_PCI) { if (pcwd_set_arm_pci(&user_command[3])) { printk(KERN_ERR "arm FAILED.\n"); return 0; } } else { // ISA CARD if ((pcwd_fw_string[0] >= '1') && (pcwd_fw_string[2] >= '2')) { if (pcwd_set_arm(&user_command[3])) { printk(KERN_ERR "arm FAILED.\n"); return 0; } } else { printk(KERN_ERR "pcwd: ISA Card and firmware > 1.20 needed.\n"); return 0; } } } else if (strncmp(user_command, "nvarm", 5) == 0) { if (revision == PCWD_PCI) { if (pcwd_set_nv_arm_pci(&user_command[5])) { printk(KERN_ERR "nvarm FAILED.\n"); return 0; } } else { // ISA CARD printk(KERN_ERR "pcwd: nvarm only works with a pci card.\n"); return 0; } } else if (strncmp(user_command, "timeout", 7) == 0) { if (revision == PCWD_PCI) { if (pcwd_set_timeout_pci(&user_command[7])) { printk(KERN_ERR "timeout FAILED.\n"); return 0; } } else { // ISA CARD if ((pcwd_fw_string[0] >= '1') && (pcwd_fw_string[2] >= '2')) { if (pcwd_set_timeout(&user_command[7])) { printk(KERN_ERR "timeout FAILED.\n"); return 0; } } else { // ISA FIRMWARE TOO OLD printk(KERN_ERR "pcwd: ISA Card and firmware > 1.20 needed.\n"); return 0; } } } else if (strncmp(user_command, "nvtimeout", 9) == 0) { if (revision == PCWD_PCI) { if (pcwd_set_nv_timeout_pci(&user_command[9])) { printk(KERN_ERR "nvtimeout FAILED.\n"); return 0; } } else { // ISA CARD printk(KERN_ERR "pcwd: nvtimeout only works with a pci card.\n"); return 0; } } else if (strncmp(user_command, "dio", 3) == 0) { if (revision == PCWD_PCI) { if (pcwd_set_dio(&user_command[3])) { printk(KERN_ERR "dio FAILED.\n"); return 0; } } else { // ISA CARD printk(KERN_ERR "pcwd: dio only works with a pci card.\n"); return 0; } } else if (strncmp(user_command, "relay", 5) == 0) { if (revision == PCWD_PCI) { if (pcwd_set_relay(&user_command[5])) { printk(KERN_ERR "relay FAILED.\n"); return 0; } } else { // ISA CARD printk(KERN_ERR "pcwd: relay only works with a pci card.\n"); return 0; } } else if (strncmp(user_command, "tempoffset", 10) == 0) { if (revision == PCWD_PCI) { if (pcwd_set_tempoffset_pci(&user_command[10])) { printk(KERN_ERR "tempoffset FAILED.\n"); return 0; } } else { // ISA CARD printk(KERN_ERR "pcwd: tempoffset only works with a pci card.\n"); return 0; } } else { printk(KERN_ERR "illegal user command: '%s'\n", user_command); pcwd_user_help(); return 0; } return 1;}static intpcwd_write_proc(struct file *file, const char *buffer, unsigned long count, void *data){ char command_buffer[80]; int rc, length; /* write only allowed for root users */ if (current->euid != 0) return -EACCES; if (count > sizeof (command_buffer) - 1) return -EINVAL; if (copy_from_user(command_buffer, buffer, count)) return -EFAULT; command_buffer[count] = '\0'; length = strlen(command_buffer); if (command_buffer[length - 1] == '\n') command_buffer[--length] = '\0'; spin_lock(&pcwd_lock); rc = pcwd_user_command(command_buffer); spin_unlock(&pcwd_lock); return (rc ? count : -EBUSY);}static int pcwd_proc_info(unsigned char *contents, char *buffer, int *len, off_t * begin, off_t offset, int size);static struct proc_dir_entry *proc_pcwd;static intpcwd_read_proc(char *buffer, char **start, off_t offset, int size, int *eof, void *data){ int len = 0; off_t begin = 0; spin_lock(&pcwd_lock); *eof = pcwd_proc_info(NULL, buffer, &len, &begin, offset, size); spin_unlock(&pcwd_lock); if (offset >= begin + len) return (0); *start = buffer + (offset - begin); // CORRECTED !!!! return (size < begin + len - offset ? size : begin + len - offset);}/* This macro frees the machine specific function from bounds checking and * * this like that... [from nvram.c]*/#define PRINT_PROC(fmt,args...) \ do { \ *len += sprintf( buffer+*len, fmt, ##args ); \ if (*begin + *len > offset + size) \ return( 0 ); \ if (*begin + *len < offset) { \ *begin += *len; \ *len = 0; \ } \ } while(0)static intpcwd_proc_info(unsigned char *buf, char *buffer, int *len, off_t * begin, off_t offset, int size){ int sw, i, j, t = 0; if (revision == PCWD_REVISION_C) { PRINT_PROC("PC Watchdog Driver %s\n", pcwd_driver_version); PRINT_PROC("Firmware : Version %s\n", pcwd_fw_string); PRINT_PROC("Option Switch: Delay Time "); sw = pcwd_get_switches(); switch (sw & 0x07) { case 0: PRINT_PROC("20 s"); break; case 1: PRINT_PROC("40 s"); break; case 2: PRINT_PROC("1 min"); break; case 3: PRINT_PROC("5 min"); break; case 4: PRINT_PROC("10 min"); break; case 5: PRINT_PROC("30 min"); break; case 6: PRINT_PROC("1 h"); break; case 7: PRINT_PROC("2 h"); break; } if (sw & 0x08) { PRINT_PROC(", POD on"); } else { PRINT_PROC(", POD off"); } if (sw & 0x10) { PRINT_PROC(", TRE on"); } else { PRINT_PROC(", TRE off"); } if (sw & 0x20) { PRINT_PROC(", R2M on"); } else { PRINT_PROC(", R2M off"); } if (sw & 0x40) { PRINT_PROC(", R1M on"); } else { PRINT_PROC(", R1M off"); } if (sw & 0x80) { PRINT_PROC(", RTM on\n"); } else { PRINT_PROC(", RTM off\n"); } } else if (revision == PCWD_PCI) { PRINT_PROC("PC PCI Watchdog Driver %s\n", pcwd_driver_version); PRINT_PROC("Firmware : Version %s\n", pcwd_fw_string); PRINT_PROC("Option Switch: Delay Time "); sw = pcwd_get_switches(); switch (sw & 0x07) { case 0: PRINT_PROC("5 s"); t = 5; break; case 1: PRINT_PROC("10 s"); t = 10; break; case 2: PRINT_PROC("30 s"); t = 30; break; case 3: PRINT_PROC("1 min"); t = 60; break; case 4: PRINT_PROC("5 min"); t = 300; break; case 5: PRINT_PROC("10 min"); t = 600; break; case 6: PRINT_PROC("30 min"); t = 1800; break; case 7: PRINT_PROC("1 h"); t = 3600; break; } if (sw & 0x08) { PRINT_PROC(", POD on"); } else { PRINT_PROC(", POD off"); } if (sw & 0x10) { PRINT_PROC(", TRE on"); } else { PRINT_PROC(", TRE off"); } if (sw & 0x20) { PRINT_PROC(", R2M on"); } else { PRINT_PROC(", R2M off"); } if (sw & 0x40) { PRINT_PROC(", R1M on"); } else { PRINT_PROC(", R1M off"); } if (sw & 0x80) { PRINT_PROC(", RTM on\n"); } else { PRINT_PROC(", RTM off\n"); } sw = send_command_ret8(0x50, 0, 0); PRINT_PROC("Relays : "); if (sw & 0x01) { PRINT_PROC("Relay 1 on"); } else { PRINT_PROC("Relay 1 off"); } if (sw & 0x02) { PRINT_PROC(", Relay 2 on"); } else { PRINT_PROC(", Relay 2 off"); } PRINT_PROC("\n "); if (sw & 0x10) { PRINT_PROC("Relay 1 invert, "); } if (sw & 0x80) { PRINT_PROC("Relay 1 invert in nvram, "); } if (temp_mode_relay2 == TEMPERATURE_TRIP) { PRINT_PROC("Relay 2 temp"); } else { PRINT_PROC("Relay 2 notemp"); } PRINT_PROC("\n"); i = send_command_ret16(0x14, 0, 0); // ARM NVRAM j = send_command_ret16(0x10, 0, 0); // ARM current PRINT_PROC("Arm Time : %d s (NVRAM: %d s)\n", j, i); i = send_command_ret16(0x1C, 0, 0); // Time NVRAM j = send_command_ret16(0x18, 0, 0); // Time current PRINT_PROC("Timer : %d s (NVRAM: %d s)\n", j, i); PRINT_PROC("Status : "); sw = send_command_ret8(0x04, 0, 0); if (sw & 0x01) { PRINT_PROC("NVRAM OK"); } else { PRINT_PROC("NVRAM FAILED"); } if (sw & 0x02) { PRINT_PROC(", TEMP SENSOR OK"); } else { PRINT_PROC(", TEMP SENSOR FAILED"); } if (sw & 0x80) { PRINT_PROC(", POD COMPLETED"); } else { PRINT_PROC(", POD ACTIVE"); } PRINT_PROC(".\n"); sw = inb(card_ioport + 7); PRINT_PROC("Digi I/O Port: OUT=%d, IN=%d\n", (sw & 15), ((sw / 16) & 15)); sw = send_command_ret8(0x84, 0, 0); PRINT_PROC("Reset Count : %d\n", sw); sw = inb(card_ioport + 2) & 15; PRINT_PROC("Temp.TripPt. : LOWER=%d 癈 UPPER=%d 癈\n", 46 + sw, 56 + sw); } else { PRINT_PROC("Firmware ROM not present\n"); } PRINT_PROC("Temperature : "); if (supports_temp) { PRINT_PROC("%d ", pcwd_get_temperature()); if (pcwd_temp_mode == CELSIUS) PRINT_PROC("癈\n"); else PRINT_PROC("癋\n"); } else { PRINT_PROC("Card without temp option\n"); } if (card_status == ENABLED) PRINT_PROC("Card status : Timer enabled\n"); else PRINT_PROC("Card status : Timer disabled\n"); if (pcwd_get_trip_status()) PRINT_PROC("Reboot status: Tripped\n"); else PRINT_PROC("Reboot status: Not tripped\n"); if (pcwd_verbose >= DEBUG) printk(KERN_INFO "pcwd: initial_status: 0x%02x\n", initial_status); if (initial_status & 0x02) { PRINT_PROC("Boot status : cleared by operator\n"); } else if ((initial_status & 0x01) && (initial_status & 0x04)) { PRINT_PROC ("Boot status : CPU Overheat + Watchdog caused reboot\n"); } else if (initial_status & 0x01) { PRINT_PROC("Boot status : Watchdog caused reboot\n"); } else if (initial_status & 0x04) { PRINT_PROC("Boot status : CPU Overheat\n"); } else { PRINT_PROC("Boot status : Cold boot or reset\n"); } // PRINT_PROC("Ping Count : %d\n", ping_counter); return 1;}#endif /* PROC_FS */static intpcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused){ if (code == SYS_DOWN || code == SYS_HALT) { pcwd_disable_card(); printk(KERN_INFO "pcwd: reboot notifier has disabled the card!\n"); //printk(KERN_INFO "pcwd: reboot notifier did not disable the card!\n"); } return NOTIFY_DONE;}static struct file_operations pcwd_fops = { owner:THIS_MODULE, write:pcwd_write, ioctl:pcwd_ioctl, open:pcwd_open, release:pcwd_release,};static struct miscdevice pcwd_miscdev = { WATCHDOG_MINOR, "watchdog", &pcwd_fops};static struct file_operations pcwd_temp_fops = { owner:THIS_MODULE, read:pcwd_read, open:pcwd_open, release:pcwd_release,};static struct miscdevice temp_miscdev = { TEMP_MINOR, "temperature", &pcwd_temp_fops};static struct notifier_block pcwd_notifier = { pcwd_notify_sys, NULL, 0};int __initpcwatchdog_init(void){ spin_lock_init(&pcwd_io_lock); spin_lock_init(&pcwd_lock); pcwd_get_version(); printk(KERN_INFO "pcwd: %s by <holger@eiboeck.de>\n", pcwd_driver_version); initial_status = 0; initial_status_set = 0; if ((!pcwd_find_card()) || (card_ioport == 0x000)) { printk(KERN_ERR "pcwd: No card detected.\n"); return -ENODEV; } pcwd_disable_card(); get_support(); get_revision(); pcwd_get_fw_string(); switch (revision) { case PCWD_REVISION_C: request_region(card_ioport, 4, "PCWD Rev C"); break; case PCWD_REVISION_A: request_region(card_ioport, 2, "PCWD Rev A"); break; case PCWD_PCI: request_region(card_ioport, 8, "PCWD PCI"); break; default: printk(KERN_ERR "pcwd: Unknown card revision.\n"); return -ENODEV; break; } pcwd_show_card_stats(); pcwd_init_status(); if (misc_register(&pcwd_miscdev) != 0) { release_region(card_ioport, (revision == PCWD_REVISION_A) ? 2 : (revision == PCWD_REVISION_C) ? 4 : 8); return -EIO; } if (supports_temp) if (misc_register(&temp_miscdev) != 0) { misc_deregister(&pcwd_miscdev); release_region(card_ioport, (revision == PCWD_REVISION_A) ? 2 : (revision == PCWD_REVISION_C) ? 4 : 8); return -EIO; }#ifdef CONFIG_PROC_FS if ((proc_pcwd = create_proc_entry("pcwd", S_IFREG | S_IRUGO | S_IWUSR, 0))) { proc_pcwd->read_proc = pcwd_read_proc; proc_pcwd->write_proc = pcwd_write_proc; }#endif if (nowayout) printk(KERN_INFO "pcwd: Watchdog cannot be stopped once started\n"); register_reboot_notifier(&pcwd_notifier); return 0;}void __exitpcwatchdog_exit(void){#ifdef CONFIG_PROC_FS if (proc_pcwd) remove_proc_entry("pcwd", 0);#endif lock_kernel(); if (!nowayout) pcwd_disable_card(); misc_deregister(&pcwd_miscdev); if (supports_temp) misc_deregister(&temp_miscdev); unregister_reboot_notifier(&pcwd_notifier); release_region(card_ioport, (revision == PCWD_REVISION_A) ? 2 : (revision == PCWD_REVISION_C) ? 4 : 8); unlock_kernel(); printk(KERN_INFO "pcwd: Watchdog Module Unloaded.\n");}module_init(pcwatchdog_init);module_exit(pcwatchdog_exit);MODULE_AUTHOR("Holger Eiboeck");MODULE_DESCRIPTION("Driver for the Berkshire PC watchdog cards");MODULE_LICENSE("GPL");EXPORT_NO_SYMBOLS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -