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);
}