|
|
1.1 ! root 1: // 16bit code to handle keyboard requests. ! 2: // ! 3: // Copyright (C) 2008 Kevin O'Connor <[email protected]> ! 4: // Copyright (C) 2002 MandrakeSoft S.A. ! 5: // ! 6: // This file may be distributed under the terms of the GNU LGPLv3 license. ! 7: ! 8: #include "biosvar.h" // GET_BDA ! 9: #include "util.h" // debug_enter ! 10: #include "config.h" // CONFIG_* ! 11: #include "bregs.h" // struct bregs ! 12: #include "ps2port.h" // kbd_command ! 13: ! 14: // Bit definitions for BDA kbd_flag[012] ! 15: #define KF0_RSHIFT (1<<0) ! 16: #define KF0_LSHIFT (1<<1) ! 17: #define KF0_CTRLACTIVE (1<<2) ! 18: #define KF0_ALTACTIVE (1<<3) ! 19: #define KF0_SCROLLACTIVE (1<<4) ! 20: #define KF0_NUMACTIVE (1<<5) ! 21: #define KF0_CAPSACTIVE (1<<6) ! 22: ! 23: #define KF1_LCTRL (1<<0) ! 24: #define KF1_LALT (1<<1) ! 25: #define KF1_PAUSEACTIVE (1<<3) ! 26: #define KF1_SCROLL (1<<4) ! 27: #define KF1_NUM (1<<5) ! 28: #define KF1_CAPS (1<<6) ! 29: ! 30: #define KF2_LAST_E1 (1<<0) ! 31: #define KF2_LAST_E0 (1<<1) ! 32: #define KF2_RCTRL (1<<2) ! 33: #define KF2_RALT (1<<3) ! 34: #define KF2_101KBD (1<<4) ! 35: ! 36: void ! 37: kbd_setup() ! 38: { ! 39: dprintf(3, "init keyboard\n"); ! 40: u16 x = offsetof(struct bios_data_area_s, kbd_buf); ! 41: SET_BDA(kbd_flag2, KF2_101KBD); ! 42: SET_BDA(kbd_buf_head, x); ! 43: SET_BDA(kbd_buf_tail, x); ! 44: SET_BDA(kbd_buf_start_offset, x); ! 45: ! 46: SET_BDA(kbd_buf_end_offset ! 47: , x + FIELD_SIZEOF(struct bios_data_area_s, kbd_buf)); ! 48: } ! 49: ! 50: static u8 ! 51: enqueue_key(u8 scan_code, u8 ascii_code) ! 52: { ! 53: u16 buffer_start = GET_BDA(kbd_buf_start_offset); ! 54: u16 buffer_end = GET_BDA(kbd_buf_end_offset); ! 55: ! 56: u16 buffer_head = GET_BDA(kbd_buf_head); ! 57: u16 buffer_tail = GET_BDA(kbd_buf_tail); ! 58: ! 59: u16 temp_tail = buffer_tail; ! 60: buffer_tail += 2; ! 61: if (buffer_tail >= buffer_end) ! 62: buffer_tail = buffer_start; ! 63: ! 64: if (buffer_tail == buffer_head) ! 65: return 0; ! 66: ! 67: SET_FARVAR(SEG_BDA, *(u8*)(temp_tail+0), ascii_code); ! 68: SET_FARVAR(SEG_BDA, *(u8*)(temp_tail+1), scan_code); ! 69: SET_BDA(kbd_buf_tail, buffer_tail); ! 70: return 1; ! 71: } ! 72: ! 73: static void ! 74: dequeue_key(struct bregs *regs, int incr, int extended) ! 75: { ! 76: u16 buffer_head; ! 77: u16 buffer_tail; ! 78: for (;;) { ! 79: buffer_head = GET_BDA(kbd_buf_head); ! 80: buffer_tail = GET_BDA(kbd_buf_tail); ! 81: ! 82: if (buffer_head != buffer_tail) ! 83: break; ! 84: if (!incr) { ! 85: regs->flags |= F_ZF; ! 86: return; ! 87: } ! 88: wait_irq(); ! 89: } ! 90: ! 91: u8 ascii_code = GET_FARVAR(SEG_BDA, *(u8*)(buffer_head+0)); ! 92: u8 scan_code = GET_FARVAR(SEG_BDA, *(u8*)(buffer_head+1)); ! 93: if ((ascii_code == 0xF0 && scan_code != 0) ! 94: || (ascii_code == 0xE0 && !extended)) ! 95: ascii_code = 0; ! 96: regs->ax = (scan_code << 8) | ascii_code; ! 97: ! 98: if (!incr) { ! 99: regs->flags &= ~F_ZF; ! 100: return; ! 101: } ! 102: u16 buffer_start = GET_BDA(kbd_buf_start_offset); ! 103: u16 buffer_end = GET_BDA(kbd_buf_end_offset); ! 104: ! 105: buffer_head += 2; ! 106: if (buffer_head >= buffer_end) ! 107: buffer_head = buffer_start; ! 108: SET_BDA(kbd_buf_head, buffer_head); ! 109: } ! 110: ! 111: // read keyboard input ! 112: static void ! 113: handle_1600(struct bregs *regs) ! 114: { ! 115: dequeue_key(regs, 1, 0); ! 116: } ! 117: ! 118: // check keyboard status ! 119: static void ! 120: handle_1601(struct bregs *regs) ! 121: { ! 122: dequeue_key(regs, 0, 0); ! 123: } ! 124: ! 125: // get shift flag status ! 126: static void ! 127: handle_1602(struct bregs *regs) ! 128: { ! 129: regs->al = GET_BDA(kbd_flag0); ! 130: } ! 131: ! 132: // store key-stroke into buffer ! 133: static void ! 134: handle_1605(struct bregs *regs) ! 135: { ! 136: regs->al = !enqueue_key(regs->ch, regs->cl); ! 137: } ! 138: ! 139: // GET KEYBOARD FUNCTIONALITY ! 140: static void ! 141: handle_1609(struct bregs *regs) ! 142: { ! 143: // bit Bochs Description ! 144: // 7 0 reserved ! 145: // 6 0 INT 16/AH=20h-22h supported (122-key keyboard support) ! 146: // 5 1 INT 16/AH=10h-12h supported (enhanced keyboard support) ! 147: // 4 1 INT 16/AH=0Ah supported ! 148: // 3 0 INT 16/AX=0306h supported ! 149: // 2 0 INT 16/AX=0305h supported ! 150: // 1 0 INT 16/AX=0304h supported ! 151: // 0 0 INT 16/AX=0300h supported ! 152: // ! 153: regs->al = 0x30; ! 154: } ! 155: ! 156: // GET KEYBOARD ID ! 157: static void ! 158: handle_160a(struct bregs *regs) ! 159: { ! 160: u8 param[2]; ! 161: int ret = kbd_command(ATKBD_CMD_GETID, param); ! 162: if (ret) { ! 163: regs->bx = 0; ! 164: return; ! 165: } ! 166: regs->bx = (param[1] << 8) | param[0]; ! 167: } ! 168: ! 169: // read MF-II keyboard input ! 170: static void ! 171: handle_1610(struct bregs *regs) ! 172: { ! 173: dequeue_key(regs, 1, 1); ! 174: } ! 175: ! 176: // check MF-II keyboard status ! 177: static void ! 178: handle_1611(struct bregs *regs) ! 179: { ! 180: dequeue_key(regs, 0, 1); ! 181: } ! 182: ! 183: // get extended keyboard status ! 184: static void ! 185: handle_1612(struct bregs *regs) ! 186: { ! 187: regs->al = GET_BDA(kbd_flag0); ! 188: regs->ah = ((GET_BDA(kbd_flag1) & ~(KF2_RCTRL|KF2_RALT)) ! 189: | (GET_BDA(kbd_flag2) & (KF2_RCTRL|KF2_RALT))); ! 190: //BX_DEBUG_INT16("int16: func 12 sending %04x\n",AX); ! 191: } ! 192: ! 193: static void ! 194: handle_166f(struct bregs *regs) ! 195: { ! 196: if (regs->al == 0x08) ! 197: // unsupported, aka normal keyboard ! 198: regs->ah = 2; ! 199: } ! 200: ! 201: // keyboard capability check called by DOS 5.0+ keyb ! 202: static void ! 203: handle_1692(struct bregs *regs) ! 204: { ! 205: // function int16 ah=0x10-0x12 supported ! 206: regs->ah = 0x80; ! 207: } ! 208: ! 209: // 122 keys capability check called by DOS 5.0+ keyb ! 210: static void ! 211: handle_16a2(struct bregs *regs) ! 212: { ! 213: // don't change AH : function int16 ah=0x20-0x22 NOT supported ! 214: } ! 215: ! 216: static void ! 217: handle_16XX(struct bregs *regs) ! 218: { ! 219: warn_unimplemented(regs); ! 220: } ! 221: ! 222: static void ! 223: set_leds() ! 224: { ! 225: u8 shift_flags = (GET_BDA(kbd_flag0) >> 4) & 0x07; ! 226: u8 kbd_led = GET_BDA(kbd_led); ! 227: u8 led_flags = kbd_led & 0x07; ! 228: if (shift_flags == led_flags) ! 229: return; ! 230: ! 231: int ret = kbd_command(ATKBD_CMD_SETLEDS, &shift_flags); ! 232: if (ret) ! 233: // Error ! 234: return; ! 235: kbd_led = (kbd_led & ~0x07) | shift_flags; ! 236: SET_BDA(kbd_led, kbd_led); ! 237: } ! 238: ! 239: // INT 16h Keyboard Service Entry Point ! 240: void VISIBLE16 ! 241: handle_16(struct bregs *regs) ! 242: { ! 243: debug_enter(regs, DEBUG_HDL_16); ! 244: if (! CONFIG_KEYBOARD) ! 245: return; ! 246: ! 247: // XXX - set_leds should be called from irq handler ! 248: set_leds(); ! 249: ! 250: switch (regs->ah) { ! 251: case 0x00: handle_1600(regs); break; ! 252: case 0x01: handle_1601(regs); break; ! 253: case 0x02: handle_1602(regs); break; ! 254: case 0x05: handle_1605(regs); break; ! 255: case 0x09: handle_1609(regs); break; ! 256: case 0x0a: handle_160a(regs); break; ! 257: case 0x10: handle_1610(regs); break; ! 258: case 0x11: handle_1611(regs); break; ! 259: case 0x12: handle_1612(regs); break; ! 260: case 0x92: handle_1692(regs); break; ! 261: case 0xa2: handle_16a2(regs); break; ! 262: case 0x6f: handle_166f(regs); break; ! 263: default: handle_16XX(regs); break; ! 264: } ! 265: } ! 266: ! 267: #define none 0 ! 268: #define MNUM KF0_NUMACTIVE ! 269: #define MCAP KF0_CAPSACTIVE ! 270: ! 271: static struct scaninfo { ! 272: u16 normal; ! 273: u16 shift; ! 274: u16 control; ! 275: u16 alt; ! 276: u8 lock_flags; ! 277: } scan_to_scanascii[] VAR16 = { ! 278: { none, none, none, none, none }, ! 279: { 0x011b, 0x011b, 0x011b, 0x0100, none }, /* escape */ ! 280: { 0x0231, 0x0221, none, 0x7800, none }, /* 1! */ ! 281: { 0x0332, 0x0340, 0x0300, 0x7900, none }, /* 2@ */ ! 282: { 0x0433, 0x0423, none, 0x7a00, none }, /* 3# */ ! 283: { 0x0534, 0x0524, none, 0x7b00, none }, /* 4$ */ ! 284: { 0x0635, 0x0625, none, 0x7c00, none }, /* 5% */ ! 285: { 0x0736, 0x075e, 0x071e, 0x7d00, none }, /* 6^ */ ! 286: { 0x0837, 0x0826, none, 0x7e00, none }, /* 7& */ ! 287: { 0x0938, 0x092a, none, 0x7f00, none }, /* 8* */ ! 288: { 0x0a39, 0x0a28, none, 0x8000, none }, /* 9( */ ! 289: { 0x0b30, 0x0b29, none, 0x8100, none }, /* 0) */ ! 290: { 0x0c2d, 0x0c5f, 0x0c1f, 0x8200, none }, /* -_ */ ! 291: { 0x0d3d, 0x0d2b, none, 0x8300, none }, /* =+ */ ! 292: { 0x0e08, 0x0e08, 0x0e7f, none, none }, /* backspace */ ! 293: { 0x0f09, 0x0f00, none, none, none }, /* tab */ ! 294: { 0x1071, 0x1051, 0x1011, 0x1000, MCAP }, /* Q */ ! 295: { 0x1177, 0x1157, 0x1117, 0x1100, MCAP }, /* W */ ! 296: { 0x1265, 0x1245, 0x1205, 0x1200, MCAP }, /* E */ ! 297: { 0x1372, 0x1352, 0x1312, 0x1300, MCAP }, /* R */ ! 298: { 0x1474, 0x1454, 0x1414, 0x1400, MCAP }, /* T */ ! 299: { 0x1579, 0x1559, 0x1519, 0x1500, MCAP }, /* Y */ ! 300: { 0x1675, 0x1655, 0x1615, 0x1600, MCAP }, /* U */ ! 301: { 0x1769, 0x1749, 0x1709, 0x1700, MCAP }, /* I */ ! 302: { 0x186f, 0x184f, 0x180f, 0x1800, MCAP }, /* O */ ! 303: { 0x1970, 0x1950, 0x1910, 0x1900, MCAP }, /* P */ ! 304: { 0x1a5b, 0x1a7b, 0x1a1b, none, none }, /* [{ */ ! 305: { 0x1b5d, 0x1b7d, 0x1b1d, none, none }, /* ]} */ ! 306: { 0x1c0d, 0x1c0d, 0x1c0a, none, none }, /* Enter */ ! 307: { none, none, none, none, none }, /* L Ctrl */ ! 308: { 0x1e61, 0x1e41, 0x1e01, 0x1e00, MCAP }, /* A */ ! 309: { 0x1f73, 0x1f53, 0x1f13, 0x1f00, MCAP }, /* S */ ! 310: { 0x2064, 0x2044, 0x2004, 0x2000, MCAP }, /* D */ ! 311: { 0x2166, 0x2146, 0x2106, 0x2100, MCAP }, /* F */ ! 312: { 0x2267, 0x2247, 0x2207, 0x2200, MCAP }, /* G */ ! 313: { 0x2368, 0x2348, 0x2308, 0x2300, MCAP }, /* H */ ! 314: { 0x246a, 0x244a, 0x240a, 0x2400, MCAP }, /* J */ ! 315: { 0x256b, 0x254b, 0x250b, 0x2500, MCAP }, /* K */ ! 316: { 0x266c, 0x264c, 0x260c, 0x2600, MCAP }, /* L */ ! 317: { 0x273b, 0x273a, none, none, none }, /* ;: */ ! 318: { 0x2827, 0x2822, none, none, none }, /* '" */ ! 319: { 0x2960, 0x297e, none, none, none }, /* `~ */ ! 320: { none, none, none, none, none }, /* L shift */ ! 321: { 0x2b5c, 0x2b7c, 0x2b1c, none, none }, /* |\ */ ! 322: { 0x2c7a, 0x2c5a, 0x2c1a, 0x2c00, MCAP }, /* Z */ ! 323: { 0x2d78, 0x2d58, 0x2d18, 0x2d00, MCAP }, /* X */ ! 324: { 0x2e63, 0x2e43, 0x2e03, 0x2e00, MCAP }, /* C */ ! 325: { 0x2f76, 0x2f56, 0x2f16, 0x2f00, MCAP }, /* V */ ! 326: { 0x3062, 0x3042, 0x3002, 0x3000, MCAP }, /* B */ ! 327: { 0x316e, 0x314e, 0x310e, 0x3100, MCAP }, /* N */ ! 328: { 0x326d, 0x324d, 0x320d, 0x3200, MCAP }, /* M */ ! 329: { 0x332c, 0x333c, none, none, none }, /* ,< */ ! 330: { 0x342e, 0x343e, none, none, none }, /* .> */ ! 331: { 0x352f, 0x353f, none, none, none }, /* /? */ ! 332: { none, none, none, none, none }, /* R Shift */ ! 333: { 0x372a, 0x372a, none, none, none }, /* * */ ! 334: { none, none, none, none, none }, /* L Alt */ ! 335: { 0x3920, 0x3920, 0x3920, 0x3920, none }, /* space */ ! 336: { none, none, none, none, none }, /* caps lock */ ! 337: { 0x3b00, 0x5400, 0x5e00, 0x6800, none }, /* F1 */ ! 338: { 0x3c00, 0x5500, 0x5f00, 0x6900, none }, /* F2 */ ! 339: { 0x3d00, 0x5600, 0x6000, 0x6a00, none }, /* F3 */ ! 340: { 0x3e00, 0x5700, 0x6100, 0x6b00, none }, /* F4 */ ! 341: { 0x3f00, 0x5800, 0x6200, 0x6c00, none }, /* F5 */ ! 342: { 0x4000, 0x5900, 0x6300, 0x6d00, none }, /* F6 */ ! 343: { 0x4100, 0x5a00, 0x6400, 0x6e00, none }, /* F7 */ ! 344: { 0x4200, 0x5b00, 0x6500, 0x6f00, none }, /* F8 */ ! 345: { 0x4300, 0x5c00, 0x6600, 0x7000, none }, /* F9 */ ! 346: { 0x4400, 0x5d00, 0x6700, 0x7100, none }, /* F10 */ ! 347: { none, none, none, none, none }, /* Num Lock */ ! 348: { none, none, none, none, none }, /* Scroll Lock */ ! 349: { 0x4700, 0x4737, 0x7700, none, MNUM }, /* 7 Home */ ! 350: { 0x4800, 0x4838, none, none, MNUM }, /* 8 UP */ ! 351: { 0x4900, 0x4939, 0x8400, none, MNUM }, /* 9 PgUp */ ! 352: { 0x4a2d, 0x4a2d, none, none, none }, /* - */ ! 353: { 0x4b00, 0x4b34, 0x7300, none, MNUM }, /* 4 Left */ ! 354: { 0x4c00, 0x4c35, none, none, MNUM }, /* 5 */ ! 355: { 0x4d00, 0x4d36, 0x7400, none, MNUM }, /* 6 Right */ ! 356: { 0x4e2b, 0x4e2b, none, none, none }, /* + */ ! 357: { 0x4f00, 0x4f31, 0x7500, none, MNUM }, /* 1 End */ ! 358: { 0x5000, 0x5032, none, none, MNUM }, /* 2 Down */ ! 359: { 0x5100, 0x5133, 0x7600, none, MNUM }, /* 3 PgDn */ ! 360: { 0x5200, 0x5230, none, none, MNUM }, /* 0 Ins */ ! 361: { 0x5300, 0x532e, none, none, MNUM }, /* Del */ ! 362: { none, none, none, none, none }, ! 363: { none, none, none, none, none }, ! 364: { 0x565c, 0x567c, none, none, none }, /* \| */ ! 365: { 0x8500, 0x8700, 0x8900, 0x8b00, none }, /* F11 */ ! 366: { 0x8600, 0x8800, 0x8a00, 0x8c00, none }, /* F12 */ ! 367: }; ! 368: ! 369: // Handle a scancode read from the ps2 port. Note that "noinline" is ! 370: // used to make sure the call to call16_simpint in process_key doesn't ! 371: // have the overhead of this function's stack. ! 372: static void noinline ! 373: __process_key(u8 scancode) ! 374: { ! 375: u8 flags0 = GET_BDA(kbd_flag0); ! 376: u8 flags1 = GET_BDA(kbd_flag1); ! 377: u8 flags2 = GET_BDA(kbd_flag2); ! 378: ! 379: if (flags2 & KF2_LAST_E1) { ! 380: // Part of "pause" key (sequence is e1 1d 45 e1 9d c5) ! 381: if ((scancode & ~0x80) == 0x1d) ! 382: // Second key of sequence ! 383: return; ! 384: // Third key of sequence - clear flag. ! 385: flags2 &= ~KF2_LAST_E1; ! 386: SET_BDA(kbd_flag2, flags2); ! 387: ! 388: if (scancode == 0xc5) { ! 389: // Final key in sequence. ! 390: ! 391: // XXX - do actual pause. ! 392: } ! 393: return; ! 394: } ! 395: ! 396: // XXX - PrtScr should cause int 0x05 ! 397: // XXX - Ctrl+Break should cause int 0x1B ! 398: // XXX - SysReq should cause int 0x15/0x85 ! 399: ! 400: switch (scancode) { ! 401: case 0x00: ! 402: dprintf(1, "KBD: int09 handler: AL=0\n"); ! 403: return; ! 404: ! 405: case 0x3a: /* Caps Lock press */ ! 406: flags0 ^= KF0_CAPSACTIVE; ! 407: flags1 |= KF1_CAPS; ! 408: break; ! 409: case 0xba: /* Caps Lock release */ ! 410: flags1 &= ~KF1_CAPS; ! 411: break; ! 412: ! 413: case 0x2a: /* L Shift press */ ! 414: flags0 |= KF0_LSHIFT; ! 415: break; ! 416: case 0xaa: /* L Shift release */ ! 417: flags0 &= ~KF0_LSHIFT; ! 418: break; ! 419: ! 420: case 0x36: /* R Shift press */ ! 421: flags0 |= KF0_RSHIFT; ! 422: break; ! 423: case 0xb6: /* R Shift release */ ! 424: flags0 &= ~KF0_RSHIFT; ! 425: break; ! 426: ! 427: case 0x1d: /* Ctrl press */ ! 428: flags0 |= KF0_CTRLACTIVE; ! 429: if (flags2 & KF2_LAST_E0) ! 430: flags2 |= KF2_RCTRL; ! 431: else ! 432: flags1 |= KF1_LCTRL; ! 433: break; ! 434: case 0x9d: /* Ctrl release */ ! 435: flags0 &= ~KF0_CTRLACTIVE; ! 436: if (flags2 & KF2_LAST_E0) ! 437: flags2 &= ~KF2_RCTRL; ! 438: else ! 439: flags1 &= ~KF1_LCTRL; ! 440: break; ! 441: ! 442: case 0x38: /* Alt press */ ! 443: flags0 |= KF0_ALTACTIVE; ! 444: if (flags2 & KF2_LAST_E0) ! 445: flags2 |= KF2_RALT; ! 446: else ! 447: flags1 |= KF1_LALT; ! 448: break; ! 449: case 0xb8: /* Alt release */ ! 450: flags0 &= ~KF0_ALTACTIVE; ! 451: if (flags2 & KF2_LAST_E0) ! 452: flags2 &= ~KF2_RALT; ! 453: else ! 454: flags1 &= ~KF1_LALT; ! 455: break; ! 456: ! 457: case 0x45: /* Num Lock press */ ! 458: flags1 |= KF1_NUM; ! 459: flags0 ^= KF0_NUMACTIVE; ! 460: break; ! 461: case 0xc5: /* Num Lock release */ ! 462: flags1 &= ~KF1_NUM; ! 463: break; ! 464: ! 465: case 0x46: /* Scroll Lock press */ ! 466: flags1 |= KF1_SCROLL; ! 467: flags0 ^= KF0_SCROLLACTIVE; ! 468: break; ! 469: case 0xc6: /* Scroll Lock release */ ! 470: flags1 &= ~KF1_SCROLL; ! 471: break; ! 472: ! 473: case 0xe0: ! 474: // Extended key ! 475: flags2 |= KF2_LAST_E0; ! 476: SET_BDA(kbd_flag2, flags2); ! 477: return; ! 478: case 0xe1: ! 479: // Start of pause key sequence ! 480: flags2 |= KF2_LAST_E1; ! 481: break; ! 482: ! 483: default: ! 484: if (scancode & 0x80) ! 485: // toss key releases ! 486: break; ! 487: if (scancode == 0x53 ! 488: && ((flags0 & (KF0_CTRLACTIVE|KF0_ALTACTIVE)) ! 489: == (KF0_CTRLACTIVE|KF0_ALTACTIVE))) { ! 490: // Ctrl+alt+del - reset machine. ! 491: SET_BDA(soft_reset_flag, 0x1234); ! 492: reset_vector(); ! 493: } ! 494: if (scancode >= ARRAY_SIZE(scan_to_scanascii)) { ! 495: dprintf(1, "KBD: int09h_handler(): unknown scancode read: 0x%02x!\n" ! 496: , scancode); ! 497: return; ! 498: } ! 499: u8 asciicode; ! 500: struct scaninfo *info = &scan_to_scanascii[scancode]; ! 501: if (flags0 & KF0_ALTACTIVE) { ! 502: asciicode = GET_GLOBAL(info->alt); ! 503: scancode = GET_GLOBAL(info->alt) >> 8; ! 504: } else if (flags0 & KF0_CTRLACTIVE) { ! 505: asciicode = GET_GLOBAL(info->control); ! 506: scancode = GET_GLOBAL(info->control) >> 8; ! 507: } else if (flags2 & KF2_LAST_E0 ! 508: && scancode >= 0x47 && scancode <= 0x53) { ! 509: /* extended keys handling */ ! 510: asciicode = 0xe0; ! 511: scancode = GET_GLOBAL(info->normal) >> 8; ! 512: } else if (flags0 & (KF0_RSHIFT|KF0_LSHIFT)) { ! 513: /* check if lock state should be ignored because a SHIFT ! 514: * key is pressed */ ! 515: ! 516: if (flags0 & GET_GLOBAL(info->lock_flags)) { ! 517: asciicode = GET_GLOBAL(info->normal); ! 518: scancode = GET_GLOBAL(info->normal) >> 8; ! 519: } else { ! 520: asciicode = GET_GLOBAL(info->shift); ! 521: scancode = GET_GLOBAL(info->shift) >> 8; ! 522: } ! 523: } else { ! 524: /* check if lock is on */ ! 525: if (flags0 & GET_GLOBAL(info->lock_flags)) { ! 526: asciicode = GET_GLOBAL(info->shift); ! 527: scancode = GET_GLOBAL(info->shift) >> 8; ! 528: } else { ! 529: asciicode = GET_GLOBAL(info->normal); ! 530: scancode = GET_GLOBAL(info->normal) >> 8; ! 531: } ! 532: } ! 533: if (scancode==0 && asciicode==0) ! 534: dprintf(1, "KBD: scancode & asciicode are zero?\n"); ! 535: enqueue_key(scancode, asciicode); ! 536: break; ! 537: } ! 538: flags2 &= ~KF2_LAST_E0; ! 539: ! 540: SET_BDA(kbd_flag0, flags0); ! 541: SET_BDA(kbd_flag1, flags1); ! 542: SET_BDA(kbd_flag2, flags2); ! 543: } ! 544: ! 545: void ! 546: process_key(u8 key) ! 547: { ! 548: if (!CONFIG_KEYBOARD) ! 549: return; ! 550: ! 551: if (CONFIG_KBD_CALL_INT15_4F) { ! 552: // allow for keyboard intercept ! 553: u32 eax = (0x4f << 8) | key; ! 554: u32 flags; ! 555: call16_simpint(0x15, &eax, &flags); ! 556: if (!(flags & F_CF)) ! 557: return; ! 558: key = eax; ! 559: } ! 560: __process_key(key); ! 561: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.