Subject: 2.11BSD gets RTS/CTS flow control (#370 - 2 of 3)
Index:	sys/tty.c,dhv.c,bin/stty.c,... 2.11BSD

Description:
	RTS/CTS flow control, used to insure reliable communications on 
	serial lines, is missing from 2.11BSD

Repeat-By:
	Using C-Kermit (version 5A-188 was included in 2.11) establish a
	connection via a modem and a line speed of 9600 or greater.  There
	are two things to watch for:

		1) If large packets are enabled (greater than ~128 bytes)
		   and a file transfer is started there will be many truncated
		   or "crunched" packets.

		2) During the interactive mode large sections of the output
		   will be missing as data overruns occur.

	Using 'tip' (or 'cu') there will be much lost data.

	It should come as no surprise that XON/XOFF is not very effective over
	modem lines at speeds of 9600 or greater (C-kermit requires more flow
	control than tip due to kermit's higher cpu utilization).

	In both cases the data loss is made much worse if there is other
	activity on the system (especially in the case of an 11/73 which is
	not as fast as the 11/44 or 11/93).  If background disk activity
	is started (via 'cron', 'sendmail', etc) the data loss on the serial
	ports will be even worse than usual.

Fix:
	This is #370 and is part 2 of 3.  Make sure you have #369 and 371
	(parts 1 and 3) before proceeding with the installation of the update.

	This part contains the second of the three patches.

	As always this and previous updates to 2.11BSD are available via
	anonymous FTP to either FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the
	directory /pub/2.11BSD.

----------------------------cut here-----------------------------
*** /usr/src/new/crash/crashsubs.c.old	Thu Dec 15 19:52:16 1994
--- /usr/src/new/crash/crashsubs.c	Fri Mar 28 21:13:13 1997
***************
*** 1,6 ****
--- 1,8 ----
  /*
   *	U N I X   2 . 9 B S D   C R A S H   A N A L Y Z E R   S U B S
   *
+  * All the tty delay bits went away.  1997/3/28
+  *
   * 'LCASE' and 'LTILDE' went away.  Some day this program should be
   * rewritten to reflect the current system.  12/9/94
   */
***************
*** 581,587 ****
  ttyflg(flgs)
  unsigned *flgs;
  {
! #define	TTY_FLAGS "\0\1TANDEM\2CBREAK\4ECHO\5CRMOD\6RAW\7ODDP\10EVENP\11NL1\12NL2\13TAB1\14TAB2\15CR1\16CR2\17FF1\20BS1\21CRTBS\22PRTERA\23CRTERA\25MDMBUF\26LITOUT\27TOSTOP\30FLUSHO\31NOHANG\32L001000\33CRTKILL\34PASS8\35CTLECH\36PENDIN\DECCTQ"
  	printb((u_long) *flgs, TTY_FLAGS);
  }
  
--- 583,589 ----
  ttyflg(flgs)
  unsigned *flgs;
  {
! #define	TTY_FLAGS "\0\1TANDEM\2CBREAK\4ECHO\5CRMOD\6RAW\7ODDP\10EVENP\21CRTBS\22PRTERA\23CRTERA\25MDMBUF\26LITOUT\27TOSTOP\30FLUSHO\31NOHANG\32RTSCTS\33CRTKILL\34PASS8\35CTLECH\36PENDIN\DECCTQ"
  	printb((u_long) *flgs, TTY_FLAGS);
  }
  
*** /usr/src/sys/h/ioctl.h.old	Mon Jun 26 19:53:56 1995
--- /usr/src/sys/h/ioctl.h	Fri Mar 28 16:04:34 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ioctl.h	1.3 (2.11BSD GTE) 1995/05/21
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ioctl.h	1.4 (2.11BSD GTE) 1997/3/28
   */
  
  /*
***************
*** 136,142 ****
  #define	TIOCGETC	_IOR(t,18,struct tchars)/* get special characters */
  #define		TANDEM		0x00000001	/* send stopc on out q full */
  #define		CBREAK		0x00000002	/* half-cooked mode */
! #define		LCASE		0x00000004	/* (obsolete) - place holder */
  #define		ECHO		0x00000008	/* echo input */
  #define		CRMOD		0x00000010	/* map \r to \r\n on output */
  #define		RAW		0x00000020	/* no i/o processing */
--- 136,142 ----
  #define	TIOCGETC	_IOR(t,18,struct tchars)/* get special characters */
  #define		TANDEM		0x00000001	/* send stopc on out q full */
  #define		CBREAK		0x00000002	/* half-cooked mode */
! 						/* 0x4 (old LCASE) */
  #define		ECHO		0x00000008	/* echo input */
  #define		CRMOD		0x00000010	/* map \r to \r\n on output */
  #define		RAW		0x00000020	/* no i/o processing */
***************
*** 143,180 ****
  #define		ODDP		0x00000040	/* get/send odd parity */
  #define		EVENP		0x00000080	/* get/send even parity */
  #define		ANYP		0x000000c0	/* get any parity/send none */
! #define		NLDELAY		0x00000300	/* \n delay */
! #define			NL0	0x00000000
! #define			NL1	0x00000100	/* tty 37 */
! #define			NL2	0x00000200	/* vt05 */
! #define			NL3	0x00000300
! #define		TBDELAY		0x00000c00	/* horizontal tab delay */
! #define			TAB0	0x00000000
! #define			TAB1	0x00000400	/* tty 37 */
! #define			TAB2	0x00000800
! #define		XTABS		0x00000c00	/* expand tabs on output */
! #define		CRDELAY		0x00003000	/* \r delay */
! #define			CR0	0x00000000
! #define			CR1	0x00001000	/* tn 300 */
! #define			CR2	0x00002000	/* tty 37 */
! #define			CR3	0x00003000	/* concept 100 */
! #define		VTDELAY		0x00004000	/* vertical tab delay */
! #define			FF0	0x00000000
! #define			FF1	0x00004000	/* tty 37 */
! #define		BSDELAY		((unsigned)0x00008000)	/* \b delay */
! #define			BS0	0x00000000
! #define			BS1	((unsigned)0x00008000)
! #define		ALLDELAY	(NLDELAY|TBDELAY|CRDELAY|VTDELAY|BSDELAY)
  #define		CRTBS		0x00010000	/* do backspacing for crt */
  #define		PRTERA		0x00020000	/* \ ... / erase */
  #define		CRTERA		0x00040000	/* " \b " to wipe out char */
! #define		TILDE		0x00080000	/* (obsolete) place holder */
  #define		MDMBUF		0x00100000	/* start/stop output on carrier intr */
  #define		LITOUT		0x00200000	/* literal output */
  #define		TOSTOP		0x00400000	/* SIGSTOP on background output */
  #define		FLUSHO		0x00800000	/* flush output to terminal */
  #define		NOHANG		0x01000000	/* no SIGHUP on carrier drop */
! #define		L001000		0x02000000
  #define		CRTKIL		0x04000000	/* kill line with " \b " */
  #define		PASS8		0x08000000
  #define		CTLECH		0x10000000	/* echo control chars as ^X */
--- 143,166 ----
  #define		ODDP		0x00000040	/* get/send odd parity */
  #define		EVENP		0x00000080	/* get/send even parity */
  #define		ANYP		0x000000c0	/* get any parity/send none */
! 						/* 0x100 (old NLDELAY) */
! 						/* 0x200 */
! #define		XTABS		0x00000400	/* expand tabs on output */
! 						/* 0x0800 (part of old XTABS) */
! 						/* 0x1000 (old CRDELAY) */
! 						/* 0x2000 */
! 						/* 0x4000 (old VTDELAY) */
! 						/* 0x8000 (old BSDELAY) */
  #define		CRTBS		0x00010000	/* do backspacing for crt */
  #define		PRTERA		0x00020000	/* \ ... / erase */
  #define		CRTERA		0x00040000	/* " \b " to wipe out char */
! 						/* 0x00080000 (old TILDE) */
  #define		MDMBUF		0x00100000	/* start/stop output on carrier intr */
  #define		LITOUT		0x00200000	/* literal output */
  #define		TOSTOP		0x00400000	/* SIGSTOP on background output */
  #define		FLUSHO		0x00800000	/* flush output to terminal */
  #define		NOHANG		0x01000000	/* no SIGHUP on carrier drop */
! #define		RTSCTS		0x02000000	/* use RTS/CTS flow control */
  #define		CRTKIL		0x04000000	/* kill line with " \b " */
  #define		PASS8		0x08000000
  #define		CTLECH		0x10000000	/* echo control chars as ^X */
***************
*** 189,200 ****
  #define		LCRTBS		((int)(CRTBS>>16))
  #define		LPRTERA		((int)(PRTERA>>16))
  #define		LCRTERA		((int)(CRTERA>>16))
- #define		LTILDE		((int)TILDE>>16)) /* (obsolete) place holder */
  #define		LMDMBUF		((int)(MDMBUF>>16))
  #define		LLITOUT		((int)(LITOUT>>16))
  #define		LTOSTOP		((int)(TOSTOP>>16))
  #define		LFLUSHO		((int)(FLUSHO>>16))
  #define		LNOHANG		((int)(NOHANG>>16))
  #define		LCRTKIL		((int)(CRTKIL>>16))
  #define		LPASS8		((int)(PASS8>>16))
  #define		LCTLECH		((int)(CTLECH>>16))
--- 175,186 ----
  #define		LCRTBS		((int)(CRTBS>>16))
  #define		LPRTERA		((int)(PRTERA>>16))
  #define		LCRTERA		((int)(CRTERA>>16))
  #define		LMDMBUF		((int)(MDMBUF>>16))
  #define		LLITOUT		((int)(LITOUT>>16))
  #define		LTOSTOP		((int)(TOSTOP>>16))
  #define		LFLUSHO		((int)(FLUSHO>>16))
  #define		LNOHANG		((int)(NOHANG>>16))
+ #define		LRTSCTS		((int)(RTSCTS>>16))
  #define		LCRTKIL		((int)(CRTKIL>>16))
  #define		LPASS8		((int)(PASS8>>16))
  #define		LCTLECH		((int)(CTLECH>>16))
*** /usr/src/sys/h/tty.h.old	Wed Dec  7 21:01:06 1994
--- /usr/src/sys/h/tty.h	Fri May  2 16:56:42 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)tty.h	7.1.1 (2.11BSD GTE) 12/7/94
   */
  
  #ifdef KERNEL
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)tty.h	7.1.2 (2.11BSD GTE) 1997/4/10
   */
  
  #ifdef KERNEL
***************
*** 93,99 ****
  #define	NSPEEDS	16
  #define	TTMASK	15
  #define	OBUFSIZ	100
! #define	TTYHOG	255
  #if defined(KERNEL) && !defined(SUPERVISOR)
  short	tthiwat[NSPEEDS], ttlowat[NSPEEDS];
  #define	TTHIWAT(tp)	tthiwat[(tp)->t_ospeed&TTMASK]
--- 93,99 ----
  #define	NSPEEDS	16
  #define	TTMASK	15
  #define	OBUFSIZ	100
! 
  #if defined(KERNEL) && !defined(SUPERVISOR)
  short	tthiwat[NSPEEDS], ttlowat[NSPEEDS];
  #define	TTHIWAT(tp)	tthiwat[(tp)->t_ospeed&TTMASK]
***************
*** 117,130 ****
  #define	TS_WCOLL	0x001000L	/* collision in write select */
  #define	TS_ASYNC	0x004000L	/* tty in async i/o mode */
  /* state for intra-line fancy editing work */
- #define	TS_BKSL		0x010000L	/* state for lowercase \ work */
- #define	TS_QUOT		0x020000L	/* last character input was \ */
  #define	TS_ERASE	0x040000L	/* within a \.../ for PRTRUB */
  #define	TS_LNCH		0x080000L	/* next character is literal */
  #define	TS_TYPEN	0x100000L	/* retyping suspended input (PENDIN) */
  #define	TS_CNTTB	0x200000L	/* counting tab width; leave FLUSHO alone */
  
! #define	TS_LOCAL	(TS_BKSL|TS_QUOT|TS_ERASE|TS_LNCH|TS_TYPEN|TS_CNTTB)
  
  /* define partab character types */
  #define	ORDINARY	0
--- 117,128 ----
  #define	TS_WCOLL	0x001000L	/* collision in write select */
  #define	TS_ASYNC	0x004000L	/* tty in async i/o mode */
  /* state for intra-line fancy editing work */
  #define	TS_ERASE	0x040000L	/* within a \.../ for PRTRUB */
  #define	TS_LNCH		0x080000L	/* next character is literal */
  #define	TS_TYPEN	0x100000L	/* retyping suspended input (PENDIN) */
  #define	TS_CNTTB	0x200000L	/* counting tab width; leave FLUSHO alone */
  
! #define	TS_LOCAL	(TS_ERASE|TS_LNCH|TS_TYPEN|TS_CNTTB)
  
  /* define partab character types */
  #define	ORDINARY	0
*** /usr/src/sys/h/ttychars.h.old	Sat May 16 11:29:24 1987
--- /usr/src/sys/h/ttychars.h	Mon Apr 21 20:21:57 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ttychars.h	7.1 (Berkeley) 6/4/86
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ttychars.h	7.2 (2.11BSD) 1997/4/15
   */
  
  /*
***************
*** 30,35 ****
--- 30,37 ----
  };
  
  #define	CTRL(c)	('c'&037)
+ #define	_POSIX_VDISABLE	((unsigned char)'\377')
+ #define	CCEQ(val,c)	(c == val ? val != _POSIX_VDISABLE : 0)
  
  /* default special characters */
  #define	CERASE	0177
***************
*** 40,46 ****
  #define	CSTOP	CTRL(s)
  #define	CEOF	CTRL(d)
  #define	CEOT	CEOF
