|
|
1.1 ! root 1: /* ! 2: * Copyright (C) 1985 by Sun Microsystems, Inc. ! 3: */ ! 4: #include "kbd.h" ! 5: #if NKBD > 0 ! 6: /* ! 7: * Keyboard input line discipline. ! 8: * Console output line discipline. ! 9: */ ! 10: #include "../h/param.h" ! 11: #include "../h/systm.h" ! 12: #include "../h/stream.h" ! 13: #include "../h/ttyio.h" ! 14: #include "../h/ttyld.h" ! 15: #include "../h/conf.h" ! 16: #include "../machine/sunromvec.h" ! 17: #include "../sundev/kbdvar.h" ! 18: ! 19: /* ! 20: * For now these are shared. ! 21: */ ! 22: extern int nkeytables; ! 23: extern struct keyboard *keytables[]; ! 24: extern char keystringtab[16][KTAB_STRLEN]; ! 25: ! 26: #define TIMEOUT 04 ! 27: ! 28: struct kbdld { ! 29: /* Added for 9th edition */ ! 30: struct queue *key_q; /* queue for the keyboard */ ! 31: struct queue *cons_q; /* queue for output to the console */ ! 32: short c_state; /* state of the console */ ! 33: /* Defined by sun */ ! 34: u_char k_id; ! 35: u_char k_idstate; ! 36: u_char k_state; ! 37: u_char k_rptkey; ! 38: u_int k_buckybits; ! 39: u_int k_shiftmask; ! 40: struct keyboard *k_curkeyboard; ! 41: u_int k_togglemask; /* Toggle shifts state */ ! 42: } kbd[NKBD], nullkbd; ! 43: ! 44: /* ! 45: * States of keyboard ID recognizer ! 46: */ ! 47: #define KID_NONE 0 /* startup */ ! 48: #define KID_IDLE 1 /* saw IDLE code */ ! 49: #define KID_LKSUN2 2 /* probably Sun-2 */ ! 50: #define KID_OK 3 /* locked on ID */ ! 51: ! 52: /* ! 53: * Constants setup during the first open of a kbd (so that hz is defined). ! 54: */ ! 55: int kbd_repeatrate; ! 56: int kbd_repeatdelay; ! 57: ! 58: int kbdopen(), kbdclose(), kbdldin(), kbdisrv(), kbdldout(); ! 59: static struct qinit kbdrinit = { kbdldin, kbdisrv, kbdopen, kbdclose,300, 60}; ! 60: static struct qinit kbdwinit = { kbdldout, NULL, kbdopen, kbdclose, 200, 100 }; ! 61: struct streamtab kbdinfo = { &kbdrinit, &kbdwinit}; ! 62: ! 63: /* ! 64: * Keyboard and console open ! 65: */ ! 66: kbdopen(qp, dev) ! 67: register struct queue *qp; ! 68: { ! 69: register struct kbdld *k; ! 70: ! 71: /* Set these up only once so that they could be changed from adb */ ! 72: if (!kbd_repeatrate) { ! 73: kbd_repeatrate = (hz+29)/30; ! 74: kbd_repeatdelay = hz/2; ! 75: } ! 76: if (qp->ptr) /* already attached */ ! 77: return(1); ! 78: for (k = kbd; k->key_q != 0; k++) ! 79: if (k >= &kbd[NKBD]) ! 80: return(0); ! 81: *k = nullkbd; ! 82: k->key_q = qp; ! 83: k->cons_q = WR(qp); ! 84: qp->ptr = (caddr_t)k; ! 85: WR(qp)->ptr = (caddr_t)k; ! 86: kbdreset(k); ! 87: return(1); ! 88: } ! 89: ! 90: kbdclose(qp) ! 91: register struct queue *qp; ! 92: { ! 93: register struct kbdld *k = (struct kbdld *)qp->ptr; ! 94: ! 95: k->key_q = 0; ! 96: k->cons_q = 0; ! 97: } ! 98: ! 99: /* ! 100: * Console write put routine ! 101: */ ! 102: kbdldout(q, bp) ! 103: register struct queue *q; ! 104: register struct block *bp; ! 105: { ! 106: register union stmsg *sp; ! 107: register struct kbdld *k = (struct kbdld *)q->ptr; ! 108: ! 109: switch(bp->type) { ! 110: ! 111: case M_IOCTL: ! 112: sp = (union stmsg *)bp->rptr; ! 113: switch (sp->ioc0.com) { ! 114: ! 115: case TIOCGDEV: ! 116: sp->ioc3.sb.ispeed = ! 117: sp->ioc3.sb.ospeed = B9600; ! 118: bp->type = M_IOCACK; ! 119: qreply(q, bp); ! 120: return; ! 121: case TIOCSDEV: ! 122: bp->wptr = bp->rptr; ! 123: bp->type = M_IOCACK; ! 124: qreply(q, bp); ! 125: return; ! 126: default: ! 127: bp->type = M_IOCNAK; ! 128: bp->wptr = bp->rptr; ! 129: qreply(q, bp); ! 130: return; ! 131: } ! 132: ! 133: case M_STOP: ! 134: k->c_state |= TTSTOP; ! 135: break; ! 136: ! 137: case M_START: ! 138: k->c_state &= ~TTSTOP; ! 139: kbdstart(k); ! 140: break; ! 141: ! 142: case M_FLUSH: ! 143: flushq(q, 0); ! 144: break; ! 145: ! 146: case M_DELAY: ! 147: case M_DATA: ! 148: putq(q, bp); ! 149: kbdstart(k); ! 150: return; ! 151: ! 152: default: ! 153: break; ! 154: } ! 155: freeb(bp); ! 156: } ! 157: ! 158: kbdtime(k) ! 159: register struct kbdld *k; ! 160: { ! 161: k->c_state &= ~TIMEOUT; ! 162: kbdstart(k); ! 163: } ! 164: ! 165: kbdstart(k) ! 166: register struct kbdld *k; ! 167: { ! 168: register s; ! 169: register struct block *bp; ! 170: register u_char *cp; ! 171: ! 172: if (k->cons_q==NULL) ! 173: return; ! 174: s = spl1(); ! 175: while ((k->c_state & (TIMEOUT|TTSTOP))==0 && k->cons_q->count) { ! 176: bp = getq(k->cons_q); ! 177: switch (bp->type) { ! 178: ! 179: case M_DATA: ! 180: /* Must clear high bit for monitor */ ! 181: for(cp = bp->rptr; cp < bp->wptr; cp++) ! 182: *cp &= 0177; ! 183: (*romp->v_fwritestr)(bp->rptr, bp->wptr - bp->rptr, ! 184: romp->v_fbaddr); ! 185: freeb(bp); ! 186: break; ! 187: ! 188: case M_DELAY: ! 189: timeout(kbdtime, (caddr_t)k, (int)*bp->rptr); ! 190: k->c_state |= TIMEOUT; ! 191: freeb(bp); ! 192: splx(s); ! 193: return; ! 194: default: ! 195: freeb(bp); ! 196: break; ! 197: } ! 198: } ! 199: splx(s); ! 200: } ! 201: ! 202: kbdldin(q, bp) ! 203: struct queue *q; ! 204: register struct block *bp; ! 205: { ! 206: register struct kbdld *k = (struct kbdld *)q->ptr; ! 207: ! 208: /* Pass along anything but data */ ! 209: if (bp->type != M_DATA) { ! 210: (*q->next->qinfo->putp)(q->next, bp); ! 211: return; ! 212: } ! 213: ! 214: while (bp->rptr < bp->wptr) ! 215: kbdinput(*bp->rptr++, k); ! 216: freeb(bp); ! 217: while ((q->next->flag&QFULL)==0 && (bp = getq(q))) ! 218: (*q->next->qinfo->putp)(q->next, bp); ! 219: } ! 220: ! 221: /* ! 222: * keyboard server processing. ! 223: */ ! 224: kbdisrv(q) ! 225: register struct queue *q; ! 226: { ! 227: register struct block *bp; ! 228: ! 229: while ((q->next->flag&QFULL)==0 && (bp = getq(q))) ! 230: (*q->next->qinfo->putp)(q->next, bp); ! 231: } ! 232: ! 233: /* ! 234: * kbdclick is used to remember the current click value of the ! 235: * Sun-3 keyboard. This brain damaged keyboard will reset the ! 236: * clicking to the "default" value after a reset command and ! 237: * there is no way to read out the current click value. We ! 238: * cannot send a click command immediately after the reset ! 239: * command or the keyboard gets screwed up. So we wait until ! 240: * we get the ID byte before we send back the click command. ! 241: * Unfortunately, this means that there is a small window ! 242: * where the keyboard can click when it really shouldn't be. ! 243: * A value of -1 means that kbdclick has not been initialized yet. ! 244: */ ! 245: int kbdclick = -1; ! 246: ! 247: /* ! 248: * Send command byte to keyboard ! 249: */ ! 250: kbdcmd(k, cmd) ! 251: register struct kbdld *k; ! 252: char cmd; ! 253: { ! 254: register struct queue *q = WR(k->key_q)->next; ! 255: ! 256: putd(q->qinfo->putp, q, cmd); ! 257: if (cmd == KBD_CMD_NOCLICK) ! 258: kbdclick = 0; ! 259: else if (cmd == KBD_CMD_CLICK) ! 260: kbdclick = 1; ! 261: } ! 262: ! 263: /* ! 264: * Reset the keyboard ! 265: */ ! 266: kbdreset(k) ! 267: register struct kbdld *k; ! 268: { ! 269: k->k_idstate = KID_NONE; ! 270: k->k_state = NORMAL; ! 271: kbdcmd(k, KBD_CMD_RESET); ! 272: } ! 273: ! 274: kbdidletimeout(k) ! 275: register struct kbdld *k; ! 276: { ! 277: untimeout(kbdidletimeout, (caddr_t)k); ! 278: /* ! 279: * Double check that was waiting for idle timeout. ! 280: */ ! 281: if (k->k_idstate == KID_IDLE) ! 282: kbdinput(IDLEKEY, k); ! 283: } ! 284: ! 285: /* ! 286: * Process a keypress ! 287: */ ! 288: kbdinput(key, k) ! 289: register u_char key; ! 290: register struct kbdld *k; ! 291: { ! 292: switch (k->k_idstate) { ! 293: ! 294: case KID_NONE: ! 295: if (key == IDLEKEY) { ! 296: k->k_idstate = KID_IDLE; ! 297: timeout(kbdidletimeout, (caddr_t)k, hz/10); ! 298: } else if (key == RESETKEY) ! 299: k->k_idstate = KID_LKSUN2; ! 300: return; ! 301: ! 302: case KID_IDLE: ! 303: if (key == IDLEKEY) ! 304: kbdid(k, KB_KLUNK); ! 305: else if (key == RESETKEY) ! 306: k->k_idstate = KID_LKSUN2; ! 307: else if (key & 0x80) ! 308: kbdid(k, (int)(KB_VT100 | (key&0x40))); ! 309: else ! 310: kbdreset(k); ! 311: return; ! 312: ! 313: case KID_LKSUN2: ! 314: if (key == 0x02) { /* Sun-2 keyboard */ ! 315: kbdid(k, KB_SUN2); ! 316: return; ! 317: } ! 318: if (key == 0x03) { /* Sun-3 keyboard */ ! 319: kbdid(k, KB_SUN3); ! 320: /* ! 321: * We just did a reset command to a Sun-3 keyboard ! 322: * which sets the click back to the default ! 323: * (which is currently ON!). We use the kbdclick ! 324: * variable to see if the keyboard should be ! 325: * turned on or off. If it has not been set, ! 326: * then on a sun3 we use the eeprom to determine ! 327: * if the default value is on or off. In the ! 328: * sun2 case, we default to off. ! 329: */ ! 330: switch (kbdclick) { ! 331: case 0: ! 332: kbdcmd(k, KBD_CMD_NOCLICK); ! 333: break; ! 334: case 1: ! 335: kbdcmd(k, KBD_CMD_CLICK); ! 336: break; ! 337: case -1: ! 338: default: ! 339: { ! 340: #ifdef sun3 ! 341: #include "../sun3/eeprom.h" ! 342: ! 343: if (EEPROM->ee_diag.eed_keyclick == ! 344: EED_KEYCLICK) ! 345: kbdcmd(k, KBD_CMD_CLICK); ! 346: else ! 347: #endif sun3 ! 348: kbdcmd(k, KBD_CMD_NOCLICK); ! 349: } ! 350: break; ! 351: } ! 352: return; ! 353: } ! 354: kbdreset(k); ! 355: return; ! 356: ! 357: case KID_OK: ! 358: if (key == 0 || key == 0xFF) { ! 359: kbdreset(k); ! 360: return; ! 361: } ! 362: break; ! 363: } ! 364: ! 365: switch (k->k_state) { ! 366: ! 367: normalstate: ! 368: k->k_state = NORMAL; ! 369: case NORMAL: ! 370: if (k->k_curkeyboard && key == k->k_curkeyboard->k_abort1) { ! 371: k->k_state = ABORT1; ! 372: break; ! 373: } ! 374: kbdtranslate(k, key); ! 375: if (key == IDLEKEY) ! 376: k->k_state = IDLE1; ! 377: break; ! 378: ! 379: case IDLE1: ! 380: if (key & 0x80) { /* ID byte */ ! 381: if (k->k_id == KB_VT100) ! 382: k->k_state = IDLE2; ! 383: else ! 384: kbdreset(k); ! 385: break; ! 386: } ! 387: if (key != IDLEKEY) ! 388: goto normalstate; /* real data */ ! 389: break; ! 390: ! 391: case IDLE2: ! 392: if (key == IDLEKEY) k->k_state = IDLE1; ! 393: else goto normalstate; ! 394: break; ! 395: ! 396: case ABORT1: ! 397: if (k->k_curkeyboard) { ! 398: if (key == k->k_curkeyboard->k_abort2) { ! 399: DELAY(100000); ! 400: montrap(*romp->v_abortent); ! 401: k->k_state = NORMAL; ! 402: kbdtranslate(k, (u_char)IDLEKEY); /* fake */ ! 403: return; ! 404: } else { ! 405: kbdtranslate(k, k->k_curkeyboard->k_abort1); ! 406: goto normalstate; ! 407: } ! 408: } ! 409: } ! 410: } ! 411: ! 412: kbdid(k, id) ! 413: register struct kbdld *k; ! 414: int id; ! 415: { ! 416: k->k_id = id & 0xF; ! 417: k->k_idstate = KID_OK; ! 418: k->k_shiftmask = 0; ! 419: if (id & 0x40) ! 420: /* Not a transition so don't send event */ ! 421: k->k_shiftmask |= CAPSMASK; ! 422: k->k_buckybits = 0; ! 423: k->k_curkeyboard = keytables[k->k_id]; ! 424: k->k_rptkey = IDLEKEY; /* Nothing happening now */ ! 425: } ! 426: ! 427: /* ! 428: * This routine determines which table we should look in to decode ! 429: * the current keycode. ! 430: */ ! 431: struct keymap * ! 432: settable(k, mask) ! 433: register struct kbdld *k; ! 434: register u_int mask; ! 435: { ! 436: register struct keyboard *kp; ! 437: ! 438: kp = k->k_curkeyboard; ! 439: if (kp == NULL) ! 440: return (NULL); ! 441: if (mask & UPMASK) ! 442: return (kp->k_up); ! 443: if (mask & CTRLMASK) ! 444: return (kp->k_control); ! 445: if (mask & SHIFTMASK) ! 446: return (kp->k_shifted); ! 447: if (mask & CAPSMASK) ! 448: return (kp->k_caps); ! 449: return (kp->k_normal); ! 450: } ! 451: ! 452: kbdrpt(k) ! 453: register struct kbdld *k; ! 454: { ! 455: kbdtranslate(k, k->k_rptkey); ! 456: if (k->k_rptkey != IDLEKEY) ! 457: timeout(kbdrpt, (caddr_t)k, kbd_repeatrate); ! 458: } ! 459: ! 460: kbdcancelrpt(k) ! 461: register struct kbdld *k; ! 462: { ! 463: if (k->k_rptkey != IDLEKEY) { ! 464: untimeout(kbdrpt, (caddr_t)k); ! 465: k->k_rptkey = IDLEKEY; ! 466: } ! 467: } ! 468: ! 469: kbdtranslate(k, keycode) ! 470: register struct kbdld *k; ! 471: register u_char keycode; ! 472: { ! 473: register u_char key, newstate, entry; ! 474: register u_char enF0; ! 475: register char *cp; ! 476: struct keymap *km; ! 477: register struct queue *q = k->key_q; ! 478: ! 479: newstate = STATEOF(keycode); ! 480: key = KEYOF(keycode); ! 481: ! 482: km = settable(k, (u_int)(k->k_shiftmask | newstate)); ! 483: if (km == NULL) { /* gross error */ ! 484: kbdcancelrpt(k); ! 485: return; ! 486: } ! 487: entry = km->keymap[key]; ! 488: enF0 = entry & 0xF0; ! 489: /* ! 490: * Handle the state of toggle shifts specially. ! 491: * Toggle shifts should only come on downs. ! 492: */ ! 493: if (((entry >> 4) == (SHIFTKEYS >> 4)) && ! 494: ((1 << (entry & 0x0F)) & k->k_curkeyboard->k_toggleshifts)) { ! 495: if ((1 << (entry & 0x0F)) & k->k_togglemask) { ! 496: newstate = RELEASED; ! 497: } else { ! 498: newstate = PRESSED; ! 499: } ! 500: } ! 501: ! 502: if (newstate == PRESSED && entry != NOSCROLL && ! 503: enF0 != SHIFTKEYS && enF0 != BUCKYBITS && ! 504: !(entry >= LEFTFUNC && entry <= BOTTOMFUNC+15)) { ! 505: if (k->k_rptkey != keycode) { ! 506: kbdcancelrpt(k); ! 507: timeout(kbdrpt, (caddr_t)k, kbd_repeatdelay); ! 508: k->k_rptkey = keycode; ! 509: } ! 510: } else if (key == KEYOF(k->k_rptkey)) /* key going up */ ! 511: kbdcancelrpt(k); ! 512: ! 513: switch (entry >> 4) { ! 514: ! 515: case 0: case 1: case 2: case 3: ! 516: case 4: case 5: case 6: case 7: ! 517: putd(putq, q, entry | k->k_buckybits); ! 518: break; ! 519: ! 520: case SHIFTKEYS >> 4: { ! 521: u_int shiftbit = 1 << (entry & 0x0F); ! 522: ! 523: /* Modify toggle state (see toggle processing above) */ ! 524: if (shiftbit & k->k_curkeyboard->k_toggleshifts) { ! 525: if (newstate == RELEASED) { ! 526: k->k_togglemask &= ~shiftbit; ! 527: k->k_shiftmask &= ~shiftbit; ! 528: } else { ! 529: k->k_togglemask |= shiftbit; ! 530: k->k_shiftmask |= shiftbit; ! 531: } ! 532: } else ! 533: k->k_shiftmask ^= shiftbit; ! 534: break; ! 535: } ! 536: ! 537: case BUCKYBITS >> 4: ! 538: k->k_buckybits ^= 1 << (7 + (entry & 0x0F)); ! 539: break; ! 540: ! 541: case FUNNY >> 4: ! 542: switch (entry) { ! 543: case NOP: ! 544: break; ! 545: ! 546: /* ! 547: * NOSCROLL/CTRLS/CTRLQ exist so that these keys, on keyboards ! 548: * with NOSCROLL, interact smoothly. If a user changes ! 549: * his tty output control keys to be something other than those ! 550: * in keytables for CTRLS & CTRLQ then he effectively disables ! 551: * his NOSCROLL key. One could imagine computing CTRLS & CTRLQ ! 552: * dynamically by watching TIOCSETC ioctl's go by in kbdioctl. ! 553: */ ! 554: case NOSCROLL: ! 555: if (k->k_shiftmask & CTLSMASK) goto sendcq; ! 556: else goto sendcs; ! 557: ! 558: case CTRLS: ! 559: sendcs: ! 560: k->k_shiftmask |= CTLSMASK; ! 561: putd(putq, q, ('S'-0x40) | k->k_buckybits); ! 562: break; ! 563: ! 564: case CTRLQ: ! 565: sendcq: ! 566: putd(putq, q, ('Q'-0x40) | k->k_buckybits); ! 567: k->k_shiftmask &= ~CTLSMASK; ! 568: break; ! 569: ! 570: case IDLE: ! 571: /* ! 572: * Minor hack to prevent keyboards unplugged ! 573: * in caps lock from retaining their capslock ! 574: * state when replugged. This should be ! 575: * solved by using the capslock info in the ! 576: * KBDID byte. ! 577: */ ! 578: if (keycode == NOTPRESENT) ! 579: k->k_shiftmask = 0; ! 580: /* Fall thru into RESET code */ ! 581: ! 582: case RESET: ! 583: gotreset: ! 584: k->k_shiftmask &= k->k_curkeyboard->k_idleshifts; ! 585: k->k_shiftmask |= k->k_togglemask; ! 586: k->k_buckybits &= k->k_curkeyboard->k_idlebuckys; ! 587: kbdcancelrpt(k); ! 588: break; ! 589: ! 590: case ERROR: ! 591: printf("kbd: Error detected\r\n"); ! 592: goto gotreset; ! 593: ! 594: /* ! 595: * Remember when adding new entries that, ! 596: * if they should NOT auto-repeat, ! 597: * they should be put into the IF statement ! 598: * just above this switch block. ! 599: */ ! 600: default: ! 601: goto badentry; ! 602: } ! 603: break; ! 604: ! 605: case STRING >> 4: ! 606: cp = &keystringtab[entry & 0x0F][0]; ! 607: while (*cp != '\0') { ! 608: putd(putq, q, *cp); ! 609: cp++; ! 610: } ! 611: break; ! 612: ! 613: /* ! 614: * Remember when adding new entries that, ! 615: * if they should NOT auto-repeat, ! 616: * they should be put into the IF statement ! 617: * just above this switch block. ! 618: */ ! 619: default: ! 620: if (entry >= LEFTFUNC && entry <= BOTTOMFUNC+15) { ! 621: char buf[10], *strsetwithdecimal(); ! 622: ! 623: if (newstate == RELEASED) ! 624: break; ! 625: cp = strsetwithdecimal(&buf[0], (u_int)entry, ! 626: sizeof (buf) - 1); ! 627: putd(putq, q, '\033'); ! 628: putd(putq, q, '['); ! 629: while (*cp != '\0') { ! 630: putd(putq, q, *cp); ! 631: cp++; ! 632: } ! 633: putd(putq, q, 'z'); ! 634: } ! 635: badentry: ! 636: break; ! 637: } ! 638: } ! 639: ! 640: char * ! 641: strsetwithdecimal(buf, val, maxdigs) ! 642: char *buf; ! 643: u_int val, maxdigs; ! 644: { ! 645: int hradix = 5; ! 646: char *bp; ! 647: int lowbit; ! 648: char *tab = "0123456789abcdef"; ! 649: ! 650: bp = buf + maxdigs; ! 651: *(--bp) = '\0'; ! 652: while (val) { ! 653: lowbit = val & 1; ! 654: val = (val >> 1); ! 655: *(--bp) = tab[val % hradix * 2 + lowbit]; ! 656: val /= hradix; ! 657: } ! 658: return (bp); ! 659: } ! 660: #endif NKBD > 0
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.