summaryrefslogtreecommitdiff
path: root/sys/arch/sparc/dev
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2005-03-29 11:36:42 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2005-03-29 11:36:42 +0000
commit7308b7b3256cb8f493d16e07a31eedb2e7385aef (patch)
tree326afc8ed9ed0e512ec291789c6cc49f4becc395 /sys/arch/sparc/dev
parent05bdd540913abf6879f0a971901b3ec6740eb6a2 (diff)
A few tctrl improvements, mostly adapted from NetBSD:
- use a better state machine, and define a simple internal interface to send commands to the microcontroller. - program the 2nd line of the LCD screen; currently limited to the ``external power available'' and ``PCMCIA'' icons. - fix races in the brightness adjustement and powerdown request. - wrap initial dmesg output at 80 chars.
Diffstat (limited to 'sys/arch/sparc/dev')
-rw-r--r--sys/arch/sparc/dev/tctrl.c600
-rw-r--r--sys/arch/sparc/dev/tctrlvar.h14
2 files changed, 362 insertions, 252 deletions
diff --git a/sys/arch/sparc/dev/tctrl.c b/sys/arch/sparc/dev/tctrl.c
index c0660769386..77872681422 100644
--- a/sys/arch/sparc/dev/tctrl.c
+++ b/sys/arch/sparc/dev/tctrl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tctrl.c,v 1.7 2004/09/29 07:35:11 miod Exp $ */
+/* $OpenBSD: tctrl.c,v 1.8 2005/03/29 11:36:40 miod Exp $ */
/* $NetBSD: tctrl.c,v 1.2 1999/08/11 00:46:06 matt Exp $ */
/*-
@@ -39,18 +39,10 @@
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/ioctl.h>
-#include <sys/select.h>
-#include <sys/tty.h>
-#include <sys/proc.h>
-#include <sys/user.h>
#include <sys/conf.h>
-#include <sys/file.h>
-#include <sys/uio.h>
#include <sys/kernel.h>
-#include <sys/syslog.h>
-#include <sys/types.h>
#include <sys/device.h>
+#include <sys/timeout.h>
#include <machine/autoconf.h>
#include <machine/cpu.h>
@@ -72,45 +64,51 @@ const char *tctrl_ext_statuses[16] = {
"external battery discharging",
};
+/* Request "packet" */
+struct tctrl_req {
+ u_int8_t cmdbuf[16];
+ u_int cmdlen;
+ u_int8_t rspbuf[16];
+ u_int rsplen;
+};
+
struct tctrl_softc {
struct device sc_dev;
struct uctrl_regs *sc_regs;
struct intrhand sc_ih;
- int sc_node;
- unsigned int sc_junk;
- unsigned int sc_ext_status;
- unsigned int sc_video_accel;
- unsigned int sc_pending;
-#define TCTRL_SEND_BITPORT 0x0001
-#define TCTRL_SEND_POWEROFF 0x0002
-#define TCTRL_SEND_RD_EXT_STATUS 0x0004
-#define TCTRL_SEND_RD_EVENT_STATUS 0x0008
-#define TCTRL_SEND_BITPORT_NOP 0x0010
-#define TCTRL_SEND_BRIGHTNESS 0x0020
-#define TCTRL_SEND_BRIGHTNESS_NOP 0x0040
+ u_int sc_ext_status;
+ u_int sc_flags;
+#define TCTRL_SEND_REQUEST 0x0001
+ u_int sc_wantdata;
enum { TCTRL_IDLE, TCTRL_ARGS,
TCTRL_ACK, TCTRL_DATA } sc_state;
u_int8_t sc_cmdbuf[16];
u_int8_t sc_rspbuf[16];
- u_int8_t sc_bitport;
u_int8_t sc_tft_on;
+ u_int8_t sc_pcmcia_on;
u_int8_t sc_brightness;
u_int8_t sc_op;
- u_int8_t sc_cmdoff;
- u_int8_t sc_cmdlen;
- u_int8_t sc_rspoff;
- u_int8_t sc_rsplen;
+ u_int sc_cmdoff;
+ u_int sc_cmdlen;
+ u_int sc_rspoff;
+ u_int sc_rsplen;
+
+ struct timeout sc_tmo;
};
-int tctrl_match(struct device *, void *, void *);
-void tctrl_attach(struct device *, struct device *, void *);
+int tctrl_match(struct device *, void *, void *);
+void tctrl_attach(struct device *, struct device *, void *);
-void tctrl_write_data(struct tctrl_softc *, u_int8_t);
+void tctrl_brightness(struct tctrl_softc *, int, int);
+void tctrl_init_lcd(struct tctrl_softc *);
+int tctrl_intr(void *);
+void tctrl_lcd(struct tctrl_softc *, int, int);
u_int8_t tctrl_read_data(struct tctrl_softc *);
-int tctrl_intr(void *);
-void tctrl_setup_bitport(struct tctrl_softc *, int);
-void tctrl_setup_brightness(struct tctrl_softc *, int, int);
-void tctrl_process_response(struct tctrl_softc *);
+void tctrl_read_event_status(void *);
+void tctrl_read_ext_status(struct tctrl_softc *);
+void tctrl_request(struct tctrl_softc *, struct tctrl_req *);
+void tctrl_tft(struct tctrl_softc *);
+void tctrl_write_data(struct tctrl_softc *, u_int8_t);
struct cfattach tctrl_ca = {
sizeof(struct tctrl_softc), tctrl_match, tctrl_attach
@@ -147,13 +145,9 @@ tctrl_attach(parent, self, aux)
{
struct confargs *ca = aux;
struct tctrl_softc *sc = (void *)self;
+ u_int i, v;
int pri;
- unsigned int i, v;
- /*
- * We're living on a sbus slot that looks like an obio that
- * looks like an sbus slot.
- */
if (ca->ca_ra.ra_nintr != 1) {
printf(": expected 1 interrupt, got %d\n",
ca->ca_ra.ra_nintr);
@@ -169,14 +163,11 @@ tctrl_attach(parent, self, aux)
sc->sc_regs = mapiodev(&(ca->ca_ra.ra_reg[0]), 0,
ca->ca_ra.ra_reg[0].rr_len);
- sc->sc_node = ca->ca_ra.ra_node;
-
printf(" pri %d\n", pri);
sc->sc_tft_on = 1;
- /* clear any pending data.
- */
+ /* clear any pending data */
for (i = 0; i < 10000; i++) {
if ((TS102_UCTRL_STS_RXNE_STA & sc->sc_regs->stat) == 0)
break;
@@ -188,42 +179,48 @@ tctrl_attach(parent, self, aux)
sc->sc_ih.ih_arg = sc;
intr_establish(pri, &sc->sc_ih, -1, self->dv_xname);
- /* See what the external status is
- */
- sc->sc_pending |= TCTRL_SEND_RD_EXT_STATUS;
- do {
- tctrl_intr(sc);
- } while (sc->sc_state != TCTRL_IDLE);
+ timeout_set(&sc->sc_tmo, tctrl_read_event_status, sc);
+ /* See what the external status is */
+ tctrl_read_ext_status(sc);
if (sc->sc_ext_status != 0) {
const char *sep;
+ u_int len;
- printf("%s: ", sc->sc_dev.dv_xname);
v = sc->sc_ext_status;
- for (i = 0, sep = ""; v != 0; i++, v >>= 1) {
- if (v & 1) {
- printf("%s%s", sep, tctrl_ext_statuses[i]);
- sep = ", ";
+ len = 0;
+ sep = "";
+ for (i = 0; v != 0; i++, v >>= 1) {
+ if ((v & 1) == 0)
+ continue;
+ /* wrap to next line if necessary */
+ if (len != 0 && len + strlen(sep) +
+ strlen(tctrl_ext_statuses[i]) > 80) {
+ printf("\n");
+ len = 0;
}
+ if (len == 0) {
+ printf("%s: ", sc->sc_dev.dv_xname);
+ len = 2 + strlen(sc->sc_dev.dv_xname);
+ sep = "";
+ }
+ printf("%s%s", sep, tctrl_ext_statuses[i]);
+ len += strlen(sep) + strlen(tctrl_ext_statuses[i]);
+ sep = ", ";
}
- printf("\n");
+ if (len != 0)
+ printf("\n");
}
- /*
- * Get a few status values.
- */
- sc->sc_video_accel =
- sc->sc_ext_status & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE;
- sc->sc_pending |= TCTRL_SEND_BITPORT_NOP;
- do {
- tctrl_intr(sc);
- } while (sc->sc_state != TCTRL_IDLE);
- sc->sc_pending |= TCTRL_SEND_BRIGHTNESS_NOP;
- do {
- tctrl_intr(sc);
- } while (sc->sc_state != TCTRL_IDLE);
+ /* Get a few status values */
+ tctrl_brightness(sc, 0xff, 0);
sc->sc_regs->intr = TS102_UCTRL_INT_RXNE_REQ|TS102_UCTRL_INT_RXNE_MSK;
+
+ sc->sc_wantdata = 0;
+
+ /* Initialize the LCD icons */
+ tctrl_init_lcd(sc);
}
int
@@ -233,9 +230,9 @@ tctrl_intr(void *arg)
unsigned int v, d;
int progress = 0;
- again:
+again:
/* find out the cause(s) of the interrupt */
- v = sc->sc_regs->stat;
+ v = sc->sc_regs->stat & TS102_UCTRL_STS_MASK;
/* clear the cause(s) of the interrupt */
sc->sc_regs->stat = v;
@@ -243,8 +240,13 @@ tctrl_intr(void *arg)
v &= ~(TS102_UCTRL_STS_RXO_STA|TS102_UCTRL_STS_TXE_STA);
if (sc->sc_cmdoff >= sc->sc_cmdlen) {
v &= ~TS102_UCTRL_STS_TXNF_STA;
+ if (sc->sc_regs->intr & TS102_UCTRL_INT_TXNF_REQ) {
+ sc->sc_regs->intr = 0;
+ progress = 1;
+ }
}
- if ((v == 0) && (sc->sc_pending == 0 || sc->sc_state != TCTRL_IDLE)) {
+ if (v == 0 && ((sc->sc_flags & TCTRL_SEND_REQUEST) == 0 ||
+ sc->sc_state != TCTRL_IDLE)) {
return (progress);
}
@@ -254,7 +256,8 @@ tctrl_intr(void *arg)
switch (sc->sc_state) {
case TCTRL_IDLE:
if (d == 0xfa) {
- sc->sc_pending |= TCTRL_SEND_RD_EVENT_STATUS;
+ /* external event */
+ timeout_add(&sc->sc_tmo, 1);
} else {
printf("%s: (op=0x%02x): unexpected data (0x%02x)\n",
sc->sc_dev.dv_xname, sc->sc_op, d);
@@ -265,13 +268,14 @@ tctrl_intr(void *arg)
printf("%s: (op=0x%02x): unexpected ack value (0x%02x)\n",
sc->sc_dev.dv_xname, sc->sc_op, d);
}
-#if 0
+#ifdef TCTRLDEBUG
printf(" ack=0x%02x", d);
#endif
sc->sc_rsplen--;
sc->sc_rspoff = 0;
sc->sc_state = sc->sc_rsplen ? TCTRL_DATA : TCTRL_IDLE;
-#if 0
+ sc->sc_wantdata = sc->sc_rsplen ? 1 : 0;
+#ifdef TCTRLDEBUG
if (sc->sc_rsplen > 0) {
printf(" [data(%u)]", sc->sc_rsplen);
} else {
@@ -281,15 +285,15 @@ tctrl_intr(void *arg)
goto again;
case TCTRL_DATA:
sc->sc_rspbuf[sc->sc_rspoff++] = d;
-#if 0
+#ifdef TCTRLDEBUG
printf(" [%d]=0x%02x", sc->sc_rspoff-1, d);
#endif
if (sc->sc_rspoff == sc->sc_rsplen) {
-#if 0
+#ifdef TCTRLDEBUG
printf(" [idle]\n");
#endif
sc->sc_state = TCTRL_IDLE;
- tctrl_process_response(sc);
+ sc->sc_wantdata = 0;
}
goto again;
default:
@@ -298,37 +302,12 @@ tctrl_intr(void *arg)
goto again;
}
}
- if (sc->sc_state == TCTRL_IDLE) {
- sc->sc_cmdoff = 0;
- sc->sc_cmdlen = 0;
- if (sc->sc_pending & TCTRL_SEND_POWEROFF) {
- sc->sc_pending &= ~TCTRL_SEND_POWEROFF;
- sc->sc_cmdbuf[0] = TS102_OP_ADMIN_POWER_OFF;
- sc->sc_cmdlen = 1;
- sc->sc_rsplen = 0;
- } else if (sc->sc_pending & TCTRL_SEND_RD_EVENT_STATUS) {
- sc->sc_pending &= ~TCTRL_SEND_RD_EVENT_STATUS;
- sc->sc_cmdbuf[0] = TS102_OP_RD_EVENT_STATUS;
- sc->sc_cmdlen = 1;
- sc->sc_rsplen = 3;
- } else if (sc->sc_pending & TCTRL_SEND_RD_EXT_STATUS) {
- sc->sc_pending &= ~TCTRL_SEND_RD_EXT_STATUS;
- sc->sc_cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
- sc->sc_cmdlen = 1;
- sc->sc_rsplen = 3;
- } else if (sc->sc_pending & TCTRL_SEND_BITPORT_NOP) {
- sc->sc_pending &= ~TCTRL_SEND_BITPORT_NOP;
- tctrl_setup_bitport(sc, 1);
- } else if (sc->sc_pending & TCTRL_SEND_BITPORT) {
- sc->sc_pending &= ~TCTRL_SEND_BITPORT;
- tctrl_setup_bitport(sc, 0);
- } else if (sc->sc_pending & TCTRL_SEND_BRIGHTNESS_NOP) {
- sc->sc_pending &= ~TCTRL_SEND_BRIGHTNESS_NOP;
- tctrl_setup_brightness(sc, 0xff, 0);
- } else if (sc->sc_pending & TCTRL_SEND_BRIGHTNESS) {
- sc->sc_pending &= ~TCTRL_SEND_BRIGHTNESS;
- tctrl_setup_brightness(sc, 0, sc->sc_brightness);
- }
+ if ((sc->sc_state == TCTRL_IDLE && sc->sc_wantdata == 0) ||
+ (sc->sc_flags & TCTRL_SEND_REQUEST)) {
+ if (sc->sc_flags & TCTRL_SEND_REQUEST) {
+ sc->sc_flags &= ~TCTRL_SEND_REQUEST;
+ sc->sc_wantdata = 1;
+ }
if (sc->sc_cmdlen > 0) {
sc->sc_regs->intr =
sc->sc_regs->intr | TS102_UCTRL_INT_TXNF_MSK
@@ -338,7 +317,7 @@ tctrl_intr(void *arg)
}
if ((sc->sc_cmdoff < sc->sc_cmdlen) && (v & TS102_UCTRL_STS_TXNF_STA)) {
tctrl_write_data(sc, sc->sc_cmdbuf[sc->sc_cmdoff++]);
-#if 0
+#ifdef TCTRLDEBUG
if (sc->sc_cmdoff == 1) {
printf("%s: op=0x%02x(l=%u)", sc->sc_dev.dv_xname,
sc->sc_cmdbuf[0], sc->sc_rsplen);
@@ -349,7 +328,7 @@ tctrl_intr(void *arg)
#endif
if (sc->sc_cmdoff == sc->sc_cmdlen) {
sc->sc_state = sc->sc_rsplen ? TCTRL_ACK : TCTRL_IDLE;
-#if 0
+#ifdef TCTRLDEBUG
printf(" %s", sc->sc_rsplen ? "[ack]" : "[idle]\n");
#endif
if (sc->sc_cmdoff == 1) {
@@ -361,7 +340,7 @@ tctrl_intr(void *arg)
} else if (sc->sc_state == TCTRL_IDLE) {
sc->sc_op = sc->sc_cmdbuf[0];
sc->sc_state = TCTRL_ARGS;
-#if 0
+#ifdef TCTRLDEBUG
printf(" [args]");
#endif
}
@@ -369,102 +348,261 @@ tctrl_intr(void *arg)
goto again;
}
+/*
+ * The Tadpole microcontroller is not preprogrammed with icon
+ * representations. The machine boots with the DC-IN light as
+ * a blank (all 0x00) and the other lights, as 4 rows of horizontal
+ * bars. The below code initializes the few icons the system will use
+ * to sane values.
+ *
+ * Programming the icons is simple. It is a 5x8 matrix, with each row a
+ * bitfield in the order 0x10 0x08 0x04 0x02 0x01.
+ */
+
+static void tctrl_set_glyph(struct tctrl_softc *, u_int, const u_int8_t *);
+
+static const u_int8_t
+ tctrl_glyph_dc[] = { 0x00, 0x00, 0x1f, 0x00, 0x15, 0x00, 0x00, 0x00 },
+#if 0
+ tctrl_glyph_bs[] = { 0x00, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00 },
+ tctrl_glyph_w1[] = { 0x0c, 0x16, 0x10, 0x15, 0x10, 0x16, 0x0c, 0x00 },
+ tctrl_glyph_w2[] = { 0x0c, 0x0d, 0x01, 0x15, 0x01, 0x0d, 0x0c, 0x00 },
+ tctrl_glyph_l1[] = { 0x00, 0x04, 0x08, 0x13, 0x08, 0x04, 0x00, 0x00 },
+ tctrl_glyph_l2[] = { 0x00, 0x04, 0x02, 0x19, 0x02, 0x04, 0x00, 0x00 },
+#endif
+ tctrl_glyph_pc[] = { 0x00, 0x0e, 0x0e, 0x1f, 0x1f, 0x1f, 0x1f, 0x00 };
+
+void
+tctrl_init_lcd(struct tctrl_softc *sc)
+{
+ tctrl_set_glyph(sc, TS102_BLK_OFF_DEF_DC_GOOD, tctrl_glyph_dc);
+#if 0
+ tctrl_set_glyph(sc, TS102_BLK_OFF_DEF_BACKSLASH, tctrl_glyph_bs);
+ tctrl_set_glyph(sc, TS102_BLK_OFF_DEF_WAN1, tctrl_glyph_w1);
+ tctrl_set_glyph(sc, TS102_BLK_OFF_DEF_WAN2, tctrl_glyph_w2);
+ tctrl_set_glyph(sc, TS102_BLK_OFF_DEF_LAN1, tctrl_glyph_l1);
+ tctrl_set_glyph(sc, TS102_BLK_OFF_DEF_LAN2, tctrl_glyph_l2);
+#endif
+ tctrl_set_glyph(sc, TS102_BLK_OFF_DEF_PCMCIA, tctrl_glyph_pc);
+}
+
+static void
+tctrl_set_glyph(struct tctrl_softc *sc, u_int glyph, const u_int8_t *data)
+{
+ struct tctrl_req req;
+
+ req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
+ req.cmdbuf[1] = 8;
+ req.cmdbuf[2] = glyph;
+ bcopy(data, req.cmdbuf + 3, 8);
+ req.cmdlen = 3 + 8;
+ req.rsplen = 1;
+
+ tctrl_request(sc, &req);
+}
+
+void
+tctrl_read_event_status(void *arg)
+{
+ struct tctrl_softc *sc = (struct tctrl_softc *)arg;
+ struct tctrl_req req;
+ unsigned int v;
+
+ req.cmdbuf[0] = TS102_OP_RD_EVENT_STATUS;
+ req.cmdlen = 1;
+ req.rsplen = 3;
+
+ tctrl_request(sc, &req);
+
+ v = req.rspbuf[0] * 256 + req.rspbuf[1];
+ if (v & TS102_EVENT_STATUS_SHUTDOWN_REQUEST) {
+ printf("%s: SHUTDOWN REQUEST!\n", sc->sc_dev.dv_xname);
+ }
+#ifdef TCTRLDEBUG
+ /* Obviously status change */
+ if (v & TS102_EVENT_STATUS_VERY_LOW_POWER_WARNING) {
+ printf("%s: Battery level change\n", sc->sc_dev.dv_xname);
+ }
+#endif
+ if (v & TS102_EVENT_STATUS_LOW_POWER_WARNING) {
+ printf("%s: LOW POWER WARNING!\n", sc->sc_dev.dv_xname);
+ }
+ if (v & TS102_EVENT_STATUS_DC_STATUS_CHANGE) {
+ tctrl_read_ext_status(sc);
+ printf("%s: main power %s\n", sc->sc_dev.dv_xname,
+ (sc->sc_ext_status & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE) ?
+ "restored" : "removed");
+#if 0 /* automatically done for us */
+ tctrl_lcd(sc, ~TS102_LCD_DC_OK,
+ sc->sc_ext_status & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE ?
+ TS102_LCD_DC_OK : 0);
+#endif
+ }
+ if (v & TS102_EVENT_STATUS_LID_STATUS_CHANGE) {
+ tctrl_read_ext_status(sc);
+ /* restore video if necessary */
+ if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) == 0 &&
+ sc->sc_tft_on)
+ tctrl_tft(sc);
+#ifdef TCTRLDEBUG
+ printf("%s: lid %s\n", sc->sc_dev.dv_xname,
+ (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) ?
+ "closed" : "opened");
+#endif
+ }
+}
+
+void
+tctrl_read_ext_status(struct tctrl_softc *sc)
+{
+ struct tctrl_req req;
+
+ req.cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
+ req.cmdlen = 1;
+ req.rsplen = 3;
+#ifdef TCTRLDEBUG
+ printf("tctrl_read_ext_status: before, ext_status = %x\n",
+ sc->sc_ext_status);
+#endif
+
+ tctrl_request(sc, &req);
+
+ sc->sc_ext_status = req.rspbuf[0] * 256 + req.rspbuf[1];
+
+#ifdef TCTRLDEBUG
+ printf("tctrl_read_ext_status: after, ext_status = %x\n",
+ sc->sc_ext_status);
+#endif
+}
+
+void
+tctrl_brightness(struct tctrl_softc *sc, int mask, int value)
+{
+ struct tctrl_req req;
+
+ req.cmdbuf[0] = TS102_OP_CTL_TFT_BRIGHTNESS;
+ req.cmdbuf[1] = mask;
+ req.cmdbuf[2] = value;
+ req.cmdlen = 3;
+ req.rsplen = 2;
+
+ tctrl_request(sc, &req);
+
+ sc->sc_brightness = req.rspbuf[0];
+}
+
void
-tctrl_setup_bitport(struct tctrl_softc *sc, int nop)
+tctrl_tft(struct tctrl_softc *sc)
{
- if (nop) {
- sc->sc_cmdbuf[0] = TS102_OP_CTL_BITPORT;
- sc->sc_cmdbuf[1] = 0xff;
- sc->sc_cmdbuf[2] = 0;
- sc->sc_cmdlen = 3;
- sc->sc_rsplen = 2;
+ struct tctrl_req req;
+
+ if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
+ || !sc->sc_tft_on) {
+ req.cmdbuf[2] = TS102_BITPORT_TFTPWR;
} else {
- if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
- || (!sc->sc_tft_on)) {
- sc->sc_cmdbuf[2] = TS102_BITPORT_TFTPWR;
- } else {
- sc->sc_cmdbuf[2] = 0;
- }
- sc->sc_cmdbuf[0] = TS102_OP_CTL_BITPORT;
- sc->sc_cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
- sc->sc_cmdlen = 3;
- sc->sc_rsplen = 2;
+ req.cmdbuf[2] = 0;
}
+ req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
+ req.cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
+ req.cmdlen = 3;
+ req.rsplen = 2;
+
+ tctrl_request(sc, &req);
}
void
-tctrl_setup_brightness(struct tctrl_softc *sc, int mask, int value)
+tctrl_lcd(struct tctrl_softc *sc, int mask, int value)
{
- sc->sc_cmdbuf[0] = TS102_OP_CTL_TFT_BRIGHTNESS;
- sc->sc_cmdbuf[1] = mask;
- sc->sc_cmdbuf[2] = value;
- sc->sc_cmdlen = 3;
- sc->sc_rsplen = 2;
+ struct tctrl_req req;
+
+ req.cmdbuf[0] = TS102_OP_CTL_LCD;
+
+ /*
+ * The mask setup for this particular command is *very* bizarre
+ * and totally undocumented.
+ * One would expect the cmdlen and rsplen to be 5 and 3,
+ * respectively, as well. Though luck, they are not...
+ */
+
+ req.cmdbuf[1] = mask & 0xff;
+ req.cmdbuf[4] = (mask >> 8) & 0x01;
+
+ req.cmdbuf[2] = value & 0xff;
+ req.cmdbuf[3] = (value >> 8 & 0x01);
+
+ req.cmdlen = 3;
+ req.rsplen = 2;
+
+ tctrl_request(sc, &req);
}
void
-tctrl_process_response(struct tctrl_softc *sc)
+tctrl_request(struct tctrl_softc *sc, struct tctrl_req *req)
{
- switch (sc->sc_op) {
- case TS102_OP_RD_EXT_STATUS: {
- unsigned int status = sc->sc_ext_status;
- sc->sc_ext_status = sc->sc_rspbuf[0] * 256 + sc->sc_rspbuf[1];
- status ^= sc->sc_ext_status;
- if (status & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE) {
- printf("%s: main power %s\n", sc->sc_dev.dv_xname,
- (sc->sc_ext_status & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE) ?
- "restored" : "removed");
-
- /* XXX reset video */
- sc->sc_video_accel = 0;
- }
-#if 0
- if (status & TS102_EXT_STATUS_LID_DOWN) {
- printf("%s: lid %s\n", sc->sc_dev.dv_xname,
- (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) ?
- "closed" : "opened");
- }
-#endif
- break;
+ int s;
+
+ while (sc->sc_wantdata != 0) {
+ DELAY(1);
}
- case TS102_OP_RD_EVENT_STATUS: {
- unsigned int v = sc->sc_rspbuf[0] * 256 + sc->sc_rspbuf[1];
- if (v & TS102_EVENT_STATUS_SHUTDOWN_REQUEST) {
- printf("%s: SHUTDOWN REQUEST!\n", sc->sc_dev.dv_xname);
- }
-#if 0
-/* Obviously status change */
- if (v & TS102_EVENT_STATUS_VERY_LOW_POWER_WARNING) {
- printf("%s: VERY LOW POWER WARNING!\n", sc->sc_dev.dv_xname);
- }
-#endif
- if (v & TS102_EVENT_STATUS_LOW_POWER_WARNING) {
- printf("%s: LOW POWER WARNING!\n", sc->sc_dev.dv_xname);
- }
- if (v & TS102_EVENT_STATUS_DC_STATUS_CHANGE) {
- sc->sc_pending |= TCTRL_SEND_RD_EXT_STATUS;
- }
- if (v & TS102_EVENT_STATUS_LID_STATUS_CHANGE) {
- sc->sc_pending |= TCTRL_SEND_RD_EXT_STATUS;
- sc->sc_pending |= TCTRL_SEND_BITPORT;
- }
- break;
+
+ s = splhigh();
+ sc->sc_flags |= TCTRL_SEND_REQUEST;
+ bcopy(req->cmdbuf, sc->sc_cmdbuf, req->cmdlen);
+ sc->sc_wantdata = 1;
+ sc->sc_rsplen = req->rsplen;
+ sc->sc_cmdlen = req->cmdlen;
+ sc->sc_cmdoff = sc->sc_rspoff = 0;
+
+ do {
+ tctrl_intr(sc);
+ } while (sc->sc_state != TCTRL_IDLE);
+
+ sc->sc_wantdata = 0; /* just in case... */
+ bcopy(sc->sc_rspbuf, req->rspbuf, sc->sc_rsplen);
+ splx(s);
+}
+
+void
+tctrl_write_data(sc, v)
+ struct tctrl_softc *sc;
+ u_int8_t v;
+{
+ unsigned int i;
+
+ for (i = 0; i < 100; i++) {
+ if (sc->sc_regs->stat & TS102_UCTRL_STS_TXNF_STA)
+ break;
}
- case TS102_OP_CTL_BITPORT:
- sc->sc_bitport = (sc->sc_rspbuf[0] & sc->sc_cmdbuf[1]) ^ sc->sc_cmdbuf[2];
- break;
- case TS102_OP_CTL_TFT_BRIGHTNESS:
- sc->sc_brightness = sc->sc_rspbuf[0];
- default:
- break;
+ sc->sc_regs->data = v;
+}
+
+u_int8_t
+tctrl_read_data(sc)
+ struct tctrl_softc *sc;
+{
+ unsigned int i, v;
+
+ for (i = 0; i < 100000; i++) {
+ if (sc->sc_regs->stat & TS102_UCTRL_STS_RXNE_STA)
+ break;
+ DELAY(1);
}
+
+ v = sc->sc_regs->data;
+ sc->sc_regs->stat = TS102_UCTRL_STS_RXNE_STA;
+ return v;
}
+/*
+ * External interfaces, used by the display and pcmcia drivers, as well
+ * as the powerdown code.
+ */
+
void
tadpole_powerdown(void)
{
struct tctrl_softc *sc;
- int i, s;
+ struct tctrl_req req;
if (tctrl_cd.cd_devs == NULL
|| tctrl_cd.cd_ndevs == 0
@@ -472,21 +610,18 @@ tadpole_powerdown(void)
return;
}
- sc = (struct tctrl_softc *) tctrl_cd.cd_devs[0];
- s = splhigh();
- sc->sc_pending |= TCTRL_SEND_POWEROFF;
- for (i = 0; i < 10000; i++) {
- tctrl_intr(sc);
- DELAY(1);
- }
- splx(s);
+ sc = (struct tctrl_softc *)tctrl_cd.cd_devs[0];
+ req.cmdbuf[0] = TS102_OP_ADMIN_POWER_OFF;
+ req.cmdlen = 1;
+ req.rsplen = 1;
+
+ tctrl_request(sc, &req);
}
void
tadpole_set_brightness(int value)
{
struct tctrl_softc *sc;
- int s;
if (tctrl_cd.cd_devs == NULL
|| tctrl_cd.cd_ndevs == 0
@@ -494,14 +629,9 @@ tadpole_set_brightness(int value)
return;
}
- sc = (struct tctrl_softc *) tctrl_cd.cd_devs[0];
- s = splhigh();
- if (value != sc->sc_brightness) {
- sc->sc_brightness = value;
- sc->sc_pending |= TCTRL_SEND_BRIGHTNESS;
- tctrl_intr(sc);
- }
- splx(s);
+ sc = (struct tctrl_softc *)tctrl_cd.cd_devs[0];
+ if (value != sc->sc_brightness)
+ tctrl_brightness(sc, 0, value);
}
int
@@ -515,7 +645,7 @@ tadpole_get_brightness()
return 0;
}
- sc = (struct tctrl_softc *) tctrl_cd.cd_devs[0];
+ sc = (struct tctrl_softc *)tctrl_cd.cd_devs[0];
return sc->sc_brightness;
}
@@ -523,7 +653,6 @@ void
tadpole_set_video(int enabled)
{
struct tctrl_softc *sc;
- int s;
if (tctrl_cd.cd_devs == NULL
|| tctrl_cd.cd_ndevs == 0
@@ -531,21 +660,16 @@ tadpole_set_video(int enabled)
return;
}
- sc = (struct tctrl_softc *) tctrl_cd.cd_devs[0];
- s = splhigh();
+ sc = (struct tctrl_softc *)tctrl_cd.cd_devs[0];
if (sc->sc_tft_on ^ enabled) {
sc->sc_tft_on = enabled;
- if (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) {
- splx(s);
- return;
- }
- sc->sc_pending |= TCTRL_SEND_BITPORT;
- tctrl_intr(sc);
+ /* nothing to do if the lid is down */
+ if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) == 0)
+ tctrl_tft(sc);
}
- splx(s);
}
-unsigned int
+u_int
tadpole_get_video()
{
struct tctrl_softc *sc;
@@ -557,44 +681,30 @@ tadpole_get_video()
return 0;
}
- sc = (struct tctrl_softc *) tctrl_cd.cd_devs[0];
- status = 0;
-
- if (sc->sc_tft_on)
- status |= TV_ON;
- if (sc->sc_video_accel)
- status |= TV_ACCEL;
+ sc = (struct tctrl_softc *)tctrl_cd.cd_devs[0];
+ status = sc->sc_tft_on ? TV_ON : 0;
return status;
}
void
-tctrl_write_data(sc, v)
- struct tctrl_softc *sc;
- u_int8_t v;
+tadpole_set_pcmcia(int slot, int enabled)
{
- unsigned int i;
-
- for (i = 0; i < 100; i++) {
- if (sc->sc_regs->stat & TS102_UCTRL_STS_TXNF_STA)
- break;
- }
- sc->sc_regs->data = v;
-}
-
-u_int8_t
-tctrl_read_data(sc)
struct tctrl_softc *sc;
-{
- unsigned int i, v;
+ int mask;
- for (i = 0; i < 100000; i++) {
- if (sc->sc_regs->stat & TS102_UCTRL_STS_RXNE_STA)
- break;
- DELAY(1);
+ if (tctrl_cd.cd_devs == NULL
+ || tctrl_cd.cd_ndevs == 0
+ || tctrl_cd.cd_devs[0] == NULL) {
+ return;
}
- v = sc->sc_regs->data;
- sc->sc_regs->stat = TS102_UCTRL_STS_RXNE_STA;
- return v;
+ sc = (struct tctrl_softc *)tctrl_cd.cd_devs[0];
+ mask = 1 << slot;
+ enabled = enabled ? mask : 0;
+ if ((sc->sc_pcmcia_on ^ enabled) & mask) {
+ sc->sc_pcmcia_on ^= mask;
+ tctrl_lcd(sc, ~TS102_LCD_PCMCIA_ACTIVE,
+ sc->sc_pcmcia_on ? TS102_LCD_PCMCIA_ACTIVE : 0);
+ }
}
diff --git a/sys/arch/sparc/dev/tctrlvar.h b/sys/arch/sparc/dev/tctrlvar.h
index 984cbe9dbc2..dd742a6f127 100644
--- a/sys/arch/sparc/dev/tctrlvar.h
+++ b/sys/arch/sparc/dev/tctrlvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tctrlvar.h,v 1.3 2004/05/10 09:05:52 miod Exp $ */
+/* $OpenBSD: tctrlvar.h,v 1.4 2005/03/29 11:36:41 miod Exp $ */
/* $NetBSD: tctrlvar.h,v 1.1 1999/08/09 18:39:58 matt Exp $ */
/*-
@@ -39,14 +39,14 @@
#ifndef _SPARC_DEV_TCTRLVAR_H
#define _SPARC_DEV_TCTRLVAR_H
-void tadpole_powerdown(void);
-int tadpole_get_brightness(void);
-unsigned int tadpole_get_video(void);
-void tadpole_set_brightness(int);
-void tadpole_set_video(int);
+int tadpole_get_brightness(void);
+u_int tadpole_get_video(void);
+void tadpole_powerdown(void);
+void tadpole_set_brightness(int);
+void tadpole_set_pcmcia(int, int);
+void tadpole_set_video(int);
/* Values for get_video */
#define TV_ON 0x01
-#define TV_ACCEL 0x02
#endif /* _SPARC_DEV_TCTRLVAR_H */