Home | History | Annotate | Line # | Download | only in dev
tctrl.c revision 1.2
      1  1.2  matt /*	$NetBSD: tctrl.c,v 1.2 1999/08/11 00:46:06 matt Exp $	*/
      2  1.1  matt 
      3  1.1  matt /*-
      4  1.1  matt  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  1.1  matt  * All rights reserved.
      6  1.1  matt  *
      7  1.1  matt  * This code is derived from software contributed to The NetBSD Foundation
      8  1.1  matt  * by Matt Thomas.
      9  1.1  matt  *
     10  1.1  matt  * Redistribution and use in source and binary forms, with or without
     11  1.1  matt  * modification, are permitted provided that the following conditions
     12  1.1  matt  * are met:
     13  1.1  matt  * 1. Redistributions of source code must retain the above copyright
     14  1.1  matt  *    notice, this list of conditions and the following disclaimer.
     15  1.1  matt  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.1  matt  *    notice, this list of conditions and the following disclaimer in the
     17  1.1  matt  *    documentation and/or other materials provided with the distribution.
     18  1.1  matt  * 3. All advertising materials mentioning features or use of this software
     19  1.1  matt  *    must display the following acknowledgement:
     20  1.1  matt  *        This product includes software developed by the NetBSD
     21  1.1  matt  *        Foundation, Inc. and its contributors.
     22  1.1  matt  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.1  matt  *    contributors may be used to endorse or promote products derived
     24  1.1  matt  *    from this software without specific prior written permission.
     25  1.1  matt  *
     26  1.1  matt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.1  matt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.1  matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.1  matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.1  matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.1  matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.1  matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.1  matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.1  matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.1  matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.1  matt  * POSSIBILITY OF SUCH DAMAGE.
     37  1.1  matt  */
     38  1.1  matt 
     39  1.1  matt #include <sys/param.h>
     40  1.1  matt #include <sys/systm.h>
     41  1.1  matt #include <sys/ioctl.h>
     42  1.1  matt #include <sys/select.h>
     43  1.1  matt #include <sys/tty.h>
     44  1.1  matt #include <sys/proc.h>
     45  1.1  matt #include <sys/user.h>
     46  1.1  matt #include <sys/conf.h>
     47  1.1  matt #include <sys/file.h>
     48  1.1  matt #include <sys/uio.h>
     49  1.1  matt #include <sys/kernel.h>
     50  1.1  matt #include <sys/syslog.h>
     51  1.1  matt #include <sys/types.h>
     52  1.1  matt #include <sys/device.h>
     53  1.1  matt 
     54  1.1  matt #include <machine/autoconf.h>
     55  1.1  matt #include <machine/cpu.h>
     56  1.1  matt #include <machine/bus.h>
     57  1.1  matt 
     58  1.1  matt #include <sparc/dev/ts102reg.h>
     59  1.1  matt #include <sparc/dev/tctrlvar.h>
     60  1.1  matt 
     61  1.1  matt static const char *tctrl_ext_statuses[16] = {
     62  1.1  matt 	"main power available",
     63  1.1  matt 	"internal battery attached",
     64  1.1  matt 	"external battery attached",
     65  1.1  matt 	"external VGA attached",
     66  1.1  matt 	"external keyboard attached",
     67  1.1  matt 	"external mouse attached",
     68  1.1  matt 	"lid down",
     69  1.1  matt 	"internal battery charging",
     70  1.1  matt 	"external battery charging",
     71  1.1  matt 	"internal battery discharging",
     72  1.1  matt 	"external battery discharging",
     73  1.1  matt };
     74  1.1  matt 
     75  1.1  matt struct tctrl_softc {
     76  1.1  matt 	struct device sc_dev;
     77  1.1  matt 	bus_space_tag_t sc_memt;
     78  1.1  matt 	bus_space_handle_t sc_memh;
     79  1.1  matt 	unsigned int sc_junk;
     80  1.1  matt 	unsigned int sc_ext_status;
     81  1.1  matt 	unsigned int sc_pending;
     82  1.1  matt #define	TCTRL_SEND_BITPORT		0x0001
     83  1.1  matt #define	TCTRL_SEND_POWEROFF		0x0002
     84  1.1  matt #define	TCTRL_SEND_RD_EXT_STATUS	0x0004
     85  1.1  matt #define	TCTRL_SEND_RD_EVENT_STATUS	0x0008
     86  1.2  matt #define	TCTRL_SEND_BITPORT_NOP		0x0010
     87  1.1  matt 	enum { TCTRL_IDLE, TCTRL_ARGS,
     88  1.1  matt 		TCTRL_ACK, TCTRL_DATA } sc_state;
     89  1.1  matt 	u_int8_t sc_cmdbuf[16];
     90  1.1  matt 	u_int8_t sc_rspbuf[16];
     91  1.1  matt 	u_int8_t sc_bitport;
     92  1.1  matt 	u_int8_t sc_tft_on;
     93  1.1  matt 	u_int8_t sc_op;
     94  1.1  matt 	u_int8_t sc_cmdoff;
     95  1.1  matt 	u_int8_t sc_cmdlen;
     96  1.1  matt 	u_int8_t sc_rspoff;
     97  1.1  matt 	u_int8_t sc_rsplen;
     98  1.1  matt 
     99  1.1  matt 	struct evcnt sc_intrcnt;	/* interrupt counting */
    100  1.1  matt };
    101  1.1  matt 
    102  1.1  matt static int tctrl_match(struct device *parent, struct cfdata *cf, void *aux);
    103  1.1  matt static void tctrl_attach(struct device *parent, struct device *self, void *aux);
    104  1.1  matt 
    105  1.1  matt static void tctrl_write(struct tctrl_softc *sc, bus_size_t off, u_int8_t v);
    106  1.1  matt static u_int8_t tctrl_read(struct tctrl_softc *sc, bus_size_t off);
    107  1.1  matt static void tctrl_write_data(struct tctrl_softc *sc, u_int8_t v);
    108  1.1  matt static u_int8_t tctrl_read_data(struct tctrl_softc *sc);
    109  1.1  matt static int tctrl_intr(void *arg);
    110  1.2  matt static void tctrl_setup_bitport(struct tctrl_softc *sc, int nop);
    111  1.1  matt static void tctrl_process_response(struct tctrl_softc *sc);
    112  1.1  matt 
    113  1.1  matt struct cfattach tctrl_ca = {
    114  1.1  matt 	sizeof(struct tctrl_softc), tctrl_match, tctrl_attach
    115  1.1  matt };
    116  1.1  matt 
    117  1.1  matt extern struct cfdriver tctrl_cd;
    118  1.1  matt 
    119  1.1  matt static int
    120  1.1  matt tctrl_match(struct device *parent, struct cfdata *cf, void *aux)
    121  1.1  matt {
    122  1.1  matt 	union obio_attach_args *uoba = aux;
    123  1.1  matt 	struct sbus_attach_args *sa = &uoba->uoba_sbus;
    124  1.1  matt 
    125  1.1  matt 	if (uoba->uoba_isobio4 != 0) {
    126  1.1  matt 		return (0);
    127  1.1  matt 	}
    128  1.1  matt 
    129  1.1  matt 	/* Tadpole 3GX/3GS uses "uctrl" for the Tadpole Microcontroller
    130  1.1  matt 	 * (who's interface is off the TS102 PCMCIA controller but there
    131  1.1  matt 	 * exists a OpenProm for microcontroller interface).
    132  1.1  matt 	 */
    133  1.1  matt 	return strcmp("uctrl", sa->sa_name) == 0;
    134  1.1  matt }
    135  1.1  matt 
    136  1.1  matt static void
    137  1.1  matt tctrl_attach(struct device *parent, struct device *self, void *aux)
    138  1.1  matt {
    139  1.1  matt 	struct tctrl_softc *sc = (void *)self;
    140  1.1  matt 	union obio_attach_args *uoba = aux;
    141  1.1  matt 	struct sbus_attach_args *sa = &uoba->uoba_sbus;
    142  1.2  matt 	unsigned int i, v;
    143  1.2  matt #if 0
    144  1.1  matt 	unsigned int ack, msb, lsb;
    145  1.2  matt #endif
    146  1.1  matt 
    147  1.1  matt 	/* We're living on a sbus slot that looks like an obio that
    148  1.1  matt 	 * looks like an sbus slot.
    149  1.1  matt 	 */
    150  1.1  matt 	sc->sc_memt = sa->sa_bustag;
    151  1.1  matt 	if (sbus_bus_map(sc->sc_memt, sa->sa_slot,
    152  1.1  matt 			 sa->sa_offset - TS102_REG_UCTRL_INT, sa->sa_size,
    153  1.1  matt 			 BUS_SPACE_MAP_LINEAR, 0,
    154  1.1  matt 			 &sc->sc_memh) != 0) {
    155  1.1  matt 		printf(": can't map registers\n");
    156  1.1  matt 		return;
    157  1.1  matt 	}
    158  1.1  matt 
    159  1.2  matt 	printf("\n");
    160  1.2  matt 
    161  1.1  matt 	sc->sc_tft_on = 1;
    162  1.2  matt 
    163  1.1  matt 	/* clear any pending data.
    164  1.1  matt 	 */
    165  1.1  matt 	for (i = 0; i < 10000; i++) {
    166  1.2  matt 		if ((TS102_UCTRL_STS_RXNE_STA & tctrl_read(sc, TS102_REG_UCTRL_STS)) == 0) {
    167  1.1  matt 			break;
    168  1.1  matt 		}
    169  1.1  matt 		v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
    170  1.2  matt 		tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
    171  1.1  matt 	}
    172  1.1  matt 
    173  1.2  matt 	(void)bus_intr_establish(sc->sc_memt, sa->sa_pri, 0, tctrl_intr, sc);
    174  1.2  matt 	evcnt_attach(&sc->sc_dev, "intr", &sc->sc_intrcnt);
    175  1.2  matt 
    176  1.2  matt 	/* See what the external status is
    177  1.2  matt 	 */
    178  1.2  matt 	sc->sc_pending |= TCTRL_SEND_RD_EXT_STATUS;
    179  1.2  matt 	do {
    180  1.2  matt 		tctrl_intr(sc);
    181  1.2  matt 	} while (sc->sc_state != TCTRL_IDLE);
    182  1.1  matt 
    183  1.2  matt 	if (sc->sc_ext_status != 0) {
    184  1.2  matt 		const char *sep;
    185  1.1  matt 
    186  1.1  matt 		printf("%s: ", sc->sc_dev.dv_xname);
    187  1.2  matt 		v = sc->sc_ext_status;
    188  1.1  matt 		for (i = 0, sep = ""; v != 0; i++, v >>= 1) {
    189  1.1  matt 			if (v & 1) {
    190  1.1  matt 				printf("%s%s", sep, tctrl_ext_statuses[i]);
    191  1.1  matt 				sep = ", ";
    192  1.1  matt 			}
    193  1.1  matt 		}
    194  1.1  matt 		printf("\n");
    195  1.1  matt 	}
    196  1.1  matt 
    197  1.2  matt 	/* Get a current of the control bitport;
    198  1.2  matt 	 */
    199  1.2  matt 	sc->sc_pending |= TCTRL_SEND_BITPORT_NOP;
    200  1.2  matt 	do {
    201  1.2  matt 		tctrl_intr(sc);
    202  1.2  matt 	} while (sc->sc_state != TCTRL_IDLE);
    203  1.1  matt 
    204  1.2  matt 	tctrl_write(sc, TS102_REG_UCTRL_INT,
    205  1.2  matt 		    TS102_UCTRL_INT_RXNE_REQ|TS102_UCTRL_INT_RXNE_MSK);
    206  1.1  matt 
    207  1.1  matt }
    208  1.1  matt 
    209  1.1  matt static int
    210  1.1  matt tctrl_intr(void *arg)
    211  1.1  matt {
    212  1.1  matt 	struct tctrl_softc *sc = arg;
    213  1.1  matt 	unsigned int v, d;
    214  1.1  matt 	int progress = 0;
    215  1.1  matt 
    216  1.1  matt     again:
    217  1.1  matt 	/* find out the cause(s) of the interrupt */
    218  1.1  matt 	v = tctrl_read(sc, TS102_REG_UCTRL_STS);
    219  1.1  matt 
    220  1.1  matt 	/* clear the cause(s) of the interrupt */
    221  1.1  matt 	tctrl_write(sc, TS102_REG_UCTRL_STS, v);
    222  1.1  matt 
    223  1.2  matt 	v &= ~(TS102_UCTRL_STS_RXO_STA|TS102_UCTRL_STS_TXE_STA);
    224  1.1  matt 	if (sc->sc_cmdoff >= sc->sc_cmdlen) {
    225  1.2  matt 		v &= ~TS102_UCTRL_STS_TXNF_STA;
    226  1.1  matt 	}
    227  1.1  matt 	if ((v == 0) && (sc->sc_pending == 0 || sc->sc_state != TCTRL_IDLE)) {
    228  1.1  matt 		return progress;
    229  1.1  matt 	}
    230  1.1  matt 
    231  1.1  matt 	progress = 1;
    232  1.2  matt 	if (v & TS102_UCTRL_STS_RXNE_STA) {
    233  1.1  matt 		d = tctrl_read_data(sc);
    234  1.1  matt 		switch (sc->sc_state) {
    235  1.1  matt 		case TCTRL_IDLE:
    236  1.2  matt 			if (d == 0xfa) {
    237  1.1  matt 				sc->sc_pending |= TCTRL_SEND_RD_EVENT_STATUS;
    238  1.2  matt 			} else {
    239  1.2  matt 				printf("%s: (op=0x%02x): unexpected data (0x%02x)\n",
    240  1.2  matt 					sc->sc_dev.dv_xname, sc->sc_op, d);
    241  1.1  matt 			}
    242  1.2  matt 			goto again;
    243  1.1  matt 		case TCTRL_ACK:
    244  1.1  matt 			if (d != 0xfe) {
    245  1.2  matt 				printf("%s: (op=0x%02x): unexpected ack value (0x%02x)\n",
    246  1.1  matt 					sc->sc_dev.dv_xname, sc->sc_op, d);
    247  1.1  matt 			}
    248  1.2  matt #if 0
    249  1.2  matt 			printf(" ack=0x%02x", d);
    250  1.2  matt #endif
    251  1.2  matt 			sc->sc_rsplen--;
    252  1.2  matt 			sc->sc_rspoff = 0;
    253  1.1  matt 			sc->sc_state = sc->sc_rsplen ? TCTRL_DATA : TCTRL_IDLE;
    254  1.2  matt #if 0
    255  1.2  matt 			if (sc->sc_rsplen > 0) {
    256  1.2  matt 				printf(" [data(%u)]", sc->sc_rsplen);
    257  1.2  matt 			} else {
    258  1.2  matt 				printf(" [idle]\n");
    259  1.2  matt 			}
    260  1.2  matt #endif
    261  1.2  matt 			goto again;
    262  1.1  matt 		case TCTRL_DATA:
    263  1.1  matt 			sc->sc_rspbuf[sc->sc_rspoff++] = d;
    264  1.2  matt #if 0
    265  1.2  matt 			printf(" [%d]=0x%02x", sc->sc_rspoff-1, d);
    266  1.2  matt #endif
    267  1.1  matt 			if (sc->sc_rspoff == sc->sc_rsplen) {
    268  1.2  matt #if 0
    269  1.2  matt 				printf(" [idle]\n");
    270  1.2  matt #endif
    271  1.1  matt 				sc->sc_state = TCTRL_IDLE;
    272  1.2  matt 				tctrl_process_response(sc);
    273  1.1  matt 			}
    274  1.2  matt 			goto again;
    275  1.1  matt 		default:
    276  1.1  matt 			printf("%s: (op=0x%02x): unexpected data (0x%02x) in state %d\n",
    277  1.1  matt 			       sc->sc_dev.dv_xname, sc->sc_op, d, sc->sc_state);
    278  1.2  matt 			goto again;
    279  1.1  matt 		}
    280  1.1  matt 	}
    281  1.1  matt 	if (sc->sc_state == TCTRL_IDLE) {
    282  1.1  matt 		sc->sc_cmdoff = 0;
    283  1.2  matt 		sc->sc_cmdlen = 0;
    284  1.1  matt 		if (sc->sc_pending & TCTRL_SEND_POWEROFF) {
    285  1.1  matt 			sc->sc_pending &= ~TCTRL_SEND_POWEROFF;
    286  1.1  matt 			sc->sc_cmdbuf[0] = TS102_OP_ADMIN_POWER_OFF;
    287  1.1  matt 			sc->sc_cmdlen = 1;
    288  1.1  matt 			sc->sc_rsplen = 0;
    289  1.1  matt 		} else if (sc->sc_pending & TCTRL_SEND_RD_EVENT_STATUS) {
    290  1.1  matt 			sc->sc_pending &= ~TCTRL_SEND_RD_EVENT_STATUS;
    291  1.1  matt 			sc->sc_cmdbuf[0] = TS102_OP_RD_EVENT_STATUS;
    292  1.1  matt 			sc->sc_cmdlen = 1;
    293  1.1  matt 			sc->sc_rsplen = 3;
    294  1.1  matt 		} else if (sc->sc_pending & TCTRL_SEND_RD_EXT_STATUS) {
    295  1.1  matt 			sc->sc_pending &= ~TCTRL_SEND_RD_EXT_STATUS;
    296  1.1  matt 			sc->sc_cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
    297  1.1  matt 			sc->sc_cmdlen = 1;
    298  1.1  matt 			sc->sc_rsplen = 3;
    299  1.2  matt 		} else if (sc->sc_pending & TCTRL_SEND_BITPORT_NOP) {
    300  1.2  matt 			sc->sc_pending &= ~TCTRL_SEND_BITPORT_NOP;
    301  1.2  matt 			tctrl_setup_bitport(sc, 1);
    302  1.1  matt 		} else if (sc->sc_pending & TCTRL_SEND_BITPORT) {
    303  1.1  matt 			sc->sc_pending &= ~TCTRL_SEND_BITPORT;
    304  1.2  matt 			tctrl_setup_bitport(sc, 0);
    305  1.1  matt 		}
    306  1.1  matt 		if (sc->sc_cmdlen > 0) {
    307  1.1  matt 			tctrl_write(sc, TS102_REG_UCTRL_INT,
    308  1.1  matt 				tctrl_read(sc, TS102_REG_UCTRL_INT)
    309  1.1  matt 				|TS102_UCTRL_INT_TXNF_MSK
    310  1.1  matt 				|TS102_UCTRL_INT_TXNF_REQ);
    311  1.1  matt 			v = tctrl_read(sc, TS102_REG_UCTRL_STS);
    312  1.1  matt 		}
    313  1.1  matt 	}
    314  1.2  matt 	if ((sc->sc_cmdoff < sc->sc_cmdlen) && (v & TS102_UCTRL_STS_TXNF_STA)) {
    315  1.1  matt 		tctrl_write_data(sc, sc->sc_cmdbuf[sc->sc_cmdoff++]);
    316  1.2  matt #if 0
    317  1.2  matt 		if (sc->sc_cmdoff == 1) {
    318  1.2  matt 			printf("%s: op=0x%02x(l=%u)", sc->sc_dev.dv_xname,
    319  1.2  matt 				sc->sc_cmdbuf[0], sc->sc_rsplen);
    320  1.2  matt 		} else {
    321  1.2  matt 			printf(" [%d]=0x%02x", sc->sc_cmdoff-1,
    322  1.2  matt 				sc->sc_cmdbuf[sc->sc_cmdoff-1]);
    323  1.2  matt 		}
    324  1.2  matt #endif
    325  1.1  matt 		if (sc->sc_cmdoff == sc->sc_cmdlen) {
    326  1.1  matt 			sc->sc_state = sc->sc_rsplen ? TCTRL_ACK : TCTRL_IDLE;
    327  1.2  matt #if 0
    328  1.2  matt 			printf(" %s", sc->sc_rsplen ? "[ack]" : "[idle]\n");
    329  1.2  matt #endif
    330  1.2  matt 			if (sc->sc_cmdoff == 1) {
    331  1.2  matt 				sc->sc_op = sc->sc_cmdbuf[0];
    332  1.2  matt 			}
    333  1.1  matt 			tctrl_write(sc, TS102_REG_UCTRL_INT,
    334  1.1  matt 				tctrl_read(sc, TS102_REG_UCTRL_INT)
    335  1.1  matt 				& (~TS102_UCTRL_INT_TXNF_MSK
    336  1.1  matt 				   |TS102_UCTRL_INT_TXNF_REQ));
    337  1.1  matt 		} else if (sc->sc_state == TCTRL_IDLE) {
    338  1.1  matt 			sc->sc_op = sc->sc_cmdbuf[0];
    339  1.1  matt 			sc->sc_state = TCTRL_ARGS;
    340  1.2  matt #if 0
    341  1.2  matt 			printf(" [args]");
    342  1.2  matt #endif
    343  1.1  matt 		}
    344  1.1  matt 	}
    345  1.1  matt 	goto again;
    346  1.1  matt }
    347  1.1  matt 
    348  1.1  matt static void
    349  1.2  matt tctrl_setup_bitport(struct tctrl_softc *sc, int nop)
    350  1.1  matt {
    351  1.2  matt 	if (nop) {
    352  1.2  matt 		sc->sc_cmdbuf[0] = TS102_OP_CTL_BITPORT;
    353  1.2  matt 		sc->sc_cmdbuf[1] = 0xff;
    354  1.1  matt 		sc->sc_cmdbuf[2] = 0;
    355  1.2  matt 		sc->sc_cmdlen = 3;
    356  1.2  matt 		sc->sc_rsplen = 2;
    357  1.1  matt 	} else {
    358  1.2  matt 		if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
    359  1.2  matt 		    || (!sc->sc_tft_on)) {
    360  1.2  matt 			sc->sc_cmdbuf[2] = TS102_BITPORT_TFTPWR;
    361  1.2  matt 		} else {
    362  1.2  matt 			sc->sc_cmdbuf[2] = 0;
    363  1.2  matt 		}
    364  1.2  matt 		sc->sc_cmdbuf[0] = TS102_OP_CTL_BITPORT;
    365  1.2  matt 		sc->sc_cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
    366  1.2  matt 		sc->sc_cmdlen = 3;
    367  1.2  matt 		sc->sc_rsplen = 2;
    368  1.1  matt 	}
    369  1.1  matt }
    370  1.1  matt 
    371  1.1  matt static void
    372  1.1  matt tctrl_process_response(struct tctrl_softc *sc)
    373  1.1  matt {
    374  1.1  matt 	switch (sc->sc_op) {
    375  1.1  matt 	case TS102_OP_RD_EXT_STATUS: {
    376  1.1  matt 		sc->sc_ext_status = sc->sc_rspbuf[0] * 256 + sc->sc_rspbuf[1];
    377  1.1  matt 		break;
    378  1.1  matt 	}
    379  1.1  matt 	case TS102_OP_RD_EVENT_STATUS: {
    380  1.1  matt 		unsigned int v = sc->sc_rspbuf[0] * 256 + sc->sc_rspbuf[1];
    381  1.1  matt 		if (v & TS102_EVENT_STATUS_SHUTDOWN_REQUEST) {
    382  1.1  matt 			printf("%s: SHUTDOWN REQUEST!\n", sc->sc_dev.dv_xname);
    383  1.1  matt 		}
    384  1.1  matt 		if (v & TS102_EVENT_STATUS_VERY_LOW_POWER_WARNING) {
    385  1.1  matt 			printf("%s: VERY LOW POWER WARNING!\n", sc->sc_dev.dv_xname);
    386  1.1  matt 		}
    387  1.1  matt 		if (v & TS102_EVENT_STATUS_LOW_POWER_WARNING) {
    388  1.1  matt 			printf("%s: LOW POWER WARNING!\n", sc->sc_dev.dv_xname);
    389  1.1  matt 		}
    390  1.1  matt 		if (v & TS102_EVENT_STATUS_DC_STATUS_CHANGE) {
    391  1.1  matt 			sc->sc_pending |= TCTRL_SEND_RD_EXT_STATUS;
    392  1.1  matt 			printf("%s: main power %s\n", sc->sc_dev.dv_xname,
    393  1.1  matt 			       (sc->sc_ext_status & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE) ? "removed" : "restored");
    394  1.1  matt 		}
    395  1.1  matt 		if (v & TS102_EVENT_STATUS_LID_STATUS_CHANGE) {
    396  1.1  matt 			sc->sc_pending |= TCTRL_SEND_RD_EXT_STATUS;
    397  1.1  matt 			sc->sc_pending |= TCTRL_SEND_BITPORT;
    398  1.2  matt #if 0
    399  1.2  matt 			printf("%s: lid %s\n", sc->sc_dev.dv_xname,
    400  1.2  matt 			       (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) ? "opened" : "closed");
    401  1.2  matt #endif
    402  1.1  matt 		}
    403  1.1  matt 		break;
    404  1.1  matt 	}
    405  1.1  matt 	case TS102_OP_CTL_BITPORT:
    406  1.2  matt 		sc->sc_bitport = (sc->sc_rspbuf[0] & sc->sc_cmdbuf[1]) ^ sc->sc_cmdbuf[2];
    407  1.1  matt 		break;
    408  1.1  matt 	default:
    409  1.1  matt 		break;
    410  1.1  matt 	}
    411  1.1  matt }
    412  1.1  matt 
    413  1.1  matt void
    414  1.1  matt tadpole_powerdown(void)
    415  1.1  matt {
    416  1.1  matt 	struct tctrl_softc *sc;
    417  1.1  matt 	int i, s;
    418  1.1  matt 
    419  1.1  matt 	if (tctrl_cd.cd_devs == NULL
    420  1.1  matt 	    || tctrl_cd.cd_ndevs == 0
    421  1.1  matt 	    || tctrl_cd.cd_devs[0] == NULL) {
    422  1.1  matt 		return;
    423  1.1  matt 	}
    424  1.1  matt 
    425  1.1  matt 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[0];
    426  1.1  matt 	s = splhigh();
    427  1.1  matt 	sc->sc_pending |= TCTRL_SEND_POWEROFF;
    428  1.1  matt 	for (i = 0; i < 10000; i++) {
    429  1.1  matt 		tctrl_intr(sc);
    430  1.1  matt 		DELAY(1);
    431  1.1  matt 	}
    432  1.1  matt 	splx(s);
    433  1.1  matt }
    434  1.1  matt 
    435  1.1  matt void
    436  1.1  matt tadpole_set_video(int enabled)
    437  1.1  matt {
    438  1.1  matt 	struct tctrl_softc *sc;
    439  1.1  matt 	int s;
    440  1.1  matt 
    441  1.1  matt 	if (tctrl_cd.cd_devs == NULL
    442  1.1  matt 	    || tctrl_cd.cd_ndevs == 0
    443  1.1  matt 	    || tctrl_cd.cd_devs[0] == NULL) {
    444  1.1  matt 		return;
    445  1.1  matt 	}
    446  1.1  matt 
    447  1.1  matt 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[0];
    448  1.1  matt 	s = splhigh();
    449  1.1  matt 	if ((sc->sc_tft_on && !enabled) || (!sc->sc_tft_on && enabled)) {
    450  1.1  matt 		sc->sc_tft_on = enabled;
    451  1.1  matt 		if (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) {
    452  1.1  matt 			splx(s);
    453  1.1  matt 			return;
    454  1.1  matt 		}
    455  1.1  matt 		sc->sc_pending |= TCTRL_SEND_BITPORT;
    456  1.1  matt 		tctrl_intr(sc);
    457  1.1  matt 	}
    458  1.1  matt 	splx(s);
    459  1.1  matt }
    460  1.1  matt 
    461  1.1  matt static void
    462  1.1  matt tctrl_write_data(struct tctrl_softc *sc, u_int8_t v)
    463  1.1  matt {
    464  1.1  matt 	unsigned int i;
    465  1.1  matt 	for (i = 0; i < 100; i++)  {
    466  1.2  matt 		if (TS102_UCTRL_STS_TXNF_STA & tctrl_read(sc, TS102_REG_UCTRL_STS))
    467  1.1  matt 			break;
    468  1.1  matt 	}
    469  1.1  matt 	tctrl_write(sc, TS102_REG_UCTRL_DATA, v);
    470  1.1  matt }
    471  1.1  matt 
    472  1.1  matt static u_int8_t
    473  1.1  matt tctrl_read_data(struct tctrl_softc *sc)
    474  1.1  matt {
    475  1.1  matt 	unsigned int i, v;
    476  1.1  matt 
    477  1.1  matt 	for (i = 0; i < 100000; i++) {
    478  1.2  matt 		if (TS102_UCTRL_STS_RXNE_STA & tctrl_read(sc, TS102_REG_UCTRL_STS))
    479  1.1  matt 			break;
    480  1.1  matt 		DELAY(1);
    481  1.1  matt 	}
    482  1.1  matt 
    483  1.1  matt 	v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
    484  1.2  matt 	tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
    485  1.1  matt 	return v;
    486  1.1  matt }
    487  1.1  matt 
    488  1.1  matt static u_int8_t
    489  1.1  matt tctrl_read(struct tctrl_softc *sc, bus_size_t off)
    490  1.1  matt {
    491  1.2  matt 	sc->sc_junk = bus_space_read_1(sc->sc_memt, sc->sc_memh, off);
    492  1.1  matt 	return sc->sc_junk;
    493  1.1  matt }
    494  1.1  matt 
    495  1.1  matt static void
    496  1.1  matt tctrl_write(struct tctrl_softc *sc, bus_size_t off, u_int8_t v)
    497  1.1  matt {
    498  1.1  matt 	sc->sc_junk = v;
    499  1.2  matt 	bus_space_write_1(sc->sc_memt, sc->sc_memh, off, v);
    500  1.1  matt }
    501