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

unix.superglobalmegacorp.com

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