1*23390Smckusick /* 2*23390Smckusick * Copyright (c) 1982 Regents of the University of California. 3*23390Smckusick * All rights reserved. The Berkeley software License Agreement 4*23390Smckusick * specifies the terms and conditions for redistribution. 5*23390Smckusick * 6*23390Smckusick * @(#)tty_pty.c 6.12 (Berkeley) 06/08/85 7*23390Smckusick */ 82283Stoy 92281Stoy /* 102281Stoy * Pseudo-teletype Driver 112281Stoy * (Actually two drivers, requiring two entries in 'cdevsw') 122281Stoy */ 132314Stoy #include "pty.h" 142314Stoy 153206Swnj #if NPTY > 0 1617096Sbloom #include "param.h" 1717096Sbloom #include "systm.h" 1817096Sbloom #include "ioctl.h" 1917096Sbloom #include "tty.h" 2017096Sbloom #include "dir.h" 2117096Sbloom #include "user.h" 2217096Sbloom #include "conf.h" 2317096Sbloom #include "file.h" 2417096Sbloom #include "proc.h" 2517096Sbloom #include "uio.h" 2617096Sbloom #include "kernel.h" 276239Sroot 287475Ssam #if NPTY == 1 2918651Sbloom #undef NPTY 306239Sroot #define NPTY 32 /* crude XXX */ 317475Ssam #endif 322281Stoy 3316788Ssam #define BUFSIZ 100 /* Chunk size iomoved to/from user */ 344484Swnj 352281Stoy /* 3618651Sbloom * pts == /dev/tty[pqrs]? 3718651Sbloom * ptc == /dev/pty[pqrs]? 382281Stoy */ 394484Swnj struct tty pt_tty[NPTY]; 404484Swnj struct pt_ioctl { 415427Swnj int pt_flags; 425427Swnj int pt_gensym; 435427Swnj struct proc *pt_selr, *pt_selw; 4418651Sbloom u_char pt_send; 4518651Sbloom u_char pt_ucntl; 464484Swnj } pt_ioctl[NPTY]; 4718651Sbloom int npty = NPTY; /* for pstat -t */ 482281Stoy 495427Swnj #define PF_RCOLL 0x01 505427Swnj #define PF_WCOLL 0x02 515427Swnj #define PF_NBIO 0x04 525427Swnj #define PF_PKT 0x08 /* packet mode */ 535574Swnj #define PF_STOPPED 0x10 /* user told stopped */ 545894Swnj #define PF_REMOTE 0x20 /* remote and flow controlled input */ 556119Swnj #define PF_NOSTOP 0x40 5618651Sbloom #define PF_UCNTL 0x80 /* user control mode */ 572281Stoy 582281Stoy /*ARGSUSED*/ 592281Stoy ptsopen(dev, flag) 605396Sroot dev_t dev; 614484Swnj { 622281Stoy register struct tty *tp; 6318651Sbloom int error; 642281Stoy 6518651Sbloom #ifdef lint 6618651Sbloom npty = npty; 6718651Sbloom #endif 688563Sroot if (minor(dev) >= NPTY) 698563Sroot return (ENXIO); 702281Stoy tp = &pt_tty[minor(dev)]; 715408Swnj if ((tp->t_state & TS_ISOPEN) == 0) { 722427Swnj ttychars(tp); /* Set up default chars */ 7312642Ssam tp->t_ispeed = tp->t_ospeed = EXTB; 742427Swnj tp->t_flags = 0; /* No features (nor raw mode) */ 758563Sroot } else if (tp->t_state&TS_XCLUDE && u.u_uid != 0) 768563Sroot return (EBUSY); 774484Swnj if (tp->t_oproc) /* Ctrlr still around. */ 785408Swnj tp->t_state |= TS_CARR_ON; 795408Swnj while ((tp->t_state & TS_CARR_ON) == 0) { 805408Swnj tp->t_state |= TS_WOPEN; 812281Stoy sleep((caddr_t)&tp->t_rawq, TTIPRI); 822281Stoy } 8318651Sbloom error = (*linesw[tp->t_line].l_open)(dev, tp); 8418651Sbloom ptcwakeup(tp, FREAD|FWRITE); 8518651Sbloom return (error); 862281Stoy } 872281Stoy 882281Stoy ptsclose(dev) 895396Sroot dev_t dev; 905408Swnj { 912281Stoy register struct tty *tp; 922281Stoy 932281Stoy tp = &pt_tty[minor(dev)]; 942281Stoy (*linesw[tp->t_line].l_close)(tp); 956299Swnj ttyclose(tp); 9618651Sbloom ptcwakeup(tp, FREAD|FWRITE); 972281Stoy } 982281Stoy 997823Sroot ptsread(dev, uio) 1005396Sroot dev_t dev; 1017823Sroot struct uio *uio; 1024484Swnj { 1035894Swnj register struct tty *tp = &pt_tty[minor(dev)]; 1045894Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 1058521Sroot int error = 0; 1062281Stoy 1075894Swnj again: 1085894Swnj if (pti->pt_flags & PF_REMOTE) { 1095894Swnj while (tp == u.u_ttyp && u.u_procp->p_pgrp != tp->t_pgrp) { 11018651Sbloom if ((u.u_procp->p_sigignore & sigmask(SIGTTIN)) || 11118651Sbloom (u.u_procp->p_sigmask & sigmask(SIGTTIN)) || 1125894Swnj /* 1135894Swnj (u.u_procp->p_flag&SDETACH) || 1145894Swnj */ 1155894Swnj u.u_procp->p_flag&SVFORK) 1168521Sroot return (EIO); 1175894Swnj gsignal(u.u_procp->p_pgrp, SIGTTIN); 1185894Swnj sleep((caddr_t)&lbolt, TTIPRI); 1195408Swnj } 12018651Sbloom if (tp->t_canq.c_cc == 0) { 1218521Sroot if (tp->t_state & TS_NBIO) 1228521Sroot return (EWOULDBLOCK); 12318651Sbloom sleep((caddr_t)&tp->t_canq, TTIPRI); 1245894Swnj goto again; 1255894Swnj } 12618651Sbloom while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0) 12718651Sbloom if (ureadc(getc(&tp->t_canq), uio) < 0) { 1288521Sroot error = EFAULT; 1297823Sroot break; 1307823Sroot } 13118651Sbloom if (tp->t_canq.c_cc == 1) 13218651Sbloom (void) getc(&tp->t_canq); 13318651Sbloom if (tp->t_canq.c_cc) 1348521Sroot return (error); 1355894Swnj } else 1365894Swnj if (tp->t_oproc) 1378521Sroot error = (*linesw[tp->t_line].l_read)(tp, uio); 13818651Sbloom ptcwakeup(tp, FWRITE); 1398521Sroot return (error); 1402281Stoy } 1412281Stoy 1425408Swnj /* 1435408Swnj * Write to pseudo-tty. 1445408Swnj * Wakeups of controlling tty will happen 1455408Swnj * indirectly, when tty driver calls ptsstart. 1465408Swnj */ 1477823Sroot ptswrite(dev, uio) 1485396Sroot dev_t dev; 1497823Sroot struct uio *uio; 1504484Swnj { 1512281Stoy register struct tty *tp; 1522281Stoy 1532281Stoy tp = &pt_tty[minor(dev)]; 1548521Sroot if (tp->t_oproc == 0) 1558521Sroot return (EIO); 1568521Sroot return ((*linesw[tp->t_line].l_write)(tp, uio)); 1572281Stoy } 1582281Stoy 1595408Swnj /* 1605408Swnj * Start output on pseudo-tty. 1615408Swnj * Wake up process selecting or sleeping for input from controlling tty. 1625408Swnj */ 1632281Stoy ptsstart(tp) 1644484Swnj struct tty *tp; 1654484Swnj { 1665574Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1674484Swnj 1685408Swnj if (tp->t_state & TS_TTSTOP) 1692281Stoy return; 1705574Swnj if (pti->pt_flags & PF_STOPPED) { 1715574Swnj pti->pt_flags &= ~PF_STOPPED; 1725574Swnj pti->pt_send = TIOCPKT_START; 1735574Swnj } 17418651Sbloom ptcwakeup(tp, FREAD); 1755430Swnj } 1765430Swnj 17718651Sbloom ptcwakeup(tp, flag) 1785430Swnj struct tty *tp; 1795430Swnj { 1805430Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 1815430Swnj 18218651Sbloom if (flag & FREAD) { 18318651Sbloom if (pti->pt_selr) { 18418651Sbloom selwakeup(pti->pt_selr, pti->pt_flags & PF_RCOLL); 18518651Sbloom pti->pt_selr = 0; 18618651Sbloom pti->pt_flags &= ~PF_RCOLL; 18718651Sbloom } 18818651Sbloom wakeup((caddr_t)&tp->t_outq.c_cf); 1894484Swnj } 19018651Sbloom if (flag & FWRITE) { 19118651Sbloom if (pti->pt_selw) { 19218651Sbloom selwakeup(pti->pt_selw, pti->pt_flags & PF_WCOLL); 19318651Sbloom pti->pt_selw = 0; 19418651Sbloom pti->pt_flags &= ~PF_WCOLL; 19518651Sbloom } 19618651Sbloom wakeup((caddr_t)&tp->t_rawq.c_cf); 19718651Sbloom } 1982281Stoy } 1992281Stoy 2002281Stoy /*ARGSUSED*/ 2012281Stoy ptcopen(dev, flag) 2024484Swnj dev_t dev; 2034484Swnj int flag; 2044484Swnj { 2052281Stoy register struct tty *tp; 2065427Swnj struct pt_ioctl *pti; 2072281Stoy 2088563Sroot if (minor(dev) >= NPTY) 2098563Sroot return (ENXIO); 2102281Stoy tp = &pt_tty[minor(dev)]; 2118563Sroot if (tp->t_oproc) 2128563Sroot return (EIO); 2134484Swnj tp->t_oproc = ptsstart; 2145408Swnj if (tp->t_state & TS_WOPEN) 2152281Stoy wakeup((caddr_t)&tp->t_rawq); 2165408Swnj tp->t_state |= TS_CARR_ON; 2175427Swnj pti = &pt_ioctl[minor(dev)]; 2185427Swnj pti->pt_flags = 0; 2195427Swnj pti->pt_send = 0; 22018651Sbloom pti->pt_ucntl = 0; 2218563Sroot return (0); 2222281Stoy } 2232281Stoy 2242281Stoy ptcclose(dev) 2254484Swnj dev_t dev; 2264484Swnj { 2272281Stoy register struct tty *tp; 2282281Stoy 2292281Stoy tp = &pt_tty[minor(dev)]; 2305408Swnj if (tp->t_state & TS_ISOPEN) 2312281Stoy gsignal(tp->t_pgrp, SIGHUP); 2325408Swnj tp->t_state &= ~TS_CARR_ON; /* virtual carrier gone */ 23312753Ssam ttyflush(tp, FREAD|FWRITE); 2344484Swnj tp->t_oproc = 0; /* mark closed */ 2352281Stoy } 2362281Stoy 2377823Sroot ptcread(dev, uio) 2385427Swnj dev_t dev; 2397823Sroot struct uio *uio; 2404484Swnj { 2418521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 24218651Sbloom struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 24316788Ssam char buf[BUFSIZ]; 24416788Ssam int error = 0, cc; 2452281Stoy 24618651Sbloom /* 24718651Sbloom * We want to block until the slave 24818651Sbloom * is open, and there's something to read; 24918651Sbloom * but if we lost the slave or we're NBIO, 25018651Sbloom * then return the appropriate error instead. 25118651Sbloom */ 25218651Sbloom for (;;) { 25318651Sbloom if (tp->t_state&TS_ISOPEN) { 25418651Sbloom if (pti->pt_flags&PF_PKT && pti->pt_send) { 25518651Sbloom error = ureadc(pti->pt_send, uio); 25618651Sbloom if (error) 25718651Sbloom return (error); 25818651Sbloom pti->pt_send = 0; 25918651Sbloom return (0); 26018651Sbloom } 26118651Sbloom if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) { 26218651Sbloom error = ureadc(pti->pt_ucntl, uio); 26318651Sbloom if (error) 26418651Sbloom return (error); 26518651Sbloom pti->pt_ucntl = 0; 26618651Sbloom return (0); 26718651Sbloom } 26818651Sbloom if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) 26918651Sbloom break; 2705427Swnj } 27116788Ssam if ((tp->t_state&TS_CARR_ON) == 0) 27216788Ssam return (EIO); 2738521Sroot if (pti->pt_flags&PF_NBIO) 2748521Sroot return (EWOULDBLOCK); 2752281Stoy sleep((caddr_t)&tp->t_outq.c_cf, TTIPRI); 2765411Swnj } 27718651Sbloom if (pti->pt_flags & (PF_PKT|PF_UCNTL)) 27818651Sbloom error = ureadc(0, uio); 27916788Ssam while (uio->uio_resid > 0 && error == 0) { 28016788Ssam cc = q_to_b(&tp->t_outq, buf, MIN(uio->uio_resid, BUFSIZ)); 28116788Ssam if (cc <= 0) 2827823Sroot break; 28316788Ssam error = uiomove(buf, cc, UIO_READ, uio); 28416788Ssam } 2855408Swnj if (tp->t_outq.c_cc <= TTLOWAT(tp)) { 2865408Swnj if (tp->t_state&TS_ASLEEP) { 2875408Swnj tp->t_state &= ~TS_ASLEEP; 2885408Swnj wakeup((caddr_t)&tp->t_outq); 2895408Swnj } 2905408Swnj if (tp->t_wsel) { 2915408Swnj selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL); 2925408Swnj tp->t_wsel = 0; 2935408Swnj tp->t_state &= ~TS_WCOLL; 2945408Swnj } 2952281Stoy } 2968521Sroot return (error); 2972281Stoy } 2982281Stoy 2995427Swnj ptsstop(tp, flush) 3005427Swnj register struct tty *tp; 3015427Swnj int flush; 3025427Swnj { 3035427Swnj struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)]; 30418651Sbloom int flag; 3055427Swnj 3065574Swnj /* note: FLUSHREAD and FLUSHWRITE already ok */ 3075574Swnj if (flush == 0) { 3085574Swnj flush = TIOCPKT_STOP; 3095574Swnj pti->pt_flags |= PF_STOPPED; 31018651Sbloom } else 3115574Swnj pti->pt_flags &= ~PF_STOPPED; 3126119Swnj pti->pt_send |= flush; 31318651Sbloom /* change of perspective */ 31418651Sbloom flag = 0; 31518651Sbloom if (flush & FREAD) 31618651Sbloom flag |= FWRITE; 31718651Sbloom if (flush & FWRITE) 31818651Sbloom flag |= FREAD; 31918651Sbloom ptcwakeup(tp, flush); 3205427Swnj } 3215427Swnj 3225408Swnj ptcselect(dev, rw) 3234484Swnj dev_t dev; 3245408Swnj int rw; 3254484Swnj { 3264484Swnj register struct tty *tp = &pt_tty[minor(dev)]; 3275894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3284484Swnj struct proc *p; 3295430Swnj int s; 3304484Swnj 33118651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 3324484Swnj return (1); 3335430Swnj s = spl5(); 3345408Swnj switch (rw) { 3355408Swnj 3365408Swnj case FREAD: 33718651Sbloom if ((tp->t_state&TS_ISOPEN) && 33818651Sbloom (pti->pt_flags&PF_PKT && pti->pt_send || 33918651Sbloom pti->pt_flags&PF_UCNTL && pti->pt_ucntl || 34018651Sbloom tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)) { 3415430Swnj splx(s); 3425408Swnj return (1); 3435430Swnj } 3445427Swnj if ((p = pti->pt_selr) && p->p_wchan == (caddr_t)&selwait) 3455427Swnj pti->pt_flags |= PF_RCOLL; 3465408Swnj else 3475427Swnj pti->pt_selr = u.u_procp; 3485430Swnj break; 3495408Swnj 3505408Swnj case FWRITE: 35118651Sbloom if ((tp->t_state&TS_ISOPEN) && 35222731Skarels ((pti->pt_flags&PF_REMOTE) == 0 || tp->t_canq.c_cc == 0)) { 3535430Swnj splx(s); 3545408Swnj return (1); 3555430Swnj } 3565427Swnj if ((p = pti->pt_selw) && p->p_wchan == (caddr_t)&selwait) 3575427Swnj pti->pt_flags |= PF_WCOLL; 3585408Swnj else 3595427Swnj pti->pt_selw = u.u_procp; 3605430Swnj break; 3615408Swnj } 3625430Swnj splx(s); 3635430Swnj return (0); 3645396Sroot } 3654484Swnj 3667823Sroot ptcwrite(dev, uio) 3675408Swnj dev_t dev; 36818651Sbloom register struct uio *uio; 3694484Swnj { 3708521Sroot register struct tty *tp = &pt_tty[minor(dev)]; 37118651Sbloom register struct iovec *iov; 37218651Sbloom register char *cp; 37318651Sbloom register int cc = 0; 3742281Stoy char locbuf[BUFSIZ]; 3755408Swnj int cnt = 0; 3765894Swnj struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 3778521Sroot int error = 0; 3782281Stoy 37918651Sbloom again: 38018651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 38118651Sbloom goto block; 38218651Sbloom if (cnt == 0 && pti->pt_flags & PF_REMOTE) { 38318651Sbloom if (uio->uio_iovcnt <= 0) 38418651Sbloom return (0); 38518651Sbloom if (tp->t_canq.c_cc) 38618651Sbloom goto block; 3877823Sroot iov = uio->uio_iov; 38818651Sbloom if (cc == 0 && iov->iov_len) { 38918651Sbloom cc = MIN(iov->iov_len, BUFSIZ); 39018651Sbloom cp = locbuf; 39118651Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 39218651Sbloom if (error) 39318651Sbloom return (error); 39418651Sbloom /* check again for safety */ 39518651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 39618651Sbloom return (EIO); 39718651Sbloom if (tp->t_canq.c_cc) 39818651Sbloom goto block; 3997823Sroot } 40018651Sbloom if (cc) 40118651Sbloom (void) b_to_q(cp, cc, &tp->t_canq); 40218651Sbloom (void) putc(0, &tp->t_canq); 40318651Sbloom ttwakeup(tp); 40418651Sbloom wakeup((caddr_t)&tp->t_canq); 40518651Sbloom return (0); 40618651Sbloom } 40718651Sbloom while (uio->uio_iovcnt > 0) { 40818651Sbloom iov = uio->uio_iov; 40918651Sbloom if (cc == 0) { 41018651Sbloom if (iov->iov_len == 0) { 41118651Sbloom uio->uio_iovcnt--; 41218651Sbloom uio->uio_iov++; 41318651Sbloom continue; 4145894Swnj } 41518651Sbloom cc = MIN(iov->iov_len, BUFSIZ); 41618651Sbloom cp = locbuf; 41718651Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 41818651Sbloom if (error) 41918651Sbloom return (error); 42018651Sbloom /* check again for safety */ 42118651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 42218651Sbloom return (EIO); 4235894Swnj } 42418651Sbloom while (--cc >= 0) { 4254141Secc (*linesw[tp->t_line].l_rint)(*cp++, tp); 4265408Swnj cnt++; 4272281Stoy } 42818651Sbloom cc = 0; 42918651Sbloom } 43018651Sbloom return (0); 43118651Sbloom block: 43218651Sbloom /* 43318651Sbloom * Come here to wait for slave to open or for space 43418651Sbloom * in outq. 43518651Sbloom */ 43618651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 43718651Sbloom return (EIO); 43818651Sbloom if (pti->pt_flags & PF_NBIO) { 43918651Sbloom if (cnt == 0) 44018651Sbloom return (EWOULDBLOCK); 44118651Sbloom iov->iov_base -= cc; 44218651Sbloom iov->iov_len += cc; 44318651Sbloom uio->uio_resid += cc; 44418651Sbloom uio->uio_offset -= cc; 44518651Sbloom return (0); 44618651Sbloom } 44718651Sbloom sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 44818651Sbloom goto again; 4492281Stoy } 4502281Stoy 4512281Stoy /*ARGSUSED*/ 4527626Ssam ptyioctl(dev, cmd, data, flag) 4537626Ssam caddr_t data; 4544484Swnj dev_t dev; 4554484Swnj { 4566119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 4576119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 45818651Sbloom int stop, error; 4592281Stoy 4604484Swnj /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */ 4617626Ssam if (cdevsw[major(dev)].d_open == ptcopen) 4627626Ssam switch (cmd) { 4637626Ssam 4647626Ssam case TIOCPKT: 46518651Sbloom if (*(int *)data) { 46618651Sbloom if (pti->pt_flags & PF_UCNTL) 46718651Sbloom return (EINVAL); 4685427Swnj pti->pt_flags |= PF_PKT; 46918651Sbloom } else 4705427Swnj pti->pt_flags &= ~PF_PKT; 4718563Sroot return (0); 4727626Ssam 47318651Sbloom case TIOCUCNTL: 47418651Sbloom if (*(int *)data) { 47518651Sbloom if (pti->pt_flags & PF_PKT) 47618651Sbloom return (EINVAL); 47718651Sbloom pti->pt_flags |= PF_UCNTL; 47818651Sbloom } else 47918651Sbloom pti->pt_flags &= ~PF_UCNTL; 48018651Sbloom return (0); 48118651Sbloom 4827626Ssam case TIOCREMOTE: 4837626Ssam if (*(int *)data) 4845894Swnj pti->pt_flags |= PF_REMOTE; 4855894Swnj else 4865894Swnj pti->pt_flags &= ~PF_REMOTE; 48712753Ssam ttyflush(tp, FREAD|FWRITE); 4888563Sroot return (0); 4897626Ssam 4907626Ssam case FIONBIO: 4917626Ssam if (*(int *)data) 4925427Swnj pti->pt_flags |= PF_NBIO; 4935411Swnj else 4945427Swnj pti->pt_flags &= ~PF_NBIO; 4958563Sroot return (0); 4967626Ssam 4977626Ssam case TIOCSETP: 4987626Ssam while (getc(&tp->t_outq) >= 0) 4997626Ssam ; 5007626Ssam break; 5015411Swnj } 50217182Smckusick error = ttioctl(tp, cmd, data, flag); 50318651Sbloom if (error < 0) { 50418651Sbloom if (pti->pt_flags & PF_UCNTL && 50518651Sbloom (cmd & ~0xff) == _IO(u,0)) { 50618651Sbloom if (cmd & 0xff) { 50718651Sbloom pti->pt_ucntl = (u_char)cmd; 50818651Sbloom ptcwakeup(tp, FREAD); 50918651Sbloom } 51018651Sbloom return (0); 51118651Sbloom } 5128563Sroot error = ENOTTY; 51318651Sbloom } 51418651Sbloom stop = (tp->t_flags & RAW) == 0 && 51518651Sbloom tp->t_stopc == CTRL(s) && tp->t_startc == CTRL(q); 5166119Swnj if (pti->pt_flags & PF_NOSTOP) { 5176119Swnj if (stop) { 5186119Swnj pti->pt_send &= TIOCPKT_NOSTOP; 5196119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 5206119Swnj pti->pt_flags &= ~PF_NOSTOP; 52118651Sbloom ptcwakeup(tp, FREAD); 5226119Swnj } 5236119Swnj } else { 52418651Sbloom if (!stop) { 5256119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 5266119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 5276119Swnj pti->pt_flags |= PF_NOSTOP; 52818651Sbloom ptcwakeup(tp, FREAD); 5296119Swnj } 5306119Swnj } 5318563Sroot return (error); 5322281Stoy } 5332313Stoy #endif 534