Annotation of researchv8dc/sys/chunix/chtty.c, revision 1.1.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.