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