! #define	CBRK	0377
  #define	CSUSP	CTRL(z)
  #define	CDSUSP	CTRL(y)
  #define	CRPRNT	CTRL(r)
--- 42,48 ----
  #define	CSTOP	CTRL(s)
  #define	CEOF	CTRL(d)
  #define	CEOT	CEOF
! #define	CBRK	_POSIX_VDISABLE
  #define	CSUSP	CTRL(z)
  #define	CDSUSP	CTRL(y)
  #define	CRPRNT	CTRL(r)
***************
*** 47,50 ****
  #define	CFLUSH	CTRL(o)
  #define	CWERASE	CTRL(w)
  #define	CLNEXT	CTRL(v)
! #endif
--- 49,52 ----
  #define	CFLUSH	CTRL(o)
  #define	CWERASE	CTRL(w)
  #define	CLNEXT	CTRL(v)
! #endif /* _TTYCHARS_ */
*** /usr/src/sys/h/ttydefaults.h.old	Mon Sep 26 21:54:54 1988
--- /usr/src/sys/h/ttydefaults.h	Tue Apr 15 20:54:18 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ttydefaults.h	1.1 (Berkeley) 3/25/88
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)ttydefaults.h	1.2 (2.11BSD) 1997/4/15
   */
  
  /*
***************
*** 17,32 ****
   * Control Character Defaults
   */
  #define	CEOF		CTRL(d)
! #define	CEOL		POSIX_V_DISABLE
! #ifdef DECSTYLE_DEFAULTS
! #define	CERASE		0177
  #define	CINTR		CTRL(c)	
  #define	CKILL		CTRL(u)
- #else
- #define	CERASE		CTRL(h)
- #define	CINTR		0177
- #define	CKILL		CTRL(x)
- #endif
  #define	CMIN		1
  #define	CQUIT		034	/* FS, ^\ */
  #define	CSUSP		CTRL(z)
--- 17,26 ----
   * Control Character Defaults
   */
  #define	CEOF		CTRL(d)
! #define	CEOL		_POSIX_VDISABLE
! #define	CERASE		CTRL(h)
  #define	CINTR		CTRL(c)	
  #define	CKILL		CTRL(u)
  #define	CMIN		1
  #define	CQUIT		034	/* FS, ^\ */
  #define	CSUSP		CTRL(z)
***************
*** 41,59 ****
  #define CQUOTE		'\\'
  #define	CEOT		CEOF
  
- #ifdef COMPAT_43
  #define	CBRK		CEOL
  #define CRPRNT		CREPRINT
  #define CFLUSH		CFLUSHO
- #endif
  
  /*
   * Settings on first open of a tty.
   */
- #define	TTYDEF_IFLAG	(BRKINT | ISTRIP | IMAXBEL | IEXTEN)
- #define TTYDEF_OFLAG	(0)
- #define TTYDEF_LFLAG	(ECHO | ICANON | ISIG)
- #define TTYDEF_CFLAG	(CREAD | CS7 | PARENB)
  #define TTYDEF_SPEED	(B9600)
  
  #endif /*_TTYDEFAULTS_*/
--- 35,47 ----
***************
*** 65,70 ****
  u_char	ttydefchars[NCC] = {
  	CEOF,	CEOL,	CEOL,	CERASE, CWERASE, CKILL, CREPRINT, CQUOTE,
  	CINTR,	CQUIT,	CSUSP,	CDSUSP,	CSTART,	CSTOP,	CLNEXT,
! 	CFLUSHO, CMIN,	CTIME, POSIX_V_DISABLE, POSIX_V_DISABLE
  };
  #endif /*TTYDEFCHARS*/
--- 53,58 ----
  u_char	ttydefchars[NCC] = {
  	CEOF,	CEOL,	CEOL,	CERASE, CWERASE, CKILL, CREPRINT, CQUOTE,
  	CINTR,	CQUIT,	CSUSP,	CDSUSP,	CSTART,	CSTOP,	CLNEXT,
! 	CFLUSHO, CMIN,	CTIME, _POSIX_VDISABLE, _POSIX_VDISABLE
  };
  #endif /*TTYDEFCHARS*/
*** /usr/src/sys/pdp/cons.c.old	Wed Nov 30 22:01:31 1994
--- /usr/src/sys/pdp/cons.c	Fri Apr 25 21:57:42 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)cons.c	1.2 (2.11BSD GTE) 11/29/94
   */
  
  /*
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)cons.c	1.3 (2.11BSD GTE) 1997/4/25
   */
  
  /*
***************
*** 32,38 ****
  int	nkl11 = NKL;			/* for pstat */
  struct	tty cons[NKL];
  int	cnstart();
- int	ttrstrt();
  char	partab[];
  
  cnattach(addr, unit)
--- 32,37 ----
***************
*** 80,85 ****
--- 79,85 ----
  
  	(*linesw[tp->t_line].l_close)(tp, flag);
  	ttyclose(tp);
+ 	return(0);
  }
  
  /*ARGSUSED*/
***************
*** 154,170 ****
  	s = spltty();
  	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
  		goto out;
! 	if (tp->t_outq.c_cc <= TTLOWAT(tp)) {
! 		if (tp->t_state&TS_ASLEEP) {
! 			tp->t_state &= ~TS_ASLEEP;
! 			wakeup((caddr_t)&tp->t_outq);
! 		}
! 		if (tp->t_wsel) {
! 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
! 			tp->t_wsel = 0;
! 			tp->t_state &= ~TS_WCOLL;
! 		}
! 	}
  	if (tp->t_outq.c_cc == 0)
  		goto out;
  	addr = (struct dldevice *)tp->t_addr;
