Subject: Re: Hardware handshaking with slip (was Re: network performance)
To: None <Mark_Weaver@brown.edu>
From: Ryutaroh Matsumoto <ryutaroh@fujiyama.iijnet.or.jp>
List: current-users
Date: 07/17/1994 01:25:56
>>>>> On Thu, 14 Jul 1994 23:53:03 -0400, Mark_Weaver@brown.edu said:

Mark> I get the same problem with my 486 box -- it's because hardware
Mark> handshaking isn't working with slip for some reason.  Perhaps it is
Mark> something in the device-independent code.

Mark> I'm giving the "-link2" option to ifconfig, which should enable
Mark> hardware handshaking, although that wasn't documented in any man page
Mark> the last I checked (I sent a pr on it).

Mark> I know it's not a modem problem, because hardware handshaking works on
Mark> this machine with both Linux and FreeBSD.  I can see the "CS" (CTS)
Mark> light go on and off on my USR Courier, but the "SD" (Send) light keeps
Mark> going anyway.  With Linux or FreeBSD, the lights go on and off
Mark> together as they should.

Hello everyone, let me say my guess about hardware handshaking.

comstart() in i386/isa/com.c uses tp->t_state&TS_TTSTOP to know
whether the serial port can receive data. commint() maintain
TS_TTSTOP according to CTS and ttyinput() in kern/tty.c always turns
off TS_TTSTOP when IXANY is on. So NetBSD can start to send data
against CTS. But I think this might have nothing to do with slip.

ttstart() should not be called directly. It is specific to tty
discipline and not appropriate for ppp or slip discipline.

Following expression at the end of comparam() is always false because
t_cflag is assigned to c_cflag before this.
	/*
	 * If DCD is off and MDMBUF is changed, we must toggle TS_TTSTOP.
	 * XXX should be done at tty layer.
	 */
	if ((sc->sc_swflags & COM_SW_SOFTCAR) == 0 &&
	    (sc->sc_msr & MSR_DCD) == 0 &&
	    (tp->t_cflag & MDMBUF) != (t->c_cflag & MDMBUF)) {
		if ((t->c_cflag & MDMBUF) == 0) {


Following is my fix to these problems. Currently I don't use NetBSD and
I cannot examine whether my guess and fix are right.
com.c is "$Id: com.c,v 1.31 1994/04/10 10:29:06 cgd Exp $".

--- com.c.~1~	Sat Jul 16 23:31:22 1994
+++ com.c	Sun Jul 17 01:04:35 1994
@@ -557,11 +557,6 @@
 
 	s = spltty();
 
-	/* and copy to tty */
-	tp->t_ispeed = t->c_ispeed;
-	tp->t_ospeed = t->c_ospeed;
-	tp->t_cflag = t->c_cflag;
-
 	if (ospeed == 0)
 		outb(iobase + com_mcr, sc->sc_mcr &= ~MCR_DTR);
 	else
@@ -584,32 +579,32 @@
 	}
 
 	/*
-	 * If CTS is off and CRTSCTS is changed, we must toggle TS_TTSTOP.
-	 * XXX should be done at tty layer.
+	 * If CTS is off and CRTSCTS is turned off, we start output.
 	 */
 	if ((sc->sc_msr & MSR_CTS) == 0 &&
-	    (tp->t_cflag & CRTSCTS) != (t->c_cflag & CRTSCTS)) {
-		if ((t->c_cflag & CRTSCTS) == 0) {
-			tp->t_state &= ~TS_TTSTOP;
-			ttstart(tp);
-		} else
-			tp->t_state |= TS_TTSTOP;
+	    (tp->t_cflag & CRTSCTS) &&
+	    (t->c_cflag & CRTSCTS) == 0) {
+		tp->t_cflag = t->c_cflag; /* We must turn off CRTSCTS to
+					     send data. */
+		(*linesw[tp->t_line].l_start)(tp);
 	}
 
 	/*
-	 * If DCD is off and MDMBUF is changed, we must toggle TS_TTSTOP.
-	 * XXX should be done at tty layer.
+	 * If DCD is off and MDMBUF is turned off, we start output.
 	 */
 	if ((sc->sc_swflags & COM_SW_SOFTCAR) == 0 &&
 	    (sc->sc_msr & MSR_DCD) == 0 &&
-	    (tp->t_cflag & MDMBUF) != (t->c_cflag & MDMBUF)) {
-		if ((t->c_cflag & MDMBUF) == 0) {
-			tp->t_state &= ~TS_TTSTOP;
-			ttstart(tp);
-		} else
-			tp->t_state |= TS_TTSTOP;
+	    (tp->t_cflag & MDMBUF) &&
+	    (t->c_cflag & MDMBUF) == 0) {
+		tp->t_cflag = t->c_cflag;
+		(*linesw[tp->t_line].l_start)(tp);
 	}
 
+	/* and copy to tty */
+	tp->t_ispeed = t->c_ispeed;
+	tp->t_ospeed = t->c_ospeed;
+	tp->t_cflag = t->c_cflag;
+
 	splx(s);
 	return 0;
 }
@@ -625,10 +620,8 @@
 	s = spltty();
 	if (tp->t_state & (TS_TTSTOP | TS_BUSY))
 		goto out;
-#if 0 /* XXXX I think this is handled adequately by commint() and comparam(). */
 	if (tp->t_cflag & CRTSCTS && (sc->sc_mcr & MSR_CTS) == 0)
 		goto out;
-#endif
 	if (tp->t_outq.c_cc <= tp->t_lowat) {
 		if (tp->t_state & TS_ASLEEP) {
 			tp->t_state &= ~TS_ASLEEP;
@@ -718,14 +711,9 @@
 			outb(iobase + com_mcr,
 			    sc->sc_mcr &= ~(MCR_DTR | MCR_RTS));
 	}
-	if (delta & MSR_CTS && tp->t_cflag & CRTSCTS) {
-		/* the line is up and we want to do rts/cts flow control */
-		if (msr & MSR_CTS) {
-			tp->t_state &= ~TS_TTSTOP;
-			ttstart(tp);
-		} else
-			tp->t_state |= TS_TTSTOP;
-	}
+	/* the line is up and we want to do cts flow control */
+	if (delta & MSR_CTS && tp->t_cflag & CRTSCTS && msr & MSR_CTS)
+		(*linesw[tp->t_line].l_start)(tp);
 }
 
 int

PS. I send this to port-i386 instead of port-hp300, since apparently
it has nothing to do with hp300.

---
Ryutaroh Matsumoto

------------------------------------------------------------------------------