|
|
1.1 ! root 1: /* ! 2: * User configurable AT keyboard/display driver. ! 3: * AT COHERENT ! 4: */ ! 5: #include <sys/coherent.h> ! 6: #include <sys/i8086.h> ! 7: #include <sys/con.h> ! 8: #include <errno.h> ! 9: #include <sys/stat.h> ! 10: #include <sys/tty.h> ! 11: #include <sys/uproc.h> ! 12: #include <signal.h> ! 13: #include <sys/seg.h> ! 14: #include <sys/sched.h> ! 15: #include <sys/kb.h> ! 16: ! 17: #define ISMAJ 2 /* Keyboard major device */ ! 18: #define ISVEC 1 /* Keyboard interrupt vector */ ! 19: ! 20: #if DEBUG ! 21: #define KBDEBUG(x) printf(x) /* debugging output */ ! 22: #define KBDEBUG2(x,y) printf(x,y) /* debugging output */ ! 23: #define KBDEBUG3(x,y,z) printf(x,y,z) /* debugging output */ ! 24: #else ! 25: #define KBDEBUG(x) /* no output */ ! 26: #define KBDEBUG2(x,y) /* no output */ ! 27: #define KBDEBUG3(x,y,z) /* no output */ ! 28: #endif ! 29: ! 30: /* ! 31: * values for kbstate ! 32: */ ! 33: #define KB_IDLE 0 /* nothing going on right now */ ! 34: #define KB_SINGLE 1 /* sent a single byte cmd to the kbd */ ! 35: #define KB_DOUBLE_1 2 /* sent 1st byte of 2-byte cmd to kbd */ ! 36: #define KB_DOUBLE_2 3 /* sent 2nd byte of 2-byte cmd to kbd */ ! 37: ! 38: /* ! 39: * patchable params for non-standard keyboards ! 40: */ ! 41: int KBDATA = 0x60; /* Keyboard data */ ! 42: int KBCTRL = 0x61; /* Keyboard control */ ! 43: int KBSTS_CMD = 0x64; /* Keyboard status/command */ ! 44: int KBFLAG = 0x80; /* Keyboard reset flag */ ! 45: int KBBOOT = 1; /* 0: disallow reboot from keyboard */ ! 46: int KBTIMEOUT = 10000; /* shouldn't need this much */ ! 47: int KBCMDBYTE = 0x05; /* no translation */ ! 48: ! 49: /* ! 50: * KBSTATUS bits ! 51: */ ! 52: #define STS_OBUF_FULL 0x01 /* kbd output buffer full */ ! 53: #define STS_IBUF_FULL 0x02 /* kbd input buffer full */ ! 54: #define STS_SYSTEM 0x04 ! 55: #define STS_CMD_DATA 0x08 /* 1: command or status */ ! 56: #define STS_INHIBIT 0x10 /* 0: keyboard inhibited */ ! 57: #define STS_AUX_OBUF_FULL 0x20 ! 58: #define STS_TIMEOUT 0x40 /* general timeout */ ! 59: #define STS_PAR_ERR 0x80 /* parity error */ ! 60: ! 61: /* ! 62: * The following are magic commands which read from or write to the ! 63: * controller command byte. These get output to the KBSTS_CMD port. ! 64: */ ! 65: #define C_READ_CMD 0x20 /* read controller command byte */ ! 66: #define C_WRITE_CMD 0x60 /* write controller command byte */ ! 67: #define C_TRANSLATE 0x40 /* translate enable bit in cmd byte */ ! 68: ! 69: /* ! 70: * Globals ! 71: * The keyboard mapping table is too large to fit into kernel data space, ! 72: * so we need to allocate a segment to it. ! 73: * The function keys tend to be small and tend to change substantially ! 74: * more often than the mapping table, so we keep them in the kernel data space. ! 75: */ ! 76: static unsigned shift; /* state of all shift/lock keys */ ! 77: static SEG *kbsegp; /* keyboard table segment */ ! 78: static unsigned char **funkeyp = 0; /* ptr to array of func. keys ptrs */ ! 79: static FNKEY *fnkeys = 0; /* pointer to structure of values */ ! 80: static unsigned fklength; /* length of k_fnval field in fnkeys */ ! 81: static unsigned prev_cmd; /* previous command sent to KBD */ ! 82: static unsigned cmd2; /* 2nd byte of command to KBD */ ! 83: static unsigned sh_index; /* shift/lock state index */ ! 84: ! 85: /* ! 86: * State variables. ! 87: */ ! 88: int islock; /* Keyboard locked flag */ ! 89: int isbusy; /* Raw input conversion busy */ ! 90: static char table_loaded; /* true == keyboard table resident */ ! 91: static char fk_loaded; /* true == function keys resident */ ! 92: static int kbstate = KB_IDLE; /* current keyboard state */ ! 93: ! 94: /* ! 95: * Functions. ! 96: */ ! 97: int isrint(); ! 98: int istime(); ! 99: void isbatch(); ! 100: int mmstart(); ! 101: int isopen(); ! 102: int isclose(); ! 103: int isread(); ! 104: int mmwrite(); ! 105: int isioctl(); ! 106: void mmwatch(); ! 107: int isload(); ! 108: int isuload(); ! 109: int ispoll(); ! 110: int nulldev(); ! 111: int nonedev(); ! 112: int updleds(); ! 113: ! 114: /* ! 115: * Configuration table. ! 116: */ ! 117: CON iscon ={ ! 118: DFCHR|DFPOL, /* Flags */ ! 119: ISMAJ, /* Major index */ ! 120: isopen, /* Open */ ! 121: isclose, /* Close */ ! 122: nulldev, /* Block */ ! 123: isread, /* Read */ ! 124: mmwrite, /* Write */ ! 125: isioctl, /* Ioctl */ ! 126: nulldev, /* Powerfail */ ! 127: mmwatch, /* Timeout */ ! 128: isload, /* Load */ ! 129: isuload, /* Unload */ ! 130: ispoll /* Poll */ ! 131: }; ! 132: ! 133: /* ! 134: * Terminal structure. ! 135: */ ! 136: TTY istty = { ! 137: {0}, {0}, 0, mmstart, NULL, 0, 0 ! 138: }; ! 139: ! 140: /* ! 141: * Load entry point. ! 142: */ ! 143: isload() ! 144: { ! 145: kbstate = KB_IDLE; ! 146: table_loaded = 0; /* no keyboard table yet */ ! 147: fk_loaded = 0; /* no Fn keys yet */ ! 148: ! 149: /* ! 150: * Enable mmwatch() invocation every second. ! 151: */ ! 152: drvl[ISMAJ].d_time = 1; ! 153: ! 154: /* ! 155: * Seize keyboard interrupt. ! 156: */ ! 157: setivec(ISVEC, isrint); ! 158: ! 159: /* ! 160: * Initiailize video display. ! 161: */ ! 162: mmstart( &istty ); ! 163: ! 164: /* ! 165: * Allocate a segment to store the in-core keyboard table. ! 166: * This would be a lot more convenient in kernel data space, ! 167: * but small model COHERENT doesn't have that luxury. ! 168: */ ! 169: kbsegp = salloc((fsize_t)MAX_TABLE_SIZE, SFSYST|SFNSWP|SFHIGH); ! 170: if (kbsegp == (SEG *)0) ! 171: printf("kb: unable to allocate keyboard table segment\n"); ! 172: fklength = 0; ! 173: KBDEBUG("Exiting kbload()\n"); ! 174: } ! 175: ! 176: /* ! 177: * Unload entry point. ! 178: */ ! 179: isuload() ! 180: { ! 181: if (kbstate != KB_IDLE) ! 182: printf("kb: keyboard busy during unload\n"); ! 183: clrivec(ISVEC); ! 184: if (kbsegp != (SEG *)0) { ! 185: table_loaded = 0; ! 186: sfree(kbsegp); ! 187: } ! 188: } ! 189: ! 190: /* ! 191: * Open routine. ! 192: */ ! 193: isopen(dev) ! 194: dev_t dev; ! 195: { ! 196: register int s; ! 197: ! 198: KBDEBUG(" kbopen()"); ! 199: if (minor(dev) != 0) { ! 200: u.u_error = ENXIO; ! 201: return; ! 202: } ! 203: if ((istty.t_flags&T_EXCL) != 0 && !super()) { ! 204: u.u_error = ENODEV; ! 205: return; ! 206: } ! 207: ttsetgrp(&istty, dev); ! 208: ! 209: s = sphi(); ! 210: if (istty.t_open++ == 0) { ! 211: istty.t_flags = T_CARR; /* indicate "carrier" */ ! 212: ttopen(&istty); ! 213: } ! 214: spl(s); ! 215: #if 0 ! 216: updleds(); /* update keyboard status LEDS */ ! 217: #endif ! 218: } ! 219: ! 220: /* ! 221: * Close a tty. ! 222: */ ! 223: isclose(dev) ! 224: { ! 225: register int s; ! 226: ! 227: s = sphi(); ! 228: if (--istty.t_open == 0) { ! 229: ttclose(&istty); ! 230: } ! 231: spl(s); ! 232: } ! 233: ! 234: /* ! 235: * Read routine. ! 236: */ ! 237: isread(dev, iop) ! 238: dev_t dev; ! 239: IO *iop; ! 240: { ! 241: ttread(&istty, iop, 0); ! 242: if (istty.t_oq.cq_cc) ! 243: mmtime(&istty); ! 244: } ! 245: ! 246: /* ! 247: * Ioctl routine. ! 248: * nb: archaic TIOCSHIFT and TIOCCSHIFT no longer needed/supported. ! 249: */ ! 250: isioctl(dev, com, vec) ! 251: dev_t dev; ! 252: struct sgttyb *vec; ! 253: { ! 254: register int s; ! 255: ! 256: switch (com) { ! 257: case TIOCSETF: ! 258: case TIOCGETF: ! 259: isfunction(com, (char *)vec); ! 260: break; ! 261: case TIOCSETKBT: ! 262: issettable(vec); ! 263: break; ! 264: case TIOCGETKBT: ! 265: isgettable(vec); ! 266: break; ! 267: default: /* pass to TTY driver */ ! 268: s = sphi(); ! 269: ttioctl(&istty, com, vec); ! 270: spl(s); ! 271: break; ! 272: } ! 273: } ! 274: ! 275: /* ! 276: * Set the in-core keyboard mapping table. ! 277: * The table is sorted by scan code prior to calling ioctl(). ! 278: * All unused table entries (holes in the scan code map) have ! 279: * a zero for the k_key field. ! 280: * This makes key lookup at interrupt time fast by using the scan code ! 281: * as an index into the table. ! 282: */ ! 283: issettable(vec) ! 284: char *vec; ! 285: { ! 286: register unsigned i; ! 287: register int s; ! 288: int timeout; ! 289: register faddr_t faddr; /* address of keyboard table */ ! 290: static KBTBL this_key; /* current key from kbd table */ ! 291: unsigned int cmd_byte; ! 292: ! 293: KBDEBUG(" TIOCSETKBT"); ! 294: kb_cmd2(K_SCANCODE_CMD, 3); /* select set 3 */ ! 295: kb_cmd(K_ALL_TMB_CMD); /* default: TMB for all keys */ ! 296: faddr = kbsegp->s_faddr; ! 297: for (i = 0; i < MAX_KEYS; ++i) { ! 298: ukcopy(vec, &this_key, sizeof(this_key)); ! 299: kfcopy(&this_key, faddr, sizeof(this_key)); ! 300: faddr += sizeof(this_key); ! 301: vec += sizeof(this_key); ! 302: if (this_key.k_key != i && this_key.k_key != 0) { ! 303: printf("kb: incorrect or unsorted table entry %d\n", i); ! 304: u.u_error = EBADFMT; ! 305: return; ! 306: } ! 307: if (this_key.k_key != i) ! 308: continue; /* no key */ ! 309: switch (this_key.k_flags&TMODE) { ! 310: case T: /* typematic */ ! 311: kb_cmd2(K_KEY_T_CMD, i); ! 312: break; ! 313: case M: /* make only */ ! 314: kb_cmd2(K_KEY_M_CMD, i); ! 315: break; ! 316: case MB: /* make/break */ ! 317: kb_cmd2(K_KEY_MB_CMD, i); ! 318: break; ! 319: case TMB: /* typematic make/break */ ! 320: break; /* this is the default */ ! 321: default: ! 322: printf("kb: bad key mode\n"); ! 323: } ! 324: } ! 325: updleds(); ! 326: kb_cmd2(K_SCANCODE_CMD, 3); /* select set 3 */ ! 327: kb_cmd(K_ENABLE_CMD); /* start scanning */ ! 328: /* ! 329: * The following code disables translation from the on-board ! 330: * keyboard/aux controller. Without disabling translation, the ! 331: * received scan codes still look like code set 1 codes even ! 332: * though we put the keyboard controller in scan code set 3. ! 333: * Yes, this is progress.... ! 334: */ ! 335: #if 0 ! 336: while (inb(KBSTS_CMD) & STS_IBUF_FULL) ! 337: ; ! 338: outb(KBSTS_CMD, C_READ_CMD); /* read controller cmd byte */ ! 339: while (!(inb(KBSTS_CMD) & STS_OBUF_FULL)) ! 340: ; ! 341: cmd_byte = inb(KBDATA); ! 342: KBDEBUG2(" cmd_byte=%x", cmd_byte); ! 343: #endif ! 344: timeout = KBTIMEOUT; ! 345: s = sphi(); ! 346: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0) ! 347: ; ! 348: outb(KBSTS_CMD, C_WRITE_CMD); /* write controller cmd byte */ ! 349: for (timeout = 50; --timeout > 0; ) ! 350: ; ! 351: timeout = KBTIMEOUT; ! 352: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0) ! 353: ; ! 354: outb(KBDATA, KBCMDBYTE); /* turn off translation */ ! 355: timeout = KBTIMEOUT; ! 356: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0) ! 357: ; ! 358: spl(s); ! 359: #if DEBUG ! 360: kb_cmd2(K_SCANCODE_CMD, 0); /* query s.c. mode */ ! 361: #endif ! 362: ++table_loaded; ! 363: } ! 364: ! 365: /* ! 366: * Get the in-core keyboard mapping table and pass it to the user. ! 367: */ ! 368: isgettable(vec) ! 369: char *vec; ! 370: { ! 371: register unsigned i; ! 372: register faddr_t faddr; /* address of keyboard table */ ! 373: static KBTBL this_key; /* current key from kbd table */ ! 374: ! 375: KBDEBUG(" TIOCGETKBT"); ! 376: faddr = kbsegp->s_faddr; ! 377: for (i = 0; i < MAX_KEYS; ++i) { ! 378: fkcopy( faddr, &this_key, sizeof(this_key)); ! 379: kucopy( &this_key, vec, sizeof(this_key)); ! 380: faddr += sizeof(this_key); ! 381: vec += sizeof(this_key); ! 382: } ! 383: } ! 384: ! 385: /* ! 386: * Set and receive the function keys. ! 387: */ ! 388: isfunction(c, v) ! 389: int c; ! 390: FNKEY *v; ! 391: { ! 392: register unsigned char *cp; ! 393: register unsigned i; ! 394: unsigned char numkeys = 0; ! 395: ! 396: if (c == TIOCGETF) { ! 397: KBDEBUG(" TIOCGETF"); ! 398: if (!fk_loaded) ! 399: u.u_error = EINVAL; ! 400: else ! 401: kucopy(fnkeys, v, fklength); /* copy ours to user */ ! 402: } else { /* TIOCSETF */ ! 403: /* ! 404: * If we had a previous function key arena, free it up. ! 405: * Since we don't know how large the function key arena will ! 406: * be, we must size it in the user data space prior to ! 407: * (re)kalloc()'ing it. This is ugly, but a helluva lot better ! 408: * than the old driver which used a hard coded limit of 150! ! 409: */ ! 410: KBDEBUG(" TIOCSETF"); ! 411: fk_loaded = 0; ! 412: if (fnkeys != (FNKEY *)0) ! 413: kfree(fnkeys); /* free old arena */ ! 414: if (funkeyp != NULL) ! 415: kfree(funkeyp); /* free old ptr array */ ! 416: ukcopy(&v->k_nfkeys, &numkeys, sizeof(numkeys)); ! 417: fklength = sizeof(FNKEY); ! 418: cp = v->k_fnval; ! 419: for (i = 0; i < numkeys; i++) { ! 420: do { ! 421: ++fklength; ! 422: } while (getubd(cp++) != DELIM); ! 423: } ! 424: fnkeys = (FNKEY *)kalloc(fklength); ! 425: funkeyp = (unsigned char **)kalloc(numkeys * sizeof(char *)); ! 426: if (fnkeys == (FNKEY *)0 || funkeyp == NULL) { ! 427: if (fnkeys != (FNKEY *)0) { ! 428: kfree(fnkeys); ! 429: fnkeys = 0; ! 430: } ! 431: if (funkeyp != NULL) { ! 432: kfree(funkeyp); ! 433: funkeyp = 0; ! 434: } ! 435: u.u_error = ENOMEM; ! 436: return; ! 437: } ! 438: cp = fnkeys->k_fnval; /* point to Fn ... */ ! 439: v = v->k_fnval; /* ... key arena */ ! 440: for (i = 0; i < numkeys; i++) { ! 441: funkeyp[i] = cp; /* save pointer */ ! 442: while ((*cp++ = getubd(v++)) != DELIM) /* copy key */ ! 443: ; ! 444: } ! 445: fnkeys->k_nfkeys = numkeys; ! 446: fk_loaded = 1; ! 447: } ! 448: } ! 449: ! 450: ! 451: /* ! 452: * Poll routine. ! 453: */ ! 454: ispoll( dev, ev, msec ) ! 455: dev_t dev; ! 456: int ev; ! 457: int msec; ! 458: { ! 459: /* ! 460: * Priority polls not supported. ! 461: */ ! 462: ev &= ~POLLPRI; ! 463: ! 464: /* ! 465: * Input poll failure. ! 466: */ ! 467: if ( (ev & POLLIN) && (istty.t_iq.cq_cc == 0) ) { ! 468: if ( msec != 0 ) ! 469: pollopen( &istty.t_ipolls ); ! 470: /* ! 471: * Second look AFTER enabling monitor, avoiding interrupt race. ! 472: */ ! 473: if ( istty.t_iq.cq_cc == 0 ) ! 474: ev &= ~POLLIN; ! 475: } ! 476: return ev; ! 477: } ! 478: ! 479: /* ! 480: * Receive interrupt. ! 481: */ ! 482: isrint() ! 483: { ! 484: register unsigned c; ! 485: register unsigned r; ! 486: static char keyup; ! 487: ! 488: /* ! 489: * Schedule raw input handler if not already active. ! 490: */ ! 491: if ( !isbusy ) { ! 492: defer( isbatch, &istty ); ! 493: isbusy = 1; ! 494: } ! 495: ! 496: /* ! 497: * Pull character from the data ! 498: * port. Pulse the KBFLAG in the control ! 499: * port to reset the data buffer. ! 500: */ ! 501: r = inb(KBDATA) & 0xFF; ! 502: c = inb(KBCTRL); ! 503: outb(KBCTRL, c|KBFLAG); ! 504: outb(KBCTRL, c); ! 505: ! 506: /* ! 507: * check returned value from keyboard to see if it's a command ! 508: * or status back to us. If not, it we assume that it's a key code. ! 509: */ ! 510: KBDEBUG2(" intr(%x)", r); ! 511: switch (r) { ! 512: case K_BREAK: ! 513: keyup = 1; /* key going up */ ! 514: break; ! 515: case K_ECHO_R: ! 516: case K_BAT_OK: ! 517: break; /* very nice, but ignored */ ! 518: case K_BAT_BAD: ! 519: printf("kb: keyboard BAT failed\n"); ! 520: break; ! 521: case K_RESEND: ! 522: KBDEBUG("\nkb: request to resend command\n"); ! 523: outb(KBDATA, prev_cmd); ! 524: break; ! 525: case K_OVERRUN_23: ! 526: printf("kb: keyboard buffer overrun\n"); ! 527: break; ! 528: case K_ACK: ! 529: /* ! 530: * we received an ACKnowledgement from the keyboard. ! 531: * advance the state machine and continue. ! 532: */ ! 533: KBDEBUG(" ACK"); ! 534: switch (kbstate) { ! 535: case KB_IDLE: /* shouldn't happen */ ! 536: printf("kb: ACK while keyboard idle\n"); ! 537: break; ! 538: case KB_SINGLE: /* done with 1-byte command */ ! 539: case KB_DOUBLE_2: /* done w/ 2nd of 2-byte cmd */ ! 540: kbstate = KB_IDLE; ! 541: wakeup(&kbstate); ! 542: break; ! 543: case KB_DOUBLE_1: ! 544: kbstate = KB_DOUBLE_2; ! 545: outb(KBDATA, cmd2); ! 546: break; ! 547: default: ! 548: printf("kb: bad kbstate %d\n", kbstate); ! 549: break; ! 550: } ! 551: break; ! 552: default: ! 553: process_key(r, keyup); ! 554: keyup = 0; ! 555: } ! 556: } ! 557: ! 558: /* ! 559: * Process a key given its scan code and direction. ! 560: * ! 561: * In this table driven version of the keyboard driver, we trade off the ! 562: * code complexity associated with all the black magic that used to be ! 563: * performed on a per-key basis with the increased memory requirements ! 564: * associated with the table driven approach. ! 565: */ ! 566: process_key( key, up) ! 567: unsigned key; ! 568: int up; ! 569: { ! 570: register unsigned char *cp; ! 571: KBTBL key_vals; /* table values for this key */ ! 572: unsigned val; ! 573: unsigned char flags; ! 574: ! 575: KBDEBUG3(" proc(%x %s)", key, (up ? "up" : "down")); ! 576: if (!table_loaded) ! 577: return; /* throw away key */ ! 578: fkcopy( kbsegp->s_faddr + (key * sizeof(KBTBL)), ! 579: &key_vals, sizeof(key_vals)); ! 580: if (key_vals.k_key != key) /* empty entry */ ! 581: return; ! 582: flags = key_vals.k_flags; ! 583: ! 584: if (flags & S) { /* some shift/lock key ? */ ! 585: switch (key_vals.k_val[BASE]) { ! 586: case caps: ! 587: case num: ! 588: if (!up) { ! 589: shift ^= (1 << key_vals.k_val[BASE]); ! 590: updleds2(); ! 591: } ! 592: break; ! 593: case scroll: ! 594: if (!up) { ! 595: shift ^= (1 << key_vals.k_val[BASE]); ! 596: updleds2(); ! 597: if (!(istty.t_sgttyb.sg_flags&RAWIN)) { ! 598: if (istty.t_flags & T_STOP) { ! 599: isin(istty.t_tchars.t_startc); ! 600: } else { ! 601: isin(istty.t_tchars.t_stopc); ! 602: } ! 603: } ! 604: } ! 605: break; ! 606: default: ! 607: if (up) ! 608: shift &= ~(1 << key_vals.k_val[BASE]); ! 609: else ! 610: shift |= (1 << key_vals.k_val[BASE]); ! 611: break; ! 612: } ! 613: /* ! 614: * Calculate the shift index based upon the state of ! 615: * the shift and lock keys. ! 616: */ ! 617: sh_index = BASE; /* default condition */ ! 618: if (shift & (1 << altgr)) ! 619: sh_index = ALT_GR; ! 620: else { ! 621: if (shift & ((1 << lalt)|(1 << ralt))) ! 622: sh_index |= ALT; ! 623: if (shift & ((1 << lctrl)|(1 << rctrl))) ! 624: sh_index |= CTRL; ! 625: if (shift & ((1 << lshift)|(1 << rshift))) ! 626: sh_index |= SHIFT; ! 627: } ! 628: return; ! 629: } /* if (flags & S) */ ! 630: ! 631: /* ! 632: * If the tty is not open or the key has no value in the current ! 633: * shift state, the key is just tossed away. ! 634: */ ! 635: if (up || !istty.t_open || key_vals.k_val[sh_index] == none) ! 636: return; ! 637: if (((flags & C) && (shift & (1 << caps))) ! 638: || ((flags & N) && (shift & (1 << num)))) ! 639: val = key_vals.k_val[sh_index^SHIFT]; ! 640: else ! 641: val = key_vals.k_val[sh_index]; ! 642: ! 643: /* ! 644: * Check for function key or special key implemented as ! 645: * a function key (reboot == f0, tab and back-tab, etc). ! 646: */ ! 647: if (flags & F) { ! 648: if (val == 0 && !up && KBBOOT) ! 649: boot(); ! 650: if (!fk_loaded || val >= fnkeys->k_nfkeys) ! 651: return; ! 652: if ((cp = funkeyp[val]) == NULL) /* has a value? */ ! 653: return; ! 654: while (*cp != DELIM) ! 655: isin(*cp++); /* queue up Fn key value */ ! 656: return; ! 657: } ! 658: ! 659: /* ! 660: * Normal key processing. ! 661: */ ! 662: isin(val); /* send the char */ ! 663: return; ! 664: } ! 665: ! 666: /** ! 667: * ! 668: * void ! 669: * ismmfunc( c ) -- process keyboard related output escape sequences ! 670: * char c; ! 671: */ ! 672: void ! 673: ismmfunc(c) ! 674: register int c; ! 675: { ! 676: switch (c) { ! 677: case 't': /* Enter numlock */ ! 678: shift |= (1 << num); ! 679: updleds(); /* update LED status */ ! 680: break; ! 681: case 'u': /* Leave numlock */ ! 682: shift &= ~(1 << num); ! 683: updleds(); /* update LED status */ ! 684: break; ! 685: case '=': /* Enter alternate keypad -- ignored */ ! 686: case '>': /* Exit alternate keypad -- ignored */ ! 687: break; ! 688: case 'c': /* Reset terminal */ ! 689: islock = 0; ! 690: break; ! 691: } ! 692: } ! 693: ! 694: /** ! 695: * ! 696: * void ! 697: * isin( c ) -- append character to raw input silo ! 698: * char c; ! 699: */ ! 700: static ! 701: isin( c ) ! 702: register int c; ! 703: { ! 704: /* ! 705: * Cache received character. ! 706: */ ! 707: istty.t_rawin.si_buf[ istty.t_rawin.si_ix ] = c; ! 708: ! 709: if ( ++istty.t_rawin.si_ix >= sizeof(istty.t_rawin.si_buf) ) ! 710: istty.t_rawin.si_ix = 0; ! 711: } ! 712: ! 713: /** ! 714: * ! 715: * void ! 716: * isbatch() -- raw input conversion routine ! 717: * ! 718: * Action: Enable the video display. ! 719: * Canonize the raw input silo. ! 720: * ! 721: * Notes: isbatch() was scheduled as a deferred process by isrint(). ! 722: */ ! 723: static void ! 724: isbatch( tp ) ! 725: register TTY * tp; ! 726: { ! 727: register int c; ! 728: static int lastc; ! 729: ! 730: /* ! 731: * Ensure video display is enabled. ! 732: */ ! 733: mm_von(); ! 734: isbusy = 0; ! 735: ! 736: /* ! 737: * Process all cached characters. ! 738: */ ! 739: while ( tp->t_rawin.si_ix != tp->t_rawin.si_ox ) { ! 740: /* ! 741: * Get next cached char. ! 742: */ ! 743: c = tp->t_rawin.si_buf[ tp->t_rawin.si_ox ]; ! 744: ! 745: if ( tp->t_rawin.si_ox >= sizeof(tp->t_rawin.si_buf) - 1 ) ! 746: tp->t_rawin.si_ox = 0; ! 747: else ! 748: tp->t_rawin.si_ox++; ! 749: ! 750: if ( (islock == 0) || ISINTR || ISQUIT ) { ! 751: ttin( tp, c ); ! 752: } else if ( (c == 'b') && (lastc == '\033') ) { ! 753: islock = 0; ! 754: ttin( tp, lastc ); ! 755: ttin( tp, c ); ! 756: } else if ( (c == 'c') && (lastc == '\033') ) { ! 757: ttin( tp, lastc ); ! 758: ttin( tp, c ); ! 759: } else ! 760: putchar('\007'); ! 761: lastc = c; ! 762: } ! 763: } ! 764: ! 765: /* ! 766: * update the keyboard status LEDS. ! 767: * we chose the shift/lock key positions so this would be easy. ! 768: * this flavor of routine is called while processing a system call on ! 769: * behalf of the user. ! 770: */ ! 771: updleds() ! 772: { ! 773: kb_cmd2(K_LED_CMD, (shift >> 1) & 0x7); ! 774: } ! 775: ! 776: /* ! 777: * same as above, but callable from interrupt routines and other places ! 778: * which cannot sleep() waiting for the state machine to go idle. ! 779: */ ! 780: updleds2() ! 781: { ! 782: register timeout; ! 783: register int s; ! 784: ! 785: timeout = KBTIMEOUT; ! 786: s = sphi(); ! 787: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL)) ! 788: ; ! 789: kbstate = KB_DOUBLE_1; ! 790: cmd2 = (shift >> 1) & 0x7; ! 791: prev_cmd = K_LED_CMD; ! 792: outb(KBDATA, K_LED_CMD); ! 793: spl(s); ! 794: } ! 795: ! 796: /* ! 797: * unlock the scroll in case an interrupt character is received ! 798: */ ! 799: kbunscroll() ! 800: { ! 801: shift &= ~(1 << scroll); ! 802: updleds(); ! 803: } ! 804: ! 805: /* ! 806: * ship a single byte command to the keyboard ! 807: */ ! 808: kb_cmd(cmd) ! 809: unsigned cmd; ! 810: { ! 811: register int timeout; ! 812: register int s; ! 813: ! 814: s = sphi(); ! 815: KBDEBUG2(" kb_cmd(%x)", cmd); ! 816: while (kbstate != KB_IDLE) ! 817: sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN); ! 818: kbstate = KB_SINGLE; ! 819: timeout = KBTIMEOUT; ! 820: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL)) ! 821: ; ! 822: if (!timeout) ! 823: printf("kb: command timeout\n"); ! 824: else { ! 825: outb(KBDATA, cmd); ! 826: while (kbstate != KB_IDLE) ! 827: sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN); ! 828: } ! 829: spl(s); ! 830: } ! 831: ! 832: /* ! 833: * ship a two byte command to the keyboard ! 834: */ ! 835: kb_cmd2(cmd, arg) ! 836: unsigned cmd, arg; ! 837: { ! 838: register int timeout; ! 839: register int s; ! 840: ! 841: s = sphi(); ! 842: KBDEBUG3(" kb_cmd2(%x, %x)", cmd, arg); ! 843: while (kbstate != KB_IDLE) ! 844: sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN); ! 845: kbstate = KB_DOUBLE_1; ! 846: cmd2 = arg; ! 847: prev_cmd = cmd; ! 848: timeout = KBTIMEOUT; ! 849: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL)) ! 850: ; ! 851: if (!timeout) ! 852: printf("kb: command timeout\n"); ! 853: else { ! 854: outb(KBDATA, cmd); ! 855: while (kbstate != KB_IDLE) ! 856: sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN); ! 857: } ! 858: spl(s); ! 859: } ! 860: ! 861: /* End of nkb.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.