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/07/2000 20:20:28
> I think twiddling the enabled state in zs_enable/zs_disable is better.
> 
> But why shove the function pointers in the zsc_softc? I think a better
> place to shove them is in the zs_chanstate structure.

OK, hopefully this time ;-)  I've also added hooks to com_obio (not that it
works yet).

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	Tue Mar  7 20:00:15 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
 };
@@ -283,6 +287,8 @@
 	struct zsc_softc *zsc = (void *) self;
 	union obio_attach_args *uoba = aux;
 	int zs_unit = zsc->zsc_dev.dv_unit;
+	struct zs_chanstate *cs;
+	int channel;
 
 	/* Use the mapping setup by the Sun PROM. */
 	if (zsaddr[zs_unit] == NULL)
@@ -292,6 +298,20 @@
 		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");
+			for (channel = 0; channel < 2; channel++) {
+				cs = &zsc->zsc_cs_store[channel];
+				cs->enable = zs_enable;
+				cs->disable = zs_disable;
+			}
+		}
+
 		if (sa->sa_nintr != 0)
 			zs_attach(zsc, sa->sa_pri);
 	} else {
@@ -1058,4 +1078,25 @@
 #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);
+	cs->enabled = 1;
+	return (0);
+}
+
+void
+zs_disable (cs)
+	struct zs_chanstate *cs;
+{
+	auxiotwoserialendis (ZS_DISABLE);
+	cs->enabled = 0;
 }
--- dev/ic/z8530tty.c.dist	Thu Nov  4 12:20:53 1999
+++ dev/ic/z8530tty.c	Tue Mar  7 20:12:56 2000
@@ -325,7 +325,10 @@
 	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 */
+	if (!cs->enable)
+		cs->enabled = 1;
 
 	/*
 	 * Hardware init
@@ -435,6 +438,16 @@
 		zs_write_reg(cs, 1, cs->cs_creg[1]);
 	}
 
+	/* Call the power management hook. */
+	if (cs->disable) {
+#ifdef DIAGNOSTIC
+		if (!cs->enabled)
+			panic("zs_shutdown: not enabled?");
+#endif
+		(*cs->disable)(zst->zst_cs);
+	}
+
+
 	splx(s);
 }
 
@@ -481,6 +494,17 @@
 		struct termios t;
 
 		tp->t_dev = dev;
+
+		/* Call the power management hook. */
+		if (cs->enable) {
+			if ((*cs->enable)(cs)) {
+				splx(s2);
+				splx(s);
+				printf("%s: device enable failed\n",
+			       	zst->zst_dev.dv_xname);
+				return (EIO);
+			}
+		}
 
 		/*
 		 * Initialize the termios status to the defaults.  Add in the
--- dev/ic/z8530sc.h.dist	Sat Mar 27 12:23:13 1999
+++ dev/ic/z8530sc.h	Tue Mar  7 18:40:54 2000
@@ -113,6 +113,12 @@
 
 	char	cs_softreq;		/* need soft interrupt call */
 	char	cs_spare1;  	/* (for skippy :) */
+
+	/* power management hooks */
+	int (*enable) __P((struct zs_chanstate *));
+	void (*disable) __P((struct zs_chanstate *));
+	int	enabled;
+
 	/* MD code might define a larger variant of this. */
 };
 

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

--- arch/sparc/dev/com_obio.c.dist	Mon Nov 22 12:15:17 1999
+++ arch/sparc/dev/com_obio.c	Tue Mar  7 19:46:51 2000
@@ -105,6 +105,9 @@
 static void com_obio_attach __P((struct device *, struct device *, void *));
 static void com_obio_cleanup __P((void *));
 
+int com_obio_enable __P((struct com_softc *));
+void com_obio_disable __P((struct com_softc *));
+
 struct cfattach com_obio_ca = {
 	sizeof(struct com_obio_softc), com_obio_match, com_obio_attach
 };
@@ -127,8 +130,9 @@
 	if (strcmp("modem", sa->sa_name) == 0) {
 		bus_space_handle_t ioh;
 		int rv = 0;
-		u_int8_t auxregval = *AUXIO4M_REG;
-		 *AUXIO4M_REG = auxregval | (AUXIO4M_LED|AUXIO4M_LTE);
+
+		auxregbisc(AUXIO4M_LED, 1);
+		auxregbisc(AUXIO4M_LTE, 1);
 		DELAY(100);
 		if (sbus_bus_map(sa->sa_bustag, sa->sa_slot,
 				 sa->sa_offset, sa->sa_size,
@@ -142,7 +146,8 @@
 #endif
 			bus_space_unmap(sa->sa_bustag, ioh, sa->sa_size);
 		}
-		*AUXIO4M_REG = auxregval;
+		auxregbisc(AUXIO4M_LED, 0);
+		auxregbisc(AUXIO4M_LTE, 0);
 		return (rv);
 	}
 	return (0);
@@ -158,6 +163,12 @@
 	union obio_attach_args *uoba = aux;
 	struct sbus_attach_args *sa = &uoba->uoba_sbus;
 
+	if (getpropint(sa->sa_node, "pwr-on-auxio", 0) !=0) {
+		printf(" powered via auxio");
+		sc->enable = com_obio_enable;
+		sc->disable = com_obio_disable;
+	}
+
 	/*
 	 * We're living on an obio that looks like an sbus slot.
 	 */
@@ -172,7 +183,7 @@
 		return;
 	}
 
-	*AUXIO4M_REG |= (AUXIO4M_LED|AUXIO4M_LTE);
+	com_obio_enable(sc);
 	do {
 		DELAY(100);
 	} while (!comprobe1(sc->sc_iot, sc->sc_ioh));
@@ -198,6 +209,7 @@
 	if (shutdownhook_establish(com_obio_cleanup, sc) == NULL) {
 		panic("com_obio_attach: could not establish shutdown hook");
 	}
+	com_obio_disable(sc);
 }
 
 static void
@@ -208,4 +220,25 @@
 
 	if (ISSET(sc->sc_hwflags, COM_HW_FIFO))
 		bus_space_write_1(sc->sc_iot, sc->sc_ioh, com_fifo, 0);
+}
+
+/*
+ * Power management hooks for comopen() and comclose()
+ * We use them to power on/off the modem.
+ */
+int
+com_obio_enable (sc)
+	struct com_softc *sc;
+{
+	auxregbisc(AUXIO4M_LED, 1);
+	auxregbisc(AUXIO4M_LTE, 1);
+	return (0);
+}
+
+void
+com_obio_disable (sc)
+	struct com_softc *sc;
+{
+	auxregbisc(AUXIO4M_LED, 0);
+	auxregbisc(AUXIO4M_LTE, 0);
 }