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 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<dhvcsr = DHV_SELECT(0) | DHV_IE; dhvact |= (1<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<dhvcsr = DHV_SELECT(0) | DHV_IE; dhvact |= (1<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 to 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 to 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) {