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