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