--- 154,160 ----
  	s = spltty();
  	if (tp->t_state & (TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
  		goto out;
! 	ttyowake(tp);
  	if (tp->t_outq.c_cc == 0)
  		goto out;
  	addr = (struct dldevice *)tp->t_addr;
***************
*** 173,185 ****
  	c = getc(&tp->t_outq);
  	if (tp->t_flags & (RAW|LITOUT))
  		addr->dlxbuf = c&0xff;
! 	else if (c <= 0177)
! 		addr->dlxbuf = (c | ((partab[c]&0200))&0xff);
! 	else {
! 		timeout(ttrstrt, (caddr_t)tp, c&0177);
! 		tp->t_state |= TS_TIMEOUT;
! 		goto out;
! 	}
  	tp->t_state |= TS_BUSY;
  out:
  	splx(s);
--- 163,170 ----
  	c = getc(&tp->t_outq);
  	if (tp->t_flags & (RAW|LITOUT))
  		addr->dlxbuf = c&0xff;
! 	else
! 		addr->dlxbuf = c | (partab[c] & 0200);
  	tp->t_state |= TS_BUSY;
  out:
  	splx(s);
***************
*** 187,193 ****
  
  /* copied, for supervisory networking, to sys_sup.c */
  cnputc(c)
! 	register int c;
  {
  	register int s, timo;
  
--- 172,178 ----
  
  /* copied, for supervisory networking, to sys_sup.c */
  cnputc(c)
! 	char c;
  {
  	register int s, timo;
  
***************
*** 203,209 ****
  		return;
  	s = cnaddr->dlxcsr;
  	cnaddr->dlxcsr = 0;
! 	cnaddr->dlxbuf = c&0xff;
  	if (c == '\n')
  		cnputc('\r');
  	cnputc(0);
--- 188,194 ----
  		return;
  	s = cnaddr->dlxcsr;
  	cnaddr->dlxcsr = 0;
! 	cnaddr->dlxbuf = c;
  	if (c == '\n')
  		cnputc('\r');
  	cnputc(0);
*** /usr/src/sys/pdpuba/dhv.c.old	Fri Feb 14 21:02:38 1997
--- /usr/src/sys/pdpuba/dhv.c	Fri May  2 20:03:42 1997
***************
*** 3,12 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)dhv.c	2.2 (2.11BSD Berkeley) 1997/2/14
   */
  
  /*
   * ported to 2.11BSD (uio logic added) 12/22/91 - SMS
   * based on	dh.c 6.3	84/03/15
   * and on	dmf.c	6.2	84/02/16
--- 3,15 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)dhv.c	2.3 (2.11BSD 2.11BSD) 1997/5/1
   */
  
  /*
+  * Rewritten to implement hardware flowcontrol. A lot of clean up was done
+  * and the formatting style change to aid in debugging.  1997/4/25 - sms
+  *
   * ported to 2.11BSD (uio logic added) 12/22/91 - SMS
   * based on	dh.c 6.3	84/03/15
   * and on	dmf.c	6.2	84/02/16
***************
*** 38,43 ****
--- 41,47 ----
  #include "uba.h"
  #include "ubavar.h"
  #include "systm.h"
+ #include "syslog.h"
  #include <sys/kernel.h>
  
  struct	uba_device dhvinfo[NDHV];
***************
*** 44,54 ****
  
  #define	NDHVLINE	(NDHV*8)
  
! #define	UNIT(x)		(minor(x) & 077)
! #define CDWAIT(x)	(!(minor(x) & 0200))
! #define HWFLOW(x)	(minor(x) & 0100)
  
- #define ISPEED	B9600
  #define IFLAGS	(EVENP|ODDP|ECHO)
  
  /*
--- 48,66 ----
  
  #define	NDHVLINE	(NDHV*8)
  
! /*
!  * The minor device number is used as follows:
!  *
!  *  bits	meaning
!  *  0-2		unit number within board
!  *  3-5		board number (max of 8)
!  *  6		RTS/CTS flow control enabled
!  *  7		softcarrier (hardwired line)
! */
! #define	UNIT(x)	(minor(x) & 077)
! #define SOFTCAR	0x80
! #define HWFLOW	0x40
  
  #define IFLAGS	(EVENP|ODDP|ECHO)
  
  /*
***************
*** 76,84 ****
  struct	tty dhv_tty[NDHVLINE];
  int	ndhv = NDHVLINE;
  int	dhvact;				/* mask of active dhv's */
! int	dhv_rcnt[16];
! int	dhvstart(), ttrstrt();
  long	dhvmctl(),dmtodhv();
  
  #if defined(UCB_CLIST)
  extern	ubadr_t clstaddr;
--- 88,97 ----
  struct	tty dhv_tty[NDHVLINE];
  int	ndhv = NDHVLINE;
  int	dhvact;				/* mask of active dhv's */
! int	dhv_overrun[NDHVLINE];
! int	dhvstart();
  long	dhvmctl(),dmtodhv();
+ extern	int wakeup();
  
  #if defined(UCB_CLIST)
  extern	ubadr_t clstaddr;
***************
*** 112,189 ****
  /*ARGSUSED*/
  dhvopen(dev, flag)
  	dev_t dev;
! {
  	register struct tty *tp;
! 	register int unit, dhv;
  	register struct dhvdevice *addr;
! 	register struct uba_device *ui;
! 	int i, s;
  
  	unit = UNIT(dev);
  	dhv = unit >> 3;
! 	if (unit >= NDHVLINE || (ui = &dhvinfo[dhv])->ui_alive == 0)
! 		return (ENXIO);
  	tp = &dhv_tty[unit];
- 	if (tp->t_state & TS_XCLUDE && u.u_uid != 0)
- 		return (EBUSY);
  	addr = (struct dhvdevice *)ui->ui_addr;
  	tp->t_addr = (caddr_t)addr;
  	tp->t_oproc = dhvstart;
  
! 	if ((dhvact&(1<<dhv)) == 0) {
  		addr->dhvcsr = DHV_SELECT(0) | DHV_IE;
  		dhvact |= (1<<dhv);
  		/* anything else to configure whole board */
! 	}
  
  	s = spltty();
! 	if ( (tp->t_state&TS_ISOPEN) && tp->t_dev == dev )
! 	{
! 	    i = (*linesw[tp->t_line].l_open)(dev, tp);
! 	    (void) splx(s);
! 	    return(i);
! 	}
! 
! 	/*
! 	 * Wait for carrier, then process line discipline specific open.
! 	 */
! 	while ( (tp->t_state&TS_ISOPEN) == 0 || tp->t_dev != dev )
! 	{
! 	    if ( tp->t_state & TS_ISOPEN )
! 	    {
! 		sleep ( (caddr_t)&tp->t_state, TTIPRI );
! 		continue;
! 	    }
! 	    tp->t_dev = dev;
! 	    addr->dhvcsr = DHV_SELECT(dev) | DHV_IE;
! 	    if ( addr->dhvstat & DHV_ST_DCD ) tp->t_state |= TS_CARR_ON;
! 	    else			      tp->t_state &= ~TS_CARR_ON;
! 	    if ( CDWAIT(dev) && (tp->t_state & TS_CARR_ON) == 0 ||
! 		 HWFLOW(dev) && (addr->dhvstat & DHV_ST_DSR) == 0 )
! 	    {
! 		dhvmctl ( dev, (long)DHV_ON, DMSET );
  		tp->t_state |= TS_WOPEN;
! 		sleep ( (caddr_t)&tp->t_rawq, TTIPRI );
! 		continue;
! 	    }
! 	    dhvmctl ( dev, (long)DHV_ON, DMSET );
! 	    break;
! 	}
! 	if ( !(tp->t_state&TS_ISOPEN) )
! 	{
  		ttychars(tp);
- 		tp->t_state |= TS_HUPCLS;
- 		tp->t_ispeed = ISPEED;
- 		tp->t_ospeed = ISPEED;
- 		tp->t_flags = IFLAGS | (HWFLOW(dev) ? TANDEM : 0);
  		tp->t_dev = dev;
  	}
- 	if ( !CDWAIT(dev) ) tp->t_state |= TS_CARR_ON;
- 	dhvparam(unit);
- 	i = (*linesw[tp->t_line].l_open)(dev, tp);
- 	(void) splx(s);
- 	return ( i );
- }
  
  /*
   * Close a DHV11 line, turning off the modem control.
--- 125,193 ----
  /*ARGSUSED*/
  dhvopen(dev, flag)
  	dev_t dev;
! 	int 	flag;
! 	{
  	register struct tty *tp;
! 	register int unit;
! 	int	dhv, error, s;
  	register struct dhvdevice *addr;
! 	struct uba_device *ui;
  
  	unit = UNIT(dev);
  	dhv = unit >> 3;
! 	if	(unit >= NDHVLINE || (ui = &dhvinfo[dhv])->ui_alive == 0)
! 		return(ENXIO);
  	tp = &dhv_tty[unit];
  	addr = (struct dhvdevice *)ui->ui_addr;
  	tp->t_addr = (caddr_t)addr;
  	tp->t_oproc = dhvstart;
  
! 	if	((dhvact & (1<<dhv)) == 0)
! 		{
  		addr->dhvcsr = DHV_SELECT(0) | DHV_IE;
  		dhvact |= (1<<dhv);
  		/* anything else to configure whole board */
! 		}
  
  	s = spltty();
! 	if	((tp->t_state & TS_ISOPEN) == 0)
! 		{
  		tp->t_state |= TS_WOPEN;
! 		if	(tp->t_ispeed == 0)
! 			{
! 			tp->t_state |= TS_HUPCLS;
! 			tp->t_ispeed = B9600;
! 			tp->t_ospeed = B9600;
! 			tp->t_flags = IFLAGS;
! 			}
  		ttychars(tp);
  		tp->t_dev = dev;
+ 		if	(dev & HWFLOW)
+ 			tp->t_flags |= RTSCTS;
+ 		else
+ 			tp->t_flags &= ~RTSCTS;
+ 		dhvparam(unit);
+ 		}
+ 	else if	((tp->t_state & TS_XCLUDE) && u.u_uid)
+ 		{
+ 		error = EBUSY;
+ 		goto out;
+ 		}
+ 	dhvmctl(dev, (long)DHV_ON, DMSET);
+ 	addr->dhvcsr = DHV_SELECT(dev) | DHV_IE;
+ 	if	((addr->dhvstat & DHV_ST_DCD) || (dev & SOFTCAR))
+ 		tp->t_state |= TS_CARR_ON;
+ 	while	((tp->t_state & TS_CARR_ON) == 0 &&
+ 		 (flag & O_NONBLOCK) == 0)
+ 		{
+ 		tp->t_state |= TS_WOPEN;
+ 		sleep((caddr_t)&tp->t_rawq, TTIPRI);
+ 		}
+ 	error = (*linesw[tp->t_line].l_open)(dev, tp);
+ out:
+ 	splx(s);
+ 	return(error);
  	}
  
  /*
   * Close a DHV11 line, turning off the modem control.
***************
*** 192,361 ****
  dhvclose(dev, flag)
  	dev_t dev;
  	int flag;
! {
  	register struct tty *tp;
! 	register unit, s;
  
  	unit = UNIT(dev);
  	tp = &dhv_tty[unit];
! 	s = spltty();
! 	if ( !(tp->t_state & TS_ISOPEN) || tp->t_dev != dev ) return;
  	(*linesw[tp->t_line].l_close)(tp, flag);
  	(void) dhvmctl(unit, (long)DHV_BRK, DMBIC);
  	(void) dhvmctl(unit, (long)DHV_OFF, DMSET);
- 	if ( CDWAIT(tp->t_dev) ||
- 	    (tp->t_state&(TS_HUPCLS|TS_WOPEN)) ||
- 	    (tp->t_state&TS_ISOPEN)==0 )
- 	{
- 		extern int wakeup();
- 
- 		/* Hold DTR low for 0.5 seconds */
- 		timeout(wakeup, (caddr_t) &tp->t_dev, hz/2);
- 		sleep((caddr_t) &tp->t_dev, PZERO);
- 	}
  	ttyclose(tp);
! 	splx(s);
! 	wakeup ( (caddr_t) &tp->t_state );
! }
  
! dhvselect ( dev, rw )	/* filter the minor device number */
  	dev_t	dev;
  	int	rw;
! {
!     return ( ttselect ( dev & ~0300, rw ) );
! }
  
  dhvread(dev, uio, flag)
  	dev_t dev;
  	struct uio *uio;
  	int flag;
! {
  	register struct tty *tp = &dhv_tty[UNIT(dev)];
  
!     return((*linesw[tp->t_line].l_read) (tp, uio, flag));
! }
  
  dhvwrite(dev, uio, flag)
  	dev_t dev;
  	struct uio *uio;
  	int flag;
! {
  	register struct tty *tp = &dhv_tty[UNIT(dev)];
  
!     return((*linesw[tp->t_line].l_write) (tp, uio, flag));
! }
  
  /*
   * DHV11 receiver interrupt.
   */
  
- int	dhvwait;
- 
  dhvrint(dhv)
  	int	dhv;
! {
  	register struct tty *tp;
! 	register c;
  	register struct dhvdevice *addr;
! 	register struct tty *tp0;
! 	register struct uba_device *ui;
! 	int line, rcnt;
! 	int overrun;
  
  	ui = &dhvinfo[dhv];
- 	if (ui->ui_alive == 0)
- 		return;
  	addr = (struct dhvdevice *)ui->ui_addr;
  	tp0 = &dhv_tty[dhv<<3];
  	/*
  	 * Loop fetching characters from the silo for this
  	 * dhv until there are no more in the silo.
  	 */
! 	rcnt = 0;
! 	overrun = 0;
! 	while ((c = addr->dhvrbuf) & DHV_RB_VALID )
! 	{
! 		rcnt++;
  		line = DHV_RX_LINE(c);
  		tp = tp0 + line;
! 		if ((c & DHV_RB_STAT) == DHV_RB_STAT) {
  			/*
  			 * modem changed or diag info
  			 */
! 			if (c & DHV_RB_DIAG)
  			{
! 			    if ( (c & 0xff) > 0201 )
! 				printf ( "dhv%d: diagnostic %o\n",
! 							dhv, c & 0xff );
! 			    continue;
  			}
! 			if ( CDWAIT(tp->t_dev) || (tp->t_flags & MDMBUF) )
! 			    (*linesw[tp->t_line].l_modem)
! 				( tp, (c & DHV_ST_DCD) != 0 );
! 			if ( HWFLOW(tp->t_dev) )
  			{
! 			    if ( c & DHV_ST_DSR )
! 			    {
! 				tp->t_state &= ~TS_TTSTOP;
! 				ttstart(tp);
! 			    }
! 			    else
! 			    {
! 				tp->t_state |= TS_TTSTOP;
! 				dhvstop (tp, 0);
! 			    }
  			}
- 			continue;
- 		}
- 		if ((tp->t_state&TS_ISOPEN) == 0)
- 		{
- 		    wakeup((caddr_t)&tp->t_rawq);
- 		    continue;
- 		}
- 		if ( c & (DHV_RB_PE|DHV_RB_DO|DHV_RB_FE) )
- 		{
- 		    if (c & DHV_RB_PE)
- 			    if ((tp->t_flags&(EVENP|ODDP)) == EVENP ||
- 				(tp->t_flags&(EVENP|ODDP)) == ODDP)
- 				    continue;
- 		    if ( (c & DHV_RB_DO) && !overrun )
- 		    {
- 			overrun = 1;
- 			    /* bit-bucket the que to free the cpu */
- 			while ( addr->dhvrbuf & DHV_RB_VALID );
- 			break;
- 		    }
- 		    if (c & DHV_RB_FE)
- 			/*
- 			 * At framing error (break) generate
- 			 * an interrupt (in cooked/cbreak mode)
- 			 * or let the char through in RAW mode
- 			 * for autobauding getty's.
- 			 */
- 			if ( !(tp->t_flags&RAW) )
- 			    c = tp->t_intrc;
- 		}
  #if NBK > 0
! 		if (tp->t_line == NETLDISC) {
  			c &= 0x7f;
  			BKINPUT(c, tp);
! 		} else
  #endif
! 		{
! 		    if ( !(c & DHV_RB_PE) && dhv_hwxon[(dhv<<3)+line] &&
! 			((c & 0x7f) == CSTOP || (c & 0x7f) == CSTART) )
  				continue;
! 		    (*linesw[tp->t_line].l_rint)(c, tp);
  		}
  	}
- 	if	(overrun)
- 		printf("dhv%d: silo overflow\n", dhv);
- 	else if	(rcnt)
- 		{
- 		for	(line = 0; rcnt; line++) rcnt >>= 1;
- 		dhv_rcnt[line]++;
- 		}
- }
  
  /*
   * Ioctl for DHV11.
--- 196,361 ----
  dhvclose(dev, flag)
  	dev_t dev;
  	int flag;
! 	{
  	register struct tty *tp;
! 	register int unit;
  
  	unit = UNIT(dev);
  	tp = &dhv_tty[unit];
! 	if	(!(tp->t_state & TS_ISOPEN))
! 		return;
  	(*linesw[tp->t_line].l_close)(tp, flag);
  	(void) dhvmctl(unit, (long)DHV_BRK, DMBIC);
  	(void) dhvmctl(unit, (long)DHV_OFF, DMSET);
  	ttyclose(tp);
! 	if	(dhv_overrun[unit])
! 		{
! 		log(LOG_NOTICE,"dhv%d %d overruns\n",unit,dhv_overrun[unit]);
! 		dhv_overrun[unit] = 0;
! 		}
! 	return(0);
! 	}
  
! dhvselect(dev, rw)
  	dev_t	dev;
  	int	rw;
! 	{
! 	struct	tty *tp = &dhv_tty[UNIT(dev)];
  
+ 	return(ttyselect(tp, rw));
+ 	}
+ 
  dhvread(dev, uio, flag)
  	dev_t dev;
  	struct uio *uio;
  	int flag;
! 	{
  	register struct tty *tp = &dhv_tty[UNIT(dev)];
  
! 	return((*linesw[tp->t_line].l_read) (tp, uio, flag));
! 	}
  
  dhvwrite(dev, uio, flag)
  	dev_t dev;
  	struct uio *uio;
  	int flag;
! 	{
  	register struct tty *tp = &dhv_tty[UNIT(dev)];
  
! 	return((*linesw[tp->t_line].l_write) (tp, uio, flag));
! 	}
  
  /*
   * DHV11 receiver interrupt.
   */
  
  dhvrint(dhv)
  	int	dhv;
! 	{
  	register struct tty *tp;
! 	register int	c;
  	register struct dhvdevice *addr;
! 	struct tty *tp0;
! 	struct uba_device *ui;
! 	int	line, p;
  
  	ui = &dhvinfo[dhv];
  	addr = (struct dhvdevice *)ui->ui_addr;
+ 	if	(!addr)
+ 		return;
  	tp0 = &dhv_tty[dhv<<3];
+ 
  	/*
  	 * Loop fetching characters from the silo for this
  	 * dhv until there are no more in the silo.
  	 */
! 	while	((c = addr->dhvrbuf) & DHV_RB_VALID)
! 		{
  		line = DHV_RX_LINE(c);
  		tp = tp0 + line;
! 		if	((c & DHV_RB_STAT) == DHV_RB_STAT)
! 			{
  			/*
  			 * modem changed or diag info
  			 */
! 			if	(c & DHV_RB_DIAG)
! 				{
! 				if	((c & 0xff) > 0201)
! 					printf ("dhv%d: diag %o\n",dhv, c&0xff);
! 			    	continue;
! 				}
! 			if	(!(tp->t_dev & SOFTCAR) || 
! 				  (tp->t_flags & MDMBUF))
! 			    	(*linesw[tp->t_line].l_modem)(tp, 
! 							(c & DHV_ST_DCD) != 0);
! 			if	(tp->t_flags & RTSCTS)
! 				{
! 				if	(c & DHV_ST_CTS)
! 			    		{
! 					tp->t_state &= ~TS_TTSTOP;
! 					ttstart(tp);
! 			    		}
! 				else
! 					{
! 					tp->t_state |= TS_TTSTOP;
! 					dhvstop(tp, 0);
! 			    		}
! 				}
! 			continue;
! 			}
! 		if	((tp->t_state&TS_ISOPEN) == 0)
  			{
! 		    	wakeup((caddr_t)&tp->t_rawq);
! 			continue;
  			}
! 		if	(c & (DHV_RB_PE|DHV_RB_DO|DHV_RB_FE))
  			{
! 		    	if	(c & DHV_RB_PE)
! 				{
! 				p = tp->t_flags & (EVENP|ODDP);
! 				if	(p == EVENP || p == ODDP)
! 					continue;
! 				}
! 			if	(c & DHV_RB_DO)
! 				{
! 				dhv_overrun[(dhv << 3) + line]++;
! 				/* bit-bucket the silo to free the cpu */
! 				while	(addr->dhvrbuf & DHV_RB_VALID)
! 					;
! 				break;
! 				}
! 			if	(c & DHV_RB_FE)
! 				{
! /*
!  * At framing error (break) generate an interrupt in cooked/cbreak mode.  
!  * Let the char through in RAW mode for autobauding getty's.  The 
!  * DH driver * has been using the 'brkc' character for years - see
!  * the comment in dh.c
! */
! 				if	(!(tp->t_flags&RAW))
! #ifdef	OLDWAY
! 					c = tp->t_intrc;
! #else
! 					c = tp->t_brkc;
! 				}
! #endif
  			}
  #if NBK > 0
! 		if	(tp->t_line == NETLDISC)
! 			{
  			c &= 0x7f;
  			BKINPUT(c, tp);
! 			}
! 		else
  #endif
! 			{
! 			if	(!(c & DHV_RB_PE) && dhv_hwxon[(dhv<<3)+line] &&
! 				 ((c & 0x7f) == CSTOP || (c & 0x7f) == CSTART))
  				continue;
! 			(*linesw[tp->t_line].l_rint)(c, tp);
! 			}
  		}
  	}
  
  /*
   * Ioctl for DHV11.
***************
*** 365,371 ****
  	register dev_t dev;
  	u_int cmd;
  	caddr_t data;
! {
  	register struct tty *tp;
  	register int unit = UNIT(dev);
  	int error;
--- 365,371 ----
  	register dev_t dev;
  	u_int cmd;
  	caddr_t data;
! 	{
  	register struct tty *tp;
  	register int unit = UNIT(dev);
  	int error;
***************
*** 372,453 ****
  
  	tp = &dhv_tty[unit];
  	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
! 	if (error >= 0)
! 		return (error);
  	error = ttioctl(tp, cmd, data, flag);
! 	if (error >= 0) {
! 		if (cmd == TIOCSETP || cmd == TIOCSETN || cmd == TIOCLSET ||
! 		    cmd == TIOCLBIC || cmd == TIOCLBIS || cmd == TIOCSETD ||
! 		    cmd == TIOCSETC)
  			dhvparam(unit);
! 		return (error);
! 	}
  
! 	switch (cmd) {
! 	case TIOCSBRK:
! 		(void) dhvmctl(unit, (long)DHV_BRK, DMBIS);
! 		break;
! 
! 	case TIOCCBRK:
! 		(void) dhvmctl(unit, (long)DHV_BRK, DMBIC);
! 		break;
! 
! 	case TIOCSDTR:
! 		(void) dhvmctl(unit, (long)DHV_DTR|DHV_RTS, DMBIS);
! 		break;
! 
! 	case TIOCCDTR:
! 		(void) dhvmctl(unit, (long)DHV_DTR|DHV_RTS, DMBIC);
! 		break;
! 
! 	case TIOCMSET:
! 		(void) dhvmctl(dev, dmtodhv(*(int *)data), DMSET);
! 		break;
! 
! 	case TIOCMBIS:
! 		(void) dhvmctl(dev, dmtodhv(*(int *)data), DMBIS);
! 		break;
! 
! 	case TIOCMBIC:
! 		(void) dhvmctl(dev, dmtodhv(*(int *)data), DMBIC);
! 		break;
! 
! 	case TIOCMGET:
! 		*(int *)data = dhvtodm(dhvmctl(dev, 0L, DMGET));
! 		break;
! 	default:
! 		return (ENOTTY);
  	}
- 	return (0);
- }
  
  static long
  dmtodhv(bits)
  	register int bits;
! {
  	long b = 0;
  
! 	if (bits & DML_RTS) b |= DHV_RTS;
! 	if (bits & DML_DTR) b |= DHV_DTR;
! 	if (bits & DML_LE) b |= DHV_LE;
  	return(b);
! }
  
  static
  dhvtodm(bits)
  	long bits;
! {
  	register int b = 0;
  
! 	if (bits & DHV_DSR) b |= DML_DSR;
! 	if (bits & DHV_RNG) b |= DML_RNG;
! 	if (bits & DHV_CAR) b |= DML_CAR;
! 	if (bits & DHV_CTS) b |= DML_CTS;
! 	if (bits & DHV_RTS) b |= DML_RTS;
! 	if (bits & DHV_DTR) b |= DML_DTR;
! 	if (bits & DHV_LE) b |= DML_LE;
  	return(b);
! }
  
  /*
   * Set parameters from open or stty into the DHV hardware
--- 372,448 ----
  
  	tp = &dhv_tty[unit];
  	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag);
! 	if	(error >= 0)
! 		return(error);
  	error = ttioctl(tp, cmd, data, flag);
! 	if	(error >= 0)
! 		{
! 		if	(cmd == TIOCSETP || cmd == TIOCSETN || 
! 			 cmd == TIOCLSET || cmd == TIOCLBIC ||
! 			 cmd == TIOCLBIS || cmd == TIOCSETD || cmd == TIOCSETC)
  			dhvparam(unit);
! 		return(error);
! 		}
  
! 	switch	(cmd)
! 		{
! 		case	TIOCSBRK:
! 			(void) dhvmctl(unit, (long)DHV_BRK, DMBIS);
! 			break;
! 		case	TIOCCBRK:
! 			(void) dhvmctl(unit, (long)DHV_BRK, DMBIC);
! 			break;
! 		case	TIOCSDTR:
! 			(void) dhvmctl(unit, (long)DHV_DTR|DHV_RTS, DMBIS);
! 			break;
! 		case	TIOCCDTR:
! 			(void) dhvmctl(unit, (long)DHV_DTR|DHV_RTS, DMBIC);
! 			break;
! 		case	TIOCMSET:
! 			(void) dhvmctl(dev, dmtodhv(*(int *)data), DMSET);
! 			break;
! 		case	TIOCMBIS:
! 			(void) dhvmctl(dev, dmtodhv(*(int *)data), DMBIS);
! 			break;
! 		case	TIOCMBIC:
! 			(void) dhvmctl(dev, dmtodhv(*(int *)data), DMBIC);
! 			break;
! 		case	TIOCMGET:
! 			*(int *)data = dhvtodm(dhvmctl(dev, 0L, DMGET));
! 			break;
! 		default:
! 			return(ENOTTY);
! 		}
! 	return(0);
  	}
  
  static long
  dmtodhv(bits)
  	register int bits;
! 	{
  	long b = 0;
  
! 	if	(bits & TIOCM_RTS) b |= DHV_RTS;
! 	if	(bits & TIOCM_DTR) b |= DHV_DTR;
! 	if	(bits & TIOCM_LE) b |= DHV_LE;
  	return(b);
! 	}
  
  static
  dhvtodm(bits)
  	long bits;
! 	{
  	register int b = 0;
  
! 	if	(bits & DHV_DSR) b |= TIOCM_DSR;
! 	if	(bits & DHV_RNG) b |= TIOCM_RNG;
! 	if	(bits & DHV_CAR) b |= TIOCM_CAR;
! 	if	(bits & DHV_CTS) b |= TIOCM_CTS;
! 	if	(bits & DHV_RTS) b |= TIOCM_RTS;
! 	if	(bits & DHV_DTR) b |= TIOCM_DTR;
! 	if	(bits & DHV_LE) b |= TIOCM_LE;
  	return(b);
! 	}
  
  /*
   * Set parameters from open or stty into the DHV hardware
***************
*** 455,466 ****
   */
  static
  dhvparam(unit)
! 	register int unit;
! {
  	register struct tty *tp;
  	register struct dhvdevice *addr;
  	register int lpar;
! 	int s;
  
  	tp = &dhv_tty[unit];
  	addr = (struct dhvdevice *)tp->t_addr;
--- 450,461 ----
   */
  static
  dhvparam(unit)
! 	int	unit;
! 	{
  	register struct tty *tp;
  	register struct dhvdevice *addr;
  	register int lpar;
! 	int	s;
  
  	tp = &dhv_tty[unit];
  	addr = (struct dhvdevice *)tp->t_addr;
***************
*** 469,497 ****
  	 * before the line interrupts.
  	 */
  	s = spltty();
! 	if ((tp->t_ispeed) == 0) {
  		tp->t_state |= TS_HUPCLS;
  		(void)dhvmctl(unit, (long)DHV_OFF, DMSET);
! 		splx(s);
! 		return;
! 	}
  	lpar = (dhv_speeds[tp->t_ospeed]<<12) | (dhv_speeds[tp->t_ispeed]<<8);
! 	if ((tp->t_ispeed) == B134)
  		lpar |= DHV_LP_BITS6|DHV_LP_PENABLE;
! 	else if (tp->t_flags & (RAW|L001000|LITOUT|PASS8))
  		lpar |= DHV_LP_BITS8;
  	else
  		lpar |= DHV_LP_BITS7|DHV_LP_PENABLE;
! 	if (tp->t_flags&EVENP)
  		lpar |= DHV_LP_EPAR;
! 	if ( (tp->t_flags & EVENP) && (tp->t_flags & ODDP) )
! 	{
  		/* hack alert.  assume "allow both" means don't care */
  		/* trying to make xon/xoff work with evenp+oddp */
  		lpar |= DHV_LP_BITS8;
  		lpar &= ~DHV_LP_PENABLE;
! 	}
! 	if ((tp->t_ospeed) == B110)
  		lpar |= DHV_LP_TWOSB;
  	addr->dhvcsr = DHV_SELECT(unit) | DHV_IE;
  	addr->dhvlpr = lpar;
--- 464,492 ----
  	 * before the line interrupts.
  	 */
  	s = spltty();
! 	if	((tp->t_ispeed) == 0)
! 		{
  		tp->t_state |= TS_HUPCLS;
  		(void)dhvmctl(unit, (long)DHV_OFF, DMSET);
! 		goto out;
! 		}
  	lpar = (dhv_speeds[tp->t_ospeed]<<12) | (dhv_speeds[tp->t_ispeed]<<8);
! 	if	(tp->t_ispeed == B134)
  		lpar |= DHV_LP_BITS6|DHV_LP_PENABLE;
! 	else if (tp->t_flags & (RAW|LITOUT|PASS8))
  		lpar |= DHV_LP_BITS8;
  	else
  		lpar |= DHV_LP_BITS7|DHV_LP_PENABLE;
! 	if	(tp->t_flags&EVENP)
  		lpar |= DHV_LP_EPAR;
! 	if	((tp->t_flags & EVENP) && (tp->t_flags & ODDP))
! 		{
  		/* hack alert.  assume "allow both" means don't care */
  		/* trying to make xon/xoff work with evenp+oddp */
  		lpar |= DHV_LP_BITS8;
  		lpar &= ~DHV_LP_PENABLE;
! 		}
! 	if	((tp->t_ospeed) == B110)
  		lpar |= DHV_LP_TWOSB;
  	addr->dhvcsr = DHV_SELECT(unit) | DHV_IE;
  	addr->dhvlpr = lpar;
***************
*** 498,513 ****
  	dhv_hwxon[unit] = !(tp->t_flags & RAW) &&
  		(tp->t_line == OTTYDISC || tp->t_line == NTTYDISC) &&
  		tp->t_stopc == CSTOP && tp->t_startc == CSTART;
! 	if ( dhv_hwxon[unit] )
! 	    addr->dhvlcr |= DHV_LC_OAUTOF;
  	else
! 	{
! 	    addr->dhvlcr &= ~DHV_LC_OAUTOF;
! 	    delay(25L); /* see the dhv manual, sec 3.3.6 */
! 	    addr->dhvlcr2 |= DHV_LC2_TXEN;
! 	}
  	splx(s);
! }
  
  /*
   * DHV11 transmitter interrupt.
--- 493,511 ----
  	dhv_hwxon[unit] = !(tp->t_flags & RAW) &&
  		(tp->t_line == OTTYDISC || tp->t_line == NTTYDISC) &&
  		tp->t_stopc == CSTOP && tp->t_startc == CSTART;
! 
! 	if	(dhv_hwxon[unit])
! 		addr->dhvlcr |= DHV_LC_OAUTOF;
  	else
! 		{
! 		addr->dhvlcr &= ~DHV_LC_OAUTOF;
! 		delay(25L); /* see the dhv manual, sec 3.3.6 */
! 		addr->dhvlcr2 |= DHV_LC2_TXEN;
! 		}
! out:
  	splx(s);
! 	return;
! 	}
  
  /*
   * DHV11 transmitter interrupt.
***************
*** 516,526 ****
   */
  dhvxint(dhv)
  	int dhv;
