Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.39 266 lines 5.3 kB view raw
1/* 2 * Drivers for the Total Impact PPC based computer "BRIQ" 3 * by Dr. Karsten Jeppesen 4 * 5 */ 6 7#include <linux/module.h> 8 9#include <linux/types.h> 10#include <linux/errno.h> 11#include <linux/tty.h> 12#include <linux/timer.h> 13#include <linux/kernel.h> 14#include <linux/wait.h> 15#include <linux/string.h> 16#include <linux/ioport.h> 17#include <linux/delay.h> 18#include <linux/miscdevice.h> 19#include <linux/fs.h> 20#include <linux/mm.h> 21#include <linux/init.h> 22 23#include <asm/uaccess.h> 24#include <asm/io.h> 25#include <asm/prom.h> 26 27#define BRIQ_PANEL_MINOR 156 28#define BRIQ_PANEL_VFD_IOPORT 0x0390 29#define BRIQ_PANEL_LED_IOPORT 0x0398 30#define BRIQ_PANEL_VER "1.1 (04/20/2002)" 31#define BRIQ_PANEL_MSG0 "Loading Linux" 32 33static int vfd_is_open; 34static unsigned char vfd[40]; 35static int vfd_cursor; 36static unsigned char ledpb, led; 37 38static void update_vfd(void) 39{ 40 int i; 41 42 /* cursor home */ 43 outb(0x02, BRIQ_PANEL_VFD_IOPORT); 44 for (i=0; i<20; i++) 45 outb(vfd[i], BRIQ_PANEL_VFD_IOPORT + 1); 46 47 /* cursor to next line */ 48 outb(0xc0, BRIQ_PANEL_VFD_IOPORT); 49 for (i=20; i<40; i++) 50 outb(vfd[i], BRIQ_PANEL_VFD_IOPORT + 1); 51 52} 53 54static void set_led(char state) 55{ 56 if (state == 'R') 57 led = 0x01; 58 else if (state == 'G') 59 led = 0x02; 60 else if (state == 'Y') 61 led = 0x03; 62 else if (state == 'X') 63 led = 0x00; 64 outb(led, BRIQ_PANEL_LED_IOPORT); 65} 66 67static int briq_panel_open(struct inode *ino, struct file *filep) 68{ 69 tty_lock(); 70 /* enforce single access, vfd_is_open is protected by BKL */ 71 if (vfd_is_open) { 72 tty_unlock(); 73 return -EBUSY; 74 } 75 vfd_is_open = 1; 76 77 tty_unlock(); 78 return 0; 79} 80 81static int briq_panel_release(struct inode *ino, struct file *filep) 82{ 83 if (!vfd_is_open) 84 return -ENODEV; 85 86 vfd_is_open = 0; 87 88 return 0; 89} 90 91static ssize_t briq_panel_read(struct file *file, char __user *buf, size_t count, 92 loff_t *ppos) 93{ 94 unsigned short c; 95 unsigned char cp; 96 97 if (!vfd_is_open) 98 return -ENODEV; 99 100 c = (inb(BRIQ_PANEL_LED_IOPORT) & 0x000c) | (ledpb & 0x0003); 101 set_led(' '); 102 /* upper button released */ 103 if ((!(ledpb & 0x0004)) && (c & 0x0004)) { 104 cp = ' '; 105 ledpb = c; 106 if (copy_to_user(buf, &cp, 1)) 107 return -EFAULT; 108 return 1; 109 } 110 /* lower button released */ 111 else if ((!(ledpb & 0x0008)) && (c & 0x0008)) { 112 cp = '\r'; 113 ledpb = c; 114 if (copy_to_user(buf, &cp, 1)) 115 return -EFAULT; 116 return 1; 117 } else { 118 ledpb = c; 119 return 0; 120 } 121} 122 123static void scroll_vfd( void ) 124{ 125 int i; 126 127 for (i=0; i<20; i++) { 128 vfd[i] = vfd[i+20]; 129 vfd[i+20] = ' '; 130 } 131 vfd_cursor = 20; 132} 133 134static ssize_t briq_panel_write(struct file *file, const char __user *buf, size_t len, 135 loff_t *ppos) 136{ 137 size_t indx = len; 138 int i, esc = 0; 139 140 if (!vfd_is_open) 141 return -EBUSY; 142 143 for (;;) { 144 char c; 145 if (!indx) 146 break; 147 if (get_user(c, buf)) 148 return -EFAULT; 149 if (esc) { 150 set_led(c); 151 esc = 0; 152 } else if (c == 27) { 153 esc = 1; 154 } else if (c == 12) { 155 /* do a form feed */ 156 for (i=0; i<40; i++) 157 vfd[i] = ' '; 158 vfd_cursor = 0; 159 } else if (c == 10) { 160 if (vfd_cursor < 20) 161 vfd_cursor = 20; 162 else if (vfd_cursor < 40) 163 vfd_cursor = 40; 164 else if (vfd_cursor < 60) 165 vfd_cursor = 60; 166 if (vfd_cursor > 59) 167 scroll_vfd(); 168 } else { 169 /* just a character */ 170 if (vfd_cursor > 39) 171 scroll_vfd(); 172 vfd[vfd_cursor++] = c; 173 } 174 indx--; 175 buf++; 176 } 177 update_vfd(); 178 179 return len; 180} 181 182static const struct file_operations briq_panel_fops = { 183 .owner = THIS_MODULE, 184 .read = briq_panel_read, 185 .write = briq_panel_write, 186 .open = briq_panel_open, 187 .release = briq_panel_release, 188 .llseek = noop_llseek, 189}; 190 191static struct miscdevice briq_panel_miscdev = { 192 BRIQ_PANEL_MINOR, 193 "briq_panel", 194 &briq_panel_fops 195}; 196 197static int __init briq_panel_init(void) 198{ 199 struct device_node *root = of_find_node_by_path("/"); 200 const char *machine; 201 int i; 202 203 machine = of_get_property(root, "model", NULL); 204 if (!machine || strncmp(machine, "TotalImpact,BRIQ-1", 18) != 0) { 205 of_node_put(root); 206 return -ENODEV; 207 } 208 of_node_put(root); 209 210 printk(KERN_INFO 211 "briq_panel: v%s Dr. Karsten Jeppesen (kj@totalimpact.com)\n", 212 BRIQ_PANEL_VER); 213 214 if (!request_region(BRIQ_PANEL_VFD_IOPORT, 4, "BRIQ Front Panel")) 215 return -EBUSY; 216 217 if (!request_region(BRIQ_PANEL_LED_IOPORT, 2, "BRIQ Front Panel")) { 218 release_region(BRIQ_PANEL_VFD_IOPORT, 4); 219 return -EBUSY; 220 } 221 ledpb = inb(BRIQ_PANEL_LED_IOPORT) & 0x000c; 222 223 if (misc_register(&briq_panel_miscdev) < 0) { 224 release_region(BRIQ_PANEL_VFD_IOPORT, 4); 225 release_region(BRIQ_PANEL_LED_IOPORT, 2); 226 return -EBUSY; 227 } 228 229 outb(0x38, BRIQ_PANEL_VFD_IOPORT); /* Function set */ 230 outb(0x01, BRIQ_PANEL_VFD_IOPORT); /* Clear display */ 231 outb(0x0c, BRIQ_PANEL_VFD_IOPORT); /* Display on */ 232 outb(0x06, BRIQ_PANEL_VFD_IOPORT); /* Entry normal */ 233 for (i=0; i<40; i++) 234 vfd[i]=' '; 235#ifndef MODULE 236 vfd[0] = 'L'; 237 vfd[1] = 'o'; 238 vfd[2] = 'a'; 239 vfd[3] = 'd'; 240 vfd[4] = 'i'; 241 vfd[5] = 'n'; 242 vfd[6] = 'g'; 243 vfd[7] = ' '; 244 vfd[8] = '.'; 245 vfd[9] = '.'; 246 vfd[10] = '.'; 247#endif /* !MODULE */ 248 249 update_vfd(); 250 251 return 0; 252} 253 254static void __exit briq_panel_exit(void) 255{ 256 misc_deregister(&briq_panel_miscdev); 257 release_region(BRIQ_PANEL_VFD_IOPORT, 4); 258 release_region(BRIQ_PANEL_LED_IOPORT, 2); 259} 260 261module_init(briq_panel_init); 262module_exit(briq_panel_exit); 263 264MODULE_LICENSE("GPL"); 265MODULE_AUTHOR("Karsten Jeppesen <karsten@jeppesens.com>"); 266MODULE_DESCRIPTION("Driver for the Total Impact briQ front panel");