|
|
1.1 ! root 1: /* ! 2: * io.386/nkb.c ! 3: * ! 4: * Keyboard driver, no virtual consoles, loadable tables. ! 5: * ! 6: * Revised: Fri Jul 16 08:39:12 1993 CDT ! 7: */ ! 8: ! 9: #include <sys/coherent.h> ! 10: #include <sys/con.h> ! 11: #include <sys/errno.h> ! 12: #include <sys/stat.h> ! 13: #include <sys/tty.h> ! 14: #include <signal.h> ! 15: #include <sys/seg.h> ! 16: #include <sys/sched.h> ! 17: #include <sys/kb.h> ! 18: #include <sys/devices.h> ! 19: #include <sys/silo.h> ! 20: #include <stddef.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 function key data */ ! 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: static int xlate = 1; /* scan code translation flag */ ! 102: ! 103: #define ESCAPE_CHAR '\x1B' ! 104: #define ESCAPE_STRING "\x1B" ! 105: ! 106: ! 107: /* ! 108: * Functions. ! 109: */ ! 110: int isrint(); ! 111: int istime(); ! 112: void isbatch(); ! 113: int mmstart(); ! 114: int isopen(); ! 115: int isclose(); ! 116: int isread(); ! 117: int mmwrite(); ! 118: int isioctl(); ! 119: void mmwatch(); ! 120: int isload(); ! 121: int isuload(); ! 122: int ispoll(); ! 123: int nulldev(); ! 124: int nonedev(); ! 125: int updleds(); ! 126: ! 127: /* ! 128: * Configuration table. ! 129: */ ! 130: ! 131: CON nkbcon ={ ! 132: DFCHR|DFPOL, /* Flags */ ! 133: KB_MAJOR, /* Major index */ ! 134: isopen, /* Open */ ! 135: isclose, /* Close */ ! 136: nulldev, /* Block */ ! 137: isread, /* Read */ ! 138: mmwrite, /* Write */ ! 139: isioctl, /* Ioctl */ ! 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: * special constants/struct for the XWindow/KDMAPDISP calls ! 269: */ ! 270: ! 271: #define KDMAPDISP (('K' << 8) | 2) /* map display into user space */ ! 272: #define KDSKBMODE (('K' << 8) | 6) /* turn scan code xlate on/off */ ! 273: #define KDMEMDISP (('K' << 8) | 7) /* dump byte of virt/phys mem */ ! 274: #define KDENABIO (('K' << 8) | 60) /* enable IO */ ! 275: #define KIOCSOUND (('K' << 8) | 63) /* start sound generation */ ! 276: #define KDSETLED (('K' << 8) | 66) /* set leds */ ! 277: ! 278: #define TIMER_CTL 0x43 /* Timer control */ ! 279: #define TIMER_CNT 0x42 /* Timer counter */ ! 280: #define SPEAKER_CTL 0x61 /* Speaker control */ ! 281: ! 282: struct kd_memloc { ! 283: char *vaddr; /* virtual address to map to */ ! 284: char *physaddr; /* physical address to map to */ ! 285: long length; /* size in bytes to map */ ! 286: long ioflg; /* enable I/O addresses if non-zero */ ! 287: }; ! 288: ! 289: static TIM tp; ! 290: ! 291: int ! 292: resetkb(action) ! 293: int action; ! 294: { ! 295: int i; ! 296: if (action == 1) { ! 297: timeout(&tp,20,resetkb,2); ! 298: outb(KBCTRL, 0xCC); /* Clock high */ ! 299: } ! 300: if (action == 2) { ! 301: i = inb(KBDATA); ! 302: outb(KBCTRL, 0xCC); /* Clear keyboard */ ! 303: outb(KBCTRL, 0x4D); /* Enable keyboard */ ! 304: } ! 305: } ! 306: ! 307: static int X11led; ! 308: ! 309: /* ! 310: * Ioctl routine. ! 311: * nb: archaic TIOCSHIFT and TIOCCSHIFT no longer needed/supported. ! 312: */ ! 313: isioctl(dev, com, vec) ! 314: dev_t dev; ! 315: struct sgttyb *vec; ! 316: { ! 317: register int s; ! 318: ! 319: switch (com) { ! 320: #define KDDEBUG 0 ! 321: #if KDDEBUG ! 322: case KDMEMDISP: ! 323: { ! 324: struct kd_memloc* mem; ! 325: unsigned char ub, pb; ! 326: mem = vec; ! 327: pxcopy( mem->physaddr, &pb, 1, SEG_386_KD ); ! 328: ub = getubd( mem->vaddr ); ! 329: printf( "User's byte %x(%x), Physical byte %x, Addresses %x %x\n", ! 330: mem->ioflg, ub, pb, mem->vaddr, mem->physaddr ); ! 331: break;; ! 332: } ! 333: #endif ! 334: case KDMAPDISP: ! 335: { ! 336: struct kd_memloc* mem; ! 337: mem = vec; ! 338: #if KDDEBUG ! 339: printf( "mapPhysUser(%x, %x, %x) = %d\n", ! 340: mem->vaddr, mem->physaddr, mem->length, ! 341: #endif ! 342: mapPhysUser(mem->vaddr, mem->physaddr, mem->length) ! 343: #if KDDEBUG ! 344: ) ! 345: #endif ! 346: ; ! 347: } ! 348: case KDENABIO: ! 349: { ! 350: int i; ! 351: for (i = 0 ; i < 64 ; i++ ) ! 352: iomapAnd(0,i); ! 353: break;; ! 354: } ! 355: case KIOCSOUND: ! 356: { ! 357: if (vec) { ! 358: outb(TIMER_CTL, 0xB6); ! 359: outb(TIMER_CNT, (int)vec&0xFF); ! 360: outb(TIMER_CNT, (int)vec>>8); ! 361: outb(SPEAKER_CTL, inb(SPEAKER_CTL) | 03); /* Turn speaker on */ ! 362: } ! 363: else ! 364: outb(SPEAKER_CTL, inb(SPEAKER_CTL) & ~03 ); /* speaker off */ ! 365: break;; ! 366: } ! 367: case KDSKBMODE: ! 368: { ! 369: static int vtB4X11; ! 370: /* outb(KBCTRL, 0x0C); /* Clock low */ ! 371: /* timeout(&tp,3,resetkb,1); /* wait about 20-30ms */ ! 372: if (xlate > vec) { /* Turning translation off */ ! 373: kb_cmd2(K_SCANCODE_CMD, 1); /* set 1 for X */ ! 374: } ! 375: else if (xlate < vec) { /* turning translation on */ ! 376: kb_cmd2(K_SCANCODE_CMD, 3); /* set 3 for COH */ ! 377: } ! 378: xlate = (int)vec; ! 379: /* kb_cmd(K_ALL_TMB_CMD); /* default: TMB for all keys */ ! 380: break;; ! 381: } ! 382: case KDSETLED: ! 383: { ! 384: X11led = (int)vec; ! 385: updleds(); ! 386: break;; ! 387: } ! 388: ! 389: case TIOCSETF: ! 390: case TIOCGETF: ! 391: isfunction(com, (char *)vec); ! 392: break; ! 393: case TIOCSETKBT: ! 394: issettable(vec); ! 395: break; ! 396: case TIOCGETKBT: ! 397: isgettable(vec); ! 398: break; ! 399: default: /* pass to TTY driver */ ! 400: s = sphi(); ! 401: ttioctl(&istty, com, vec); ! 402: spl(s); ! 403: break; ! 404: } ! 405: } ! 406: ! 407: /* ! 408: * Set the in-core keyboard mapping table. ! 409: * The table is sorted by scan code prior to calling ioctl(). ! 410: * All unused table entries (holes in the scan code map) have ! 411: * a zero for the k_key field. ! 412: * This makes key lookup at interrupt time fast by using the scan code ! 413: * as an index into the table. ! 414: */ ! 415: issettable(vec) ! 416: char *vec; ! 417: { ! 418: register unsigned i; ! 419: register int s; ! 420: int timeout; ! 421: static KBTBL this_key; /* current key from kbd table */ ! 422: unsigned int cmd_byte; ! 423: #ifndef _I386 ! 424: register faddr_t faddr; /* address of keyboard table */ ! 425: #endif ! 426: ! 427: KBDEBUG(" TIOCSETKBT"); ! 428: kb_cmd2(K_SCANCODE_CMD, 3); /* select set 3 */ ! 429: kb_cmd(K_ALL_TMB_CMD); /* default: TMB for all keys */ ! 430: #ifndef _I386 ! 431: faddr = kbsegp->s_faddr; ! 432: #endif ! 433: for (i = 0; i < MAX_KEYS; ++i) { ! 434: ukcopy(vec, &this_key, sizeof(this_key)); ! 435: #ifdef _I386 ! 436: kb[i] = this_key; /* store away */ ! 437: #else ! 438: kfcopy(&this_key, faddr, sizeof(this_key)); ! 439: faddr += sizeof(this_key); ! 440: #endif ! 441: vec += sizeof(this_key); ! 442: if (this_key.k_key != i && this_key.k_key != 0) { ! 443: printf("kb: incorrect or unsorted table entry %d\n", i); ! 444: #ifdef _I386 ! 445: u.u_error = EINVAL; ! 446: #else ! 447: u.u_error = EBADFMT; ! 448: #endif ! 449: return; ! 450: } ! 451: if (this_key.k_key != i) ! 452: continue; /* no key */ ! 453: switch (this_key.k_flags&TMODE) { ! 454: case T: /* typematic */ ! 455: kb_cmd2(K_KEY_T_CMD, i); ! 456: break; ! 457: case M: /* make only */ ! 458: kb_cmd2(K_KEY_M_CMD, i); ! 459: break; ! 460: case MB: /* make/break */ ! 461: kb_cmd2(K_KEY_MB_CMD, i); ! 462: break; ! 463: case TMB: /* typematic make/break */ ! 464: break; /* this is the default */ ! 465: default: ! 466: printf("kb: bad key mode\n"); ! 467: } ! 468: } ! 469: updleds(); ! 470: kb_cmd2(K_SCANCODE_CMD, 3); /* select set 3 */ ! 471: kb_cmd(K_ENABLE_CMD); /* start scanning */ ! 472: /* ! 473: * The following code disables translation from the on-board ! 474: * keyboard/aux controller. Without disabling translation, the ! 475: * received scan codes still look like code set 1 codes even ! 476: * though we put the keyboard controller in scan code set 3. ! 477: * Yes, this is progress.... ! 478: */ ! 479: #if 0 ! 480: while (inb(KBSTS_CMD) & STS_IBUF_FULL) ! 481: ; ! 482: outb(KBSTS_CMD, C_READ_CMD); /* read controller cmd byte */ ! 483: while (!(inb(KBSTS_CMD) & STS_OBUF_FULL)) ! 484: ; ! 485: cmd_byte = inb(KBDATA); ! 486: KBDEBUG2(" cmd_byte=%x", cmd_byte); ! 487: #endif ! 488: timeout = KBTIMEOUT; ! 489: s = sphi(); ! 490: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0) ! 491: ; ! 492: outb(KBSTS_CMD, C_WRITE_CMD); /* write controller cmd byte */ ! 493: for (timeout = 50; --timeout > 0;) ! 494: ; ! 495: timeout = KBTIMEOUT; ! 496: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0) ! 497: ; ! 498: outb(KBDATA, KBCMDBYTE); /* turn off translation */ ! 499: timeout = KBTIMEOUT; ! 500: while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0) ! 501: ; ! 502: spl(s); ! 503: #if DEBUG ! 504: kb_cmd2(K_SCANCODE_CMD, 0); /* query s.c. mode */ ! 505: #endif ! 506: ++table_loaded; ! 507: } ! 508: ! 509: /* ! 510: * Get the in-core keyboard mapping table and pass it to the user. ! 511: */ ! 512: isgettable(vec) ! 513: char *vec; ! 514: { ! 515: #ifdef _I386 ! 516: KBDEBUG(" TIOCGETKBT"); ! 517: kucopy(kb, vec, sizeof(kb)); ! 518: #else ! 519: register unsigned i; ! 520: register faddr_t faddr; /* address of keyboard table */ ! 521: static KBTBL this_key; /* current key from kbd table */ ! 522: ! 523: KBDEBUG(" TIOCGETKBT"); ! 524: faddr = kbsegp->s_faddr; ! 525: for (i = 0; i < MAX_KEYS; ++i) { ! 526: fkcopy(faddr, &this_key, sizeof(this_key)); ! 527: kucopy(&this_key, vec, sizeof(this_key)); ! 528: faddr += sizeof(this_key); ! 529: vec += sizeof(this_key); ! 530: } ! 531: #endif ! 532: } ! 533: ! 534: ! 535: /* ! 536: * Set and receive the function keys. ! 537: */ ! 538: isfunction(c, v) ! 539: int c; ! 540: FNKEY *v; ! 541: { ! 542: register unsigned char *cp; ! 543: register unsigned i; ! 544: unsigned char numkeys = 0; ! 545: ! 546: if (c == TIOCGETF) { ! 547: KBDEBUG(" TIOCGETF"); ! 548: if (!fk_loaded) ! 549: u.u_error = EINVAL; ! 550: else ! 551: kucopy(fnkeys, v, fklength); /* copy ours to user */ ! 552: } else { /* TIOCSETF */ ! 553: /* ! 554: * If we had a previous function key arena, free it up. ! 555: * Since we don't know how large the function key arena will ! 556: * be, we must size it in the user data space prior to ! 557: * (re)kalloc()'ing it. This is ugly, but a helluva lot better ! 558: * than the old driver which used a hard coded limit of 150! ! 559: */ ! 560: KBDEBUG(" TIOCSETF"); ! 561: fk_loaded = 0; ! 562: if (fnkeys != (FNKEY *)0) ! 563: kfree(fnkeys); /* free old arena */ ! 564: if (funkeyp != NULL) ! 565: kfree(funkeyp); /* free old ptr array */ ! 566: ukcopy(&v->k_nfkeys, &numkeys, sizeof(numkeys)); ! 567: fklength = sizeof (FNKEY); ! 568: cp = (char *) (v + 1); ! 569: for (i = 0; i < numkeys; i++) { ! 570: do { ! 571: ++fklength; ! 572: } while (getubd(cp++) != DELIM); ! 573: } ! 574: fnkeys = (FNKEY *)kalloc(fklength); ! 575: funkeyp = (unsigned char **)kalloc(numkeys * sizeof(char *)); ! 576: if (fnkeys == (FNKEY *)0 || funkeyp == NULL) { ! 577: if (fnkeys != (FNKEY *)0) { ! 578: kfree(fnkeys); ! 579: fnkeys = 0; ! 580: } ! 581: if (funkeyp != NULL) { ! 582: kfree(funkeyp); ! 583: funkeyp = 0; ! 584: } ! 585: u.u_error = ENOMEM; ! 586: return; ! 587: } ! 588: cp = (char *) (fnkeys + 1); /* point to Fn ... */ ! 589: v = (char *) (v + 1); /* ... key arena */ ! 590: for (i = 0; i < numkeys; i++) { ! 591: funkeyp[i] = cp; /* save pointer */ ! 592: while ((*cp++ = getubd(v++)) != DELIM) /* copy key */ ! 593: ; ! 594: } ! 595: fnkeys->k_nfkeys = numkeys; ! 596: fk_loaded = 1; ! 597: } ! 598: } ! 599: ! 600: ! 601: /* ! 602: * Poll routine. ! 603: */ ! 604: ispoll(dev, ev, msec) ! 605: dev_t dev; ! 606: int ev; ! 607: int msec; ! 608: { ! 609: return ttpoll (& istty, ev, msec); ! 610: } ! 611: ! 612: /* ! 613: * Receive interrupt. ! 614: */ ! 615: isrint() ! 616: { ! 617: register unsigned c; ! 618: register unsigned r; ! 619: static char keyup; ! 620: ! 621: /* ! 622: * Schedule raw input handler if not already active. ! 623: */ ! 624: ! 625: if (! isbusy) { ! 626: defer (isbatch, & istty); ! 627: isbusy = 1; ! 628: } ! 629: ! 630: /* ! 631: * Pull character from the data ! 632: * port. Pulse the KBFLAG in the control ! 633: * port to reset the data buffer. ! 634: */ ! 635: ! 636: r = inb(KBDATA) & 0xFF; ! 637: c = inb (KBCTRL); ! 638: outb (KBCTRL, c | KBFLAG); ! 639: outb (KBCTRL, c); ! 640: ! 641: /* ! 642: * check returned value from keyboard to see if it's a command ! 643: * or status back to us. If not, it we assume that it's a key code. ! 644: */ ! 645: ! 646: KBDEBUG2 (" intr(%x)", r); ! 647: ! 648: if (!xlate) switch (r) { ! 649: ! 650: case K_BAT_BAD: ! 651: printf("kb: keyboard BAT failed\n"); ! 652: break; ! 653: case K_RESEND: ! 654: KBDEBUG("\nkb: request to resend command\n"); ! 655: outb(KBDATA, prev_cmd); ! 656: break; ! 657: case K_OVERRUN_23: ! 658: printf("kb: keyboard buffer overrun\n"); ! 659: break; ! 660: case K_ACK: ! 661: /* ! 662: * we received an ACKnowledgement from the keyboard. ! 663: * advance the state machine and continue. ! 664: */ ! 665: KBDEBUG(" ACK "); ! 666: switch (kbstate) { ! 667: case KB_IDLE: /* shouldn't happen */ ! 668: printf("vtnkb: ACK while idle "); ! 669: break; ! 670: case KB_SINGLE: /* done with 1-byte command */ ! 671: case KB_DOUBLE_2: /* done w/ 2nd of 2-byte cmd */ ! 672: kbstate = KB_IDLE; ! 673: wakeup(&kbstate); ! 674: break; ! 675: case KB_DOUBLE_1: ! 676: kbstate = KB_DOUBLE_2; ! 677: outb(KBDATA, cmd2); ! 678: break; ! 679: default: ! 680: printf("kb: bad kbstate %d\n", kbstate); ! 681: break; ! 682: } ! 683: break; ! 684: default: ! 685: isin(r); ! 686: break; ! 687: } else switch (r) { ! 688: ! 689: case K_BREAK: ! 690: keyup = 1; /* key going up */ ! 691: break; ! 692: ! 693: case K_ECHO_R: ! 694: case K_BAT_OK: ! 695: break; /* very nice, but ignored */ ! 696: ! 697: case K_BAT_BAD: ! 698: printf ("kb: keyboard BAT failed\n"); ! 699: break; ! 700: ! 701: case K_RESEND: ! 702: KBDEBUG ("\nkb: request to resend command\n"); ! 703: outb(KBDATA, prev_cmd); ! 704: break; ! 705: ! 706: case K_OVERRUN_23: ! 707: printf ("kb: keyboard buffer overrun\n"); ! 708: break; ! 709: ! 710: case K_ACK: ! 711: /* ! 712: * we received an ACKnowledgement from the keyboard. ! 713: * advance the state machine and continue. ! 714: */ ! 715: KBDEBUG(" ACK"); ! 716: switch (kbstate) { ! 717: ! 718: case KB_IDLE: /* shouldn't happen */ ! 719: printf ("kb: ACK while keyboard idle\n"); ! 720: break; ! 721: ! 722: case KB_SINGLE: /* done with 1-byte command */ ! 723: case KB_DOUBLE_2: /* done w/ 2nd of 2-byte cmd */ ! 724: kbstate = KB_IDLE; ! 725: wakeup (& kbstate); ! 726: break; ! 727: ! 728: case KB_DOUBLE_1: ! 729: kbstate = KB_DOUBLE_2; ! 730: outb (KBDATA, cmd2); ! 731: break; ! 732: ! 733: default: ! 734: printf ("kb: bad kbstate %d\n", kbstate); ! 735: break; ! 736: } ! 737: break; ! 738: default: ! 739: process_key (r, keyup); ! 740: keyup = 0; ! 741: } ! 742: } ! 743: ! 744: /* ! 745: * Process a key given its scan code and direction. ! 746: * ! 747: * In this table driven version of the keyboard driver, we trade off the ! 748: * code complexity associated with all the black magic that used to be ! 749: * performed on a per-key basis with the increased memory requirements ! 750: * associated with the table driven approach. ! 751: */ ! 752: process_key(key, up) ! 753: unsigned key; ! 754: int up; ! 755: { ! 756: register unsigned char *cp; ! 757: KBTBL key_vals; /* table values for this key */ ! 758: unsigned val; ! 759: unsigned char flags; ! 760: ! 761: KBDEBUG3(" proc(%x %s)", key, (up ? "up" : "down")); ! 762: if (!table_loaded) ! 763: return; /* throw away key */ ! 764: #ifdef _I386 ! 765: key_vals = kb[key]; ! 766: #else ! 767: fkcopy(kbsegp->s_faddr + (key * sizeof(KBTBL)), ! 768: &key_vals, sizeof(key_vals)); ! 769: #endif ! 770: if (key_vals.k_key != key) /* empty entry */ ! 771: return; ! 772: flags = key_vals.k_flags; ! 773: ! 774: if (flags & S) { /* some shift/lock key ? */ ! 775: switch (key_vals.k_val [BASE]) { ! 776: case caps: ! 777: case num: ! 778: if (!up) { ! 779: shift ^= (1 << key_vals.k_val [BASE]); ! 780: updleds2 (); ! 781: } ! 782: break; ! 783: case scroll: ! 784: if (!up) { ! 785: shift ^= (1 << key_vals.k_val [BASE]); ! 786: updleds2 (); ! 787: if (! _IS_RAW_INPUT (& istty)) { ! 788: if (istty.t_flags & T_STOP) ! 789: isin (istty.t_tchars.t_startc); ! 790: else ! 791: isin (istty.t_tchars.t_stopc); ! 792: } ! 793: } ! 794: break; ! 795: default: ! 796: if (up) ! 797: shift &= ~(1 << key_vals.k_val [BASE]); ! 798: else ! 799: shift |= (1 << key_vals.k_val [BASE]); ! 800: break; ! 801: } ! 802: /* ! 803: * Calculate the shift index based upon the state of ! 804: * the shift and lock keys. ! 805: */ ! 806: sh_index = BASE; /* default condition */ ! 807: if (shift & (1 << altgr)) ! 808: sh_index = ALT_GR; ! 809: else { ! 810: if (shift & ((1 << lalt)|(1 << ralt))) ! 811: sh_index |= ALT; ! 812: if (shift & ((1 << lctrl)|(1 << rctrl))) ! 813: sh_index |= CTRL; ! 814: if (shift & ((1 << lshift)|(1 << rshift))) ! 815: sh_index |= SHIFT; ! 816: } ! 817: return; ! 818: } /* if (flags & S) */ ! 819: ! 820: /* ! 821: * If the tty is not open or the key has no value in the current ! 822: * shift state, the key is just tossed away. ! 823: */ ! 824: ! 825: if (up || ! istty.t_open || key_vals.k_val [sh_index] == none) ! 826: return; ! 827: ! 828: if (((flags & C) && (shift & (1 << caps))) ! 829: || ((flags & N) && (shift & (1 << num)))) ! 830: val = key_vals.k_val [sh_index ^ SHIFT]; ! 831: else ! 832: val = key_vals.k_val [sh_index]; ! 833: ! 834: /* ! 835: * Check for function key or special key implemented as ! 836: * a function key (reboot == f0, tab and back-tab, etc). ! 837: */ ! 838: ! 839: if (flags & F) { ! 840: if (val == 0 && ! up && KBBOOT) ! 841: boot (); ! 842: if (! fk_loaded || val >= fnkeys->k_nfkeys) ! 843: return; ! 844: if ((cp = funkeyp [val]) == NULL) /* has a value? */ ! 845: return; ! 846: while (* cp != DELIM) ! 847: isin (* cp ++); /* queue up Fn key value */ ! 848: return; ! 849: } ! 850: ! 851: /* ! 852: * Normal key processing. ! 853: */ ! 854: isin (val); /* send the char */ ! 855: return; ! 856: } ! 857: ! 858: /** ! 859: * ! 860: * void ! 861: * ismmfunc(c) -- process keyboard related output escape sequences ! 862: * char c; ! 863: */ ! 864: void ! 865: ismmfunc(c) ! 866: register int c; ! 867: { ! 868: switch (c) { ! 869: case 't': /* Enter numlock */ ! 870: shift |= (1 << num); ! 871: updleds(); /* update LED status */ ! 872: break; ! 873: ! 874: case 'u': /* Leave numlock */ ! 875: shift &= ~ (1 << num); ! 876: updleds (); /* update LED status */ ! 877: break; ! 878: ! 879: case '=': /* Enter alternate keypad -- ignored */ ! 880: case '>': /* Exit alternate keypad -- ignored */ ! 881: break; ! 882: ! 883: case 'c': /* Reset terminal */ ! 884: islock = 0; ! 885: break; ! 886: } ! 887: } ! 888: ! 889: /** ! 890: * ! 891: * void ! 892: * isin(c) -- append character to raw input silo ! 893: * char c; ! 894: */ ! 895: static ! 896: isin(c) ! 897: register int c; ! 898: { ! 899: int cache_it = 1; ! 900: TTY * tp = &istty; ! 901: void ttstart(); ! 902: ! 903: /* ! 904: * If using software incoming flow control, process and ! 905: * discard t_stopc and t_startc. ! 906: */ ! 907: if (_IS_IXON_MODE (tp)) { ! 908: #if _I386 ! 909: if (_IS_START_CHAR (tp, c) || ! 910: (_IS_IXANY_MODE (tp) && (tp->t_flags & T_STOP) != 0)) { ! 911: tp->t_flags &= ~ (T_STOP | T_XSTOP); ! 912: ttstart (tp); ! 913: cache_it = 0; ! 914: } else if (_IS_STOP_CHAR (tp, c)) { ! 915: if ((tp->t_flags & T_STOP) == 0) ! 916: tp->t_flags |= (T_STOP | T_XSTOP); ! 917: cache_it = 0; ! 918: } ! 919: #else ! 920: if (_IS_STOP_CHAR (tp, c)) { ! 921: if ((tp->t_flags & T_STOP) == 0) ! 922: tp->t_flags |= T_STOP; ! 923: cache_it = 0; ! 924: } ! 925: if (I_S_START_CHAR (tp, c)) { ! 926: tp->t_flags &= ~ T_STOP; ! 927: ttstart(tp); ! 928: cache_it = 0; ! 929: } ! 930: #endif ! 931: } ! 932: ! 933: /* ! 934: * Cache received character. ! 935: */ ! 936: if (cache_it) { ! 937: in_silo.si_buf [in_silo.si_ix] = c; ! 938: ! 939: if (++ in_silo.si_ix >= sizeof (in_silo.si_buf)) ! 940: in_silo.si_ix = 0; ! 941: } ! 942: } ! 943: ! 944: /** ! 945: * ! 946: * void ! 947: * isbatch() -- raw input conversion routine ! 948: * ! 949: * Action: Enable the video display. ! 950: * Canonize the raw input silo. ! 951: * ! 952: * Notes: isbatch() was scheduled as a deferred process by isrint(). ! 953: */ ! 954: ! 955: static void ! 956: isbatch(tp) ! 957: register TTY * tp; ! 958: { ! 959: register int c; ! 960: static int lastc; ! 961: ! 962: /* ! 963: * Ensure video display is enabled. ! 964: */ ! 965: mm_von (); ! 966: isbusy = 0; ! 967: ! 968: /* ! 969: * Process all cached characters. ! 970: */ ! 971: ! 972: while (in_silo.si_ix != in_silo.si_ox) { ! 973: /* ! 974: * Get next cached char. ! 975: */ ! 976: c = in_silo.si_buf [in_silo.si_ox]; ! 977: ! 978: if (in_silo.si_ox >= sizeof (in_silo.si_buf) - 1) ! 979: in_silo.si_ox = 0; ! 980: else ! 981: in_silo.si_ox ++; ! 982: ! 983: if (islock == 0 || _IS_INTERRUPT_CHAR (tp,c) || ! 984: _IS_QUIT_CHAR (tp, c)) { ! 985: ttin (tp, c); ! 986: } else if ((c == 'b') && lastc == ESCAPE_CHAR) { ! 987: islock = 0; ! 988: ttin (tp, lastc); ! 989: ttin (tp, c); ! 990: } else if ((c == 'c') && lastc == ESCAPE_CHAR) { ! 991: ttin (tp, lastc); ! 992: ttin (tp, c); ! 993: } else ! 994: putchar ('\a'); ! 995: lastc = c; ! 996: } ! 997: } ! 998: ! 999: /* ! 1000: * update the keyboard status LEDS. ! 1001: * we chose the shift/lock key positions so this would be easy. ! 1002: * this flavor of routine is called while processing a system call on ! 1003: * behalf of the user. ! 1004: */ ! 1005: updleds() ! 1006: { ! 1007: if (!xlate) ! 1008: kb_cmd2(K_LED_CMD, X11led); ! 1009: else ! 1010: kb_cmd2(K_LED_CMD, (shift >> 1) & 0x7); ! 1011: } ! 1012: ! 1013: /* ! 1014: * same as above, but callable from interrupt routines and other places ! 1015: * which cannot sleep() waiting for the state machine to go idle. ! 1016: */ ! 1017: updleds2() ! 1018: { ! 1019: register int timeout; ! 1020: register int s; ! 1021: ! 1022: timeout = KBTIMEOUT; ! 1023: s = sphi(); ! 1024: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL)) ! 1025: ; ! 1026: kbstate = KB_DOUBLE_1; ! 1027: ! 1028: if (!xlate) cmd2 = X11led; ! 1029: else cmd2 = (shift >> 1) & 0x7; ! 1030: prev_cmd = K_LED_CMD; ! 1031: outb(KBDATA, K_LED_CMD); ! 1032: spl(s); ! 1033: } ! 1034: ! 1035: /* ! 1036: * unlock the scroll in case an interrupt character is received ! 1037: */ ! 1038: kbunscroll() ! 1039: { ! 1040: shift &= ~(1 << scroll); ! 1041: updleds(); ! 1042: } ! 1043: ! 1044: /* ! 1045: * ship a single byte command to the keyboard ! 1046: */ ! 1047: kb_cmd(cmd) ! 1048: unsigned cmd; ! 1049: { ! 1050: register int timeout; ! 1051: register int s; ! 1052: ! 1053: s = sphi(); ! 1054: KBDEBUG2(" kb_cmd(%x)", cmd); ! 1055: while (kbstate != KB_IDLE) { ! 1056: #ifdef _I386 ! 1057: x_sleep(&kbstate, pritty, slpriSigLjmp, "nkbcmd"); ! 1058: #else ! 1059: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "nkbcmd"); ! 1060: #endif ! 1061: /* The nkb driver is waiting for a command to complete. */ ! 1062: } ! 1063: kbstate = KB_SINGLE; ! 1064: timeout = KBTIMEOUT; ! 1065: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL)) ! 1066: ; ! 1067: if (!timeout) ! 1068: printf("kb: command timeout\n"); ! 1069: else { ! 1070: outb(KBDATA, cmd); ! 1071: while (kbstate != KB_IDLE) { ! 1072: #ifdef _I386 ! 1073: x_sleep(&kbstate, pritty, slpriSigLjmp, "nkbcmd..."); ! 1074: #else ! 1075: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "nkbcmd..."); ! 1076: #endif ! 1077: /* The nkb driver is still waiting for a command to complete. */ ! 1078: } ! 1079: } ! 1080: spl(s); ! 1081: } ! 1082: ! 1083: /* ! 1084: * ship a two byte command to the keyboard ! 1085: */ ! 1086: kb_cmd2(cmd, arg) ! 1087: unsigned cmd, arg; ! 1088: { ! 1089: register int timeout; ! 1090: register int s; ! 1091: ! 1092: s = sphi(); ! 1093: KBDEBUG3(" kb_cmd2(%x, %x)", cmd, arg); ! 1094: while (kbstate != KB_IDLE) { ! 1095: #ifdef _I386 ! 1096: x_sleep(&kbstate, pritty, slpriSigLjmp, "nkbcmd2"); ! 1097: #else ! 1098: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "nkbcmd2"); ! 1099: #endif ! 1100: /* ! 1101: * The nkb driver is waiting for a ! 1102: * 2 byte command to complete. ! 1103: */ ! 1104: } ! 1105: kbstate = KB_DOUBLE_1; ! 1106: cmd2 = arg; ! 1107: prev_cmd = cmd; ! 1108: timeout = KBTIMEOUT; ! 1109: while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL)) ! 1110: ; ! 1111: if (!timeout) ! 1112: printf("kb: command timeout\n"); ! 1113: else { ! 1114: outb(KBDATA, cmd); ! 1115: while (kbstate != KB_IDLE) { ! 1116: #ifdef _I386 ! 1117: x_sleep(&kbstate, pritty, slpriSigLjmp, "nkbcmd2..."); ! 1118: #else ! 1119: v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "nkbcmd2..."); ! 1120: #endif ! 1121: /* ! 1122: * The nkb driver is still waiting for a ! 1123: * 2 byte command to complete. ! 1124: */ ! 1125: } ! 1126: } ! 1127: spl(s); ! 1128: } ! 1129: ! 1130: /* End of nkb.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.