xref: /csrg-svn/sys/kern/tty.c (revision 121)
1 /*	tty.c	3.2	10/14/12	*/
2 
3 /*
4  * general TTY subroutines
5  */
6 #include "../h/param.h"
7 #include "../h/systm.h"
8 #include "../h/dir.h"
9 #include "../h/user.h"
10 #include "../h/tty.h"
11 #include "../h/proc.h"
12 #include "../h/mx.h"
13 #include "../h/inode.h"
14 #include "../h/file.h"
15 #include "../h/reg.h"
16 #include "../h/conf.h"
17 #include "../h/buf.h"
18 
19 char	partab[];
20 
21 
22 /*
23  * Input mapping table-- if an entry is non-zero, when the
24  * corresponding character is typed preceded by "\" the escape
25  * sequence is replaced by the table value.  Mostly used for
26  * upper-case only terminals.
27  */
28 
29 char	maptab[] ={
30 	000,000,000,000,000,000,000,000,
31 	000,000,000,000,000,000,000,000,
32 	000,000,000,000,000,000,000,000,
33 	000,000,000,000,000,000,000,000,
34 	000,'|',000,000,000,000,000,'`',
35 	'{','}',000,000,000,000,000,000,
36 	000,000,000,000,000,000,000,000,
37 	000,000,000,000,000,000,000,000,
38 	000,000,000,000,000,000,000,000,
39 	000,000,000,000,000,000,000,000,
40 	000,000,000,000,000,000,000,000,
41 	000,000,000,000,000,000,'~',000,
42 	000,'A','B','C','D','E','F','G',
43 	'H','I','J','K','L','M','N','O',
44 	'P','Q','R','S','T','U','V','W',
45 	'X','Y','Z',000,000,000,000,000,
46 };
47 
48 
49 /*
50  * shorthand
51  */
52 #define	q1	tp->t_rawq
53 #define	q2	tp->t_canq
54 #define	q3	tp->t_outq
55 #define	q4	tp->t_un.t_ctlq
56 
57 #define	OBUFSIZ	100
58 
59 /*
60  * routine called on first teletype open.
61  * establishes a process group for distribution
62  * of quits and interrupts from the tty.
63  */
64 ttyopen(dev, tp)
65 dev_t dev;
66 register struct tty *tp;
67 {
68 	register struct proc *pp;
69 
70 	pp = u.u_procp;
71 	tp->t_dev = dev;
72 	if(pp->p_pgrp == 0) {
73 		u.u_ttyp = tp;
74 		u.u_ttyd = dev;
75 		if (tp->t_pgrp==0)
76 			tp->t_pgrp = pp->p_pid;
77 		pp->p_pgrp = tp->t_pgrp;
78 	}
79 	tp->t_state &= ~WOPEN;
80 	tp->t_state |= ISOPEN;
81 }
82 
83 
84 /*
85  * set default control characters.
86  */
87 ttychars(tp)
88 register struct tty *tp;
89 {
90 	tun.t_intrc = CINTR;
91 	tun.t_quitc = CQUIT;
92 	tun.t_startc = CSTART;
93 	tun.t_stopc = CSTOP;
94 	tun.t_eofc = CEOT;
95 	tun.t_brkc = CBRK;
96 	tp->t_erase = CERASE;
97 	tp->t_kill = CKILL;
98 }
99 
100 /*
101  * clean tp on last close
102  */
103 ttyclose(tp)
104 register struct tty *tp;
105 {
106 
107 	tp->t_pgrp = 0;
108 	wflushtty(tp);
109 	tp->t_state = 0;
110 }
111 
112 /*
113  * stty/gtty writearound
114  */
115 stty()
116 {
117 	u.u_arg[2] = u.u_arg[1];
118 	u.u_arg[1] = TIOCSETP;
119 	ioctl();
120 }
121 
122 gtty()
123 {
124 	u.u_arg[2] = u.u_arg[1];
125 	u.u_arg[1] = TIOCGETP;
126 	ioctl();
127 }
128 
129 /*
130  * Do nothing specific version of line
131  * discipline specific ioctl command.
132  */
133 nullioctl(tp, cmd, addr)
134 register struct tty *tp;
135 caddr_t addr;
136 {
137 
138 	return (cmd);
139 }
140 
141 /*
142  * ioctl system call
143  * Check legality, execute common code, and switch out to individual
144  * device routine.
145  */
146 ioctl()
147 {
148 	register struct file *fp;
149 	register struct inode *ip;
150 	register struct a {
151 		int	fdes;
152 		int	cmd;
153 		caddr_t	cmarg;
154 	} *uap;
155 	register dev_t dev;
156 	register fmt;
157 
158 	uap = (struct a *)u.u_ap;
159 	if ((fp = getf(uap->fdes)) == NULL)
160 		return;
161 	if (uap->cmd==FIOCLEX) {
162 		u.u_pofile[uap->fdes] |= EXCLOSE;
163 		return;
164 	}
165 	if (uap->cmd==FIONCLEX) {
166 		u.u_pofile[uap->fdes] &= ~EXCLOSE;
167 		return;
168 	}
169 	ip = fp->f_inode;
170 	fmt = ip->i_mode & IFMT;
171 	if (fmt != IFCHR && fmt != IFMPC) {
172 		u.u_error = ENOTTY;
173 		return;
174 	}
175 	dev = ip->i_un.i_rdev;
176 	u.u_r.r_val1 = 0;
177 	(*cdevsw[major(dev)].d_ioctl)(dev, uap->cmd, uap->cmarg, fp->f_flag);
178 }
179 
180 /*
181  * Common code for several tty ioctl commands
182  */
183 ttioccomm(com, tp, addr, dev)
184 register struct tty *tp;
185 caddr_t addr;
186 {
187 	unsigned t;
188 	struct ttiocb iocb;
189 	extern int nldisp;
190 	register s;
191 
192 	switch(com) {
193 
194 	/*
195 	 * get discipline number
196 	 */
197 	case TIOCGETD:
198 		t = tp->t_line;
199 		if (copyout((caddr_t)&t, addr, sizeof(t)))
200 			u.u_error = EFAULT;
201 		break;
202 
203 	/*
204 	 * set line discipline
205 	 */
206 	case TIOCSETD:
207 		if (copyin(addr, (caddr_t)&t, sizeof(t))) {
208 			u.u_error = EFAULT;
209 			break;
210 		}
211 		if (t >= nldisp) {
212 			u.u_error = ENXIO;
213 			break;
214 		}
215 		s = spl5();
216 		if (tp->t_line)
217 			(*linesw[tp->t_line].l_close)(tp);
218 		if (t)
219 			(*linesw[t].l_open)(dev, tp, addr);
220 		if (u.u_error==0)
221 			tp->t_line = t;
222 		splx(s);
223 		break;
224 
225 	/*
226 	 * prevent more opens on channel
227 	 */
228 	case TIOCEXCL:
229 		tp->t_state |= XCLUDE;
230 		break;
231 
232 	case TIOCNXCL:
233 		tp->t_state &= ~XCLUDE;
234 		break;
235 
236 	/*
237 	 * Set new parameters
238 	 */
239 	case TIOCSETP:
240 		wflushtty(tp);
241 	case TIOCSETN:
242 		if (copyin(addr, (caddr_t)&iocb, sizeof(iocb))) {
243 			u.u_error = EFAULT;
244 			return(1);
245 		}
246 		(void) spl5();
247 		while (canon(tp)>=0)
248 			;
249 		if ((tp->t_state&SPEEDS)==0) {
250 			tp->t_ispeed = iocb.ioc_ispeed;
251 			tp->t_ospeed = iocb.ioc_ospeed;
252 		}
253 		tp->t_erase = iocb.ioc_erase;
254 		tp->t_kill = iocb.ioc_kill;
255 		tp->t_flags = iocb.ioc_flags;
256 		(void) spl0();
257 		break;
258 
259 	/*
260 	 * send current parameters to user
261 	 */
262 	case TIOCGETP:
263 		iocb.ioc_ispeed = tp->t_ispeed;
264 		iocb.ioc_ospeed = tp->t_ospeed;
265 		iocb.ioc_erase = tp->t_erase;
266 		iocb.ioc_kill = tp->t_kill;
267 		iocb.ioc_flags = tp->t_flags;
268 		if (copyout((caddr_t)&iocb, addr, sizeof(iocb)))
269 			u.u_error = EFAULT;
270 		break;
271 
272 	/*
273 	 * Hang up line on last close
274 	 */
275 
276 	case TIOCHPCL:
277 		tp->t_state |= HUPCLS;
278 		break;
279 
280 	case TIOCFLUSH:
281 		flushtty(tp);
282 		break;
283 
284 	/*
285 	 * ioctl entries to line discipline
286 	 */
287 	case DIOCSETP:
288 	case DIOCGETP:
289 		if ((*linesw[tp->t_line].l_ioctl)(com, tp, addr))
290 			u.u_error = ENOTTY;
291 		break;
292 
293 	/*
294 	 * set and fetch special characters
295 	 */
296 	case TIOCSETC:
297 		if (copyin(addr, (caddr_t)&tun, sizeof(struct tc)))
298 			u.u_error = EFAULT;
299 		break;
300 
301 	case TIOCGETC:
302 		if (copyout((caddr_t)&tun, addr, sizeof(struct tc)))
303 			u.u_error = EFAULT;
304 		break;
305 
306 	default:
307 		return(0);
308 	}
309 	return(1);
310 }
311 
312 /*
313  * Wait for output to drain, then flush input waiting.
314  */
315 wflushtty(tp)
316 register struct tty *tp;
317 {
318 
319 	(void) spl5();
320 	while (tp->t_outq.c_cc && tp->t_state&CARR_ON) {
321 		(*tp->t_oproc)(tp);
322 		tp->t_state |= ASLEEP;
323 		sleep((caddr_t)&tp->t_outq, TTOPRI);
324 	}
325 	flushtty(tp);
326 	(void) spl0();
327 }
328 
329 /*
330  * flush all TTY queues
331  */
332 flushtty(tp)
333 register struct tty *tp;
334 {
335 	register s;
336 
337 	s = spl6();
338 	while (getc(&tp->t_canq) >= 0)
339 		;
340 	wakeup((caddr_t)&tp->t_rawq);
341 	wakeup((caddr_t)&tp->t_outq);
342 	tp->t_state &= ~TTSTOP;
343 	(*cdevsw[major(tp->t_dev)].d_stop)(tp);
344 	while (getc(&tp->t_outq) >= 0)
345 		;
346 	while (getc(&tp->t_rawq) >= 0)
347 		;
348 	tp->t_delct = 0;
349 	splx(s);
350 }
351 
352 
353 
354 /*
355  * transfer raw input list to canonical list,
356  * doing erase-kill processing and handling escapes.
357  * It waits until a full line has been typed in cooked mode,
358  * or until any character has been typed in raw mode.
359  */
360 canon(tp)
361 register struct tty *tp;
362 {
363 	register char *bp;
364 	char *bp1;
365 	register int c;
366 	int mc;
367 	int s;
368 
369 	if ((tp->t_flags&(RAW|CBREAK))==0 && tp->t_delct==0
370 	    || (tp->t_flags&(RAW|CBREAK))!=0 && tp->t_rawq.c_cc==0) {
371 		return(-1);
372 	}
373 	s = spl0();
374 loop:
375 	bp = &canonb[2];
376 	while ((c=getc(&tp->t_rawq)) >= 0) {
377 		if ((tp->t_flags&(RAW|CBREAK))==0) {
378 			if (c==0377) {
379 				tp->t_delct--;
380 				break;
381 			}
382 			if (bp[-1]!='\\') {
383 				if (c==tp->t_erase) {
384 					if (bp > &canonb[2])
385 						bp--;
386 					continue;
387 				}
388 				if (c==tp->t_kill)
389 					goto loop;
390 				if (c==tun.t_eofc)
391 					continue;
392 			} else {
393 				mc = maptab[c];
394 				if (c==tp->t_erase || c==tp->t_kill)
395 					mc = c;
396 				if (mc && (mc==c || (tp->t_flags&LCASE))) {
397 					if (bp[-2] != '\\')
398 						c = mc;
399 					bp--;
400 				}
401 			}
402 		}
403 		*bp++ = c;
404 		if (bp>=canonb+CANBSIZ)
405 			break;
406 	}
407 	bp1 = &canonb[2];
408 	(void) b_to_q(bp1, bp-bp1, &tp->t_canq);
409 
410 	if (tp->t_state&TBLOCK && tp->t_rawq.c_cc < TTYHOG/5) {
411 		if (putc(tun.t_startc, &tp->t_outq)==0) {
412 			tp->t_state &= ~TBLOCK;
413 			ttstart(tp);
414 		}
415 		tp->t_char = 0;
416 	}
417 
418 	splx(s);
419 	return(0);
420 }
421 
422 
423 /*
424  * block transfer input handler.
425  */
426 ttyrend(tp, pb, pe)
427 register struct tty *tp;
428 register char *pb, *pe;
429 {
430 	int	tandem;
431 
432 	tandem = tp->t_flags&TANDEM;
433 	if (tp->t_flags&RAW) {
434 		(void) b_to_q(pb, pe-pb, &tp->t_rawq);
435 		if (tp->t_chan)
436 			(void) sdata(tp->t_chan); else
437 			wakeup((caddr_t)&tp->t_rawq);
438 	} else {
439 		tp->t_flags &= ~TANDEM;
440 		while (pb < pe)
441 			ttyinput(*pb++, tp);
442 		tp->t_flags |= tandem;
443 	}
444 	if (tandem)
445 		ttyblock(tp);
446 }
447 
448 /*
449  * Place a character on raw TTY input queue, putting in delimiters
450  * and waking up top half as needed.
451  * Also echo if required.
452  * The arguments are the character and the appropriate
453  * tty structure.
454  */
455 ttyinput(c, tp)
456 register c;
457 register struct tty *tp;
458 {
459 	register int t_flags;
460 	register struct chan *cp;
461 
462 	tk_nin += 1;
463 	c &= 0377;
464 	t_flags = tp->t_flags;
465 	if (t_flags&TANDEM)
466 		ttyblock(tp);
467 	if ((t_flags&RAW)==0) {
468 		c &= 0177;
469 		if (tp->t_state&TTSTOP) {
470 			if (c==tun.t_startc) {
471 				tp->t_state &= ~TTSTOP;
472 				ttstart(tp);
473 				return;
474 			}
475 			if (c==tun.t_stopc)
476 				return;
477 			tp->t_state &= ~TTSTOP;
478 			ttstart(tp);
479 		} else {
480 			if (c==tun.t_stopc) {
481 				tp->t_state |= TTSTOP;
482 				(*cdevsw[major(tp->t_dev)].d_stop)(tp);
483 				return;
484 			}
485 			if (c==tun.t_startc)
486 				return;
487 		}
488 		if (c==tun.t_quitc || c==tun.t_intrc) {
489 			flushtty(tp);
490 			c = (c==tun.t_intrc) ? SIGINT:SIGQUIT;
491 			if (tp->t_chan)
492 				scontrol(tp->t_chan, M_SIG, c);
493 			else
494 				signal(tp->t_pgrp, c);
495 			return;
496 		}
497 		if (c=='\r' && t_flags&CRMOD)
498 			c = '\n';
499 	}
500 	if (tp->t_rawq.c_cc>TTYHOG) {
501 		flushtty(tp);
502 		return;
503 	}
504 	if (t_flags&LCASE && c>='A' && c<='Z')
505 		c += 'a'-'A';
506 	(void) putc(c, &tp->t_rawq);
507 	if (t_flags&(RAW|CBREAK)||(c=='\n'||c==tun.t_eofc||c==tun.t_brkc)) {
508 		if ((t_flags&(RAW|CBREAK))==0 && putc(0377, &tp->t_rawq)==0)
509 			tp->t_delct++;
510 		if ((cp=tp->t_chan)!=NULL)
511 			(void) sdata(cp); else
512 			wakeup((caddr_t)&tp->t_rawq);
513 	}
514 	if (t_flags&ECHO) {
515 		ttyoutput(c, tp);
516 		if (c==tp->t_kill && (t_flags&(RAW|CBREAK))==0)
517 			ttyoutput('\n', tp);
518 		ttstart(tp);
519 	}
520 }
521 
522 
523 /*
524  * Send stop character on input overflow.
525  */
526 ttyblock(tp)
527 register struct tty *tp;
528 {
529 	register x;
530 	x = q1.c_cc + q2.c_cc;
531 	if (q1.c_cc > TTYHOG) {
532 		flushtty(tp);
533 		tp->t_state &= ~TBLOCK;
534 	}
535 	if (x >= TTYHOG/2) {
536 		if (putc(tun.t_stopc, &tp->t_outq)==0) {
537 			tp->t_state |= TBLOCK;
538 			tp->t_char++;
539 			ttstart(tp);
540 		}
541 	}
542 }
543 
544 /*
545  * put character on TTY output queue, adding delays,
546  * expanding tabs, and handling the CR/NL bit.
547  * It is called both from the top half for output, and from
548  * interrupt level for echoing.
549  * The arguments are the character and the tty structure.
550  */
551 ttyoutput(c, tp)
552 register c;
553 register struct tty *tp;
554 {
555 	register char *colp;
556 	register ctype;
557 
558 	/*
559 	 * Ignore EOT in normal mode to avoid hanging up
560 	 * certain terminals.
561 	 * In raw mode dump the char unchanged.
562 	 */
563 	if ((tp->t_flags&RAW)==0) {
564 		c &= 0177;
565 		if ((tp->t_flags&CBREAK)==0 && c==CEOT)
566 			return;
567 	} else {
568 		tk_nout++;
569 		(void) putc(c, &tp->t_outq);
570 		return;
571 	}
572 
573 	/*
574 	 * Turn tabs to spaces as required
575 	 */
576 	if (c=='\t' && (tp->t_flags&TBDELAY)==XTABS) {
577 		c = 8 - (tp->t_col & 7);
578 		(void) b_to_q("        ", c, &tp->t_outq);
579 		tp->t_col += c;
580 		tk_nout += c;
581 		return;
582 	}
583 	tk_nout++;
584 	/*
585 	 * for upper-case-only terminals,
586 	 * generate escapes.
587 	 */
588 	if (tp->t_flags&LCASE) {
589 		colp = "({)}!|^~'`";
590 		while(*colp++)
591 			if(c == *colp++) {
592 				ttyoutput('\\', tp);
593 				c = colp[-2];
594 				break;
595 			}
596 		if ('a'<=c && c<='z')
597 			c += 'A' - 'a';
598 	}
599 	/*
600 	 * turn <nl> to <cr><lf> if desired.
601 	 */
602 	if (c=='\n' && tp->t_flags&CRMOD)
603 		ttyoutput('\r', tp);
604 	(void) putc(c, &tp->t_outq);
605 	/*
606 	 * Calculate delays.
607 	 * The numbers here represent clock ticks
608 	 * and are not necessarily optimal for all terminals.
609 	 * The delays are indicated by characters above 0200.
610 	 * In raw mode there are no delays and the
611 	 * transmission path is 8 bits wide.
612 	 */
613 	colp = &tp->t_col;
614 	ctype = partab[c];
615 	c = 0;
616 	switch (ctype&077) {
617 
618 	/* ordinary */
619 	case 0:
620 		(*colp)++;
621 
622 	/* non-printing */
623 	case 1:
624 		break;
625 
626 	/* backspace */
627 	case 2:
628 		if (*colp)
629 			(*colp)--;
630 		break;
631 
632 	/* newline */
633 	case 3:
634 		ctype = (tp->t_flags >> 8) & 03;
635 		if(ctype == 1) { /* tty 37 */
636 			if (*colp)
637 				c = max(((unsigned)*colp>>4) + 3, (unsigned)6);
638 		} else
639 		if(ctype == 2) { /* vt05 */
640 			c = 6;
641 		}
642 		*colp = 0;
643 		break;
644 
645 	/* tab */
646 	case 4:
647 		ctype = (tp->t_flags >> 10) & 03;
648 		if(ctype == 1) { /* tty 37 */
649 			c = 1 - (*colp | ~07);
650 			if(c < 5)
651 				c = 0;
652 		}
653 		*colp |= 07;
654 		(*colp)++;
655 		break;
656 
657 	/* vertical motion */
658 	case 5:
659 		if(tp->t_flags & VTDELAY) /* tty 37 */
660 			c = 0177;
661 		break;
662 
663 	/* carriage return */
664 	case 6:
665 		ctype = (tp->t_flags >> 12) & 03;
666 		if(ctype == 1) { /* tn 300 */
667 			c = 5;
668 		} else if(ctype == 2) { /* ti 700 */
669 			c = 10;
670 		} else if(ctype == 3) { /* concept 100 */
671 			int i;
672 			for (i= *colp; i<9; i++)
673 				(void) putc(0177, &tp->t_outq);
674 		}
675 		*colp = 0;
676 	}
677 	if(c)
678 		(void) putc(c|0200, &tp->t_outq);
679 }
680 
681 /*
682  * Restart typewriter output following a delay
683  * timeout.
684  * The name of the routine is passed to the timeout
685  * subroutine and it is called during a clock interrupt.
686  */
687 ttrstrt(tp)
688 register struct tty *tp;
689 {
690 
691 	tp->t_state &= ~TIMEOUT;
692 	ttstart(tp);
693 }
694 
695 /*
696  * Start output on the typewriter. It is used from the top half
697  * after some characters have been put on the output queue,
698  * from the interrupt routine to transmit the next
699  * character, and after a timeout has finished.
700  */
701 ttstart(tp)
702 register struct tty *tp;
703 {
704 	register s;
705 
706 	s = spl5();
707 	if((tp->t_state&(TIMEOUT|TTSTOP|BUSY)) == 0)
708 		(*tp->t_oproc)(tp);
709 	splx(s);
710 }
711 
712 /*
713  * Called from device's read routine after it has
714  * calculated the tty-structure given as argument.
715  */
716 ttread(tp)
717 register struct tty *tp;
718 {
719 register s;
720 
721 	if ((tp->t_state&CARR_ON)==0)
722 		return(-1);
723 	s = spl5();
724 	if (tp->t_canq.c_cc==0)
725 		while (canon(tp)<0)
726 			if (tp->t_chan==NULL) {
727 				sleep((caddr_t)&tp->t_rawq, TTIPRI);
728 			} else {
729 				splx(s);
730 				return(0);
731 			}
732 	splx(s);
733 	while (tp->t_canq.c_cc && passc(getc(&tp->t_canq))>=0)
734 			;
735 	return(tp->t_rawq.c_cc+tp->t_canq.c_cc);
736 }
737 
738 /*
739  * Called from the device's write routine after it has
740  * calculated the tty-structure given as argument.
741  */
742 caddr_t
743 ttwrite(tp)
744 register struct tty *tp;
745 {
746 	/*
747 	 * THE POSITIONING OF CP, CC, AND CE ARE CRITICAL
748 	 * AND MUST NOT BE CHANGED WITHOUT PATCHING
749 	 * THE 'ASM' INLINES BELOW.  WATCH OUT.
750 	 */
751 	register char *cp;
752 	register int cc, ce;
753 	register i;
754 	char obuf[OBUFSIZ];
755 
756 	if ((tp->t_state&CARR_ON)==0)
757 		return(NULL);
758 	while (u.u_count) {
759 		cc = MIN(u.u_count, OBUFSIZ);
760 		cp = obuf;
761 		iomove(cp, (unsigned)cc, B_WRITE);
762 		if (u.u_error)
763 			break;
764 		(void) spl5();
765 		while (tp->t_outq.c_cc > TTHIWAT) {
766 			ttstart(tp);
767 			tp->t_state |= ASLEEP;
768 			if (tp->t_chan) {
769 				u.u_base -= cc;
770 				u.u_offset -= cc;
771 				u.u_count += cc;
772 				(void) spl0();
773 				return((caddr_t)&tp->t_outq);
774 			}
775 			sleep((caddr_t)&tp->t_outq, TTOPRI);
776 		}
777 		(void) spl0();
778 		if (tp->t_flags&LCASE) {
779 			while (cc--)
780 				ttyoutput(*cp++,tp);
781 			continue;
782 		}
783 		while (cc) {
784 			if (tp->t_flags&RAW)
785 				ce=cc;
786 			else {
787 #ifdef VAX
788 				asm("	scanc	r9,(r10),_partab,$077");
789 				asm("	subl3	r0,r9,r8");
790 #else
791 				ce=0;
792 				while(((partab[*(cp+ce)]&077)==0)&&(ce<cc))
793 					ce++;
794 #endif
795 				if (ce==0) {
796 					ttyoutput(*cp++,tp);
797 					cc--;
798 					goto check;
799 				}
800 			}
801 			i=b_to_q(cp,ce,&tp->t_outq);
802 			ce-=i;
803 			tk_nout+=ce;
804 			tp->t_col+=ce;
805 			cp+=ce;
806 			cc-=ce;
807 			if (i == 0)
808 				continue;
809 check:
810 			if (tp->t_outq.c_cc > TTHIWAT) {
811 				(void) spl5();
812 				while (tp->t_outq.c_cc > TTHIWAT) {
813 					ttstart(tp);
814 					tp->t_state |= ASLEEP;
815 					sleep((caddr_t)&tp->t_outq, TTOPRI);
816 				}
817 				(void) spl0();
818 			}
819 		}
820 	}
821 	ttstart(tp);
822 	return(NULL);
823 }
824