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.15 441 lines 10 kB view raw
1/* 2 * 3 * This file is subject to the terms and conditions of the GNU General Public 4 * License. See the file "COPYING" in the main directory of this archive 5 * for more details. 6 * 7 * Copyright (C) 1999-2002 Harald Koerfgen <hkoerfg@web.de> 8 * Copyright (C) 2001, 2002, 2003, 2004 Maciej W. Rozycki 9 */ 10 11#include <linux/config.h> 12 13#include <linux/errno.h> 14#include <linux/sched.h> 15#include <linux/tty.h> 16#include <linux/kernel.h> 17#include <linux/init.h> 18#include <linux/delay.h> 19#include <linux/kbd_ll.h> 20#include <linux/kbd_kern.h> 21#include <linux/vt_kern.h> 22 23#include <asm/keyboard.h> 24#include <asm/dec/tc.h> 25#include <asm/dec/machtype.h> 26#include <asm/dec/serial.h> 27 28#include "lk201.h" 29 30/* 31 * Only handle DECstations that have an LK201 interface. 32 * Maxine uses LK501 at the Access.Bus and various DECsystems 33 * have no keyboard interface at all. 34 */ 35#define LK_IFACE (mips_machtype == MACH_DS23100 || \ 36 mips_machtype == MACH_DS5000_200 || \ 37 mips_machtype == MACH_DS5000_1XX || \ 38 mips_machtype == MACH_DS5000_2X0) 39/* 40 * These use the Z8530 SCC. Others use the DZ11. 41 */ 42#define LK_IFACE_ZS (mips_machtype == MACH_DS5000_1XX || \ 43 mips_machtype == MACH_DS5000_2X0) 44 45/* Simple translation table for the SysRq keys */ 46 47#ifdef CONFIG_MAGIC_SYSRQ 48/* 49 * Actually no translation at all, at least until we figure out 50 * how to define SysRq for LK201 and friends. --macro 51 */ 52unsigned char lk201_sysrq_xlate[128]; 53unsigned char *kbd_sysrq_xlate = lk201_sysrq_xlate; 54 55unsigned char kbd_sysrq_key = -1; 56#endif 57 58#define KEYB_LINE 3 59 60static int __init lk201_init(void *); 61static void __init lk201_info(void *); 62static void lk201_rx_char(unsigned char, unsigned char); 63 64static struct dec_serial_hook lk201_hook = { 65 .init_channel = lk201_init, 66 .init_info = lk201_info, 67 .rx_char = NULL, 68 .poll_rx_char = NULL, 69 .poll_tx_char = NULL, 70 .cflags = B4800 | CS8 | CSTOPB | CLOCAL, 71}; 72 73/* 74 * This is used during keyboard initialisation 75 */ 76static unsigned char lk201_reset_string[] = { 77 LK_CMD_SET_DEFAULTS, 78 LK_CMD_MODE(LK_MODE_RPT_DOWN, 1), 79 LK_CMD_MODE(LK_MODE_RPT_DOWN, 2), 80 LK_CMD_MODE(LK_MODE_RPT_DOWN, 3), 81 LK_CMD_MODE(LK_MODE_RPT_DOWN, 4), 82 LK_CMD_MODE(LK_MODE_DOWN_UP, 5), 83 LK_CMD_MODE(LK_MODE_DOWN_UP, 6), 84 LK_CMD_MODE(LK_MODE_RPT_DOWN, 7), 85 LK_CMD_MODE(LK_MODE_RPT_DOWN, 8), 86 LK_CMD_MODE(LK_MODE_RPT_DOWN, 9), 87 LK_CMD_MODE(LK_MODE_RPT_DOWN, 10), 88 LK_CMD_MODE(LK_MODE_RPT_DOWN, 11), 89 LK_CMD_MODE(LK_MODE_RPT_DOWN, 12), 90 LK_CMD_MODE(LK_MODE_DOWN, 13), 91 LK_CMD_MODE(LK_MODE_RPT_DOWN, 14), 92 LK_CMD_DIS_KEYCLK, 93 LK_CMD_ENB_BELL, LK_PARAM_VOLUME(4), 94}; 95 96static void *lk201_handle; 97 98static int lk201_send(unsigned char ch) 99{ 100 if (lk201_hook.poll_tx_char(lk201_handle, ch)) { 101 printk(KERN_ERR "lk201: transmit timeout\n"); 102 return -EIO; 103 } 104 return 0; 105} 106 107static inline int lk201_get_id(void) 108{ 109 return lk201_send(LK_CMD_REQ_ID); 110} 111 112static int lk201_reset(void) 113{ 114 int i, r; 115 116 for (i = 0; i < sizeof(lk201_reset_string); i++) { 117 r = lk201_send(lk201_reset_string[i]); 118 if (r < 0) 119 return r; 120 } 121 return 0; 122} 123 124static void lk201_report(unsigned char id[6]) 125{ 126 char *report = "lk201: keyboard attached, "; 127 128 switch (id[2]) { 129 case LK_STAT_PWRUP_OK: 130 printk(KERN_INFO "%sself-test OK\n", report); 131 break; 132 case LK_STAT_PWRUP_KDOWN: 133 /* The keyboard will resend the power-up ID 134 after all keys are released, so we don't 135 bother handling the error specially. Still 136 there may be a short-circuit inside. 137 */ 138 printk(KERN_ERR "%skey down (stuck?), code: 0x%02x\n", 139 report, id[3]); 140 break; 141 case LK_STAT_PWRUP_ERROR: 142 printk(KERN_ERR "%sself-test failure\n", report); 143 break; 144 default: 145 printk(KERN_ERR "%sunknown error: 0x%02x\n", 146 report, id[2]); 147 } 148} 149 150static void lk201_id(unsigned char id[6]) 151{ 152 /* 153 * Report whether there is an LK201 or an LK401 154 * The LK401 has ALT keys... 155 */ 156 switch (id[4]) { 157 case 1: 158 printk(KERN_INFO "lk201: LK201 detected\n"); 159 break; 160 case 2: 161 printk(KERN_INFO "lk201: LK401 detected\n"); 162 break; 163 case 3: 164 printk(KERN_INFO "lk201: LK443 detected\n"); 165 break; 166 case 4: 167 printk(KERN_INFO "lk201: LK421 detected\n"); 168 break; 169 default: 170 printk(KERN_WARNING 171 "lk201: unknown keyboard detected, ID %d\n", id[4]); 172 printk(KERN_WARNING "lk201: ... please report to " 173 "<linux-mips@linux-mips.org>\n"); 174 } 175} 176 177#define DEFAULT_KEYB_REP_DELAY (250/5) /* [5ms] */ 178#define DEFAULT_KEYB_REP_RATE 30 /* [cps] */ 179 180static struct kbd_repeat kbdrate = { 181 DEFAULT_KEYB_REP_DELAY, 182 DEFAULT_KEYB_REP_RATE 183}; 184 185static void parse_kbd_rate(struct kbd_repeat *r) 186{ 187 if (r->delay <= 0) 188 r->delay = kbdrate.delay; 189 if (r->rate <= 0) 190 r->rate = kbdrate.rate; 191 192 if (r->delay < 5) 193 r->delay = 5; 194 if (r->delay > 630) 195 r->delay = 630; 196 if (r->rate < 12) 197 r->rate = 12; 198 if (r->rate > 127) 199 r->rate = 127; 200 if (r->rate == 125) 201 r->rate = 124; 202} 203 204static int write_kbd_rate(struct kbd_repeat *rep) 205{ 206 int delay, rate; 207 int i; 208 209 delay = rep->delay / 5; 210 rate = rep->rate; 211 for (i = 0; i < 4; i++) { 212 if (lk201_hook.poll_tx_char(lk201_handle, 213 LK_CMD_RPT_RATE(i))) 214 return 1; 215 if (lk201_hook.poll_tx_char(lk201_handle, 216 LK_PARAM_DELAY(delay))) 217 return 1; 218 if (lk201_hook.poll_tx_char(lk201_handle, 219 LK_PARAM_RATE(rate))) 220 return 1; 221 } 222 return 0; 223} 224 225static int lk201_kbd_rate(struct kbd_repeat *rep) 226{ 227 if (rep == NULL) 228 return -EINVAL; 229 230 parse_kbd_rate(rep); 231 232 if (write_kbd_rate(rep)) { 233 memcpy(rep, &kbdrate, sizeof(struct kbd_repeat)); 234 return -EIO; 235 } 236 237 memcpy(&kbdrate, rep, sizeof(struct kbd_repeat)); 238 239 return 0; 240} 241 242static void lk201_kd_mksound(unsigned int hz, unsigned int ticks) 243{ 244 if (!ticks) 245 return; 246 247 /* 248 * Can't set frequency and we "approximate" 249 * duration by volume. ;-) 250 */ 251 ticks /= HZ / 32; 252 if (ticks > 7) 253 ticks = 7; 254 ticks = 7 - ticks; 255 256 if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_ENB_BELL)) 257 return; 258 if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_VOLUME(ticks))) 259 return; 260 if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_BELL)) 261 return; 262} 263 264void kbd_leds(unsigned char leds) 265{ 266 unsigned char l = 0; 267 268 if (!lk201_handle) /* FIXME */ 269 return; 270 271 /* FIXME -- Only Hold and Lock LEDs for now. --macro */ 272 if (leds & LED_SCR) 273 l |= LK_LED_HOLD; 274 if (leds & LED_CAP) 275 l |= LK_LED_LOCK; 276 277 if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_LEDS_ON)) 278 return; 279 if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_LED_MASK(l))) 280 return; 281 if (lk201_hook.poll_tx_char(lk201_handle, LK_CMD_LEDS_OFF)) 282 return; 283 if (lk201_hook.poll_tx_char(lk201_handle, LK_PARAM_LED_MASK(~l))) 284 return; 285} 286 287int kbd_setkeycode(unsigned int scancode, unsigned int keycode) 288{ 289 return -EINVAL; 290} 291 292int kbd_getkeycode(unsigned int scancode) 293{ 294 return -EINVAL; 295} 296 297int kbd_translate(unsigned char scancode, unsigned char *keycode, 298 char raw_mode) 299{ 300 *keycode = scancode; 301 return 1; 302} 303 304char kbd_unexpected_up(unsigned char keycode) 305{ 306 return 0x80; 307} 308 309static void lk201_rx_char(unsigned char ch, unsigned char fl) 310{ 311 static unsigned char id[6]; 312 static int id_i; 313 314 static int shift_state = 0; 315 static int prev_scancode; 316 unsigned char c = scancodeRemap[ch]; 317 318 if (fl != TTY_NORMAL && fl != TTY_OVERRUN) { 319 printk(KERN_ERR "lk201: keyboard receive error: 0x%02x\n", fl); 320 return; 321 } 322 323 /* Assume this is a power-up ID. */ 324 if (ch == LK_STAT_PWRUP_ID && !id_i) { 325 id[id_i++] = ch; 326 return; 327 } 328 329 /* Handle the power-up sequence. */ 330 if (id_i) { 331 id[id_i++] = ch; 332 if (id_i == 4) { 333 /* OK, the power-up concluded. */ 334 lk201_report(id); 335 if (id[2] == LK_STAT_PWRUP_OK) 336 lk201_get_id(); 337 else { 338 id_i = 0; 339 printk(KERN_ERR "lk201: keyboard power-up " 340 "error, skipping initialization\n"); 341 } 342 } else if (id_i == 6) { 343 /* We got the ID; report it and start operation. */ 344 id_i = 0; 345 lk201_id(id); 346 lk201_reset(); 347 } 348 return; 349 } 350 351 /* Everything else is a scancode/status response. */ 352 id_i = 0; 353 switch (ch) { 354 case LK_STAT_RESUME_ERR: 355 case LK_STAT_ERROR: 356 case LK_STAT_INHIBIT_ACK: 357 case LK_STAT_TEST_ACK: 358 case LK_STAT_MODE_KEYDOWN: 359 case LK_STAT_MODE_ACK: 360 break; 361 case LK_KEY_LOCK: 362 shift_state ^= LK_LOCK; 363 handle_scancode(c, (shift_state & LK_LOCK) ? 1 : 0); 364 break; 365 case LK_KEY_SHIFT: 366 shift_state ^= LK_SHIFT; 367 handle_scancode(c, (shift_state & LK_SHIFT) ? 1 : 0); 368 break; 369 case LK_KEY_CTRL: 370 shift_state ^= LK_CTRL; 371 handle_scancode(c, (shift_state & LK_CTRL) ? 1 : 0); 372 break; 373 case LK_KEY_COMP: 374 shift_state ^= LK_COMP; 375 handle_scancode(c, (shift_state & LK_COMP) ? 1 : 0); 376 break; 377 case LK_KEY_RELEASE: 378 if (shift_state & LK_SHIFT) 379 handle_scancode(scancodeRemap[LK_KEY_SHIFT], 0); 380 if (shift_state & LK_CTRL) 381 handle_scancode(scancodeRemap[LK_KEY_CTRL], 0); 382 if (shift_state & LK_COMP) 383 handle_scancode(scancodeRemap[LK_KEY_COMP], 0); 384 if (shift_state & LK_LOCK) 385 handle_scancode(scancodeRemap[LK_KEY_LOCK], 0); 386 shift_state = 0; 387 break; 388 case LK_KEY_REPEAT: 389 handle_scancode(prev_scancode, 1); 390 break; 391 default: 392 prev_scancode = c; 393 handle_scancode(c, 1); 394 break; 395 } 396 tasklet_schedule(&keyboard_tasklet); 397} 398 399static void __init lk201_info(void *handle) 400{ 401} 402 403static int __init lk201_init(void *handle) 404{ 405 /* First install handlers. */ 406 lk201_handle = handle; 407 kbd_rate = lk201_kbd_rate; 408 kd_mksound = lk201_kd_mksound; 409 410 lk201_hook.rx_char = lk201_rx_char; 411 412 /* Then just issue a reset -- the handlers will do the rest. */ 413 lk201_send(LK_CMD_POWER_UP); 414 415 return 0; 416} 417 418void __init kbd_init_hw(void) 419{ 420 /* Maxine uses LK501 at the Access.Bus. */ 421 if (!LK_IFACE) 422 return; 423 424 printk(KERN_INFO "lk201: DECstation LK keyboard driver v0.05.\n"); 425 426 if (LK_IFACE_ZS) { 427 /* 428 * kbd_init_hw() is being called before 429 * rs_init() so just register the kbd hook 430 * and let zs_init do the rest :-) 431 */ 432 if (!register_dec_serial_hook(KEYB_LINE, &lk201_hook)) 433 unregister_dec_serial_hook(KEYB_LINE); 434 } else { 435 /* 436 * TODO: modify dz.c to allow similar hooks 437 * for LK201 handling on DS2100, DS3100, and DS5000/200 438 */ 439 printk(KERN_ERR "lk201: support for DZ11 not yet ready.\n"); 440 } 441}