Annotation of researchv8dc/sys/chunix/chtty.c, revision 1.1

1.1     ! root        1: #include "../chunix/chsys.h"
        !             2: #include "../chunix/chconf.h"
        !             3: #include "../chaos/chaos.h"
        !             4: #include "../chaos/dev.h"
        !             5: #include "../h/inode.h"
        !             6: #include "../h/file.h"
        !             7: #include "../h/tty.h"
        !             8: #include "../h/dir.h"
        !             9: #include "../h/user.h"
        !            10: #include "../h/conf.h"
        !            11: /*
        !            12:  * This file contains functions for treating a chaos channel as a UNIX tty
        !            13:  */
        !            14: #include "cht.h"
        !            15: struct tty cht_tty[NCHT * 16];
        !            16: int cht_cnt = NCHT * 16;
        !            17: 
        !            18: /*
        !            19:  * Do the additional work necessary to open a channel as a UNIX tty.
        !            20:  * Basically the existence of an associated connection is much like
        !            21:  * the existence of a carrier.
        !            22:  */
        !            23: /* ARGSUSED */
        !            24: chtopen(dev, flag)
        !            25:        dev_t dev;
        !            26: {
        !            27:        register struct tty *tp;
        !            28:        register int unit;
        !            29:        int chtstart(), chtinput();
        !            30: 
        !            31:        unit = minor(dev);
        !            32:        if (unit >= cht_cnt) {
        !            33:                u.u_error = ENXIO;
        !            34:                return;
        !            35:        }
        !            36:        tp = &cht_tty[unit];
        !            37:        if (tp->t_state & XCLUDE && u.u_uid != 0) {
        !            38:                u.u_error = EBUSY;
        !            39:                return;
        !            40:        }
        !            41:        tp->t_state |= WOPEN;
        !            42:        tp->t_oproc = chtstart;
        !            43:        tp->t_iproc = chtinput;
        !            44:        if ((tp->t_state&ISOPEN) == 0) {
        !            45:                ttychars(tp);
        !            46:                tp->t_ispeed = B9600;
        !            47:                tp->t_ospeed = B9600;
        !            48:                tp->t_flags = ODDP|EVENP|ECHO;
        !            49:                tp->t_state |= HUPCLS;
        !            50:        }
        !            51:        tp->t_lstate |= LSCHAOS;
        !            52:        LOCK;
        !            53:        /*
        !            54:         * Since ttyclose forces CARR_ON off, we turn it on again if
        !            55:         * the connection is still around.
        !            56:         */
        !            57:        if (tp->t_addr)
        !            58:                tp->t_state |= CARR_ON;
        !            59:        else while ((tp->t_state & CARR_ON) == 0)
        !            60:                sleep((caddr_t)&tp->t_rawq, TTIPRI);
        !            61:        UNLOCK;
        !            62:        tp->t_line = NTTYDISC;
        !            63:        (*linesw[tp->t_line].l_open)(dev, tp);
        !            64: }
        !            65: /*
        !            66:  * Close the tty associated with the given connection.
        !            67:  */
        !            68: chtclose(dev, flag)
        !            69:        dev_t dev;
        !            70:        int flag;
        !            71: {
        !            72:        register struct connection *conn;
        !            73:        register struct tty *tp;
        !            74: 
        !            75:        tp = &cht_tty[minor(dev)];
        !            76:        (*linesw[tp->t_line].l_close)(tp);
        !            77:        conn = (struct connection *)tp->t_addr;
        !            78:        if (tp->t_state & HUPCLS || conn->cn_state != CSOPEN) {
        !            79:                /*
        !            80:                 * We call the main close routine in RECORD mode, which
        !            81:                 * closes the connection directly.
        !            82:                 */
        !            83:                conn->cn_mode = CHRECORD;
        !            84:                chclose(conn, flag);
        !            85:                tp->t_addr = 0;
        !            86:                tp->t_state &= ~CARR_ON;
        !            87:                tp->t_lstate &= ~LSCHAOS;
        !            88:        }
        !            89:        ttyclose(tp);
        !            90: }
        !            91: 
        !            92: /*
        !            93:  * Read from a chaos channel that is a tty.
        !            94:  */
        !            95: chtread(dev)
        !            96:        dev_t dev;
        !            97: {
        !            98:        register struct tty *tp = &cht_tty[minor(dev)];
        !            99:        register struct connection *conn = (struct connection *)tp->t_addr;
        !           100:        /*
        !           101:         * Since ttys are quite possibly interactive, be sure
        !           102:         * to flush any output when input is desired.  It would
        !           103:         * be soon anyway due to timeouts.
        !           104:         */
        !           105:        spl6();
        !           106:        if (conn->cn_toutput != NOPKT && !chtfull(conn))
        !           107:                ch_sflush(conn);
        !           108:        spl0();
        !           109:        (*linesw[tp->t_line].l_read)(tp);
        !           110: }
        !           111: int chttyraw;
        !           112: /*
        !           113:  * Write to a chaos channel that is a tty.
        !           114:  */
        !           115: chtwrite(dev)
        !           116:        dev_t dev;
        !           117: {
        !           118:        register struct tty *tp = &cht_tty[minor(dev)];
        !           119: 
        !           120:        if (tp->t_flags & RAW) {
        !           121:                chttyraw++;
        !           122:                chwrite((struct connection *)tp->t_addr);
        !           123:        } else
        !           124:                (*linesw[tp->t_line].l_write)(tp);
        !           125: }
        !           126: /*
        !           127:  * We only allow tty ioctl's for a chaos tty.
        !           128:  * We could also allow chaos ioctl's if needed.
        !           129:  */
        !           130: chtioctl(dev, cmd, addr, flag)
        !           131:        dev_t dev;
        !           132:        caddr_t addr;
        !           133: {
        !           134:        register struct tty *tp = &cht_tty[minor(dev)];
        !           135: 
        !           136:        cmd = (*linesw[tp->t_line].l_ioctl)(tp, cmd, addr);
        !           137:        if (cmd == 0)
        !           138:                return;
        !           139:        if (ttioctl(tp, cmd, addr, flag)) {
        !           140:                if (cmd==TIOCSETP || cmd==TIOCSETN) {
        !           141:                        /*
        !           142:                         * Send virtual terminal codes here?
        !           143:                         */
        !           144: /*                     chparam(conn); */
        !           145:                }
        !           146:        } else switch(cmd) {
        !           147:        /*
        !           148:         * We need a remote terminal protocol here. - Yick.
        !           149:         */
        !           150:        case TIOCSBRK:
        !           151:                /* maybe someday a code for break on output ? */
        !           152:                break;
        !           153:        case TIOCCBRK:
        !           154:                break;
        !           155:        case TIOCSDTR:
        !           156:                break;
        !           157:        case TIOCCDTR:
        !           158:                break;
        !           159:        default:
        !           160:                u.u_error = ENOTTY;
        !           161:        }
        !           162: }
        !           163: /*
        !           164:  * Interrupt routine called when a new packet is available for a tty channel
        !           165:  * Basically empty the packet into the tty system.
        !           166:  * Called both from interrupt level when the read packet queue becomes
        !           167:  * non-empty and also (at high priority) from top level.  THe top level
        !           168:  * call is needed to retrieve data not queued at interrupt time due to
        !           169:  * input queue high water mark reached.
        !           170:  */
        !           171: chtrint(conn)
        !           172: struct connection *conn;
        !           173: {
        !           174:        register struct packet *pkt;
        !           175:        register struct tty *tp = conn->cn_ttyp;
        !           176:        register char *cp;
        !           177: 
        !           178:        while ((pkt = conn->cn_rhead) != NOPKT) {
        !           179:                if (ISDATOP(pkt) && conn->cn_state == CSOPEN)
        !           180:                        for (cp = &pkt->pk_cdata[conn->cn_roffset];
        !           181:                             pkt->pk_len != 0; pkt->pk_len--)
        !           182:                                if (tp->t_rawq.c_cc + tp->t_canq.c_cc >=
        !           183:                                    TTYHOG) {
        !           184:                                        conn->cn_roffset = cp - pkt->pk_cdata;
        !           185:                                        return;
        !           186:                                } else
        !           187:                                        (*linesw[tp->t_line].l_rint)
        !           188:                                                (*cp++ & 0377, tp);
        !           189:                ch_read(conn);
        !           190:        }
        !           191:        /*
        !           192:         * Flush any output since we might have echoed something at
        !           193:         * interrupt level.
        !           194:         */
        !           195:        if (conn->cn_toutput != NOPKT)
        !           196:                ch_sflush(conn);
        !           197: }
        !           198: /*
        !           199:  * Get more data if possible.  This is called from ttread (ntread) to
        !           200:  * see if more data can be read from the connection.
        !           201:  * It is only needed to account for the case where packets are not
        !           202:  * completely emptied at interrupt level due to input clist buffer
        !           203:  * overflow (>TTYHOG).  In this respect, chaos connections win better
        !           204:  * than ttys, which just throw the data away.
        !           205:  */
        !           206: chtinput(tp)
        !           207: register struct tty *tp;
        !           208: {
        !           209:        register int opl = spl6();
        !           210: 
        !           211:        chtrint((struct connection *)tp->t_addr);
        !           212:        splx(opl);
        !           213: }
        !           214: /*
        !           215:  * Interrupt routine called when more packets can again be sent after things
        !           216:  * block due to window full.
        !           217:  */
        !           218: chtxint(conn)
        !           219: register struct connection *conn;
        !           220: {
        !           221:        register struct tty *tp = conn->cn_ttyp;
        !           222:        register int s = spl6();
        !           223: 
        !           224:        if (tp->t_state & ASLEEP) {
        !           225:                tp->t_state &= ~ASLEEP;
        !           226:                wakeup((caddr_t)&tp->t_outq);
        !           227:        }
        !           228:        if (tp->t_line)
        !           229:                (*linesw[tp->t_line].l_start)(tp);
        !           230:        else
        !           231:                chtstart(tp);
        !           232:        splx(s);
        !           233: }
        !           234: /*
        !           235:  * Are we output flow controlled?
        !           236:  */
        !           237: chtblocked(tp)
        !           238:        struct tty *tp;
        !           239: {
        !           240:        register struct connection *conn = (struct connection *)tp->t_addr;
        !           241: 
        !           242:        return chtfull(conn);
        !           243: }
        !           244: /*
        !           245:  * Are we empty on output?
        !           246:  */
        !           247: chtnobuf(tp)
        !           248: struct tty *tp;
        !           249: {
        !           250:        register struct connection *conn = (struct connection *)tp->t_addr;
        !           251: 
        !           252:        return !conn->cn_toutput;
        !           253: }
        !           254: /*
        !           255:  * Flush any buffered output that we can.
        !           256:  * Called from high priority.
        !           257:  */
        !           258: chtflush(tp)
        !           259: struct tty *tp;
        !           260: {
        !           261:        register struct connection *conn = (struct connection *)tp->t_addr;
        !           262: 
        !           263:        
        !           264:        if (conn->cn_toutput) {
        !           265:                ch_free((caddr_t)conn->cn_toutput);
        !           266:                conn->cn_toutput = NOPKT;
        !           267:        }
        !           268: }
        !           269: 
        !           270: /*
        !           271:  * Start sending any buffered output.
        !           272:  * We just start sending any packet that is partially full.
        !           273:  */
        !           274: chtstart(tp)
        !           275:        struct tty *tp;
        !           276: {
        !           277:        ch_sflush((struct connection *)tp->t_addr);
        !           278: }
        !           279: /*
        !           280:  * Put out one character and return non-zero if we couldn't
        !           281:  */
        !           282: chtputc(c, tp)
        !           283: char c;
        !           284: struct tty *tp;
        !           285: {
        !           286:        return chtout(&c, 1, tp);
        !           287: }
        !           288: /*
        !           289:  * Send a contiguous array of bytes.
        !           290:  * Return the number we can't accept now.
        !           291:  * Packet allocation strategy:
        !           292:  * We allocate a packet that is at least large enough to hold all bytes
        !           293:  * remaining to be sent in this system call. We rely on the fact that
        !           294:  * packets are really powers of two in size and at least 16 bytes of data,
        !           295:  * since we don't round up our request at all.
        !           296:  * If our "clever" request fails, we try for a small packet.
        !           297:  */
        !           298: chtout(cp, cc, tp)
        !           299:        register char *cp;
        !           300:        struct tty *tp;
        !           301: {
        !           302:        register struct connection *conn = (struct connection *)tp->t_addr;
        !           303:        register struct packet *pkt;
        !           304:        register int n;
        !           305:        int sps = spl6();
        !           306:        extern int ttrstrt();
        !           307: 
        !           308:        if (conn->cn_state == CSOPEN &&
        !           309:            (tp->t_state & (TIMEOUT|BUSY|TTSTOP)) == 0) {
        !           310:                while (cc != 0) {
        !           311:                        if ((pkt = conn->cn_toutput) == NOPKT) {
        !           312:                                n = chtfull(conn) ? CHMAXDATA :
        !           313:                                        chroundup(u.u_count + cc);
        !           314:                                if ((pkt = pkalloc(n, 1)) == NOPKT) {
        !           315:                                        n = CHMINDATA;
        !           316:                                        if ((pkt = pkalloc(n, 1)) == NOPKT)
        !           317:                                                break;
        !           318:                                }
        !           319:                                pkt->pk_op = DATOP;
        !           320:                                pkt->pk_type = 0;
        !           321:                                pkt->pk_lenword = 0;
        !           322:                                conn->cn_troom = n;
        !           323:                                conn->cn_toutput = pkt;
        !           324:                        }
        !           325:                        if ((n = cc) > conn->cn_troom)
        !           326:                                n = conn->cn_troom;
        !           327:                        if (n != 0) {
        !           328:                                chmove(cp, &pkt->pk_cdata[pkt->pk_lenword], n);
        !           329:                                pkt->pk_time = Chclock;
        !           330:                                pkt->pk_lenword += n;
        !           331:                                cp += n;
        !           332:                        }
        !           333:                        cc -= n;
        !           334:                        if ((conn->cn_troom -= n) == 0)
        !           335:                                if (chtfull(conn))
        !           336:                                        break;
        !           337:                                else
        !           338:                                        ch_sflush(conn);
        !           339:                }
        !           340:        }
        !           341:        splx(sps);
        !           342:        return (cc);
        !           343: }
        !           344: /*
        !           345:  * Process a connection state change for a tty.
        !           346:  */
        !           347: chtnstate(conn)
        !           348: register struct connection *conn;
        !           349: {
        !           350:        register struct tty *tp;
        !           351: 
        !           352:        tp = conn->cn_ttyp;
        !           353:        switch (conn->cn_state) {
        !           354:        /*
        !           355:         * This shouldn't really happen since the connection shouldn't
        !           356:         * become a tty until it is open.
        !           357:         */
        !           358:        case CSOPEN:
        !           359:                if ((tp->t_state & CARR_ON) == 0) {
        !           360:                        wakeup((caddr_t)&tp->t_rawq);
        !           361:                        tp->t_state |= CARR_ON;
        !           362:                }
        !           363:                break;
        !           364:        case CSCLOSED:
        !           365:        case CSINCT:
        !           366:        case CSLOST:
        !           367:                if (tp->t_state & CARR_ON) {
        !           368:                        if ((tp->t_local & LNOHANG) == 0 &&
        !           369:                            tp->t_state & ISOPEN) {
        !           370:                                gsignal(tp->t_pgrp, SIGHUP);
        !           371: #ifdef SIGCONT
        !           372:                                gsignal(tp->t_pgrp, SIGCONT);
        !           373: #endif
        !           374:                                flushtty(tp, FREAD|FWRITE);
        !           375:                        }
        !           376:                        tp->t_state &= ~CARR_ON;
        !           377:                } else if (!(tp->t_state & ISOPEN)) {
        !           378:                        tp->t_addr = 0;
        !           379:                        ch_close(conn, NOPKT, 1);
        !           380:                        ch_buffree();
        !           381:                }
        !           382:                break;
        !           383:        default:
        !           384:                panic("chtnstate");
        !           385:        }
        !           386: }
        !           387: 
        !           388: 

unix.superglobalmegacorp.com

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