Annotation of coherent/d/kernel/USRSRC/i8086/drv/nkb.c, revision 1.1.1.1

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