|
|
1.1 ! root 1: /* (-lgl ! 2: * COHERENT Driver Kit Version 1.1.0 ! 3: * Copyright (c) 1982, 1990 by Mark Williams Company. ! 4: * All rights reserved. May not be copied without permission. ! 5: -lgl) */ ! 6: /* ! 7: * Keyboard/display driver. ! 8: * Coherent, IBM PC/XT/AT. ! 9: */ ! 10: ! 11: /* ! 12: * virtual terminal additions Copyright 1991, 1992 Todd Fleming ! 13: * 6/91, 1/92 ! 14: * ! 15: * Todd Fleming ! 16: * 1991 Mountainside Drive ! 17: * Blacksburg, VA 24060 ! 18: */ ! 19: ! 20: /* Notes on virtual terminal additions: ! 21: * ! 22: * Console minor dev # = 0, virtual terminal minor #'s = 1 - 10 ! 23: * User switches terminals w/CTRL + F1-10 ! 24: * ! 25: * Console is parasitic. Its output is always directed to the current ! 26: * onscreen terminal and it steels its input from the current terminal. ! 27: * ! 28: * NEVER allow the console to be enabled via /etc/ttys while virtual terminals ! 29: * are enabled. It is only used in single-user mode and for system messages. ! 30: * (When in single-user mode, the kernal automatically uses the console ! 31: * even though it is disabled in /etc/ttys) ! 32: * ! 33: * Each virtual terminal has its own resources for the screen buffer, ! 34: * toggle key state (num, caps, and scroll lock), alternate keypad state, ! 35: * keyboard lock state, and ESC-string parsing state. Except for input, ! 36: * all virtual terminals are fully functional at all times. The ! 37: * virtual-terminal switching is transparent to the kernal and user programs. ! 38: * ! 39: * Loadable key tables are not supported. (This feature was unavailable in ! 40: * the origional source code for kb). Loadable function keys are supported. ! 41: */ ! 42: ! 43: #include <sys/coherent.h> ! 44: #include <sys/i8086.h> ! 45: #include <sys/con.h> ! 46: #include <sys/devices.h> ! 47: #include <errno.h> ! 48: #include <sys/stat.h> ! 49: #include <sys/tty.h> ! 50: #include <signal.h> ! 51: #include <sys/sched.h> ! 52: #include <sys/silo.h> ! 53: ! 54: #define NVIRTERMS 4 /* Number of virtual terminals */ ! 55: /* (Does not include console) */ ! 56: ! 57: #define SPC 0376 /* Special encoding */ ! 58: #define XXX 0377 /* Non-character */ ! 59: #define KBDATA 0x60 /* Keyboard data */ ! 60: #define KBCTRL 0x61 /* Keyboard control */ ! 61: #define KBFLAG 0x80 /* Keyboard reset flag */ ! 62: #define LEDCMD 0xED /* status indicator command */ ! 63: #define KBACK 0xFA /* status indicator acknowledge */ ! 64: #define EXTENDED1 0xE1 /* extended key seq initiator */ ! 65: ! 66: #define KEYUP 0x80 /* Key up change */ ! 67: #define KEYSC 0x7F /* Key scan code mask */ ! 68: #define LSHIFT 0x2A-1 /* Left shift key */ ! 69: #define LSHIFTA 0x2B-1 /* Alternate left-shift key */ ! 70: #define RSHIFT 0x36-1 /* Right shift key */ ! 71: #define CTRL 0x1D-1 /* Control key */ ! 72: /*-- #define CAPLOCK 0x1D-1 --*/ /* Control key */ ! 73: #define ALT 0x38-1 /* Alt key */ ! 74: #define CAPLOCK 0x3A-1 /* Caps lock key */ ! 75: /*-- #define CTRL 0x3A-1 --*/ /* Caps lock key */ ! 76: #define NUMLOCK 0x45-1 /* Numeric lock key */ ! 77: #define DELETE 0x53-1 /* Del, as in CTRL-ALT-DEL */ ! 78: #define BACKSP 0x0E-1 /* Back space */ ! 79: #define SCRLOCK 0x46-1 /* Scroll lock */ ! 80: ! 81: /* Shift flags */ ! 82: #define SRS 0x01 /* Right shift key on */ ! 83: #define SLS 0x02 /* Left shift key on */ ! 84: #define CTS 0x04 /* Ctrl key on */ ! 85: #define ALS 0x08 /* Alt key on */ ! 86: #define CPLS 0x10 /* Caps lock on */ ! 87: #define NMLS 0x20 /* Num lock on */ ! 88: #define AKPS 0x40 /* Alternate keypad shift */ ! 89: #define SHFT 0x80 /* Shift key flag */ ! 90: ! 91: /* Function key information */ ! 92: #define NFKEY 20 /* Number of settable functions */ ! 93: #define NFCHAR 150 /* Number of characters settable */ ! 94: #define NFBUF (NFKEY*2+NFCHAR+1) /* Size of buffer */ ! 95: ! 96: /* ! 97: * Functions. ! 98: */ ! 99: int isrint(); ! 100: int istime(); ! 101: void isbatch(); ! 102: int mmstart(); ! 103: int isopen(); ! 104: int isclose(); ! 105: int isread(); ! 106: int mmwrite(); ! 107: int isioctl(); ! 108: void mmwatch(); ! 109: int isload(); ! 110: int isuload(); ! 111: int ispoll(); ! 112: int nulldev(); ! 113: int nonedev(); ! 114: ! 115: /* ! 116: * virtual terminal stuff ! 117: */ ! 118: ! 119: extern int mmcurvirterm; /* current on-screen terminal */ ! 120: extern int mmvirtermsinitialized; /* initialization flag */ ! 121: extern mminitvirterm(); /* starter function */ ! 122: extern mmchangevirterm(); /* mm's half of this function */ ! 123: kbchangeterm(); /* kb's part */ ! 124: unsigned kbAKPShold[NVIRTERMS+1]; /* Alternate keypad states */ ! 125: unsigned kbNUMLCKhold[NVIRTERMS+1]; /* NumLock states */ ! 126: unsigned kbCAPLCKhold[NVIRTERMS+1]; /* CapLock states */ ! 127: ! 128: /* ! 129: * Configuration table. ! 130: */ ! 131: CON iscon ={ ! 132: DFCHR|DFPOL, /* Flags */ ! 133: KB_MAJOR, /* Major index */ ! 134: isopen, /* Open */ ! 135: isclose, /* Close */ ! 136: nulldev, /* Block */ ! 137: isread, /* Read */ ! 138: mmwrite, /* Write */ ! 139: isioctl, /* Ioctl */ ! 140: nulldev, /* Powerfail */ ! 141: mmwatch, /* Timeout */ ! 142: isload, /* Load */ ! 143: isuload, /* Unload */ ! 144: ispoll /* Poll */ ! 145: }; ! 146: ! 147: /* ! 148: * Flag indicating turbo machine. ! 149: */ ! 150: int isturbo = 0; ! 151: ! 152: /* ! 153: * Terminal structures. ! 154: * istty[0]= console ! 155: * 1-10 = virtual terminals ! 156: */ ! 157: TTY istty[NVIRTERMS+1] = { ! 158: {{0}, {0}, 0, mmstart, NULL, 0, 0}, ! 159: {{0}, {0}, 1, mmstart, NULL, 0, 0}, ! 160: {{0}, {0}, 2, mmstart, NULL, 0, 0}, ! 161: {{0}, {0}, 3, mmstart, NULL, 0, 0}, ! 162: {{0}, {0}, 4, mmstart, NULL, 0, 0}, ! 163: #if 0 ! 164: {{0}, {0}, 5, mmstart, NULL, 0, 0}, ! 165: {{0}, {0}, 6, mmstart, NULL, 0, 0}, ! 166: {{0}, {0}, 7, mmstart, NULL, 0, 0}, ! 167: {{0}, {0}, 8, mmstart, NULL, 0, 0}, ! 168: {{0}, {0}, 9, mmstart, NULL, 0, 0}, ! 169: {{0}, {0}, 10, mmstart, NULL, 0, 0} ! 170: #endif ! 171: }; ! 172: silo_t in_silo[NVIRTERMS+1]; ! 173: ! 174: /* ! 175: * State variables. ! 176: */ ! 177: int islock[NVIRTERMS+1]; /* Keyboard locked flag */ ! 178: int isbusy; /* Raw input conversion busy */ ! 179: static char shift; /* Overall shift state */ ! 180: static char scroll[NVIRTERMS+1]; /* Scroll lock state */ ! 181: static char lshift = LSHIFT; /* Left shift alternate state */ ! 182: static char isfbuf[NFBUF]; /* Function key values */ ! 183: static char *isfval[NFKEY]; /* Function key string pointers */ ! 184: static int ledcmd; /* LED update command flag */ ! 185: static int extended; /* extended key scan count */ ! 186: ! 187: /* ! 188: * Tables for converting key code to ASCII. ! 189: * lmaptab specifies unshifted conversion, ! 190: * umaptab specifies shifted conversion, ! 191: * smaptab specifies the shift states which are active. ! 192: * An entry of XXX says the key is dead. ! 193: * An entry of SPC requires further processing. ! 194: * ! 195: * Key codes: ! 196: * ESC .. <- == 1 .. 14 ! 197: * -> .. \n == 15 .. 28 ! 198: * CTRL .. ` == 29 .. 41 ! 199: * ^Shift .. PrtSc == 42 .. 55 ! 200: * ALT .. CapsLock == 56 .. 58 ! 201: * F1 .. F10 == 59 .. 68 ! 202: * NumLock .. Del == 69 .. 83 ! 203: */ ! 204: static unsigned char lmaptab[] ={ ! 205: '\33', '1', '2', '3', '4', '5', '6', /* 1 - 7 */ ! 206: '7', '8', '9', '0', '-', '=', '\b', '\t', /* 8 - 15 */ ! 207: 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* 16 - 23 */ ! 208: 'o', 'p', '[', ']', '\r', XXX, 'a', 's', /* 24 - 31 */ ! 209: 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 32 - 39 */ ! 210: '\'', '`', XXX, '\\', 'z', 'x', 'c', 'v', /* 40 - 47 */ ! 211: 'b', 'n', 'm', ',', '.', '/', XXX, '*', /* 48 - 55 */ ! 212: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */ ! 213: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */ ! 214: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */ ! 215: SPC, SPC, SPC, SPC /* 80 - 83 */ ! 216: }; ! 217: ! 218: static unsigned char umaptab[] ={ ! 219: '\33', '!', '@', '#', '$', '%', '^', /* 1 - 7 */ ! 220: '&', '*', '(', ')', '_', '+', '\b', SPC, /* 8 - 15 */ ! 221: 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* 16 - 23 */ ! 222: 'O', 'P', '{', '}', '\r', XXX, 'A', 'S', /* 24 - 31 */ ! 223: 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* 32 - 39 */ ! 224: '"', '~', XXX, '|', 'Z', 'X', 'C', 'V', /* 40 - 47 */ ! 225: 'B', 'N', 'M', '<', '>', '?', XXX, '*', /* 48 - 55 */ ! 226: XXX, ' ', XXX, SPC, SPC, SPC, SPC, SPC, /* 56 - 63 */ ! 227: SPC, SPC, SPC, SPC, SPC, SPC, SPC, SPC, /* 64 - 71 */ ! 228: SPC, SPC, '-', SPC, SPC, SPC, '+', SPC, /* 72 - 79 */ ! 229: SPC, SPC, SPC, SPC /* 80 - 83 */ ! 230: }; ! 231: ! 232: #define SS0 0 /* No shift */ ! 233: #define SS1 (SLS|SRS|CTS) /* Shift, Ctrl */ ! 234: #define SES (SLS|SRS) /* Shift */ ! 235: #define LET (SLS|SRS|CPLS|CTS) /* Shift, Caps, Ctrl */ ! 236: #define KEY (SLS|SRS|NMLS|AKPS) /* Shift, Num, Alt keypad */ ! 237: ! 238: static unsigned char smaptab[] ={ ! 239: SS0, SES, SS1, SES, SES, SES, SS1, /* 1 - 7 */ ! 240: SES, SES, SES, SES, SS1, SES, CTS, SES, /* 8 - 15 */ ! 241: LET, LET, LET, LET, LET, LET, LET, LET, /* 16 - 23 */ ! 242: LET, LET, SS1, SS1, CTS, SHFT, LET, LET, /* 24 - 31 */ ! 243: LET, LET, LET, LET, LET, LET, LET, SES, /* 32 - 39 */ ! 244: SES, SS1, SHFT, SS1, LET, LET, LET, LET, /* 40 - 47 */ ! 245: LET, LET, LET, SES, SES, SES, SHFT, SES, /* 48 - 55 */ ! 246: SHFT, SS1, SHFT, SS0, SS0, SS0, SS0, SS0, /* 56 - 63 */ ! 247: SS0, SS0, SS0, SS0, SS0, SHFT, KEY, KEY, /* 64 - 71 */ ! 248: KEY, KEY, SS0, KEY, KEY, KEY, SS0, KEY, /* 72 - 79 */ ! 249: KEY, KEY, KEY, KEY /* 80 - 83 */ ! 250: }; ! 251: ! 252: /* ! 253: * Load entry point. ! 254: * Do reset the keyboard because it gets terribly munged ! 255: * if you type during the boot. ! 256: */ ! 257: isload() ! 258: { ! 259: register int i; ! 260: ! 261: /* ! 262: * Reset keyboard if NOT an XT turbo. ! 263: */ ! 264: if ( ! isturbo ) { ! 265: outb(KBCTRL, 0x0C); /* Clock low */ ! 266: for (i = 10582; --i >= 0; ); /* For 20ms */ ! 267: outb(KBCTRL, 0xCC); /* Clock high */ ! 268: for (i = 0; --i != 0; ) ! 269: ; ! 270: i = inb(KBDATA); ! 271: outb(KBCTRL, 0xCC); /* Clear keyboard */ ! 272: outb(KBCTRL, 0x4D); /* Enable keyboard */ ! 273: } ! 274: ! 275: /* ! 276: * Enable mmwatch() invocation every second. ! 277: */ ! 278: drvl[KB_MAJOR].d_time = 1; ! 279: ! 280: /* ! 281: * Seize keyboard interrupt. ! 282: */ ! 283: setivec(1, isrint); ! 284: ! 285: /* ! 286: * Initiailize video display. ! 287: */ ! 288: for(i=0;i<=NVIRTERMS;i++) /* initialize console, virterms */ ! 289: mmstart( &istty[i] ); ! 290: } ! 291: ! 292: /* ! 293: * Unload entry point. ! 294: */ ! 295: isuload() ! 296: { ! 297: clrivec(1); ! 298: } ! 299: ! 300: /* ! 301: * Default function key strings (terminated by -1 [\377]) ! 302: */ ! 303: static char *deffuncs[] = { ! 304: "\33[1x\377", /* F1 */ ! 305: "\33[2x\377", /* F2 */ ! 306: "\33[3x\377", /* F3 */ ! 307: "\33[4x\377", /* F4 */ ! 308: "\33[5x\377", /* F5 */ ! 309: "\33[6x\377", /* F6 */ ! 310: "\33[7x\377", /* F7 */ ! 311: "\33[8x\377", /* F8 */ ! 312: "\33[9x\377", /* F9 */ ! 313: "\33[0x\377", /* F10 - historical value */ ! 314: "\33[1y\377", /* F11 */ ! 315: "\33[2y\377", /* F12 */ ! 316: "\33[3y\377", /* F13 */ ! 317: "\33[4y\377", /* F14 */ ! 318: "\33[5y\377", /* F15 */ ! 319: "\33[6y\377", /* F16 */ ! 320: "\33[7y\377", /* F17 */ ! 321: "\33[8y\377", /* F18 */ ! 322: "\33[9y\377", /* F19 */ ! 323: "\33[0y\377" /* F20 */ ! 324: }; ! 325: ! 326: /* ! 327: * Open routine. ! 328: */ ! 329: isopen(dev) ! 330: dev_t dev; ! 331: { ! 332: register int s; ! 333: ! 334: if (minor(dev) > NVIRTERMS) { ! 335: u.u_error = ENXIO; ! 336: return; ! 337: } ! 338: ! 339: if ((istty[minor(dev)].t_flags&T_EXCL)!=0 && super()==0) { ! 340: u.u_error = ENODEV; ! 341: return; ! 342: } ! 343: ttsetgrp(&istty[minor(dev)], dev); ! 344: ! 345: s = sphi(); ! 346: if ((istty[minor(dev)].t_open)++ == 0) ! 347: { initkeys(); /* init function keys */ ! 348: istty[minor(dev)].t_flags = T_CARR; /* indicate "carrier" */ ! 349: ttopen(&istty[minor(dev)]); ! 350: } ! 351: spl(s); ! 352: updleds(); /* update keyboard status LEDS */ ! 353: } ! 354: ! 355: /* Init function keys */ ! 356: initkeys() ! 357: { register int i; ! 358: register char *cp1, *cp2; ! 359: ! 360: for (i=0; i<NFKEY; i++) ! 361: isfval[i] = 0; /* clear function key buffer */ ! 362: cp2 = isfbuf; /* pointer to key buffer */ ! 363: for (i=0; i<NFKEY; i++) ! 364: { isfval[i] = cp2; /* save pointer to key string */ ! 365: cp1 = deffuncs[i]; /* get init string pointer */ ! 366: while ((*cp2++ = *cp1++) != -1) /* copy key data */ ! 367: if (cp2 >= &isfbuf[NFBUF-3]) /* overflow? */ ! 368: return; ! 369: } ! 370: } ! 371: ! 372: /* ! 373: * Close a tty. ! 374: */ ! 375: isclose(dev) ! 376: { ! 377: register int s; ! 378: ! 379: s = sphi(); ! 380: if (--(istty[minor(dev)].t_open) == 0) ! 381: { s = sphi(); ! 382: ttclose(&istty[minor(dev)]); ! 383: } ! 384: spl(s); ! 385: } ! 386: ! 387: /* ! 388: * Read routine. ! 389: */ ! 390: isread(dev, iop) ! 391: dev_t dev; ! 392: IO *iop; ! 393: { ! 394: dev_t usedev=dev; ! 395: if(minor(usedev)==0 && istty[mmcurvirterm].t_open) ! 396: /* Route input from current */ ! 397: usedev=makedev(2,mmcurvirterm); /* virtual terminal to console (TBF) */ ! 398: ttread(&istty[minor(usedev)], iop, 0); ! 399: if (istty[minor(usedev)].t_oq.cq_cc) ! 400: mmtime(&istty[minor(usedev)]); ! 401: } ! 402: ! 403: /* ! 404: * Ioctl routine. ! 405: */ ! 406: isioctl(dev, com, vec) ! 407: dev_t dev; ! 408: struct sgttyb *vec; ! 409: { ! 410: register int s; ! 411: ! 412: switch(com) { ! 413: case TIOCSETF: ! 414: case TIOCGETF: ! 415: isfunction(com, (char *)vec); ! 416: return; ! 417: case TIOCSHIFT: /* switch left-SHIFT and "\" */ ! 418: lshift = LSHIFTA; /* alternate values */ ! 419: lmaptab[41] = '\\'; ! 420: lmaptab[42] = XXX; ! 421: umaptab[41] = '|'; ! 422: umaptab[42] = XXX; ! 423: smaptab[41] = SS1; ! 424: smaptab[42] = SHFT; ! 425: return; ! 426: case TIOCCSHIFT: /* normal (default) left-SHIFT and "\" */ ! 427: lshift = LSHIFT; /* normal values */ ! 428: lmaptab[41] = XXX; ! 429: lmaptab[42] = '\\'; ! 430: umaptab[41] = XXX; ! 431: umaptab[42] = '|'; ! 432: smaptab[41] = SHFT; ! 433: smaptab[42] = SS1; ! 434: return; ! 435: } ! 436: s = sphi(); ! 437: ttioctl(&istty[minor(dev)], com, vec); ! 438: spl(s); ! 439: } ! 440: ! 441: /* ! 442: * Set and receive the function keys. ! 443: */ ! 444: isfunction(c, v) ! 445: int c; ! 446: char *v; ! 447: { ! 448: register char *cp; ! 449: register int i; ! 450: ! 451: if (c == TIOCGETF) { ! 452: for (cp = isfbuf; cp < &isfbuf[NFBUF]; cp++) ! 453: putubd(v++, *cp); ! 454: } else { ! 455: for (i=0; i<NFKEY; i++) /* zap current settings */ ! 456: isfval[i] = 0; ! 457: cp = isfbuf; /* pointer to key buffer */ ! 458: for (i=0; i<NFKEY; i++) { ! 459: isfval[i] = cp; /* save pointer to key string */ ! 460: while ((*cp++ = getubd(v++)) != -1) /* copy key data */ ! 461: if (cp >= &isfbuf[NFBUF-3]) /* overflow? */ ! 462: return; ! 463: } ! 464: } ! 465: } ! 466: ! 467: ! 468: /* ! 469: * Poll routine. ! 470: */ ! 471: ispoll( dev, ev, msec ) ! 472: dev_t dev; ! 473: int ev; ! 474: int msec; ! 475: { ! 476: if(minor(dev)==0 && istty[mmcurvirterm].t_open) ! 477: /* Route input from current */ ! 478: dev=makedev(2,mmcurvirterm); /* virtual terminal to console (TBF) */ ! 479: ! 480: /* ! 481: * Priority polls not supported. ! 482: */ ! 483: ev &= ~POLLPRI; ! 484: ! 485: /* ! 486: * Input poll failure. ! 487: */ ! 488: if ( (ev & POLLIN) && (istty[minor(dev)].t_iq.cq_cc == 0) ) { ! 489: ! 490: if ( msec != 0 ) ! 491: pollopen( &istty[minor(dev)].t_ipolls ); ! 492: ! 493: /* ! 494: * Second look AFTER enabling monitor, avoiding interrupt race. ! 495: */ ! 496: if ( istty[minor(dev)].t_iq.cq_cc == 0 ) ! 497: ev &= ~POLLIN; ! 498: } ! 499: ! 500: return ev; ! 501: } ! 502: ! 503: /* ! 504: * Receive interrupt. ! 505: */ ! 506: isrint() ! 507: { ! 508: register int c; ! 509: register int s; ! 510: register int r; ! 511: int savests; ! 512: int update_leds = 0; ! 513: ! 514: /* ! 515: * Schedule raw input handler if not already active. ! 516: */ ! 517: if ( isbusy == 0 ) { ! 518: if(istty[mmcurvirterm].t_open) /* only for opened term (TBF) */ ! 519: defer( isbatch, &istty[mmcurvirterm] ); ! 520: else /* use console */ ! 521: defer( isbatch, &istty[0] ); ! 522: isbusy = 1; ! 523: } ! 524: ! 525: /* ! 526: * Pull character from the data ! 527: * port. Pulse the KBFLAG in the control ! 528: * port to reset the data buffer. ! 529: */ ! 530: r = inb(KBDATA) & 0xFF; ! 531: c = inb(KBCTRL); ! 532: outb(KBCTRL, c|KBFLAG); ! 533: outb(KBCTRL, c); ! 534: #if KBDEBUG ! 535: printf("kbd: %d\n", r); /* print scan code/direction */ ! 536: #endif ! 537: if (ledcmd) { ! 538: /* ledcmd = 0; */ ! 539: if (r == KBACK) { /* output to status LEDS */ ! 540: ledcmd = 0; ! 541: c = scroll[mmcurvirterm] & 1; ! 542: if (shift & NMLS) ! 543: c |= 2; ! 544: if (shift & CPLS) ! 545: c |= 4; ! 546: outb(KBDATA, c); ! 547: return; ! 548: } ! 549: /*return;*/ ! 550: } ! 551: if (extended > 0) { /* if multi-character seq, */ ! 552: --extended; /* ... ignore this char */ ! 553: return; ! 554: } ! 555: if (r == EXTENDED1) { /* ignore extended sequences */ ! 556: extended = 5; ! 557: return; ! 558: } ! 559: if (r == 0xFF) { ! 560: return; /* Overrun */ ! 561: } ! 562: c = (r & KEYSC) - 1; ! 563: /* ! 564: * Check for reset. ! 565: */ ! 566: if ((r&KEYUP) == 0 && c == DELETE && (shift&(CTS|ALS)) == (CTS|ALS)) ! 567: boot(); ! 568: ! 569: /* ! 570: * Track "shift" keys. ! 571: */ ! 572: s = smaptab[c]; ! 573: if (s&SHFT) { ! 574: if (r&KEYUP) { /* "shift" released */ ! 575: if (c == RSHIFT) ! 576: shift &= ~SRS; ! 577: else if (c == lshift) ! 578: shift &= ~SLS; ! 579: else if (c == CTRL) ! 580: shift &= ~CTS; ! 581: else if (c == ALT) ! 582: shift &= ~ALS; ! 583: } else { /* "shift" pressed */ ! 584: if (c == lshift) ! 585: shift |= SLS; ! 586: else if (c == RSHIFT) ! 587: shift |= SRS; ! 588: else if (c == CTRL) ! 589: shift |= CTS; ! 590: else if (c == ALT) ! 591: shift |= ALS; ! 592: else if (c == CAPLOCK) { ! 593: shift ^= CPLS; /* toggle cap lock */ ! 594: kbCAPLCKhold[mmcurvirterm]=shift&CPLS; /* TBF */ ! 595: updleds(); ! 596: } else if (c == NUMLOCK) { ! 597: shift ^= NMLS; /* toggle num lock */ ! 598: kbNUMLCKhold[mmcurvirterm]=shift&NMLS; /* TBF */ ! 599: updleds(); ! 600: } ! 601: } ! 602: return; ! 603: } ! 604: ! 605: /* ! 606: * No other key up codes of interest. ! 607: */ ! 608: if (r&KEYUP) { ! 609: return; ! 610: } ! 611: ! 612: /* ! 613: * If CTRL-F? switch virtual terminals (TBF) ! 614: * ! 615: */ ! 616: ! 617: if(c>=58 && c-58<NVIRTERMS && shift&CTS && !(shift&(SRS|SLS|ALS))) ! 618: defer(kbchangeterm,(char *)(c-58+1)); ! 619: ! 620: /* ! 621: * If the tty is not open the character is ! 622: * just tossed away. XXXXXXXXXX ! 623: * routed to console if opened (TBF) ! 624: */ ! 625: ! 626: if (istty[mmcurvirterm].t_open == 0 && istty[0].t_open==0) { ! 627: return; ! 628: } ! 629: ! 630: /* ! 631: * Map character, based on the ! 632: * current state of the shift, control, ! 633: * meta and lock flags. ! 634: */ ! 635: if (shift & CTS) { ! 636: if (s == CTS) /* Map Ctrl (BS | NL) */ ! 637: c = (c == BACKSP) ? 0x7F : 0x0A; ! 638: else if (s==SS1 || s==LET) /* Normal Ctrl map */ ! 639: c = umaptab[c]&0x1F; /* Clear bits 5-6 */ ! 640: else { ! 641: return; /* Ignore this char */ ! 642: } ! 643: } else if (s &= shift) { ! 644: if (shift & SES) { /* if shift on */ ! 645: if (s & (CPLS|NMLS)) /* if caps/num lock */ ! 646: c = lmaptab[c]; /* use unshifted */ ! 647: else ! 648: c = umaptab[c]; /* use shifted */ ! 649: } else { /* if shift not on */ ! 650: if (s & (CPLS|NMLS)) /* if caps/num lock */ ! 651: c = umaptab[c]; /* use shifted */ ! 652: else ! 653: c = lmaptab[c]; /* use unshifted */ ! 654: } ! 655: } else ! 656: c = lmaptab[c]; /* use unshifted */ ! 657: ! 658: /* ! 659: * Act on character. ! 660: */ ! 661: if (c == XXX) { ! 662: return; /* char to ignore */ ! 663: } ! 664: ! 665: if (c != SPC) { /* not special char? */ ! 666: if (shift & ALS) /* ALT (meta bit)? */ ! 667: c |= 0x80; /* set meta */ ! 668: #if KBDEBUG ! 669: printf("%x %c ", c, c&0xff); ! 670: #endif ! 671: isin(c); /* send the char */ ! 672: } else { ! 673: update_leds += isspecial(r); /* special chars */ ! 674: } ! 675: if (update_leds) { ! 676: savests = sphi(); ! 677: outb(KBDATA, LEDCMD); ! 678: ledcmd = 1; ! 679: spl(savests); ! 680: } ! 681: } ! 682: ! 683: /* ! 684: * Handle special input sequences. ! 685: * The character passed is the key number. ! 686: * ! 687: * The keypad is translated by the following table, ! 688: * the first entry is the normal sequence, the second the shifted, ! 689: * and the third the alternate keypad sequence. ! 690: */ ! 691: static char *keypad[][3] = { ! 692: { "\33[H", "7", "\33?w" }, /* 71 */ ! 693: { "\33[A", "8", "\33?x" }, /* 72 */ ! 694: { "\33[V", "9", "\33?y" }, /* 73 */ ! 695: { "\33[D", "4", "\33?t" }, /* 75 */ ! 696: { "\0337", "5", "\33?u" }, /* 76 */ ! 697: { "\33[C", "6", "\33?v" }, /* 77 */ ! 698: { "\33[24H","1", "\33?q" }, /* 79 */ ! 699: { "\33[B", "2", "\33?r" }, /* 80 */ ! 700: { "\33[U", "3", "\33?s" }, /* 81 */ ! 701: { "\33[@", "0", "\33?p" }, /* 82 */ ! 702: { "\33[P", ".", "\33?n" } /* 83 */ ! 703: }; ! 704: ! 705: isspecial(c) ! 706: int c; ! 707: { ! 708: register char *cp; ! 709: register int s; ! 710: int update_leds = 0; ! 711: ! 712: cp = 0; ! 713: ! 714: switch (c) { ! 715: case 15: /* cursor back tab */ ! 716: cp = "\033[Z"; ! 717: break; ! 718: case 59: case 60: case 61: case 62: case 63: /* Function keys */ ! 719: case 64: case 65: case 66: case 67: case 68: ! 720: /* offset to function string */ ! 721: if(shift&CTS) ! 722: cp=""; /* disable CTRL-F? (TBF) */ ! 723: else ! 724: { ! 725: if ( shift & ALS ) ! 726: cp = isfval[c-49]; ! 727: else ! 728: cp = isfval[c-59]; ! 729: } ! 730: break; ! 731: ! 732: case 70: /* Scroll Lock -- stop/start output */ ! 733: { ! 734: static char cbuf[2]; ! 735: ! 736: cp = &cbuf[0]; /* working buffer */ ! 737: if (!(istty[mmcurvirterm].t_sgttyb.sg_flags&RAWIN)) { /* not if in RAW mode */ ! 738: ++update_leds; ! 739: if (istty[mmcurvirterm].t_flags & T_STOP) { /* output stopped? */ ! 740: cbuf[0] = istty[mmcurvirterm].t_tchars.t_startc; /* start it */ ! 741: scroll[mmcurvirterm] = 0; ! 742: } else { ! 743: cbuf[0] = istty[mmcurvirterm].t_tchars.t_stopc; /* stop output */ ! 744: scroll[mmcurvirterm] = 1; ! 745: } ! 746: } ! 747: break; ! 748: } ! 749: ! 750: case 79: /* 1/End */ ! 751: case 80: /* 2/DOWN */ ! 752: case 81: /* 3/PgDn */ ! 753: case 82: /* 0/Ins */ ! 754: case 83: /* ./Del */ ! 755: --c; /* adjust code */ ! 756: case 75: /* 4/LEFT */ ! 757: case 76: /* 5 */ ! 758: case 77: /* 6/RIGHT */ ! 759: --c; /* adjust code */ ! 760: case 71: /* 7/Home/Clear */ ! 761: case 72: /* 8/UP */ ! 762: case 73: /* 9/PgUp */ ! 763: s = 0; /* start off with normal keypad */ ! 764: if (shift&NMLS) /* num lock? */ ! 765: s = 1; /* set shift pad */ ! 766: if (shift&SES) /* shift? */ ! 767: s ^= 1; /* toggle shift pad */ ! 768: if (shift&AKPS) /* alternate pad? */ ! 769: s = 2; /* set alternate pad */ ! 770: cp = keypad[c-71][s]; /* get keypad value */ ! 771: break; ! 772: } ! 773: if (cp) /* send string */ ! 774: while ((*cp != 0) && (*cp != -1)) ! 775: isin( *cp++ & 0377 ); ! 776: return update_leds; ! 777: } ! 778: ! 779: /** ! 780: * ! 781: * void ! 782: * ismmfunc( c,VTN ) -- process keyboard related output escape sequences ! 783: * char c; ! 784: * unsigned VTN; -- virterm # 0=console, 1-NVIRTERMS=virterm ! 785: */ ! 786: void ! 787: ismmfunc(c,VTN) ! 788: register int c; ! 789: unsigned VTN; ! 790: { ! 791: switch (c) { ! 792: case 't': /* Enter numlock */ ! 793: kbNUMLCKhold[VTN]=NMLS; ! 794: if(VTN==mmcurvirterm) ! 795: shift |= NMLS; ! 796: updleds(); /* update LED status */ ! 797: break; ! 798: case 'u': /* Leave numlock */ ! 799: kbNUMLCKhold[VTN]=0; ! 800: if(VTN==mmcurvirterm) ! 801: shift &= ~NMLS; ! 802: updleds(); /* update LED status */ ! 803: break; ! 804: case '=': /* Enter alternate keypad */ ! 805: kbAKPShold[VTN]=AKPS; ! 806: if(VTN==mmcurvirterm) ! 807: shift |= AKPS; ! 808: break; ! 809: case '>': /* Exit alternate keypad */ ! 810: kbAKPShold[VTN]=0; ! 811: if(VTN==mmcurvirterm) ! 812: shift &= ~AKPS; ! 813: break; ! 814: case 'c': /* Reset terminal */ ! 815: islock[VTN] = 0; ! 816: kbAKPShold[VTN]=0; ! 817: kbNUMLCKhold[VTN]=0; ! 818: kbCAPLCKhold[VTN]=0; ! 819: scroll[VTN]=0; ! 820: if(VTN==mmcurvirterm) ! 821: shift = 0; ! 822: if(istty[VTN].t_flags & T_STOP) /* output stopped? */ ! 823: ttin(&istty[VTN], /* re-start output */ ! 824: istty[VTN].t_tchars.t_startc); ! 825: initkeys(); ! 826: updleds(); /* update LED status */ ! 827: break; ! 828: } ! 829: } ! 830: ! 831: /** ! 832: * ! 833: * void ! 834: * isin( c ) -- append character to raw input silo ! 835: * char c; ! 836: */ ! 837: static ! 838: isin( c ) ! 839: register int c; ! 840: { ! 841: int cache_it = 1; ! 842: register TTY * tp = istty + mmcurvirterm; ! 843: register silo_t *in_s = in_silo + mmcurvirterm; ! 844: ! 845: if(!tp->t_open) ! 846: tp = istty; ! 847: ! 848: /* ! 849: * If using software incoming flow control, process and ! 850: * discard t_stopc and t_startc. ! 851: */ ! 852: if (!ISRIN) { ! 853: if (ISSTOP) { ! 854: if ((tp->t_flags&T_STOP) == 0) ! 855: tp->t_flags |= T_STOP; ! 856: cache_it = 0; ! 857: } ! 858: if (ISSTART) { ! 859: tp->t_flags &= ~T_STOP; ! 860: ttstart(tp); ! 861: cache_it = 0; ! 862: } ! 863: } ! 864: /* ! 865: * Cache received character. ! 866: */ ! 867: if (cache_it) { ! 868: #if KBDEBUG ! 869: printf("put %c ix=%d ox=%d\n", c,in_s->si_ix,in_s->si_ox); ! 870: #endif ! 871: in_s->si_buf[ in_s->si_ix ] = c; ! 872: ! 873: if ( ++(in_s->si_ix) >= sizeof(in_s->si_buf) ) ! 874: in_s->si_ix = 0; ! 875: } ! 876: } ! 877: ! 878: /** ! 879: * ! 880: * void ! 881: * isbatch() -- raw input conversion routine ! 882: * ! 883: * Action: Enable the video display. ! 884: * Canonize the raw input silo. ! 885: * ! 886: * Notes: isbatch() was scheduled as a deferred process by isrint(). ! 887: */ ! 888: static void ! 889: isbatch( tp ) ! 890: register TTY * tp; ! 891: { ! 892: register int c; ! 893: register silo_t *in_s = in_silo + mmcurvirterm; ! 894: static int lastc; ! 895: ! 896: /* ! 897: * Ensure video display is enabled. ! 898: */ ! 899: mm_von(); ! 900: ! 901: isbusy = 0; ! 902: ! 903: /* ! 904: * Process all cached characters. ! 905: */ ! 906: while ( in_s->si_ix != in_s->si_ox ) { ! 907: ! 908: /* ! 909: * Get next cached char. ! 910: */ ! 911: c = in_s->si_buf[ in_s->si_ox ]; ! 912: ! 913: if ( in_s->si_ox >= sizeof(in_s->si_buf) - 1 ) ! 914: in_s->si_ox = 0; ! 915: else ! 916: in_s->si_ox++; ! 917: ! 918: #if KBDEBUG ! 919: printf("get %c ix=%d ox=%d\n", c,in_s->si_ix,in_s->si_ox); ! 920: #endif ! 921: if ( (islock[mmcurvirterm] == 0) || ISINTR || ISQUIT ) { ! 922: ttin( tp, c ); ! 923: } ! 924: ! 925: else if ( (c == 'b') && (lastc == '\033') ) { ! 926: islock[mmcurvirterm] = 0; ! 927: ttin( tp, lastc ); ! 928: ttin( tp, c ); ! 929: } ! 930: ! 931: else if ( (c == 'c') && (lastc == '\033') ) { ! 932: ttin( tp, lastc ); ! 933: ttin( tp, c ); ! 934: } ! 935: ! 936: else ! 937: putchar('\007'); ! 938: ! 939: lastc = c; ! 940: } ! 941: } ! 942: ! 943: /* ! 944: * update the keyboard status LEDS ! 945: */ ! 946: updleds() ! 947: { ! 948: int s; ! 949: ! 950: s = sphi(); ! 951: outb(KBDATA, LEDCMD); ! 952: ledcmd = 1; ! 953: spl(s); ! 954: } ! 955: ! 956: /* ! 957: * unlock the scroll in case an interrupt character is received ! 958: */ ! 959: kbunscroll() ! 960: { ! 961: scroll[mmcurvirterm] = 0; ! 962: updleds(); ! 963: } ! 964: ! 965: /* ! 966: * Change terminals (TBF) ! 967: * scheduled as a deferred process by isrint ! 968: */ ! 969: kbchangeterm(termno) ! 970: char *termno; ! 971: { ! 972: unsigned intrstate=sphi(); /* Disable interrupts */ ! 973: ! 974: mmchangeterm((unsigned int)termno); ! 975: ! 976: if(kbAKPShold[mmcurvirterm]) /* set alternate keypad */ ! 977: shift|=AKPS; ! 978: else ! 979: shift&=~AKPS; ! 980: ! 981: if(kbCAPLCKhold[mmcurvirterm]) /* set capslock */ ! 982: shift|=CPLS; ! 983: else ! 984: shift&=~CPLS; ! 985: ! 986: if(kbNUMLCKhold[mmcurvirterm]) /* set numlock */ ! 987: shift|=NMLS; ! 988: else ! 989: shift&=~NMLS; ! 990: ! 991: updleds(); ! 992: spl(intrstate); /* Restore interrupts */ ! 993: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.