Annotation of coherent/b/STREAMS/io.386/pty.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * File:       pty.c
                      3:  *
                      4:  * Purpose:    pseudoterminal device driver
                      5:  *
                      6:  *     Master devices are named /dev/pty[pqrs][0-f].
                      7:  *     Corresponding slaves are /dev/tty[pqrs][0-f].
                      8:  *
                      9:  *     Minor numbers are 0..127 assigned in increasing order,
                     10:  *     plus 128 for master device.
                     11:  *
                     12:  *     Output written to master appears as input to slave and
                     13:  *     vice versa.  Data path is:
                     14:  *
                     15:  *             app     master          slave   line    app
                     16:  *             using   device  shunt   device  disc.   using
                     17:  *             master  driver          driver  module  slave
                     18:  *
                     19:  *      slave read does ttread() which is fed by ttin()
                     20:  *     master write does ttin()
                     21:  *
                     22:  *      slave write does ttwrite() which is fed by ttout()
                     23:  *     master read does ttout()
                     24:  *
                     25:  * $Log:       pty.c,v $
                     26:  * Revision 2.2  93/07/26  15:32:12  nigel
                     27:  * Nigel's R80
                     28:  * 
                     29:  * Revision 1.4  93/04/14  10:12:10  root
                     30:  * r75
                     31:  * 
                     32:  * Revision 1.3  92/07/16  16:35:29  hal
                     33:  * Kernel #58
                     34:  * 
                     35:  * Revision 1.2  92/03/18  07:45:33  hal
                     36:  * master device polling added
                     37:  * 
                     38:  * Revision 1.1  92/03/16  12:57:31  hal
                     39:  * Initial revision
                     40:  * 
                     41:  */
                     42: 
                     43: /*
                     44:  * -----------------------------------------------------------------
                     45:  * Includes.
                     46:  */
                     47: #include <sys/coherent.h>
                     48: #include <sys/stat.h>
                     49: #include <sys/proc.h>
                     50: #include <sys/tty.h>           /* indirectly includes sgtty.h */
                     51: #include <sys/con.h>
                     52: #include <sys/devices.h>
                     53: #include <sys/errno.h>
                     54: #include <poll.h>
                     55: #include <sys/sched.h>         /* CVTTOUT, IVTTOUT, SVTTOUT */
                     56: 
                     57: /*
                     58:  * -----------------------------------------------------------------
                     59:  * Definitions.
                     60:  *     Constants.
                     61:  *     Macros with argument lists.
                     62:  *     Typedefs.
                     63:  *     Enums.
                     64:  */
                     65: 
                     66: #define channel(dev)   (dev & 0x7F)
                     67: #define master(dev)    (dev & 0x80)
                     68: #ifdef _I386
                     69: #define        EEBUSY  EBUSY
                     70: #else
                     71: #define        EEBUSY  EDBUSY
                     72: #endif
                     73: 
                     74: /*
                     75:  * Explanation of p_mopen values:
                     76:  * 0 - master is closed
                     77:  * 1 - master open, waiting for slave to open
                     78:  * 2 - master and slave both open
                     79:  * 3 - master open, slave has closed
                     80:  */
                     81: 
                     82: typedef struct pty {
                     83:        TTY p_tp;
                     84:        event_t p_iev;
                     85:        event_t p_oev;
                     86:        char p_mopen;
                     87:        char p_asleep;  /* master is asleep in read or write awaiting slave */
                     88:        char p_ttwr;    /* slave is suspended in mid ttwrite() */
                     89: } PTY;
                     90: 
                     91: /*
                     92:  * -----------------------------------------------------------------
                     93:  * Functions.
                     94:  *     Import Functions.
                     95:  *     Export Functions.
                     96:  *     Local Functions.
                     97:  */
                     98: int nulldev();
                     99: void pollwake();
                    100: 
                    101: /*
                    102:  * Configuration functions (local functions).
                    103:  */
                    104: static void ptyclose();
                    105: static void ptyioctl();
                    106: static void ptyload();
                    107: static void ptyopen();
                    108: static void ptyread();
                    109: static void ptyunload();
                    110: static void ptywrite();
                    111: static void ptystart();
                    112: static int ptypoll();
                    113: 
                    114: /*
                    115:  * Support functions (local functions).
                    116:  */
                    117: static void ptycycle();
                    118: 
                    119: /*
                    120:  * -----------------------------------------------------------------
                    121:  * Global Data.
                    122:  *     Import Variables.
                    123:  *     Export Variables.
                    124:  *     Local Variables.
                    125:  */
                    126: int NUPTY = 8;
                    127: 
                    128: /*
                    129:  * Configuration table (export data).
                    130:  */
                    131: CON ptycon ={
                    132:        DFCHR|DFPOL,                    /* Flags */
                    133:        PTY_MAJOR,                      /* Major index */
                    134:        ptyopen,                        /* Open */
                    135:        ptyclose,                       /* Close */
                    136:        nulldev,                        /* Block */
                    137:        ptyread,                        /* Read */
                    138:        ptywrite,                       /* Write */
                    139:        ptyioctl,                       /* Ioctl */
                    140:        nulldev,                        /* Powerfail */
                    141:        nulldev,                        /* Timeout */
                    142:        ptyload,                        /* Load */
                    143:        ptyunload,                      /* Unload */
                    144:        ptypoll                         /* Poll */
                    145: };
                    146: 
                    147: static PTY * p;
                    148: 
                    149: /*
                    150:  * -----------------------------------------------------------------
                    151:  * Code.
                    152:  */
                    153: 
                    154: /*
                    155:  * ptyload()
                    156:  */
                    157: static void
                    158: ptyload()
                    159: {
                    160:        int i;
                    161:        TTY * tp;
                    162: 
                    163:        if ((p = (PTY *)kalloc(NUPTY*sizeof(PTY))) == 0) {
                    164:                printf("ptyload: can't allocate %s pty's\n", NUPTY);
                    165:                return;
                    166:        }
                    167:        kclear(p, NUPTY*sizeof(PTY));
                    168:        for (i = 0; i < NUPTY; i++) {
                    169:                tp = &p[i].p_tp;
                    170:                tp->t_cs_sel  = cs_sel();
                    171:                tp->t_start   = ptystart;
                    172:                tp->t_param   = nulldev;
                    173:                tp->t_ddp     = (char *)i;
                    174:        }
                    175: }
                    176: 
                    177: /*
                    178:  * ptyunload()
                    179:  */
                    180: static void
                    181: ptyunload()
                    182: {
                    183:        if (p)
                    184:                kfree(p);
                    185:        printf("pty driver unloaded\n");
                    186: }
                    187: 
                    188: /*
                    189:  * ptyopen()
                    190:  */
                    191: static void
                    192: ptyopen(dev, mode)
                    193: dev_t dev;
                    194: int mode;
                    195: {
                    196:        int chan = channel(dev);
                    197:        PTY * pp = p + chan;
                    198:        TTY * tp = &pp->p_tp;
                    199: 
                    200:        if (chan >= NUPTY) {
                    201:                u.u_error = ENXIO;
                    202:                goto open_done;
                    203:        }
                    204: 
                    205:        if (master(dev)){
                    206:                if (pp->p_mopen) {
                    207:                        u.u_error = EEBUSY;
                    208:                        goto open_done;
                    209:                }
                    210:                if (tp->t_open)
                    211:                        pp->p_mopen = 2;
                    212:                else
                    213:                        pp->p_mopen = 1;
                    214:                wakeup((char *)(&tp->t_open));
                    215:                ptycycle(chan);
                    216:        } else {
                    217:                tp->t_flags |= T_HOPEN | T_STOP;
                    218:                for (;;) {      /* wait for carrier */
                    219:                        if (pp->p_mopen)
                    220:                                break;
                    221:                        /* PTY driver is waiting for carrier.  */
                    222: #ifdef _I386
                    223:                        if (x_sleep ((char *) & tp->t_open, pritty,
                    224:                                     slpriSigCatch, "ptycd")
                    225:                            == PROCESS_SIGNALLED) {
                    226: #else
                    227:                        v_sleep((char *)(&tp->t_open), CVTTOUT, IVTTOUT,
                    228:                          SVTTOUT, "ptycd");
                    229:                        if (nondsig ()) {  /* signal? */
                    230: #endif
                    231:                                u.u_error = EINTR;
                    232:                                tp->t_flags &= ~(T_HOPEN | T_STOP);
                    233:                                goto open_done;
                    234:                        }
                    235:                }
                    236:                tp->t_flags |= T_CARR;
                    237:                tp->t_flags &= ~(T_HOPEN | T_STOP);
                    238:                ttopen(tp);
                    239:                tp->t_open++;
                    240:                ttsetgrp(tp, dev, mode);
                    241:                if (pp->p_mopen == 1 || pp->p_mopen == 3)
                    242:                        pp->p_mopen = 2;
                    243:        }
                    244: open_done:;
                    245: }
                    246: 
                    247: /*
                    248:  * ptyclose()
                    249:  */
                    250: static void
                    251: ptyclose(dev, mode)
                    252: dev_t dev;
                    253: int mode;
                    254: {
                    255:        int chan = channel(dev);
                    256:        PTY * pp = p + chan;
                    257:        TTY * tp = &pp->p_tp;
                    258: 
                    259:        if (chan >= NUPTY) {
                    260:                u.u_error = ENXIO;
                    261:                return;
                    262:        }
                    263: 
                    264:        if (master(dev)){
                    265:                if (pp->p_mopen) {
                    266:                        tp->t_flags &= ~T_CARR;
                    267:                        tthup(tp);
                    268:                        pp->p_mopen = 0;
                    269:                }
                    270:        } else {
                    271:                if (--tp->t_open == 0) {
                    272:                        ttclose(tp);
                    273:                        if (pp->p_mopen == 2)
                    274:                                pp->p_mopen = 3;
                    275:                        wakeup(&pp->p_mopen);
                    276:                }
                    277:        }
                    278: }
                    279: 
                    280: /*
                    281:  * ptyread()
                    282:  */
                    283: static void
                    284: ptyread(dev, iop)
                    285: dev_t dev;
                    286: register IO * iop;
                    287: {
                    288:        int chan = channel(dev);
                    289:        PTY * pp = p + chan;
                    290:        TTY * tp = &pp->p_tp;
                    291:        int c;
                    292: 
                    293:        if (master(dev)){
                    294:                int char_read = 0;
                    295: 
                    296:                while (iop->io_ioc) {
                    297:                        c = ttout(tp);
                    298:                        if (c == -1) { /* nothing to fetch */
                    299:                                if (char_read) {
                    300:                                        ttstart(tp);
                    301:                                        goto read_done;
                    302:                                }
                    303:                                if (iop->io_flag & (IONDLY | IONONBLOCK)) {
                    304:                                        if (tp->t_group == 0 ||
                    305:                                            (iop->io_flag & IONONBLOCK) != 0)
                    306:                                                u.u_error = EAGAIN;
                    307:                                        goto read_done;
                    308:                                }
                    309:                                if (pp->p_mopen == 3) {
                    310:                                        u.u_error = EIO;
                    311:                                        goto read_done;
                    312:                                }
                    313:                                ttstart(tp);
                    314:                                pp->p_asleep = 1;
                    315:                                /* The PTY driver is waiting for a read.  */
                    316: #ifdef _I386
                    317:                                if (x_sleep (& pp->p_mopen, pritty,
                    318:                                             slpriSigCatch, "ptyread")
                    319:                                    == PROCESS_SIGNALLED) {
                    320: #else
                    321:                                v_sleep(&pp->p_mopen, CVTTOUT, IVTTOUT,
                    322:                                  SVTTOUT, "ptyread");
                    323:                                if (nondsig ()) {
                    324: #endif
                    325:                                        u.u_error = EINTR;
                    326:                                        goto read_done;
                    327:                                }
                    328:                        } else {
                    329:                                ioputc(c, iop);
                    330:                                char_read = 1;
                    331:                        }
                    332:                }
                    333: read_done:;
                    334:        } else {
                    335: #if 0
                    336:                if (pp->p_asleep) {
                    337:                        pp->p_asleep = 0;
                    338:                        wakeup(&pp->p_mopen);
                    339:                }
                    340:                pollwake(&pp->p_oev);
                    341:                ttread(tp, iop);
                    342: #else
                    343:                pp->p_asleep = 0;       /* ttread0 will awaken the sleeper */
                    344:                ttread0(tp,iop,wakeup,&pp->p_mopen,pollwake,&pp->p_oev);
                    345: #endif
                    346:        }
                    347: }
                    348: 
                    349: /*
                    350:  * ptywrite()
                    351:  */
                    352: static void
                    353: ptywrite(dev, iop)
                    354: dev_t dev;
                    355: register IO * iop;
                    356: {
                    357:        int chan = channel(dev);
                    358:        PTY * pp = p + chan;
                    359:        TTY * tp = &pp->p_tp;
                    360:        int c;
                    361: 
                    362:        if (master(dev)){
                    363:                while (iop->io_ioc) {
                    364:                        if (!ttinp(tp)) {
                    365:                                if (iop->io_flag & (IONDLY | IONONBLOCK)) {
                    366:                                        u.u_error = EAGAIN;
                    367:                                        goto write_done;
                    368:                                }
                    369:                                if (pp->p_mopen == 3) {
                    370:                                        u.u_error = EIO;
                    371:                                        goto write_done;
                    372:                                }
                    373:                                pp->p_asleep = 1;
                    374:                                /* The PTY driver is waiting for a write.  */
                    375: #ifdef _I386
                    376:                                if (x_sleep (& pp->p_mopen, pritty,
                    377:                                             slpriSigCatch, "ptywrite")
                    378:                                    == PROCESS_SIGNALLED) {
                    379: #else
                    380:                                v_sleep(&pp->p_mopen, CVTTOUT, IVTTOUT,
                    381:                                  SVTTOUT, "ptywrite");
                    382:                                if (nondsig ()) {  /* signal? */
                    383: #endif
                    384:                                        u.u_error = EINTR;
                    385:                                        goto write_done;
                    386:                                }
                    387:                        }
                    388:                        c = iogetc(iop);
                    389:                        ttin(tp, c);
                    390:                }
                    391:                wakeup(&pp->p_mopen);
                    392:        } else {
                    393:                pp->p_ttwr = 1;
                    394:                ttwrite0(tp,iop,wakeup,&pp->p_mopen,pollwake,&pp->p_iev);
                    395:                pp->p_ttwr = 0;
                    396:        }
                    397: write_done:;
                    398: }
                    399: 
                    400: /*
                    401:  * ptyioctl()
                    402:  */
                    403: static void
                    404: ptyioctl(dev, com, vec)
                    405: dev_t  dev;
                    406: int    com;
                    407: struct sgttyb *vec;
                    408: {
                    409:        int chan = channel(dev);
                    410:        PTY * pp = p + chan;
                    411:        TTY * tp = &pp->p_tp;
                    412: 
                    413:        if (master(dev)){
                    414:                u.u_error = EINVAL;
                    415:        } else {
                    416:                ttioctl(tp, com, vec);
                    417:        }
                    418: }
                    419: 
                    420: /*
                    421:  * ptystart()
                    422:  */
                    423: static void
                    424: ptystart(tp)
                    425: TTY * tp;
                    426: {
                    427:        int chan = (int)tp->t_ddp;
                    428:        PTY * pp = p + chan;
                    429: 
                    430:        if (chan >= 0 && chan < NUPTY) {
                    431:                if (pp->p_ttwr)
                    432:                        wakeup(&pp->p_mopen);
                    433:        }
                    434: }
                    435: 
                    436: /*
                    437:  * ptypoll()
                    438:  */
                    439: static int
                    440: ptypoll(dev, ev, msec)
                    441: dev_t dev;
                    442: int ev;
                    443: int msec;
                    444: {
                    445:        int chan = channel(dev);
                    446:        PTY * pp = p + chan;
                    447:        TTY * tp = &pp->p_tp;
                    448:        int ret;
                    449: 
                    450:        if (master(dev)) {
                    451:                /*
                    452:                 * Priority polls not supported.
                    453:                 */
                    454:                ev &= (POLLIN | POLLOUT);
                    455: 
                    456:                /*
                    457:                 * Input poll with no data present.
                    458:                 */
                    459:                if ((ev & POLLIN) && (ttoutp(tp) == 0)) {
                    460: 
                    461:                        /*
                    462:                         * Blocking input poll.
                    463:                         */
                    464:                        if (msec != 0) {
                    465:                                pollopen(&pp->p_iev);
                    466:                        }
                    467: 
                    468:                        /*
                    469:                         * Second look to avoid interrupt race.
                    470:                         */
                    471:                        if (ttoutp(tp) == 0)
                    472:                                ev &= ~POLLIN;
                    473:                }
                    474: 
                    475:                /*
                    476:                 * Output poll with no space.
                    477:                 */
                    478:                if ((ev & POLLOUT) && (ttinp(tp) == 0)) {
                    479: 
                    480:                        /*
                    481:                         * Blocking output poll.
                    482:                         */
                    483:                        if (msec != 0) {
                    484:                                pollopen(&pp->p_oev);
                    485:                        }
                    486: 
                    487:                        /*
                    488:                         * Second look to avoid interrupt race.
                    489:                         */
                    490:                        if (ttinp(tp) == 0)
                    491:                                ev &= ~POLLOUT;
                    492:                }
                    493: 
                    494:                ret = ev;
                    495:        } else
                    496:                ret = ttpoll(tp, ev, msec);
                    497:        return ret;
                    498: }
                    499: 
                    500: /*
                    501:  * ptycycle()
                    502:  *
                    503:  * Do a wakeup of any sleeping pty's at regular intervals.
                    504:  */
                    505: static void
                    506: ptycycle(chan)
                    507: int chan;
                    508: {
                    509:        PTY * pp = p + chan;
                    510:        TTY * tp = &pp->p_tp;
                    511: 
                    512:        /*
                    513:         * Do wakeups.
                    514:         */
                    515:        if (pp->p_asleep || pp->p_ttwr) {
                    516:                wakeup(&pp->p_mopen);
                    517:                pollwake(&pp->p_oev);
                    518:        }
                    519: 
                    520:        /*
                    521:         * Schedule next cycle.
                    522:         */
                    523:        if (pp->p_mopen)
                    524:                timeout(&tp->t_rawtim, HZ/10, ptycycle, chan);
                    525: }

unix.superglobalmegacorp.com

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