123390Smckusick /* 223390Smckusick * Copyright (c) 1982 Regents of the University of California. 323390Smckusick * All rights reserved. The Berkeley software License Agreement 423390Smckusick * specifies the terms and conditions for redistribution. 523390Smckusick * 6*23633Sbloom * @(#)tty_pty.c 6.13 (Berkeley) 06/21/85 723390Smckusick */ 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; 319*23633Sbloom ptcwakeup(tp, flag); 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; 382*23633Sbloom if (pti->pt_flags & PF_REMOTE) { 38318651Sbloom if (tp->t_canq.c_cc) 38418651Sbloom goto block; 385*23633Sbloom while (uio->uio_iovcnt > 0 && tp->t_canq.c_cc < TTYHOG - 1) { 386*23633Sbloom iov = uio->uio_iov; 387*23633Sbloom if (iov->iov_len == 0) { 388*23633Sbloom uio->uio_iovcnt--; 389*23633Sbloom uio->uio_iov++; 390*23633Sbloom continue; 391*23633Sbloom } 392*23633Sbloom if (cc == 0) { 393*23633Sbloom cc = MIN(iov->iov_len, BUFSIZ); 394*23633Sbloom cc = MIN(cc, TTYHOG - 1 - tp->t_canq.c_cc); 395*23633Sbloom cp = locbuf; 396*23633Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 397*23633Sbloom if (error) 398*23633Sbloom return (error); 399*23633Sbloom /* check again for safety */ 400*23633Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 401*23633Sbloom return (EIO); 402*23633Sbloom } 403*23633Sbloom if (cc) 404*23633Sbloom (void) b_to_q(cp, cc, &tp->t_canq); 405*23633Sbloom cc = 0; 4067823Sroot } 40718651Sbloom (void) putc(0, &tp->t_canq); 40818651Sbloom ttwakeup(tp); 40918651Sbloom wakeup((caddr_t)&tp->t_canq); 41018651Sbloom return (0); 41118651Sbloom } 41218651Sbloom while (uio->uio_iovcnt > 0) { 41318651Sbloom iov = uio->uio_iov; 41418651Sbloom if (cc == 0) { 41518651Sbloom if (iov->iov_len == 0) { 41618651Sbloom uio->uio_iovcnt--; 41718651Sbloom uio->uio_iov++; 41818651Sbloom continue; 4195894Swnj } 42018651Sbloom cc = MIN(iov->iov_len, BUFSIZ); 42118651Sbloom cp = locbuf; 42218651Sbloom error = uiomove(cp, cc, UIO_WRITE, uio); 42318651Sbloom if (error) 42418651Sbloom return (error); 42518651Sbloom /* check again for safety */ 42618651Sbloom if ((tp->t_state&TS_ISOPEN) == 0) 42718651Sbloom return (EIO); 4285894Swnj } 429*23633Sbloom while (cc > 0) { 430*23633Sbloom if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 && 431*23633Sbloom (tp->t_canq.c_cc > 0)) { 432*23633Sbloom wakeup((caddr_t)&tp->t_rawq); 433*23633Sbloom goto block; 434*23633Sbloom } 4354141Secc (*linesw[tp->t_line].l_rint)(*cp++, tp); 4365408Swnj cnt++; 437*23633Sbloom cc--; 4382281Stoy } 43918651Sbloom cc = 0; 44018651Sbloom } 44118651Sbloom return (0); 44218651Sbloom block: 44318651Sbloom /* 444*23633Sbloom * Come here to wait for slave to open, for space 445*23633Sbloom * in outq, or space in rawq. 44618651Sbloom */ 44718651Sbloom if ((tp->t_state&TS_CARR_ON) == 0) 44818651Sbloom return (EIO); 44918651Sbloom if (pti->pt_flags & PF_NBIO) { 45018651Sbloom iov->iov_base -= cc; 45118651Sbloom iov->iov_len += cc; 45218651Sbloom uio->uio_resid += cc; 45318651Sbloom uio->uio_offset -= cc; 454*23633Sbloom if (cnt == 0) 455*23633Sbloom return (EWOULDBLOCK); 45618651Sbloom return (0); 45718651Sbloom } 45818651Sbloom sleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI); 45918651Sbloom goto again; 4602281Stoy } 4612281Stoy 4622281Stoy /*ARGSUSED*/ 4637626Ssam ptyioctl(dev, cmd, data, flag) 4647626Ssam caddr_t data; 4654484Swnj dev_t dev; 4664484Swnj { 4676119Swnj register struct tty *tp = &pt_tty[minor(dev)]; 4686119Swnj register struct pt_ioctl *pti = &pt_ioctl[minor(dev)]; 46918651Sbloom int stop, error; 4702281Stoy 4714484Swnj /* IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG ??? */ 4727626Ssam if (cdevsw[major(dev)].d_open == ptcopen) 4737626Ssam switch (cmd) { 4747626Ssam 4757626Ssam case TIOCPKT: 47618651Sbloom if (*(int *)data) { 47718651Sbloom if (pti->pt_flags & PF_UCNTL) 47818651Sbloom return (EINVAL); 4795427Swnj pti->pt_flags |= PF_PKT; 48018651Sbloom } else 4815427Swnj pti->pt_flags &= ~PF_PKT; 4828563Sroot return (0); 4837626Ssam 48418651Sbloom case TIOCUCNTL: 48518651Sbloom if (*(int *)data) { 48618651Sbloom if (pti->pt_flags & PF_PKT) 48718651Sbloom return (EINVAL); 48818651Sbloom pti->pt_flags |= PF_UCNTL; 48918651Sbloom } else 49018651Sbloom pti->pt_flags &= ~PF_UCNTL; 49118651Sbloom return (0); 49218651Sbloom 4937626Ssam case TIOCREMOTE: 4947626Ssam if (*(int *)data) 4955894Swnj pti->pt_flags |= PF_REMOTE; 4965894Swnj else 4975894Swnj pti->pt_flags &= ~PF_REMOTE; 49812753Ssam ttyflush(tp, FREAD|FWRITE); 4998563Sroot return (0); 5007626Ssam 5017626Ssam case FIONBIO: 5027626Ssam if (*(int *)data) 5035427Swnj pti->pt_flags |= PF_NBIO; 5045411Swnj else 5055427Swnj pti->pt_flags &= ~PF_NBIO; 5068563Sroot return (0); 5077626Ssam 5087626Ssam case TIOCSETP: 5097626Ssam while (getc(&tp->t_outq) >= 0) 5107626Ssam ; 5117626Ssam break; 5125411Swnj } 51317182Smckusick error = ttioctl(tp, cmd, data, flag); 51418651Sbloom if (error < 0) { 51518651Sbloom if (pti->pt_flags & PF_UCNTL && 51618651Sbloom (cmd & ~0xff) == _IO(u,0)) { 51718651Sbloom if (cmd & 0xff) { 51818651Sbloom pti->pt_ucntl = (u_char)cmd; 51918651Sbloom ptcwakeup(tp, FREAD); 52018651Sbloom } 52118651Sbloom return (0); 52218651Sbloom } 5238563Sroot error = ENOTTY; 52418651Sbloom } 52518651Sbloom stop = (tp->t_flags & RAW) == 0 && 52618651Sbloom tp->t_stopc == CTRL(s) && tp->t_startc == CTRL(q); 5276119Swnj if (pti->pt_flags & PF_NOSTOP) { 5286119Swnj if (stop) { 5296119Swnj pti->pt_send &= TIOCPKT_NOSTOP; 5306119Swnj pti->pt_send |= TIOCPKT_DOSTOP; 5316119Swnj pti->pt_flags &= ~PF_NOSTOP; 53218651Sbloom ptcwakeup(tp, FREAD); 5336119Swnj } 5346119Swnj } else { 53518651Sbloom if (!stop) { 5366119Swnj pti->pt_send &= ~TIOCPKT_DOSTOP; 5376119Swnj pti->pt_send |= TIOCPKT_NOSTOP; 5386119Swnj pti->pt_flags |= PF_NOSTOP; 53918651Sbloom ptcwakeup(tp, FREAD); 5406119Swnj } 5416119Swnj } 5428563Sroot return (error); 5432281Stoy } 5442313Stoy #endif 545