! {
  	register struct tty *tp;
  	register struct dhvdevice *addr;
! 	register struct tty *tp0;
! 	register struct uba_device *ui;
  	register int line, t;
  	u_short cntr;
  	ubadr_t base;
--- 514,524 ----
   */
  dhvxint(dhv)
  	int dhv;
! 	{
  	register struct tty *tp;
  	register struct dhvdevice *addr;
! 	struct tty *tp0;
! 	struct uba_device *ui;
  	register int line, t;
  	u_short cntr;
  	ubadr_t base;
***************
*** 528,544 ****
  	ui = &dhvinfo[dhv];
  	tp0 = &dhv_tty[dhv<<4];
  	addr = (struct dhvdevice *)ui->ui_addr;
! 	while ((t = addr->dhvcsrh) & DHV_CSH_TI) {
  		line = DHV_TX_LINE(t);
  		tp = tp0 + line;
  		tp->t_state &= ~TS_BUSY;
! 		if (t & DHV_CSH_NXM) {
! 			printf("dhv(%d,%d): NXM fault\n", dhv, line);
  			/* SHOULD RESTART OR SOMETHING... */
! 		}
! 		if (tp->t_state&TS_FLUSH)
  			tp->t_state &= ~TS_FLUSH;
! 		else {
  			addr->dhvcsrl = DHV_SELECT(line) | DHV_IE;
  			base = (ubadr_t) addr->dhvbar1;
  			/*
--- 526,545 ----
  	ui = &dhvinfo[dhv];
  	tp0 = &dhv_tty[dhv<<4];
  	addr = (struct dhvdevice *)ui->ui_addr;
! 	while	((t = addr->dhvcsrh) & DHV_CSH_TI)
! 		{
  		line = DHV_TX_LINE(t);
  		tp = tp0 + line;
  		tp->t_state &= ~TS_BUSY;
! 		if	(t & DHV_CSH_NXM)
! 			{
! 			printf("dhv(%d,%d) NXM\n", dhv, line);
  			/* SHOULD RESTART OR SOMETHING... */
! 			}
! 		if	(tp->t_state&TS_FLUSH)
  			tp->t_state &= ~TS_FLUSH;
! 		else
! 			{
  			addr->dhvcsrl = DHV_SELECT(line) | DHV_IE;
  			base = (ubadr_t) addr->dhvbar1;
  			/*
***************
*** 550,566 ****
  			 *
  			 * In either case, the extension bits are 0.
  			 */
! 			if (!ubmap)
! 			      base |= (ubadr_t)((addr->dhvbar2 & 037) << 16);
  		        cntr = base - cpaddr(tp->t_outq.c_cf);
  			ndflush(&tp->t_outq,cntr);
! 		}
! 		if (tp->t_line)
  			(*linesw[tp->t_line].l_start)(tp);
  		else
  			dhvstart(tp);
  	}
- }
  
  /*
   * Start (restart) transmission on the given DHV11 line.
--- 551,567 ----
  			 *
  			 * In either case, the extension bits are 0.
  			 */
! 			if	(!ubmap)
! 				base |= (ubadr_t)((addr->dhvbar2 & 037) << 16);
  		        cntr = base - cpaddr(tp->t_outq.c_cf);
  			ndflush(&tp->t_outq,cntr);
! 			}
! 		if	(tp->t_line)
  			(*linesw[tp->t_line].l_start)(tp);
  		else
  			dhvstart(tp);
