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

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

unix.superglobalmegacorp.com

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