diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2005-03-29 11:36:42 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2005-03-29 11:36:42 +0000 |
commit | 7308b7b3256cb8f493d16e07a31eedb2e7385aef (patch) | |
tree | 326afc8ed9ed0e512ec291789c6cc49f4becc395 /sys/arch/sparc/dev | |
parent | 05bdd540913abf6879f0a971901b3ec6740eb6a2 (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.c | 600 | ||||
-rw-r--r-- | sys/arch/sparc/dev/tctrlvar.h | 14 |
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 */ |