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