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

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

unix.superglobalmegacorp.com

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