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

unix.superglobalmegacorp.com

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