Fork me on GitHub

root/drivers/char/keyboard.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. keyboard_delay
  2. keyboard_wait_input
  3. keyboard_write
  4. keyboard_wait_output
  5. keyboard_wait_ack
  6. keyboard_identify
  7. keyboard_reset
  8. putc
  9. puts
  10. reboot
  11. set_leds
  12. irq_keyboard
  13. irq_keyboard_bh
  14. keyboard_init

   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 }

/* [previous][next][first][last][top][bottom][index][help] */