Subject: Request for review
To: None <tech-kern@netbsd.org>
From: Andrew Doran <ad@interlude.eu.org>
List: tech-kern
Date: 09/20/2002 05:57:30
Hi,

This patch handles the kooky wiring on DEC SCCs, and will mean that the
alpha TCWSCONS config can be got rid of. It's a rehash of a patch Ken
Hornstein posted a few years ago.

There are maybe another 20 or 30 places around the tree where cs_ctl_chan
needs to be set by MD code; those aren't shown here.

Any objections?
 
Index: z8530sc.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/z8530sc.c,v
retrieving revision 1.16
diff -u -r1.16 z8530sc.c
--- z8530sc.c	2001/11/13 13:14:46	1.16
+++ z8530sc.c	2002/09/20 04:38:13
@@ -132,7 +132,7 @@
 zs_loadchannelregs(cs)
 	struct zs_chanstate *cs;
 {
-	u_char *reg;
+	u_char *reg, v;
 
 	zs_write_csr(cs, ZSM_RESET_ERR); /* XXX: reset error condition */
 
@@ -144,9 +144,15 @@
 	zs_iflush(cs);	/* XXX */
 #endif
 
-	if (memcmp((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16) == 0)
-	    return;	/* only change if values are different */
+	if (cs->cs_ctl_chan != NULL)
+		v = ((cs->cs_ctl_chan->cs_creg[5] & (ZSWR5_RTS | ZSWR5_DTR)) !=
+		    (cs->cs_ctl_chan->cs_preg[5] & (ZSWR5_RTS | ZSWR5_DTR)));
+	else
+		v = 0;
 
+	if (memcmp((caddr_t)cs->cs_preg, (caddr_t)cs->cs_creg, 16) == 0 && !v)
+		return;	/* only change if values are different */
+
 	/* Copy "pending" regs to "current" */
 	memcpy((caddr_t)cs->cs_creg, (caddr_t)cs->cs_preg, 16);
 	reg = cs->cs_creg;	/* current regs */
@@ -215,6 +221,13 @@
 	/* char size, enable (RX/TX)*/
 	zs_write_reg(cs, 3, reg[3]);
 	zs_write_reg(cs, 5, reg[5]);
+
+	/* Write the status bits on the alternate channel also. */
+	if (cs->cs_ctl_chan != NULL && cs->cs_ctl_chan != cs) {
+		v = cs->cs_ctl_chan->cs_preg[5];
+		cs->cs_ctl_chan->cs_creg[5] = v;
+		zs_write_reg(cs->cs_ctl_chan, 5, v);
+	}
 
 	/* interrupt enables: RX, TX, STATUS */
 	zs_write_reg(cs, 1, reg[1]);
Index: z8530sc.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/z8530sc.h,v
retrieving revision 1.16
diff -u -r1.16 z8530sc.h
--- z8530sc.h	2002/09/06 13:23:12	1.16
+++ z8530sc.h	2002/09/20 04:38:13
@@ -83,6 +83,13 @@
 	int	cs_defcflag;		/* default cflag */
 
 	/*
+	 * For strange systems that have oddly wired serial ports, we
+	 * provide a pointer to the channel state of the port that has
+	 * our status lines on it
+	 */
+	struct zs_chanstate *cs_ctl_chan;
+
+	/*
 	 * We must keep a copy of the write registers as they are
 	 * mostly write-only and we sometimes need to set and clear
 	 * individual bits (e.g., in WR3).  Not all of these are
Index: z8530tty.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ic/z8530tty.c,v
retrieving revision 1.80
diff -u -r1.80 z8530tty.c
--- z8530tty.c	2002/09/06 13:23:12	1.80
+++ z8530tty.c	2002/09/20 04:38:15
@@ -1235,13 +1235,13 @@
 {
 	struct zs_chanstate *cs = zst->zst_cs;
 
-	if (cs->cs_wr5_dtr == 0)
+	if (cs->cs_wr5_dtr == 0 || cs->cs_ctl_chan == NULL)
 		return;
 
 	if (onoff)
-		SET(cs->cs_preg[5], cs->cs_wr5_dtr);
+		SET(cs->cs_ctl_chan->cs_preg[5], cs->cs_wr5_dtr);
 	else
-		CLR(cs->cs_preg[5], cs->cs_wr5_dtr);
+		CLR(cs->cs_ctl_chan->cs_preg[5], cs->cs_wr5_dtr);
 
 	if (!cs->cs_heldchange) {
 		if (zst->zst_tx_busy) {
@@ -1262,6 +1262,9 @@
 	struct zs_chanstate *cs = zst->zst_cs;
 	u_char zsbits;
 
+	if (cs->cs_ctl_chan == NULL)
+		return;
+
 	zsbits = 0;
 	if (ISSET(ttybits, TIOCM_DTR))
 		SET(zsbits, ZSWR5_DTR);
@@ -1270,16 +1273,16 @@
 
 	switch (how) {
 	case TIOCMBIC:
-		CLR(cs->cs_preg[5], zsbits);
+		CLR(cs->cs_ctl_chan->cs_preg[5], zsbits);
 		break;
 
 	case TIOCMBIS:
-		SET(cs->cs_preg[5], zsbits);
+		SET(cs->cs_ctl_chan->cs_preg[5], zsbits);
 		break;
 
 	case TIOCMSET:
-		CLR(cs->cs_preg[5], ZSWR5_RTS | ZSWR5_DTR);
-		SET(cs->cs_preg[5], zsbits);
+		CLR(cs->cs_ctl_chan->cs_preg[5], ZSWR5_RTS | ZSWR5_DTR);
+		SET(cs->cs_ctl_chan->cs_preg[5], zsbits);
 		break;
 	}
 
@@ -1301,11 +1304,13 @@
 	u_char zsbits;
 	int ttybits = 0;
 
-	zsbits = cs->cs_preg[5];
-	if (ISSET(zsbits, ZSWR5_DTR))
-		SET(ttybits, TIOCM_DTR);
-	if (ISSET(zsbits, ZSWR5_RTS))
-		SET(ttybits, TIOCM_RTS);
+	if (cs->cs_ctl_chan != NULL) {
+		zsbits = cs->cs_ctl_chan->cs_preg[5];
+		if (ISSET(zsbits, ZSWR5_DTR))
+			SET(ttybits, TIOCM_DTR);
+		if (ISSET(zsbits, ZSWR5_RTS))
+			SET(ttybits, TIOCM_RTS);
+	}
 
 	zsbits = cs->cs_rr0;
 	if (ISSET(zsbits, ZSRR0_DCD))
@@ -1365,17 +1370,17 @@
 {
 	struct zs_chanstate *cs = zst->zst_cs;
 
-	if (cs->cs_wr5_rts == 0)
+	if (cs->cs_wr5_rts == 0 || cs->cs_ctl_chan == NULL)
 		return;
 
 	if (ISSET(zst->zst_rx_flags, RX_ANY_BLOCK)) {
-		CLR(cs->cs_preg[5], cs->cs_wr5_rts);
-		CLR(cs->cs_creg[5], cs->cs_wr5_rts);
+		CLR(cs->cs_ctl_chan->cs_preg[5], cs->cs_wr5_rts);
+		CLR(cs->cs_ctl_chan->cs_creg[5], cs->cs_wr5_rts);
 	} else {
-		SET(cs->cs_preg[5], cs->cs_wr5_rts);
-		SET(cs->cs_creg[5], cs->cs_wr5_rts);
+		SET(cs->cs_ctl_chan->cs_preg[5], cs->cs_wr5_rts);
+		SET(cs->cs_ctl_chan->cs_creg[5], cs->cs_wr5_rts);
 	}
-	zs_write_reg(cs, 5, cs->cs_creg[5]);
+	zs_write_reg(cs->cs_ctl_chan, 5, cs->cs_cs_ctl_chan->creg[5]);
 }
 
 
Index: zs_ioasic.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/tc/zs_ioasic.c,v
retrieving revision 1.11
diff -u -r1.11 zs_ioasic.c
--- zs_ioasic.c	2002/09/06 13:23:37	1.11
+++ zs_ioasic.c	2002/09/20 04:38:55
@@ -317,7 +317,6 @@
 			zs_write_reg(cs, 9, 0);
 		}
 
-#ifdef notyet /* XXX thorpej */
 		/*
 		 * Set up the flow/modem control channel pointer to
 		 * deal with the weird wiring on the TC Alpha and
@@ -327,7 +326,6 @@
 			cs->cs_ctl_chan = zs->zsc_cs[0];
 		else
 			cs->cs_ctl_chan = NULL;
-#endif
 
 		/*
 		 * Look for a child driver for this channel.