Annotation of 43BSDReno/sys/tahoe/cons.c, revision 1.1.1.1

1.1       root        1: /*     cons.c  7.5     90/01/17        */
                      2: 
                      3: /*
                      4:  * Tahoe console processor driver
                      5:  *
                      6:  * Minor device 0 is the CP itself.
                      7:  *       No real read/writes can be done to him.
                      8:  * Minor 1 is the console terminal.
                      9:  * Minor 2 is the remote line trminal.
                     10:  */
                     11: #include "param.h"
                     12: #include "conf.h"
                     13: #include "ioctl.h"
                     14: #include "user.h"
                     15: #include "proc.h"
                     16: #include "tty.h"
                     17: #include "callout.h"
                     18: #include "systm.h"
                     19: #include "kernel.h"
                     20: #include "syslog.h"
                     21: 
                     22: #include "../tahoe/cp.h"
                     23: #include "../tahoe/cpu.h"
                     24: #include "../tahoe/mtpr.h"
                     25: 
                     26: int    cnrestart();
                     27: int    timeout();
                     28: 
                     29: struct tty CPtty;
                     30: struct tty cons;
                     31: struct tty RLtty;
                     32: struct tty *cntty[3] = { &CPtty, &cons, &RLtty };
                     33: 
                     34: struct tty *constty = 0;       /* virtual console */
                     35: 
                     36: struct consoftc {
                     37:        char    cs_flags;
                     38: #define        CSF_ACTIVE      0x1     /* timeout active */
                     39: #define        CSF_POLLING     0x2     /* polling for input */
                     40:        char    cs_lastc;       /* last char sent */
                     41:        int     cs_timo;        /* timeouts since interrupt */
                     42:        u_long  cs_wedgecnt;    /* times restarted */
                     43: } consoftc[3];
                     44: 
                     45: struct speedtab cnspeedtab[] = {
                     46:        9600,   13,
                     47:        4800,   12,
                     48:        2400,   11,
                     49:        1800,   10,
                     50:        1200,   9,
                     51:        600,    8,
                     52:        300,    7,
                     53:        200,    6,
                     54:        150,    5,
                     55:        134,    4,
                     56:        110,    3,
                     57:        75,     2,
                     58:        50,     1,
                     59:        0,      13,
                     60:        -1,     -1,
                     61: };
                     62: 
                     63: /*
                     64:  * We check the console periodically to make sure
                     65:  * that it hasn't wedged.  Unfortunately, if an XOFF
                     66:  * is typed on the console, that can't be distinguished
                     67:  * from more catastrophic failure.
                     68:  */
                     69: #define        CN_TIMERVAL     (hz)            /* frequency at which to check cons */
                     70: #define        CN_TIMO         (2*60)          /* intervals to allow for output char */
                     71: 
                     72: struct cpdcb_o consout[3] = { 
                     73:        { CPTAKE|CPDONE }, { CPTAKE|CPDONE }, { CPTAKE|CPDONE }
                     74: };
                     75: struct cpdcb_i consin[3] = {
                     76:        { CPTAKE|CPDONE }, { CPTAKE|CPDONE }, { CPTAKE|CPDONE }
                     77: };
                     78: struct cphdr *cnlast;
                     79: 
                     80: int    cnstart();
                     81: int    ttrstrt();
                     82: char   partab[];
                     83: 
                     84: /*
                     85:  * Wait for CP to accept last CP command sent
                     86:  * before setting up next command.
                     87:  */
                     88: #define        waitforlast(timo) { \
                     89:        if (cnlast) { \
                     90:                (timo) = 10000; \
                     91:                do \
                     92:                        uncache((char *)&cnlast->cp_unit); \
                     93:                while ((cnlast->cp_unit&CPTAKE) == 0 && --(timo)); \
                     94:        } \
                     95: }
                     96: 
                     97: /*ARGSUSED*/
                     98: cnopen(dev, flag)
                     99:        dev_t dev;
                    100: {
                    101:        register struct tty *tp;
                    102:        int unit = minor(dev);
                    103:        int cnparams();
                    104: 
                    105:        if (unit > CPREMOT) 
                    106:                return (ENXIO);
                    107:        tp = cntty[unit];
                    108:        if (tp->t_state&TS_XCLUDE && u.u_uid != 0)
                    109:                return (EBUSY);
                    110:        cnpostread(unit);               /* post request for input */
                    111:        tp->t_oproc = cnstart;
                    112:        tp->t_param = cnparams;
                    113:        tp->t_dev = dev;
                    114:        if ((tp->t_state&TS_ISOPEN) == 0) {
                    115:                ttychars(tp);
                    116:                tp->t_iflag = TTYDEF_IFLAG|ICRNL;
                    117:                tp->t_oflag = TTYDEF_OFLAG|OPOST|ONLCR;
                    118:                tp->t_lflag = TTYDEF_LFLAG;
                    119:                tp->t_cflag = CS8|CREAD;
                    120:                tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
                    121:                tp->t_state = TS_ISOPEN|TS_CARR_ON;
                    122:                cnparams(tp, &tp->t_termios);
                    123:                ttsetwater(tp);
                    124:        }
                    125:        return ((*linesw[tp->t_line].l_open)(dev, tp));
                    126: }
                    127: 
                    128: cnpostread(unit)
                    129:        int unit;
                    130: {
                    131:        register struct cpdcb_i *cin;
                    132:        register int timo;
                    133: 
                    134:        waitforlast(timo);
                    135:        cin = &consin[unit];
                    136:        cin->cp_hdr.cp_unit = unit;
                    137:        cin->cp_hdr.cp_comm = CPREAD;
                    138:        cin->cp_hdr.cp_count = 1;       /* Get ready for input */
                    139:        mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)cin));
                    140:        cnlast = &cin->cp_hdr;
                    141: }
                    142: 
                    143: cnclose(dev)
                    144:        dev_t dev;
                    145: {
                    146:        register struct tty *tp = cntty[minor(dev)];
                    147: 
                    148:        (*linesw[tp->t_line].l_close)(tp);
                    149:        ttyclose(tp);
                    150: }
                    151: 
                    152: /*ARGSUSED*/
                    153: cnread(dev, uio, flag)
                    154:        dev_t dev;
                    155:        struct uio *uio;
                    156: {
                    157:        struct tty *tp = cntty[minor(dev)];
                    158: 
                    159:        return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
                    160: }
                    161: 
                    162: /*ARGSUSED*/
                    163: cnwrite(dev, uio, flag)
                    164:        dev_t dev;
                    165:        struct uio *uio;
                    166: {
                    167:        register struct tty *tp = cntty[minor(dev)];
                    168: 
                    169:        if (tp == &cons && constty &&
                    170:            (constty->t_state & (TS_CARR_ON | TS_ISOPEN)) ==
                    171:            (TS_CARR_ON | TS_ISOPEN))
                    172:                tp = constty;
                    173:        return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
                    174: }
                    175: 
                    176: /*
                    177:  * Got a console receive interrupt -
                    178:  * the console processor wants to give us a character.
                    179:  * Catch the character, and see who it goes to.
                    180:  */
                    181: cnrint(dev)
                    182:        dev_t dev;
                    183: {
                    184:        register int unit, timo;
                    185:        register struct tty *tp;
                    186:        int c;
                    187: 
                    188:        unit = minor(dev);
                    189:        if (!intenable || consoftc[unit].cs_flags&CSF_POLLING)
                    190:                return;
                    191:        /* make sure we dont take it from cache */
                    192:        uncache(&consin[unit].cpi_buf[0]);
                    193:        c = consin[unit].cpi_buf[0];
                    194:        waitforlast(timo);
                    195:        /* This resets status bits */
                    196:        consin[unit].cp_hdr.cp_unit = unit;
                    197:        /* Ready for new character */
                    198:        mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)&consin[unit]));
                    199:        cnlast = &consin[unit].cp_hdr;
                    200: 
                    201:        tp = cntty[unit];
                    202:        if ((tp->t_cflag&CSIZE) != CS8)
                    203:                c &= 0177;
                    204: #ifdef KADB
                    205:        if (unit == CPCONS && kdbrintr(c, tp))
                    206:                return;
                    207: #endif
                    208:        (*linesw[tp->t_line].l_rint)(c & 0377, tp);
                    209: }
                    210: 
                    211: cnioctl(dev, cmd, addr, flag)
                    212:        dev_t dev;
                    213:        caddr_t addr;
                    214: {
                    215:        register struct tty *tp = cntty[minor(dev)];
                    216:        register error;
                    217:  
                    218:        error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
                    219:        if (error >= 0)
                    220:                return error;
                    221:        if ((error = ttioctl(tp, cmd, addr, flag)) < 0)
                    222:                error = ENOTTY;
                    223:        return (error);
                    224: }
                    225: 
                    226: int    consintr = 1;
                    227: /*
                    228:  * Got a console transmission interrupt -
                    229:  * the console processor wants another character.
                    230:  */
                    231: cnxint(dev)
                    232:        dev_t dev;
                    233: {
                    234:        register struct tty *tp;
                    235:        register int unit;
                    236: 
                    237:        if (!intenable || !consintr)
                    238:                return;
                    239:        unit = minor(dev);
                    240: #ifdef CPPERF
                    241:        scope_in(unit == CPCONS ? 1 : 2);
                    242: #endif
                    243:        tp = cntty[unit];
                    244:        tp->t_state &= ~TS_BUSY;
                    245:        consoftc[unit].cs_timo = 0;
                    246:        if (tp->t_line)
                    247:                (*linesw[tp->t_line].l_start)(tp);
                    248:        else
                    249:                cnstart(tp);
                    250: }
                    251: 
                    252: cnstart(tp)
                    253:        register struct tty *tp;
                    254: {
                    255:        register c, s;
                    256: 
                    257: #ifdef CPPERF
                    258:        scope_in(minor(tp->t_dev) == CPCONS ? 3 : 4);
                    259: #endif
                    260:        s = spl8();
                    261:        if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
                    262:                goto out;
                    263:        if (tp->t_outq.c_cc <= tp->t_lowat) {
                    264:                if (tp->t_state&TS_ASLEEP) {
                    265:                        tp->t_state &= ~TS_ASLEEP;
                    266:                        wakeup((caddr_t)&tp->t_outq);
                    267:                }
                    268:                if (tp->t_wsel) {
                    269:                        selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
                    270:                        tp->t_wsel = 0;
                    271:                        tp->t_state &= ~TS_WCOLL;
                    272:                }
                    273:        }
                    274:        if (tp->t_outq.c_cc == 0)
                    275:                goto out;
                    276:        c = getc(&tp->t_outq) & 0xff;
                    277:        if (tp->t_cflag&PARENB && ((tp->t_cflag&CSIZE)==CS7)) {
                    278:                c &= 0177;
                    279:                c |= (tp->t_cflag&PARODD ? ~partab[c] : partab[c]) & 0200;
                    280:        }
                    281:        cnputchar(c, tp);
                    282:        tp->t_state |= TS_BUSY;
                    283: out:
                    284:        splx(s);
                    285: }
                    286: 
                    287: cnputc(c)
                    288:        char c;
                    289: {
                    290: 
                    291:        if (c == '\n')
                    292:                cnputchar('\r', (struct tty *)0);
                    293:        cnputchar(c, (struct tty *)0);
                    294: }
                    295: 
                    296: /*
                    297:  * Print a character on console.
                    298:  */
                    299: cnputchar(c, tp)
                    300:        char c;
                    301:        register struct tty *tp;
                    302: {
                    303:        register timo;
                    304:        register struct cpdcb_o *current;
                    305:        register struct consoftc *cs;
                    306:        int unit;
                    307: 
                    308:        /* tp == 0 only in system error messages */
                    309:        if (tp == 0) {
                    310:                tp = &cons;
                    311:                tp->t_dev = CPCONS;             /* may not be open */
                    312:                c |= partab[c&0177]&0200;
                    313:        }
                    314:        unit = minor(tp->t_dev);
                    315:        current = &consout[unit];
                    316:        timo = 30000;
                    317:        /*
                    318:         * Try waiting for the console tty to finish previous command
                    319:         * on this unit, otherwise give up after a reasonable time.
                    320:         */
                    321:        do
                    322:                uncache(&current->cp_hdr.cp_unit);
                    323:        while ((current->cp_hdr.cp_unit&CPDONE) == 0 && --timo);
                    324: 
                    325:        current->cp_hdr.cp_comm = CPWRITE;
                    326:        current->cp_hdr.cp_count = 1;
                    327:        current->cp_buf[0] = c;
                    328:        /*
                    329:         * Try waiting for the console tty
                    330:         * to accept previous command.
                    331:         */
                    332:        waitforlast(timo);
                    333: 
                    334:        /* Reset done bit */
                    335:        current->cp_hdr.cp_unit = (char)unit;
                    336: #ifdef CPPERF
                    337:        if (intenable != 0)
                    338:                scope_in(5);
                    339: #endif
                    340:        cs = &consoftc[unit];
                    341:        cs->cs_lastc = c;
                    342:        cs->cs_timo = CN_TIMO;
                    343:        if ((cs->cs_flags&CSF_ACTIVE) == 0 && clk_enable) {
                    344:                cs->cs_flags |= CSF_ACTIVE;
                    345:                timeout(cnrestart, (caddr_t)tp, CN_TIMERVAL);
                    346:        }
                    347:        mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current));
                    348:        cnlast = &current->cp_hdr;
                    349: }
                    350: 
                    351: #if defined(KADB) || defined(GENERIC)
                    352: cngetc()
                    353: {
                    354:        register int c, s;
                    355: 
                    356:        s = spl8();             /* block cnrint while we poll */
                    357:        c = cngetchar(&cons);
                    358:        if (c == '\r')
                    359:                c = '\n';
                    360:        splx(s);
                    361:        return (c);
                    362: }
                    363: 
                    364: cngetchar(tp)
                    365:        register struct tty *tp;
                    366: {
                    367:        register timo, unit;
                    368:        register struct cpdcb_i *current;
                    369:        char c;
                    370: 
                    371:        unit = minor(tp->t_dev);
                    372:        current = &consin[unit];
                    373:        waitforlast(timo);
                    374:        current->cp_hdr.cp_unit = unit;         /* Resets done bit */
                    375:        current->cp_hdr.cp_comm = CPREAD;
                    376:        current->cp_hdr.cp_count = 1;
                    377:        mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current));
                    378:        while ((current->cp_hdr.cp_unit&CPDONE) == 0) 
                    379:                uncache(&current->cp_hdr.cp_unit);
                    380:        uncache(&current->cpi_buf[0]);
                    381:        c = current->cpi_buf[0] & 0x7f;
                    382:        cnlast = &current->cp_hdr;
                    383:        return (c);
                    384: }
                    385: #endif
                    386: 
                    387: /*
                    388:  * Restart (if necessary) transfer to CP line.
                    389:  * This way, lost transmit interrupts don't wedge output.
                    390:  */
                    391: cnrestart(tp)
                    392:        struct tty *tp;
                    393: {
                    394:        register struct consoftc *cs;
                    395: 
                    396:        cs = &consoftc[minor(tp->t_dev)];
                    397:        cs->cs_flags &= ~CSF_ACTIVE;
                    398:        if (cs->cs_timo) {
                    399:                if (--cs->cs_timo == 0) {
                    400:                        cs->cs_wedgecnt++;
                    401:                        cnreset(tp);
                    402:                        cnputchar(cs->cs_lastc, tp);
                    403:                } else {
                    404:                        cs->cs_flags |= CSF_ACTIVE;
                    405:                        timeout(cnrestart, (caddr_t)tp, CN_TIMERVAL);
                    406:                }
                    407:        }
                    408: }
                    409: 
                    410: /*
                    411:  * Reset console.
                    412:  */
                    413: cnreset(tp)
                    414:        register struct tty *tp;
                    415: {
                    416:        register timo;
                    417:        register struct cpdcb_o *current;
                    418:        register unit;
                    419:        static int failed;
                    420: 
                    421:        unit = minor(tp->t_dev);
                    422:        current = &consout[unit];
                    423:        current->cp_hdr.cp_comm = CPRESET;
                    424:        current->cp_hdr.cp_count = 0;
                    425:        current->cp_hdr.cp_unit = unit; 
                    426:        mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current));
                    427:        cnlast = &current->cp_hdr;
                    428:        timo = 10000;
                    429:        do
                    430:                uncache(&current->cp_hdr.cp_unit);
                    431:        while ((current->cp_hdr.cp_unit&CPTAKE) == 0 && --timo);
                    432:        if (current->cp_hdr.cp_unit & CPTAKE) {
                    433:                cnparams(tp, &tp->t_termios);
                    434:                failed = 0;
                    435:        } else if (failed++ == 0)
                    436:                log(LOG_ERR, "Console wedged, reset failed.\n");
                    437: }
                    438: 
                    439: /*
                    440:  * Set line parameters
                    441:  */
                    442: cnparams(tp, t)
                    443:        register struct tty *tp;
                    444:        register struct termios *t;
                    445: {
                    446:        register timo = 30000;
                    447:        int unit = minor(tp->t_dev);
                    448:        register struct cpdcb_o *current = &consout[unit];
                    449:        register cflag = t->c_cflag;
                    450:        int speedcode, csize;
                    451: 
                    452:        if (((speedcode == ttspeedtab(t->c_ospeed, cnspeedtab)) < 0) ||
                    453:           (t->c_ispeed && t->c_ispeed != t->c_ospeed) ||
                    454:           ((csize = (cflag&CSIZE)) != CS7 && csize != CS8))
                    455:                return (EINVAL);
                    456:        /*XXX*/return (0);
                    457:        /*
                    458:         * Try waiting for the console tty to finish any output,
                    459:         * otherwise give up after a reasonable time.
                    460:         */
                    461:        do
                    462:                uncache(&current->cp_hdr.cp_unit);
                    463:        while ((current->cp_hdr.cp_unit&CPDONE) == 0 && --timo);
                    464:        current->cp_hdr.cp_comm = CPSTTY;
                    465:        current->cp_hdr.cp_count = 4;
                    466:        current->cp_buf[0] = speedcode;
                    467: #ifdef notyet
                    468:        /* parity */
                    469:        current->cp_buf[1] = (cflag&PARENB) ? ((cflag&PARODD) ? 2 : 1) : 0;     
                    470:        /* stop bits */
                    471:        current->cp_buf[2] = (cflag&CSTOPB) ? 2 : 0;
                    472:        /* data bits */
                    473:        current->cp_buf[3] = (csize==CS8) ? 8 : 7;
                    474: #else
                    475:        current->cp_buf[1] = 0; /* no parity */
                    476:        current->cp_buf[2] = 0; /* stop bits */
                    477:        current->cp_buf[3] = 8; /* data bits */
                    478: #endif
                    479: 
                    480:        /* Reset done bit */
                    481:        current->cp_hdr.cp_unit = unit; 
                    482: 
                    483:        waitforlast(timo);
                    484:        mtpr(CPMDCB, vtoph((struct proc *)0, (unsigned)current));
                    485:        cnlast = &current->cp_hdr;
                    486:        cnpostread(unit);
                    487:        return (0);
                    488: }
                    489: 
                    490: #ifdef KADB
                    491: /*
                    492:  * Turn input polling on/off (used by debugger).
                    493:  */
                    494: cnpoll(onoff)
                    495:        int onoff;
                    496: {
                    497: 
                    498:        if (!onoff) {
                    499:                consoftc[CPCONS].cs_flags &= ~CSF_POLLING;
                    500:                cnpostread(CPCONS);             /* restart input */
                    501:        } else
                    502:                consoftc[CPCONS].cs_flags |= CSF_POLLING;
                    503: }
                    504: #endif

unix.superglobalmegacorp.com

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