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