+ 		}
  	}
  
  /*
   * Start (restart) transmission on the given DHV11 line.
***************
*** 567,573 ****
   */
  dhvstart(tp)
  	register struct tty *tp;
! {
  	register struct dhvdevice *addr;
  	register int unit, nch;
  	ubadr_t car;
--- 568,574 ----
   */
  dhvstart(tp)
  	register struct tty *tp;
! 	{
  	register struct dhvdevice *addr;
  	register int unit, nch;
  	ubadr_t car;
***************
*** 584,644 ****
  	/*
  	 * If it's currently active, or delaying, no need to do anything.
  	 */
! 	if (tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
  		goto out;
  	/*
  	 * If there are sleepers, and output has drained below low
  	 * water mark, wake up the sleepers..
  	 */
! 	if (tp->t_outq.c_cc<=TTLOWAT(tp)) {
! 		if (tp->t_state&TS_ASLEEP) {
! 			tp->t_state &= ~TS_ASLEEP;
! 			wakeup((caddr_t)&tp->t_outq);
! 		}
! 		if (tp->t_wsel) {
! 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
! 			tp->t_wsel = 0;
! 			tp->t_state &= ~TS_WCOLL;
! 		}
! 	}
  	/*
  	 * Now restart transmission unless the output queue is
  	 * empty.
  	 */
! 	if (tp->t_outq.c_cc == 0)
  		goto out;
! 	if (tp->t_flags & (RAW|L001000|LITOUT))
! 		nch = ndqb(&tp->t_outq, 0);
! 	else {
! 		nch = ndqb(&tp->t_outq, 0200);
! 		/*
! 		 * If first thing on queue is a delay process it.
! 		 */
! 		if (nch == 0) {
! 			nch = getc(&tp->t_outq);
! 			timeout(ttrstrt, (caddr_t)tp, (nch&0x7f)+6);
! 			tp->t_state |= TS_TIMEOUT;
! 			goto out;
  		}
! 	}
  	/*
  	 * If characters to transmit, restart transmission.
  	 */
! 	if (nch) {
  		car = cpaddr(tp->t_outq.c_cf);
  		addr->dhvcsrl = DHV_SELECT(unit) | DHV_IE;
  		addr->dhvlcr &= ~DHV_LC_TXABORT;
  		addr->dhvbcr = nch;
  		addr->dhvbar1 = loint(car);
! 		if (ubmap)
  			addr->dhvbar2 = (hiint(car) & DHV_BA2_XBA) | DHV_BA2_DMAGO;
  		else
  			addr->dhvbar2 = (hiint(car) & 037) | DHV_BA2_DMAGO;
  		tp->t_state |= TS_BUSY;
! 	}
  out:
  	splx(s);
! }
  
  /*
   * Stop output on a line, e.g. for ^S/^Q or output flush.
--- 585,640 ----
  	/*
  	 * If it's currently active, or delaying, no need to do anything.
  	 */
! 	if	(tp->t_state&(TS_TIMEOUT|TS_BUSY|TS_TTSTOP))
  		goto out;
  	/*
  	 * If there are sleepers, and output has drained below low
  	 * water mark, wake up the sleepers..
  	 */
! 	ttyowake(tp);
! 
  	/*
  	 * Now restart transmission unless the output queue is
  	 * empty.
  	 */
! 	if	(tp->t_outq.c_cc == 0)
  		goto out;
! 	addr->dhvcsrl = DHV_SELECT(unit) | DHV_IE;
! /*
!  * If CTS is off and we're doing hardware flow control then mark the output
!  * as stopped and do not transmit anything.
! */
! 	if	((addr->dhvstat & DHV_ST_CTS) == 0 && (tp->t_flags & RTSCTS))
! 		{
! 		tp->t_state |= TS_TTSTOP;
! 		goto out;
  		}
! /*
!  * This is where any per character delay handling for special characters
!  * would go if ever implemented again.  The call to ndqb would be replaced
!  * with a scan for special characters and then the appropriate sleep/wakeup
!  * done.
! */
! 	nch = ndqb(&tp->t_outq, 0);
  	/*
  	 * If characters to transmit, restart transmission.
  	 */
! 	if	(nch)
! 		{
  		car = cpaddr(tp->t_outq.c_cf);
  		addr->dhvcsrl = DHV_SELECT(unit) | DHV_IE;
  		addr->dhvlcr &= ~DHV_LC_TXABORT;
  		addr->dhvbcr = nch;
  		addr->dhvbar1 = loint(car);
! 		if	(ubmap)
  			addr->dhvbar2 = (hiint(car) & DHV_BA2_XBA) | DHV_BA2_DMAGO;
  		else
  			addr->dhvbar2 = (hiint(car) & 037) | DHV_BA2_DMAGO;
  		tp->t_state |= TS_BUSY;
! 		}
  out:
  	splx(s);
! 	}
  
  /*
   * Stop output on a line, e.g. for ^S/^Q or output flush.
***************
*** 646,652 ****
  /*ARGSUSED*/
  dhvstop(tp, flag)
  	register struct tty *tp;
! {
  	register struct dhvdevice *addr;
  	register int unit, s;
  
--- 642,648 ----
  /*ARGSUSED*/
  dhvstop(tp, flag)
  	register struct tty *tp;
! 	{
  	register struct dhvdevice *addr;
  	register int unit, s;
  
***************
*** 655,661 ****
  	 * Block input/output interrupts while messing with state.
  	 */
  	s = spltty();
! 	if (tp->t_state & TS_BUSY) {
  		/*
  		 * Device is transmitting; stop output
  		 * by selecting the line and setting the
--- 651,658 ----
  	 * Block input/output interrupts while messing with state.
  	 */
  	s = spltty();
! 	if	(tp->t_state & TS_BUSY)
! 		{
  		/*
  		 * Device is transmitting; stop output
  		 * by selecting the line and setting the
***************
*** 670,680 ****
  		addr->dhvlcr |= DHV_LC_TXABORT;
  		delay(25L); /* see the dhv manual, sec 3.3.6 */
  		addr->dhvlcr2 |= DHV_LC2_TXEN;
! 		if ((tp->t_state&TS_TTSTOP)==0)
  			tp->t_state |= TS_FLUSH;
! 	}
  	(void) splx(s);
! }
  
  /*
   * DHV11 modem control
--- 667,677 ----
  		addr->dhvlcr |= DHV_LC_TXABORT;
  		delay(25L); /* see the dhv manual, sec 3.3.6 */
  		addr->dhvlcr2 |= DHV_LC2_TXEN;
! 		if	((tp->t_state&TS_TTSTOP)==0)
  			tp->t_state |= TS_FLUSH;
! 		}
  	(void) splx(s);
! 	}
  
  /*
   * DHV11 modem control
***************
*** 684,690 ****
  	dev_t dev;
  	long bits;
  	int how;
! {
  	register struct dhvdevice *dhvaddr;
  	register int unit;
  	register struct tty *tp;
--- 681,687 ----
  	dev_t dev;
  	long bits;
  	int how;
! 	{
  	register struct dhvdevice *dhvaddr;
  	register int unit;
  	register struct tty *tp;
***************
*** 701,729 ****
  	 * with lcr register (read write, bits 0..15).
  	 */
  	mbits = (u_short)dhvaddr->dhvlcr | ((long)dhvaddr->dhvstat << 16);
! 	switch (how) {
! 
! 	case DMSET:
! 		mbits = (mbits & 0xff0000L) | bits;
! 		break;
! 
! 	case DMBIS:
! 		mbits |= bits;
! 		break;
! 
! 	case DMBIC:
! 		mbits &= ~bits;
! 		break;
! 
! 	case DMGET:
! 		(void) splx(s);
! 		return(mbits);
! 	}
  	dhvaddr->dhvlcr = (mbits & 0xffff) | DHV_LC_RXEN;
! 	if ( dhv_hwxon[unit] )
! 	    dhvaddr->dhvlcr |= DHV_LC_OAUTOF;
  	dhvaddr->dhvlcr2 = DHV_LC2_TXEN;
  	(void) splx(s);
  	return(mbits);
! }
  #endif
--- 698,723 ----
  	 * with lcr register (read write, bits 0..15).
  	 */
  	mbits = (u_short)dhvaddr->dhvlcr | ((long)dhvaddr->dhvstat << 16);
! 	switch	(how)
! 		{
! 		case	DMSET:
! 			mbits = (mbits & 0xff0000L) | bits;
! 			break;
! 		case	DMBIS:
! 			mbits |= bits;
! 			break;
! 		case	DMBIC:
! 			mbits &= ~bits;
! 			break;
! 		case	DMGET:
! 			(void) splx(s);
! 			return(mbits);
! 		}
  	dhvaddr->dhvlcr = (mbits & 0xffff) | DHV_LC_RXEN;
! 	if	(dhv_hwxon[unit])
! 		dhvaddr->dhvlcr |= DHV_LC_OAUTOF;
  	dhvaddr->dhvlcr2 = DHV_LC2_TXEN;
  	(void) splx(s);
  	return(mbits);
! 	}
  #endif
*** /usr/src/sys/pdpuba/dhvreg.h.old	Thu Sep  1 14:14:05 1988
--- /usr/src/sys/pdpuba/dhvreg.h	Thu May  1 23:18:35 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)dhvreg.h	1.1 (2.10BSD Berkeley) 12/1/86
   */
  
  /* 
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)dhvreg.h	1.2 (2.11BSD) 1997/5/1
   */
  
  /* 
***************
*** 91,97 ****
  #define	DHV_ST_DSR	0x80		/* data set ready */
  #define	DHV_ST_RI	0x20		/* ring indicator */
  #define	DHV_ST_DCD	0x10		/* carrier detect */
! #define	DHV_ST_CTS	0x04		/* clear to send */
  #define	DHV_ST_DHU	0x01		/* always one on a dhu, zero on dhv */
  
  /* Bits in dhvlcr */
--- 91,97 ----
  #define	DHV_ST_DSR	0x80		/* data set ready */
  #define	DHV_ST_RI	0x20		/* ring indicator */
  #define	DHV_ST_DCD	0x10		/* carrier detect */
! #define	DHV_ST_CTS	0x08		/* clear to send */
  #define	DHV_ST_DHU	0x01		/* always one on a dhu, zero on dhv */
  
  /* Bits in dhvlcr */
***************
*** 127,140 ****
  #define	DHV_DTR	DHV_LC_DTR
  #define DHV_BRK	DHV_LC_BREAK
  #define DHV_LE	DHV_LC_MODEM
- 
- /* bits in dm lsr, copied from dmreg.h */
- #define	DML_DSR		0000400		/* data set ready, not a real DM bit */
- #define	DML_RNG		0000200		/* ring */
- #define	DML_CAR		0000100		/* carrier detect */
- #define	DML_CTS		0000040		/* clear to send */
- #define	DML_SR		0000020		/* secondary receive */
- #define	DML_ST		0000010		/* secondary transmit */
- #define	DML_RTS		0000004		/* request to send */
- #define	DML_DTR		0000002		/* data terminal ready */
- #define	DML_LE		0000001		/* line enable */
--- 127,129 ----
*** /usr/src/sys/sys/tty.c.old	Thu Dec  8 22:44:34 1994
--- /usr/src/sys/sys/tty.c	Sun May  4 21:10:15 1997
***************
*** 3,9 ****
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)tty.c	1.4 (2.11BSD GTE) 12/8/94
   */
  
  #include "param.h"
--- 3,9 ----
   * All rights reserved.  The Berkeley software License Agreement
   * specifies the terms and conditions for redistribution.
   *
