Annotation of coherent/d/PS2_KERNEL/io.386/vtnkb.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * User configurable AT keyboard/display driver.
                      3:  * 286/386 AT COHERENT
                      4:  */
                      5: #include <sys/coherent.h>
                      6: #ifdef _I386
                      7: #include <sys/reg.h>
                      8: #else
                      9: #include <sys/i8086.h>
                     10: #endif
                     11: #include <sys/con.h>
                     12: #include <errno.h>
                     13: #include <sys/stat.h>
                     14: #include <sys/tty.h>
                     15: #include <signal.h>
                     16: #include <sys/seg.h>
                     17: #include <sys/sched.h>
                     18: #include <sys/kb.h>
                     19: #include <sys/devices.h>
                     20: #include <sys/silo.h>
                     21: 
                     22: #include <sys/vt.h>
                     23: 
                     24: #define        ISVEC           1               /* Keyboard interrupt vector */
                     25: #define        DEBUG           0
                     26: 
                     27: #define        KBDEBUG(x)      T_CON(1,printf(x));     /* debugging output */
                     28: #define        KBDEBUG2(x,y)   T_CON(1,printf(x,y));   /* debugging output */
                     29: #define        KBDEBUG3(x,y,z) T_CON(1,printf(x,y,z)); /* debugging output */
                     30: 
                     31: /*
                     32:  * values for kbstate
                     33:  */
                     34: #define        KB_IDLE         0               /* nothing going on right now */
                     35: #define        KB_SINGLE       1               /* sent a single byte cmd to the kbd */
                     36: #define        KB_DOUBLE_1     2               /* sent 1st byte of 2-byte cmd to kbd */
                     37: #define        KB_DOUBLE_2     3               /* sent 2nd byte of 2-byte cmd to kbd */
                     38: 
                     39: /*
                     40:  * patchable params for non-standard keyboards
                     41:  */
                     42: int    KBDATA = 0x60;                  /* Keyboard data */
                     43: int    KBCTRL = 0x61;                  /* Keyboard control */
                     44: int    KBSTS_CMD = 0x64;               /* Keyboard status/command */
                     45: int    KBFLAG = 0x80;                  /* Keyboard reset flag */
                     46: int    KBBOOT = 1;                     /* 0: disallow reboot from keyboard */
                     47: int    KBTIMEOUT = 10000;              /* shouldn't need this much */
                     48: int    KBCMDBYTE = 0x05;               /* no translation */
                     49: 
                     50: /*
                     51:  * KBSTATUS bits
                     52:  */
                     53: #define        STS_OBUF_FULL   0x01            /* kbd output buffer full */
                     54: #define        STS_IBUF_FULL   0x02            /* kbd input buffer full */
                     55: #define        STS_SYSTEM      0x04
                     56: #define        STS_CMD_DATA    0x08            /* 1: command or status */
                     57: #define        STS_INHIBIT     0x10            /* 0: keyboard inhibited */
                     58: #define        STS_AUX_OBUF_FULL       0x20
                     59: #define        STS_TIMEOUT     0x40            /* general timeout */
                     60: #define        STS_PAR_ERR     0x80            /* parity error */
                     61: 
                     62: /*
                     63:  * The following are magic commands which read from or write to the
                     64:  * controller command byte. These get output to the KBSTS_CMD port.
                     65:  */
                     66: #define        C_READ_CMD      0x20            /* read controller command byte */
                     67: #define        C_WRITE_CMD     0x60            /* write controller command byte */
                     68: #define        C_TRANSLATE     0x40            /* translate enable bit in cmd byte */
                     69: 
                     70: /*
                     71:  * Globals:
                     72:  * The 286 keyboard mapping table is too large to fit into kernel data space,
                     73:  * so we need to allocate a segment to it.  386 is easy.
                     74:  * The function keys tend to be small and tend to change substantially
                     75:  * more often than the mapping table, so we keep them in the kernel data space.
                     76:  */
                     77: static unsigned shift;                 /* state of all shift/lock keys */
                     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: #ifdef _I386
                     85: static KBTBL   kb[MAX_KEYS];           /* keyboard table */
                     86: #else
                     87: static SEG     *kbsegp;                /* keyboard table segment */
                     88: #endif
                     89: 
                     90: /*
                     91:  * State variables.
                     92:  */
                     93: int            islock;                 /* Keyboard locked flag */
                     94: int            isbusy;                 /* Raw input conversion busy */
                     95: static char    table_loaded;           /* true == keyboard table resident */
                     96: static char    fk_loaded;              /* true == function keys resident */
                     97: static int     kbstate = KB_IDLE;      /* current keyboard state */
                     98: 
                     99: /*
                    100:  * Functions.
                    101:  */
                    102: int            isrint();
                    103: int            istime();
                    104: void           isbatch();
                    105: int            mmstart();
                    106: int            isopen();
                    107: int            isclose();
                    108: int            isread();
                    109: int            mmwrite();
                    110: int            isioctl();
                    111: void           mmwatch();
                    112: int            isload();
                    113: int            isuload();
                    114: int            ispoll();
                    115: int            nulldev();
                    116: int            nonedev();
                    117: int            updleds();
                    118: 
                    119: static int     isioctl0();
                    120: 
                    121: /*
                    122:  * Configuration table.
                    123:  */
                    124: CON iscon ={
                    125:        DFCHR|DFPOL,                    /* Flags */
                    126:        KB_MAJOR,                       /* Major index */
                    127:        isopen,                         /* Open */
                    128:        isclose,                        /* Close */
                    129:        nulldev,                        /* Block */
                    130:        isread,                         /* Read */
                    131:        mmwrite,                        /* Write */
                    132: #ifdef _I386
                    133:        isioctl0,                       /* Ioctl */
                    134: #else
                    135:        isioctl,                        /* Ioctl */
                    136: #endif
                    137:        nulldev,                        /* Powerfail */
                    138:        mmwatch,                        /* Timeout */
                    139:        isload,                         /* Load */
                    140:        isuload,                        /* Unload */
                    141:        ispoll                          /* Poll */
                    142: };
                    143: 
                    144: /*
                    145: ==============================================================================
                    146: ==============================================================================
                    147: */
                    148: /* constants for vtdata[] */
                    149: #define VT_VGAPORT     0x3D4
                    150: #define VT_MONOPORT    0x3B4
                    151: 
                    152: #ifdef _I386
                    153: #define VT_MONOBASE    SEG_VIDEOa
                    154: #define VT_VGABASE     SEG_VIDEOb
                    155: #else
                    156: #define VT_MONOBASE    0xB000
                    157: #define VT_VGABASE     0xB800
                    158: #endif
                    159: 
                    160: /*
                    161:        Patchable table entrys,
                    162:        we go indirect in order to produce a label which can be addressed
                    163: */
                    164: HWentry        VTVGA =         { 4, 0, VT_VGAPORT, { 0, VT_VGABASE }, { 25, 80 } };
                    165: HWentry        VTMONO =        { 4, 0, VT_MONOPORT, { 0, VT_MONOBASE }, { 25, 80 } };
                    166: 
                    167: HWentry        *vtHWtable[] = {
                    168:        VTVGA,          /* VGA followed by MONO is compatible to DOS */
                    169:        VTMONO,
                    170:        0               /* MUST STAY AS LAST ELEMENT !!! */
                    171: };
                    172: 
                    173: extern int     mminit();
                    174: static VTDATA  const_vtdata    = {
                    175:        mminit, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 23, 24, 0, 0, 0, 23, 0, 0, 1
                    176: };
                    177: 
                    178: /* later this should be dynamic */
                    179: VTDATA *vtconsole, **vtdata;
                    180: 
                    181: int    vtcount, vtmax;
                    182: extern int     vtactive;
                    183: int    vt_verbose = { 0 };
                    184: int    vt_opened = { 0 };
                    185: 
                    186: /* Terminal structure. */
                    187: TTY    **vttty;
                    188: 
                    189: /*
                    190: ==============================================================================
                    191: ==============================================================================
                    192: */
                    193: 
                    194: static silo_t in_silo;
                    195: 
                    196: /*
                    197:  * Given hw pointer for one of four types of adapters, see if
                    198:  * device is present by write/readback of video memory.
                    199:  *
                    200:  * return 1 if present, else 0
                    201:  */
                    202: int
                    203: hwpresent( hw )
                    204: HWentry *hw;
                    205: {
                    206:        int     save, present = 1;
                    207: 
                    208:        PRINTV( "hwpresent: %x:%x",
                    209:                hw->vidmemory.seg, hw->vidmemory.off );
                    210:        save = ffword( hw->vidmemory.off, hw->vidmemory.seg );
                    211: 
                    212:        sfword(  hw->vidmemory.off, hw->vidmemory.seg, 0xAA55 );
                    213:        if( ffword( hw->vidmemory.off, hw->vidmemory.seg ) != 0xAA55 )
                    214:                present = 0;
                    215: 
                    216:        sfword(  hw->vidmemory.off, hw->vidmemory.seg, 0x55AA );
                    217:        if( ffword( hw->vidmemory.off, hw->vidmemory.seg ) != 0x55AA )
                    218:                present = 0;
                    219: 
                    220:        sfword(  hw->vidmemory.off, hw->vidmemory.seg, save );
                    221:        PRINTV( "%s present\n", present ? "" : " NOT" );
                    222:        return present;
                    223: }
                    224: 
                    225: /*
                    226:  * Load entry point.
                    227:  */
                    228: isload()
                    229: {
                    230:        register        int i;
                    231:        register        HWentry **hw;
                    232:        register        VTDATA *vp;
                    233: 
                    234:        PRINTV("vtload:\n");
                    235:        fk_loaded = 0;
                    236:        table_loaded = 0;
                    237:        kbstate = KB_IDLE;
                    238: 
                    239:        /* figure out what our current max is */
                    240:        for( vtmax = 0, hw = vtHWtable; *hw; ++hw ) {
                    241:                vtmax += (*hw)->count;
                    242:                (*hw)->found = 0;       /* assume non-exist */
                    243:        }
                    244:        PRINTV( "vtload: %d screens possible\n", vtmax );
                    245: 
                    246:        vtdata = (VTDATA **) kalloc( vtmax * sizeof( *vtdata ) );
                    247:        if( vtdata == NULL ) {
                    248:                printf( "vtload: unable to obtain vtdata[%d]\n", vtmax );
                    249:                u.u_error = -1;
                    250:                return;
                    251:        }
                    252:        PRINTV( "vtload: obtained vtdata[%d] @%x\n", vtmax, vtdata );
                    253: 
                    254:        vttty = (TTY **) kalloc( vtmax * sizeof( *vttty ) );
                    255:        if( vttty == NULL ) {
                    256:                printf( "vtload: unable to obtain vttty[%d]\n", vtmax );
                    257:                u.u_error = -1;
                    258:                return;
                    259:        }
                    260:        PRINTV( "vtload: obtained vttty[%d] @%x\n", vtmax, vttty );
                    261: 
                    262:        /* determine which video adaptors are present */
                    263:        for( vtcount = 0, hw = vtHWtable; *hw; ++hw ) {
                    264: /* suppress board sensing since it seems to confuse some equipment */
                    265: #if 0
                    266:                if( !hwpresent(*hw) )
                    267:                        continue;
                    268: #endif
                    269: 
                    270:                /* remember our logical start */
                    271:                (*hw)->start = vtcount;
                    272:                PRINTV( ", start %d\n", vtcount );
                    273: 
                    274:                /* allocate the necessary memory */
                    275:                for ( i = 0; i < (*hw)->count; ++i ) {
                    276:                        vp = vtdata[vtcount] = kalloc( sizeof(VTDATA) );
                    277:                        PRINTV( "     vtdata[%d] = @%x\n", vtcount, vp );
                    278:                        if( vp == NULL || !VTttyinit(vtcount) ) {
                    279:                                printf("not enough memory for VTDATA\n" );
                    280:                                break;
                    281:                        }
                    282: 
                    283:                        /* fill in appropriately */
                    284:                        *vp = const_vtdata;
                    285:                        vp->vmm_port = (*hw)->port;
                    286:                        vp->vmm_vseg = (*hw)->vidmemory.seg;
                    287:                        vp->vmm_voff = (*hw)->vidmemory.off;
                    288: 
                    289:                        vp->vt_ind = vtcount;
                    290:                        vtdatainit(vp);
                    291:                        if (i == 0 ) {
                    292:                                vp->vmm_visible = VNKB_TRUE;
                    293:                                vp->vmm_seg = vp->vmm_vseg;
                    294:                                vp->vmm_off = vp->vmm_voff;
                    295:                                updscreen(vtcount);
                    296:                        }
                    297:                        (*hw)->found++;
                    298:                        vtcount++;
                    299:                }
                    300:        }
                    301: 
                    302:        /*
                    303:         * initialize vtconsole
                    304:         */
                    305:        vtconsole = vtdata[vtactive = 0];
                    306:        vtconsole->vmm_invis = 0;               /* vtconsole cursor visible */
                    307: 
                    308:        /*
                    309:         * Seize keyboard interrupt.
                    310:         */
                    311: #ifdef _I386
                    312:        setivec(ISVEC, isrint);
                    313: #else
                    314: #if    VT_MAJOR == KB_MAJOR
                    315:        setivec(1, isrint);
                    316: #else
                    317:        /*
                    318:         * Map table and vector to us
                    319:         */
                    320:        i = sphi();
                    321:        PRINTV( "VTload: unload old vector\n" );
                    322:        kcall( Kclrivec, 1 );
                    323:        setivec(1, isrint);
                    324:        spl( i );
                    325: #endif
                    326: #endif /* _I386 */
                    327: 
                    328:        /*
                    329:         * Enable mmwatch() invocation every second.
                    330:         */
                    331:        drvl[VT_MAJOR].d_time = 1;
                    332: 
                    333:        /*
                    334:         * Initialize video display.
                    335:         */
                    336:        for ( i = 0; i < vtcount; ++i )
                    337:                mmstart( vttty[i] );
                    338: 
                    339: 
                    340: #ifndef        _I386
                    341:        /*
                    342:         * Allocate a segment to store the in-core keyboard table.
                    343:         * This would be a lot more convenient in kernel data space,
                    344:         * but small model COHERENT doesn't have that luxury.
                    345:         */
                    346:        kbsegp = salloc((fsize_t)MAX_TABLE_SIZE, SFSYST|SFNSWP|SFHIGH);
                    347:        if (kbsegp == (SEG *)0)
                    348:                printf("kb: unable to allocate keyboard table segment\n");
                    349:        KBDEBUG("Exiting kbload()\n");
                    350: #endif
                    351:        fklength = 0;
                    352: }
                    353: 
                    354: /*
                    355:  * Unload entry point.
                    356:  */
                    357: isuload()
                    358: {
                    359:        register int i;
                    360:        register level = sphi();
                    361: 
                    362:        clrivec(ISVEC);
                    363: #ifndef        _I386
                    364: #if    VT_MAJOR != KB_MAJOR
                    365:        kcall( Ksetivec, ISVEC, &Kisrint );
                    366: #endif
                    367: #endif
                    368:        spl( level );
                    369: 
                    370:        /* Restore pointers to original state. */
                    371:        vtconsole = vtdata[0];
                    372:        vtconsole->vmm_invis = 0;
                    373:        vtconsole->vmm_visible = VNKB_TRUE;
                    374: 
                    375:        if( vt_opened )
                    376:                printf( "VTclose with %d open screens\n", vt_opened );
                    377:        if( kbstate != KB_IDLE )
                    378:                printf("kb: keyboard busy during unload\n");
                    379: #ifndef        _I386
                    380:        if (kbsegp != (SEG *)0) {
                    381:                table_loaded = 0;
                    382:                sfree(kbsegp);
                    383:        }
                    384: #endif
                    385: 
                    386: #ifndef        _I386
                    387:        for( i = 0; i < vtcount; ++i ) {
                    388:                PRINTV( "VTuload: free far %x:%x, tty %x\n",
                    389:                        vttty[i]->t_buffer->s_faddr, vttty[i] );
                    390:                sfree( vttty[i]->t_buffer );
                    391:                kfree( vttty[i] );
                    392:                sfree( vtdata[i].vt_buffer );
                    393:        }
                    394: #endif
                    395: }
                    396: 
                    397: /*
                    398:  * Open routine.
                    399:  */
                    400: isopen(dev, mode)
                    401: dev_t dev;
                    402: unsigned int mode;
                    403: {
                    404:        register int s;
                    405:        register TTY *tp;
                    406:        int     index = vtindex(dev);
                    407: 
                    408:        PRINTV("isopen: %x\n", dev);
                    409:        if (index < 0 || index >= vtcount) {
                    410:                u.u_error = ENXIO;
                    411:                return;
                    412:        }
                    413: 
                    414:        tp = vttty[index];
                    415:        if ((tp->t_flags&T_EXCL) != 0 && !super()) {
                    416:                u.u_error = ENODEV;
                    417:                return;
                    418:        }
                    419:        ttsetgrp(tp, dev, mode);
                    420: 
                    421:        s = sphi();
                    422:        if (tp->t_open++ == 0) {
                    423:                tp->t_flags = T_CARR;   /* indicate "carrier" */
                    424:                ttopen(tp);
                    425:        }
                    426:        spl(s);
                    427: #if 0
                    428:        updleds();                      /* update keyboard status LEDS */
                    429: #endif
                    430: }
                    431: 
                    432: 
                    433: void isvtswitch();
                    434: 
                    435: /*
                    436:  * Close a tty.
                    437:  */
                    438: isclose(dev)
                    439: {
                    440:        register int s;
                    441:        int     index = vtindex(dev);
                    442:        register TTY *tp = vttty[index];
                    443: 
                    444: #if 0
                    445:        s = sphi();
                    446:        if (--tp->t_open == 0) {
                    447:                ttclose(tp);
                    448:                spl(s);
                    449:                if( index == vtactive )
                    450:                        isvtswitch( VTKEY_HOME );
                    451:        } else
                    452:                spl(s);
                    453: #else
                    454:        if (--tp->t_open == 0)
                    455:                ttclose(tp);
                    456: #endif
                    457: }
                    458: 
                    459: /*
                    460:  * Read routine.
                    461:  */
                    462: isread(dev, iop)
                    463: dev_t dev;
                    464: IO *iop;
                    465: {
                    466:        int     index = vtindex(dev);
                    467:        register TTY *tp = vttty[index];
                    468: 
                    469:        ttread(tp, iop, 0);
                    470:        if (tp->t_oq.cq_cc)
                    471:                mmtime(tp);
                    472: }
                    473: 
                    474: /*
                    475:  * Ioctl routine.
                    476:  * nb: archaic TIOCSHIFT and TIOCCSHIFT no longer needed/supported.
                    477:  */
                    478: #ifdef _I386
                    479: isioctl0(dev, com, vec)
                    480: dev_t dev;
                    481: struct sgttyb *vec;
                    482: {
                    483:        tioc286(dev, com, vec, isioctl);
                    484: }
                    485: #endif
                    486: 
                    487: isioctl(dev, com, vec)
                    488: dev_t dev;
                    489: struct sgttyb *vec;
                    490: {
                    491:        register int s;
                    492: 
                    493:        switch (com) {
                    494:        case TIOCSETF:
                    495:        case TIOCGETF:
                    496:                isfunction(com, (char *)vec);
                    497:                break;
                    498:        case TIOCSETKBT:
                    499:                issettable(vec);
                    500:                break;
                    501:        case TIOCGETKBT:
                    502:                isgettable(vec);
                    503:                break;
                    504:        default:                                /* pass to TTY driver */
                    505:                s = sphi();
                    506:                ttioctl(vttty[vtindex(dev)], com, vec);
                    507:                spl(s);
                    508:                break;
                    509:        }
                    510: }
                    511: 
                    512: /*
                    513:  * Set the in-core keyboard mapping table.
                    514:  * The table is sorted by scan code prior to calling ioctl().
                    515:  * All unused table entries (holes in the scan code map) have
                    516:  * a zero for the k_key field.
                    517:  * This makes key lookup at interrupt time fast by using the scan code
                    518:  * as an index into the table.
                    519:  */
                    520: issettable(vec)
                    521: char   *vec;
                    522: {
                    523:        register unsigned i;
                    524:        register int s;
                    525:        int timeout;
                    526:        static  KBTBL   this_key;       /* current key from kbd table */
                    527:        unsigned int cmd_byte;
                    528: #ifndef _I386
                    529:        register faddr_t faddr;         /* address of keyboard table */
                    530: #endif
                    531: 
                    532:        PRINTV(" TIOCSETKBT");
                    533:        kb_cmd2(K_SCANCODE_CMD, 3);             /* select set 3 */
                    534:        kb_cmd(K_ALL_TMB_CMD);                  /* default: TMB for all keys */
                    535: #ifndef _I386
                    536:        faddr = kbsegp->s_faddr;
                    537: #endif
                    538:        for (i = 0; i < MAX_KEYS; ++i) {
                    539:                ukcopy(vec, &this_key, sizeof(this_key));
                    540: #ifdef _I386
                    541:                kb[i] = this_key;               /* store away */
                    542: #else
                    543:                kfcopy(&this_key, faddr, sizeof(this_key));
                    544:                faddr += sizeof(this_key);
                    545: #endif
                    546:                vec += sizeof(this_key);
                    547:                if (this_key.k_key != i && this_key.k_key != 0) {
                    548:                        printf("kb: incorrect or unsorted table entry %d\n", i);
                    549: #ifdef _I386
                    550:                        u.u_error = EINVAL;
                    551: #else
                    552:                        u.u_error = EBADFMT;
                    553: #endif
                    554:                        return;
                    555:                }
                    556:                if (this_key.k_key != i)
                    557:                        continue;               /* no key */
                    558:                switch (this_key.k_flags&TMODE) {
                    559:                case T:                         /* typematic */
                    560:                        kb_cmd2(K_KEY_T_CMD, i);
                    561:                        break;
                    562:                case M:                         /* make only */
                    563:                        kb_cmd2(K_KEY_M_CMD, i);
                    564:                        break;
                    565:                case MB:                        /* make/break */
                    566:                        kb_cmd2(K_KEY_MB_CMD, i);
                    567:                        break;
                    568:                case TMB:                       /* typematic make/break */
                    569:                        break;                  /* this is the default */
                    570:                default:
                    571:                        printf("kb: bad key mode\n");
                    572:                }
                    573:        }
                    574:        updleds();
                    575:        kb_cmd2(K_SCANCODE_CMD, 3);             /* select set 3 */
                    576:        kb_cmd(K_ENABLE_CMD);                   /* start scanning */
                    577:        /*
                    578:         * The following code disables translation from the on-board
                    579:         * keyboard/aux controller. Without disabling translation, the
                    580:         * received scan codes still look like code set 1 codes even
                    581:         * though we put the keyboard controller in scan code set 3.
                    582:         * Yes, this is progress....
                    583:         */
                    584: #if 0
                    585:        while (inb(KBSTS_CMD) & STS_IBUF_FULL)
                    586:                ;
                    587:        outb(KBSTS_CMD, C_READ_CMD);            /* read controller cmd byte */
                    588:        while (!(inb(KBSTS_CMD) & STS_OBUF_FULL))
                    589:                ;
                    590:        cmd_byte = inb(KBDATA);
                    591:        KBDEBUG2(" cmd_byte=%x", cmd_byte);
                    592: #endif
                    593:        timeout = KBTIMEOUT;
                    594:        s = sphi();
                    595:        while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
                    596:                ;
                    597:        outb(KBSTS_CMD, C_WRITE_CMD);           /* write controller cmd byte */
                    598:        for (timeout = 50; --timeout > 0;)
                    599:                ;
                    600:        timeout = KBTIMEOUT;
                    601:        while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
                    602:                ;
                    603:        outb(KBDATA, KBCMDBYTE);                 /* turn off translation */     
                    604:        timeout = KBTIMEOUT;
                    605:        while ((inb(KBSTS_CMD) & STS_IBUF_FULL) && --timeout > 0)
                    606:                ;
                    607:        spl(s);
                    608: #if DEBUG || 1
                    609:        kb_cmd2(K_SCANCODE_CMD, 0);             /* query s.c. mode */
                    610: #endif
                    611:        ++table_loaded;
                    612:        PRINTV("... TIOCSETKBT\n");
                    613: }
                    614: 
                    615: /*
                    616:  * Get the in-core keyboard mapping table and pass it to the user.
                    617:  */
                    618: isgettable(vec)
                    619: char   *vec;
                    620: {
                    621: #ifdef _I386
                    622:        KBDEBUG(" TIOCGETKBT");
                    623:        kucopy(kb, vec, sizeof(kb));
                    624: #else
                    625:        register unsigned i;
                    626:        register faddr_t faddr;         /* address of keyboard table */
                    627:        static  KBTBL   this_key;       /* current key from kbd table */
                    628: 
                    629:        KBDEBUG(" TIOCGETKBT");
                    630:        faddr = kbsegp->s_faddr;
                    631:        for (i = 0; i < MAX_KEYS; ++i) {
                    632:                fkcopy(faddr, &this_key, sizeof(this_key));
                    633:                kucopy(&this_key, vec, sizeof(this_key));
                    634:                faddr += sizeof(this_key);
                    635:                vec += sizeof(this_key);
                    636:        }
                    637: #endif
                    638: }
                    639: 
                    640: 
                    641: /*
                    642:  * Set and receive the function keys.
                    643:  */
                    644: isfunction(c, v)
                    645: int c;
                    646: FNKEY *v;
                    647: {
                    648:        register unsigned char *cp;
                    649:        register unsigned i;
                    650:        unsigned char   numkeys = 0;
                    651: 
                    652:        if (c == TIOCGETF) {
                    653:                KBDEBUG(" TIOCGETF");
                    654:                if (!fk_loaded)
                    655:                        u.u_error = EINVAL;
                    656:                else
                    657:                        kucopy(fnkeys, v, fklength);    /* copy ours to user */
                    658:        } else { /* TIOCSETF */
                    659:                /*
                    660:                 * If we had a previous function key arena, free it up.
                    661:                 * Since we don't know how large the function key arena will
                    662:                 * be, we must size it in the user data space prior to
                    663:                 * (re)kalloc()'ing it. This is ugly, but a helluva lot better
                    664:                 * than the old driver which used a hard coded limit of 150!
                    665:                 */
                    666:                KBDEBUG(" TIOCSETF");
                    667:                fk_loaded = 0;
                    668:                if (fnkeys != (FNKEY *)0)
                    669:                        kfree(fnkeys);          /* free old arena */
                    670:                if (funkeyp != NULL)
                    671:                        kfree(funkeyp);         /* free old ptr array */
                    672:                ukcopy(&v->k_nfkeys, &numkeys, sizeof(numkeys));
                    673:                fklength = sizeof(FNKEY);
                    674:                cp = v->k_fnval;
                    675:                for (i = 0; i < numkeys; i++) {
                    676:                        do {
                    677:                                ++fklength;
                    678:                        } while (getubd(cp++) != DELIM);
                    679:                }
                    680:                fnkeys = (FNKEY *)kalloc(fklength);
                    681:                funkeyp = (unsigned char **)kalloc(numkeys * sizeof(char *));
                    682:                if (fnkeys == (FNKEY *)0 || funkeyp == NULL) {
                    683:                        if (fnkeys != (FNKEY *)0) {
                    684:                                kfree(fnkeys);
                    685:                                fnkeys = 0;
                    686:                        }
                    687:                        if (funkeyp != NULL) {
                    688:                                kfree(funkeyp);
                    689:                                funkeyp = 0;
                    690:                        }
                    691:                        u.u_error = ENOMEM;
                    692:                        return;
                    693:                }
                    694:                cp = fnkeys->k_fnval;                   /* point to Fn ... */
                    695:                v = v->k_fnval;                         /* ... key arena */
                    696:                for (i = 0; i < numkeys; i++) {
                    697:                        funkeyp[i] = cp;                   /* save pointer */
                    698:                        while ((*cp++ = getubd(v++)) != DELIM)  /* copy key */
                    699:                                ;
                    700:                }
                    701:                fnkeys->k_nfkeys = numkeys;
                    702:                fk_loaded = 1;
                    703:        }
                    704: }
                    705: 
                    706: 
                    707: /*
                    708:  * Poll routine.
                    709:  */
                    710: ispoll(dev, ev, msec)
                    711: dev_t dev;
                    712: int ev;
                    713: int msec;
                    714: {
                    715:        register TTY *tp = vttty[vtindex(dev)];
                    716: 
                    717:        return ttpoll(tp, ev, msec);
                    718: }
                    719: 
                    720: /*
                    721:  * Receive interrupt.
                    722:  */
                    723: isrint()
                    724: {
                    725:        register unsigned c;
                    726:        register unsigned r;
                    727:        static  char keyup;
                    728: 
                    729:        /*
                    730:         * Schedule raw input handler if not already active.
                    731:         */
                    732:        if (!isbusy) {
                    733:                defer(isbatch,  vttty[vtactive]);
                    734:                isbusy = 1;
                    735:        }
                    736: 
                    737:        /*
                    738:         * Pull character from the data
                    739:         * port. Pulse the KBFLAG in the control
                    740:         * port to reset the data buffer.
                    741:         */
                    742:        r = inb(KBDATA) & 0xFF;
                    743:        c = inb(KBCTRL);
                    744:        outb(KBCTRL, c|KBFLAG);
                    745:        outb(KBCTRL, c);
                    746: 
                    747:        /*
                    748:         * check returned value from keyboard to see if it's a command
                    749:         * or status back to us. If not, it we assume that it's a key code.
                    750:         */
                    751:        KBDEBUG2("\nintr(%x) ", r);
                    752:        switch (r) {
                    753:        case K_BREAK:
                    754:                keyup = 1;                      /* key going up */
                    755:                break;
                    756:        case K_ECHO_R:
                    757:        case K_BAT_OK:
                    758:                break;                          /* very nice, but ignored */
                    759:        case K_BAT_BAD:
                    760:                printf("kb: keyboard BAT failed\n");
                    761:                break;
                    762:        case K_RESEND:
                    763:                KBDEBUG("\nkb: request to resend command\n");
                    764:                outb(KBDATA, prev_cmd);
                    765:                break;
                    766:        case K_OVERRUN_23:
                    767:                printf("kb: keyboard buffer overrun\n");
                    768:                break;
                    769:        case K_ACK:
                    770:                /*
                    771:                 * we received an ACKnowledgement from the keyboard.
                    772:                 * advance the state machine and continue.
                    773:                 */
                    774:                KBDEBUG(" ACK ");
                    775:                switch (kbstate) {
                    776:                case KB_IDLE:                   /* shouldn't happen */
                    777:                        printf("vtnkb: ACK while idle ");
                    778:                        break;
                    779:                case KB_SINGLE:                 /* done with 1-byte command */
                    780:                case KB_DOUBLE_2:               /* done w/ 2nd of 2-byte cmd */
                    781:                        kbstate = KB_IDLE;
                    782:                        wakeup(&kbstate);
                    783:                        break;
                    784:                case KB_DOUBLE_1:
                    785:                        kbstate = KB_DOUBLE_2;
                    786:                        outb(KBDATA, cmd2);
                    787:                        break;
                    788:                default:
                    789:                        printf("kb: bad kbstate %d\n", kbstate);
                    790:                        break;
                    791:                }
                    792:                break;
                    793:        default:
                    794:                process_key(r, keyup);
                    795:                keyup = 0;
                    796:        }
                    797: }
                    798: 
                    799: /*
                    800:  * Process a key given its scan code and direction.
                    801:  * 
                    802:  * In this table driven version of the keyboard driver, we trade off the
                    803:  * code complexity associated with all the black magic that used to be
                    804:  * performed on a per-key basis with the increased memory requirements
                    805:  * associated with the table driven approach.
                    806:  */
                    807: process_key(key, up)
                    808: unsigned key;
                    809: int     up;
                    810: {
                    811:        register unsigned char *cp;
                    812:        KBTBL   key_vals;                       /* table values for this key */
                    813:        unsigned val;
                    814:        unsigned char flags;
                    815:        register TTY *tp = vttty[vtactive];
                    816:        VTDATA *vp = vtdata[vtactive];
                    817: 
                    818:        KBDEBUG3(" proc(%x %s)", key, (up ? "up" : "down"));
                    819:        if (!table_loaded)
                    820:                return;                         /* throw away key */
                    821: #ifdef _I386
                    822:        key_vals = kb[key];
                    823: #else
                    824:        fkcopy(kbsegp->s_faddr + (key * sizeof(KBTBL)),
                    825:                &key_vals, sizeof(key_vals));
                    826: #endif
                    827:        if (key_vals.k_key != key)              /* empty entry */
                    828:                return;
                    829:        flags = key_vals.k_flags;
                    830: 
                    831:        if (flags & S) {                        /* some shift/lock key ? */
                    832:                switch (key_vals.k_val[BASE]) {
                    833:                case caps:
                    834:                case num:
                    835:                        if (!up) {
                    836:                                shift ^= (1 << key_vals.k_val[BASE]);
                    837:                                updleds2();
                    838:                        }
                    839:                        break;
                    840:                case scroll:
                    841:                        if (!up) {
                    842:                                shift ^= (1 << key_vals.k_val[BASE]);
                    843:                                updleds2();
                    844:                                if (!(tp->t_sgttyb.sg_flags&RAWIN)) {
                    845:                                        if (tp->t_flags & T_STOP) {
                    846:                                                isin(tp->t_tchars.t_startc);
                    847:                                        } else {
                    848:                                                isin(tp->t_tchars.t_stopc);
                    849:                                        }
                    850:                                }
                    851:                        }
                    852:                        break;
                    853:                default:
                    854:                        if (up)
                    855:                                shift &= ~(1 << key_vals.k_val[BASE]);
                    856:                        else
                    857:                                shift |= (1 << key_vals.k_val[BASE]);
                    858:                        break;
                    859:                }
                    860:                /*
                    861:                 * Calculate the shift index based upon the state of
                    862:                 * the shift and lock keys.
                    863:                 */
                    864:                sh_index = BASE;                /* default condition */
                    865:                if (shift & (1 << altgr))
                    866:                        sh_index = ALT_GR;
                    867:                else {
                    868:                        if (shift & ((1 << lalt)|(1 << ralt)))
                    869:                                sh_index |= ALT;
                    870:                        if (shift & ((1 << lctrl)|(1 << rctrl)))
                    871:                                sh_index |= CTRL;
                    872:                        if (shift & ((1 << lshift)|(1 << rshift)))
                    873:                                sh_index |= SHIFT;
                    874:                }
                    875:                T_CON(2, printf("shift=%x sh_index=%d\n", shift, sh_index));
                    876:                return;
                    877:        } /* if (flags & S) */
                    878: 
                    879:        /*
                    880:         * If the key has no value in the current
                    881:         * shift state, the key is just tossed away.
                    882:         */
                    883:        if (up || key_vals.k_val[sh_index] == none)
                    884:                return;
                    885: 
                    886:        if (((flags & C) && (shift & (1 << caps)))
                    887:           || ((flags & N) && (shift & (1 << num))))
                    888:                val = key_vals.k_val[sh_index^SHIFT];
                    889:        else
                    890:                val = key_vals.k_val[sh_index];
                    891: 
                    892:        /*
                    893:         * Check for function key or special key implemented as
                    894:         * a function key (reboot == f0, tab and back-tab, etc).
                    895:         */
                    896:        if (flags & F) {
                    897:                PRINTV( "<{F%d}>", val );
                    898:                if (VTKEY(val)) {
                    899:                        T_CON(4,
                    900:                          printf( "<{F%d !!}>\b\b\b\b\b\b\b\b\b\b", val));
                    901:                        defer( isvtswitch, val );
                    902:                        return;
                    903:                }
                    904:                /* If the tty is not open, ignore it */
                    905:                if( !tp->t_open )
                    906:                        return;
                    907:                if (val == 0 && !up && KBBOOT)
                    908:                        boot();
                    909:                if (!fk_loaded || val >= fnkeys->k_nfkeys)
                    910:                        return;
                    911:                if ((cp = funkeyp[val]) == NULL) /* has a value? */
                    912:                        return;
                    913:                while (*cp != DELIM)
                    914:                        isin(*cp++);            /* queue up Fn key value */
                    915:                return;
                    916:        }
                    917: 
                    918:        /*
                    919:         * Normal key processing.
                    920:         */
                    921:        /* If the tty is not open, ignore it */
                    922:        if( tp->t_open )
                    923:                isin(val);               /* send the char */
                    924: }
                    925: 
                    926: /**
                    927:  *
                    928:  * void
                    929:  * ismmfunc(c) -- process keyboard related output escape sequences
                    930:  * char c;
                    931:  */
                    932: void
                    933: ismmfunc(c)
                    934: register int c;
                    935: {
                    936: 
                    937:        switch (c) {
                    938:        case 't':       /* Enter numlock */
                    939:                shift |= (1 << num);
                    940:                updleds();                      /* update LED status */
                    941:                break;
                    942:        case 'u':       /* Leave numlock */
                    943:                shift &= ~(1 << num);
                    944:                updleds();                      /* update LED status */
                    945:                break;
                    946:        case '=':                       /* Enter alternate keypad -- ignored */
                    947:        case '>':                       /* Exit alternate keypad -- ignored */
                    948:                break;
                    949:        case 'c':       /* Reset terminal */
                    950:                islock = 0;
                    951:                break;
                    952:        }
                    953: }
                    954: 
                    955: /**
                    956:  *
                    957:  * void
                    958:  * isin(c)     -- append character to raw input silo
                    959:  * char c;
                    960:  */
                    961: static
                    962: isin(c)
                    963: register int c;
                    964: {
                    965:        int cache_it = 1;
                    966:        TTY * tp = vttty[vtactive];
                    967:        void ttstart();
                    968: 
                    969:        /*
                    970:         * If using software incoming flow control, process and
                    971:         * discard t_stopc and t_startc.
                    972:         */
                    973:        if (!ISRIN) {
                    974:                if (ISSTOP) {
                    975:                        if ((tp->t_flags&T_STOP) == 0)
                    976:                                tp->t_flags |= T_STOP;
                    977:                        cache_it = 0;
                    978:                }
                    979:                if (ISSTART) {
                    980:                        tp->t_flags &= ~T_STOP;
                    981:                        defer(ttstart, tp);
                    982:                        cache_it = 0;
                    983:                }
                    984:        }
                    985: 
                    986:        /*
                    987:         * Cache received character.
                    988:         */
                    989:        if (cache_it) {
                    990:                in_silo.si_buf[ in_silo.si_ix ] = c;
                    991: 
                    992:                if (++in_silo.si_ix >= sizeof(in_silo.si_buf))
                    993:                        in_silo.si_ix = 0;
                    994:        }
                    995: }
                    996: 
                    997: /**
                    998:  *
                    999:  * void
                   1000:  * isbatch()   -- raw input conversion routine
                   1001:  *
                   1002:  *     Action: Enable the video display.
                   1003:  *             Canonize the raw input silo.
                   1004:  *
                   1005:  *     Notes:  isbatch() was scheduled as a deferred process by isrint().
                   1006:  */
                   1007: static void
                   1008: isbatch(tp)
                   1009: register TTY * tp;
                   1010: {
                   1011:        register int c;
                   1012:        static int lastc;
                   1013:        VTDATA *vp = tp->t_ddp;
                   1014: 
                   1015:        /*
                   1016:         * Ensure video display is enabled.
                   1017:         */
                   1018:        if( vp->vmm_visible ) {
                   1019:                mm_von(vp);
                   1020:        }
                   1021:        isbusy = 0;
                   1022: 
                   1023:        /*
                   1024:         * Process all cached characters.
                   1025:         */
                   1026:        while (in_silo.si_ix != in_silo.si_ox) {
                   1027:                /*
                   1028:                 * Get next cached char.
                   1029:                 */
                   1030:                c = in_silo.si_buf[ in_silo.si_ox ];
                   1031: 
                   1032:                if (in_silo.si_ox >= sizeof(in_silo.si_buf) - 1)
                   1033:                        in_silo.si_ox = 0;
                   1034:                else
                   1035:                        in_silo.si_ox++;
                   1036: 
                   1037:                if ((islock == 0) || ISINTR || ISQUIT) {
                   1038:                        ttin(tp, c);
                   1039:                } else if ((c == 'b') && (lastc == '\033')) {
                   1040:                        islock = 0;
                   1041:                        ttin(tp, lastc);
                   1042:                        ttin(tp, c);
                   1043:                } else if ((c == 'c') && (lastc == '\033')) {
                   1044:                        ttin(tp, lastc);
                   1045:                        ttin(tp, c);
                   1046:                } else
                   1047:                        putchar('\007');
                   1048:                lastc = c;
                   1049:        }
                   1050: }
                   1051: 
                   1052: /*
                   1053:  * update the keyboard status LEDS.
                   1054:  * we chose the shift/lock key positions so this would be easy.
                   1055:  * this flavor of routine is called while processing a system call on
                   1056:  * behalf of the user.
                   1057:  */
                   1058: updleds()
                   1059: {
                   1060:        kb_cmd2(K_LED_CMD, (shift >> 1) & 0x7);
                   1061: }
                   1062: 
                   1063: /*
                   1064:  * same as above, but callable from interrupt routines and other places
                   1065:  * which cannot sleep() waiting for the state machine to go idle.
                   1066:  */
                   1067: updleds2()
                   1068: {
                   1069:        register timeout;
                   1070:        register int s;
                   1071: 
                   1072:        timeout = KBTIMEOUT;
                   1073:        s = sphi();
                   1074:        while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
                   1075:                ;
                   1076:        kbstate = KB_DOUBLE_1;
                   1077:        cmd2 = (shift >> 1) & 0x7;
                   1078:        prev_cmd = K_LED_CMD;
                   1079:        outb(KBDATA, K_LED_CMD);
                   1080:        spl(s);
                   1081: }
                   1082: 
                   1083: /*
                   1084:  * unlock the scroll in case an interrupt character is received
                   1085:  */
                   1086: kbunscroll()
                   1087: {
                   1088:        shift &= ~(1 << scroll);
                   1089:        updleds();
                   1090: }
                   1091: 
                   1092: /*
                   1093:  * ship a single byte command to the keyboard
                   1094:  */
                   1095: kb_cmd(cmd)
                   1096: unsigned cmd;
                   1097: {
                   1098:        register int timeout;
                   1099:        register int s;
                   1100: 
                   1101:        s = sphi();
                   1102:        KBDEBUG2(" kb_cmd(%x)", cmd);
                   1103:        while (kbstate != KB_IDLE)
                   1104:                v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb a");
                   1105:        kbstate = KB_SINGLE;
                   1106:        timeout = KBTIMEOUT;
                   1107:        while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
                   1108:                ;
                   1109:        if (!timeout)
                   1110:                printf("kb: command timeout\n");
                   1111:        else {
                   1112:                outb(KBDATA, cmd);
                   1113:                while (kbstate != KB_IDLE)
                   1114:                        v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb b");
                   1115:        }
                   1116:        spl(s);
                   1117: }
                   1118: 
                   1119: /*
                   1120:  * ship a two byte command to the keyboard
                   1121:  */
                   1122: kb_cmd2(cmd, arg)
                   1123: unsigned cmd, arg;
                   1124: {
                   1125:        register int timeout;
                   1126:        register int s;
                   1127: 
                   1128:        s = sphi();
                   1129:        KBDEBUG3(" kb_cmd2(%x, %x)", cmd, arg);
                   1130:        while (kbstate != KB_IDLE)
                   1131:                v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb c");
                   1132:        kbstate = KB_DOUBLE_1;
                   1133:        cmd2 = arg;
                   1134:        prev_cmd = cmd;
                   1135:        timeout = KBTIMEOUT;
                   1136:        while (--timeout > 0 && (inb(KBSTS_CMD) & STS_IBUF_FULL))
                   1137:                ;
                   1138:        if (!timeout)
                   1139:                printf("kb: command timeout\n");
                   1140:        else {
                   1141:                outb(KBDATA, cmd);
                   1142:                while (kbstate != KB_IDLE)
                   1143:                        v_sleep(&kbstate, CVTTIN, IVTTIN, SVTTIN, "kb d");
                   1144:        }
                   1145:        spl(s);
                   1146: }
                   1147: 
                   1148: /*
                   1149: ==============================================================================
                   1150: ==============================================================================
                   1151: */
                   1152: 
                   1153: int
                   1154: VTttyinit(i)
                   1155: int i;
                   1156: {
                   1157:        TTY *tp;
                   1158: 
                   1159:        /*
                   1160:         * get pointer to TTY structure from kernal memory space
                   1161:         */
                   1162:        if( (tp = vttty[i] = (TTY *)kalloc(sizeof (TTY))) == NULL )
                   1163:                return(0);
                   1164:        PRINTV( "     vttty[%d]: @%x, ", i, tp );
                   1165: 
                   1166: #if    FAR_TTY
                   1167:        /*
                   1168:         * get pointers to the buffers pointed to by the TTY structure 
                   1169:         * from user memory space
                   1170:         */
                   1171:        tp->t_buffer = salloc( (fsize_t)NCIB+2*SI_BUFSIZ, SFSYST|SFNSWP );
                   1172:        tp->t_ib = 0;
                   1173:        tp->t_rawin.si_buf = NCIB;
                   1174:        tp->t_rawout.si_buf = NCIB+SI_BUFSIZ;
                   1175: #endif
                   1176:        tp->t_param = NULL;
                   1177:        tp->t_start = &mmstart;
                   1178: 
                   1179: #ifndef        _I386
                   1180: #if    VT_MAJOR == KB_MAJOR
                   1181:        tp->t_cs_sel = 0;
                   1182: #else
                   1183:        tp->t_cs_sel = cs_sel();
                   1184: #endif
                   1185: #endif
                   1186:        tp->t_ddp = vtdata[i];
                   1187:        PRINTV( "data @%lx\n", tp->t_ddp );
                   1188:        return(1);
                   1189: }
                   1190: 
                   1191: vtdatainit(vp)
                   1192: VTDATA *vp;
                   1193: {
                   1194: #ifndef        _I386
                   1195:        VT_FARSEG       vt_farseg;
                   1196: #endif
                   1197:        /*
                   1198:         * vtdata init - vmm part
                   1199:         */
                   1200:        vp->vmm_invis = -1;                     /* cursor invisible */
                   1201: 
                   1202: #ifdef _I386
                   1203:        vp->vt_buffer = kalloc( TEXTBLOCK );
                   1204:        vp->vmm_seg = vp->vmm_mseg = ds_sel();
                   1205:        vp->vmm_off = vp->vmm_moff = vp->vt_buffer;
                   1206: #else
                   1207:        vp->vt_buffer = salloc ( (fsize_t)TEXTBLOCK, SFSYST|SFNSWP|SFHIGH );
                   1208:        vp->vmm_seg = vp->vmm_mseg = FP_SEG( vp->vt_buffer->vt_faddr );
                   1209:        vp->vmm_off = vp->vmm_moff = FP_OFF( vp->vt_buffer->vt_faddr );
                   1210: #endif
                   1211:        PRINTV( "vt@%x init index %d,%d), seg %x, off %x\n",
                   1212:                vp, vp->vt_ind, vp->vmm_mseg, vp->vmm_moff );
                   1213:        /*
                   1214:         * vtdata init - vnkb part
                   1215:         */
                   1216:        /* Make the first memory block active, if present */ 
                   1217:        vp->vnkb_lastc = 0;
                   1218:        vp->vnkb_fnkeys = 0;    
                   1219:        vp->vnkb_funkeyp = 0;   
                   1220:        vp->vnkb_fk_loaded = 0;                 /* no Fn keys yet */
                   1221: }
                   1222: 
                   1223: /*
                   1224:  * Given device number, return index for vtdata[], vttty[], etc.
                   1225:  *
                   1226:  * Major number must be VT_MAJOR for CPU to get here.
                   1227:  *
                   1228:  *      Minor Number   Index Value
                   1229:  *     ----- ------    ----- -----  
                   1230:  *     0000  0000      vtactive ... device (2,0) is the active screen
                   1231:  *     0000  0001      0
                   1232:  *     0000  0010      1
                   1233:  *     0000  0011      2
                   1234:  *        ....
                   1235:  *     0000  1111      14
                   1236:  *
                   1237:  *     0100  xxxx      xxxx ... color devices only
                   1238:  *     0101  xxxx      xxxx - (# of color devices found) ... monochrome only
                   1239:  *
                   1240:  * Return value is in range 0 to vtcount-1 for valid minor numbers,
                   1241:  * -1 for invalid minor numbers.
                   1242:  */
                   1243: int
                   1244: vtindex( dev )
                   1245: dev_t dev;
                   1246: {
                   1247:        register int    ret = -1;
                   1248: 
                   1249:        if ( dev & VT_PHYSICAL ) {
                   1250:                int     hw = ( dev >> 4 ) & 3;
                   1251:                int     hw_index = dev & 0x0F;
                   1252: 
                   1253:                if( hw_index < vtHWtable[hw]->found )
                   1254:                        ret = vtHWtable[hw]->start + hw_index;
                   1255:        } else {
                   1256:                int     lg_index = dev & 0x0F;
                   1257: 
                   1258:                if (lg_index == 0)
                   1259:                        ret = vtactive;
                   1260:                if (lg_index > 0 && lg_index <= vtcount ) 
                   1261:                        ret = lg_index-1;
                   1262:        }
                   1263:        if (ret >= 0)
                   1264:                ret %= vtcount;
                   1265:        else
                   1266:                PRINTV( "vtindex: (%x) %d. invalid !\n", dev, ret );
                   1267:        return ret;
                   1268: }
                   1269: 
                   1270: /*
                   1271:  *
                   1272:  * void
                   1273:  * isvtswitch()        -- deferred virtual terminal switch
                   1274:  *
                   1275:  *     Action: - save current shift key status
                   1276:  *             - determine new active virtual terminal
                   1277:  *             - deactivate shift key status of the current virtual terminal
                   1278:  *             - deactivate current virtual terminal
                   1279:  *             - activate shift key status of the new virtual terminal with 
                   1280:  *               the previously saved shift key status
                   1281:  *             - activate new virtual terminal 
                   1282:  *
                   1283:  *     Notes:  isvtswitch() was scheduled as a deferred process by 
                   1284:  *     process_key() which is a function called by isrint().
                   1285:  */
                   1286: void
                   1287: isvtswitch(key_val)
                   1288: {
                   1289:        register int    new_index, i;
                   1290:        unsigned        lockshift, nolockshift; 
                   1291:        VTDATA          *vp = vtdata[vtactive];
                   1292:        VTDATA          *vp_old, *vp_new;
                   1293:        static int      vtprevious;
                   1294: 
                   1295:        T_CON(2, printf("old shift=%x sh_index=%d\n", shift, sh_index));
                   1296:        lockshift = shift & ((1<<scroll)|(1<<num)|(1<<caps));
                   1297:        nolockshift = shift & ~((1<<scroll)|(1<<num)|(1<<caps));
                   1298: 
                   1299:        PRINTV( "F%d: %d", key_val, vtactive );
                   1300: #if 0
                   1301:        if( key_val == VTKEY_HOME )
                   1302:                new_index = 0;
                   1303:        else if( key_val == VTKEY_NEXT ) {
                   1304:                new_index = vtactive;
                   1305:                for( i = 0; i < vtcount; ++i ) {
                   1306:                        new_index = ++new_index % vtcount;
                   1307:                        if( vttty[new_index]->t_open )
                   1308:                                break;
                   1309:                }
                   1310:        } else {
                   1311:                new_index = vtindex(vtkey_to_dev(key_val));
                   1312:                if( new_index < 0) {
                   1313:                        putchar( '\007' );
                   1314:                        return;
                   1315:                }
                   1316:        }
                   1317: #else
                   1318:        switch (key_val) {
                   1319:        case VTKEY_HOME:
                   1320:                new_index = 0;
                   1321:                break;
                   1322:        case VTKEY_NEXT:
                   1323:                new_index = vtactive;
                   1324:                for( i = 0; i < vtcount; ++i ) {
                   1325:                        new_index = ++new_index % vtcount;
                   1326:                        if( vttty[new_index]->t_open )
                   1327:                                break;
                   1328:                }
                   1329:                break;
                   1330:        case VTKEY_PREV:
                   1331:                new_index = vtactive;
                   1332:                for( i = 0; i < vtcount; ++i ) {
                   1333:                        new_index = (--new_index+vtcount) % vtcount;
                   1334:                        if( vttty[new_index]->t_open )
                   1335:                                break;
                   1336:                }
                   1337:                break;
                   1338:        case VTKEY_TOGL:
                   1339:                new_index = vtprevious;
                   1340:                break;
                   1341:        default:
                   1342:                new_index = vtindex(vtkey_to_dev(key_val));
                   1343:                if( new_index < 0) {
                   1344:                        putchar( '\007' );
                   1345:                        return;
                   1346:                }
                   1347:        }
                   1348: #endif
                   1349:        T_CON(8, printf("%d->%d ", vtactive, new_index));
                   1350:        if( new_index == vtactive )
                   1351:                return;
                   1352: 
                   1353:        /* Save which locking shift states are in effect. */
                   1354: 
                   1355:        vp_old = vtdata[vtactive];
                   1356:        vp_new = vtdata[new_index];
                   1357: 
                   1358:        vp_old->vnkb_shift = lockshift;
                   1359:        vtdeactivate(vp_new, vp_old);   /* deactivate old virtual terminal */
                   1360: 
                   1361:        /* Restore shift lock state, append current momentary shift state. */
                   1362:        shift = vp_new->vnkb_shift | nolockshift;
                   1363:        T_CON(2, printf("new shift=%x sh_index=%d\n", shift, sh_index));
                   1364:        vtactivate(vp_new);             /* activate new virtual terminal */
                   1365:        updterminal(new_index);
                   1366:        vtprevious = vtactive;
                   1367:        vtactive = new_index;           /* update vtactive */
                   1368: }
                   1369: 
                   1370: vtdeactivate(vp_new, vp_old)
                   1371: register VTDATA        *vp_new, *vp_old;
                   1372: {
                   1373:        register i;
                   1374:        VTDATA  *vpi;
                   1375: 
                   1376:        /* store old screen contents in memory segment */
                   1377:        FFCOPY( vp_old->vmm_voff, vp_old->vmm_vseg,
                   1378:                vp_old->vmm_moff, vp_old->vmm_mseg, TEXTBLOCK );
                   1379: 
                   1380:        /*
                   1381:         * if changing to another screen on same video board
                   1382:         *      for all screens on same board as new screen
                   1383:         *              deactivate, but don't update
                   1384:         * else - changing to a screen on different board
                   1385:         *      for all screens NOT on same board as new screen
                   1386:         *              deactivate, but don't update
                   1387:         */
                   1388:        if ( vp_old->vmm_port == vp_new->vmm_port ) {
                   1389:                T_CON(8, printf("deactivate on %x ", vp_new->vmm_port));
                   1390:                for (i = 0; i < vtcount; ++i) {
                   1391:                        vpi = vtdata[i];
                   1392:                        if ( vpi->vmm_port == vp_new->vmm_port ) {
                   1393:                                /* deactivate, but don't update */
                   1394:                                vpi->vmm_invis = ~0; 
                   1395:                                vpi->vmm_visible = VNKB_FALSE;
                   1396:                                vpi->vmm_seg = vpi->vmm_mseg;
                   1397:                                vpi->vmm_off = vpi->vmm_moff;
                   1398:                                if( vpi->vmm_seg == 0 )
                   1399:                                        printf( "[1]vpi->vmm_seg = 0\n" );
                   1400:                                PRINTV( "vt.back %d. seg %x off %x\n", i,
                   1401:                                        vpi->vmm_seg, vpi->vmm_off );
                   1402:                        }
                   1403:                }
                   1404:        } else {
                   1405:                T_CON(8, printf("deactivate %x->%x ",
                   1406:                  vp_old->vmm_port, vp_new->vmm_port));
                   1407:                for (i = 0; i < vtcount; ++i) {
                   1408:                        vpi = vtdata[i];
                   1409:                        if ( (vpi->vmm_port != vp_new->vmm_port) 
                   1410:                          && (vpi->vmm_invis == 0) ) {
                   1411:                                /* update, but don't deactivate */
                   1412:                                vpi->vmm_invis = ~0; 
                   1413:                                updscreen(i);
                   1414:                        }
                   1415:                }
                   1416:        }
                   1417: }
                   1418: 
                   1419: vtactivate(vp)
                   1420: VTDATA *vp;
                   1421: {
                   1422:        register VTDATA *vpi;
                   1423:        register i;
                   1424: 
                   1425:        /* 
                   1426:         * copy from screen contents from heap segment to video memory 
                   1427:         * only if necessary
                   1428:         */
                   1429:        if ( vp->vmm_visible == VNKB_FALSE )
                   1430:                FFCOPY( vp->vmm_moff, vp->vmm_mseg,
                   1431:                        vp->vmm_voff, vp->vmm_vseg, TEXTBLOCK );
                   1432: 
                   1433:        for (i = 0; i < vtcount; ++i) {
                   1434:                vpi = vtdata[i];
                   1435:                if (vpi->vmm_port == vp->vmm_port) {
                   1436:                        vpi->vmm_invis = -1;
                   1437:                        vpi->vmm_visible = VNKB_FALSE;
                   1438:                        vpi->vmm_seg = vpi->vmm_mseg;
                   1439:                        vpi->vmm_off = vpi->vmm_moff;
                   1440:                        if( vpi->vmm_seg == 0 )
                   1441:                                printf( "[2]vpi->vmm_seg = 0\n" );
                   1442:                        PRINTV( "vt.back seg %x off %x\n",
                   1443:                                vpi->vmm_seg, vpi->vmm_off );
                   1444:                }               
                   1445:        }
                   1446:        /*
                   1447:         * Set new active terminal
                   1448:         */
                   1449:        vp->vmm_invis = 0;      
                   1450:        vp->vmm_visible = VNKB_TRUE;
                   1451:        vp->vmm_seg = vp->vmm_vseg;
                   1452:        vp->vmm_off = vp->vmm_voff;
                   1453:        if( vp->vmm_seg == 0 )
                   1454:                printf( "vp->vmm_seg = 0\n" );
                   1455: }
                   1456: 
                   1457: /*
                   1458:  * update the terminal to match vtactive
                   1459:  */
                   1460: updterminal(index)
                   1461: int index;
                   1462: {
                   1463:        updscreen(index);
                   1464:        updleds2();
                   1465: }
                   1466: 
                   1467: #undef si
                   1468: asmdump( cs, ds, es, di, si, bp, sp, bx, dx, cx, i, ip, ax )
                   1469: int    cs, ds, es, di, si, bp, sp, bx, dx, cx, i, ip, ax;
                   1470: {
                   1471:        if( vt_verbose < 2 )
                   1472:                return;
                   1473: 
                   1474:        printf( "asmdump %d: es %x, ds %x, cs:ip %x:%x\n", i, es, ds, cs, ip );
                   1475:        printf( "   ax %x, bx %x, cx %x, dx %x\n", ax, bx, cx, dx );
                   1476:        printf( "   di %x, si %x, bp %x, sp %d\n", di, si, bp, sp );
                   1477: #if    USING_RS232
                   1478:        if( vt_verbose > 2 )
                   1479:                getchar();
                   1480: #endif
                   1481: }
                   1482: 
                   1483: vtdataprint( vp )
                   1484: register VTDATA *vp;
                   1485: {
                   1486:        if( vt_verbose < 2 )
                   1487:                return;
                   1488: 
                   1489:        printf( "VTDATA:    @%x, esc %x, func %x()\n",
                   1490:                vp, vp->vmm_esc, vp->vmm_func );
                   1491:        printf( "       hw: port %x, seg %x, off %x\n",
                   1492:                vp->vmm_port, vp->vmm_vseg, vp->vmm_voff );
                   1493:        printf( "   memory: size %x, seg %x, off %x\n",
                   1494:                0/*vp->vmm_size*/, vp->vmm_mseg, vp->vmm_moff );
                   1495:        printf( "   cursor: seg %x, off %x, visible %d\n",
                   1496:                vp->vmm_seg, vp->vmm_off, !vp->vmm_invis );
                   1497:        printf( "           row %d, col %d = offset %d.\n",
                   1498:                vp->vmm_rowl, vp->vmm_col, vp->vmm_pos );
                   1499:        printf( "     saved row %d, col %d\n",
                   1500:                vp->vmm_srow, vp->vmm_scol );
                   1501:        printf( "   screen: visible %d, attr %x, wrap %d, slow %d\n",
                   1502:                vp->vmm_visible, vp->vmm_attr, vp->vmm_wrap, vp->vmm_slow );
                   1503:        printf( "           row base %d, end %d, limit %d\n",
                   1504:                vp->vmm_brow, vp->vmm_erow, vp->vmm_lrow ); 
                   1505:        printf( "           row initial base %d, initial end %d\n",
                   1506:                vp->vmm_ibrow, vp->vmm_ierow ); 
                   1507: #if    USING_RS232
                   1508:        if( vt_verbose > 2 )
                   1509:                getchar();
                   1510: #endif
                   1511: }
                   1512: 
                   1513: FFCOPY( src_off, src_seg, dst_off, dst_seg, count )
                   1514: {
                   1515:        register i;
                   1516: 
                   1517: #if    0
                   1518:        i = ffcopy( src_off, src_seg, dst_off, dst_seg, count );
                   1519: #else
                   1520:        for( i = 0; i < count; i += 2 ) {
                   1521:                register word = ffword( src_off, src_seg );
                   1522:                sfword( dst_off, dst_seg, word );
                   1523:                src_off += 2;
                   1524:                dst_off += 2;
                   1525:        }
                   1526: #endif
                   1527:        return i;       
                   1528: }
                   1529: 
                   1530: /*
                   1531:  * Given a function key number (e.g. vt0),
                   1532:  * return the corresponding minor device number.
                   1533:  *
                   1534:  * Assume valid key number (VTKEY(fnum) is true) by the time we get here.
                   1535:  */
                   1536: int
                   1537: vtkey_to_dev(fnum)
                   1538: int fnum;
                   1539: {
                   1540:        if (fnum >=vt0 && fnum <= vt15)
                   1541:                return fnum-vt0+1;
                   1542:        if (fnum >=color0 && fnum <= color15)
                   1543:                return (fnum-color0)|(VT_PHYSICAL|VT_HW_COLOR);
                   1544:        if (fnum >=mono0 && fnum <= mono15)
                   1545:                return (fnum-mono0)|(VT_PHYSICAL|VT_HW_MONO);
                   1546:        printf("vtkey_to_dev(%d)! ", fnum);
                   1547:        return 0;
                   1548: }
                   1549: /* 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.