Annotation of coherent/b/kernel/io.386/nkb.c, revision 1.1.1.1

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 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.