!  *	@(#)tty.c	1.5 (2.11BSD GTE) 1997/5/4
   */
  
  #include "param.h"
***************
*** 18,25 ****
--- 18,46 ----
  #include "kernel.h"
  #include "systm.h"
  #include "inode.h"
+ #include "syslog.h"
  
  /*
+  * These were moved here from tty.h so that they could be easily modified
+  * and/or patched instead of recompiling the kernel.  There is only 1 other
+  * place which references these - see tty_pty.c
+  *
+  * The block and unblock numbers may look low but certain devices (the DHV-11
+  * for example) have poor silo handling and at high data rates (19200) the
+  * raw queue overflows even though we've stopped the sending device.  At 192
+  * characters for the 'block' point c-kermit would regularily see dropped data
+  * during interactive mode at 19200.
+  *
+  * It would be nice to have a larger than 8kb clist area and raise these limits
+  * but that would require 2 mapping registers and/or a rewrite of the entire
+  * clist handling.
+ */
+ 
+ 	int	TTYHOG = 255;
+ 	int	TTYBLOCK=128;
+ 	int	TTYUNBLOCK=64;
+ 
+ /*
   * Table giving parity for characters and indicating
   * character classes to tty driver.  In particular,
   * if the low 6 bits are 0, then the character needs
***************
*** 79,84 ****
--- 100,113 ----
  	CBRK,	CSUSP,	CDSUSP, CRPRNT, CFLUSH, CWERASE,CLNEXT
  };
  
+ #define	SET(t,f)	(t) |= (f)
+ #define	CLR(t,f)	(t) &= ~(f)
+ #define	ISSET(t,f)	((t) & (f))
+ 
+ extern	char	*nextc();
+ extern	int	nldisp;
+ extern	int	wakeup();
+ 
  ttychars(tp)
  	struct tty *tp;
  {
***************
*** 87,92 ****
--- 116,146 ----
  }
  
  /*
+  * Wakeup processes waiting on output flow control (TS_ASLEEP).  Normally
+  * called from driver start routine (dhvstart, etc) after a transmit done
+  * interrupt.  If t_outq.c_cc <= t_lowat then do the wakeup.
+ */
+ ttyowake(tp)
+ 	register struct tty *tp;
+ 	{
+ 
+ 	if	(tp->t_outq.c_cc <= TTLOWAT(tp))
+ 		{
+ 		if	(ISSET(tp->t_state,TS_ASLEEP))
+ 			{
+ 			CLR(tp->t_state,TS_ASLEEP);
+ 			wakeup((caddr_t)&tp->t_outq);
+ 			}
+ 		if	(tp->t_wsel)
+ 			{
+ 			selwakeup(tp->t_wsel, tp->t_state & TS_WCOLL);
+ 			tp->t_wsel = 0;
+ 			CLR(tp->t_state,TS_WCOLL);
+ 			}
+ 		}
+ 	}
+ 
+ /*
   * Wait for output to drain, then flush input waiting.
   */
  ttywflush(tp)
***************
*** 105,112 ****
--- 159,174 ----
  	while ((tp->t_outq.c_cc || tp->t_state&TS_BUSY) &&
  	    tp->t_state&TS_CARR_ON && tp->t_oproc) {
  		(*tp->t_oproc)(tp);
+ /*
+  * If the output routine drains the queue and the device is no longer busy
+  * then don't wait for something that's already happened.
+ */
+ 		if	(tp->t_outq.c_cc == 0 && !ISSET(tp->t_state,TS_BUSY))
+ 			break;
  		tp->t_state |= TS_ASLEEP;
  		sleep((caddr_t)&tp->t_outq, TTOPRI);
+ 		splx(s);	/* drop priority, give interrupts a chance */
+ 		s = spltty();
  	}
  	splx(s);
  }
