Annotation of 43BSDReno/sys/tahoe/cons.c, revision 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.