Subject: Re: MD hooks in zsopen()/zsclose()
To: NetBSD tech-kern mailing list <tech-kern@netbsd.org>
From: Julian Coleman <J.D.Coleman@newcastle.ac.uk>
List: tech-kern
Date: 03/05/2000 22:24:05
> Looks like this is okay... but I think you want to have the "enabled" state
> to be chanstate ... because there are some applications where there are
> two chips, each with one tty and a mouse/kbd on the other channel of each
> chip.

OK.  Better?  Or should I change cs->enabled in zs_enable()/zs_disable()?

Thanks,

J

-- 
                    My other computer also runs NetBSD
                          http://www.netbsd.org/

 ---8<---------------------------- Cut here ---------------------------->8---

--- arch/sparc/dev/zs.c.dist	Mon Feb 21 20:56:39 2000
+++ arch/sparc/dev/zs.c	Sat Mar  4 19:53:52 2000
@@ -71,6 +71,7 @@
 
 #include <sparc/sparc/vaddrs.h>
 #include <sparc/sparc/auxreg.h>
+#include <sparc/sparc/auxiotwo.h>
 #include <sparc/dev/cons.h>
 
 #include "kbd.h"	/* NKBD */
@@ -194,6 +195,9 @@
 static void zs_attach __P((struct zsc_softc *, int));
 static int  zs_print __P((void *, const char *name));
 
+int zs_enable __P((struct zs_chanstate *));
+void zs_disable __P((struct zs_chanstate *));
+
 struct cfattach zs_mainbus_ca = {
 	sizeof(struct zsc_softc), zs_match_mainbus, zs_attach_mainbus
 };
@@ -292,6 +296,17 @@
 		struct sbus_attach_args *sa = &uoba->uoba_sbus;
 		zsc->zsc_bustag = sa->sa_bustag;
 		zsc->zsc_dmatag = sa->sa_dmatag;
+
+		/*
+		 * Check if power state can be set, e.g. Tadpole 3GX
+		 */
+		if (getpropint(sa->sa_node, "pwr-on-auxio2", 0))
+		{
+			printf (" powered via auxio2");
+			zsc->enable = zs_enable;
+			zsc->disable = zs_disable;
+		}
+
 		if (sa->sa_nintr != 0)
 			zs_attach(zsc, sa->sa_pri);
 	} else {
@@ -1058,4 +1073,23 @@
 #ifdef	KGDB
 	zs_kgdb_init();
 #endif
+}
+
+/*
+ * Power management hooks for zsopen() and zsclose()
+ * We use them to power on/off the ports, if necessary.
+ */
+int
+zs_enable (cs)
+	struct zs_chanstate *cs;
+{
+	auxiotwoserialendis (ZS_ENABLE);
+	return (0);
+}
+
+void
+zs_disable (cs)
+	struct zs_chanstate *cs;
+{
+	auxiotwoserialendis (ZS_DISABLE);
 }
--- arch/sparc/include/z8530var.h.dist	Sun Mar 22 12:20:23 1998
+++ arch/sparc/include/z8530var.h	Sat Mar  4 19:24:45 2000
@@ -53,6 +53,10 @@
 	bus_dma_tag_t		zsc_dmatag;
 	struct zs_chanstate	*zsc_cs[2];	/* channel A and B soft state */
 
+	/* power management hooks */
+	int (*enable) __P((struct zs_chanstate *));
+	void (*disable) __P((struct zs_chanstate *));
+
 	/* Machine-dependent part follows... */
 	struct evcnt		zsc_intrcnt;	/* count interrupts */
 	struct zs_chanstate	zsc_cs_store[2];
--- dev/ic/z8530sc.h.dist	Sat Mar 27 12:23:13 1999
+++ dev/ic/z8530sc.h	Sun Mar  5 21:02:05 2000
@@ -113,6 +113,10 @@
 
 	char	cs_softreq;		/* need soft interrupt call */
 	char	cs_spare1;  	/* (for skippy :) */
+
+	/* power management */
+	int	enabled;
+
 	/* MD code might define a larger variant of this. */
 };
 
--- dev/ic/z8530tty.c.dist	Thu Nov  4 12:20:53 1999
+++ dev/ic/z8530tty.c	Sun Mar  5 21:01:01 2000
@@ -190,6 +190,10 @@
 			zst_st_check,	/* got a status interrupt */
 			zst_rx_ready;
 
+	/* power management hooks */
+	int (*enable) __P((struct zs_chanstate *));
+	void (*disable) __P((struct zs_chanstate *));
+
 	/* PPS signal on DCD, with or without inkernel clock disciplining */
 	u_char  zst_ppsmask;			/* pps signal mask */
 	u_char  zst_ppsassert;			/* pps leading edge */
@@ -325,7 +329,12 @@
 	zst->zst_rbget = zst->zst_rbput = zst->zst_rbuf;
 	zst->zst_rbavail = zstty_rbuf_size;
 
-	/* XXX - Do we need an MD hook here? */
+	/* if there are no enable/disable functions, assume the device
+	   is always enabled */
+	zst->enable = zsc->enable;
+	zst->disable = zsc->disable;
+	if (!zst->enable)
+		cs->enabled = 1;
 
 	/*
 	 * Hardware init
@@ -435,6 +444,17 @@
 		zs_write_reg(cs, 1, cs->cs_creg[1]);
 	}
 
+	/* Call the power management hook. */
+	if (zst->disable) {
+#ifdef DIAGNOSTIC
+		if (!zst->enabled)
+			panic("zs_shutdown: not enabled?");
+#endif
+		(*zst->disable)(zst->zst_cs);
+		cs->enabled = 0;
+	}
+
+
 	splx(s);
 }
 
@@ -481,6 +501,18 @@
 		struct termios t;
 
 		tp->t_dev = dev;
+
+		/* Call the power management hook. */
+		if (zst->enable) {
+			if ((*zst->enable)(cs)) {
+				splx(s2);
+				splx(s);
+				printf("%s: device enable failed\n",
+			       	zst->zst_dev.dv_xname);
+				return (EIO);
+			}
+			cs->enabled = 1;
+		}
 
 		/*
 		 * Initialize the termios status to the defaults.  Add in the