***************
*** 117,177 ****
  ttyflush(tp, rw)
  	register struct tty *tp;
  {
! 	register s;
  
  	s = spltty();
  	if (rw & FREAD) {
  		while (getc(&tp->t_canq) >= 0)
  			;
! 		wakeup((caddr_t)&tp->t_rawq);
  	}
  	if (rw & FWRITE) {
- 		wakeup((caddr_t)&tp->t_outq);
  		tp->t_state &= ~TS_TTSTOP;
  		(*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
  		while (getc(&tp->t_outq) >= 0)
  			;
  	}
! 	if (rw & FREAD) {
! 		while (getc(&tp->t_rawq) >= 0)
! 			;
! 		tp->t_rocount = 0;
! 		tp->t_rocol = 0;
! 		tp->t_state &= ~TS_LOCAL;
! 	}
  	splx(s);
  }
  
  /*
   * Send stop character on input overflow.
   */
  ttyblock(tp)
  	register struct tty *tp;
! {
! 	register x;
  
! 	x = tp->t_rawq.c_cc + tp->t_canq.c_cc;
! 	if (tp->t_rawq.c_cc > TTYHOG) {
! 		ttyflush(tp, FREAD|FWRITE);
! 		tp->t_state &= ~TS_TBLOCK;
! 	}
  	/*
  	 * Block further input iff:
  	 * Current input > threshold AND input is available to user program
  	 */
! 	if (x >= TTYHOG/2 && 
! 	    ((tp->t_flags & (RAW|CBREAK)) || (tp->t_canq.c_cc > 0)) &&
! 	    (tp->t_state&TS_TBLOCK) == 0) {
! 		if (putc(tp->t_stopc, &tp->t_outq)==0) {
! 			tp->t_state |= TS_TBLOCK;
  			ttstart(tp);
  		}
  	}
- }
  
  /*
!  * Restart typewriter output following a delay
!  * timeout.
   * The name of the routine is passed to the timeout
   * subroutine and it is called during a clock interrupt.
   */
--- 179,275 ----
  ttyflush(tp, rw)
  	register struct tty *tp;
  {
! 	register int s;
  
  	s = spltty();
  	if (rw & FREAD) {
  		while (getc(&tp->t_canq) >= 0)
  			;
! 		while (getc(&tp->t_rawq) >= 0)
! 			;
! 		tp->t_rocount = 0;
! 		tp->t_rocol = 0;
! 		tp->t_state &= ~TS_LOCAL;
! 		ttwakeup(tp);
  	}
  	if (rw & FWRITE) {
  		tp->t_state &= ~TS_TTSTOP;
  		(*cdevsw[major(tp->t_dev)].d_stop)(tp, rw);
+ 		wakeup((caddr_t)&tp->t_outq);
  		while (getc(&tp->t_outq) >= 0)
  			;
+ 		selwakeup(&tp->t_wsel, tp->t_state & TS_WCOLL);
+ 		CLR(tp->t_state, TS_WCOLL);
+ 		tp->t_wsel = 0;
  	}
! 	if (rw & FREAD && ISSET(tp->t_state,TS_TBLOCK))
! 		ttyunblock(tp);
  	splx(s);
  }
  
+ static	int	rts = TIOCM_RTS;
+ 
  /*
   * Send stop character on input overflow.
   */
  ttyblock(tp)
  	register struct tty *tp;
! 	{
! 	register int total;
  
! 	total = tp->t_rawq.c_cc + tp->t_canq.c_cc;
  	/*
  	 * Block further input iff:
  	 * Current input > threshold AND input is available to user program
  	 */
! 	if	(total >= TTYBLOCK && 
! 		 ((tp->t_flags & (RAW|CBREAK)) || (tp->t_canq.c_cc > 0)) &&
! 		 (tp->t_state&TS_TBLOCK) == 0)
! 		{
! /*
!  * TANDEM is the same as IXOFF for all intents and purposes.  Since we could
!  * get called for either software or hardware flow control we need to check
!  * the IXOFF bit.
! */
! 		if	(ISSET(tp->t_flags,TANDEM) && 
! 			 tp->t_stopc != _POSIX_VDISABLE && 
! 			 putc(tp->t_stopc, &tp->t_outq) == 0)
! 			{
! 			SET(tp->t_state, TS_TBLOCK);
  			ttstart(tp);
+ 			}
+ /*
+  * If queue is full, drop RTS to tell modem to stop sending us stuff
+ */
+ 		if	(ISSET(tp->t_flags, RTSCTS) &&
+ 			 (*cdevsw[major(tp->t_dev)].d_ioctl)(tp->t_dev,TIOCMBIC, &rts, 0) == 0)
+ 			{
+ 			SET(tp->t_state, TS_TBLOCK);
+ 			}
  		}
  	}
  
+ ttyunblock(tp)
+ 	register struct tty *tp;
+ 	{
+ 	register int s = spltty();
+ 
+ 	if	(ISSET(tp->t_flags,TANDEM) &&
+ 		 tp->t_startc != _POSIX_VDISABLE && 
+ 		 putc(tp->t_startc, &tp->t_outq) == 0)
+ 		{
+ 		CLR(tp->t_state,TS_TBLOCK);
+ 		ttstart(tp);
+ 		}
+ 	if	(ISSET(tp->t_flags, RTSCTS) && 
+ 		 (*cdevsw[major(tp->t_dev)].d_ioctl)(tp->t_dev,TIOCMBIS,&rts,0) == 0)
+ 		{
+ 		CLR(tp->t_state, TS_TBLOCK);
+ 		}
+ 	}
+ 
  /*
!  * Restart typewriter output following a delay timeout.
   * The name of the routine is passed to the timeout
   * subroutine and it is called during a clock interrupt.
   */
***************
*** 179,188 ****
  	register struct tty *tp;
  {
  
- #ifdef	DIAGNOSTIC
- 	if (tp == 0)
- 		panic("ttrstrt");
- #endif
  	tp->t_state &= ~TS_TIMEOUT;
  	ttstart(tp);
  }
--- 277,282 ----
***************
*** 192,209 ****
   * after some characters have been put on the output queue,
   * from the interrupt routine to transmit the next
   * character, and after a timeout has finished.
   */
  ttstart(tp)
  	register struct tty *tp;
! {
! 	register s;
  
! 	s = spltty();
! 	if ((tp->t_state & (TS_TIMEOUT|TS_TTSTOP|TS_BUSY)) == 0 &&
! 	    tp->t_oproc)		/* kludge for pty */
  		(*tp->t_oproc)(tp);
! 	splx(s);
! }
  
  /*
   * Common code for tty ioctls.
--- 286,301 ----
   * after some characters have been put on the output queue,
   * from the interrupt routine to transmit the next
   * character, and after a timeout has finished.
+  *
+  * The spl calls were removed because the priority should already be spltty.
   */
  ttstart(tp)
  	register struct tty *tp;
! 	{
  
! 	if	(tp->t_oproc)		/* kludge for pty */
  		(*tp->t_oproc)(tp);
! 	}
  
  /*
   * Common code for tty ioctls.
***************
*** 216,222 ****
  	int flag;
  {
  	int dev = tp->t_dev;
- 	extern int nldisp;
  	int s;
  	long newflags;
  
--- 308,313 ----
***************
*** 483,491 ****
  }
  
  ttnread(tp)
! 	struct tty *tp;
  {
! 	int nread = 0;
  
  	if (tp->t_flags & PENDIN)
  		ttypend(tp);
--- 574,582 ----
  }
  
  ttnread(tp)
! 	register struct tty *tp;
  {
! 	register int nread = 0;
  
  	if (tp->t_flags & PENDIN)
  		ttypend(tp);
***************
*** 495,511 ****
  	return (nread);
  }
  
  ttselect(dev, rw)
! 	dev_t dev;
  	int rw;
! {
! #ifdef pdp11
! 	register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)&0177];
! #else
! 	register struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)];
! #endif
  	int nread;
! 	int s = spltty();
  
  	switch (rw) {
  
--- 586,614 ----
  	return (nread);
  }
  
+ /*
+  * XXX - this cleans up the minor device number by stripping off the 
+  * softcarrier bit.  Drives which use more bits of the minor device
+  * MUST call their own select routine.  See dhv.c for an example.
+  *
+  * This routine will go away when all the drivers have been updated/converted
+ */
+ 
  ttselect(dev, rw)
! 	register dev_t dev;
  	int rw;
! 	{
! 	struct tty *tp = &cdevsw[major(dev)].d_ttys[minor(dev)&0177];
! 
! 	return(ttyselect(tp,rw));
! 	}
! 
! ttyselect(tp,rw)
! 	register struct tty *tp;
! 	int	rw;
! 	{
  	int nread;
! 	register int s = spltty();
  
  	switch (rw) {
  
***************
*** 570,575 ****
--- 673,679 ----
   */
  ttylclose(tp, flag)
  	register struct tty *tp;
+ 	int flag;
  {
  
  /*
***************
*** 604,609 ****
--- 708,714 ----
   */
  ttymodem(tp, flag)
  	register struct tty *tp;
+ 	int flag;
  {
  
  	if ((tp->t_state&TS_WOPEN) == 0 && (tp->t_flags & MDMBUF)) {
***************
*** 664,670 ****
  	register struct tty *tp;
  {
  	struct clist tq;
! 	register c;
  
  	tp->t_flags &= ~PENDIN;
  	tp->t_state |= TS_TYPEN;
--- 769,775 ----
  	register struct tty *tp;
  {
  	struct clist tq;
! 	register int c;
  
  	tp->t_flags &= ~PENDIN;
  	tp->t_state |= TS_TYPEN;
***************
*** 684,690 ****
   * appropriate tty structure.
   */
  ttyinput(c, tp)
! 	register c;
  	register struct tty *tp;
  {
  	long t_flags = tp->t_flags;
--- 789,795 ----
   * appropriate tty structure.
   */
  ttyinput(c, tp)
! 	register int c;
  	register struct tty *tp;
  {
  	long t_flags = tp->t_flags;
***************
*** 703,709 ****
  	/*
  	 * In tandem mode, check high water mark.
  	 */
! 	if (t_flags&TANDEM)
  		ttyblock(tp);
  
  	if (t_flags&RAW) {
--- 808,814 ----
  	/*
  	 * In tandem mode, check high water mark.
  	 */
! 	if	(t_flags & (TANDEM|RTSCTS))
  		ttyblock(tp);
  
  	if (t_flags&RAW) {
***************
*** 714,720 ****
  		if (tp->t_rawq.c_cc > TTYHOG) 
  			ttyflush(tp, FREAD|FWRITE);
  		else {
! 			if (putc(c, &tp->t_rawq) >= 0)
  				ttwakeup(tp);
  			ttyecho(c, tp);
  		}
--- 819,825 ----
  		if (tp->t_rawq.c_cc > TTYHOG) 
  			ttyflush(tp, FREAD|FWRITE);
  		else {
! 			if (putc(c, &tp->t_rawq) == 0)
  				ttwakeup(tp);
  			ttyecho(c, tp);
  		}
***************
*** 727,734 ****
  	 */
  	if ((tp->t_state&TS_TYPEN) == 0 && (t_flags&PASS8) == 0)
  		c &= 0177;
  	/*
! 	 * Check for literal nexting very first
  	 */
  	if (tp->t_state&TS_LNCH) {
  		c |= 0200;
--- 832,853 ----
  	 */
  	if ((tp->t_state&TS_TYPEN) == 0 && (t_flags&PASS8) == 0)
  		c &= 0177;
+ 
  	/*
! 	 * Check for literal nexting very first.  This is the _ONLY_ place
! 	 * left which ORs in 0200.  Handling literal nexting this way is
! 	 * what keeps the tty subsystem from being 8 bit clean.  The fix is
! 	 * horrendous though and is put off for now.  And to think that ALL
! 	 * of this is made necessary by ttyrubout() - it's the only place that
! 	 * actually _checks_ the 0200 bit and only for newline and tab chars
! 	 * at that!
! 	 *
! 	 * If we had 9 bit bytes life would be a lot simpler ;)
! 	 *
! 	 * The basic idea is to flag the character as "special" and also
! 	 * modify it so that the character does not match any of the special
! 	 * editing or control characters.  We could just as simply jump directly
! 	 * to the test for 'cbreak' below.
  	 */
  	if (tp->t_state&TS_LNCH) {
  		c |= 0200;
***************
*** 743,755 ****
  	 * it after a case match, or similar.
  	 */
  	if (tp->t_line == NTTYDISC) {
! 		if (c == tp->t_lnextc) {
  			if (t_flags&ECHO)
  				ttyout("^\b", tp);
  			tp->t_state |= TS_LNCH;
  			goto endcase;
  		}
! 		if (c == tp->t_flushc) {
  			if (t_flags&FLUSHO)
  				tp->t_flags &= ~FLUSHO;
  			else {
--- 862,874 ----
  	 * it after a case match, or similar.
  	 */
  	if (tp->t_line == NTTYDISC) {
! 		if (CCEQ(tp->t_lnextc,c)) {
  			if (t_flags&ECHO)
  				ttyout("^\b", tp);
  			tp->t_state |= TS_LNCH;
  			goto endcase;
  		}
! 		if (CCEQ(tp->t_flushc,c)) {
  			if (t_flags&FLUSHO)
  				tp->t_flags &= ~FLUSHO;
  			else {
***************
*** 761,767 ****
  			}
  			goto startoutput;
  		}
! 		if (c == tp->t_suspc) {
  			if ((t_flags&NOFLSH) == 0)
  				ttyflush(tp, FREAD);
  			ttyecho(c, tp);
--- 880,886 ----
  			}
  			goto startoutput;
  		}
! 		if (CCEQ(tp->t_suspc,c)) {
  			if ((t_flags&NOFLSH) == 0)
  				ttyflush(tp, FREAD);
  			ttyecho(c, tp);
***************
*** 773,799 ****
  	/*
  	 * Handle start/stop characters.
  	 */
! 	if (c == tp->t_stopc) {
  		if ((tp->t_state&TS_TTSTOP) == 0) {
  			tp->t_state |= TS_TTSTOP;
  			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
  			return;
  		}
! 		if (c != tp->t_startc)
  			return;
  		goto endcase;
  	}
! 	if (c == tp->t_startc)
  		goto restartoutput;
  
  	/*
  	 * Look for interrupt/quit chars.
  	 */
! 	if (c == tp->t_intrc || c == tp->t_quitc) {
  		if ((t_flags&NOFLSH) == 0)
  			ttyflush(tp, FREAD|FWRITE);
  		ttyecho(c, tp);
! 		gsignal(tp->t_pgrp, c == tp->t_intrc ? SIGINT : SIGQUIT);
  		goto endcase;
  	}
  
--- 892,918 ----
  	/*
  	 * Handle start/stop characters.
  	 */
! 	if (CCEQ(tp->t_stopc,c)) {
  		if ((tp->t_state&TS_TTSTOP) == 0) {
  			tp->t_state |= TS_TTSTOP;
  			(*cdevsw[major(tp->t_dev)].d_stop)(tp, 0);
  			return;
  		}
! 		if (CCEQ(tp->t_startc,c))
  			return;
  		goto endcase;
  	}
! 	if (CCEQ(tp->t_startc,c))
  		goto restartoutput;
  
  	/*
  	 * Look for interrupt/quit chars.
  	 */
! 	if (CCEQ(tp->t_intrc,c) || CCEQ(tp->t_quitc,c)) {
  		if ((t_flags&NOFLSH) == 0)
  			ttyflush(tp, FREAD|FWRITE);
  		ttyecho(c, tp);
! 		gsignal(tp->t_pgrp, CCEQ(tp->t_intrc,c) ? SIGINT : SIGQUIT);
  		goto endcase;
  	}
  
***************
*** 806,812 ****
  			if (tp->t_outq.c_cc < TTHIWAT(tp) &&
  			    tp->t_line == NTTYDISC)
  				(void) ttyoutput(CTRL(g), tp);
! 		} else if (putc(c, &tp->t_rawq) >= 0) {
  			ttwakeup(tp);
  			ttyecho(c, tp);
  		}
--- 925,931 ----
  			if (tp->t_outq.c_cc < TTHIWAT(tp) &&
  			    tp->t_line == NTTYDISC)
  				(void) ttyoutput(CTRL(g), tp);
! 		} else if (putc(c, &tp->t_rawq) == 0) {
  			ttwakeup(tp);
  			ttyecho(c, tp);
  		}
***************
*** 817,833 ****
  	 * From here on down cooked mode character
  	 * processing takes place.
  	 */
! 	if ((tp->t_state&TS_QUOT) &&
! 	    (c == tp->t_erase || c == tp->t_kill)) {
! 		ttyrub(unputc(&tp->t_rawq), tp);
! 		c |= 0200;
! 	}
! 	if (c == tp->t_erase) {
  		if (tp->t_rawq.c_cc)
  			ttyrub(unputc(&tp->t_rawq), tp);
  		goto endcase;
  	}
! 	if (c == tp->t_kill) {
  		if (t_flags&CRTKIL &&
  		    tp->t_rawq.c_cc == tp->t_rocount) {
  			while (tp->t_rawq.c_cc)
--- 936,947 ----
  	 * From here on down cooked mode character
  	 * processing takes place.
  	 */
! 	if (CCEQ(tp->t_erase,c)) {
  		if (tp->t_rawq.c_cc)
  			ttyrub(unputc(&tp->t_rawq), tp);
  		goto endcase;
  	}
! 	if (CCEQ(tp->t_kill,c)) {
  		if (t_flags&CRTKIL &&
  		    tp->t_rawq.c_cc == tp->t_rocount) {
  			while (tp->t_rawq.c_cc)
***************
*** 848,854 ****
  	 * check word erase/reprint line.
  	 */
  	if (tp->t_line == NTTYDISC) {
! 		if (c == tp->t_werasc) {
  			if (tp->t_rawq.c_cc == 0)
  				goto endcase;
  			do {
--- 962,968 ----
  	 * check word erase/reprint line.
  	 */
  	if (tp->t_line == NTTYDISC) {
! 		if (CCEQ(tp->t_werasc,c)) {
  			if (tp->t_rawq.c_cc == 0)
  				goto endcase;
  			do {
***************
*** 868,874 ****
  			(void) putc(c, &tp->t_rawq);
  			goto endcase;
  		}
! 		if (c == tp->t_rprntc) {
  			ttyretype(tp);
  			goto endcase;
  		}
--- 982,988 ----
  			(void) putc(c, &tp->t_rawq);
  			goto endcase;
  		}
! 		if (CCEQ(tp->t_rprntc,c)) {
  			ttyretype(tp);
  			goto endcase;
  		}
***************
*** 887,893 ****
  	 * Put data char in q for user and
  	 * wakeup on seeing a line delimiter.
  	 */
! 	if (putc(c, &tp->t_rawq) >= 0) {
  		if (ttbreakc(c, tp)) {
  			tp->t_rocount = 0;
  			catq(&tp->t_rawq, &tp->t_canq);
--- 1001,1007 ----
  	 * Put data char in q for user and
  	 * wakeup on seeing a line delimiter.
  	 */
! 	if (putc(c, &tp->t_rawq) == 0) {
  		if (ttbreakc(c, tp)) {
  			tp->t_rocount = 0;
  			catq(&tp->t_rawq, &tp->t_canq);
***************
*** 894,902 ****
  			ttwakeup(tp);
  		} else if (tp->t_rocount++ == 0)
  			tp->t_rocol = tp->t_col;
- 		tp->t_state &= ~TS_QUOT;
- 		if (c == '\\')
- 			tp->t_state |= TS_QUOT;
  		if (tp->t_state&TS_ERASE) {
  			tp->t_state &= ~TS_ERASE;
  			(void) ttyoutput('/', tp);
--- 1008,1013 ----
***************
*** 903,909 ****
  		}
  		i = tp->t_col;
  		ttyecho(c, tp);
! 		if (c == tp->t_eofc && t_flags&ECHO) {
  			i = MIN(2, tp->t_col - i);
  			while (i > 0) {
  				(void) ttyoutput('\b', tp);
--- 1014,1020 ----
  		}
  		i = tp->t_col;
  		ttyecho(c, tp);
! 		if (CCEQ(tp->t_eofc,c) && t_flags&ECHO) {
  			i = MIN(2, tp->t_col - i);
  			while (i > 0) {
  				(void) ttyoutput('\b', tp);
***************
*** 933,969 ****
   * and from interrupt level for echoing.
   * The arguments are the character and the tty structure.
   * Returns < 0 if putc succeeds, otherwise returns char to resend
-  * Must be recursive.
   */
  ttyoutput(c, tp)
! 	register c;
  	register struct tty *tp;
  {
! 	register char *colp;
! 	register ctype;
  
  	if (tp->t_flags & (RAW|LITOUT)) {
  		if (tp->t_flags&FLUSHO)
  			return (-1);
  		if (putc(c, &tp->t_outq))
! 			return (c);
  #ifdef UCB_METER
  		tk_nout++;
  #endif
! 		return (-1);
  	}
  
  	/*
  	 * Ignore EOT in normal mode to avoid
  	 * hanging up certain terminals.
  	 */
- 	c &= 0177;
  	if (c == CEOT && (tp->t_flags&CBREAK) == 0)
! 		return (-1);
  	/*
  	 * Turn tabs to spaces as required
  	 */
! 	if (c == '\t' && (tp->t_flags&TBDELAY) == XTABS) {
  		register int s;
  
  		c = 8 - (tp->t_col&7);
--- 1044,1080 ----
   * and from interrupt level for echoing.
   * The arguments are the character and the tty structure.
   * Returns < 0 if putc succeeds, otherwise returns char to resend
   */
  ttyoutput(c, tp)
! 	register int c;
  	register struct tty *tp;
  {
! 	register int col;
  
  	if (tp->t_flags & (RAW|LITOUT)) {
  		if (tp->t_flags&FLUSHO)
  			return (-1);
  		if (putc(c, &tp->t_outq))
! 			return(c);
  #ifdef UCB_METER
  		tk_nout++;
  #endif
! 		return(-1);
  	}
  
+ 	c &= 0177;
+ #ifdef	whybother
  	/*
  	 * Ignore EOT in normal mode to avoid
  	 * hanging up certain terminals.
  	 */
  	if (c == CEOT && (tp->t_flags&CBREAK) == 0)
! 		return(-1);
! #endif
  	/*
  	 * Turn tabs to spaces as required
  	 */
! 	if (c == '\t' && (tp->t_flags&XTABS)) {
  		register int s;
  
  		c = 8 - (tp->t_col&7);
***************
*** 985,1075 ****
  	 * turn <nl> to <cr><lf> if desired.
  	 */
  	if (c == '\n' && tp->t_flags&CRMOD)
! 		if (ttyoutput('\r', tp) >= 0)
! 			return (c);
  	if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq))
  		return (c);
- 	/*
- 	 * Calculate delays.
- 	 * The numbers here represent clock ticks
- 	 * and are not necessarily optimal for all terminals.
- 	 * The delays are indicated by characters above 0200.
- 	 * In raw mode there are no delays and the
- 	 * transmission path is 8 bits wide.
- 	 *
- 	 * SHOULD JUST ALLOW USER TO SPECIFY DELAYS
- 	 */
- 	colp = &tp->t_col;
- 	ctype = partab[c];
- 	c = 0;
- 	switch (ctype&077) {
  
! 	case ORDINARY:
! 		(*colp)++;
  
  	case CONTROL:
  		break;
- 
  	case BACKSPACE:
! 		if (*colp)
! 			(*colp)--;
  		break;
- 
- 	/*
- 	 * This macro is close enough to the correct thing;
- 	 * it should be replaced by real user settable delays
- 	 * in any event...
- 	 */
- #define	mstohz(ms)	(((ms) * hz) >> 10)
  	case NEWLINE:
! 		ctype = (tp->t_flags >> 8) & 03L;
! 		if (ctype == 1) { /* tty 37 */
! 			if (*colp > 0) {
! 				c = (((unsigned)*colp) >> 4) + 3;
! 				if ((unsigned)c > 6)
! 					c = 6;
! 			}
! 		} else if (ctype == 2) /* vt05 */
! 			c = mstohz(100);
! 		*colp = 0;
  		break;
- 
  	case TAB:
! 		ctype = (tp->t_flags >> 10) & 03L;
! 		if (ctype == 1) { /* tty 37 */
! 			c = 1 - (*colp | ~07);
! 			if (c < 5)
! 				c = 0;
! 		}
! 		*colp |= 07;
! 		(*colp)++;
  		break;
- 
- 	case VTAB:
- 		if (tp->t_flags&VTDELAY) /* tty 37 */
- 			c = 0177;
- 		break;
- 
- 	case RETURN:
- 		ctype = (tp->t_flags >> 12) & 03L;
- 		if (ctype == 1) /* tn 300 */
- 			c = mstohz(83);
- 		else if (ctype == 2) /* ti 700 */
- 			c = mstohz(166);
- 		else if (ctype == 3) { /* concept 100 */
- 			int i;
- 
- 			if ((i = *colp) >= 0)
- 				for (; i < 9; i++)
- 					(void) putc(0177, &tp->t_outq);
- 		}
- 		*colp = 0;
  	}
! 	if (c && (tp->t_flags&FLUSHO) == 0)
! 		(void) putc(c|0200, &tp->t_outq);
! 	return (-1);
  }
- #undef mstohz
  
  /*
   * Called from device's read routine after it has
--- 1096,1133 ----
  	 * turn <nl> to <cr><lf> if desired.
  	 */
  	if (c == '\n' && tp->t_flags&CRMOD)
! 		{
! 		if (putc('\r', &tp->t_outq))
! 			return(c);
! #ifdef UCB_METER
! 		tk_nout++;
! #endif
! 		}
  	if ((tp->t_flags&FLUSHO) == 0 && putc(c, &tp->t_outq))
  		return (c);
  
! 	col = tp->t_col;
! 	switch (partab[c]&077) {
  
+ 	case ORDINARY:
+ 		col++;
  	case CONTROL:
  		break;
  	case BACKSPACE:
! 		if (col)
! 			col--;
  		break;
  	case NEWLINE:
! 	case RETURN:
! 		col = 0;
  		break;
  	case TAB:
! 		col = (col | 07) + 1;
  		break;
  	}
! 	tp->t_col = col;
! 	return(-1);
  }
  
  /*
   * Called from device's read routine after it has
***************
*** 1080,1088 ****
  	struct uio *uio;
  {
  	register struct clist *qp;
! 	register c;
  	long t_flags;
! 	int s, first, error = 0;
  
  loop:
  	/*
--- 1138,1146 ----
  	struct uio *uio;
  {
  	register struct clist *qp;
! 	register int c;
  	long t_flags;
! 	int s, first, error = 0, carrier;
  
  loop:
  	/*
***************
*** 1093,1101 ****
  		ttypend(tp);
  	splx(s);
  
- 	if ((tp->t_state&TS_CARR_ON)==0)
- 		return (EIO);
- 
  	/*
  	 * Hang process if it's in the background.
  	 */
--- 1151,1156 ----
***************
*** 1118,1128 ****
  	if (t_flags&RAW) {
  		s = spltty();
  		if (tp->t_rawq.c_cc <= 0) {
! 			if ((tp->t_state&TS_CARR_ON) == 0 ||
! 			    (flag & IO_NDELAY)) {
  				splx(s);
! 				return (EWOULDBLOCK);
! 			}
  			sleep((caddr_t)&tp->t_rawq, TTIPRI);
  			splx(s);
  			goto loop;
--- 1173,1189 ----
  	if (t_flags&RAW) {
  		s = spltty();
  		if (tp->t_rawq.c_cc <= 0) {
! 			carrier = ISSET(tp->t_state, TS_CARR_ON);
! 			if (!carrier && ISSET(tp->t_state, TS_ISOPEN))
! 				{
  				splx(s);
! 				return(0);	/* EOF */
! 				}
! 			if (flag & IO_NDELAY)
! 				{
! 				splx(s);
! 				return(EWOULDBLOCK);
! 				}
  			sleep((caddr_t)&tp->t_rawq, TTIPRI);
  			splx(s);
  			goto loop;
***************
*** 1145,1154 ****
  	 */
  	s = spltty();
  	if (qp->c_cc <= 0) {
! 		if ((tp->t_state&TS_CARR_ON) == 0 || (flag & IO_NDELAY)) {
  			splx(s);
! 			return (EWOULDBLOCK);
! 		}
  		sleep((caddr_t)&tp->t_rawq, TTIPRI);
  		splx(s);
  		goto loop;
--- 1206,1222 ----
  	 */
  	s = spltty();
  	if (qp->c_cc <= 0) {
! 		carrier = ISSET(tp->t_state, TS_CARR_ON);
! 		if (!carrier && ISSET(tp->t_state,TS_ISOPEN))
! 			{
  			splx(s);
! 			return(0);	/* EOF */
! 			}
! 		if (flag & IO_NDELAY)
! 			{
! 			splx(s);
! 			return(EWOULDBLOCK);
! 			}
  		sleep((caddr_t)&tp->t_rawq, TTIPRI);
  		splx(s);
  		goto loop;
***************
*** 1166,1172 ****
  		/*
  		 * Check for delayed suspend character.
  		 */
! 		if (tp->t_line == NTTYDISC && c == tp->t_dsuspc) {
  			gsignal(tp->t_pgrp, SIGTSTP);
  			if (first) {
  				sleep((caddr_t)&lbolt, TTIPRI);
--- 1234,1240 ----
  		/*
  		 * Check for delayed suspend character.
  		 */
! 		if (tp->t_line == NTTYDISC && CCEQ(tp->t_dsuspc,c)) {
  			gsignal(tp->t_pgrp, SIGTSTP);
  			if (first) {
  				sleep((caddr_t)&lbolt, TTIPRI);
***************
*** 1177,1183 ****
  		/*
  		 * Interpret EOF only in cooked mode.
  		 */
! 		if (c == tp->t_eofc && (t_flags&CBREAK) == 0)
  			break;
  		/*
  		 * Give user character.
--- 1245,1251 ----
  		/*
  		 * Interpret EOF only in cooked mode.
  		 */
! 		if (CCEQ(tp->t_eofc,c) && (t_flags&CBREAK) == 0)
  			break;
  		/*
  		 * Give user character.
***************
*** 1201,1214 ****
  	 * Look to unblock output now that (presumably)
  	 * the input queue has gone down.
  	 */
! 	if (tp->t_state&TS_TBLOCK && 
! 	    (tp->t_rawq.c_cc+tp->t_canq.c_cc < TTYHOG/5 ||
! 	    (t_flags&(RAW|CBREAK)) == 0 && tp->t_canq.c_cc == 0))
! 		if (putc(tp->t_startc, &tp->t_outq) == 0) {
! 			tp->t_state &= ~TS_TBLOCK;
! 			ttstart(tp);
! 		}
! 	return (error);
  }
  
  /*
--- 1269,1279 ----
  	 * Look to unblock output now that (presumably)
  	 * the input queue has gone down.
  	 */
! 	s = spltty();
! 	if	(ISSET(tp->t_state,TS_TBLOCK) && tp->t_rawq.c_cc < TTYUNBLOCK)
! 		ttyunblock(tp);
! 	splx(s);
! 	return(error);
  }
  
  /*
***************
*** 1224,1230 ****
  	int wait;
  {
  	int hiwat, s, oldsig;
- 	int	wakeup();
  
  	hiwat = TTHIWAT(tp);
  	s = spltty();
--- 1289,1294 ----
***************
*** 1234,1240 ****
  		ttstart(tp);
  		if (wait == 0 || u.u_procp->p_sig != oldsig) {
  			splx(s);
! 			return (0);
  		}
  		timeout(wakeup, (caddr_t)&tp->t_outq, hz);
  		tp->t_state |= TS_ASLEEP;
--- 1298,1304 ----
  		ttstart(tp);
  		if (wait == 0 || u.u_procp->p_sig != oldsig) {
  			splx(s);
! 			return(0);
  		}
  		timeout(wakeup, (caddr_t)&tp->t_outq, hz);
  		tp->t_state |= TS_ASLEEP;
***************
*** 1241,1247 ****
  		sleep((caddr_t)&tp->t_outq, PZERO - 1);
  	}
  	splx(s);
! 	return (1);
  }
  
  /*
--- 1305,1311 ----
  		sleep((caddr_t)&tp->t_outq, PZERO - 1);
  	}
  	splx(s);
! 	return(1);
  }
  
  /*
***************
*** 1414,1426 ****
   * as cleanly as possible.
   */
  ttyrub(c, tp)
! 	register c;
  	register struct tty *tp;
  {
  	register char *cp;
! 	register int savecol;
  	int s;
- 	char *nextc();
  
  	if ((tp->t_flags&ECHO) == 0)
  		return;
--- 1478,1489 ----
   * as cleanly as possible.
   */
  ttyrub(c, tp)
! 	register int c;
  	register struct tty *tp;
  {
  	register char *cp;
! 	int savecol;
  	int s;
  
  	if ((tp->t_flags&ECHO) == 0)
  		return;
***************
*** 1434,1439 ****
--- 1497,1506 ----
  			ttyretype(tp);
  			return;
  		}
+ /*
+  * Out of the ENTIRE tty subsystem would believe this is the ONLY place
+  * that the "9th" bit (quoted chars) is tested?
+ */
  		if (c == ('\t'|0200) || c == ('\n'|0200))
  			ttyrubo(tp, 2);
  		else switch (partab[c&=0177]&0177) {
***************
*** 1508,1518 ****
   */
  ttyrubo(tp, cnt)
  	register struct tty *tp;
! 	int cnt;
  {
  	register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b";
  
! 	while (--cnt >= 0)
  		ttyout(rubostring, tp);
  }
  
--- 1575,1585 ----
   */
  ttyrubo(tp, cnt)
  	register struct tty *tp;
! 	register int cnt;
  {
  	register char *rubostring = tp->t_flags&CRTERA ? "\b \b" : "\b";
  
! 	while	(--cnt >= 0)
  		ttyout(rubostring, tp);
  }
  
***************
*** 1524,1533 ****
  	register struct tty *tp;
  {
  	register char *cp;
- 	char *nextc();
  	int s;
  
! 	if (tp->t_rprntc != 0377)
  		ttyecho(tp->t_rprntc, tp);
  	(void) ttyoutput('\n', tp);
  	s = spltty();
--- 1591,1599 ----
  	register struct tty *tp;
  {
  	register char *cp;
  	int s;
  
! 	if (tp->t_rprntc != _POSIX_VDISABLE)
  		ttyecho(tp->t_rprntc, tp);
  	(void) ttyoutput('\n', tp);
  	s = spltty();
***************
*** 1560,1568 ****
   * Echo a typed character to the terminal
   */
  ttyecho(c, tp)
! 	register c;
  	register struct tty *tp;
  {
  
  	if ((tp->t_state&TS_CNTTB) == 0)
  		tp->t_flags &= ~FLUSHO;
--- 1626,1635 ----
   * Echo a typed character to the terminal
   */
  ttyecho(c, tp)
! 	register int c;
  	register struct tty *tp;
  {
+ 	register int c7;
  
  	if ((tp->t_state&TS_CNTTB) == 0)
  		tp->t_flags &= ~FLUSHO;
***************
*** 1569,1574 ****
--- 1636,1642 ----
  	if ((tp->t_flags&ECHO) == 0)
  		return;
  	c &= 0377;
+ 
  	if (tp->t_flags&RAW) {
  		(void) ttyoutput(c, tp);
  		return;
***************
*** 1575,1591 ****
  	}
  	if (c == '\r' && tp->t_flags&CRMOD)
  		c = '\n';
  	if (tp->t_flags&CTLECH) {
! 		if ((c&0177) <= 037 && c!='\t' && c!='\n' || (c&0177)==0177) {
  			(void) ttyoutput('^', tp);
! 			c &= 0177;
! 			if (c == 0177)
! 				c = '?';
  			else
! 				c += 'A' - 1;
  		}
  	}
! 	(void) ttyoutput(c&0177, tp);
  }
  
  /*
--- 1643,1659 ----
  	}
  	if (c == '\r' && tp->t_flags&CRMOD)
  		c = '\n';
+ 	c7 = c & 0177;
  	if (tp->t_flags&CTLECH) {
! 		if (c7 <= 037 && c != '\t' && c != '\n' || c7 == 0177) {
  			(void) ttyoutput('^', tp);
! 			if (c7 == 0177)
! 				c7 = '?';
  			else
! 				c7 += 'A' - 1;
  		}
  	}
! 	(void) ttyoutput(c7, tp);
  }
  
  /*
***************
*** 1592,1601 ****
   * Is c a break char for tp?
   */
  ttbreakc(c, tp)
! 	register c;
  	register struct tty *tp;
  {
! 	return (c == '\n' || c == tp->t_eofc || c == tp->t_brkc ||
  		c == '\r' && (tp->t_flags&CRMOD));
  }
  
--- 1660,1669 ----
   * Is c a break char for tp?
   */
  ttbreakc(c, tp)
! 	register int c;
  	register struct tty *tp;
  {
! 	return (c == '\n' || CCEQ(tp->t_eofc,c) || CCEQ(tp->t_brkc,c) ||
  		c == '\r' && (tp->t_flags&CRMOD));
  }
  
***************
*** 1606,1612 ****
  	register char *cp;
  	register struct tty *tp;
  {
! 	register char c;
  
  	while (c = *cp++)
  		(void) ttyoutput(c, tp);
--- 1674,1680 ----
  	register char *cp;
  	register struct tty *tp;
  {
! 	register int c;
  
  	while (c = *cp++)
  		(void) ttyoutput(c, tp);
***************
*** 1613,1619 ****
  }
  
  ttwakeup(tp)
! 	struct tty *tp;
  {
  
  	if (tp->t_rsel) {
--- 1681,1687 ----
  }
  
  ttwakeup(tp)
! 	register struct tty *tp;
  {
  
  	if (tp->t_rsel) {
