1 /* 2 * linux/arch/m68k/atari/atakeyb.c 3 * 4 * Atari Keyboard driver for 680x0 Linux 5 * 6 * This file is subject to the terms and conditions of the GNU General Public 7 * License. See the file COPYING in the main directory of this archive 8 * for more details. 9 */ 10 11 /* 12 * Atari support by Robert de Vries 13 * enhanced by Bjoern Brauel and Roman Hodek 14 * 15 * 2.6 and input cleanup (removed autorepeat stuff) for 2.6.21 16 * 06/07 Michael Schmitz 17 */ 18 19 #include <linux/module.h> 20 #include <linux/sched.h> 21 #include <linux/kernel.h> 22 #include <linux/interrupt.h> 23 #include <linux/errno.h> 24 #include <linux/keyboard.h> 25 #include <linux/delay.h> 26 #include <linux/timer.h> 27 #include <linux/kd.h> 28 #include <linux/random.h> 29 #include <linux/init.h> 30 #include <linux/kbd_kern.h> 31 32 #include <asm/atariints.h> 33 #include <asm/atarihw.h> 34 #include <asm/atarikb.h> 35 #include <asm/atari_joystick.h> 36 #include <asm/irq.h> 37 38 extern unsigned int keymap_count; 39 40 /* Hook for MIDI serial driver */ 41 void (*atari_MIDI_interrupt_hook) (void); 42 /* Hook for mouse driver */ 43 void (*atari_mouse_interrupt_hook) (char *); 44 /* Hook for keyboard inputdev driver */ 45 void (*atari_input_keyboard_interrupt_hook) (unsigned char, char); 46 /* Hook for mouse inputdev driver */ 47 void (*atari_input_mouse_interrupt_hook) (char *); 48 EXPORT_SYMBOL(atari_mouse_interrupt_hook); 49 EXPORT_SYMBOL(atari_input_keyboard_interrupt_hook); 50 EXPORT_SYMBOL(atari_input_mouse_interrupt_hook); 51 52 /* variables for IKBD self test: */ 53 54 /* state: 0: off; >0: in progress; >1: 0xf1 received */ 55 static volatile int ikbd_self_test; 56 /* timestamp when last received a char */ 57 static volatile unsigned long self_test_last_rcv; 58 /* bitmap of keys reported as broken */ 59 static unsigned long broken_keys[128/(sizeof(unsigned long)*8)] = { 0, }; 60 61 #define BREAK_MASK (0x80) 62 63 /* 64 * ++roman: The following changes were applied manually: 65 * 66 * - The Alt (= Meta) key works in combination with Shift and 67 * Control, e.g. Alt+Shift+a sends Meta-A (0xc1), Alt+Control+A sends 68 * Meta-Ctrl-A (0x81) ... 69 * 70 * - The parentheses on the keypad send '(' and ')' with all 71 * modifiers (as would do e.g. keypad '+'), but they cannot be used as 72 * application keys (i.e. sending Esc O c). 73 * 74 * - HELP and UNDO are mapped to be F21 and F24, resp, that send the 75 * codes "\E[M" and "\E[P". (This is better than the old mapping to 76 * F11 and F12, because these codes are on Shift+F1/2 anyway.) This 77 * way, applications that allow their own keyboard mappings 78 * (e.g. tcsh, X Windows) can be configured to use them in the way 79 * the label suggests (providing help or undoing). 80 * 81 * - Console switching is done with Alt+Fx (consoles 1..10) and 82 * Shift+Alt+Fx (consoles 11..20). 83 * 84 * - The misc. special function implemented in the kernel are mapped 85 * to the following key combinations: 86 * 87 * ClrHome -> Home/Find 88 * Shift + ClrHome -> End/Select 89 * Shift + Up -> Page Up 90 * Shift + Down -> Page Down 91 * Alt + Help -> show system status 92 * Shift + Help -> show memory info 93 * Ctrl + Help -> show registers 94 * Ctrl + Alt + Del -> Reboot 95 * Alt + Undo -> switch to last console 96 * Shift + Undo -> send interrupt 97 * Alt + Insert -> stop/start output (same as ^S/^Q) 98 * Alt + Up -> Scroll back console (if implemented) 99 * Alt + Down -> Scroll forward console (if implemented) 100 * Alt + CapsLock -> NumLock 101 * 102 * ++Andreas: 103 * 104 * - Help mapped to K_HELP 105 * - Undo mapped to K_UNDO (= K_F246) 106 * - Keypad Left/Right Parenthesis mapped to new K_PPAREN[LR] 107 */ 108 109 typedef enum kb_state_t { 110 KEYBOARD, AMOUSE, RMOUSE, JOYSTICK, CLOCK, RESYNC 111 } KB_STATE_T; 112 113 #define IS_SYNC_CODE(sc) ((sc) >= 0x04 && (sc) <= 0xfb) 114 115 typedef struct keyboard_state { 116 unsigned char buf[6]; 117 int len; 118 KB_STATE_T state; 119 } KEYBOARD_STATE; 120 121 KEYBOARD_STATE kb_state; 122 123 /* ++roman: If a keyboard overrun happened, we can't tell in general how much 124 * bytes have been lost and in which state of the packet structure we are now. 125 * This usually causes keyboards bytes to be interpreted as mouse movements 126 * and vice versa, which is very annoying. It seems better to throw away some 127 * bytes (that are usually mouse bytes) than to misinterpret them. Therefor I 128 * introduced the RESYNC state for IKBD data. In this state, the bytes up to 129 * one that really looks like a key event (0x04..0xf2) or the start of a mouse 130 * packet (0xf8..0xfb) are thrown away, but at most 2 bytes. This at least 131 * speeds up the resynchronization of the event structure, even if maybe a 132 * mouse movement is lost. However, nothing is perfect. For bytes 0x01..0x03, 133 * it's really hard to decide whether they're mouse or keyboard bytes. Since 134 * overruns usually occur when moving the Atari mouse rapidly, they're seen as 135 * mouse bytes here. If this is wrong, only a make code of the keyboard gets 136 * lost, which isn't too bad. Loosing a break code would be disastrous, 137 * because then the keyboard repeat strikes... 138 */ 139 140 static irqreturn_t atari_keyboard_interrupt(int irq, void *dummy) 141 { 142 u_char acia_stat; 143 int scancode; 144 int break_flag; 145 146 repeat: 147 if (acia.mid_ctrl & ACIA_IRQ) 148 if (atari_MIDI_interrupt_hook) 149 atari_MIDI_interrupt_hook(); 150 acia_stat = acia.key_ctrl; 151 /* check out if the interrupt came from this ACIA */ 152 if (!((acia_stat | acia.mid_ctrl) & ACIA_IRQ)) 153 return IRQ_HANDLED; 154 155 if (acia_stat & ACIA_OVRN) { 156 /* a very fast typist or a slow system, give a warning */ 157 /* ...happens often if interrupts were disabled for too long */ 158 printk(KERN_DEBUG "Keyboard overrun\n"); 159 scancode = acia.key_data; 160 if (ikbd_self_test) 161 /* During self test, don't do resyncing, just process the code */ 162 goto interpret_scancode; 163 else if (IS_SYNC_CODE(scancode)) { 164 /* This code seem already to be the start of a new packet or a 165 * single scancode */ 166 kb_state.state = KEYBOARD; 167 goto interpret_scancode; 168 } else { 169 /* Go to RESYNC state and skip this byte */ 170 kb_state.state = RESYNC; 171 kb_state.len = 1; /* skip max. 1 another byte */ 172 goto repeat; 173 } 174 } 175 176 if (acia_stat & ACIA_RDRF) { 177 /* received a character */ 178 scancode = acia.key_data; /* get it or reset the ACIA, I'll get it! */ 179 tasklet_schedule(&keyboard_tasklet); 180 interpret_scancode: 181 switch (kb_state.state) { 182 case KEYBOARD: 183 switch (scancode) { 184 case 0xF7: 185 kb_state.state = AMOUSE; 186 kb_state.len = 0; 187 break; 188 189 case 0xF8: 190 case 0xF9: 191 case 0xFA: 192 case 0xFB: 193 kb_state.state = RMOUSE; 194 kb_state.len = 1; 195 kb_state.buf[0] = scancode; 196 break; 197 198 case 0xFC: 199 kb_state.state = CLOCK; 200 kb_state.len = 0; 201 break; 202 203 case 0xFE: 204 case 0xFF: 205 kb_state.state = JOYSTICK; 206 kb_state.len = 1; 207 kb_state.buf[0] = scancode; 208 break; 209 210 case 0xF1: 211 /* during self-test, note that 0xf1 received */ 212 if (ikbd_self_test) { 213 ++ikbd_self_test; 214 self_test_last_rcv = jiffies; 215 break; 216 } 217 /* FALL THROUGH */ 218 219 default: 220 break_flag = scancode & BREAK_MASK; 221 scancode &= ~BREAK_MASK; 222 if (ikbd_self_test) { 223 /* Scancodes sent during the self-test stand for broken 224 * keys (keys being down). The code *should* be a break 225 * code, but nevertheless some AT keyboard interfaces send 226 * make codes instead. Therefore, simply ignore 227 * break_flag... 228 */ 229 int keyval, keytyp; 230 231 set_bit(scancode, broken_keys); 232 self_test_last_rcv = jiffies; 233 /* new Linux scancodes; approx. */ 234 keyval = scancode; 235 keytyp = KTYP(keyval) - 0xf0; 236 keyval = KVAL(keyval); 237 238 printk(KERN_WARNING "Key with scancode %d ", scancode); 239 if (keytyp == KT_LATIN || keytyp == KT_LETTER) { 240 if (keyval < ' ') 241 printk("('^%c') ", keyval + '@'); 242 else 243 printk("('%c') ", keyval); 244 } 245 printk("is broken -- will be ignored.\n"); 246 break; 247 } else if (test_bit(scancode, broken_keys)) 248 break; 249 250 if (atari_input_keyboard_interrupt_hook) 251 atari_input_keyboard_interrupt_hook((unsigned char)scancode, !break_flag); 252 break; 253 } 254 break; 255 256 case AMOUSE: 257 kb_state.buf[kb_state.len++] = scancode; 258 if (kb_state.len == 5) { 259 kb_state.state = KEYBOARD; 260 /* not yet used */ 261 /* wake up someone waiting for this */ 262 } 263 break; 264 265 case RMOUSE: 266 kb_state.buf[kb_state.len++] = scancode; 267 if (kb_state.len == 3) { 268 kb_state.state = KEYBOARD; 269 if (atari_mouse_interrupt_hook) 270 atari_mouse_interrupt_hook(kb_state.buf); 271 } 272 break; 273 274 case JOYSTICK: 275 kb_state.buf[1] = scancode; 276 kb_state.state = KEYBOARD; 277 #ifdef FIXED_ATARI_JOYSTICK 278 atari_joystick_interrupt(kb_state.buf); 279 #endif 280 break; 281 282 case CLOCK: 283 kb_state.buf[kb_state.len++] = scancode; 284 if (kb_state.len == 6) { 285 kb_state.state = KEYBOARD; 286 /* wake up someone waiting for this. 287 But will this ever be used, as Linux keeps its own time. 288 Perhaps for synchronization purposes? */ 289 /* wake_up_interruptible(&clock_wait); */ 290 } 291 break; 292 293 case RESYNC: 294 if (kb_state.len <= 0 || IS_SYNC_CODE(scancode)) { 295 kb_state.state = KEYBOARD; 296 goto interpret_scancode; 297 } 298 kb_state.len--; 299 break; 300 } 301 } 302 303 #if 0 304 if (acia_stat & ACIA_CTS) 305 /* cannot happen */; 306 #endif 307 308 if (acia_stat & (ACIA_FE | ACIA_PE)) { 309 printk("Error in keyboard communication\n"); 310 } 311 312 /* handle_scancode() can take a lot of time, so check again if 313 * some character arrived 314 */ 315 goto repeat; 316 } 317 318 /* 319 * I write to the keyboard without using interrupts, I poll instead. 320 * This takes for the maximum length string allowed (7) at 7812.5 baud 321 * 8 data 1 start 1 stop bit: 9.0 ms 322 * If this takes too long for normal operation, interrupt driven writing 323 * is the solution. (I made a feeble attempt in that direction but I 324 * kept it simple for now.) 325 */ 326 void ikbd_write(const char *str, int len) 327 { 328 u_char acia_stat; 329 330 if ((len < 1) || (len > 7)) 331 panic("ikbd: maximum string length exceeded"); 332 while (len) { 333 acia_stat = acia.key_ctrl; 334 if (acia_stat & ACIA_TDRE) { 335 acia.key_data = *str++; 336 len--; 337 } 338 } 339 } 340 341 /* Reset (without touching the clock) */ 342 void ikbd_reset(void) 343 { 344 static const char cmd[2] = { 0x80, 0x01 }; 345 346 ikbd_write(cmd, 2); 347 348 /* 349 * if all's well code 0xF1 is returned, else the break codes of 350 * all keys making contact 351 */ 352 } 353 354 /* Set mouse button action */ 355 void ikbd_mouse_button_action(int mode) 356 { 357 char cmd[2] = { 0x07, mode }; 358 359 ikbd_write(cmd, 2); 360 } 361 362 /* Set relative mouse position reporting */ 363 void ikbd_mouse_rel_pos(void) 364 { 365 static const char cmd[1] = { 0x08 }; 366 367 ikbd_write(cmd, 1); 368 } 369 EXPORT_SYMBOL(ikbd_mouse_rel_pos); 370 371 /* Set absolute mouse position reporting */ 372 void ikbd_mouse_abs_pos(int xmax, int ymax) 373 { 374 char cmd[5] = { 0x09, xmax>>8, xmax&0xFF, ymax>>8, ymax&0xFF }; 375 376 ikbd_write(cmd, 5); 377 } 378 379 /* Set mouse keycode mode */ 380 void ikbd_mouse_kbd_mode(int dx, int dy) 381 { 382 char cmd[3] = { 0x0A, dx, dy }; 383 384 ikbd_write(cmd, 3); 385 } 386 387 /* Set mouse threshold */ 388 void ikbd_mouse_thresh(int x, int y) 389 { 390 char cmd[3] = { 0x0B, x, y }; 391 392 ikbd_write(cmd, 3); 393 } 394 EXPORT_SYMBOL(ikbd_mouse_thresh); 395 396 /* Set mouse scale */ 397 void ikbd_mouse_scale(int x, int y) 398 { 399 char cmd[3] = { 0x0C, x, y }; 400 401 ikbd_write(cmd, 3); 402 } 403 404 /* Interrogate mouse position */ 405 void ikbd_mouse_pos_get(int *x, int *y) 406 { 407 static const char cmd[1] = { 0x0D }; 408 409 ikbd_write(cmd, 1); 410 411 /* wait for returning bytes */ 412 } 413 414 /* Load mouse position */ 415 void ikbd_mouse_pos_set(int x, int y) 416 { 417 char cmd[6] = { 0x0E, 0x00, x>>8, x&0xFF, y>>8, y&0xFF }; 418 419 ikbd_write(cmd, 6); 420 } 421 422 /* Set Y=0 at bottom */ 423 void ikbd_mouse_y0_bot(void) 424 { 425 static const char cmd[1] = { 0x0F }; 426 427 ikbd_write(cmd, 1); 428 } 429 430 /* Set Y=0 at top */ 431 void ikbd_mouse_y0_top(void) 432 { 433 static const char cmd[1] = { 0x10 }; 434 435 ikbd_write(cmd, 1); 436 } 437 EXPORT_SYMBOL(ikbd_mouse_y0_top); 438 439 /* Resume */ 440 void ikbd_resume(void) 441 { 442 static const char cmd[1] = { 0x11 }; 443 444 ikbd_write(cmd, 1); 445 } 446 447 /* Disable mouse */ 448 void ikbd_mouse_disable(void) 449 { 450 static const char cmd[1] = { 0x12 }; 451 452 ikbd_write(cmd, 1); 453 } 454 EXPORT_SYMBOL(ikbd_mouse_disable); 455 456 /* Pause output */ 457 void ikbd_pause(void) 458 { 459 static const char cmd[1] = { 0x13 }; 460 461 ikbd_write(cmd, 1); 462 } 463 464 /* Set joystick event reporting */ 465 void ikbd_joystick_event_on(void) 466 { 467 static const char cmd[1] = { 0x14 }; 468 469 ikbd_write(cmd, 1); 470 } 471 472 /* Set joystick interrogation mode */ 473 void ikbd_joystick_event_off(void) 474 { 475 static const char cmd[1] = { 0x15 }; 476 477 ikbd_write(cmd, 1); 478 } 479 480 /* Joystick interrogation */ 481 void ikbd_joystick_get_state(void) 482 { 483 static const char cmd[1] = { 0x16 }; 484 485 ikbd_write(cmd, 1); 486 } 487 488 #if 0 489 /* This disables all other ikbd activities !!!! */ 490 /* Set joystick monitoring */ 491 void ikbd_joystick_monitor(int rate) 492 { 493 static const char cmd[2] = { 0x17, rate }; 494 495 ikbd_write(cmd, 2); 496 497 kb_state.state = JOYSTICK_MONITOR; 498 } 499 #endif 500 501 /* some joystick routines not in yet (0x18-0x19) */ 502 503 /* Disable joysticks */ 504 void ikbd_joystick_disable(void) 505 { 506 static const char cmd[1] = { 0x1A }; 507 508 ikbd_write(cmd, 1); 509 } 510 511 /* Time-of-day clock set */ 512 void ikbd_clock_set(int year, int month, int day, int hour, int minute, int second) 513 { 514 char cmd[7] = { 0x1B, year, month, day, hour, minute, second }; 515 516 ikbd_write(cmd, 7); 517 } 518 519 /* Interrogate time-of-day clock */ 520 void ikbd_clock_get(int *year, int *month, int *day, int *hour, int *minute, int second) 521 { 522 static const char cmd[1] = { 0x1C }; 523 524 ikbd_write(cmd, 1); 525 } 526 527 /* Memory load */ 528 void ikbd_mem_write(int address, int size, char *data) 529 { 530 panic("Attempt to write data into keyboard memory"); 531 } 532 533 /* Memory read */ 534 void ikbd_mem_read(int address, char data[6]) 535 { 536 char cmd[3] = { 0x21, address>>8, address&0xFF }; 537 538 ikbd_write(cmd, 3); 539 540 /* receive data and put it in data */ 541 } 542 543 /* Controller execute */ 544 void ikbd_exec(int address) 545 { 546 char cmd[3] = { 0x22, address>>8, address&0xFF }; 547 548 ikbd_write(cmd, 3); 549 } 550 551 /* Status inquiries (0x87-0x9A) not yet implemented */ 552 553 /* Set the state of the caps lock led. */ 554 void atari_kbd_leds(unsigned int leds) 555 { 556 char cmd[6] = {32, 0, 4, 1, 254 + ((leds & 4) != 0), 0}; 557 558 ikbd_write(cmd, 6); 559 } 560 561 /* 562 * The original code sometimes left the interrupt line of 563 * the ACIAs low forever. I hope, it is fixed now. 564 * 565 * Martin Rogge, 20 Aug 1995 566 */ 567 568 static int atari_keyb_done = 0; 569 570 int __init atari_keyb_init(void) 571 { 572 if (atari_keyb_done) 573 return 0; 574 575 kb_state.state = KEYBOARD; 576 kb_state.len = 0; 577 578 request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt, IRQ_TYPE_SLOW, 579 "keyboard/mouse/MIDI", atari_keyboard_interrupt); 580 581 atari_turnoff_irq(IRQ_MFP_ACIA); 582 do { 583 /* reset IKBD ACIA */ 584 acia.key_ctrl = ACIA_RESET | 585 (atari_switches & ATARI_SWITCH_IKBD) ? ACIA_RHTID : 0; 586 (void)acia.key_ctrl; 587 (void)acia.key_data; 588 589 /* reset MIDI ACIA */ 590 acia.mid_ctrl = ACIA_RESET | 591 (atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0; 592 (void)acia.mid_ctrl; 593 (void)acia.mid_data; 594 595 /* divide 500kHz by 64 gives 7812.5 baud */ 596 /* 8 data no parity 1 start 1 stop bit */ 597 /* receive interrupt enabled */ 598 /* RTS low (except if switch selected), transmit interrupt disabled */ 599 acia.key_ctrl = (ACIA_DIV64|ACIA_D8N1S|ACIA_RIE) | 600 ((atari_switches & ATARI_SWITCH_IKBD) ? 601 ACIA_RHTID : ACIA_RLTID); 602 603 acia.mid_ctrl = ACIA_DIV16 | ACIA_D8N1S | 604 (atari_switches & ATARI_SWITCH_MIDI) ? ACIA_RHTID : 0; 605 606 /* make sure the interrupt line is up */ 607 } while ((mfp.par_dt_reg & 0x10) == 0); 608 609 /* enable ACIA Interrupts */ 610 mfp.active_edge &= ~0x10; 611 atari_turnon_irq(IRQ_MFP_ACIA); 612 613 ikbd_self_test = 1; 614 ikbd_reset(); 615 /* wait for a period of inactivity (here: 0.25s), then assume the IKBD's 616 * self-test is finished */ 617 self_test_last_rcv = jiffies; 618 while (time_before(jiffies, self_test_last_rcv + HZ/4)) 619 barrier(); 620 /* if not incremented: no 0xf1 received */ 621 if (ikbd_self_test == 1) 622 printk(KERN_ERR "WARNING: keyboard self test failed!\n"); 623 ikbd_self_test = 0; 624 625 ikbd_mouse_disable(); 626 ikbd_joystick_disable(); 627 628 #ifdef FIXED_ATARI_JOYSTICK 629 atari_joystick_init(); 630 #endif 631 632 // flag init done 633 atari_keyb_done = 1; 634 return 0; 635 } 636 637 int atari_kbd_translate(unsigned char keycode, unsigned char *keycodep, char raw_mode) 638 { 639 #ifdef CONFIG_MAGIC_SYSRQ 640 /* ALT+HELP pressed? */ 641 if ((keycode == 98) && ((shift_state & 0xff) == 8)) 642 *keycodep = 0xff; 643 else 644 #endif 645 *keycodep = keycode; 646 return 1; 647 } 648