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