tty_pty.c revision 1.22 1 /*
2 * Copyright (c) 1982, 1986, 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 *
33 * from: @(#)tty_pty.c 8.2 (Berkeley) 9/23/93
34 * $Id: tty_pty.c,v 1.22 1994/05/12 03:48:36 cgd Exp $
35 */
36
37 /*
38 * Pseudo-teletype Driver
39 * (Actually two drivers, requiring two entries in 'cdevsw')
40 */
41 #include "pty.h" /* XXX */
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/ioctl.h>
46 #include <sys/proc.h>
47 #include <sys/tty.h>
48 #include <sys/conf.h>
49 #include <sys/file.h>
50 #include <sys/uio.h>
51 #include <sys/kernel.h>
52 #include <sys/vnode.h>
53
54 #if NPTY == 1
55 #undef NPTY
56 #define NPTY 32 /* crude XXX */
57 #endif
58
59 #define BUFSIZ 100 /* Chunk size iomoved to/from user */
60
61 /*
62 * pts == /dev/tty[pqrs]?
63 * ptc == /dev/pty[pqrs]?
64 */
65 struct tty *pt_tty[NPTY]; /* XXX */
66 struct pt_ioctl {
67 int pt_flags;
68 struct selinfo pt_selr, pt_selw;
69 u_char pt_send;
70 u_char pt_ucntl;
71 } pt_ioctl[NPTY]; /* XXX */
72 int npty = NPTY; /* for pstat -t */
73
74 #define PF_PKT 0x08 /* packet mode */
75 #define PF_STOPPED 0x10 /* user told stopped */
76 #define PF_REMOTE 0x20 /* remote and flow controlled input */
77 #define PF_NOSTOP 0x40
78 #define PF_UCNTL 0x80 /* user control mode */
79
80 void ptsstop __P((struct tty *, int));
81
82 /*
83 * Establish n (or default if n is 1) ptys in the system.
84 *
85 * XXX cdevsw & pstat require the array `pty[]' to be an array
86 */
87 void
88 ptyattach(n)
89 int n;
90 {
91 #ifdef notyet
92 char *mem;
93 register u_long ntb;
94 #define DEFAULT_NPTY 32
95
96 /* maybe should allow 0 => none? */
97 if (n <= 1)
98 n = DEFAULT_NPTY;
99 ntb = n * sizeof(struct tty);
100 mem = malloc(ntb + ALIGNBYTES + n * sizeof(struct pt_ioctl),
101 M_DEVBUF, M_WAITOK);
102 pt_tty = (struct tty *)mem;
103 mem = (char *)ALIGN(mem + ntb);
104 pt_ioctl = (struct pt_ioctl *)mem;
105 npty = n;
106 #endif
107 }
108
109 /*ARGSUSED*/
110 ptsopen(dev, flag, devtype, p)
111 dev_t dev;
112 int flag, devtype;
113 struct proc *p;
114 {
115 register struct tty *tp;
116 int error;
117
118 if (minor(dev) >= npty)
119 return (ENXIO);
120 if (!pt_tty[minor(dev)]) {
121 tp = pt_tty[minor(dev)] = ttymalloc();
122 } else
123 tp = pt_tty[minor(dev)];
124 if ((tp->t_state & TS_ISOPEN) == 0) {
125 tp->t_state |= TS_WOPEN;
126 ttychars(tp); /* Set up default chars */
127 tp->t_iflag = TTYDEF_IFLAG;
128 tp->t_oflag = TTYDEF_OFLAG;
129 tp->t_lflag = TTYDEF_LFLAG;
130 tp->t_cflag = TTYDEF_CFLAG;
131 tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
132 ttsetwater(tp); /* would be done in xxparam() */
133 } else if (tp->t_state&TS_XCLUDE && p->p_ucred->cr_uid != 0)
134 return (EBUSY);
135 if (tp->t_oproc) /* Ctrlr still around. */
136 tp->t_state |= TS_CARR_ON;
137 while ((tp->t_state & TS_CARR_ON) == 0) {
138 tp->t_state |= TS_WOPEN;
139 if (flag&FNONBLOCK)
140 break;
141 if (error = ttysleep(tp, (caddr_t)&tp->t_rawq, TTIPRI | PCATCH,
142 ttopen, 0))
143 return (error);
144 }
145 error = (*linesw[tp->t_line].l_open)(dev, tp);
146 ptcwakeup(tp, FREAD|FWRITE);
147 return (error);
148 }
149
150 ptsclose(dev, flag, mode, p)
151 dev_t dev;
152 int flag, mode;
153 struct proc *p;
154 {
155 register struct tty *tp;
156 int err;
157
158 tp = pt_tty[minor(dev)];
159 err = (*linesw[tp->t_line].l_close)(tp, flag);
160 err |= ttyclose(tp);
161 ptcwakeup(tp, FREAD|FWRITE);
162 return (err);
163 }
164
165 ptsread(dev, uio, flag)
166 dev_t dev;
167 struct uio *uio;
168 int flag;
169 {
170 struct proc *p = curproc;
171 register struct tty *tp = pt_tty[minor(dev)];
172 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
173 int error = 0;
174
175 again:
176 if (pti->pt_flags & PF_REMOTE) {
177 while (isbackground(p, tp)) {
178 if ((p->p_sigignore & sigmask(SIGTTIN)) ||
179 (p->p_sigmask & sigmask(SIGTTIN)) ||
180 p->p_pgrp->pg_jobc == 0 ||
181 p->p_flag & P_PPWAIT)
182 return (EIO);
183 pgsignal(p->p_pgrp, SIGTTIN, 1);
184 if (error = ttysleep(tp, (caddr_t)&lbolt,
185 TTIPRI | PCATCH, ttybg, 0))
186 return (error);
187 }
188 if (tp->t_canq.c_cc == 0) {
189 if (flag & IO_NDELAY)
190 return (EWOULDBLOCK);
191 if (error = ttysleep(tp, (caddr_t)&tp->t_canq,
192 TTIPRI | PCATCH, ttyin, 0))
193 return (error);
194 goto again;
195 }
196 while (tp->t_canq.c_cc > 1 && uio->uio_resid > 0)
197 if (ureadc(getc(&tp->t_canq), uio) < 0) {
198 error = EFAULT;
199 break;
200 }
201 if (tp->t_canq.c_cc == 1)
202 (void) getc(&tp->t_canq);
203 if (tp->t_canq.c_cc)
204 return (error);
205 } else
206 if (tp->t_oproc)
207 error = (*linesw[tp->t_line].l_read)(tp, uio, flag);
208 ptcwakeup(tp, FWRITE);
209 return (error);
210 }
211
212 /*
213 * Write to pseudo-tty.
214 * Wakeups of controlling tty will happen
215 * indirectly, when tty driver calls ptsstart.
216 */
217 ptswrite(dev, uio, flag)
218 dev_t dev;
219 struct uio *uio;
220 int flag;
221 {
222 register struct tty *tp;
223
224 tp = pt_tty[minor(dev)];
225 if (tp->t_oproc == 0)
226 return (EIO);
227 return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
228 }
229
230 /*
231 * Start output on pseudo-tty.
232 * Wake up process selecting or sleeping for input from controlling tty.
233 */
234 void
235 ptsstart(tp)
236 struct tty *tp;
237 {
238 register struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
239
240 if (tp->t_state & TS_TTSTOP)
241 return;
242 if (pti->pt_flags & PF_STOPPED) {
243 pti->pt_flags &= ~PF_STOPPED;
244 pti->pt_send = TIOCPKT_START;
245 }
246 ptcwakeup(tp, FREAD);
247 }
248
249 ptcwakeup(tp, flag)
250 struct tty *tp;
251 int flag;
252 {
253 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
254
255 if (flag & FREAD) {
256 selwakeup(&pti->pt_selr);
257 wakeup((caddr_t)&tp->t_outq.c_cf);
258 }
259 if (flag & FWRITE) {
260 selwakeup(&pti->pt_selw);
261 wakeup((caddr_t)&tp->t_rawq.c_cf);
262 }
263 }
264
265 /*ARGSUSED*/
266 #ifdef __STDC__
267 ptcopen(dev_t dev, int flag, int devtype, struct proc *p)
268 #else
269 ptcopen(dev, flag, devtype, p)
270 dev_t dev;
271 int flag, devtype;
272 struct proc *p;
273 #endif
274 {
275 register struct tty *tp;
276 struct pt_ioctl *pti;
277
278 if (minor(dev) >= npty)
279 return (ENXIO);
280 if(!pt_tty[minor(dev)]) {
281 tp = pt_tty[minor(dev)] = ttymalloc();
282 } else
283 tp = pt_tty[minor(dev)];
284 if (tp->t_oproc)
285 return (EIO);
286 tp->t_oproc = ptsstart;
287 (void)(*linesw[tp->t_line].l_modem)(tp, 1);
288 tp->t_lflag &= ~EXTPROC;
289 pti = &pt_ioctl[minor(dev)];
290 pti->pt_flags = 0;
291 pti->pt_send = 0;
292 pti->pt_ucntl = 0;
293 return (0);
294 }
295
296 ptcclose(dev)
297 dev_t dev;
298 {
299 register struct tty *tp;
300
301 tp = pt_tty[minor(dev)];
302 (void)(*linesw[tp->t_line].l_modem)(tp, 0);
303 tp->t_state &= ~TS_CARR_ON;
304 tp->t_oproc = 0; /* mark closed */
305 return (0);
306 }
307
308 ptcread(dev, uio, flag)
309 dev_t dev;
310 struct uio *uio;
311 int flag;
312 {
313 register struct tty *tp = pt_tty[minor(dev)];
314 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
315 char buf[BUFSIZ];
316 int error = 0, cc;
317
318 /*
319 * We want to block until the slave
320 * is open, and there's something to read;
321 * but if we lost the slave or we're NBIO,
322 * then return the appropriate error instead.
323 */
324 for (;;) {
325 if (tp->t_state&TS_ISOPEN) {
326 if (pti->pt_flags&PF_PKT && pti->pt_send) {
327 error = ureadc((int)pti->pt_send, uio);
328 if (error)
329 return (error);
330 if (pti->pt_send & TIOCPKT_IOCTL) {
331 cc = min(uio->uio_resid,
332 sizeof(tp->t_termios));
333 uiomove(&tp->t_termios, cc, uio);
334 }
335 pti->pt_send = 0;
336 return (0);
337 }
338 if (pti->pt_flags&PF_UCNTL && pti->pt_ucntl) {
339 error = ureadc((int)pti->pt_ucntl, uio);
340 if (error)
341 return (error);
342 pti->pt_ucntl = 0;
343 return (0);
344 }
345 if (tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0)
346 break;
347 }
348 if ((tp->t_state&TS_CARR_ON) == 0)
349 return (0); /* EOF */
350 if (flag & IO_NDELAY)
351 return (EWOULDBLOCK);
352 if (error = tsleep((caddr_t)&tp->t_outq.c_cf, TTIPRI | PCATCH,
353 ttyin, 0))
354 return (error);
355 }
356 if (pti->pt_flags & (PF_PKT|PF_UCNTL))
357 error = ureadc(0, uio);
358 while (uio->uio_resid > 0 && error == 0) {
359 cc = q_to_b(&tp->t_outq, buf, min(uio->uio_resid, BUFSIZ));
360 if (cc <= 0)
361 break;
362 error = uiomove(buf, cc, uio);
363 }
364 if (tp->t_outq.c_cc <= tp->t_lowat) {
365 if (tp->t_state&TS_ASLEEP) {
366 tp->t_state &= ~TS_ASLEEP;
367 wakeup((caddr_t)&tp->t_outq);
368 }
369 selwakeup(&tp->t_wsel);
370 }
371 return (error);
372 }
373
374 void
375 ptsstop(tp, flush)
376 register struct tty *tp;
377 int flush;
378 {
379 struct pt_ioctl *pti = &pt_ioctl[minor(tp->t_dev)];
380 int flag;
381
382 /* note: FLUSHREAD and FLUSHWRITE already ok */
383 if (flush == 0) {
384 flush = TIOCPKT_STOP;
385 pti->pt_flags |= PF_STOPPED;
386 } else
387 pti->pt_flags &= ~PF_STOPPED;
388 pti->pt_send |= flush;
389 /* change of perspective */
390 flag = 0;
391 if (flush & FREAD)
392 flag |= FWRITE;
393 if (flush & FWRITE)
394 flag |= FREAD;
395 ptcwakeup(tp, flag);
396 }
397
398 ptcselect(dev, rw, p)
399 dev_t dev;
400 int rw;
401 struct proc *p;
402 {
403 register struct tty *tp = pt_tty[minor(dev)];
404 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
405 int s;
406
407 if ((tp->t_state&TS_CARR_ON) == 0)
408 return (1);
409 switch (rw) {
410
411 case FREAD:
412 /*
413 * Need to block timeouts (ttrstart).
414 */
415 s = spltty();
416 if ((tp->t_state&TS_ISOPEN) &&
417 tp->t_outq.c_cc && (tp->t_state&TS_TTSTOP) == 0) {
418 splx(s);
419 return (1);
420 }
421 splx(s);
422 /* FALLTHROUGH */
423
424 case 0: /* exceptional */
425 if ((tp->t_state&TS_ISOPEN) &&
426 (pti->pt_flags&PF_PKT && pti->pt_send ||
427 pti->pt_flags&PF_UCNTL && pti->pt_ucntl))
428 return (1);
429 selrecord(p, &pti->pt_selr);
430 break;
431
432
433 case FWRITE:
434 if (tp->t_state&TS_ISOPEN) {
435 if (pti->pt_flags & PF_REMOTE) {
436 if (tp->t_canq.c_cc == 0)
437 return (1);
438 } else {
439 if (tp->t_rawq.c_cc + tp->t_canq.c_cc < TTYHOG-2)
440 return (1);
441 if (tp->t_canq.c_cc == 0 && (tp->t_iflag&ICANON))
442 return (1);
443 }
444 }
445 selrecord(p, &pti->pt_selw);
446 break;
447
448 }
449 return (0);
450 }
451
452 ptcwrite(dev, uio, flag)
453 dev_t dev;
454 register struct uio *uio;
455 int flag;
456 {
457 register struct tty *tp = pt_tty[minor(dev)];
458 register u_char *cp;
459 register int cc = 0;
460 u_char locbuf[BUFSIZ];
461 int cnt = 0;
462 struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
463 int error = 0;
464
465 again:
466 if ((tp->t_state&TS_ISOPEN) == 0)
467 goto block;
468 if (pti->pt_flags & PF_REMOTE) {
469 if (tp->t_canq.c_cc)
470 goto block;
471 while (uio->uio_resid > 0 && tp->t_canq.c_cc < TTYHOG - 1) {
472 if (cc == 0) {
473 cc = min(uio->uio_resid, BUFSIZ);
474 cc = min(cc, TTYHOG - 1 - tp->t_canq.c_cc);
475 cp = locbuf;
476 error = uiomove((caddr_t)cp, cc, uio);
477 if (error)
478 return (error);
479 /* check again for safety */
480 if ((tp->t_state&TS_ISOPEN) == 0)
481 return (EIO);
482 }
483 if (cc)
484 (void) b_to_q((char *)cp, cc, &tp->t_canq);
485 cc = 0;
486 }
487 (void) putc(0, &tp->t_canq);
488 ttwakeup(tp);
489 wakeup((caddr_t)&tp->t_canq);
490 return (0);
491 }
492 while (uio->uio_resid > 0) {
493 if (cc == 0) {
494 cc = min(uio->uio_resid, BUFSIZ);
495 cp = locbuf;
496 error = uiomove((caddr_t)cp, cc, uio);
497 if (error)
498 return (error);
499 /* check again for safety */
500 if ((tp->t_state&TS_ISOPEN) == 0)
501 return (EIO);
502 }
503 while (cc > 0) {
504 if ((tp->t_rawq.c_cc + tp->t_canq.c_cc) >= TTYHOG - 2 &&
505 (tp->t_canq.c_cc > 0 || !(tp->t_iflag&ICANON))) {
506 wakeup((caddr_t)&tp->t_rawq);
507 goto block;
508 }
509 (*linesw[tp->t_line].l_rint)(*cp++, tp);
510 cnt++;
511 cc--;
512 }
513 cc = 0;
514 }
515 return (0);
516 block:
517 /*
518 * Come here to wait for slave to open, for space
519 * in outq, or space in rawq.
520 */
521 if ((tp->t_state&TS_CARR_ON) == 0)
522 return (EIO);
523 if (flag & IO_NDELAY) {
524 /* adjust for data copied in but not written */
525 uio->uio_resid += cc;
526 if (cnt == 0)
527 return (EWOULDBLOCK);
528 return (0);
529 }
530 if (error = tsleep((caddr_t)&tp->t_rawq.c_cf, TTOPRI | PCATCH,
531 ttyout, 0)) {
532 /* adjust for data copied in but not written */
533 uio->uio_resid += cc;
534 return (error);
535 }
536 goto again;
537 }
538
539 /*ARGSUSED*/
540 ptyioctl(dev, cmd, data, flag, p)
541 dev_t dev;
542 int cmd;
543 caddr_t data;
544 int flag;
545 struct proc *p;
546 {
547 register struct tty *tp = pt_tty[minor(dev)];
548 register struct pt_ioctl *pti = &pt_ioctl[minor(dev)];
549 register u_char *cc = tp->t_cc;
550 int stop, error;
551
552 /*
553 * IF CONTROLLER STTY THEN MUST FLUSH TO PREVENT A HANG.
554 * ttywflush(tp) will hang if there are characters in the outq.
555 */
556 if (cmd == TIOCEXT) {
557 /*
558 * When the EXTPROC bit is being toggled, we need
559 * to send an TIOCPKT_IOCTL if the packet driver
560 * is turned on.
561 */
562 if (*(int *)data) {
563 if (pti->pt_flags & PF_PKT) {
564 pti->pt_send |= TIOCPKT_IOCTL;
565 ptcwakeup(tp, FREAD);
566 }
567 tp->t_lflag |= EXTPROC;
568 } else {
569 if ((tp->t_state & EXTPROC) &&
570 (pti->pt_flags & PF_PKT)) {
571 pti->pt_send |= TIOCPKT_IOCTL;
572 ptcwakeup(tp, FREAD);
573 }
574 tp->t_lflag &= ~EXTPROC;
575 }
576 return(0);
577 } else
578 if (cdevsw[major(dev)].d_open == ptcopen)
579 switch (cmd) {
580
581 case TIOCGPGRP:
582 /*
583 * We aviod calling ttioctl on the controller since,
584 * in that case, tp must be the controlling terminal.
585 */
586 *(int *)data = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
587 return (0);
588
589 case TIOCPKT:
590 if (*(int *)data) {
591 if (pti->pt_flags & PF_UCNTL)
592 return (EINVAL);
593 pti->pt_flags |= PF_PKT;
594 } else
595 pti->pt_flags &= ~PF_PKT;
596 return (0);
597
598 case TIOCUCNTL:
599 if (*(int *)data) {
600 if (pti->pt_flags & PF_PKT)
601 return (EINVAL);
602 pti->pt_flags |= PF_UCNTL;
603 } else
604 pti->pt_flags &= ~PF_UCNTL;
605 return (0);
606
607 case TIOCREMOTE:
608 if (*(int *)data)
609 pti->pt_flags |= PF_REMOTE;
610 else
611 pti->pt_flags &= ~PF_REMOTE;
612 ttyflush(tp, FREAD|FWRITE);
613 return (0);
614
615 #ifdef COMPAT_43
616 case TIOCSETP:
617 case TIOCSETN:
618 #endif
619 case TIOCSETD:
620 case TIOCSETA:
621 case TIOCSETAW:
622 case TIOCSETAF:
623 ndflush(&tp->t_outq, tp->t_outq.c_cc);
624 break;
625
626 case TIOCSIG:
627 if (*(unsigned int *)data >= NSIG)
628 return(EINVAL);
629 if ((tp->t_lflag&NOFLSH) == 0)
630 ttyflush(tp, FREAD|FWRITE);
631 pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
632 if ((*(unsigned int *)data == SIGINFO) &&
633 ((tp->t_lflag&NOKERNINFO) == 0))
634 ttyinfo(tp);
635 return(0);
636 }
637 error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
638 if (error < 0)
639 error = ttioctl(tp, cmd, data, flag, p);
640 if (error < 0) {
641 if (pti->pt_flags & PF_UCNTL &&
642 (cmd & ~0xff) == UIOCCMD(0)) {
643 if (cmd & 0xff) {
644 pti->pt_ucntl = (u_char)cmd;
645 ptcwakeup(tp, FREAD);
646 }
647 return (0);
648 }
649 error = ENOTTY;
650 }
651 /*
652 * If external processing and packet mode send ioctl packet.
653 */
654 if ((tp->t_lflag&EXTPROC) && (pti->pt_flags & PF_PKT)) {
655 switch(cmd) {
656 case TIOCSETA:
657 case TIOCSETAW:
658 case TIOCSETAF:
659 #ifdef COMPAT_43
660 case TIOCSETP:
661 case TIOCSETN:
662 #endif
663 #if defined(COMPAT_43) || defined(COMPAT_SUNOS)
664 case TIOCSETC:
665 case TIOCSLTC:
666 case TIOCLBIS:
667 case TIOCLBIC:
668 case TIOCLSET:
669 #endif
670 pti->pt_send |= TIOCPKT_IOCTL;
671 ptcwakeup(tp, FREAD);
672 default:
673 break;
674 }
675 }
676 stop = (tp->t_iflag & IXON) && CCEQ(cc[VSTOP], CTRL('s'))
677 && CCEQ(cc[VSTART], CTRL('q'));
678 if (pti->pt_flags & PF_NOSTOP) {
679 if (stop) {
680 pti->pt_send &= ~TIOCPKT_NOSTOP;
681 pti->pt_send |= TIOCPKT_DOSTOP;
682 pti->pt_flags &= ~PF_NOSTOP;
683 ptcwakeup(tp, FREAD);
684 }
685 } else {
686 if (!stop) {
687 pti->pt_send &= ~TIOCPKT_DOSTOP;
688 pti->pt_send |= TIOCPKT_NOSTOP;
689 pti->pt_flags |= PF_NOSTOP;
690 ptcwakeup(tp, FREAD);
691 }
692 }
693 return (error);
694 }
695