Welcome to The Fiwix Project
A UNIX-like kernel for the i386 architecture
1 /* 2 * fiwix/drivers/char/keyboard.c 3 * 4 * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved. 5 * Distributed under the terms of the Fiwix License. 6 */ 7 8 #include <fiwix/asm.h> 9 #include <fiwix/kernel.h> 10 #include <fiwix/limits.h> 11 #include <fiwix/keyboard.h> 12 #include <fiwix/console.h> 13 #include <fiwix/vgacon.h> 14 #include <fiwix/pic.h> 15 #include <fiwix/signal.h> 16 #include <fiwix/process.h> 17 #include <fiwix/sleep.h> 18 #include <fiwix/kd.h> 19 #include <fiwix/sysrq.h> 20 #include <fiwix/stdio.h> 21 #include <fiwix/string.h> 22 23 #define KB_DATA 0x60 /* I/O data port */ 24 #define KBC_COMMAND 0x64 /* command/control port */ 25 #define KBC_STATUS 0x64 /* status register port */ 26 27 /* 28 * PS/2 System Control Port A 29 * -------------------------------- 30 * bit 7 -> fixed disk activity led 31 * bit 6 -> fixed disk activity led 32 * bit 5 -> reserved 33 * bit 4 -> watchdog timer status 34 * bit 3 -> security lock latch 35 * bit 2 -> reserved 36 * bit 1 -> alternate gate A20 37 * bit 0 -> alternate hot reset 38 */ 39 #define PS2_SYSCTRL_A 0x92 /* PS/2 system control port A (write) */ 40 41 #define KB_CMD_RESET 0xFF /* keyboard reset */ 42 #define KB_CMD_ENABLE 0xF4 /* keyboard enable scanning */ 43 #define KB_CMD_DISABLE 0xF5 /* keyboard disable scanning */ 44 #define KB_CMD_IDENTIFY 0xF2 /* keyboard identify (for PS/2 only) */ 45 #define KB_CMD_ECHO 0xEE /* echo (for diagnostics only) */ 46 47 #define KBC_CMD_RECV_CONFIG 0x20 /* read controller's config byte */ 48 #define KBC_CMD_SEND_CONFIG 0x60 /* write controller's config byte */ 49 #define KBC_CMD_SELF_TEST 0xAA /* self-test command */ 50 #define KBC_CMD_PS2_1_TEST 0xAB /* first PS/2 interface test command */ 51 #define KBC_CMD_PS2_2_TEST 0xA9 /* second PS/2 interface test command */ 52 #define KBC_CMD_DISABLE_PS2_1 0xAD /* disable first PS/2 port */ 53 #define KBC_CMD_ENABLE_PS2_1 0xAE /* enable first PS/2 port */ 54 #define KBC_CMD_DISABLE_PS2_2 0xA7 /* disable second PS/2 port (if any) */ 55 #define KBC_CMD_ENABLE_PS2_2 0xA8 /* enable second PS/2 port (if any) */ 56 #define KBC_CMD_GET_IFACE 0xCA /* get interface type (AT or MCA) */ 57 #define KBC_CMD_HOTRESET 0xFE /* Hot Reset */ 58 59 /* flags of the status register */ 60 #define KB_STR_OUTBUSY 0x01 /* output buffer full, don't read yet */ 61 #define KB_STR_INBUSY 0x02 /* input buffer full, don't write yet */ 62 #define KB_STR_TXTMOUT 0x20 /* transmit time-out error */ 63 #define KB_STR_RXTMOUT 0x40 /* receive time-out error */ 64 #define KB_STR_PARERR 0X80 /* parity error */ 65 #define KB_STR_COMMERR (KB_STR_TXTMOUT | KB_STR_RXTMOUT) 66 67 #define KB_RESET_OK 0xAA /* self-test passed */ 68 #define KB_ACK 0xFA /* acknowledge */ 69 #define KB_SETLED 0xED /* set/reset status indicators (LEDs) */ 70 #define KB_RATE 0xF3 /* set typematic rate/delay */ 71 #define DELAY_250 0x00 /* typematic delay at 250ms (default) */ 72 #define DELAY_500 0x40 /* typematic delay at 500ms */ 73 #define DELAY_750 0x80 /* typematic delay at 750ms */ 74 #define DELAY_1000 0xC0 /* typematic delay at 1000ms */ 75 #define RATE_30 0x00 /* typematic rate at 30.0 reports/sec (default) */ 76 77 #define EXTKEY 0xE0 /* extended key (AltGr, Ctrl-Print, etc.) */ 78 79 __key_t *keymap_line; 80 81 static unsigned char e0_keys[128] = { 82 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00-0x07 */ 83 0, 0, 0, 0, 0, 0, 0, 0, /* 0x08-0x0F */ 84 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10-0x17 */ 85 0, 0, 0, 0, E0ENTER, RCTRL, 0, 0, /* 0x18-0x1F */ 86 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20-0x27 */ 87 0, 0, 0, 0, 0, 0, 0, 0, /* 0x28-0x2F */ 88 0, 0, 0, 0, 0, E0SLASH, 0, 0, /* 0x30-0x37 */ 89 ALTGR, 0, 0, 0, 0, 0, 0, 0, /* 0x38-0x3F */ 90 0, 0, 0, 0, 0, 0, 0, E0HOME, /* 0x40-0x47 */ 91 E0UP, E0PGUP, 0, E0LEFT, 0, E0RIGHT, 0, E0END, /* 0x48-0x4F */ 92 E0DOWN, E0PGDN, E0INS, E0DEL, 0, 0, 0, 0, /* 0x50-0x57 */ 93 0, 0, 0, 0, 0, 0, 0, 0, /* 0x58-0x5f */ 94 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60-0x67 */ 95 0, 0, 0, 0, 0, 0, 0, 0, /* 0x68-0x6F */ 96 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70-0x77 */ 97 0, 0, 0, 0, 0, 0, 0, 0 /* 0x78-0x7F */ 98 }; 99 100 static unsigned char leds = 0; 101 static unsigned char shift = 0; 102 static unsigned char altgr = 0; 103 static unsigned char ctrl = 0; 104 static unsigned char alt = 0; 105 static unsigned char extkey = 0; 106 static unsigned char deadkey = 0; 107 static unsigned char sysrq = 0; 108 static int sysrq_op = 0; 109 110 static unsigned char do_buf_scroll = 0; 111 static char do_switch_console = -1; 112 struct video_parms video; 113 114 unsigned char kb_identify[2] = {0, 0}; 115 char ps2_active_ports = 0; 116 char ps2_supp_ports = 0; 117 char ps2_iface = 0; 118 short int current_cons; 119 char ctrl_alt_del = 1; 120 char any_key_to_reboot = 0; 121 122 static struct bh keyboard_bh = { 0, &irq_keyboard_bh, NULL }; 123 static struct interrupt irq_config_keyboard = { 0, "keyboard", &irq_keyboard, NULL }; 124 125 struct diacritic *diacr; 126 static char *diacr_chars = "`'^ \""; 127 struct diacritic grave_table[NR_DIACR] = { 128 { 'A', '\300' }, 129 { 'E', '\310' }, 130 { 'I', '\314' }, 131 { 'O', '\322' }, 132 { 'U', '\331' }, 133 { 'a', '\340' }, 134 { 'e', '\350' }, 135 { 'i', '\354' }, 136 { 'o', '\362' }, 137 { 'u', '\371' }, 138 }; 139 struct diacritic acute_table[NR_DIACR] = { 140 { 'A', '\301' }, 141 { 'E', '\311' }, 142 { 'I', '\315' }, 143 { 'O', '\323' }, 144 { 'U', '\332' }, 145 { 'a', '\341' }, 146 { 'e', '\351' }, 147 { 'i', '\355' }, 148 { 'o', '\363' }, 149 { 'u', '\372' }, 150 }; 151 struct diacritic circm_table[NR_DIACR] = { 152 { 'A', '\302' }, 153 { 'E', '\312' }, 154 { 'I', '\316' }, 155 { 'O', '\324' }, 156 { 'U', '\333' }, 157 { 'a', '\342' }, 158 { 'e', '\352' }, 159 { 'i', '\356' }, 160 { 'o', '\364' }, 161 { 'u', '\373' }, 162 }; 163 struct diacritic diere_table[NR_DIACR] = { 164 { 'A', '\304' }, 165 { 'E', '\313' }, 166 { 'I', '\317' }, 167 { 'O', '\326' }, 168 { 'U', '\334' }, 169 { 'a', '\344' }, 170 { 'e', '\353' }, 171 { 'i', '\357' }, 172 { 'o', '\366' }, 173 { 'u', '\374' }, 174 }; 175 176 static char *pad_chars = "0123456789+-*/\015,."; 177 178 static char *pad_seq[] = { 179 "\033[2~", /* INS */ 180 "\033[4~", /* END */ 181 "\033[B" , /* DOWN */ 182 "\033[6~", /* PGDN */ 183 "\033[D" , /* LEFT */ 184 "\033[G" , /* MID */ 185 "\033[C" , /* RIGHT */ 186 "\033[1~", /* HOME */ 187 "\033[A" , /* UP */ 188 "\033[5~", /* PGUP */ 189 "+", /* PLUS */ 190 "-", /* MINUS */ 191 "*", /* ASTERISK */ 192 "/", /* SLASH */ 193 "'\n'", /* ENTER */ 194 ",", /* COMMA */ 195 "\033[3~", /* DEL */ 196 }; 197 198 static char *fn_seq[] = { 199 "\033[[A", /* F1 */ 200 "\033[[B", /* F2 */ 201 "\033[[C", /* F3 */ 202 "\033[[D", /* F4 */ 203 "\033[[E", /* F5 */ 204 "\033[17~", /* F6 */ 205 "\033[18~", /* F7 */ 206 "\033[19~", /* F8 */ 207 "\033[20~", /* F9 */ 208 "\033[21~", /* F10 */ 209 "\033[23~", /* F11, SF1 */ 210 "\033[24~", /* F12, SF2 */ 211 "\033[25~", /* SF3 */ 212 "\033[26~", /* SF4 */ 213 "\033[28~", /* SF5 */ 214 "\033[29~", /* SF6 */ 215 "\033[31~", /* SF7 */ 216 "\033[32~", /* SF8 */ 217 "\033[33~", /* SF9 */ 218 "\033[34~", /* SF10 */ 219 }; 220 221 static void keyboard_delay(void) 222 { 223 int n; 224 225 for(n = 0; n < 1000; n++) { 226 NOP(); 227 } 228 } 229 230 /* wait controller input buffer to be clear (ready to write) */ 231 static int keyboard_wait_input(void) 232 { 233 int n; 234 235 for(n = 0; n < 500000; n++) { 236 if(!(inport_b(KBC_STATUS) & KB_STR_INBUSY)) { 237 return 0; 238 } 239 } 240 return 1; 241 } 242 243 static int keyboard_write(const unsigned char port, const unsigned char byte) 244 { 245 if(!keyboard_wait_input()) { 246 outport_b(port, byte); 247 if(!keyboard_wait_input()) { 248 return 0; 249 } 250 } 251 252 return 1; 253 } 254 255 /* wait controller output buffer to be full (ready to read) */ 256 static int keyboard_wait_output(void) 257 { 258 int n, value; 259 260 for(n = 0; n < 500000; n++) { 261 if((value = inport_b(KBC_STATUS)) & KB_STR_OUTBUSY) { 262 if(value & (KB_STR_COMMERR | KB_STR_PARERR)) { 263 continue; 264 } 265 return 0; 266 } 267 } 268 return 1; 269 } 270 271 static int keyboard_wait_ack(void) 272 { 273 int n; 274 275 keyboard_wait_output(); 276 for(n = 0; n < 1000; n++) { 277 if(inport_b(KB_DATA) == KB_ACK) { 278 return 0; 279 } 280 keyboard_delay(); 281 } 282 return 1; 283 } 284 285 static void keyboard_identify(void) 286 { 287 /* disable */ 288 keyboard_write(KB_DATA, KB_CMD_DISABLE); 289 if(keyboard_wait_ack()) { 290 printk("WARNING: %s(): ACK not received on disable command!\n", __FUNCTION__); 291 } 292 293 /* identify */ 294 keyboard_write(KB_DATA, KB_CMD_IDENTIFY); 295 if(keyboard_wait_ack()) { 296 printk("WARNING: %s(): ACK not received on identify command!\n", __FUNCTION__); 297 } 298 if(!keyboard_wait_output()) { 299 kb_identify[0] = inport_b(KB_DATA); 300 } 301 if(!keyboard_wait_output()) { 302 kb_identify[1] = inport_b(KB_DATA); 303 } 304 305 /* enable */ 306 keyboard_write(KB_DATA, KB_CMD_ENABLE); 307 if(keyboard_wait_ack()) { 308 printk("WARNING: %s(): ACK not received on enable command!\n", __FUNCTION__); 309 } 310 keyboard_wait_output(); 311 inport_b(KB_DATA); 312 313 /* get the interface type */ 314 keyboard_write(KBC_COMMAND, KBC_CMD_GET_IFACE); 315 keyboard_wait_output(); 316 ps2_iface = inport_b(KB_DATA); 317 } 318 319 static void keyboard_reset(void) 320 { 321 int errno; 322 unsigned char config; 323 324 /* disable device(s) */ 325 keyboard_write(KBC_COMMAND, KBC_CMD_DISABLE_PS2_1); 326 keyboard_write(KBC_COMMAND, KBC_CMD_DISABLE_PS2_2); 327 328 /* flush buffers */ 329 while(!keyboard_wait_output()) { 330 inport_b(KB_DATA); 331 } 332 333 /* get controller configuration */ 334 keyboard_write(KBC_COMMAND, KBC_CMD_RECV_CONFIG); 335 keyboard_wait_output(); 336 config = inport_b(KB_DATA); 337 ps2_active_ports = config & 0x01 ? 1 : 0; 338 ps2_active_ports += config & 0x02 ? 1 : 0; 339 ps2_supp_ports = 1 + (config & 0x20 ? 1 : 0); 340 341 /* set controller configuration (disabling IRQs) */ 342 /* 343 keyboard_write(KBC_COMMAND, KBC_CMD_SEND_CONFIG); 344 keyboard_write(KB_DATA, config & ~(0x01 | 0x02 | 0x40)); 345 */ 346 347 /* PS/2 controller self-test */ 348 keyboard_write(KBC_COMMAND, KBC_CMD_SELF_TEST); 349 keyboard_wait_output(); 350 if((errno = inport_b(KB_DATA)) != 0x55) { 351 printk("WARNING: %s(): keyboard returned 0x%x in self-test.\n", __FUNCTION__, errno); 352 } 353 354 /* 355 * This sets again the controller configuration since the previous 356 * step may also reset the PS/2 controller to its power-on defaults. 357 */ 358 keyboard_write(KBC_COMMAND, KBC_CMD_SEND_CONFIG); 359 keyboard_write(KB_DATA, config); 360 361 /* first PS/2 interface test */ 362 keyboard_write(KBC_COMMAND, KBC_CMD_PS2_1_TEST); 363 keyboard_wait_output(); 364 if((errno = inport_b(KB_DATA)) != 0) { 365 printk("WARNING: %s(): keyboard returned 0x%x in first PS/2 interface test.\n", __FUNCTION__, errno); 366 } 367 368 if(ps2_supp_ports > 1) { 369 /* second PS/2 interface test */ 370 keyboard_write(KBC_COMMAND, KBC_CMD_PS2_2_TEST); 371 keyboard_wait_output(); 372 if((errno = inport_b(KB_DATA)) != 0) { 373 printk("WARNING: %s(): keyboard returned 0x%x in second PS/2 interface test.\n", __FUNCTION__, errno); 374 } 375 } 376 377 /* enable device(s) */ 378 keyboard_write(KBC_COMMAND, KBC_CMD_ENABLE_PS2_1); 379 keyboard_write(KBC_COMMAND, KBC_CMD_ENABLE_PS2_2); 380 381 /* reset device(s) */ 382 keyboard_write(KB_DATA, KB_CMD_RESET); 383 if(keyboard_wait_ack()) { 384 printk("WARNING: %s(): ACK not received on reset command!\n", __FUNCTION__); 385 } 386 if(!keyboard_wait_output()) { 387 if((errno = inport_b(KB_DATA)) != KB_RESET_OK) { 388 printk("WARNING: %s(): keyboard returned 0x%x in reset.\n", __FUNCTION__, errno); 389 } 390 } 391 392 return; 393 } 394 395 static void putc(struct tty *tty, unsigned char ch) 396 { 397 if(tty_queue_putchar(tty, &tty->read_q, ch) < 0) { 398 if(tty->termios.c_iflag & IMAXBEL) { 399 vconsole_beep(); 400 } 401 } 402 } 403 404 static void puts(struct tty *tty, char *seq) 405 { 406 char ch; 407 408 while((ch = *(seq++))) { 409 putc(tty, ch); 410 } 411 } 412 413 void reboot(void) 414 { 415 CLI(); 416 keyboard_write(PS2_SYSCTRL_A, 0x01); /* Fast Hot Reset */ 417 keyboard_write(KBC_COMMAND, KBC_CMD_HOTRESET); /* Hot Reset */ 418 HLT(); 419 } 420 421 void set_leds(unsigned char leds) 422 { 423 keyboard_write(KB_DATA, KB_SETLED); 424 keyboard_wait_ack(); 425 426 keyboard_write(KB_DATA, leds); 427 keyboard_wait_ack(); 428 } 429 430 void irq_keyboard(int num, struct sigcontext *sc) 431 { 432 __key_t key, type; 433 unsigned char scode, mod; 434 struct tty *tty; 435 struct vconsole *vc; 436 unsigned char c; 437 int n; 438 439 tty = get_tty(MKDEV(VCONSOLES_MAJOR, current_cons)); 440 vc = (struct vconsole *)tty->driver_data; 441 442 scode = inport_b(KB_DATA); 443 444 /* keyboard said all is OK, perfect */ 445 if(scode == KB_ACK) { 446 return; 447 } 448 449 video.screen_on(vc); 450 keyboard_bh.flags |= BH_ACTIVE; 451 452 /* if in pure raw mode just queue the scan code and return */ 453 if(tty->kbd.mode == K_RAW) { 454 putc(tty, scode); 455 return; 456 } 457 458 if(scode == EXTKEY) { 459 extkey = 1; 460 return; 461 } 462 463 if(extkey) { 464 key = e0_keys[scode & 0x7F]; 465 } else { 466 key = scode & 0x7F; 467 } 468 469 if(tty->kbd.mode == K_MEDIUMRAW) { 470 putc(tty, key | (scode & 0x80)); 471 extkey = 0; 472 return; 473 } 474 475 key = keymap[NR_MODIFIERS * (scode & 0x7F)]; 476 477 /* bit 7 enabled means a key has been released */ 478 if(scode & NR_SCODES) { 479 switch(key) { 480 case CTRL: 481 case LCTRL: 482 case RCTRL: 483 ctrl = 0; 484 break; 485 case ALT: 486 if(!extkey) { 487 alt = 0; 488 sysrq = 0; 489 } else { 490 altgr = 0; 491 } 492 break; 493 case SHIFT: 494 case LSHIFT: 495 case RSHIFT: 496 if(!extkey) { 497 shift = 0; 498 } 499 break; 500 case CAPS: 501 case NUMS: 502 case SCRL: 503 leds = 0; 504 break; 505 } 506 extkey = 0; 507 return; 508 } 509 510 switch(key) { 511 case CAPS: 512 if(!leds) { 513 vc->led_status ^= CAPSBIT; 514 vc->capslock = !vc->capslock; 515 set_leds(vc->led_status); 516 } 517 leds = 1; 518 return; 519 case NUMS: 520 if(!leds) { 521 vc->led_status ^= NUMSBIT; 522 vc->numlock = !vc->numlock; 523 set_leds(vc->led_status); 524 } 525 leds = 1; 526 return; 527 case SCRL: 528 if(!leds) { 529 if(vc->scrlock) { 530 tty->start(tty); 531 } else { 532 tty->stop(tty); 533 } 534 } 535 leds = 1; 536 return; 537 case CTRL: 538 case LCTRL: 539 case RCTRL: 540 ctrl = 1; 541 return; 542 case ALT: 543 if(!extkey) { 544 alt = 1; 545 } else { 546 altgr = 1; 547 } 548 return; 549 case SHIFT: 550 case LSHIFT: 551 case RSHIFT: 552 shift = 1; 553 extkey = 0; 554 return; 555 } 556 557 if(ctrl && alt && key == DEL) { 558 if(ctrl_alt_del) { 559 reboot(); 560 } else { 561 send_sig(&proc_table[INIT], SIGINT); 562 } 563 return; 564 } 565 566 keymap_line = &keymap[(scode & 0x7F) * NR_MODIFIERS]; 567 mod = 0; 568 569 if(vc->capslock && (keymap_line[MOD_BASE] & LETTER_KEYS)) { 570 mod = !vc->capslock ? shift : vc->capslock - shift; 571 } else { 572 if(shift && !extkey) { 573 mod = 1; 574 } 575 } 576 if(altgr) { 577 mod = 2; 578 } 579 if(ctrl) { 580 mod = 4; 581 } 582 if(alt) { 583 mod = 8; 584 } 585 586 key = keymap_line[mod]; 587 588 if(key >= AF1 && key <= AF12) { 589 do_switch_console = key - CONS_KEYS; 590 return; 591 } 592 593 if(shift && (key == PGUP)) { 594 do_buf_scroll = SCROLL_UP; 595 return; 596 } 597 598 if(shift && (key == PGDN)) { 599 do_buf_scroll = SCROLL_DOWN; 600 return; 601 } 602 603 if(extkey && (scode == SLASH_NPAD)) { 604 key = SLASH; 605 } 606 607 if(any_key_to_reboot) { 608 reboot(); 609 } 610 611 if(tty->count) { 612 type = key & 0xFF00; 613 c = key & 0xFF; 614 615 if(sysrq) { 616 /* treat 0-9 and a-z keys as normal */ 617 type &= ~META_KEYS; 618 } 619 620 switch(type) { 621 case FN_KEYS: 622 puts(tty, fn_seq[c]); 623 break; 624 625 case SPEC_KEYS: 626 switch(key) { 627 case CR: 628 putc(tty, C('M')); 629 break; 630 case SYSRQ: 631 sysrq = 1; 632 break; 633 } 634 break; 635 636 case PAD_KEYS: 637 if(!vc->numlock) { 638 puts(tty, pad_seq[c]); 639 } else { 640 putc(tty, pad_chars[c]); 641 } 642 break; 643 644 case DEAD_KEYS: 645 if(!deadkey) { 646 switch(c) { 647 case GRAVE ^ DEAD_KEYS: 648 deadkey = 1; 649 diacr = grave_table; 650 break; 651 case ACUTE ^ DEAD_KEYS: 652 deadkey = 2; 653 diacr = acute_table; 654 break; 655 case CIRCM ^ DEAD_KEYS: 656 deadkey = 3; 657 diacr = circm_table; 658 break; 659 case DIERE ^ DEAD_KEYS: 660 deadkey = 5; 661 diacr = diere_table; 662 break; 663 } 664 return; 665 } 666 c = diacr_chars[c]; 667 deadkey = 0; 668 putc(tty, c); 669 670 break; 671 672 case META_KEYS: 673 putc(tty, '\033'); 674 putc(tty, c); 675 break; 676 677 case LETTER_KEYS: 678 if(deadkey) { 679 for(n = 0; n < NR_DIACR; n++) { 680 if(diacr[n].letter == c) { 681 c = diacr[n].code; 682 } 683 } 684 } 685 putc(tty, c); 686 break; 687 688 default: 689 if(sysrq) { 690 switch(c) { 691 case 'l': 692 sysrq_op = SYSRQ_STACK; 693 break; 694 case 't': 695 sysrq_op = SYSRQ_TASKS; 696 break; 697 default: 698 sysrq_op = SYSRQ_UNDEF; 699 break; 700 } 701 return; 702 } 703 if(deadkey && c == ' ') { 704 c = diacr_chars[deadkey - 1]; 705 } 706 putc(tty, c); 707 break; 708 } 709 } 710 deadkey = 0; 711 return; 712 } 713 714 void irq_keyboard_bh(void) 715 { 716 int n; 717 struct tty *tty; 718 struct vconsole *vc; 719 720 tty = get_tty(MKDEV(VCONSOLES_MAJOR, current_cons)); 721 vc = (struct vconsole *)tty->driver_data; 722 723 if(do_switch_console >= 0) { 724 vconsole_select(do_switch_console); 725 do_switch_console = -1; 726 } 727 728 if(do_buf_scroll) { 729 video.buf_scroll(vc, do_buf_scroll); 730 do_buf_scroll = 0; 731 } 732 733 tty = &tty_table[0]; 734 for(n = 0; n < NR_VCONSOLES; n++, tty++) { 735 if(!tty->read_q.count) { 736 continue; 737 } 738 if(tty->kbd.mode == K_RAW || tty->kbd.mode == K_MEDIUMRAW) { 739 wakeup(&tty_read); 740 continue; 741 } 742 if(lock_area(AREA_TTY_READ)) { 743 keyboard_bh.flags |= BH_ACTIVE; 744 continue; 745 } 746 tty->input(tty); 747 unlock_area(AREA_TTY_READ); 748 } 749 750 if(sysrq_op) { 751 do_sysrq(sysrq_op); 752 sysrq_op = 0; 753 } 754 } 755 756 void keyboard_init(void) 757 { 758 struct tty *tty; 759 struct vconsole *vc; 760 761 tty = get_tty(MKDEV(VCONSOLES_MAJOR, current_cons)); 762 vc = (struct vconsole *)tty->driver_data; 763 video.screen_on(vc); 764 video.cursor_blink((unsigned int)vc); 765 766 add_bh(&keyboard_bh); 767 keyboard_reset(); 768 769 /* flush buffers */ 770 while(!keyboard_wait_output()) { 771 inport_b(KB_DATA); 772 } 773 774 keyboard_identify(); 775 776 keyboard_write(KB_DATA, KB_RATE); 777 keyboard_wait_ack(); 778 keyboard_write(KB_DATA, DELAY_250 | RATE_30); 779 keyboard_wait_ack(); 780 781 printk("keyboard 0x%04X-0x%04X %d type=%s %s PS/2 devices=%d/%d\n", 0x60, 0x64, KEYBOARD_IRQ, kb_identify[0] == 0xAB ? "MF2" : "unknown", ps2_iface & 0x1 ? "MCA" : "AT", ps2_active_ports, ps2_supp_ports); 782 783 if(!register_irq(KEYBOARD_IRQ, &irq_config_keyboard)) { 784 enable_irq(KEYBOARD_IRQ); 785 } 786 }