Home | History | Annotate | Line # | Download | only in dev
tctrl.c revision 1.26.16.5
      1  1.26.16.5      yamt /*	$NetBSD: tctrl.c,v 1.26.16.5 2007/12/07 17:26:12 yamt Exp $	*/
      2        1.1      matt 
      3        1.1      matt /*-
      4  1.26.16.1      yamt  * Copyright (c) 1998, 2005, 2006 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.25     lukem 
     39       1.25     lukem #include <sys/cdefs.h>
     40  1.26.16.5      yamt __KERNEL_RCSID(0, "$NetBSD: tctrl.c,v 1.26.16.5 2007/12/07 17:26:12 yamt Exp $");
     41        1.1      matt 
     42        1.1      matt #include <sys/param.h>
     43        1.1      matt #include <sys/systm.h>
     44        1.1      matt #include <sys/ioctl.h>
     45        1.1      matt #include <sys/select.h>
     46        1.1      matt #include <sys/tty.h>
     47        1.1      matt #include <sys/proc.h>
     48        1.1      matt #include <sys/user.h>
     49        1.1      matt #include <sys/conf.h>
     50        1.1      matt #include <sys/file.h>
     51        1.1      matt #include <sys/uio.h>
     52        1.1      matt #include <sys/kernel.h>
     53  1.26.16.1      yamt #include <sys/kthread.h>
     54        1.1      matt #include <sys/syslog.h>
     55        1.1      matt #include <sys/types.h>
     56        1.1      matt #include <sys/device.h>
     57        1.4   garbled #include <sys/envsys.h>
     58        1.4   garbled #include <sys/poll.h>
     59  1.26.16.1      yamt #include <sys/kauth.h>
     60        1.1      matt 
     61        1.4   garbled #include <machine/apmvar.h>
     62        1.1      matt #include <machine/autoconf.h>
     63        1.1      matt #include <machine/bus.h>
     64       1.11        pk #include <machine/intr.h>
     65        1.4   garbled #include <machine/tctrl.h>
     66        1.1      matt 
     67        1.1      matt #include <sparc/dev/ts102reg.h>
     68        1.1      matt #include <sparc/dev/tctrlvar.h>
     69        1.7       jdc #include <sparc/sparc/auxiotwo.h>
     70  1.26.16.1      yamt #include <sparc/sparc/auxreg.h>
     71  1.26.16.1      yamt 
     72  1.26.16.1      yamt #include <dev/sysmon/sysmonvar.h>
     73  1.26.16.1      yamt #include <dev/sysmon/sysmon_taskq.h>
     74  1.26.16.1      yamt 
     75  1.26.16.1      yamt #include "sysmon_envsys.h"
     76  1.26.16.1      yamt 
     77  1.26.16.1      yamt /*#define TCTRLDEBUG*/
     78  1.26.16.1      yamt 
     79  1.26.16.1      yamt /* disk spinner */
     80  1.26.16.1      yamt #include <sys/disk.h>
     81  1.26.16.1      yamt #include <dev/scsipi/sdvar.h>
     82  1.26.16.1      yamt 
     83  1.26.16.1      yamt /* ethernet carrier */
     84  1.26.16.1      yamt #include <net/if.h>
     85  1.26.16.1      yamt #include <net/if_dl.h>
     86  1.26.16.1      yamt #include <net/if_ether.h>
     87  1.26.16.1      yamt #include <net/if_media.h>
     88  1.26.16.1      yamt #include <dev/ic/lancevar.h>
     89        1.1      matt 
     90       1.15   gehenna extern struct cfdriver tctrl_cd;
     91        1.4   garbled 
     92       1.15   gehenna dev_type_open(tctrlopen);
     93       1.15   gehenna dev_type_close(tctrlclose);
     94       1.15   gehenna dev_type_ioctl(tctrlioctl);
     95       1.15   gehenna dev_type_poll(tctrlpoll);
     96       1.20  jdolecek dev_type_kqfilter(tctrlkqfilter);
     97       1.15   gehenna 
     98       1.15   gehenna const struct cdevsw tctrl_cdevsw = {
     99       1.15   gehenna 	tctrlopen, tctrlclose, noread, nowrite, tctrlioctl,
    100       1.20  jdolecek 	nostop, notty, tctrlpoll, nommap, tctrlkqfilter,
    101       1.15   gehenna };
    102        1.4   garbled 
    103        1.1      matt static const char *tctrl_ext_statuses[16] = {
    104        1.1      matt 	"main power available",
    105        1.1      matt 	"internal battery attached",
    106        1.1      matt 	"external battery attached",
    107        1.1      matt 	"external VGA attached",
    108        1.1      matt 	"external keyboard attached",
    109        1.1      matt 	"external mouse attached",
    110        1.1      matt 	"lid down",
    111        1.1      matt 	"internal battery charging",
    112        1.1      matt 	"external battery charging",
    113        1.1      matt 	"internal battery discharging",
    114        1.1      matt 	"external battery discharging",
    115        1.1      matt };
    116        1.1      matt 
    117        1.1      matt struct tctrl_softc {
    118        1.4   garbled 	struct	device sc_dev;
    119        1.4   garbled 	bus_space_tag_t	sc_memt;
    120        1.4   garbled 	bus_space_handle_t	sc_memh;
    121        1.4   garbled 	unsigned int	sc_junk;
    122        1.4   garbled 	unsigned int	sc_ext_status;
    123        1.4   garbled 	unsigned int	sc_flags;
    124        1.4   garbled #define TCTRL_SEND_REQUEST		0x0001
    125        1.4   garbled #define TCTRL_APM_CTLOPEN		0x0002
    126  1.26.16.1      yamt 	uint32_t	sc_wantdata;
    127  1.26.16.1      yamt 	uint32_t	sc_ext_pending;
    128  1.26.16.1      yamt 	volatile uint16_t	sc_lcdstate;
    129  1.26.16.1      yamt 	uint16_t	sc_lcdwanted;
    130  1.26.16.1      yamt 
    131        1.1      matt 	enum { TCTRL_IDLE, TCTRL_ARGS,
    132        1.1      matt 		TCTRL_ACK, TCTRL_DATA } sc_state;
    133  1.26.16.1      yamt 	uint8_t		sc_cmdbuf[16];
    134  1.26.16.1      yamt 	uint8_t		sc_rspbuf[16];
    135  1.26.16.1      yamt 	uint8_t		sc_bitport;
    136  1.26.16.1      yamt 	uint8_t		sc_tft_on;
    137  1.26.16.1      yamt 	uint8_t		sc_op;
    138  1.26.16.1      yamt 	uint8_t		sc_cmdoff;
    139  1.26.16.1      yamt 	uint8_t		sc_cmdlen;
    140  1.26.16.1      yamt 	uint8_t		sc_rspoff;
    141  1.26.16.1      yamt 	uint8_t		sc_rsplen;
    142        1.4   garbled 	/* APM stuff */
    143        1.4   garbled #define APM_NEVENTS 16
    144        1.4   garbled 	struct	apm_event_info sc_event_list[APM_NEVENTS];
    145        1.4   garbled 	int	sc_event_count;
    146        1.4   garbled 	int	sc_event_ptr;
    147        1.4   garbled 	struct	selinfo sc_rsel;
    148  1.26.16.1      yamt 
    149        1.4   garbled 	/* ENVSYS stuff */
    150        1.4   garbled #define ENVSYS_NUMSENSORS 3
    151        1.4   garbled 	struct	evcnt sc_intrcnt;	/* interrupt counting */
    152  1.26.16.5      yamt 	struct	sysmon_envsys *sc_sme;
    153  1.26.16.4      yamt 	envsys_data_t sc_sensor[ENVSYS_NUMSENSORS];
    154  1.26.16.1      yamt 
    155  1.26.16.1      yamt 	struct	sysmon_pswitch sc_sm_pbutton;	/* power button */
    156  1.26.16.1      yamt 	struct	sysmon_pswitch sc_sm_lid;	/* lid state */
    157  1.26.16.1      yamt 	struct	sysmon_pswitch sc_sm_ac;	/* AC adaptor presence */
    158  1.26.16.1      yamt 	int	sc_powerpressed;
    159  1.26.16.1      yamt 
    160  1.26.16.1      yamt 	/* hardware status stuff */
    161  1.26.16.1      yamt 	int sc_lid;	/* 1 - open, 0 - closed */
    162  1.26.16.1      yamt 	int sc_power_state;
    163  1.26.16.1      yamt 	int sc_spl;
    164  1.26.16.1      yamt 
    165  1.26.16.1      yamt 	/*
    166  1.26.16.1      yamt 	 * we call this when we detect connection or removal of an external
    167  1.26.16.1      yamt 	 * monitor. 0 for no monitor, !=0 for monitor present
    168  1.26.16.1      yamt 	 */
    169  1.26.16.1      yamt 	void (*sc_video_callback)(void *, int);
    170  1.26.16.1      yamt 	void *sc_video_callback_cookie;
    171  1.26.16.1      yamt 	int sc_extvga;
    172  1.26.16.1      yamt 
    173  1.26.16.1      yamt 	uint32_t sc_events;
    174  1.26.16.4      yamt 	lwp_t *sc_thread;			/* event thread */
    175  1.26.16.4      yamt 	kmutex_t sc_requestlock;
    176        1.1      matt };
    177        1.1      matt 
    178        1.4   garbled #define TCTRL_STD_DEV		0
    179        1.4   garbled #define TCTRL_APMCTL_DEV	8
    180        1.1      matt 
    181  1.26.16.1      yamt static int tctrl_match(struct device *, struct cfdata *, void *);
    182  1.26.16.1      yamt static void tctrl_attach(struct device *, struct device *, void *);
    183  1.26.16.1      yamt static void tctrl_write(struct tctrl_softc *, bus_size_t, uint8_t);
    184  1.26.16.1      yamt static uint8_t tctrl_read(struct tctrl_softc *, bus_size_t);
    185  1.26.16.1      yamt static void tctrl_write_data(struct tctrl_softc *, uint8_t);
    186  1.26.16.1      yamt static uint8_t tctrl_read_data(struct tctrl_softc *);
    187  1.26.16.1      yamt static int tctrl_intr(void *);
    188  1.26.16.1      yamt static void tctrl_setup_bitport(void);
    189  1.26.16.1      yamt static void tctrl_setup_bitport_nop(void);
    190  1.26.16.1      yamt static void tctrl_read_ext_status(void);
    191  1.26.16.1      yamt static void tctrl_read_event_status(struct tctrl_softc *);
    192  1.26.16.1      yamt static int tctrl_apm_record_event(struct tctrl_softc *, u_int);
    193  1.26.16.1      yamt static void tctrl_init_lcd(void);
    194  1.26.16.1      yamt 
    195  1.26.16.1      yamt static void tctrl_sensor_setup(struct tctrl_softc *);
    196  1.26.16.5      yamt static void tctrl_refresh(struct sysmon_envsys *, envsys_data_t *);
    197  1.26.16.1      yamt 
    198  1.26.16.1      yamt static void tctrl_power_button_pressed(void *);
    199  1.26.16.1      yamt static void tctrl_lid_state(struct tctrl_softc *);
    200  1.26.16.1      yamt static void tctrl_ac_state(struct tctrl_softc *);
    201  1.26.16.1      yamt 
    202  1.26.16.1      yamt static int tctrl_powerfail(void *);
    203  1.26.16.1      yamt 
    204  1.26.16.1      yamt static void tctrl_event_thread(void *);
    205  1.26.16.1      yamt void tctrl_update_lcd(struct tctrl_softc *);
    206        1.8   thorpej 
    207  1.26.16.1      yamt static void tctrl_lock(struct tctrl_softc *);
    208  1.26.16.1      yamt static void tctrl_unlock(struct tctrl_softc *);
    209        1.1      matt 
    210       1.17   thorpej CFATTACH_DECL(tctrl, sizeof(struct tctrl_softc),
    211       1.18   thorpej     tctrl_match, tctrl_attach, NULL, NULL);
    212        1.1      matt 
    213  1.26.16.4      yamt static int tadpole_request(struct tctrl_req *, int, int);
    214  1.26.16.1      yamt 
    215        1.4   garbled /* XXX wtf is this? see i386/apm.c */
    216        1.4   garbled int tctrl_apm_evindex;
    217        1.1      matt 
    218        1.1      matt static int
    219  1.26.16.1      yamt tctrl_match(struct device *parent, struct cfdata *cf, void *aux)
    220        1.1      matt {
    221        1.1      matt 	union obio_attach_args *uoba = aux;
    222        1.1      matt 	struct sbus_attach_args *sa = &uoba->uoba_sbus;
    223        1.1      matt 
    224        1.1      matt 	if (uoba->uoba_isobio4 != 0) {
    225        1.1      matt 		return (0);
    226        1.1      matt 	}
    227        1.1      matt 
    228        1.1      matt 	/* Tadpole 3GX/3GS uses "uctrl" for the Tadpole Microcontroller
    229        1.1      matt 	 * (who's interface is off the TS102 PCMCIA controller but there
    230        1.1      matt 	 * exists a OpenProm for microcontroller interface).
    231        1.1      matt 	 */
    232        1.1      matt 	return strcmp("uctrl", sa->sa_name) == 0;
    233        1.1      matt }
    234        1.1      matt 
    235        1.1      matt static void
    236  1.26.16.1      yamt tctrl_attach(struct device *parent, struct device *self, void *aux)
    237        1.1      matt {
    238        1.1      matt 	struct tctrl_softc *sc = (void *)self;
    239        1.1      matt 	union obio_attach_args *uoba = aux;
    240        1.1      matt 	struct sbus_attach_args *sa = &uoba->uoba_sbus;
    241        1.2      matt 	unsigned int i, v;
    242        1.1      matt 
    243        1.1      matt 	/* We're living on a sbus slot that looks like an obio that
    244        1.1      matt 	 * looks like an sbus slot.
    245        1.1      matt 	 */
    246        1.1      matt 	sc->sc_memt = sa->sa_bustag;
    247       1.14        pk 	if (sbus_bus_map(sc->sc_memt,
    248       1.14        pk 			 sa->sa_slot,
    249       1.14        pk 			 sa->sa_offset - TS102_REG_UCTRL_INT,
    250       1.14        pk 			 sa->sa_size,
    251       1.14        pk 			 BUS_SPACE_MAP_LINEAR, &sc->sc_memh) != 0) {
    252        1.1      matt 		printf(": can't map registers\n");
    253        1.1      matt 		return;
    254        1.1      matt 	}
    255        1.1      matt 
    256        1.2      matt 	printf("\n");
    257        1.2      matt 
    258        1.1      matt 	sc->sc_tft_on = 1;
    259        1.2      matt 
    260        1.1      matt 	/* clear any pending data.
    261        1.1      matt 	 */
    262        1.1      matt 	for (i = 0; i < 10000; i++) {
    263        1.4   garbled 		if ((TS102_UCTRL_STS_RXNE_STA &
    264        1.4   garbled 		    tctrl_read(sc, TS102_REG_UCTRL_STS)) == 0) {
    265        1.1      matt 			break;
    266        1.1      matt 		}
    267        1.1      matt 		v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
    268        1.2      matt 		tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
    269        1.1      matt 	}
    270        1.1      matt 
    271        1.3        pk 	if (sa->sa_nintr != 0) {
    272       1.11        pk 		(void)bus_intr_establish(sc->sc_memt, sa->sa_pri, IPL_NONE,
    273       1.22        pk 					 tctrl_intr, sc);
    274       1.10       cgd 		evcnt_attach_dynamic(&sc->sc_intrcnt, EVCNT_TYPE_INTR, NULL,
    275       1.22        pk 				     sc->sc_dev.dv_xname, "intr");
    276        1.3        pk 	}
    277        1.2      matt 
    278  1.26.16.1      yamt 	/* See what the external status is */
    279  1.26.16.1      yamt 	sc->sc_ext_status = 0;
    280        1.4   garbled 	tctrl_read_ext_status();
    281        1.2      matt 	if (sc->sc_ext_status != 0) {
    282        1.2      matt 		const char *sep;
    283        1.1      matt 
    284        1.1      matt 		printf("%s: ", sc->sc_dev.dv_xname);
    285        1.2      matt 		v = sc->sc_ext_status;
    286        1.1      matt 		for (i = 0, sep = ""; v != 0; i++, v >>= 1) {
    287        1.1      matt 			if (v & 1) {
    288        1.1      matt 				printf("%s%s", sep, tctrl_ext_statuses[i]);
    289        1.1      matt 				sep = ", ";
    290        1.1      matt 			}
    291        1.1      matt 		}
    292        1.1      matt 		printf("\n");
    293        1.1      matt 	}
    294        1.1      matt 
    295  1.26.16.1      yamt 	/* Get a current of the control bitport */
    296        1.4   garbled 	tctrl_setup_bitport_nop();
    297        1.2      matt 	tctrl_write(sc, TS102_REG_UCTRL_INT,
    298        1.2      matt 		    TS102_UCTRL_INT_RXNE_REQ|TS102_UCTRL_INT_RXNE_MSK);
    299  1.26.16.1      yamt 	sc->sc_lid = (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) == 0;
    300  1.26.16.1      yamt 	sc->sc_power_state = PWR_RESUME;
    301  1.26.16.1      yamt 
    302  1.26.16.1      yamt 	sc->sc_extvga = (sc->sc_ext_status &
    303  1.26.16.1      yamt 	    TS102_EXT_STATUS_EXTERNAL_VGA_ATTACHED) != 0;
    304  1.26.16.1      yamt 	sc->sc_video_callback = NULL;
    305  1.26.16.1      yamt 
    306  1.26.16.1      yamt 
    307        1.4   garbled 	sc->sc_wantdata = 0;
    308        1.4   garbled 	sc->sc_event_count = 0;
    309  1.26.16.1      yamt 	sc->sc_ext_pending = 0;
    310  1.26.16.1      yamt 		sc->sc_ext_pending = 0;
    311        1.4   garbled 
    312  1.26.16.4      yamt 	mutex_init(&sc->sc_requestlock, MUTEX_DEFAULT, IPL_NONE);
    313  1.26.16.4      yamt 
    314  1.26.16.1      yamt 	/* setup sensors and register the power button */
    315  1.26.16.1      yamt 	tctrl_sensor_setup(sc);
    316  1.26.16.1      yamt 	tctrl_lid_state(sc);
    317  1.26.16.1      yamt 	tctrl_ac_state(sc);
    318        1.6   garbled 
    319        1.6   garbled 	/* initialize the LCD */
    320        1.6   garbled 	tctrl_init_lcd();
    321        1.6   garbled 
    322        1.6   garbled 	/* initialize sc_lcdstate */
    323        1.6   garbled 	sc->sc_lcdstate = 0;
    324  1.26.16.1      yamt 	sc->sc_lcdwanted = 0;
    325  1.26.16.1      yamt 	tadpole_set_lcd(2, 0);
    326  1.26.16.1      yamt 
    327  1.26.16.1      yamt 	/* fire up the LCD event thread */
    328  1.26.16.1      yamt 	sc->sc_events = 0;
    329  1.26.16.4      yamt 
    330  1.26.16.4      yamt 	if (kthread_create(PRI_NONE, 0, NULL, tctrl_event_thread, sc,
    331  1.26.16.4      yamt 	    &sc->sc_thread, "%s", sc->sc_dev.dv_xname) != 0) {
    332  1.26.16.4      yamt 		printf("%s: unable to create event kthread",
    333  1.26.16.4      yamt 		    sc->sc_dev.dv_xname);
    334  1.26.16.4      yamt 	}
    335        1.1      matt }
    336        1.1      matt 
    337        1.1      matt static int
    338  1.26.16.1      yamt tctrl_intr(void *arg)
    339        1.1      matt {
    340        1.1      matt 	struct tctrl_softc *sc = arg;
    341        1.1      matt 	unsigned int v, d;
    342        1.1      matt 	int progress = 0;
    343        1.1      matt 
    344        1.1      matt     again:
    345        1.1      matt 	/* find out the cause(s) of the interrupt */
    346       1.12    toddpw 	v = tctrl_read(sc, TS102_REG_UCTRL_STS) & TS102_UCTRL_STS_MASK;
    347        1.1      matt 
    348        1.1      matt 	/* clear the cause(s) of the interrupt */
    349        1.1      matt 	tctrl_write(sc, TS102_REG_UCTRL_STS, v);
    350        1.1      matt 
    351        1.2      matt 	v &= ~(TS102_UCTRL_STS_RXO_STA|TS102_UCTRL_STS_TXE_STA);
    352        1.1      matt 	if (sc->sc_cmdoff >= sc->sc_cmdlen) {
    353        1.2      matt 		v &= ~TS102_UCTRL_STS_TXNF_STA;
    354  1.26.16.1      yamt 		if (tctrl_read(sc, TS102_REG_UCTRL_INT) &
    355  1.26.16.1      yamt 		    TS102_UCTRL_INT_TXNF_REQ) {
    356        1.4   garbled 			tctrl_write(sc, TS102_REG_UCTRL_INT, 0);
    357        1.4   garbled 			progress = 1;
    358        1.4   garbled 		}
    359        1.1      matt 	}
    360        1.4   garbled 	if ((v == 0) && ((sc->sc_flags & TCTRL_SEND_REQUEST) == 0 ||
    361        1.4   garbled 	    sc->sc_state != TCTRL_IDLE)) {
    362        1.4   garbled 		wakeup(sc);
    363        1.1      matt 		return progress;
    364        1.1      matt 	}
    365        1.1      matt 
    366        1.1      matt 	progress = 1;
    367        1.2      matt 	if (v & TS102_UCTRL_STS_RXNE_STA) {
    368        1.1      matt 		d = tctrl_read_data(sc);
    369        1.1      matt 		switch (sc->sc_state) {
    370        1.1      matt 		case TCTRL_IDLE:
    371        1.2      matt 			if (d == 0xfa) {
    372  1.26.16.1      yamt 				/*
    373  1.26.16.1      yamt 				 * external event,
    374  1.26.16.1      yamt 				 * set a flag and wakeup the event thread
    375  1.26.16.1      yamt 				 */
    376  1.26.16.1      yamt 				sc->sc_ext_pending = 1;
    377        1.2      matt 			} else {
    378        1.2      matt 				printf("%s: (op=0x%02x): unexpected data (0x%02x)\n",
    379        1.2      matt 					sc->sc_dev.dv_xname, sc->sc_op, d);
    380        1.1      matt 			}
    381        1.2      matt 			goto again;
    382        1.1      matt 		case TCTRL_ACK:
    383        1.1      matt 			if (d != 0xfe) {
    384        1.2      matt 				printf("%s: (op=0x%02x): unexpected ack value (0x%02x)\n",
    385        1.1      matt 					sc->sc_dev.dv_xname, sc->sc_op, d);
    386        1.1      matt 			}
    387        1.4   garbled #ifdef TCTRLDEBUG
    388        1.2      matt 			printf(" ack=0x%02x", d);
    389        1.2      matt #endif
    390        1.2      matt 			sc->sc_rsplen--;
    391        1.2      matt 			sc->sc_rspoff = 0;
    392        1.1      matt 			sc->sc_state = sc->sc_rsplen ? TCTRL_DATA : TCTRL_IDLE;
    393        1.4   garbled 			sc->sc_wantdata = sc->sc_rsplen ? 1 : 0;
    394        1.4   garbled #ifdef TCTRLDEBUG
    395        1.2      matt 			if (sc->sc_rsplen > 0) {
    396        1.2      matt 				printf(" [data(%u)]", sc->sc_rsplen);
    397        1.2      matt 			} else {
    398        1.2      matt 				printf(" [idle]\n");
    399        1.2      matt 			}
    400        1.2      matt #endif
    401        1.2      matt 			goto again;
    402        1.1      matt 		case TCTRL_DATA:
    403        1.1      matt 			sc->sc_rspbuf[sc->sc_rspoff++] = d;
    404        1.4   garbled #ifdef TCTRLDEBUG
    405        1.2      matt 			printf(" [%d]=0x%02x", sc->sc_rspoff-1, d);
    406        1.2      matt #endif
    407        1.1      matt 			if (sc->sc_rspoff == sc->sc_rsplen) {
    408        1.4   garbled #ifdef TCTRLDEBUG
    409        1.2      matt 				printf(" [idle]\n");
    410        1.2      matt #endif
    411        1.1      matt 				sc->sc_state = TCTRL_IDLE;
    412        1.4   garbled 				sc->sc_wantdata = 0;
    413        1.1      matt 			}
    414        1.2      matt 			goto again;
    415        1.1      matt 		default:
    416        1.1      matt 			printf("%s: (op=0x%02x): unexpected data (0x%02x) in state %d\n",
    417        1.1      matt 			       sc->sc_dev.dv_xname, sc->sc_op, d, sc->sc_state);
    418        1.2      matt 			goto again;
    419        1.1      matt 		}
    420        1.1      matt 	}
    421        1.4   garbled 	if ((sc->sc_state == TCTRL_IDLE && sc->sc_wantdata == 0) ||
    422        1.4   garbled 	    sc->sc_flags & TCTRL_SEND_REQUEST) {
    423        1.4   garbled 		if (sc->sc_flags & TCTRL_SEND_REQUEST) {
    424        1.4   garbled 			sc->sc_flags &= ~TCTRL_SEND_REQUEST;
    425        1.4   garbled 			sc->sc_wantdata = 1;
    426        1.4   garbled 		}
    427        1.1      matt 		if (sc->sc_cmdlen > 0) {
    428        1.1      matt 			tctrl_write(sc, TS102_REG_UCTRL_INT,
    429        1.1      matt 				tctrl_read(sc, TS102_REG_UCTRL_INT)
    430        1.1      matt 				|TS102_UCTRL_INT_TXNF_MSK
    431        1.1      matt 				|TS102_UCTRL_INT_TXNF_REQ);
    432        1.1      matt 			v = tctrl_read(sc, TS102_REG_UCTRL_STS);
    433        1.1      matt 		}
    434        1.1      matt 	}
    435        1.2      matt 	if ((sc->sc_cmdoff < sc->sc_cmdlen) && (v & TS102_UCTRL_STS_TXNF_STA)) {
    436        1.1      matt 		tctrl_write_data(sc, sc->sc_cmdbuf[sc->sc_cmdoff++]);
    437        1.4   garbled #ifdef TCTRLDEBUG
    438        1.2      matt 		if (sc->sc_cmdoff == 1) {
    439        1.2      matt 			printf("%s: op=0x%02x(l=%u)", sc->sc_dev.dv_xname,
    440        1.2      matt 				sc->sc_cmdbuf[0], sc->sc_rsplen);
    441        1.2      matt 		} else {
    442        1.2      matt 			printf(" [%d]=0x%02x", sc->sc_cmdoff-1,
    443        1.2      matt 				sc->sc_cmdbuf[sc->sc_cmdoff-1]);
    444        1.2      matt 		}
    445        1.2      matt #endif
    446        1.1      matt 		if (sc->sc_cmdoff == sc->sc_cmdlen) {
    447        1.1      matt 			sc->sc_state = sc->sc_rsplen ? TCTRL_ACK : TCTRL_IDLE;
    448        1.4   garbled #ifdef TCTRLDEBUG
    449        1.2      matt 			printf(" %s", sc->sc_rsplen ? "[ack]" : "[idle]\n");
    450        1.2      matt #endif
    451        1.2      matt 			if (sc->sc_cmdoff == 1) {
    452        1.2      matt 				sc->sc_op = sc->sc_cmdbuf[0];
    453        1.2      matt 			}
    454        1.1      matt 			tctrl_write(sc, TS102_REG_UCTRL_INT,
    455        1.1      matt 				tctrl_read(sc, TS102_REG_UCTRL_INT)
    456        1.1      matt 				& (~TS102_UCTRL_INT_TXNF_MSK
    457        1.1      matt 				   |TS102_UCTRL_INT_TXNF_REQ));
    458        1.1      matt 		} else if (sc->sc_state == TCTRL_IDLE) {
    459        1.1      matt 			sc->sc_op = sc->sc_cmdbuf[0];
    460        1.1      matt 			sc->sc_state = TCTRL_ARGS;
    461        1.4   garbled #ifdef TCTRLDEBUG
    462        1.2      matt 			printf(" [args]");
    463        1.2      matt #endif
    464        1.1      matt 		}
    465        1.1      matt 	}
    466        1.1      matt 	goto again;
    467        1.1      matt }
    468        1.1      matt 
    469        1.1      matt static void
    470        1.4   garbled tctrl_setup_bitport_nop(void)
    471        1.4   garbled {
    472        1.4   garbled 	struct tctrl_softc *sc;
    473        1.4   garbled 	struct tctrl_req req;
    474        1.4   garbled 	int s;
    475  1.26.16.1      yamt 
    476        1.4   garbled 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    477        1.4   garbled 	req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
    478        1.4   garbled 	req.cmdbuf[1] = 0xff;
    479  1.26.16.1      yamt 	req.cmdbuf[2] = 0x00;
    480        1.4   garbled 	req.cmdlen = 3;
    481        1.4   garbled 	req.rsplen = 2;
    482  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    483        1.4   garbled 	s = splts102();
    484        1.4   garbled 	sc->sc_bitport = (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
    485        1.4   garbled 	splx(s);
    486        1.4   garbled }
    487        1.4   garbled 
    488        1.4   garbled static void
    489        1.4   garbled tctrl_setup_bitport(void)
    490        1.1      matt {
    491        1.4   garbled 	struct tctrl_softc *sc;
    492        1.4   garbled 	struct tctrl_req req;
    493        1.4   garbled 	int s;
    494  1.26.16.1      yamt 
    495        1.4   garbled 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    496        1.4   garbled 	s = splts102();
    497  1.26.16.1      yamt 	req.cmdbuf[2] = 0;
    498        1.4   garbled 	if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
    499        1.4   garbled 	    || (!sc->sc_tft_on)) {
    500        1.4   garbled 		req.cmdbuf[2] = TS102_BITPORT_TFTPWR;
    501        1.4   garbled 	}
    502        1.4   garbled 	req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
    503        1.4   garbled 	req.cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
    504        1.4   garbled 	req.cmdlen = 3;
    505        1.4   garbled 	req.rsplen = 2;
    506  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    507        1.4   garbled 	s = splts102();
    508        1.4   garbled 	sc->sc_bitport = (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
    509        1.4   garbled 	splx(s);
    510        1.4   garbled }
    511        1.4   garbled 
    512        1.6   garbled /*
    513        1.6   garbled  * The tadpole microcontroller is not preprogrammed with icon
    514        1.6   garbled  * representations.  The machine boots with the DC-IN light as
    515        1.6   garbled  * a blank (all 0x00) and the other lights, as 4 rows of horizontal
    516        1.6   garbled  * bars.  The below code initializes the icons in the system to
    517        1.6   garbled  * sane values.  Some of these icons could be used for any purpose
    518        1.6   garbled  * desired, namely the pcmcia, LAN and WAN lights.  For the disk spinner,
    519        1.6   garbled  * only the backslash is unprogrammed.  (sigh)
    520        1.6   garbled  *
    521        1.6   garbled  * programming the icons is simple.  It is a 5x8 matrix, which each row a
    522        1.6   garbled  * bitfield in the order 0x10 0x08 0x04 0x02 0x01.
    523        1.6   garbled  */
    524        1.6   garbled 
    525        1.6   garbled static void
    526        1.6   garbled tctrl_init_lcd(void)
    527        1.6   garbled {
    528        1.6   garbled 	struct tctrl_req req;
    529        1.6   garbled 
    530        1.6   garbled 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    531        1.6   garbled 	req.cmdlen = 11;
    532        1.6   garbled 	req.rsplen = 1;
    533        1.6   garbled 	req.cmdbuf[1] = 0x08;	/*len*/
    534        1.6   garbled 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_DC_GOOD;
    535        1.6   garbled 	req.cmdbuf[3] =  0x00;	/* ..... */
    536        1.6   garbled 	req.cmdbuf[4] =  0x00;	/* ..... */
    537        1.6   garbled 	req.cmdbuf[5] =  0x1f;	/* XXXXX */
    538        1.6   garbled 	req.cmdbuf[6] =  0x00;	/* ..... */
    539        1.6   garbled 	req.cmdbuf[7] =  0x15;	/* X.X.X */
    540        1.6   garbled 	req.cmdbuf[8] =  0x00;	/* ..... */
    541        1.6   garbled 	req.cmdbuf[9] =  0x00;	/* ..... */
    542        1.6   garbled 	req.cmdbuf[10] = 0x00;	/* ..... */
    543  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    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_BACKSLASH;
    550        1.6   garbled 	req.cmdbuf[3] =  0x00;	/* ..... */
    551        1.6   garbled 	req.cmdbuf[4] =  0x10;	/* X.... */
    552        1.6   garbled 	req.cmdbuf[5] =  0x08;	/* .X... */
    553        1.6   garbled 	req.cmdbuf[6] =  0x04;	/* ..X.. */
    554        1.6   garbled 	req.cmdbuf[7] =  0x02;	/* ...X. */
    555        1.6   garbled 	req.cmdbuf[8] =  0x01;	/* ....X */
    556        1.6   garbled 	req.cmdbuf[9] =  0x00;	/* ..... */
    557        1.6   garbled 	req.cmdbuf[10] = 0x00;	/* ..... */
    558  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    559        1.6   garbled 
    560        1.6   garbled 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    561        1.6   garbled 	req.cmdlen = 11;
    562        1.6   garbled 	req.rsplen = 1;
    563        1.6   garbled 	req.cmdbuf[1] = 0x08;	/*len*/
    564        1.6   garbled 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_WAN1;
    565        1.6   garbled 	req.cmdbuf[3] =  0x0c;	/* .XXX. */
    566        1.6   garbled 	req.cmdbuf[4] =  0x16;	/* X.XX. */
    567        1.6   garbled 	req.cmdbuf[5] =  0x10;	/* X.... */
    568        1.6   garbled 	req.cmdbuf[6] =  0x15;	/* X.X.X */
    569        1.6   garbled 	req.cmdbuf[7] =  0x10;	/* X.... */
    570        1.6   garbled 	req.cmdbuf[8] =  0x16;	/* X.XX. */
    571        1.6   garbled 	req.cmdbuf[9] =  0x0c;	/* .XXX. */
    572        1.6   garbled 	req.cmdbuf[10] = 0x00;	/* ..... */
    573  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    574        1.6   garbled 
    575        1.6   garbled 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    576        1.6   garbled 	req.cmdlen = 11;
    577        1.6   garbled 	req.rsplen = 1;
    578        1.6   garbled 	req.cmdbuf[1] = 0x08;	/*len*/
    579        1.6   garbled 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_WAN2;
    580        1.6   garbled 	req.cmdbuf[3] =  0x0c;	/* .XXX. */
    581        1.6   garbled 	req.cmdbuf[4] =  0x0d;	/* .XX.X */
    582        1.6   garbled 	req.cmdbuf[5] =  0x01;	/* ....X */
    583        1.6   garbled 	req.cmdbuf[6] =  0x15;	/* X.X.X */
    584        1.6   garbled 	req.cmdbuf[7] =  0x01;	/* ....X */
    585        1.6   garbled 	req.cmdbuf[8] =  0x0d;	/* .XX.X */
    586        1.6   garbled 	req.cmdbuf[9] =  0x0c;	/* .XXX. */
    587        1.6   garbled 	req.cmdbuf[10] = 0x00;	/* ..... */
    588  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    589        1.6   garbled 
    590        1.6   garbled 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    591        1.6   garbled 	req.cmdlen = 11;
    592        1.6   garbled 	req.rsplen = 1;
    593        1.6   garbled 	req.cmdbuf[1] = 0x08;	/*len*/
    594        1.6   garbled 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_LAN1;
    595        1.6   garbled 	req.cmdbuf[3] =  0x00;	/* ..... */
    596        1.6   garbled 	req.cmdbuf[4] =  0x04;	/* ..X.. */
    597        1.6   garbled 	req.cmdbuf[5] =  0x08;	/* .X... */
    598        1.6   garbled 	req.cmdbuf[6] =  0x13;	/* X..XX */
    599        1.6   garbled 	req.cmdbuf[7] =  0x08;	/* .X... */
    600        1.6   garbled 	req.cmdbuf[8] =  0x04;	/* ..X.. */
    601        1.6   garbled 	req.cmdbuf[9] =  0x00;	/* ..... */
    602        1.6   garbled 	req.cmdbuf[10] = 0x00;	/* ..... */
    603  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    604        1.6   garbled 
    605        1.6   garbled 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    606        1.6   garbled 	req.cmdlen = 11;
    607        1.6   garbled 	req.rsplen = 1;
    608        1.6   garbled 	req.cmdbuf[1] = 0x08;	/*len*/
    609        1.6   garbled 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_LAN2;
    610        1.6   garbled 	req.cmdbuf[3] =  0x00;	/* ..... */
    611        1.6   garbled 	req.cmdbuf[4] =  0x04;	/* ..X.. */
    612        1.6   garbled 	req.cmdbuf[5] =  0x02;	/* ...X. */
    613        1.6   garbled 	req.cmdbuf[6] =  0x19;	/* XX..X */
    614        1.6   garbled 	req.cmdbuf[7] =  0x02;	/* ...X. */
    615        1.6   garbled 	req.cmdbuf[8] =  0x04;	/* ..X.. */
    616        1.6   garbled 	req.cmdbuf[9] =  0x00;	/* ..... */
    617        1.6   garbled 	req.cmdbuf[10] = 0x00;	/* ..... */
    618  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    619        1.6   garbled 
    620        1.6   garbled 	req.cmdbuf[0] = TS102_OP_BLK_DEF_SPCL_CHAR;
    621        1.6   garbled 	req.cmdlen = 11;
    622        1.6   garbled 	req.rsplen = 1;
    623        1.6   garbled 	req.cmdbuf[1] = 0x08;	/*len*/
    624        1.6   garbled 	req.cmdbuf[2] = TS102_BLK_OFF_DEF_PCMCIA;
    625        1.6   garbled 	req.cmdbuf[3] =  0x00;	/* ..... */
    626        1.6   garbled 	req.cmdbuf[4] =  0x0c;	/* .XXX. */
    627        1.6   garbled 	req.cmdbuf[5] =  0x1f;	/* XXXXX */
    628        1.6   garbled 	req.cmdbuf[6] =  0x1f;	/* XXXXX */
    629        1.6   garbled 	req.cmdbuf[7] =  0x1f;	/* XXXXX */
    630        1.6   garbled 	req.cmdbuf[8] =  0x1f;	/* XXXXX */
    631        1.6   garbled 	req.cmdbuf[9] =  0x00;	/* ..... */
    632        1.6   garbled 	req.cmdbuf[10] = 0x00;	/* ..... */
    633  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    634        1.6   garbled }
    635        1.6   garbled 
    636  1.26.16.1      yamt /* sc_lcdwanted -> lcd_state */
    637        1.6   garbled void
    638  1.26.16.1      yamt tctrl_update_lcd(struct tctrl_softc *sc)
    639        1.6   garbled {
    640        1.6   garbled 	struct tctrl_req req;
    641        1.6   garbled 	int s;
    642        1.6   garbled 
    643  1.26.16.1      yamt 	s = splhigh();
    644  1.26.16.1      yamt 	if (sc->sc_lcdwanted == sc->sc_lcdstate) {
    645        1.6   garbled 		splx(s);
    646        1.6   garbled 		return;
    647        1.6   garbled 	}
    648  1.26.16.1      yamt 	sc->sc_lcdstate = sc->sc_lcdwanted;
    649  1.26.16.1      yamt 	splx(s);
    650  1.26.16.1      yamt 
    651        1.6   garbled 	/*
    652        1.6   garbled 	 * the mask setup on this particular command is *very* bizzare
    653        1.6   garbled 	 * and totally undocumented.
    654        1.6   garbled 	 */
    655        1.6   garbled 	req.cmdbuf[0] = TS102_OP_CTL_LCD;
    656  1.26.16.1      yamt 
    657  1.26.16.1      yamt 	/* leave caps-lock alone */
    658  1.26.16.1      yamt 	req.cmdbuf[2] = (u_int8_t)(sc->sc_lcdstate & 0xfe);
    659  1.26.16.1      yamt 	req.cmdbuf[3] = (u_int8_t)((sc->sc_lcdstate & 0x100)>>8);
    660  1.26.16.1      yamt 
    661  1.26.16.1      yamt 	req.cmdbuf[1] = 1;
    662  1.26.16.1      yamt 	req.cmdbuf[4] = 0;
    663  1.26.16.1      yamt 
    664        1.6   garbled 
    665       1.13       wiz 	/* XXX this thing is weird.... */
    666        1.6   garbled 	req.cmdlen = 3;
    667        1.6   garbled 	req.rsplen = 2;
    668  1.26.16.1      yamt 
    669  1.26.16.1      yamt 	/* below are the values one would expect but which won't work */
    670        1.6   garbled #if 0
    671        1.6   garbled 	req.cmdlen = 5;
    672        1.6   garbled 	req.rsplen = 4;
    673        1.6   garbled #endif
    674  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    675  1.26.16.1      yamt }
    676  1.26.16.1      yamt 
    677  1.26.16.1      yamt 
    678  1.26.16.1      yamt /*
    679  1.26.16.1      yamt  * set the blinken-lights on the lcd.  what:
    680  1.26.16.1      yamt  * what = 0 off,  what = 1 on,  what = 2 toggle
    681  1.26.16.1      yamt  */
    682  1.26.16.1      yamt 
    683  1.26.16.1      yamt void
    684  1.26.16.1      yamt tadpole_set_lcd(int what, unsigned short which)
    685  1.26.16.1      yamt {
    686  1.26.16.1      yamt 	struct tctrl_softc *sc;
    687  1.26.16.1      yamt 	int s;
    688  1.26.16.1      yamt 
    689  1.26.16.1      yamt 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    690  1.26.16.1      yamt 
    691  1.26.16.1      yamt 	s = splhigh();
    692  1.26.16.1      yamt 	switch (what) {
    693  1.26.16.1      yamt 		case 0:
    694  1.26.16.1      yamt 			sc->sc_lcdwanted &= ~which;
    695  1.26.16.1      yamt 			break;
    696  1.26.16.1      yamt 		case 1:
    697  1.26.16.1      yamt 			sc->sc_lcdwanted |= which;
    698  1.26.16.1      yamt 			break;
    699  1.26.16.1      yamt 		case 2:
    700  1.26.16.1      yamt 			sc->sc_lcdwanted ^= which;
    701  1.26.16.1      yamt 			break;
    702  1.26.16.1      yamt 	}
    703        1.6   garbled 	splx(s);
    704        1.6   garbled }
    705        1.6   garbled 
    706        1.4   garbled static void
    707        1.4   garbled tctrl_read_ext_status(void)
    708        1.4   garbled {
    709        1.4   garbled 	struct tctrl_softc *sc;
    710        1.4   garbled 	struct tctrl_req req;
    711        1.4   garbled 	int s;
    712  1.26.16.1      yamt 
    713        1.4   garbled 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    714        1.4   garbled 	req.cmdbuf[0] = TS102_OP_RD_EXT_STATUS;
    715        1.4   garbled 	req.cmdlen = 1;
    716        1.4   garbled 	req.rsplen = 3;
    717        1.4   garbled #ifdef TCTRLDEBUG
    718        1.4   garbled 	printf("pre read: sc->sc_ext_status = 0x%x\n", sc->sc_ext_status);
    719        1.4   garbled #endif
    720  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    721        1.4   garbled 	s = splts102();
    722  1.26.16.1      yamt 	sc->sc_ext_status = (req.rspbuf[0] << 8) + req.rspbuf[1];
    723        1.4   garbled 	splx(s);
    724        1.4   garbled #ifdef TCTRLDEBUG
    725        1.4   garbled 	printf("post read: sc->sc_ext_status = 0x%x\n", sc->sc_ext_status);
    726        1.4   garbled #endif
    727        1.4   garbled }
    728        1.4   garbled 
    729        1.4   garbled /*
    730        1.4   garbled  * return 0 if the user will notice and handle the event,
    731        1.4   garbled  * return 1 if the kernel driver should do so.
    732        1.4   garbled  */
    733        1.4   garbled static int
    734  1.26.16.1      yamt tctrl_apm_record_event(struct tctrl_softc *sc, u_int event_type)
    735        1.4   garbled {
    736        1.4   garbled 	struct apm_event_info *evp;
    737        1.4   garbled 
    738        1.4   garbled 	if ((sc->sc_flags & TCTRL_APM_CTLOPEN) &&
    739        1.4   garbled 	    (sc->sc_event_count < APM_NEVENTS)) {
    740        1.4   garbled 		evp = &sc->sc_event_list[sc->sc_event_ptr];
    741        1.4   garbled 		sc->sc_event_count++;
    742        1.4   garbled 		sc->sc_event_ptr++;
    743        1.4   garbled 		sc->sc_event_ptr %= APM_NEVENTS;
    744        1.4   garbled 		evp->type = event_type;
    745        1.4   garbled 		evp->index = ++tctrl_apm_evindex;
    746       1.20  jdolecek 		selnotify(&sc->sc_rsel, 0);
    747        1.4   garbled 		return(sc->sc_flags & TCTRL_APM_CTLOPEN) ? 0 : 1;
    748        1.1      matt 	}
    749        1.4   garbled 	return(1);
    750        1.1      matt }
    751        1.1      matt 
    752        1.1      matt static void
    753  1.26.16.1      yamt tctrl_read_event_status(struct tctrl_softc *sc)
    754        1.1      matt {
    755        1.4   garbled 	struct tctrl_req req;
    756  1.26.16.1      yamt 	int s, lid;
    757  1.26.16.1      yamt 	uint32_t v;
    758  1.26.16.1      yamt 
    759        1.4   garbled 	req.cmdbuf[0] = TS102_OP_RD_EVENT_STATUS;
    760        1.4   garbled 	req.cmdlen = 1;
    761        1.4   garbled 	req.rsplen = 3;
    762  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    763        1.4   garbled 	s = splts102();
    764        1.4   garbled 	v = req.rspbuf[0] * 256 + req.rspbuf[1];
    765  1.26.16.1      yamt #ifdef TCTRLDEBUG
    766  1.26.16.1      yamt 	printf("event: %x\n",v);
    767  1.26.16.1      yamt #endif
    768  1.26.16.1      yamt 	if (v & TS102_EVENT_STATUS_POWERON_BTN_PRESSED) {
    769  1.26.16.1      yamt 		printf("%s: Power button pressed\n",sc->sc_dev.dv_xname);
    770  1.26.16.1      yamt 		tctrl_powerfail(sc);
    771  1.26.16.1      yamt 	}
    772        1.4   garbled 	if (v & TS102_EVENT_STATUS_SHUTDOWN_REQUEST) {
    773        1.4   garbled 		printf("%s: SHUTDOWN REQUEST!\n", sc->sc_dev.dv_xname);
    774  1.26.16.1      yamt 		tctrl_powerfail(sc);
    775        1.4   garbled 	}
    776        1.4   garbled 	if (v & TS102_EVENT_STATUS_VERY_LOW_POWER_WARNING) {
    777        1.4   garbled /*printf("%s: VERY LOW POWER WARNING!\n", sc->sc_dev.dv_xname);*/
    778        1.4   garbled /* according to a tadpole header, and observation */
    779        1.4   garbled #ifdef TCTRLDEBUG
    780  1.26.16.1      yamt 		printf("%s: Battery charge level change\n",
    781  1.26.16.1      yamt 		    sc->sc_dev.dv_xname);
    782        1.4   garbled #endif
    783        1.1      matt 	}
    784        1.4   garbled 	if (v & TS102_EVENT_STATUS_LOW_POWER_WARNING) {
    785        1.4   garbled 		if (tctrl_apm_record_event(sc, APM_BATTERY_LOW))
    786        1.1      matt 			printf("%s: LOW POWER WARNING!\n", sc->sc_dev.dv_xname);
    787        1.4   garbled 	}
    788        1.4   garbled 	if (v & TS102_EVENT_STATUS_DC_STATUS_CHANGE) {
    789        1.4   garbled 		splx(s);
    790        1.4   garbled 		tctrl_read_ext_status();
    791  1.26.16.1      yamt 		tctrl_ac_state(sc);
    792        1.4   garbled 		s = splts102();
    793        1.4   garbled 		if (tctrl_apm_record_event(sc, APM_POWER_CHANGE))
    794        1.1      matt 			printf("%s: main power %s\n", sc->sc_dev.dv_xname,
    795        1.4   garbled 			    (sc->sc_ext_status &
    796        1.4   garbled 			    TS102_EXT_STATUS_MAIN_POWER_AVAILABLE) ?
    797        1.4   garbled 			    "restored" : "removed");
    798        1.4   garbled 	}
    799        1.4   garbled 	if (v & TS102_EVENT_STATUS_LID_STATUS_CHANGE) {
    800        1.4   garbled 		splx(s);
    801        1.4   garbled 		tctrl_read_ext_status();
    802  1.26.16.1      yamt 		tctrl_lid_state(sc);
    803        1.4   garbled 		tctrl_setup_bitport();
    804        1.4   garbled #ifdef TCTRLDEBUG
    805        1.4   garbled 		printf("%s: lid %s\n", sc->sc_dev.dv_xname,
    806        1.4   garbled 		    (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN)
    807        1.4   garbled 		    ? "closed" : "opened");
    808        1.2      matt #endif
    809  1.26.16.1      yamt 		lid = (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) == 0;
    810        1.1      matt 	}
    811  1.26.16.1      yamt 	if (v & TS102_EVENT_STATUS_EXTERNAL_VGA_STATUS_CHANGE) {
    812  1.26.16.1      yamt 		int vga;
    813  1.26.16.1      yamt 		splx(s);
    814  1.26.16.1      yamt 		tctrl_read_ext_status();
    815  1.26.16.1      yamt 		vga = (sc->sc_ext_status &
    816  1.26.16.1      yamt 		    TS102_EXT_STATUS_EXTERNAL_VGA_ATTACHED) != 0;
    817  1.26.16.1      yamt 		if (vga != sc->sc_extvga) {
    818  1.26.16.1      yamt 			sc->sc_extvga = vga;
    819  1.26.16.1      yamt 			if (sc->sc_video_callback != NULL) {
    820  1.26.16.1      yamt 				sc->sc_video_callback(
    821  1.26.16.1      yamt 				    sc->sc_video_callback_cookie,
    822  1.26.16.1      yamt 				    sc->sc_extvga);
    823  1.26.16.1      yamt 			}
    824  1.26.16.1      yamt 		}
    825  1.26.16.1      yamt 	}
    826  1.26.16.1      yamt #ifdef DIAGNOSTIC
    827  1.26.16.1      yamt 	if (v & TS102_EVENT_STATUS_EXT_MOUSE_STATUS_CHANGE) {
    828  1.26.16.1      yamt 		splx(s);
    829  1.26.16.1      yamt 		tctrl_read_ext_status();
    830  1.26.16.1      yamt 		if (sc->sc_ext_status &
    831  1.26.16.1      yamt 		    TS102_EXT_STATUS_EXTERNAL_MOUSE_ATTACHED) {
    832  1.26.16.1      yamt 			printf("tctrl: external mouse detected\n");
    833  1.26.16.1      yamt 		}
    834  1.26.16.1      yamt 	}
    835  1.26.16.1      yamt #endif
    836  1.26.16.1      yamt 	sc->sc_ext_pending = 0;
    837        1.4   garbled 	splx(s);
    838        1.1      matt }
    839        1.1      matt 
    840  1.26.16.1      yamt static void
    841  1.26.16.1      yamt tctrl_lock(struct tctrl_softc *sc)
    842  1.26.16.1      yamt {
    843  1.26.16.1      yamt 
    844  1.26.16.4      yamt 	mutex_enter(&sc->sc_requestlock);
    845  1.26.16.1      yamt }
    846  1.26.16.1      yamt 
    847  1.26.16.1      yamt static void
    848  1.26.16.1      yamt tctrl_unlock(struct tctrl_softc *sc)
    849  1.26.16.1      yamt {
    850  1.26.16.1      yamt 
    851  1.26.16.4      yamt 	mutex_exit(&sc->sc_requestlock);
    852  1.26.16.1      yamt }
    853  1.26.16.1      yamt 
    854  1.26.16.1      yamt int
    855  1.26.16.4      yamt tadpole_request(struct tctrl_req *req, int spin, int sleep)
    856        1.1      matt {
    857        1.1      matt 	struct tctrl_softc *sc;
    858        1.1      matt 	int i, s;
    859        1.1      matt 
    860        1.1      matt 	if (tctrl_cd.cd_devs == NULL
    861        1.1      matt 	    || tctrl_cd.cd_ndevs == 0
    862        1.4   garbled 	    || tctrl_cd.cd_devs[TCTRL_STD_DEV] == NULL) {
    863  1.26.16.1      yamt 		return ENODEV;
    864        1.1      matt 	}
    865        1.1      matt 
    866        1.4   garbled 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    867  1.26.16.1      yamt 	tctrl_lock(sc);
    868  1.26.16.1      yamt 
    869        1.4   garbled 	if (spin)
    870        1.4   garbled 		s = splhigh();
    871        1.4   garbled 	else
    872        1.4   garbled 		s = splts102();
    873        1.4   garbled 	sc->sc_flags |= TCTRL_SEND_REQUEST;
    874        1.4   garbled 	memcpy(sc->sc_cmdbuf, req->cmdbuf, req->cmdlen);
    875  1.26.16.1      yamt #ifdef DIAGNOSTIC
    876  1.26.16.1      yamt 	if (sc->sc_wantdata != 0) {
    877  1.26.16.1      yamt 		splx(s);
    878  1.26.16.1      yamt 		printf("tctrl: we lost the race\n");
    879  1.26.16.1      yamt 		tctrl_unlock(sc);
    880  1.26.16.1      yamt 		return EAGAIN;
    881  1.26.16.1      yamt 	}
    882  1.26.16.1      yamt #endif
    883        1.4   garbled 	sc->sc_wantdata = 1;
    884        1.4   garbled 	sc->sc_rsplen = req->rsplen;
    885        1.4   garbled 	sc->sc_cmdlen = req->cmdlen;
    886        1.4   garbled 	sc->sc_cmdoff = sc->sc_rspoff = 0;
    887        1.4   garbled 
    888        1.4   garbled 	/* we spin for certain commands, like poweroffs */
    889        1.4   garbled 	if (spin) {
    890        1.6   garbled /*		for (i = 0; i < 30000; i++) {*/
    891  1.26.16.1      yamt 		i = 0;
    892  1.26.16.1      yamt 		while ((sc->sc_wantdata == 1) && (i < 30000)) {
    893        1.4   garbled 			tctrl_intr(sc);
    894        1.4   garbled 			DELAY(1);
    895  1.26.16.1      yamt 			i++;
    896        1.4   garbled 		}
    897  1.26.16.1      yamt #ifdef DIAGNOSTIC
    898  1.26.16.1      yamt 		if (i >= 30000) {
    899  1.26.16.1      yamt 			printf("tctrl: timeout busy waiting for micro controller request!\n");
    900  1.26.16.1      yamt 			sc->sc_wantdata = 0;
    901  1.26.16.1      yamt 			splx(s);
    902  1.26.16.1      yamt 			tctrl_unlock(sc);
    903  1.26.16.1      yamt 			return EAGAIN;
    904  1.26.16.1      yamt 		}
    905  1.26.16.1      yamt #endif
    906        1.4   garbled 	} else {
    907  1.26.16.1      yamt 		int timeout = 5 * (sc->sc_rsplen + sc->sc_cmdlen);
    908        1.1      matt 		tctrl_intr(sc);
    909        1.5   garbled 		i = 0;
    910        1.5   garbled 		while (((sc->sc_rspoff != sc->sc_rsplen) ||
    911        1.5   garbled 		    (sc->sc_cmdoff != sc->sc_cmdlen)) &&
    912  1.26.16.1      yamt 		    (i < timeout))
    913  1.26.16.4      yamt 			if (sleep) {
    914        1.5   garbled 				tsleep(sc, PWAIT, "tctrl_data", 15);
    915        1.5   garbled 				i++;
    916  1.26.16.1      yamt 			} else
    917        1.4   garbled 				DELAY(1);
    918  1.26.16.1      yamt #ifdef DIAGNOSTIC
    919  1.26.16.1      yamt 		if (i >= timeout) {
    920  1.26.16.1      yamt 			printf("tctrl: timeout waiting for microcontroller request\n");
    921  1.26.16.1      yamt 			sc->sc_wantdata = 0;
    922  1.26.16.1      yamt 			splx(s);
    923  1.26.16.1      yamt 			tctrl_unlock(sc);
    924  1.26.16.1      yamt 			return EAGAIN;
    925  1.26.16.1      yamt 		}
    926  1.26.16.1      yamt #endif
    927        1.1      matt 	}
    928        1.5   garbled 	/*
    929        1.5   garbled 	 * we give the user a reasonable amount of time for a command
    930        1.5   garbled 	 * to complete.  If it doesn't complete in time, we hand them
    931        1.5   garbled 	 * garbage.  This is here to stop things like setting the
    932        1.5   garbled 	 * rsplen too long, and sleeping forever in a CMD_REQ ioctl.
    933        1.5   garbled 	 */
    934        1.5   garbled 	sc->sc_wantdata = 0;
    935        1.4   garbled 	memcpy(req->rspbuf, sc->sc_rspbuf, req->rsplen);
    936        1.1      matt 	splx(s);
    937  1.26.16.1      yamt 
    938  1.26.16.1      yamt 	tctrl_unlock(sc);
    939  1.26.16.1      yamt 	return 0;
    940        1.1      matt }
    941        1.1      matt 
    942        1.1      matt void
    943        1.4   garbled tadpole_powerdown(void)
    944        1.4   garbled {
    945        1.4   garbled 	struct tctrl_req req;
    946  1.26.16.1      yamt 
    947        1.4   garbled 	req.cmdbuf[0] = TS102_OP_ADMIN_POWER_OFF;
    948        1.4   garbled 	req.cmdlen = 1;
    949        1.4   garbled 	req.rsplen = 1;
    950  1.26.16.4      yamt 	tadpole_request(&req, 1, 0);
    951        1.4   garbled }
    952        1.4   garbled 
    953        1.4   garbled void
    954  1.26.16.1      yamt tadpole_set_video(int enabled)
    955        1.1      matt {
    956        1.1      matt 	struct tctrl_softc *sc;
    957        1.4   garbled 	struct tctrl_req req;
    958        1.1      matt 	int s;
    959        1.1      matt 
    960        1.4   garbled 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
    961        1.4   garbled 	while (sc->sc_wantdata != 0)
    962        1.4   garbled 		DELAY(1);
    963        1.4   garbled 	s = splts102();
    964        1.4   garbled 	if ((sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN && !enabled)
    965        1.4   garbled 	    || (sc->sc_tft_on)) {
    966        1.4   garbled 		req.cmdbuf[2] = TS102_BITPORT_TFTPWR;
    967        1.4   garbled 	} else {
    968        1.4   garbled 		req.cmdbuf[2] = 0;
    969        1.1      matt 	}
    970        1.4   garbled 	req.cmdbuf[0] = TS102_OP_CTL_BITPORT;
    971        1.4   garbled 	req.cmdbuf[1] = ~TS102_BITPORT_TFTPWR;
    972        1.4   garbled 	req.cmdlen = 3;
    973        1.4   garbled 	req.rsplen = 2;
    974        1.1      matt 
    975        1.1      matt 	if ((sc->sc_tft_on && !enabled) || (!sc->sc_tft_on && enabled)) {
    976        1.1      matt 		sc->sc_tft_on = enabled;
    977        1.1      matt 		if (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) {
    978        1.1      matt 			splx(s);
    979        1.1      matt 			return;
    980        1.1      matt 		}
    981  1.26.16.4      yamt 		tadpole_request(&req, 1, 0);
    982        1.4   garbled 		sc->sc_bitport =
    983        1.4   garbled 		    (req.rspbuf[0] & req.cmdbuf[1]) ^ req.cmdbuf[2];
    984        1.1      matt 	}
    985        1.1      matt 	splx(s);
    986        1.1      matt }
    987        1.1      matt 
    988        1.1      matt static void
    989  1.26.16.1      yamt tctrl_write_data(struct tctrl_softc *sc, uint8_t v)
    990        1.1      matt {
    991        1.1      matt 	unsigned int i;
    992        1.4   garbled 
    993        1.1      matt 	for (i = 0; i < 100; i++)  {
    994  1.26.16.1      yamt 		if (TS102_UCTRL_STS_TXNF_STA &
    995  1.26.16.1      yamt 		    tctrl_read(sc, TS102_REG_UCTRL_STS))
    996        1.1      matt 			break;
    997        1.1      matt 	}
    998        1.1      matt 	tctrl_write(sc, TS102_REG_UCTRL_DATA, v);
    999        1.1      matt }
   1000        1.1      matt 
   1001  1.26.16.1      yamt static uint8_t
   1002  1.26.16.1      yamt tctrl_read_data(struct tctrl_softc *sc)
   1003        1.4   garbled {
   1004        1.1      matt 	unsigned int i, v;
   1005        1.1      matt 
   1006        1.1      matt 	for (i = 0; i < 100000; i++) {
   1007  1.26.16.1      yamt 		if (TS102_UCTRL_STS_RXNE_STA &
   1008  1.26.16.1      yamt 		    tctrl_read(sc, TS102_REG_UCTRL_STS))
   1009        1.1      matt 			break;
   1010        1.1      matt 		DELAY(1);
   1011        1.1      matt 	}
   1012        1.1      matt 
   1013        1.1      matt 	v = tctrl_read(sc, TS102_REG_UCTRL_DATA);
   1014        1.2      matt 	tctrl_write(sc, TS102_REG_UCTRL_STS, TS102_UCTRL_STS_RXNE_STA);
   1015        1.1      matt 	return v;
   1016        1.1      matt }
   1017        1.1      matt 
   1018  1.26.16.1      yamt static uint8_t
   1019  1.26.16.1      yamt tctrl_read(struct tctrl_softc *sc, bus_size_t off)
   1020        1.1      matt {
   1021        1.4   garbled 
   1022        1.2      matt 	sc->sc_junk = bus_space_read_1(sc->sc_memt, sc->sc_memh, off);
   1023        1.1      matt 	return sc->sc_junk;
   1024        1.1      matt }
   1025        1.1      matt 
   1026        1.1      matt static void
   1027  1.26.16.1      yamt tctrl_write(struct tctrl_softc *sc, bus_size_t off, uint8_t v)
   1028        1.1      matt {
   1029        1.4   garbled 
   1030        1.1      matt 	sc->sc_junk = v;
   1031        1.2      matt 	bus_space_write_1(sc->sc_memt, sc->sc_memh, off, v);
   1032        1.4   garbled }
   1033        1.4   garbled 
   1034        1.4   garbled int
   1035  1.26.16.1      yamt tctrlopen(dev_t dev, int flags, int mode, struct lwp *l)
   1036        1.4   garbled {
   1037        1.4   garbled 	int unit = (minor(dev)&0xf0);
   1038        1.4   garbled 	int ctl = (minor(dev)&0x0f);
   1039        1.4   garbled 	struct tctrl_softc *sc;
   1040        1.4   garbled 
   1041        1.4   garbled 	if (unit >= tctrl_cd.cd_ndevs)
   1042        1.4   garbled 		return(ENXIO);
   1043        1.4   garbled 	sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
   1044        1.4   garbled 	if (!sc)
   1045        1.4   garbled 		return(ENXIO);
   1046  1.26.16.1      yamt 
   1047        1.4   garbled 	switch (ctl) {
   1048        1.4   garbled 	case TCTRL_STD_DEV:
   1049        1.4   garbled 		break;
   1050        1.4   garbled 	case TCTRL_APMCTL_DEV:
   1051        1.4   garbled 		if (!(flags & FWRITE))
   1052        1.4   garbled 			return(EINVAL);
   1053        1.4   garbled 		if (sc->sc_flags & TCTRL_APM_CTLOPEN)
   1054        1.4   garbled 			return(EBUSY);
   1055        1.4   garbled 		sc->sc_flags |= TCTRL_APM_CTLOPEN;
   1056        1.4   garbled 		break;
   1057        1.4   garbled 	default:
   1058        1.4   garbled 		return(ENXIO);
   1059        1.4   garbled 		break;
   1060        1.4   garbled 	}
   1061        1.4   garbled 
   1062        1.4   garbled 	return(0);
   1063        1.4   garbled }
   1064        1.4   garbled 
   1065        1.4   garbled int
   1066  1.26.16.1      yamt tctrlclose(dev_t dev, int flags, int mode, struct lwp *l)
   1067        1.4   garbled {
   1068        1.4   garbled 	int ctl = (minor(dev)&0x0f);
   1069        1.4   garbled 	struct tctrl_softc *sc;
   1070        1.4   garbled 
   1071        1.4   garbled 	sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
   1072        1.4   garbled 	if (!sc)
   1073        1.4   garbled 		return(ENXIO);
   1074        1.4   garbled 
   1075        1.4   garbled 	switch (ctl) {
   1076        1.4   garbled 	case TCTRL_STD_DEV:
   1077        1.4   garbled 		break;
   1078        1.4   garbled 	case TCTRL_APMCTL_DEV:
   1079        1.4   garbled 		sc->sc_flags &= ~TCTRL_APM_CTLOPEN;
   1080        1.4   garbled 		break;
   1081        1.4   garbled 	}
   1082        1.4   garbled 	return(0);
   1083        1.4   garbled }
   1084        1.4   garbled 
   1085        1.4   garbled int
   1086  1.26.16.4      yamt tctrlioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
   1087        1.4   garbled {
   1088        1.4   garbled 	struct tctrl_req req, *reqn;
   1089  1.26.16.1      yamt 	struct tctrl_pwr *pwrreq;
   1090        1.4   garbled 	struct apm_power_info *powerp;
   1091        1.4   garbled 	struct apm_event_info *evp;
   1092        1.4   garbled 	struct tctrl_softc *sc;
   1093        1.4   garbled 	int i;
   1094  1.26.16.1      yamt 	uint8_t c;
   1095        1.4   garbled 
   1096        1.4   garbled 	if (tctrl_cd.cd_devs == NULL
   1097        1.4   garbled 	    || tctrl_cd.cd_ndevs == 0
   1098        1.4   garbled 	    || tctrl_cd.cd_devs[TCTRL_STD_DEV] == NULL) {
   1099        1.4   garbled 		return ENXIO;
   1100        1.4   garbled 	}
   1101        1.4   garbled 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
   1102        1.4   garbled         switch (cmd) {
   1103        1.4   garbled 
   1104        1.4   garbled 	case APM_IOC_STANDBY:
   1105  1.26.16.1      yamt 		/* turn off backlight and so on ? */
   1106  1.26.16.1      yamt 
   1107  1.26.16.1      yamt 		return 0; /* for now */
   1108        1.4   garbled 
   1109        1.4   garbled 	case APM_IOC_SUSPEND:
   1110  1.26.16.1      yamt 		/* not sure what to do here - we can't really suspend */
   1111  1.26.16.1      yamt 
   1112  1.26.16.1      yamt 		return 0; /* for now */
   1113        1.4   garbled 
   1114       1.19  takemura 	case OAPM_IOC_GETPOWER:
   1115        1.4   garbled 	case APM_IOC_GETPOWER:
   1116        1.4   garbled 		powerp = (struct apm_power_info *)data;
   1117        1.4   garbled 		req.cmdbuf[0] = TS102_OP_RD_INT_CHARGE_RATE;
   1118        1.4   garbled 		req.cmdlen = 1;
   1119        1.4   garbled 		req.rsplen = 2;
   1120  1.26.16.4      yamt 		tadpole_request(&req, 0, l->l_proc ? 1 : 0);
   1121        1.4   garbled 		if (req.rspbuf[0] > 0x00)
   1122        1.4   garbled 			powerp->battery_state = APM_BATT_CHARGING;
   1123        1.4   garbled 		req.cmdbuf[0] = TS102_OP_RD_INT_CHARGE_LEVEL;
   1124        1.4   garbled 		req.cmdlen = 1;
   1125        1.4   garbled 		req.rsplen = 3;
   1126  1.26.16.4      yamt 		tadpole_request(&req, 0, l->l_proc ? 1 : 0);
   1127        1.4   garbled 		c = req.rspbuf[0];
   1128        1.4   garbled 		powerp->battery_life = c;
   1129        1.6   garbled 		if (c > 0x70)	/* the tadpole sometimes dips below zero, and */
   1130        1.6   garbled 			c = 0;	/* into the 255 range. */
   1131        1.4   garbled 		powerp->minutes_left = (45 * c) / 100; /* XXX based on 45 min */
   1132        1.4   garbled 		if (powerp->battery_state != APM_BATT_CHARGING) {
   1133        1.4   garbled 			if (c < 0x20)
   1134        1.4   garbled 				powerp->battery_state = APM_BATT_CRITICAL;
   1135        1.4   garbled 			else if (c < 0x40)
   1136        1.4   garbled 				powerp->battery_state = APM_BATT_LOW;
   1137        1.4   garbled 			else if (c < 0x66)
   1138        1.4   garbled 				powerp->battery_state = APM_BATT_HIGH;
   1139        1.4   garbled 			else
   1140        1.4   garbled 				powerp->battery_state = APM_BATT_UNKNOWN;
   1141        1.4   garbled 		}
   1142  1.26.16.1      yamt 
   1143  1.26.16.1      yamt 		if (sc->sc_ext_status & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE)
   1144        1.4   garbled 			powerp->ac_state = APM_AC_ON;
   1145        1.4   garbled 		else
   1146        1.4   garbled 			powerp->ac_state = APM_AC_OFF;
   1147        1.4   garbled 		break;
   1148        1.4   garbled 
   1149        1.4   garbled 	case APM_IOC_NEXTEVENT:
   1150        1.4   garbled 		if (!sc->sc_event_count)
   1151        1.4   garbled 			return EAGAIN;
   1152        1.4   garbled 
   1153        1.4   garbled 		evp = (struct apm_event_info *)data;
   1154        1.4   garbled 		i = sc->sc_event_ptr + APM_NEVENTS - sc->sc_event_count;
   1155        1.4   garbled 		i %= APM_NEVENTS;
   1156        1.4   garbled 		*evp = sc->sc_event_list[i];
   1157        1.4   garbled 		sc->sc_event_count--;
   1158        1.4   garbled 		return(0);
   1159        1.4   garbled 
   1160        1.4   garbled 	/* this ioctl assumes the caller knows exactly what he is doing */
   1161        1.4   garbled 	case TCTRL_CMD_REQ:
   1162        1.4   garbled 		reqn = (struct tctrl_req *)data;
   1163  1.26.16.2      yamt 		if ((i = kauth_authorize_generic(l->l_cred,
   1164  1.26.16.3      yamt 		    KAUTH_GENERIC_ISSUSER, NULL)) != 0 &&
   1165        1.4   garbled 		    (reqn->cmdbuf[0] == TS102_OP_CTL_BITPORT ||
   1166        1.4   garbled 		    (reqn->cmdbuf[0] >= TS102_OP_CTL_WATCHDOG &&
   1167        1.4   garbled 		    reqn->cmdbuf[0] <= TS102_OP_CTL_SECURITY_KEY) ||
   1168        1.4   garbled 		    reqn->cmdbuf[0] == TS102_OP_CTL_TIMEZONE ||
   1169        1.4   garbled 		    reqn->cmdbuf[0] == TS102_OP_CTL_DIAGNOSTIC_MODE ||
   1170        1.4   garbled 		    reqn->cmdbuf[0] == TS102_OP_CMD_SOFTWARE_RESET ||
   1171        1.4   garbled 		    (reqn->cmdbuf[0] >= TS102_OP_CMD_SET_RTC &&
   1172        1.4   garbled 		    reqn->cmdbuf[0] < TS102_OP_RD_INT_CHARGE_LEVEL) ||
   1173        1.4   garbled 		    reqn->cmdbuf[0] > TS102_OP_RD_EXT_CHARGE_LEVEL))
   1174        1.4   garbled 			return(i);
   1175  1.26.16.4      yamt 		tadpole_request(reqn, 0, l->l_proc ? 1 : 0);
   1176        1.4   garbled 		break;
   1177        1.7       jdc 	/* serial power mode (via auxiotwo) */
   1178        1.7       jdc 	case TCTRL_SERIAL_PWR:
   1179  1.26.16.1      yamt 		pwrreq = (struct tctrl_pwr *)data;
   1180        1.7       jdc 		if (pwrreq->rw)
   1181        1.7       jdc 			pwrreq->state = auxiotwoserialgetapm();
   1182        1.7       jdc 		else
   1183        1.7       jdc 			auxiotwoserialsetapm(pwrreq->state);
   1184        1.7       jdc 		break;
   1185        1.7       jdc 
   1186        1.7       jdc 	/* modem power mode (via auxio) */
   1187        1.7       jdc 	case TCTRL_MODEM_PWR:
   1188        1.7       jdc 		return(EOPNOTSUPP); /* for now */
   1189        1.7       jdc 		break;
   1190        1.4   garbled 
   1191        1.4   garbled 
   1192        1.4   garbled         default:
   1193        1.4   garbled                 return (ENOTTY);
   1194        1.4   garbled         }
   1195        1.4   garbled         return (0);
   1196        1.4   garbled }
   1197        1.4   garbled 
   1198        1.4   garbled int
   1199  1.26.16.1      yamt tctrlpoll(dev_t dev, int events, struct lwp *l)
   1200        1.4   garbled {
   1201        1.4   garbled 	struct tctrl_softc *sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
   1202        1.4   garbled 	int revents = 0;
   1203        1.4   garbled 
   1204        1.4   garbled 	if (events & (POLLIN | POLLRDNORM)) {
   1205        1.4   garbled 		if (sc->sc_event_count)
   1206        1.4   garbled 			revents |= events & (POLLIN | POLLRDNORM);
   1207        1.4   garbled 		else
   1208  1.26.16.1      yamt 			selrecord(l, &sc->sc_rsel);
   1209        1.4   garbled 	}
   1210        1.4   garbled 
   1211        1.4   garbled 	return (revents);
   1212        1.1      matt }
   1213       1.20  jdolecek 
   1214       1.20  jdolecek static void
   1215       1.20  jdolecek filt_tctrlrdetach(struct knote *kn)
   1216       1.20  jdolecek {
   1217       1.20  jdolecek 	struct tctrl_softc *sc = kn->kn_hook;
   1218       1.20  jdolecek 	int s;
   1219       1.20  jdolecek 
   1220       1.20  jdolecek 	s = splts102();
   1221       1.21  christos 	SLIST_REMOVE(&sc->sc_rsel.sel_klist, kn, knote, kn_selnext);
   1222       1.20  jdolecek 	splx(s);
   1223       1.20  jdolecek }
   1224       1.20  jdolecek 
   1225       1.20  jdolecek static int
   1226       1.20  jdolecek filt_tctrlread(struct knote *kn, long hint)
   1227       1.20  jdolecek {
   1228       1.20  jdolecek 	struct tctrl_softc *sc = kn->kn_hook;
   1229       1.20  jdolecek 
   1230       1.20  jdolecek 	kn->kn_data = sc->sc_event_count;
   1231       1.20  jdolecek 	return (kn->kn_data > 0);
   1232       1.20  jdolecek }
   1233       1.20  jdolecek 
   1234       1.20  jdolecek static const struct filterops tctrlread_filtops =
   1235       1.20  jdolecek 	{ 1, NULL, filt_tctrlrdetach, filt_tctrlread };
   1236       1.20  jdolecek 
   1237       1.20  jdolecek int
   1238       1.20  jdolecek tctrlkqfilter(dev_t dev, struct knote *kn)
   1239       1.20  jdolecek {
   1240       1.20  jdolecek 	struct tctrl_softc *sc = tctrl_cd.cd_devs[TCTRL_STD_DEV];
   1241       1.20  jdolecek 	struct klist *klist;
   1242       1.20  jdolecek 	int s;
   1243       1.20  jdolecek 
   1244       1.20  jdolecek 	switch (kn->kn_filter) {
   1245       1.20  jdolecek 	case EVFILT_READ:
   1246       1.21  christos 		klist = &sc->sc_rsel.sel_klist;
   1247       1.20  jdolecek 		kn->kn_fop = &tctrlread_filtops;
   1248       1.20  jdolecek 		break;
   1249       1.20  jdolecek 
   1250       1.20  jdolecek 	default:
   1251       1.20  jdolecek 		return (1);
   1252       1.20  jdolecek 	}
   1253       1.20  jdolecek 
   1254       1.20  jdolecek 	kn->kn_hook = sc;
   1255       1.20  jdolecek 
   1256       1.20  jdolecek 	s = splts102();
   1257       1.20  jdolecek 	SLIST_INSERT_HEAD(klist, kn, kn_selnext);
   1258       1.20  jdolecek 	splx(s);
   1259       1.20  jdolecek 
   1260       1.20  jdolecek 	return (0);
   1261       1.20  jdolecek }
   1262       1.20  jdolecek 
   1263  1.26.16.1      yamt static void
   1264  1.26.16.1      yamt tctrl_sensor_setup(struct tctrl_softc *sc)
   1265  1.26.16.1      yamt {
   1266  1.26.16.5      yamt 	int i, error;
   1267  1.26.16.5      yamt 
   1268  1.26.16.5      yamt 	sc->sc_sme = sysmon_envsys_create();
   1269  1.26.16.1      yamt 
   1270  1.26.16.1      yamt 	/* case temperature */
   1271  1.26.16.4      yamt 	(void)strlcpy(sc->sc_sensor[0].desc, "Case temperature",
   1272  1.26.16.4      yamt 	    sizeof(sc->sc_sensor[0].desc));
   1273  1.26.16.4      yamt 	sc->sc_sensor[0].units = ENVSYS_STEMP;
   1274  1.26.16.1      yamt 
   1275  1.26.16.1      yamt 	/* battery voltage */
   1276  1.26.16.4      yamt 	(void)strlcpy(sc->sc_sensor[1].desc, "Internal battery voltage",
   1277  1.26.16.4      yamt 	    sizeof(sc->sc_sensor[1].desc));
   1278  1.26.16.4      yamt 	sc->sc_sensor[1].units = ENVSYS_SVOLTS_DC;
   1279  1.26.16.1      yamt 
   1280  1.26.16.1      yamt 	/* DC voltage */
   1281  1.26.16.4      yamt 	(void)strlcpy(sc->sc_sensor[2].desc, "DC-In voltage",
   1282  1.26.16.4      yamt 	    sizeof(sc->sc_sensor[2].desc));
   1283  1.26.16.4      yamt 	sc->sc_sensor[2].units = ENVSYS_SVOLTS_DC;
   1284  1.26.16.1      yamt 
   1285  1.26.16.5      yamt 	for (i = 0; i < ENVSYS_NUMSENSORS; i++) {
   1286  1.26.16.5      yamt 		if (sysmon_envsys_sensor_attach(sc->sc_sme,
   1287  1.26.16.5      yamt 						&sc->sc_sensor[i])) {
   1288  1.26.16.5      yamt 			sysmon_envsys_destroy(sc->sc_sme);
   1289  1.26.16.5      yamt 			return;
   1290  1.26.16.5      yamt 		}
   1291  1.26.16.5      yamt 	}
   1292  1.26.16.5      yamt 
   1293  1.26.16.5      yamt 	sc->sc_sme->sme_name = sc->sc_dev.dv_xname;
   1294  1.26.16.5      yamt 	sc->sc_sme->sme_cookie = sc;
   1295  1.26.16.5      yamt 	sc->sc_sme->sme_refresh = tctrl_refresh;
   1296  1.26.16.1      yamt 
   1297  1.26.16.5      yamt 	if ((error = sysmon_envsys_register(sc->sc_sme)) != 0) {
   1298  1.26.16.1      yamt 		printf("%s: couldn't register sensors (%d)\n",
   1299  1.26.16.1      yamt 		    sc->sc_dev.dv_xname, error);
   1300  1.26.16.5      yamt 		sysmon_envsys_destroy(sc->sc_sme);
   1301  1.26.16.5      yamt 		return;
   1302  1.26.16.1      yamt 	}
   1303  1.26.16.1      yamt 
   1304  1.26.16.1      yamt 	/* now register the power button */
   1305  1.26.16.1      yamt 
   1306  1.26.16.1      yamt 	sysmon_task_queue_init();
   1307  1.26.16.1      yamt 
   1308  1.26.16.1      yamt 	sc->sc_powerpressed = 0;
   1309  1.26.16.1      yamt 	memset(&sc->sc_sm_pbutton, 0, sizeof(struct sysmon_pswitch));
   1310  1.26.16.1      yamt 	sc->sc_sm_pbutton.smpsw_name = sc->sc_dev.dv_xname;
   1311  1.26.16.1      yamt 	sc->sc_sm_pbutton.smpsw_type = PSWITCH_TYPE_POWER;
   1312  1.26.16.1      yamt 	if (sysmon_pswitch_register(&sc->sc_sm_pbutton) != 0)
   1313  1.26.16.1      yamt 		printf("%s: unable to register power button with sysmon\n",
   1314  1.26.16.1      yamt 		    sc->sc_dev.dv_xname);
   1315  1.26.16.1      yamt 
   1316  1.26.16.1      yamt 	memset(&sc->sc_sm_lid, 0, sizeof(struct sysmon_pswitch));
   1317  1.26.16.1      yamt 	sc->sc_sm_lid.smpsw_name = sc->sc_dev.dv_xname;
   1318  1.26.16.1      yamt 	sc->sc_sm_lid.smpsw_type = PSWITCH_TYPE_LID;
   1319  1.26.16.1      yamt 	if (sysmon_pswitch_register(&sc->sc_sm_lid) != 0)
   1320  1.26.16.1      yamt 		printf("%s: unable to register lid switch with sysmon\n",
   1321  1.26.16.1      yamt 		    sc->sc_dev.dv_xname);
   1322  1.26.16.1      yamt 
   1323  1.26.16.1      yamt 	memset(&sc->sc_sm_ac, 0, sizeof(struct sysmon_pswitch));
   1324  1.26.16.1      yamt 	sc->sc_sm_ac.smpsw_name = sc->sc_dev.dv_xname;
   1325  1.26.16.1      yamt 	sc->sc_sm_ac.smpsw_type = PSWITCH_TYPE_ACADAPTER;
   1326  1.26.16.1      yamt 	if (sysmon_pswitch_register(&sc->sc_sm_ac) != 0)
   1327  1.26.16.1      yamt 		printf("%s: unable to register AC adaptor with sysmon\n",
   1328  1.26.16.1      yamt 		    sc->sc_dev.dv_xname);
   1329  1.26.16.1      yamt }
   1330  1.26.16.1      yamt 
   1331  1.26.16.1      yamt static void
   1332  1.26.16.1      yamt tctrl_power_button_pressed(void *arg)
   1333  1.26.16.1      yamt {
   1334  1.26.16.1      yamt 	struct tctrl_softc *sc = arg;
   1335  1.26.16.1      yamt 
   1336  1.26.16.1      yamt 	sysmon_pswitch_event(&sc->sc_sm_pbutton, PSWITCH_EVENT_PRESSED);
   1337  1.26.16.1      yamt 	sc->sc_powerpressed = 0;
   1338  1.26.16.1      yamt }
   1339  1.26.16.1      yamt 
   1340  1.26.16.1      yamt static void
   1341  1.26.16.1      yamt tctrl_lid_state(struct tctrl_softc *sc)
   1342  1.26.16.1      yamt {
   1343  1.26.16.1      yamt 	int state;
   1344  1.26.16.1      yamt 
   1345  1.26.16.1      yamt 	state = (sc->sc_ext_status & TS102_EXT_STATUS_LID_DOWN) ?
   1346  1.26.16.4      yamt 	    PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED;
   1347  1.26.16.1      yamt 	sysmon_pswitch_event(&sc->sc_sm_lid, state);
   1348  1.26.16.1      yamt }
   1349  1.26.16.1      yamt 
   1350  1.26.16.1      yamt static void
   1351  1.26.16.1      yamt tctrl_ac_state(struct tctrl_softc *sc)
   1352  1.26.16.1      yamt {
   1353  1.26.16.1      yamt 	int state;
   1354  1.26.16.1      yamt 
   1355  1.26.16.1      yamt 	state = (sc->sc_ext_status & TS102_EXT_STATUS_MAIN_POWER_AVAILABLE) ?
   1356  1.26.16.4      yamt 	    PSWITCH_EVENT_PRESSED : PSWITCH_EVENT_RELEASED;
   1357  1.26.16.1      yamt 	sysmon_pswitch_event(&sc->sc_sm_ac, state);
   1358  1.26.16.1      yamt }
   1359  1.26.16.1      yamt 
   1360  1.26.16.1      yamt static int
   1361  1.26.16.1      yamt tctrl_powerfail(void *arg)
   1362  1.26.16.1      yamt {
   1363  1.26.16.1      yamt 	struct tctrl_softc *sc = (struct tctrl_softc *)arg;
   1364  1.26.16.1      yamt 
   1365  1.26.16.1      yamt 	/*
   1366  1.26.16.1      yamt 	 * We lost power. Queue a callback with thread context to
   1367  1.26.16.1      yamt 	 * handle all the real work.
   1368  1.26.16.1      yamt 	 */
   1369  1.26.16.1      yamt 	if (sc->sc_powerpressed == 0) {
   1370  1.26.16.1      yamt 		sc->sc_powerpressed = 1;
   1371  1.26.16.1      yamt 		sysmon_task_queue_sched(0, tctrl_power_button_pressed, sc);
   1372  1.26.16.1      yamt 	}
   1373  1.26.16.1      yamt 	return (1);
   1374  1.26.16.1      yamt }
   1375  1.26.16.1      yamt 
   1376  1.26.16.5      yamt static void
   1377  1.26.16.5      yamt tctrl_refresh(struct sysmon_envsys *sme, envsys_data_t *edata)
   1378  1.26.16.1      yamt {
   1379  1.26.16.1      yamt 	/*struct tctrl_softc *sc = sme->sme_cookie;*/
   1380  1.26.16.1      yamt 	struct tctrl_req req;
   1381  1.26.16.4      yamt 	int sleepable;
   1382  1.26.16.1      yamt 	int i;
   1383  1.26.16.1      yamt 
   1384  1.26.16.4      yamt 	i = edata->sensor;
   1385  1.26.16.4      yamt 	sleepable = curlwp ? 1 : 0;
   1386  1.26.16.1      yamt 
   1387  1.26.16.1      yamt 	switch (i)
   1388  1.26.16.1      yamt 	{
   1389  1.26.16.1      yamt 		case 0:	/* case temperature */
   1390  1.26.16.1      yamt 			req.cmdbuf[0] = TS102_OP_RD_CURRENT_TEMP;
   1391  1.26.16.1      yamt 			req.cmdlen = 1;
   1392  1.26.16.1      yamt 			req.rsplen = 2;
   1393  1.26.16.4      yamt 			tadpole_request(&req, 0, sleepable);
   1394  1.26.16.4      yamt 			edata->value_cur =             /* 273160? */
   1395  1.26.16.1      yamt 			    (uint32_t)((int)((int)req.rspbuf[0] - 32) * 5000000
   1396  1.26.16.1      yamt 			    / 9 + 273150000);
   1397  1.26.16.1      yamt 			req.cmdbuf[0] = TS102_OP_RD_MAX_TEMP;
   1398  1.26.16.1      yamt 			req.cmdlen = 1;
   1399  1.26.16.1      yamt 			req.rsplen = 2;
   1400  1.26.16.4      yamt 			tadpole_request(&req, 0, sleepable);
   1401  1.26.16.4      yamt 			edata->value_max =
   1402  1.26.16.1      yamt 			    (uint32_t)((int)((int)req.rspbuf[0] - 32) * 5000000
   1403  1.26.16.1      yamt 			    / 9 + 273150000);
   1404  1.26.16.4      yamt 			edata->flags |= ENVSYS_FVALID_MAX;
   1405  1.26.16.1      yamt 			req.cmdbuf[0] = TS102_OP_RD_MIN_TEMP;
   1406  1.26.16.1      yamt 			req.cmdlen = 1;
   1407  1.26.16.1      yamt 			req.rsplen = 2;
   1408  1.26.16.4      yamt 			tadpole_request(&req, 0, sleepable);
   1409  1.26.16.4      yamt 			edata->value_min =
   1410  1.26.16.1      yamt 			    (uint32_t)((int)((int)req.rspbuf[0] - 32) * 5000000
   1411  1.26.16.1      yamt 			    / 9 + 273150000);
   1412  1.26.16.4      yamt 			edata->flags |= ENVSYS_FVALID_MIN;
   1413  1.26.16.4      yamt 			edata->units = ENVSYS_STEMP;
   1414  1.26.16.1      yamt 			break;
   1415  1.26.16.1      yamt 
   1416  1.26.16.1      yamt 		case 1: /* battery voltage */
   1417  1.26.16.1      yamt 			{
   1418  1.26.16.4      yamt 				edata->units = ENVSYS_SVOLTS_DC;
   1419  1.26.16.1      yamt 				req.cmdbuf[0] = TS102_OP_RD_INT_BATT_VLT;
   1420  1.26.16.1      yamt 				req.cmdlen = 1;
   1421  1.26.16.1      yamt 				req.rsplen = 2;
   1422  1.26.16.4      yamt 				tadpole_request(&req, 0, sleepable);
   1423  1.26.16.4      yamt 				edata->value_cur = (int32_t)req.rspbuf[0] *
   1424  1.26.16.1      yamt 				    1000000 / 11;
   1425  1.26.16.1      yamt 			}
   1426  1.26.16.1      yamt 			break;
   1427  1.26.16.1      yamt 		case 2: /* DC voltage */
   1428  1.26.16.1      yamt 			{
   1429  1.26.16.4      yamt 				edata->units = ENVSYS_SVOLTS_DC;
   1430  1.26.16.1      yamt 				req.cmdbuf[0] = TS102_OP_RD_DC_IN_VLT;
   1431  1.26.16.1      yamt 				req.cmdlen = 1;
   1432  1.26.16.1      yamt 				req.rsplen = 2;
   1433  1.26.16.4      yamt 				tadpole_request(&req, 0, sleepable);
   1434  1.26.16.4      yamt 				edata->value_cur = (int32_t)req.rspbuf[0] *
   1435  1.26.16.1      yamt 				    1000000 / 11;
   1436  1.26.16.1      yamt 			}
   1437  1.26.16.1      yamt 			break;
   1438  1.26.16.1      yamt 	}
   1439  1.26.16.4      yamt 	edata->state = ENVSYS_SVALID;
   1440  1.26.16.1      yamt }
   1441  1.26.16.1      yamt 
   1442  1.26.16.1      yamt static void
   1443  1.26.16.1      yamt tctrl_event_thread(void *v)
   1444  1.26.16.1      yamt {
   1445  1.26.16.1      yamt 	struct tctrl_softc *sc = v;
   1446  1.26.16.1      yamt 	struct device *dv;
   1447  1.26.16.1      yamt 	struct sd_softc *sd = NULL;
   1448  1.26.16.1      yamt 	struct lance_softc *le = NULL;
   1449  1.26.16.1      yamt 	int ticks = hz/2;
   1450  1.26.16.1      yamt 	int rcount, wcount;
   1451  1.26.16.1      yamt 	int s;
   1452  1.26.16.1      yamt 
   1453  1.26.16.1      yamt 	while (sd == NULL) {
   1454  1.26.16.1      yamt 		for (dv = alldevs.tqh_first; dv; dv = dv->dv_list.tqe_next) {
   1455  1.26.16.1      yamt 			if (strcmp(dv->dv_xname, "sd0") == 0) {
   1456  1.26.16.1      yamt 			    	sd = (struct sd_softc *)dv;
   1457  1.26.16.1      yamt 			}
   1458  1.26.16.1      yamt 			if (le == NULL) {
   1459  1.26.16.1      yamt 				if (strcmp(dv->dv_xname, "le0") == 0)
   1460  1.26.16.1      yamt 					le = (struct lance_softc *)dv;
   1461  1.26.16.1      yamt 			}
   1462  1.26.16.1      yamt 		}
   1463  1.26.16.1      yamt 		if (sd == NULL)
   1464  1.26.16.1      yamt 			tsleep(&sc->sc_events, PWAIT, "probe_disk", hz);
   1465  1.26.16.1      yamt 	}
   1466  1.26.16.1      yamt 	printf("found %s\n", sd->sc_dev.dv_xname);
   1467  1.26.16.1      yamt 	rcount = sd->sc_dk.dk_stats->io_rxfer;
   1468  1.26.16.1      yamt 	wcount = sd->sc_dk.dk_stats->io_wxfer;
   1469  1.26.16.1      yamt 
   1470  1.26.16.1      yamt 	tctrl_read_event_status(sc);
   1471  1.26.16.1      yamt 
   1472  1.26.16.1      yamt 	while (1) {
   1473  1.26.16.1      yamt 		tsleep(&sc->sc_events, PWAIT, "tctrl_event", ticks);
   1474  1.26.16.1      yamt 		s = splhigh();
   1475  1.26.16.1      yamt 		if ((rcount != sd->sc_dk.dk_stats->io_rxfer) ||
   1476  1.26.16.1      yamt 		    (wcount != sd->sc_dk.dk_stats->io_wxfer)) {
   1477  1.26.16.1      yamt 			rcount = sd->sc_dk.dk_stats->io_rxfer;
   1478  1.26.16.1      yamt 			wcount = sd->sc_dk.dk_stats->io_wxfer;
   1479  1.26.16.1      yamt 			sc->sc_lcdwanted |= TS102_LCD_DISK_ACTIVE;
   1480  1.26.16.1      yamt 		} else
   1481  1.26.16.1      yamt 			sc->sc_lcdwanted &= ~TS102_LCD_DISK_ACTIVE;
   1482  1.26.16.1      yamt 		if (le != NULL) {
   1483  1.26.16.1      yamt 			if (le->sc_havecarrier != 0) {
   1484  1.26.16.1      yamt 				sc->sc_lcdwanted |= TS102_LCD_LAN_ACTIVE;
   1485  1.26.16.1      yamt 			} else
   1486  1.26.16.1      yamt 				sc->sc_lcdwanted &= ~TS102_LCD_LAN_ACTIVE;
   1487  1.26.16.1      yamt 		}
   1488  1.26.16.1      yamt 		splx(s);
   1489  1.26.16.1      yamt 		tctrl_update_lcd(sc);
   1490  1.26.16.1      yamt 		if (sc->sc_ext_pending)
   1491  1.26.16.1      yamt 			tctrl_read_event_status(sc);
   1492  1.26.16.1      yamt 	}
   1493  1.26.16.1      yamt }
   1494  1.26.16.1      yamt 
   1495        1.6   garbled void
   1496  1.26.16.1      yamt tadpole_register_callback(void (*callback)(void *, int), void *cookie)
   1497        1.6   garbled {
   1498        1.6   garbled 	struct tctrl_softc *sc;
   1499        1.6   garbled 
   1500        1.6   garbled 	sc = (struct tctrl_softc *) tctrl_cd.cd_devs[TCTRL_STD_DEV];
   1501  1.26.16.1      yamt 	sc->sc_video_callback = callback;
   1502  1.26.16.1      yamt 	sc->sc_video_callback_cookie = cookie;
   1503  1.26.16.1      yamt 	if (sc->sc_video_callback != NULL) {
   1504  1.26.16.1      yamt 		sc->sc_video_callback(sc->sc_video_callback_cookie,
   1505  1.26.16.1      yamt 		    sc->sc_extvga);
   1506        1.6   garbled 	}
   1507        1.6   garbled }
   1508