briq_panel.c
来自「linux 内核源代码」· C语言 代码 · 共 263 行
C
263 行
/* * Drivers for the Total Impact PPC based computer "BRIQ" * by Dr. Karsten Jeppesen * */#include <linux/module.h>#include <linux/types.h>#include <linux/errno.h>#include <linux/tty.h>#include <linux/timer.h>#include <linux/kernel.h>#include <linux/wait.h>#include <linux/string.h>#include <linux/slab.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/miscdevice.h>#include <linux/fs.h>#include <linux/mm.h>#include <linux/init.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/prom.h>#define BRIQ_PANEL_MINOR 156#define BRIQ_PANEL_VFD_IOPORT 0x0390#define BRIQ_PANEL_LED_IOPORT 0x0398#define BRIQ_PANEL_VER "1.1 (04/20/2002)"#define BRIQ_PANEL_MSG0 "Loading Linux"static int vfd_is_open;static unsigned char vfd[40];static int vfd_cursor;static unsigned char ledpb, led;static void update_vfd(void){ int i; /* cursor home */ outb(0x02, BRIQ_PANEL_VFD_IOPORT); for (i=0; i<20; i++) outb(vfd[i], BRIQ_PANEL_VFD_IOPORT + 1); /* cursor to next line */ outb(0xc0, BRIQ_PANEL_VFD_IOPORT); for (i=20; i<40; i++) outb(vfd[i], BRIQ_PANEL_VFD_IOPORT + 1);}static void set_led(char state){ if (state == 'R') led = 0x01; else if (state == 'G') led = 0x02; else if (state == 'Y') led = 0x03; else if (state == 'X') led = 0x00; outb(led, BRIQ_PANEL_LED_IOPORT);}static int briq_panel_open(struct inode *ino, struct file *filep){ /* enforce single access */ if (vfd_is_open) return -EBUSY; vfd_is_open = 1; return 0;}static int briq_panel_release(struct inode *ino, struct file *filep){ if (!vfd_is_open) return -ENODEV; vfd_is_open = 0; return 0;}static ssize_t briq_panel_read(struct file *file, char __user *buf, size_t count, loff_t *ppos){ unsigned short c; unsigned char cp; if (!vfd_is_open) return -ENODEV; c = (inb(BRIQ_PANEL_LED_IOPORT) & 0x000c) | (ledpb & 0x0003); set_led(' '); /* upper button released */ if ((!(ledpb & 0x0004)) && (c & 0x0004)) { cp = ' '; ledpb = c; if (copy_to_user(buf, &cp, 1)) return -EFAULT; return 1; } /* lower button released */ else if ((!(ledpb & 0x0008)) && (c & 0x0008)) { cp = '\r'; ledpb = c; if (copy_to_user(buf, &cp, 1)) return -EFAULT; return 1; } else { ledpb = c; return 0; }}static void scroll_vfd( void ){ int i; for (i=0; i<20; i++) { vfd[i] = vfd[i+20]; vfd[i+20] = ' '; } vfd_cursor = 20;}static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos){ size_t indx = len; int i, esc = 0; if (!vfd_is_open) return -EBUSY; for (;;) { char c; if (!indx) break; if (get_user(c, buf)) return -EFAULT; if (esc) { set_led(c); esc = 0; } else if (c == 27) { esc = 1; } else if (c == 12) { /* do a form feed */ for (i=0; i<40; i++) vfd[i] = ' '; vfd_cursor = 0; } else if (c == 10) { if (vfd_cursor < 20) vfd_cursor = 20; else if (vfd_cursor < 40) vfd_cursor = 40; else if (vfd_cursor < 60) vfd_cursor = 60; if (vfd_cursor > 59) scroll_vfd(); } else { /* just a character */ if (vfd_cursor > 39) scroll_vfd(); vfd[vfd_cursor++] = c; } indx--; buf++; } update_vfd(); return len;}static const struct file_operations briq_panel_fops = { .owner = THIS_MODULE, .read = briq_panel_read, .write = briq_panel_write, .open = briq_panel_open, .release = briq_panel_release,};static struct miscdevice briq_panel_miscdev = { BRIQ_PANEL_MINOR, "briq_panel", &briq_panel_fops};static int __init briq_panel_init(void){ struct device_node *root = of_find_node_by_path("/"); const char *machine; int i; machine = of_get_property(root, "model", NULL); if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) { of_node_put(root); return -ENODEV; } of_node_put(root); printk(KERN_INFO "briq_panel: v%s Dr. Karsten Jeppesen (kj@totalimpact.com)\n", BRIQ_PANEL_VER); if (!request_region(BRIQ_PANEL_VFD_IOPORT, 4, "BRIQ Front Panel")) return -EBUSY; if (!request_region(BRIQ_PANEL_LED_IOPORT, 2, "BRIQ Front Panel")) { release_region(BRIQ_PANEL_VFD_IOPORT, 4); return -EBUSY; } ledpb = inb(BRIQ_PANEL_LED_IOPORT) & 0x000c; if (misc_register(&briq_panel_miscdev) < 0) { release_region(BRIQ_PANEL_VFD_IOPORT, 4); release_region(BRIQ_PANEL_LED_IOPORT, 2); return -EBUSY; } outb(0x38, BRIQ_PANEL_VFD_IOPORT); /* Function set */ outb(0x01, BRIQ_PANEL_VFD_IOPORT); /* Clear display */ outb(0x0c, BRIQ_PANEL_VFD_IOPORT); /* Display on */ outb(0x06, BRIQ_PANEL_VFD_IOPORT); /* Entry normal */ for (i=0; i<40; i++) vfd[i]=' ';#ifndef MODULE vfd[0] = 'L'; vfd[1] = 'o'; vfd[2] = 'a'; vfd[3] = 'd'; vfd[4] = 'i'; vfd[5] = 'n'; vfd[6] = 'g'; vfd[7] = ' '; vfd[8] = '.'; vfd[9] = '.'; vfd[10] = '.';#endif /* !MODULE */ update_vfd(); return 0;}static void __exit briq_panel_exit(void){ misc_deregister(&briq_panel_miscdev); release_region(BRIQ_PANEL_VFD_IOPORT, 4); release_region(BRIQ_PANEL_LED_IOPORT, 2);}module_init(briq_panel_init);module_exit(briq_panel_exit);MODULE_LICENSE("GPL");MODULE_AUTHOR("Karsten Jeppesen <karsten@jeppesens.com>");MODULE_DESCRIPTION("Driver for the Total Impact briQ front panel");
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?