Home | History | Annotate | Line # | Download | only in dev
tctrl.c revision 1.13.6.2
      1  1.13.6.2  nathanw /*	$NetBSD: tctrl.c,v 1.13.6.2 2002/04/01 07:42:43 nathanw Exp $	*/
      2  1.13.6.2  nathanw 
      3  1.13.6.2  nathanw /*-
      4  1.13.6.2  nathanw  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  1.13.6.2  nathanw  * All rights reserved.
      6  1.13.6.2  nathanw  *
      7  1.13.6.2  nathanw  * This code is derived from software contributed to The NetBSD Foundation
      8  1.13.6.2  nathanw  * by Matt Thomas.
      9  1.13.6.2  nathanw  *
     10  1.13.6.2  nathanw  * Redistribution and use in source and binary forms, with or without
     11  1.13.6.2  nathanw  * modification, are permitted provided that the following conditions
     12  1.13.6.2  nathanw  * are met:
     13  1.13.6.2  nathanw  * 1. Redistributions of source code must retain the above copyright
     14  1.13.6.2  nathanw  *    notice, this list of conditions and the following disclaimer.
     15  1.13.6.2  nathanw  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.13.6.2  nathanw  *    notice, this list of conditions and the following disclaimer in the
     17  1.13.6.2  nathanw  *    documentation and/or other materials provided with the distribution.
     18  1.13.6.2  nathanw  * 3. All advertising materials mentioning features or use of this software
     19  1.13.6.2  nathanw  *    must display the following acknowledgement:
     20  1.13.6.2  nathanw  *        This product includes software developed by the NetBSD
     21  1.13.6.2  nathanw  *        Foundation, Inc. and its contributors.
     22  1.13.6.2  nathanw  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23  1.13.6.2  nathanw  *    contributors may be used to endorse or promote products derived
     24  1.13.6.2  nathanw  *    from this software without specific prior written permission.
     25  1.13.6.2  nathanw  *
     26  1.13.6.2  nathanw  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27  1.13.6.2  nathanw  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28  1.13.6.2  nathanw  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29  1.13.6.2  nathanw  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30  1.13.6.2  nathanw  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31  1.13.6.2  nathanw  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32  1.13.6.2  nathanw  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33  1.13.6.2  nathanw  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34  1.13.6.2  nathanw  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35  1.13.6.2  nathanw  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36  1.13.6.2  nathanw  * POSSIBILITY OF SUCH DAMAGE.
     37  1.13.6.2  nathanw  */
     38  1.13.6.2  nathanw 
     39  1.13.6.2  nathanw #include <sys/param.h>
     40  1.13.6.2  nathanw #include <sys/systm.h>
     41  1.13.6.2  nathanw #include <sys/callout.h>
     42  1.13.6.2  nathanw #include <sys/ioctl.h>
     43  1.13.6.2  nathanw #include <sys/select.h>
     44  1.13.6.2  nathanw #include <sys/tty.h>
     45  1.13.6.2  nathanw #include <sys/proc.h>
     46  1.13.6.2  nathanw #include <sys/user.h>
     47  1.13.6.2  nathanw #include <sys/conf.h>
     48  1.13.6.2  nathanw #include <sys/file.h>
     49  1.13.6.2  nathanw #include <sys/uio.h>
     50  1.13.6.2  nathanw #include <sys/kernel.h>
     51  1.13.6.2  nathanw #include <sys/syslog.h>
     52  1.13.6.2  nathanw #include <sys/types.h>
     53  1.13.6.2  nathanw #include <sys/device.h>
     54  1.13.6.2  nathanw #include <sys/envsys.h>
     55  1.13.6.2  nathanw #include <sys/poll.h>
     56  1.13.6.2  nathanw 
     57  1.13.6.2  nathanw #include <machine/apmvar.h>
     58  1.13.6.2  nathanw #include <machine/autoconf.h>
     59  1.13.6.2  nathanw #include <machine/bus.h>
     60  1.13.6.2  nathanw #include <machine/intr.h>
     61  1.13.6.2  nathanw #include <machine/tctrl.h>
     62  1.13.6.2  nathanw 
     63  1.13.6.2  nathanw #include <sparc/dev/ts102reg.h>
     64  1.13.6.2  nathanw #include <sparc/dev/tctrlvar.h>
     65  1.13.6.2  nathanw #include <sparc/sparc/auxiotwo.h>
     66  1.13.6.2  nathanw 
     67  1.13.6.2  nathanw cdev_decl(tctrl);
     68  1.13.6.2  nathanw 
     69  1.13.6.2  nathanw extern struct cfdriver tctrl_cd;
     70  1.13.6.2  nathanw 
     71  1.13.6.2  nathanw static const char *tctrl_ext_statuses[16] = {
     72  1.13.6.2  nathanw 	"main power available",
     73  1.13.6.2  nathanw 	"internal battery attached",
     74  1.13.6.2  nathanw 	"external battery attached",
     75  1.13.6.2  nathanw 	"external VGA attached",
     76  1.13.6.2  nathanw 	"external keyboard attached",
     77  1.13.6.2  nathanw 	"external mouse attached",
     78  1.13.6.2  nathanw 	"lid down",
     79  1.13.6.2  nathanw 	"internal battery charging",
     80  1.13.6.2  nathanw 	"external battery charging",
     81  1.13.6.2  nathanw 	"internal battery discharging",
     82  1.13.6.2  nathanw 	"external battery discharging",
     83  1.13.6.2  nathanw };
     84  1.13.6.2  nathanw 
     85  1.13.6.2  nathanw struct tctrl_softc {
     86  1.13.6.2  nathanw 	struct	device sc_dev;
     87  1.13.6.2  nathanw 	bus_space_tag_t	sc_memt;
     88  1.13.6.2  nathanw 	bus_space_handle_t	sc_memh;
     89  1.13.6.2  nathanw 	unsigned int	sc_junk;
     90  1.13.6.2  nathanw 	unsigned int	sc_ext_status;
     91  1.13.6.2  nathanw 	unsigned int	sc_flags;
     92  1.13.6.2  nathanw #define TCTRL_SEND_REQUEST		0x0001
     93  1.13.6.2  nathanw #define TCTRL_APM_CTLOPEN		0x0002
     94  1.13.6.2  nathanw 	unsigned int	sc_wantdata;
     95  1.13.6.2  nathanw 	volatile unsigned short	sc_lcdstate;
     96  1.13.6.2  nathanw 	enum { TCTRL_IDLE, TCTRL_ARGS,
     97  1.13.6.2  nathanw 		TCTRL_ACK, TCTRL_DATA } sc_state;
     98  1.13.6.2  nathanw 	u_int8_t	sc_cmdbuf[16];
     99  1.13.6.2  nathanw 	u_int8_t	sc_rspbuf[16];
    100  1.13.6.2  nathanw 	u_int8_t	sc_bitport;
    101  1.13.6.2  nathanw 	u_int8_t	sc_tft_on;
    102  1.13.6.2  nathanw 	u_int8_t	sc_op;
    103  1.13.6.2  nathanw 	u_int8_t	sc_cmdoff;
    104  1.13.6.2  nathanw 	u_int8_t	sc_cmdlen;
    105  1.13.6.2  nathanw 	u_int8_t	sc_rspoff;
    106  1.13.6.2  nathanw 	u_int8_t	sc_rsplen;
    107  1.13.6.2  nathanw 	/* APM stuff */
    108  1.13.6.2  nathanw #define APM_NEVENTS 16
    109  1.13.6.2  nathanw 	struct	apm_event_info sc_event_list[APM_NEVENTS];
    110  1.13.6.2  nathanw 	int	sc_event_count;
    111  1.13.6.2  nathanw 	int	sc_event_ptr;
    112  1.13.6.2  nathanw 	struct	selinfo sc_rsel;
    113  1.13.6.2  nathanw 	/* ENVSYS stuff */
    114  1.13.6.2  nathanw #define ENVSYS_NUMSENSORS 3
    115  1.13.6.2  nathanw 	struct	envsys_sensor sc_esensors[ENVSYS_NUMSENSORS];
    116  1.13.6.2  nathanw 
    117  1.13.6.2  nathanw 	struct	evcnt sc_intrcnt;	/* interrupt counting */
    118  1.13.6.2  nathanw };
    119  1.13.6.2  nathanw 
    120  1.13.6.2  nathanw #define TCTRL_STD_DEV		0
    121  1.13.6.2  nathanw #define TCTRL_APMCTL_DEV	8
    122  1.13.6.2  nathanw 
    123  1.13.6.2  nathanw static struct callout tctrl_event_ch = CALLOUT_INITIALIZER;
    124  1.13.6.2  nathanw 
    125  1.13.6.2  nathanw static int tctrl_match __P((struct device *parent, struct cfdata *cf,
    126  1.13.6.2  nathanw 	void *aux));
    127  1.13.6.2  nathanw static void tctrl_attach __P((struct device *parent, struct device *self,
    128  1.13.6.2  nathanw 	void *aux));
    129  1.13.6.2  nathanw static void tctrl_write __P((struct tctrl_softc *sc, bus_size_t off,
    130  1.13.6.2  nathanw 	u_int8_t v));
    131  1.13.6.2  nathanw static u_int8_t tctrl_read __P((struct tctrl_softc *sc, bus_size_t off));
    132  1.13.6.2  nathanw static void tctrl_write_data __P((struct tctrl_softc *sc, u_int8_t v));
    133  1.13.6.2  nathanw static u_int8_t tctrl_read_data __P((struct tctrl_softc *sc));
    134  1.13.6.2  nathanw static int tctrl_intr __P((void *arg));
    135  1.13.6.2  nathanw static void tctrl_setup_bitport __P((void));
    136  1.13.6.2  nathanw static void tctrl_setup_bitport_nop __P((void));
    137  1.13.6.2  nathanw static void tctrl_read_ext_status __P((void));
    138  1.13.6.2  nathanw static void tctrl_read_event_status __P((void *arg));
    139  1.13.6.2  nathanw static int tctrl_apm_record_event __P((struct tctrl_softc *sc,
    140  1.13.6.2  nathanw 	u_int event_type));
    141  1.13.6.2  nathanw static void tctrl_init_lcd __P((void));
    142  1.13.6.2  nathanw 
    143  1.13.6.2  nathanw struct cfattach tctrl_ca = {
    144  1.13.6.2  nathanw 	sizeof(struct tctrl_softc), tctrl_match, tctrl_attach
    145  1.13.6.2  nathanw };
    146  1.13.6.2  nathanw 
    147  1.13.6.2  nathanw extern struct cfdriver tctrl_cd;
    148  1.13.6.2  nathanw /* XXX wtf is this? see i386/apm.c */
    149  1.13.6.2  nathanw int tctrl_apm_evindex;
    150  1.13.6.2  nathanw 
    151  1.13.6.2  nathanw static int
    152  1.13.6.2  nathanw tctrl_match(parent, cf, aux)
    153  1.13.6.2  nathanw 	struct device *parent;
    154  1.13.6.2  nathanw 	struct cfdata *cf;
    155  1.13.6.2  nathanw 	void *aux;
    156  1.13.6.2  nathanw {
    157  1.13.6.2  nathanw 	union obio_attach_args *uoba = aux;
    158  1.13.6.2  nathanw 	struct sbus_attach_args *sa = &uoba->uoba_sbus;
    159  1.13.6.2  nathanw 
    160  1.13.6.2  nathanw 	if (uoba->uoba_isobio4 != 0) {
    161  1.13.6.2  nathanw 		return (0);
    162  1.13.6.2  nathanw 	}
    163  1.13.6.2  nathanw 
    164  1.13.6.2  nathanw 	/* Tadpole 3GX/3GS uses "uctrl" for the Tadpole Microcontroller
    165  1.13.6.2  nathanw 	 * (who's interface is off the TS102 PCMCIA controller but there
    166  1.13.6.2  nathanw 	 * exists a OpenProm for microcontroller interface).
    167  1.13.6.2  nathanw 	 */
    168  1.13.6.2  nathanw 	return strcmp("uctrl", sa->sa_name) == 0;
    169  1.13.6.2  nathanw }
    170  1.13.6.2  nathanw 
    171  1.13.6.2  nathanw static void
    172  1.13.6.2  nathanw tctrl_attach(parent, self, aux)
    173  1.13.6.2  nathanw 	struct device *parent;
    174  1.13.6.2  nathanw 	struct device *self;
    175  1.13.6.2  nathanw 	void *aux;
    176  1.13.6.2  nathanw {
    177  1.13.6.2  nathanw 	struct tctrl_softc *sc = (void *)self;
    178  1.13.6.2  nathanw 	union obio_attach_args *uoba = aux;
    179  1.13.6.2  nathanw 	struct sbus_attach_args *sa = &uoba->uoba_sbus;
    180  1.13.6.2  nathanw 	unsigned int i, v;
    181  1.13.6.2  nathanw #if 0
    182  1.13.6.2  nathanw 	unsigned int ack, msb, lsb;
    183  1.13.6.2  nathanw #endif
    184  1.13.6.2  nathanw 
    185  1.13.6.2  nathanw 	/* We're living on a sbus slot that looks like an obio that
    186  1.13.6.2  nathanw 	 * looks like an sbus slot.
    187  1.13.6.2  nathanw 	 */
    188  1.13.6.2  nathanw 	sc->sc_memt = sa->sa_bustag;
    189  1.13.6.2  nathanw 	if (sbus_bus_map(sc->sc_memt,
    190  1.13.6.2  nathanw 			 sa->sa_slot,
    191  1.13.6.2  nathanw 			 sa->sa_offset - TS102_REG_UCTRL_INT,
    192  1.13.6.2  nathanw 			 sa->sa_size,
    193  1.13.6.2  nathanw 			 BUS_SPACE_MAP_LINEAR, &sc->sc_memh) != 0) {
    194  1.13.6.2  nathanw 		printf(": can't map registers\n");
    195  1.13.6.2  nathanw 		return;
    196  1.13.6.2  nathanw 	}
    197  1.13.6.2  nathanw 
    198  1.13.6.2  nathanw 	printf("\n");
    199  1.13.6.2  nathanw 
    200  1.13.6.2  nathanw 	sc->sc_tft_on = 1;
    201  1.13.6.2  nathanw 
    202  1.13.6.2  nathanw 	/* clear any pending data.
    203  1.13.6.2  nathanw 	 */
    204  1.13.6.2  nathanw 	for (i = 0; i < 10000; i++) {
    205  1.13.6.2  nathanw 		if ((TS102_UCTRL_STS_RXNE_STA &
    206  1.13.6.2  nathanw 		    tctrl_read(sc, TS102_REG_UCTRL_STS)) == 0) {
    207  1.13.6.2  nathanw 			break;
    208  1.13.6.2  nathanw 		}
    209  1.13.6.2  nathanw 		v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
    210  1.13.6.2  nathanw 		tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
    211  1.13.6.2  nathanw 	}
    212  1.13.6.2  nathanw 
    213  1.13.6.2  nathanw 	if (sa->sa_nintr != 0) {
    214  1.13.6.2  nathanw 		(void)bus_intr_establish(sc->sc_memt, sa->sa_pri, IPL_NONE,
    215  1.13.6.2  nathanw 		    0, tctrl_intr, sc);
    216  1.13.6.2  nathanw 		evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
    217  1.13.6.2  nathanw 		    sc->sc_dev.dv_xname, "intr");
    218  1.13.6.2  nathanw 	}
    219  1.13.6.2  nathanw 
    220  1.13.6.2  nathanw 	/* See what the external status is
    221  1.13.6.2  nathanw 	 */
    222  1.13.6.2  nathanw 
    223  1.13.6.2  nathanw 	tctrl_read_ext_status();
    224  1.13.6.2  nathanw 	if (sc->sc_ext_status != 0) {
    225  1.13.6.2  nathanw 		const char *sep;
    226  1.13.6.2  nathanw 
    227  1.13.6.2  nathanw 		printf("%s: ", sc->sc_dev.dv_xname);
    228  1.13.6.2  nathanw 		v = sc->sc_ext_status;
    229  1.13.6.2  nathanw 		for (i = 0, sep = ""; v != 0; i++, v >>= 1) {
    230  1.13.6.2  nathanw 			if (v & 1) {
    231  1.13.6.2  nathanw 				printf("%s%s", sep, tctrl_ext_statuses[i]);
    232  1.13.6.2  nathanw 				sep = ", ";
    233  1.13.6.2  nathanw 			}
    234  1.13.6.2  nathanw 		}
    235  1.13.6.2  nathanw 		printf("\n");
    236  1.13.6.2  nathanw 	}
    237  1.13.6.2  nathanw 
    238  1.13.6.2  nathanw 	/* Get a current of the control bitport;
    239  1.13.6.2  nathanw 	 */
    240  1.13.6.2  nathanw 	tctrl_setup_bitport_nop();
    241  1.13.6.2  nathanw 	tctrl_write(sc, TS102_REG_UCTRL_INT,
    242  1.13.6.2  nathanw 		    TS102_UCTRL_INT_RXNE_REQ|TS102_UCTRL_INT_RXNE_MSK);
    243  1.13.6.2  nathanw 
    244  1.13.6.2  nathanw 	sc->sc_wantdata = 0;
    245  1.13.6.2  nathanw 	sc->sc_event_count = 0;
    246  1.13.6.2  nathanw 
    247  1.13.6.2  nathanw 	/* prime the sensor data */
    248  1.13.6.2  nathanw 	sprintf(sc->sc_esensors[0].desc, "%s", "Internal Unit Temperature");
    249  1.13.6.2  nathanw 	sc->sc_esensors[0].units = ENVSYS_STEMP;
    250  1.13.6.2  nathanw 	sprintf(sc->sc_esensors[1].desc, "%s", "Internal Battery Voltage");
    251  1.13.6.2  nathanw 	sc->sc_esensors[1].units = ENVSYS_SVOLTS_DC;
    252  1.13.6.2  nathanw 	sprintf(sc->sc_esensors[2].desc, "%s", "DC-In Voltage");
    253  1.13.6.2  nathanw 	sc->sc_esensors[2].units = ENVSYS_SVOLTS_DC;
    254  1.13.6.2  nathanw 
    255  1.13.6.2  nathanw 	/* initialize the LCD */
    256  1.13.6.2  nathanw 	tctrl_init_lcd();
    257  1.13.6.2  nathanw 
    258  1.13.6.2  nathanw 	/* initialize sc_lcdstate */
    259  1.13.6.2  nathanw 	sc->sc_lcdstate = 0;
    260  1.13.6.2  nathanw 	tctrl_set_lcd(2, 0);
    261  1.13.6.2  nathanw }
    262  1.13.6.2  nathanw 
    263  1.13.6.2  nathanw static int
    264  1.13.6.2  nathanw tctrl_intr(arg)
    265  1.13.6.2  nathanw 	void *arg;
    266  1.13.6.2  nathanw {
    267  1.13.6.2  nathanw 	struct tctrl_softc *sc = arg;
    268  1.13.6.2  nathanw 	unsigned int v, d;
    269  1.13.6.2  nathanw 	int progress = 0;
    270  1.13.6.2  nathanw 
    271  1.13.6.2  nathanw     again:
    272  1.13.6.2  nathanw 	/* find out the cause(s) of the interrupt */
    273  1.13.6.2  nathanw 	v = tctrl_read(sc, TS102_REG_UCTRL_STS) & TS102_UCTRL_STS_MASK;
    274  1.13.6.2  nathanw 
    275  1.13.6.2  nathanw 	/* clear the cause(s) of the interrupt */
    276  1.13.6.2  nathanw 	tctrl_write(sc, TS102_REG_UCTRL_STS, v);
    277  1.13.6.2  nathanw 
    278  1.13.6.2  nathanw 	v &= ~(TS102_UCTRL_STS_RXO_STA|TS102_UCTRL_STS_TXE_STA);
    279  1.13.6.2  nathanw 	if (sc->sc_cmdoff >= sc->sc_cmdlen) {
    280  1.13.6.2  nathanw 		v &= ~TS102_UCTRL_STS_TXNF_STA;
    281  1.13.6.2  nathanw 		if (tctrl_read(sc, TS102_REG_UCTRL_INT) & TS102_UCTRL_INT_TXNF_REQ) {
    282  1.13.6.2  nathanw 			tctrl_write(sc, TS102_REG_UCTRL_INT, 0);
    283  1.13.6.2  nathanw 			progress = 1;
    284  1.13.6.2  nathanw 		}
    285  1.13.6.2  nathanw 	}
    286  1.13.6.2  nathanw 	if ((v == 0) && ((sc->sc_flags & TCTRL_SEND_REQUEST) == 0 ||
    287  1.13.6.2  nathanw 	    sc->sc_state != TCTRL_IDLE)) {
    288  1.13.6.2  nathanw 		wakeup(sc);
    289  1.13.6.2  nathanw 		return progress;
    290  1.13.6.2  nathanw 	}
    291  1.13.6.2  nathanw 
    292  1.13.6.2  nathanw 	progress = 1;
    293  1.13.6.2  nathanw 	if (v & TS102_UCTRL_STS_RXNE_STA) {
    294  1.13.6.2  nathanw 		d = tctrl_read_data(sc);
    295  1.13.6.2  nathanw 		switch (sc->sc_state) {
    296  1.13.6.2  nathanw 		case TCTRL_IDLE:
    297  1.13.6.2  nathanw 			if (d == 0xfa) {
    298  1.13.6.2  nathanw 				/* external event */
    299  1.13.6.2  nathanw 				callout_reset(&tctrl_event_ch, 1,
    300  1.13.6.2  nathanw 				    tctrl_read_event_status, NULL);
    301  1.13.6.2  nathanw 			} else {
    302  1.13.6.2  nathanw 				printf("%s: (op=0x%02x): unexpected data (0x%02x)\n",
    303  1.13.6.2  nathanw 					sc->sc_dev.dv_xname, sc->sc_op, d);
    304  1.13.6.2  nathanw 			}
    305  1.13.6.2  nathanw 			goto again;
    306  1.13.6.2  nathanw 		case TCTRL_ACK:
    307  1.13.6.2  nathanw 			if (d != 0xfe) {
    308  1.13.6.2  nathanw 				printf("%s: (op=0x%02x): unexpected ack value (0x%02x)\n",
    309  1.13.6.2  nathanw 					sc->sc_dev.dv_xname, sc->sc_op, d);
    310  1.13.6.2  nathanw 			}
    311  1.13.6.2  nathanw #ifdef TCTRLDEBUG
    312  1.13.6.2  nathanw 			printf(" ack=0x%02x", d);
    313  1.13.6.2  nathanw #endif
    314  1.13.6.2  nathanw 			sc->sc_rsplen--;
    315  1.13.6.2  nathanw 			sc->sc_rspoff = 0;
    316  1.13.6.2  nathanw 			sc->sc_state = sc->sc_rsplen ? TCTRL_DATA : TCTRL_IDLE;
    317  1.13.6.2  nathanw 			sc->sc_wantdata = sc->sc_rsplen ? 1 : 0;
    318  1.13.6.2  nathanw #ifdef TCTRLDEBUG
    319  1.13.6.2  nathanw 			if (sc->sc_rsplen > 0) {
    320  1.13.6.2  nathanw 				printf(" [data(%u)]", sc->sc_rsplen);
    321  1.13.6.2  nathanw 			} else {
    322  1.13.6.2  nathanw 				printf(" [idle]\n");
    323  1.13.6.2  nathanw 			}
    324  1.13.6.2  nathanw #endif
    325  1.13.6.2  nathanw 			goto again;
    326  1.13.6.2  nathanw 		case TCTRL_DATA:
    327  1.13.6.2  nathanw 			sc->sc_rspbuf[sc->sc_rspoff++] = d;
    328  1.13.6.2  nathanw #ifdef TCTRLDEBUG
    329  1.13.6.2  nathanw 			printf(" [%d]=0x%02x", sc->sc_rspoff-1, d);
    330  1.13.6.2  nathanw #endif
    331  1.13.6.2  nathanw 			if (sc->sc_rspoff == sc->sc_rsplen) {
    332  1.13.6.2  nathanw #ifdef TCTRLDEBUG
    333  1.13.6.2  nathanw 				printf(" [idle]\n");
    334  1.13.6.2  nathanw #endif
    335  1.13.6.2  nathanw 				sc->sc_state = TCTRL_IDLE;
    336  1.13.6.2  nathanw 				sc->sc_wantdata = 0;
    337  1.13.6.2  nathanw 			}
    338  1.13.6.2  nathanw 			goto again;
    339  1.13.6.2  nathanw 		default:
    340  1.13.6.2  nathanw 			printf("%s: (op=0x%02x): unexpected data (0x%02x) in state %d\n",
    341  1.13.6.2  nathanw 			       sc->sc_dev.dv_xname, sc->sc_op, d, sc->sc_state);
    342  1.13.6.2  nathanw 			goto again;
    343  1.13.6.2  nathanw 		}
    344  1.13.6.2  nathanw 	}
    345  1.13.6.2  nathanw 	if ((sc->sc_state == TCTRL_IDLE && sc->sc_wantdata == 0) ||
    346  1.13.6.2  nathanw 	    sc->sc_flags & TCTRL_SEND_REQUEST) {
    347  1.13.6.2  nathanw 		if (sc->sc_flags & TCTRL_SEND_REQUEST) {
    348  1.13.6.2  nathanw 			sc->sc_flags &= ~TCTRL_SEND_REQUEST;
    349  1.13.6.2  nathanw 			sc->sc_wantdata = 1;
    350  1.13.6.2  nathanw 		}
    351  1.13.6.2  nathanw 		if (sc->sc_cmdlen > 0) {
    352  1.13.6.2  nathanw 			tctrl_write(sc, TS102_REG_UCTRL_INT,
    353  1.13.6.2  nathanw 				tctrl_read(sc, TS102_REG_UCTRL_INT)
    354  1.13.6.2  nathanw 				|TS102_UCTRL_INT_TXNF_MSK
    355  1.13.6.2  nathanw 				|TS102_UCTRL_INT_TXNF_REQ);
    356  1.13.6.2  nathanw 			v = tctrl_read(sc, TS102_REG_UCTRL_STS);
    357  1.13.6.2  nathanw 		}
    358  1.13.6.2  nathanw 	}
    359  1.13.6.2  nathanw 	if ((sc->sc_cmdoff < sc->sc_cmdlen) && (v & TS102_UCTRL_STS_TXNF_STA)) {
    360  1.13.6.2  nathanw 		tctrl_write_data(sc, sc->sc_cmdbuf[sc->sc_cmdoff++]);
    361  1.13.6.2  nathanw #ifdef TCTRLDEBUG
    362  1.13.6.2  nathanw 		if (sc->sc_cmdoff == 1) {
    363  1.13.6.2  nathanw 			printf("%s: op=0x%02x(l=%u)", sc->sc_dev.dv_xname,
    364  1.13.6.2  nathanw 				sc->sc_cmdbuf[0], sc->sc_rsplen);
    365  1.13.6.2  nathanw 		} else {
    366  1.13.6.2  nathanw 			printf(" [%d]=0x%02x", sc->sc_cmdoff-1,
    367  1.13.6.2  nathanw 				sc->sc_cmdbuf[sc->sc_cmdoff-1]);
    368  1.13.6.2  nathanw 		}
    369  1.13.6.2  nathanw #endif
    370  1.13.6.2  nathanw 		if (sc->sc_cmdoff == sc->sc_cmdlen) {
    371  1.13.6.2  nathanw 			sc->sc_state = sc->sc_rsplen ? TCTRL_ACK : TCTRL_IDLE;
    372  1.13.6.2  nathanw #ifdef TCTRLDEBUG
    373  1.13.6.2  nathanw 			printf(" %s", sc->sc_rsplen ? "[ack]" : "[idle]\n");
    374  1.13.6.2  nathanw #endif
    375  1.13.6.2  nathanw 			if (sc->sc_cmdoff == 1) {
    376  1.13.6.2  nathanw 				sc->sc_op = sc->sc_cmdbuf[0];
    377  1.13.6.2  nathanw 			}
    378  1.13.6.2  nathanw 			tctrl_write(sc, TS102_REG_UCTRL_INT,
    379  1.13.6.2  nathanw 				tctrl_read(sc, TS102_REG_UCTRL_INT)
    380  1.13.6.2  nathanw 				& (~TS102_UCTRL_INT_TXNF_MSK
    381  1.13.6.2  nathanw 				   |TS102_UCTRL_INT_TXNF_REQ));
    382  1.13.6.2  nathanw 		} else if (sc->sc_state == TCTRL_IDLE) {
    383  1.13.6.2  nathanw 			sc->sc_op = sc->sc_cmdbuf[0];
    384  1.13.6.2  nathanw 			sc->sc_state = TCTRL_ARGS;
    385  1.13.6.2  nathanw #ifdef TCTRLDEBUG
    386  1.13.6.2  nathanw 			printf(" [args]");
    387  1.13.6.2  nathanw #endif
    388  1.13.6.2  nathanw 		}
    389  1.13.6.2  nathanw 	}
    390  1.13.6.2  nathanw 	goto again;
    391  1.13.6.2  nathanw }
    392  1.13.6.2  nathanw 
    393  1.13.6.2  nathanw static void
    394  1.13.6.2  nathanw tctrl_setup_bitport_nop(void)
    395  1.13.6.2  nathanw {
    396  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    397  1.13.6.2  nathanw 	struct tctrl_req req;
    398  1.13.6.2  nathanw 	int s;
    399  1.13.6.2  nathanw 
    400  1.13.6.2  nathanw 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    401  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
    402  1.13.6.2  nathanw 	req.cmdbuf[1] = 0xff;
    403  1.13.6.2  nathanw 	req.cmdbuf[2] = 0;
    404  1.13.6.2  nathanw 	req.cmdlen = 3;
    405  1.13.6.2  nathanw 	req.rsplen = 2;
    406  1.13.6.2  nathanw 	req.p = NULL;
    407  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    408  1.13.6.2  nathanw 	s = splts102();
    409  1.13.6.2  nathanw 	sc->sc_bitport = (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
    410  1.13.6.2  nathanw 	splx(s);
    411  1.13.6.2  nathanw }
    412  1.13.6.2  nathanw 
    413  1.13.6.2  nathanw static void
    414  1.13.6.2  nathanw tctrl_setup_bitport(void)
    415  1.13.6.2  nathanw {
    416  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    417  1.13.6.2  nathanw 	struct tctrl_req req;
    418  1.13.6.2  nathanw 	int s;
    419  1.13.6.2  nathanw 
    420  1.13.6.2  nathanw 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    421  1.13.6.2  nathanw 	s = splts102();
    422  1.13.6.2  nathanw 	if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
    423  1.13.6.2  nathanw 	    || (!sc->sc_tft_on)) {
    424  1.13.6.2  nathanw 		req.cmdbuf[2] = TS102_BITPORT_TFTPWR;
    425  1.13.6.2  nathanw 	} else {
    426  1.13.6.2  nathanw 		req.cmdbuf[2] = 0;
    427  1.13.6.2  nathanw 	}
    428  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
    429  1.13.6.2  nathanw 	req.cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
    430  1.13.6.2  nathanw 	req.cmdlen = 3;
    431  1.13.6.2  nathanw 	req.rsplen = 2;
    432  1.13.6.2  nathanw 	req.p = NULL;
    433  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    434  1.13.6.2  nathanw 	s = splts102();
    435  1.13.6.2  nathanw 	sc->sc_bitport = (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
    436  1.13.6.2  nathanw 	splx(s);
    437  1.13.6.2  nathanw }
    438  1.13.6.2  nathanw 
    439  1.13.6.2  nathanw /*
    440  1.13.6.2  nathanw  * The tadpole microcontroller is not preprogrammed with icon
    441  1.13.6.2  nathanw  * representations.  The machine boots with the DC-IN light as
    442  1.13.6.2  nathanw  * a blank (all 0x00) and the other lights, as 4 rows of horizontal
    443  1.13.6.2  nathanw  * bars.  The below code initializes the icons in the system to
    444  1.13.6.2  nathanw  * sane values.  Some of these icons could be used for any purpose
    445  1.13.6.2  nathanw  * desired, namely the pcmcia, LAN and WAN lights.  For the disk spinner,
    446  1.13.6.2  nathanw  * only the backslash is unprogrammed.  (sigh)
    447  1.13.6.2  nathanw  *
    448  1.13.6.2  nathanw  * programming the icons is simple.  It is a 5x8 matrix, which each row a
    449  1.13.6.2  nathanw  * bitfield in the order 0x10 0x08 0x04 0x02 0x01.
    450  1.13.6.2  nathanw  */
    451  1.13.6.2  nathanw 
    452  1.13.6.2  nathanw static void
    453  1.13.6.2  nathanw tctrl_init_lcd(void)
    454  1.13.6.2  nathanw {
    455  1.13.6.2  nathanw 	struct tctrl_req req;
    456  1.13.6.2  nathanw 
    457  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    458  1.13.6.2  nathanw 	req.cmdlen = 11;
    459  1.13.6.2  nathanw 	req.rsplen = 1;
    460  1.13.6.2  nathanw 	req.cmdbuf[1] = 0x08;	/*len*/
    461  1.13.6.2  nathanw 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_DC_GOOD;
    462  1.13.6.2  nathanw 	req.cmdbuf[3] =  0x00;	/* ..... */
    463  1.13.6.2  nathanw 	req.cmdbuf[4] =  0x00;	/* ..... */
    464  1.13.6.2  nathanw 	req.cmdbuf[5] =  0x1f;	/* XXXXX */
    465  1.13.6.2  nathanw 	req.cmdbuf[6] =  0x00;	/* ..... */
    466  1.13.6.2  nathanw 	req.cmdbuf[7] =  0x15;	/* X.X.X */
    467  1.13.6.2  nathanw 	req.cmdbuf[8] =  0x00;	/* ..... */
    468  1.13.6.2  nathanw 	req.cmdbuf[9] =  0x00;	/* ..... */
    469  1.13.6.2  nathanw 	req.cmdbuf[10] = 0x00;	/* ..... */
    470  1.13.6.2  nathanw 	req.p = NULL;
    471  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    472  1.13.6.2  nathanw 
    473  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    474  1.13.6.2  nathanw 	req.cmdlen = 11;
    475  1.13.6.2  nathanw 	req.rsplen = 1;
    476  1.13.6.2  nathanw 	req.cmdbuf[1] = 0x08;	/*len*/
    477  1.13.6.2  nathanw 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_BACKSLASH;
    478  1.13.6.2  nathanw 	req.cmdbuf[3] =  0x00;	/* ..... */
    479  1.13.6.2  nathanw 	req.cmdbuf[4] =  0x10;	/* X.... */
    480  1.13.6.2  nathanw 	req.cmdbuf[5] =  0x08;	/* .X... */
    481  1.13.6.2  nathanw 	req.cmdbuf[6] =  0x04;	/* ..X.. */
    482  1.13.6.2  nathanw 	req.cmdbuf[7] =  0x02;	/* ...X. */
    483  1.13.6.2  nathanw 	req.cmdbuf[8] =  0x01;	/* ....X */
    484  1.13.6.2  nathanw 	req.cmdbuf[9] =  0x00;	/* ..... */
    485  1.13.6.2  nathanw 	req.cmdbuf[10] = 0x00;	/* ..... */
    486  1.13.6.2  nathanw 	req.p = NULL;
    487  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    488  1.13.6.2  nathanw 
    489  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    490  1.13.6.2  nathanw 	req.cmdlen = 11;
    491  1.13.6.2  nathanw 	req.rsplen = 1;
    492  1.13.6.2  nathanw 	req.cmdbuf[1] = 0x08;	/*len*/
    493  1.13.6.2  nathanw 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_WAN1;
    494  1.13.6.2  nathanw 	req.cmdbuf[3] =  0x0c;	/* .XXX. */
    495  1.13.6.2  nathanw 	req.cmdbuf[4] =  0x16;	/* X.XX. */
    496  1.13.6.2  nathanw 	req.cmdbuf[5] =  0x10;	/* X.... */
    497  1.13.6.2  nathanw 	req.cmdbuf[6] =  0x15;	/* X.X.X */
    498  1.13.6.2  nathanw 	req.cmdbuf[7] =  0x10;	/* X.... */
    499  1.13.6.2  nathanw 	req.cmdbuf[8] =  0x16;	/* X.XX. */
    500  1.13.6.2  nathanw 	req.cmdbuf[9] =  0x0c;	/* .XXX. */
    501  1.13.6.2  nathanw 	req.cmdbuf[10] = 0x00;	/* ..... */
    502  1.13.6.2  nathanw 	req.p = NULL;
    503  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    504  1.13.6.2  nathanw 
    505  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    506  1.13.6.2  nathanw 	req.cmdlen = 11;
    507  1.13.6.2  nathanw 	req.rsplen = 1;
    508  1.13.6.2  nathanw 	req.cmdbuf[1] = 0x08;	/*len*/
    509  1.13.6.2  nathanw 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_WAN2;
    510  1.13.6.2  nathanw 	req.cmdbuf[3] =  0x0c;	/* .XXX. */
    511  1.13.6.2  nathanw 	req.cmdbuf[4] =  0x0d;	/* .XX.X */
    512  1.13.6.2  nathanw 	req.cmdbuf[5] =  0x01;	/* ....X */
    513  1.13.6.2  nathanw 	req.cmdbuf[6] =  0x15;	/* X.X.X */
    514  1.13.6.2  nathanw 	req.cmdbuf[7] =  0x01;	/* ....X */
    515  1.13.6.2  nathanw 	req.cmdbuf[8] =  0x0d;	/* .XX.X */
    516  1.13.6.2  nathanw 	req.cmdbuf[9] =  0x0c;	/* .XXX. */
    517  1.13.6.2  nathanw 	req.cmdbuf[10] = 0x00;	/* ..... */
    518  1.13.6.2  nathanw 	req.p = NULL;
    519  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    520  1.13.6.2  nathanw 
    521  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    522  1.13.6.2  nathanw 	req.cmdlen = 11;
    523  1.13.6.2  nathanw 	req.rsplen = 1;
    524  1.13.6.2  nathanw 	req.cmdbuf[1] = 0x08;	/*len*/
    525  1.13.6.2  nathanw 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_LAN1;
    526  1.13.6.2  nathanw 	req.cmdbuf[3] =  0x00;	/* ..... */
    527  1.13.6.2  nathanw 	req.cmdbuf[4] =  0x04;	/* ..X.. */
    528  1.13.6.2  nathanw 	req.cmdbuf[5] =  0x08;	/* .X... */
    529  1.13.6.2  nathanw 	req.cmdbuf[6] =  0x13;	/* X..XX */
    530  1.13.6.2  nathanw 	req.cmdbuf[7] =  0x08;	/* .X... */
    531  1.13.6.2  nathanw 	req.cmdbuf[8] =  0x04;	/* ..X.. */
    532  1.13.6.2  nathanw 	req.cmdbuf[9] =  0x00;	/* ..... */
    533  1.13.6.2  nathanw 	req.cmdbuf[10] = 0x00;	/* ..... */
    534  1.13.6.2  nathanw 	req.p = NULL;
    535  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    536  1.13.6.2  nathanw 
    537  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    538  1.13.6.2  nathanw 	req.cmdlen = 11;
    539  1.13.6.2  nathanw 	req.rsplen = 1;
    540  1.13.6.2  nathanw 	req.cmdbuf[1] = 0x08;	/*len*/
    541  1.13.6.2  nathanw 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_LAN2;
    542  1.13.6.2  nathanw 	req.cmdbuf[3] =  0x00;	/* ..... */
    543  1.13.6.2  nathanw 	req.cmdbuf[4] =  0x04;	/* ..X.. */
    544  1.13.6.2  nathanw 	req.cmdbuf[5] =  0x02;	/* ...X. */
    545  1.13.6.2  nathanw 	req.cmdbuf[6] =  0x19;	/* XX..X */
    546  1.13.6.2  nathanw 	req.cmdbuf[7] =  0x02;	/* ...X. */
    547  1.13.6.2  nathanw 	req.cmdbuf[8] =  0x04;	/* ..X.. */
    548  1.13.6.2  nathanw 	req.cmdbuf[9] =  0x00;	/* ..... */
    549  1.13.6.2  nathanw 	req.cmdbuf[10] = 0x00;	/* ..... */
    550  1.13.6.2  nathanw 	req.p = NULL;
    551  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    552  1.13.6.2  nathanw 
    553  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    554  1.13.6.2  nathanw 	req.cmdlen = 11;
    555  1.13.6.2  nathanw 	req.rsplen = 1;
    556  1.13.6.2  nathanw 	req.cmdbuf[1] = 0x08;	/*len*/
    557  1.13.6.2  nathanw 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_PCMCIA;
    558  1.13.6.2  nathanw 	req.cmdbuf[3] =  0x00;	/* ..... */
    559  1.13.6.2  nathanw 	req.cmdbuf[4] =  0x0c;	/* .XXX. */
    560  1.13.6.2  nathanw 	req.cmdbuf[5] =  0x1f;	/* XXXXX */
    561  1.13.6.2  nathanw 	req.cmdbuf[6] =  0x1f;	/* XXXXX */
    562  1.13.6.2  nathanw 	req.cmdbuf[7] =  0x1f;	/* XXXXX */
    563  1.13.6.2  nathanw 	req.cmdbuf[8] =  0x1f;	/* XXXXX */
    564  1.13.6.2  nathanw 	req.cmdbuf[9] =  0x00;	/* ..... */
    565  1.13.6.2  nathanw 	req.cmdbuf[10] = 0x00;	/* ..... */
    566  1.13.6.2  nathanw 	req.p = NULL;
    567  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    568  1.13.6.2  nathanw }
    569  1.13.6.2  nathanw 
    570  1.13.6.2  nathanw 
    571  1.13.6.2  nathanw 
    572  1.13.6.2  nathanw /*
    573  1.13.6.2  nathanw  * set the blinken-lights on the lcd.  what:
    574  1.13.6.2  nathanw  * what = 0 off,  what = 1 on,  what = 2 toggle
    575  1.13.6.2  nathanw  */
    576  1.13.6.2  nathanw 
    577  1.13.6.2  nathanw void
    578  1.13.6.2  nathanw tctrl_set_lcd(what, which)
    579  1.13.6.2  nathanw 	int what;
    580  1.13.6.2  nathanw 	unsigned short which;
    581  1.13.6.2  nathanw {
    582  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    583  1.13.6.2  nathanw 	struct tctrl_req req;
    584  1.13.6.2  nathanw 	int s;
    585  1.13.6.2  nathanw 
    586  1.13.6.2  nathanw 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    587  1.13.6.2  nathanw 	s = splts102();
    588  1.13.6.2  nathanw 
    589  1.13.6.2  nathanw 	/* provide a quick exit to save cpu time */
    590  1.13.6.2  nathanw 	if ((what == 1 && sc->sc_lcdstate & which) ||
    591  1.13.6.2  nathanw 	    (what == 0 && !(sc->sc_lcdstate & which))) {
    592  1.13.6.2  nathanw 		splx(s);
    593  1.13.6.2  nathanw 		return;
    594  1.13.6.2  nathanw 	}
    595  1.13.6.2  nathanw 	/*
    596  1.13.6.2  nathanw 	 * the mask setup on this particular command is *very* bizzare
    597  1.13.6.2  nathanw 	 * and totally undocumented.
    598  1.13.6.2  nathanw 	 */
    599  1.13.6.2  nathanw 	if ((what == 1) || (what == 2 && !(sc->sc_lcdstate & which))) {
    600  1.13.6.2  nathanw 		req.cmdbuf[2] = (u_int8_t)(which&0xff);
    601  1.13.6.2  nathanw 		req.cmdbuf[3] = (u_int8_t)(which>>8);
    602  1.13.6.2  nathanw 	} else {
    603  1.13.6.2  nathanw 		req.cmdbuf[2] = 0;
    604  1.13.6.2  nathanw 		req.cmdbuf[3] = 0;
    605  1.13.6.2  nathanw 	}
    606  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_CTL_LCD;
    607  1.13.6.2  nathanw 	req.cmdbuf[4] = (u_int8_t)(~which>>8);
    608  1.13.6.2  nathanw 	req.cmdbuf[1] = (u_int8_t)(~which&0xff);
    609  1.13.6.2  nathanw 
    610  1.13.6.2  nathanw 	/* XXX this thing is weird.... */
    611  1.13.6.2  nathanw 	req.cmdlen = 3;
    612  1.13.6.2  nathanw 	req.rsplen = 2;
    613  1.13.6.2  nathanw #if 0
    614  1.13.6.2  nathanw 	req.cmdlen = 5;
    615  1.13.6.2  nathanw 	req.rsplen = 4;
    616  1.13.6.2  nathanw #endif
    617  1.13.6.2  nathanw 	req.p = NULL;
    618  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    619  1.13.6.2  nathanw 	s = splts102();
    620  1.13.6.2  nathanw 	sc->sc_lcdstate = (unsigned short)req.rspbuf[0];
    621  1.13.6.2  nathanw 	splx(s);
    622  1.13.6.2  nathanw }
    623  1.13.6.2  nathanw 
    624  1.13.6.2  nathanw static void
    625  1.13.6.2  nathanw tctrl_read_ext_status(void)
    626  1.13.6.2  nathanw {
    627  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    628  1.13.6.2  nathanw 	struct tctrl_req req;
    629  1.13.6.2  nathanw 	int s;
    630  1.13.6.2  nathanw 
    631  1.13.6.2  nathanw 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    632  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
    633  1.13.6.2  nathanw 	req.cmdlen = 1;
    634  1.13.6.2  nathanw 	req.rsplen = 3;
    635  1.13.6.2  nathanw 	req.p = NULL;
    636  1.13.6.2  nathanw #ifdef TCTRLDEBUG
    637  1.13.6.2  nathanw 	printf("pre read: sc->sc_ext_status = 0x%x\n", sc->sc_ext_status);
    638  1.13.6.2  nathanw #endif
    639  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    640  1.13.6.2  nathanw 	s = splts102();
    641  1.13.6.2  nathanw 	sc->sc_ext_status = req.rspbuf[0] * 256 + req.rspbuf[1];
    642  1.13.6.2  nathanw 	splx(s);
    643  1.13.6.2  nathanw #ifdef TCTRLDEBUG
    644  1.13.6.2  nathanw 	printf("post read: sc->sc_ext_status = 0x%x\n", sc->sc_ext_status);
    645  1.13.6.2  nathanw #endif
    646  1.13.6.2  nathanw }
    647  1.13.6.2  nathanw 
    648  1.13.6.2  nathanw /*
    649  1.13.6.2  nathanw  * return 0 if the user will notice and handle the event,
    650  1.13.6.2  nathanw  * return 1 if the kernel driver should do so.
    651  1.13.6.2  nathanw  */
    652  1.13.6.2  nathanw static int
    653  1.13.6.2  nathanw tctrl_apm_record_event(sc, event_type)
    654  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    655  1.13.6.2  nathanw 	u_int event_type;
    656  1.13.6.2  nathanw {
    657  1.13.6.2  nathanw 	struct apm_event_info *evp;
    658  1.13.6.2  nathanw 
    659  1.13.6.2  nathanw 	if ((sc->sc_flags & TCTRL_APM_CTLOPEN) &&
    660  1.13.6.2  nathanw 	    (sc->sc_event_count < APM_NEVENTS)) {
    661  1.13.6.2  nathanw 		evp = &sc->sc_event_list[sc->sc_event_ptr];
    662  1.13.6.2  nathanw 		sc->sc_event_count++;
    663  1.13.6.2  nathanw 		sc->sc_event_ptr++;
    664  1.13.6.2  nathanw 		sc->sc_event_ptr %= APM_NEVENTS;
    665  1.13.6.2  nathanw 		evp->type = event_type;
    666  1.13.6.2  nathanw 		evp->index = ++tctrl_apm_evindex;
    667  1.13.6.2  nathanw 		selwakeup(&sc->sc_rsel);
    668  1.13.6.2  nathanw 		return(sc->sc_flags & TCTRL_APM_CTLOPEN) ? 0 : 1;
    669  1.13.6.2  nathanw 	}
    670  1.13.6.2  nathanw 	return(1);
    671  1.13.6.2  nathanw }
    672  1.13.6.2  nathanw 
    673  1.13.6.2  nathanw static void
    674  1.13.6.2  nathanw tctrl_read_event_status(arg)
    675  1.13.6.2  nathanw 	void *arg;
    676  1.13.6.2  nathanw {
    677  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    678  1.13.6.2  nathanw 	struct tctrl_req req;
    679  1.13.6.2  nathanw 	int s;
    680  1.13.6.2  nathanw 	unsigned int v;
    681  1.13.6.2  nathanw 
    682  1.13.6.2  nathanw 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    683  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_RD_EVENT_STATUS;
    684  1.13.6.2  nathanw 	req.cmdlen = 1;
    685  1.13.6.2  nathanw 	req.rsplen = 3;
    686  1.13.6.2  nathanw 	req.p = NULL;
    687  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    688  1.13.6.2  nathanw 	s = splts102();
    689  1.13.6.2  nathanw 	v = req.rspbuf[0] * 256 + req.rspbuf[1];
    690  1.13.6.2  nathanw 	if (v & TS102_EVENT_STATUS_SHUTDOWN_REQUEST) {
    691  1.13.6.2  nathanw 		printf("%s: SHUTDOWN REQUEST!\n", sc->sc_dev.dv_xname);
    692  1.13.6.2  nathanw 	}
    693  1.13.6.2  nathanw 	if (v & TS102_EVENT_STATUS_VERY_LOW_POWER_WARNING) {
    694  1.13.6.2  nathanw /*printf("%s: VERY LOW POWER WARNING!\n", sc->sc_dev.dv_xname);*/
    695  1.13.6.2  nathanw /* according to a tadpole header, and observation */
    696  1.13.6.2  nathanw #ifdef TCTRLDEBUG
    697  1.13.6.2  nathanw 		printf("%s: Battery charge level change\n", sc->sc_dev.dv_xname);
    698  1.13.6.2  nathanw #endif
    699  1.13.6.2  nathanw 	}
    700  1.13.6.2  nathanw 	if (v & TS102_EVENT_STATUS_LOW_POWER_WARNING) {
    701  1.13.6.2  nathanw 		if (tctrl_apm_record_event(sc, APM_BATTERY_LOW))
    702  1.13.6.2  nathanw 			printf("%s: LOW POWER WARNING!\n", sc->sc_dev.dv_xname);
    703  1.13.6.2  nathanw 	}
    704  1.13.6.2  nathanw 	if (v & TS102_EVENT_STATUS_DC_STATUS_CHANGE) {
    705  1.13.6.2  nathanw 		splx(s);
    706  1.13.6.2  nathanw 		tctrl_read_ext_status();
    707  1.13.6.2  nathanw 		s = splts102();
    708  1.13.6.2  nathanw 		if (tctrl_apm_record_event(sc, APM_POWER_CHANGE))
    709  1.13.6.2  nathanw 			printf("%s: main power %s\n", sc->sc_dev.dv_xname,
    710  1.13.6.2  nathanw 			    (sc->sc_ext_status &
    711  1.13.6.2  nathanw 			    TS102_EXT_STATUS_MAIN_POWER_AVAILABLE) ?
    712  1.13.6.2  nathanw 			    "restored" : "removed");
    713  1.13.6.2  nathanw 	}
    714  1.13.6.2  nathanw 	if (v & TS102_EVENT_STATUS_LID_STATUS_CHANGE) {
    715  1.13.6.2  nathanw 		splx(s);
    716  1.13.6.2  nathanw 		tctrl_read_ext_status();
    717  1.13.6.2  nathanw 		tctrl_setup_bitport();
    718  1.13.6.2  nathanw #ifdef TCTRLDEBUG
    719  1.13.6.2  nathanw 		printf("%s: lid %s\n", sc->sc_dev.dv_xname,
    720  1.13.6.2  nathanw 		    (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
    721  1.13.6.2  nathanw 		    ? "closed" : "opened");
    722  1.13.6.2  nathanw #endif
    723  1.13.6.2  nathanw 	}
    724  1.13.6.2  nathanw 	splx(s);
    725  1.13.6.2  nathanw }
    726  1.13.6.2  nathanw 
    727  1.13.6.2  nathanw void
    728  1.13.6.2  nathanw tadpole_request(req, spin)
    729  1.13.6.2  nathanw 	struct tctrl_req *req;
    730  1.13.6.2  nathanw 	int spin;
    731  1.13.6.2  nathanw {
    732  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    733  1.13.6.2  nathanw 	int i, s;
    734  1.13.6.2  nathanw 
    735  1.13.6.2  nathanw 	if (tctrl_cd.cd_devs == NULL
    736  1.13.6.2  nathanw 	    || tctrl_cd.cd_ndevs == 0
    737  1.13.6.2  nathanw 	    || tctrl_cd.cd_devs[TCTRL_STD_DEV] == NULL) {
    738  1.13.6.2  nathanw 		return;
    739  1.13.6.2  nathanw 	}
    740  1.13.6.2  nathanw 
    741  1.13.6.2  nathanw 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    742  1.13.6.2  nathanw 	while (sc->sc_wantdata != 0) {
    743  1.13.6.2  nathanw 		if (req->p != NULL)
    744  1.13.6.2  nathanw 			tsleep(&sc->sc_wantdata, PLOCK, "tctrl_lock", 10);
    745  1.13.6.2  nathanw 		else
    746  1.13.6.2  nathanw 			DELAY(1);
    747  1.13.6.2  nathanw 	}
    748  1.13.6.2  nathanw 	if (spin)
    749  1.13.6.2  nathanw 		s = splhigh();
    750  1.13.6.2  nathanw 	else
    751  1.13.6.2  nathanw 		s = splts102();
    752  1.13.6.2  nathanw 	sc->sc_flags |= TCTRL_SEND_REQUEST;
    753  1.13.6.2  nathanw 	memcpy(sc->sc_cmdbuf, req->cmdbuf, req->cmdlen);
    754  1.13.6.2  nathanw 	sc->sc_wantdata = 1;
    755  1.13.6.2  nathanw 	sc->sc_rsplen = req->rsplen;
    756  1.13.6.2  nathanw 	sc->sc_cmdlen = req->cmdlen;
    757  1.13.6.2  nathanw 	sc->sc_cmdoff = sc->sc_rspoff = 0;
    758  1.13.6.2  nathanw 
    759  1.13.6.2  nathanw 	/* we spin for certain commands, like poweroffs */
    760  1.13.6.2  nathanw 	if (spin) {
    761  1.13.6.2  nathanw /*		for (i = 0; i < 30000; i++) {*/
    762  1.13.6.2  nathanw 		while (sc->sc_wantdata == 1) {
    763  1.13.6.2  nathanw 			tctrl_intr(sc);
    764  1.13.6.2  nathanw 			DELAY(1);
    765  1.13.6.2  nathanw 		}
    766  1.13.6.2  nathanw 	} else {
    767  1.13.6.2  nathanw 		tctrl_intr(sc);
    768  1.13.6.2  nathanw 		i = 0;
    769  1.13.6.2  nathanw 		while (((sc->sc_rspoff != sc->sc_rsplen) ||
    770  1.13.6.2  nathanw 		    (sc->sc_cmdoff != sc->sc_cmdlen)) &&
    771  1.13.6.2  nathanw 		    (i < (5 * sc->sc_rsplen + sc->sc_cmdlen)))
    772  1.13.6.2  nathanw 			if (req->p != NULL) {
    773  1.13.6.2  nathanw 				tsleep(sc, PWAIT, "tctrl_data", 15);
    774  1.13.6.2  nathanw 				i++;
    775  1.13.6.2  nathanw 			}
    776  1.13.6.2  nathanw 			else
    777  1.13.6.2  nathanw 				DELAY(1);
    778  1.13.6.2  nathanw 	}
    779  1.13.6.2  nathanw 	/*
    780  1.13.6.2  nathanw 	 * we give the user a reasonable amount of time for a command
    781  1.13.6.2  nathanw 	 * to complete.  If it doesn't complete in time, we hand them
    782  1.13.6.2  nathanw 	 * garbage.  This is here to stop things like setting the
    783  1.13.6.2  nathanw 	 * rsplen too long, and sleeping forever in a CMD_REQ ioctl.
    784  1.13.6.2  nathanw 	 */
    785  1.13.6.2  nathanw 	sc->sc_wantdata = 0;
    786  1.13.6.2  nathanw 	memcpy(req->rspbuf, sc->sc_rspbuf, req->rsplen);
    787  1.13.6.2  nathanw 	splx(s);
    788  1.13.6.2  nathanw }
    789  1.13.6.2  nathanw 
    790  1.13.6.2  nathanw void
    791  1.13.6.2  nathanw tadpole_powerdown(void)
    792  1.13.6.2  nathanw {
    793  1.13.6.2  nathanw 	struct tctrl_req req;
    794  1.13.6.2  nathanw 
    795  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_ADMIN_POWER_OFF;
    796  1.13.6.2  nathanw 	req.cmdlen = 1;
    797  1.13.6.2  nathanw 	req.rsplen = 1;
    798  1.13.6.2  nathanw 	req.p = NULL;
    799  1.13.6.2  nathanw 	tadpole_request(&req, 1);
    800  1.13.6.2  nathanw }
    801  1.13.6.2  nathanw 
    802  1.13.6.2  nathanw void
    803  1.13.6.2  nathanw tadpole_set_video(enabled)
    804  1.13.6.2  nathanw 	int enabled;
    805  1.13.6.2  nathanw {
    806  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    807  1.13.6.2  nathanw 	struct tctrl_req req;
    808  1.13.6.2  nathanw 	int s;
    809  1.13.6.2  nathanw 
    810  1.13.6.2  nathanw 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    811  1.13.6.2  nathanw 	while (sc->sc_wantdata != 0)
    812  1.13.6.2  nathanw 		DELAY(1);
    813  1.13.6.2  nathanw 	s = splts102();
    814  1.13.6.2  nathanw 	req.p = NULL;
    815  1.13.6.2  nathanw 	if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN && !enabled)
    816  1.13.6.2  nathanw 	    || (sc->sc_tft_on)) {
    817  1.13.6.2  nathanw 		req.cmdbuf[2] = TS102_BITPORT_TFTPWR;
    818  1.13.6.2  nathanw 	} else {
    819  1.13.6.2  nathanw 		req.cmdbuf[2] = 0;
    820  1.13.6.2  nathanw 	}
    821  1.13.6.2  nathanw 	req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
    822  1.13.6.2  nathanw 	req.cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
    823  1.13.6.2  nathanw 	req.cmdlen = 3;
    824  1.13.6.2  nathanw 	req.rsplen = 2;
    825  1.13.6.2  nathanw 
    826  1.13.6.2  nathanw 	if ((sc->sc_tft_on && !enabled) || (!sc->sc_tft_on && enabled)) {
    827  1.13.6.2  nathanw 		sc->sc_tft_on = enabled;
    828  1.13.6.2  nathanw 		if (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) {
    829  1.13.6.2  nathanw 			splx(s);
    830  1.13.6.2  nathanw 			return;
    831  1.13.6.2  nathanw 		}
    832  1.13.6.2  nathanw 		tadpole_request(&req, 1);
    833  1.13.6.2  nathanw 		sc->sc_bitport =
    834  1.13.6.2  nathanw 		    (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
    835  1.13.6.2  nathanw 	}
    836  1.13.6.2  nathanw 	splx(s);
    837  1.13.6.2  nathanw }
    838  1.13.6.2  nathanw 
    839  1.13.6.2  nathanw static void
    840  1.13.6.2  nathanw tctrl_write_data(sc, v)
    841  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    842  1.13.6.2  nathanw 	u_int8_t v;
    843  1.13.6.2  nathanw {
    844  1.13.6.2  nathanw 	unsigned int i;
    845  1.13.6.2  nathanw 
    846  1.13.6.2  nathanw 	for (i = 0; i < 100; i++)  {
    847  1.13.6.2  nathanw 		if (TS102_UCTRL_STS_TXNF_STA & tctrl_read(sc, TS102_REG_UCTRL_STS))
    848  1.13.6.2  nathanw 			break;
    849  1.13.6.2  nathanw 	}
    850  1.13.6.2  nathanw 	tctrl_write(sc, TS102_REG_UCTRL_DATA, v);
    851  1.13.6.2  nathanw }
    852  1.13.6.2  nathanw 
    853  1.13.6.2  nathanw static u_int8_t
    854  1.13.6.2  nathanw tctrl_read_data(sc)
    855  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    856  1.13.6.2  nathanw {
    857  1.13.6.2  nathanw 	unsigned int i, v;
    858  1.13.6.2  nathanw 
    859  1.13.6.2  nathanw 	for (i = 0; i < 100000; i++) {
    860  1.13.6.2  nathanw 		if (TS102_UCTRL_STS_RXNE_STA & tctrl_read(sc, TS102_REG_UCTRL_STS))
    861  1.13.6.2  nathanw 			break;
    862  1.13.6.2  nathanw 		DELAY(1);
    863  1.13.6.2  nathanw 	}
    864  1.13.6.2  nathanw 
    865  1.13.6.2  nathanw 	v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
    866  1.13.6.2  nathanw 	tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
    867  1.13.6.2  nathanw 	return v;
    868  1.13.6.2  nathanw }
    869  1.13.6.2  nathanw 
    870  1.13.6.2  nathanw static u_int8_t
    871  1.13.6.2  nathanw tctrl_read(sc, off)
    872  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    873  1.13.6.2  nathanw 	bus_size_t off;
    874  1.13.6.2  nathanw {
    875  1.13.6.2  nathanw 
    876  1.13.6.2  nathanw 	sc->sc_junk = bus_space_read_1(sc->sc_memt, sc->sc_memh, off);
    877  1.13.6.2  nathanw 	return sc->sc_junk;
    878  1.13.6.2  nathanw }
    879  1.13.6.2  nathanw 
    880  1.13.6.2  nathanw static void
    881  1.13.6.2  nathanw tctrl_write(sc, off, v)
    882  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    883  1.13.6.2  nathanw 	bus_size_t off;
    884  1.13.6.2  nathanw 	u_int8_t v;
    885  1.13.6.2  nathanw {
    886  1.13.6.2  nathanw 
    887  1.13.6.2  nathanw 	sc->sc_junk = v;
    888  1.13.6.2  nathanw 	bus_space_write_1(sc->sc_memt, sc->sc_memh, off, v);
    889  1.13.6.2  nathanw }
    890  1.13.6.2  nathanw 
    891  1.13.6.2  nathanw int
    892  1.13.6.2  nathanw tctrlopen(dev, flags, mode, p)
    893  1.13.6.2  nathanw 	dev_t dev;
    894  1.13.6.2  nathanw 	int flags, mode;
    895  1.13.6.2  nathanw 	struct proc *p;
    896  1.13.6.2  nathanw {
    897  1.13.6.2  nathanw 	int unit = (minor(dev)&0xf0);
    898  1.13.6.2  nathanw 	int ctl = (minor(dev)&0x0f);
    899  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    900  1.13.6.2  nathanw 
    901  1.13.6.2  nathanw 	if (unit >= tctrl_cd.cd_ndevs)
    902  1.13.6.2  nathanw 		return(ENXIO);
    903  1.13.6.2  nathanw 	sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
    904  1.13.6.2  nathanw 	if (!sc)
    905  1.13.6.2  nathanw 		return(ENXIO);
    906  1.13.6.2  nathanw 
    907  1.13.6.2  nathanw 	switch (ctl) {
    908  1.13.6.2  nathanw 	case TCTRL_STD_DEV:
    909  1.13.6.2  nathanw 		break;
    910  1.13.6.2  nathanw 	case TCTRL_APMCTL_DEV:
    911  1.13.6.2  nathanw 		if (!(flags & FWRITE))
    912  1.13.6.2  nathanw 			return(EINVAL);
    913  1.13.6.2  nathanw 		if (sc->sc_flags & TCTRL_APM_CTLOPEN)
    914  1.13.6.2  nathanw 			return(EBUSY);
    915  1.13.6.2  nathanw 		sc->sc_flags |= TCTRL_APM_CTLOPEN;
    916  1.13.6.2  nathanw 		break;
    917  1.13.6.2  nathanw 	default:
    918  1.13.6.2  nathanw 		return(ENXIO);
    919  1.13.6.2  nathanw 		break;
    920  1.13.6.2  nathanw 	}
    921  1.13.6.2  nathanw 
    922  1.13.6.2  nathanw 	return(0);
    923  1.13.6.2  nathanw }
    924  1.13.6.2  nathanw 
    925  1.13.6.2  nathanw int
    926  1.13.6.2  nathanw tctrlclose(dev, flags, mode, p)
    927  1.13.6.2  nathanw 	dev_t dev;
    928  1.13.6.2  nathanw 	int flags, mode;
    929  1.13.6.2  nathanw 	struct proc *p;
    930  1.13.6.2  nathanw {
    931  1.13.6.2  nathanw 	int ctl = (minor(dev)&0x0f);
    932  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    933  1.13.6.2  nathanw 
    934  1.13.6.2  nathanw 	sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
    935  1.13.6.2  nathanw 	if (!sc)
    936  1.13.6.2  nathanw 		return(ENXIO);
    937  1.13.6.2  nathanw 
    938  1.13.6.2  nathanw 	switch (ctl) {
    939  1.13.6.2  nathanw 	case TCTRL_STD_DEV:
    940  1.13.6.2  nathanw 		break;
    941  1.13.6.2  nathanw 	case TCTRL_APMCTL_DEV:
    942  1.13.6.2  nathanw 		sc->sc_flags &= ~TCTRL_APM_CTLOPEN;
    943  1.13.6.2  nathanw 		break;
    944  1.13.6.2  nathanw 	}
    945  1.13.6.2  nathanw 	return(0);
    946  1.13.6.2  nathanw }
    947  1.13.6.2  nathanw 
    948  1.13.6.2  nathanw int
    949  1.13.6.2  nathanw tctrlioctl(dev, cmd, data, flags, p)
    950  1.13.6.2  nathanw         dev_t dev;
    951  1.13.6.2  nathanw         u_long cmd;
    952  1.13.6.2  nathanw         caddr_t data;
    953  1.13.6.2  nathanw         int flags;
    954  1.13.6.2  nathanw         struct proc *p;
    955  1.13.6.2  nathanw {
    956  1.13.6.2  nathanw 	struct tctrl_req req, *reqn;
    957  1.13.6.2  nathanw 	struct tctrl_pwr *pwrreq;
    958  1.13.6.2  nathanw 	envsys_range_t *envrange;
    959  1.13.6.2  nathanw 	envsys_temp_data_t *envdata;
    960  1.13.6.2  nathanw 	envsys_temp_info_t *envinfo;
    961  1.13.6.2  nathanw 	struct apm_power_info *powerp;
    962  1.13.6.2  nathanw 	struct apm_event_info *evp;
    963  1.13.6.2  nathanw 	struct tctrl_softc *sc;
    964  1.13.6.2  nathanw 	int i;
    965  1.13.6.2  nathanw 	u_int j;
    966  1.13.6.2  nathanw 	u_int16_t a;
    967  1.13.6.2  nathanw 	u_int8_t c;
    968  1.13.6.2  nathanw 
    969  1.13.6.2  nathanw 	if (tctrl_cd.cd_devs == NULL
    970  1.13.6.2  nathanw 	    || tctrl_cd.cd_ndevs == 0
    971  1.13.6.2  nathanw 	    || tctrl_cd.cd_devs[TCTRL_STD_DEV] == NULL) {
    972  1.13.6.2  nathanw 		return ENXIO;
    973  1.13.6.2  nathanw 	}
    974  1.13.6.2  nathanw 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    975  1.13.6.2  nathanw         switch (cmd) {
    976  1.13.6.2  nathanw 
    977  1.13.6.2  nathanw 	case APM_IOC_STANDBY:
    978  1.13.6.2  nathanw 		return(EOPNOTSUPP); /* for now */
    979  1.13.6.2  nathanw 
    980  1.13.6.2  nathanw 	case APM_IOC_SUSPEND:
    981  1.13.6.2  nathanw 		return(EOPNOTSUPP); /* for now */
    982  1.13.6.2  nathanw 
    983  1.13.6.2  nathanw 	case APM_IOC_GETPOWER:
    984  1.13.6.2  nathanw 		powerp = (struct apm_power_info *)data;
    985  1.13.6.2  nathanw 		req.cmdbuf[0] = TS102_OP_RD_INT_CHARGE_RATE;
    986  1.13.6.2  nathanw 		req.cmdlen = 1;
    987  1.13.6.2  nathanw 		req.rsplen = 2;
    988  1.13.6.2  nathanw 		req.p = p;
    989  1.13.6.2  nathanw 		tadpole_request(&req, 0);
    990  1.13.6.2  nathanw 		if (req.rspbuf[0] > 0x00)
    991  1.13.6.2  nathanw 			powerp->battery_state = APM_BATT_CHARGING;
    992  1.13.6.2  nathanw 		req.cmdbuf[0] = TS102_OP_RD_INT_CHARGE_LEVEL;
    993  1.13.6.2  nathanw 		req.cmdlen = 1;
    994  1.13.6.2  nathanw 		req.rsplen = 3;
    995  1.13.6.2  nathanw 		req.p = p;
    996  1.13.6.2  nathanw 		tadpole_request(&req, 0);
    997  1.13.6.2  nathanw 		c = req.rspbuf[0];
    998  1.13.6.2  nathanw 		powerp->battery_life = c;
    999  1.13.6.2  nathanw 		if (c > 0x70)	/* the tadpole sometimes dips below zero, and */
   1000  1.13.6.2  nathanw 			c = 0;	/* into the 255 range. */
   1001  1.13.6.2  nathanw 		powerp->minutes_left = (45 * c) / 100; /* XXX based on 45 min */
   1002  1.13.6.2  nathanw 		if (powerp->battery_state != APM_BATT_CHARGING) {
   1003  1.13.6.2  nathanw 			if (c < 0x20)
   1004  1.13.6.2  nathanw 				powerp->battery_state = APM_BATT_CRITICAL;
   1005  1.13.6.2  nathanw 			else if (c < 0x40)
   1006  1.13.6.2  nathanw 				powerp->battery_state = APM_BATT_LOW;
   1007  1.13.6.2  nathanw 			else if (c < 0x66)
   1008  1.13.6.2  nathanw 				powerp->battery_state = APM_BATT_HIGH;
   1009  1.13.6.2  nathanw 			else
   1010  1.13.6.2  nathanw 				powerp->battery_state = APM_BATT_UNKNOWN;
   1011  1.13.6.2  nathanw 		}
   1012  1.13.6.2  nathanw 		req.cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
   1013  1.13.6.2  nathanw 		req.cmdlen = 1;
   1014  1.13.6.2  nathanw 		req.rsplen = 3;
   1015  1.13.6.2  nathanw 		req.p = p;
   1016  1.13.6.2  nathanw 		tadpole_request(&req, 0);
   1017  1.13.6.2  nathanw 		a = req.rspbuf[0] * 256 + req.rspbuf[1];
   1018  1.13.6.2  nathanw 		if (a & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE)
   1019  1.13.6.2  nathanw 			powerp->ac_state = APM_AC_ON;
   1020  1.13.6.2  nathanw 		else
   1021  1.13.6.2  nathanw 			powerp->ac_state = APM_AC_OFF;
   1022  1.13.6.2  nathanw 		break;
   1023  1.13.6.2  nathanw 
   1024  1.13.6.2  nathanw 	case APM_IOC_NEXTEVENT:
   1025  1.13.6.2  nathanw 		if (!sc->sc_event_count)
   1026  1.13.6.2  nathanw 			return EAGAIN;
   1027  1.13.6.2  nathanw 
   1028  1.13.6.2  nathanw 		evp = (struct apm_event_info *)data;
   1029  1.13.6.2  nathanw 		i = sc->sc_event_ptr + APM_NEVENTS - sc->sc_event_count;
   1030  1.13.6.2  nathanw 		i %= APM_NEVENTS;
   1031  1.13.6.2  nathanw 		*evp = sc->sc_event_list[i];
   1032  1.13.6.2  nathanw 		sc->sc_event_count--;
   1033  1.13.6.2  nathanw 		return(0);
   1034  1.13.6.2  nathanw 
   1035  1.13.6.2  nathanw 	/* this ioctl assumes the caller knows exactly what he is doing */
   1036  1.13.6.2  nathanw 	case TCTRL_CMD_REQ:
   1037  1.13.6.2  nathanw 		reqn = (struct tctrl_req *)data;
   1038  1.13.6.2  nathanw 		if ((i = suser(p->p_ucred, &p->p_acflag)) != 0 &&
   1039  1.13.6.2  nathanw 		    (reqn->cmdbuf[0] == TS102_OP_CTL_BITPORT ||
   1040  1.13.6.2  nathanw 		    (reqn->cmdbuf[0] >= TS102_OP_CTL_WATCHDOG &&
   1041  1.13.6.2  nathanw 		    reqn->cmdbuf[0] <= TS102_OP_CTL_SECURITY_KEY) ||
   1042  1.13.6.2  nathanw 		    reqn->cmdbuf[0] == TS102_OP_CTL_TIMEZONE ||
   1043  1.13.6.2  nathanw 		    reqn->cmdbuf[0] == TS102_OP_CTL_DIAGNOSTIC_MODE ||
   1044  1.13.6.2  nathanw 		    reqn->cmdbuf[0] == TS102_OP_CMD_SOFTWARE_RESET ||
   1045  1.13.6.2  nathanw 		    (reqn->cmdbuf[0] >= TS102_OP_CMD_SET_RTC &&
   1046  1.13.6.2  nathanw 		    reqn->cmdbuf[0] < TS102_OP_RD_INT_CHARGE_LEVEL) ||
   1047  1.13.6.2  nathanw 		    reqn->cmdbuf[0] > TS102_OP_RD_EXT_CHARGE_LEVEL))
   1048  1.13.6.2  nathanw 			return(i);
   1049  1.13.6.2  nathanw 		reqn->p = p;
   1050  1.13.6.2  nathanw 		tadpole_request(reqn, 0);
   1051  1.13.6.2  nathanw 		break;
   1052  1.13.6.2  nathanw 
   1053  1.13.6.2  nathanw 	case ENVSYS_VERSION:
   1054  1.13.6.2  nathanw 		*(int32_t *)data = 1000;
   1055  1.13.6.2  nathanw 		break;
   1056  1.13.6.2  nathanw 
   1057  1.13.6.2  nathanw 	case ENVSYS_GRANGE:
   1058  1.13.6.2  nathanw 		envrange = (envsys_range_t *)data;
   1059  1.13.6.2  nathanw 		i = 0;
   1060  1.13.6.2  nathanw 		envrange->high = envrange->low = 0;
   1061  1.13.6.2  nathanw 		for (j=0; j < ENVSYS_NUMSENSORS; j++) {
   1062  1.13.6.2  nathanw 			if (!i && envrange->units == sc->sc_esensors[j].units) {
   1063  1.13.6.2  nathanw 				envrange->low = j;
   1064  1.13.6.2  nathanw 				i++;
   1065  1.13.6.2  nathanw 			}
   1066  1.13.6.2  nathanw 			if (i && envrange->units == sc->sc_esensors[j].units)
   1067  1.13.6.2  nathanw 				envrange->high = j;
   1068  1.13.6.2  nathanw 		}
   1069  1.13.6.2  nathanw 		if (!i) {
   1070  1.13.6.2  nathanw 			envrange->high = 0;
   1071  1.13.6.2  nathanw 			envrange->low = 1;
   1072  1.13.6.2  nathanw 		}
   1073  1.13.6.2  nathanw 		break;
   1074  1.13.6.2  nathanw 
   1075  1.13.6.2  nathanw 	case ENVSYS_GTREDATA:
   1076  1.13.6.2  nathanw 		envdata = (envsys_temp_data_t *)data;
   1077  1.13.6.2  nathanw 		if (envdata->sensor >= ENVSYS_NUMSENSORS) {
   1078  1.13.6.2  nathanw 			envdata->validflags = 0;
   1079  1.13.6.2  nathanw 			break;
   1080  1.13.6.2  nathanw 		}
   1081  1.13.6.2  nathanw 		envdata->warnflags = ENVSYS_WARN_OK;
   1082  1.13.6.2  nathanw 		if (envdata->sensor == 0) {
   1083  1.13.6.2  nathanw 			envdata->validflags |= ENVSYS_FVALID;
   1084  1.13.6.2  nathanw 			req.cmdbuf[0] = TS102_OP_RD_CURRENT_TEMP;
   1085  1.13.6.2  nathanw 			req.cmdlen = 1;
   1086  1.13.6.2  nathanw 			req.rsplen = 2;
   1087  1.13.6.2  nathanw 			req.p = p;
   1088  1.13.6.2  nathanw 			tadpole_request(&req, 0);
   1089  1.13.6.2  nathanw 			envdata->cur.data_us =             /* 273160? */
   1090  1.13.6.2  nathanw 			    (u_int32_t)((int)((int)req.rspbuf[0]-32)*5000000/9+273150000);
   1091  1.13.6.2  nathanw 			envdata->validflags |= ENVSYS_FCURVALID;
   1092  1.13.6.2  nathanw 			req.cmdbuf[0] = TS102_OP_RD_MAX_TEMP;
   1093  1.13.6.2  nathanw 			req.cmdlen = 1;
   1094  1.13.6.2  nathanw 			req.rsplen = 2;
   1095  1.13.6.2  nathanw 			req.p = p;
   1096  1.13.6.2  nathanw 			tadpole_request(&req, 0);
   1097  1.13.6.2  nathanw 			envdata->max.data_us =
   1098  1.13.6.2  nathanw 			    (u_int32_t)((int)((int)req.rspbuf[0]-32)*5000000/9+273150000);
   1099  1.13.6.2  nathanw 			envdata->validflags |= ENVSYS_FMAXVALID;
   1100  1.13.6.2  nathanw 			req.cmdbuf[0] = TS102_OP_RD_MIN_TEMP;
   1101  1.13.6.2  nathanw 			req.cmdlen = 1;
   1102  1.13.6.2  nathanw 			req.rsplen = 2;
   1103  1.13.6.2  nathanw 			req.p = p;
   1104  1.13.6.2  nathanw 			tadpole_request(&req, 0);
   1105  1.13.6.2  nathanw 			envdata->min.data_us =
   1106  1.13.6.2  nathanw 			    (u_int32_t)((int)((int)req.rspbuf[0]-32)*5000000/9+273150000);
   1107  1.13.6.2  nathanw 			envdata->validflags |= ENVSYS_FMINVALID;
   1108  1.13.6.2  nathanw 			envdata->units = sc->sc_esensors[envdata->sensor].units;
   1109  1.13.6.2  nathanw 			break;
   1110  1.13.6.2  nathanw 		} else if (envdata->sensor == 1 || envdata->sensor == 2) {
   1111  1.13.6.2  nathanw 			envdata->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID;
   1112  1.13.6.2  nathanw 			envdata->units = sc->sc_esensors[envdata->sensor].units;
   1113  1.13.6.2  nathanw 			if (envdata->sensor == 1)
   1114  1.13.6.2  nathanw 				req.cmdbuf[0] = TS102_OP_RD_INT_BATT_VLT;
   1115  1.13.6.2  nathanw 			else
   1116  1.13.6.2  nathanw 				req.cmdbuf[0] = TS102_OP_RD_DC_IN_VLT;
   1117  1.13.6.2  nathanw 			req.cmdlen = 1;
   1118  1.13.6.2  nathanw 			req.rsplen = 2;
   1119  1.13.6.2  nathanw 			req.p = p;
   1120  1.13.6.2  nathanw 			tadpole_request(&req, 0);
   1121  1.13.6.2  nathanw 			envdata->cur.data_s = (int32_t)req.rspbuf[0]*1000000/11;
   1122  1.13.6.2  nathanw 			break;
   1123  1.13.6.2  nathanw 		}
   1124  1.13.6.2  nathanw 		break;
   1125  1.13.6.2  nathanw 
   1126  1.13.6.2  nathanw         case ENVSYS_GTREINFO:
   1127  1.13.6.2  nathanw 		envinfo = (envsys_temp_info_t *)data;
   1128  1.13.6.2  nathanw 		if (envinfo->sensor >= ENVSYS_NUMSENSORS) {
   1129  1.13.6.2  nathanw 			envinfo->validflags = 0;
   1130  1.13.6.2  nathanw 			break;
   1131  1.13.6.2  nathanw 		}
   1132  1.13.6.2  nathanw 		envinfo->units = sc->sc_esensors[envinfo->sensor].units;
   1133  1.13.6.2  nathanw 		memcpy(envinfo->desc, sc->sc_esensors[envinfo->sensor].desc,
   1134  1.13.6.2  nathanw 		    sizeof(sc->sc_esensors[envinfo->sensor].desc) >
   1135  1.13.6.2  nathanw 		    sizeof(envinfo->desc) ? sizeof(envinfo->desc) :
   1136  1.13.6.2  nathanw 		    sizeof(sc->sc_esensors[envinfo->sensor].desc));
   1137  1.13.6.2  nathanw 		if (envinfo->units == ENVSYS_STEMP) {
   1138  1.13.6.2  nathanw 			envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID|
   1139  1.13.6.2  nathanw 			    ENVSYS_FMINVALID|ENVSYS_FMAXVALID;
   1140  1.13.6.2  nathanw 		} else if (envinfo->units == ENVSYS_SVOLTS_DC) {
   1141  1.13.6.2  nathanw 			envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID;
   1142  1.13.6.2  nathanw 		} else
   1143  1.13.6.2  nathanw 			envinfo->validflags = 0;
   1144  1.13.6.2  nathanw                 break;
   1145  1.13.6.2  nathanw 
   1146  1.13.6.2  nathanw         case ENVSYS_STREINFO:
   1147  1.13.6.2  nathanw 		envinfo = (envsys_temp_info_t *)data;
   1148  1.13.6.2  nathanw 		if (envinfo->sensor >= ENVSYS_NUMSENSORS) {
   1149  1.13.6.2  nathanw 			envinfo->validflags = 0;
   1150  1.13.6.2  nathanw 			break;
   1151  1.13.6.2  nathanw 		}
   1152  1.13.6.2  nathanw 		if (envinfo->units == sc->sc_esensors[envinfo->sensor].units)
   1153  1.13.6.2  nathanw 			memcpy(sc->sc_esensors[envinfo->sensor].desc,
   1154  1.13.6.2  nathanw 			    envinfo->desc,
   1155  1.13.6.2  nathanw 			    sizeof(envinfo->desc) > sizeof(char)*32 ?
   1156  1.13.6.2  nathanw 			    sizeof(char)*32 : sizeof(envinfo->desc) );
   1157  1.13.6.2  nathanw 		if (envinfo->units == ENVSYS_STEMP) {
   1158  1.13.6.2  nathanw 			envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID|
   1159  1.13.6.2  nathanw 			    ENVSYS_FMINVALID|ENVSYS_FMAXVALID;
   1160  1.13.6.2  nathanw 		} else if (envinfo->units == ENVSYS_SVOLTS_DC) {
   1161  1.13.6.2  nathanw 			envinfo->validflags = ENVSYS_FVALID|ENVSYS_FCURVALID;
   1162  1.13.6.2  nathanw 		} else
   1163  1.13.6.2  nathanw 			envinfo->validflags = 0;
   1164  1.13.6.2  nathanw                 break;
   1165  1.13.6.2  nathanw 
   1166  1.13.6.2  nathanw 	/* serial power mode (via auxiotwo) */
   1167  1.13.6.2  nathanw 	case TCTRL_SERIAL_PWR:
   1168  1.13.6.2  nathanw 		pwrreq = (struct tctrl_pwr *)data;
   1169  1.13.6.2  nathanw 		if (pwrreq->rw)
   1170  1.13.6.2  nathanw 			pwrreq->state = auxiotwoserialgetapm();
   1171  1.13.6.2  nathanw 		else
   1172  1.13.6.2  nathanw 			auxiotwoserialsetapm(pwrreq->state);
   1173  1.13.6.2  nathanw 		break;
   1174  1.13.6.2  nathanw 
   1175  1.13.6.2  nathanw 	/* modem power mode (via auxio) */
   1176  1.13.6.2  nathanw 	case TCTRL_MODEM_PWR:
   1177  1.13.6.2  nathanw 		return(EOPNOTSUPP); /* for now */
   1178  1.13.6.2  nathanw 		break;
   1179  1.13.6.2  nathanw 
   1180  1.13.6.2  nathanw 
   1181  1.13.6.2  nathanw         default:
   1182  1.13.6.2  nathanw                 return (ENOTTY);
   1183  1.13.6.2  nathanw         }
   1184  1.13.6.2  nathanw         return (0);
   1185  1.13.6.2  nathanw }
   1186  1.13.6.2  nathanw 
   1187  1.13.6.2  nathanw int
   1188  1.13.6.2  nathanw tctrlpoll(dev, events, p)
   1189  1.13.6.2  nathanw 	dev_t dev;
   1190  1.13.6.2  nathanw 	int events;
   1191  1.13.6.2  nathanw 	struct proc *p;
   1192  1.13.6.2  nathanw {
   1193  1.13.6.2  nathanw 	struct tctrl_softc *sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
   1194  1.13.6.2  nathanw 	int revents = 0;
   1195  1.13.6.2  nathanw 
   1196  1.13.6.2  nathanw 	if (events & (POLLIN | POLLRDNORM)) {
   1197  1.13.6.2  nathanw 		if (sc->sc_event_count)
   1198  1.13.6.2  nathanw 			revents |= events & (POLLIN | POLLRDNORM);
   1199  1.13.6.2  nathanw 		else
   1200  1.13.6.2  nathanw 			selrecord(p, &sc->sc_rsel);
   1201  1.13.6.2  nathanw 	}
   1202  1.13.6.2  nathanw 
   1203  1.13.6.2  nathanw 	return (revents);
   1204  1.13.6.2  nathanw }
   1205  1.13.6.2  nathanw /* DO NOT SET THIS OPTION */
   1206  1.13.6.2  nathanw #ifdef TADPOLE_BLINK
   1207  1.13.6.2  nathanw void
   1208  1.13.6.2  nathanw cpu_disk_unbusy(busy)
   1209  1.13.6.2  nathanw         int busy;
   1210  1.13.6.2  nathanw {
   1211  1.13.6.2  nathanw 	static struct timeval tctrl_ds_timestamp;
   1212  1.13.6.2  nathanw         struct timeval dv_time, diff_time;
   1213  1.13.6.2  nathanw 	struct tctrl_softc *sc;
   1214  1.13.6.2  nathanw 
   1215  1.13.6.2  nathanw 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
   1216  1.13.6.2  nathanw 
   1217  1.13.6.2  nathanw 	/* quickly bail */
   1218  1.13.6.2  nathanw 	if (!(sc->sc_lcdstate & TS102_LCD_DISK_ACTIVE) || busy > 0)
   1219  1.13.6.2  nathanw 		return;
   1220  1.13.6.2  nathanw 
   1221  1.13.6.2  nathanw         /* we aren't terribly concerned with precision here */
   1222  1.13.6.2  nathanw         dv_time = mono_time;
   1223  1.13.6.2  nathanw         timersub(&dv_time, &tctrl_ds_timestamp, &diff_time);
   1224  1.13.6.2  nathanw 
   1225  1.13.6.2  nathanw 	if (diff_time.tv_sec > 0) {
   1226  1.13.6.2  nathanw                 tctrl_set_lcd(0, TS102_LCD_DISK_ACTIVE);
   1227  1.13.6.2  nathanw 		tctrl_ds_timestamp = mono_time;
   1228  1.13.6.2  nathanw 	}
   1229  1.13.6.2  nathanw }
   1230  1.13.6.2  nathanw #endif
   1231