Home | History | Annotate | Line # | Download | only in hil
hil.c revision 1.2.4.2
      1  1.2.4.2  bouyer /*	$NetBSD: hil.c,v 1.2.4.2 2011/03/06 15:07:56 bouyer Exp $	*/
      2  1.2.4.2  bouyer /*	$OpenBSD: hil.c,v 1.24 2010/11/20 16:45:46 miod Exp $	*/
      3  1.2.4.2  bouyer /*
      4  1.2.4.2  bouyer  * Copyright (c) 2003, 2004, Miodrag Vallat.
      5  1.2.4.2  bouyer  * All rights reserved.
      6  1.2.4.2  bouyer  *
      7  1.2.4.2  bouyer  * Redistribution and use in source and binary forms, with or without
      8  1.2.4.2  bouyer  * modification, are permitted provided that the following conditions
      9  1.2.4.2  bouyer  * are met:
     10  1.2.4.2  bouyer  * 1. Redistributions of source code must retain the above copyright
     11  1.2.4.2  bouyer  *    notice, this list of conditions and the following disclaimer.
     12  1.2.4.2  bouyer  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.2.4.2  bouyer  *    notice, this list of conditions and the following disclaimer in the
     14  1.2.4.2  bouyer  *    documentation and/or other materials provided with the distribution.
     15  1.2.4.2  bouyer  *
     16  1.2.4.2  bouyer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  1.2.4.2  bouyer  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18  1.2.4.2  bouyer  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     19  1.2.4.2  bouyer  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
     20  1.2.4.2  bouyer  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     21  1.2.4.2  bouyer  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     22  1.2.4.2  bouyer  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  1.2.4.2  bouyer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
     24  1.2.4.2  bouyer  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
     25  1.2.4.2  bouyer  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     26  1.2.4.2  bouyer  * POSSIBILITY OF SUCH DAMAGE.
     27  1.2.4.2  bouyer  *
     28  1.2.4.2  bouyer  */
     29  1.2.4.2  bouyer 
     30  1.2.4.2  bouyer /*
     31  1.2.4.2  bouyer  * Copyright (c) 1988 University of Utah.
     32  1.2.4.2  bouyer  * Copyright (c) 1990, 1993
     33  1.2.4.2  bouyer  *	The Regents of the University of California.  All rights reserved.
     34  1.2.4.2  bouyer  *
     35  1.2.4.2  bouyer  * This code is derived from software contributed to Berkeley by
     36  1.2.4.2  bouyer  * the Systems Programming Group of the University of Utah Computer
     37  1.2.4.2  bouyer  * Science Department.
     38  1.2.4.2  bouyer  *
     39  1.2.4.2  bouyer  * Redistribution and use in source and binary forms, with or without
     40  1.2.4.2  bouyer  * modification, are permitted provided that the following conditions
     41  1.2.4.2  bouyer  * are met:
     42  1.2.4.2  bouyer  * 1. Redistributions of source code must retain the above copyright
     43  1.2.4.2  bouyer  *    notice, this list of conditions and the following disclaimer.
     44  1.2.4.2  bouyer  * 2. Redistributions in binary form must reproduce the above copyright
     45  1.2.4.2  bouyer  *    notice, this list of conditions and the following disclaimer in the
     46  1.2.4.2  bouyer  *    documentation and/or other materials provided with the distribution.
     47  1.2.4.2  bouyer  * 3. Neither the name of the University nor the names of its contributors
     48  1.2.4.2  bouyer  *    may be used to endorse or promote products derived from this software
     49  1.2.4.2  bouyer  *    without specific prior written permission.
     50  1.2.4.2  bouyer  *
     51  1.2.4.2  bouyer  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     52  1.2.4.2  bouyer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     53  1.2.4.2  bouyer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     54  1.2.4.2  bouyer  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     55  1.2.4.2  bouyer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     56  1.2.4.2  bouyer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     57  1.2.4.2  bouyer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     58  1.2.4.2  bouyer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     59  1.2.4.2  bouyer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     60  1.2.4.2  bouyer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     61  1.2.4.2  bouyer  * SUCH DAMAGE.
     62  1.2.4.2  bouyer  *
     63  1.2.4.2  bouyer  * from: Utah $Hdr: hil.c 1.38 92/01/21$
     64  1.2.4.2  bouyer  *
     65  1.2.4.2  bouyer  *	@(#)hil.c	8.2 (Berkeley) 1/12/94
     66  1.2.4.2  bouyer  */
     67  1.2.4.2  bouyer 
     68  1.2.4.2  bouyer #include <sys/param.h>
     69  1.2.4.2  bouyer #include <sys/systm.h>
     70  1.2.4.2  bouyer #include <sys/conf.h>
     71  1.2.4.2  bouyer #include <sys/device.h>
     72  1.2.4.2  bouyer #include <sys/file.h>
     73  1.2.4.2  bouyer #include <sys/ioctl.h>
     74  1.2.4.2  bouyer #include <sys/kernel.h>
     75  1.2.4.2  bouyer #include <sys/proc.h>
     76  1.2.4.2  bouyer #include <sys/kthread.h>
     77  1.2.4.2  bouyer #include <sys/bus.h>
     78  1.2.4.2  bouyer #include <sys/cpu.h>
     79  1.2.4.2  bouyer 
     80  1.2.4.2  bouyer #include <machine/autoconf.h>
     81  1.2.4.2  bouyer 
     82  1.2.4.2  bouyer #include <dev/hil/hilreg.h>
     83  1.2.4.2  bouyer #include <dev/hil/hilvar.h>
     84  1.2.4.2  bouyer #include <dev/hil/hildevs.h>
     85  1.2.4.2  bouyer #include <dev/hil/hildevs_data.h>
     86  1.2.4.2  bouyer 
     87  1.2.4.2  bouyer #include "hilkbd.h"
     88  1.2.4.2  bouyer 
     89  1.2.4.2  bouyer static void	hilconfig(struct hil_softc *, u_int);
     90  1.2.4.2  bouyer static void	hilempty(struct hil_softc *);
     91  1.2.4.2  bouyer static int	hilsubmatch(device_t, cfdata_t, const int *, void *);
     92  1.2.4.2  bouyer static void	hil_process_int(struct hil_softc *, uint8_t, uint8_t);
     93  1.2.4.2  bouyer static int	hil_process_poll(struct hil_softc *, uint8_t, uint8_t);
     94  1.2.4.2  bouyer static void	hil_thread(void *);
     95  1.2.4.2  bouyer static int	send_device_cmd(struct hil_softc *sc, u_int device, u_int cmd);
     96  1.2.4.2  bouyer static void	polloff(struct hil_softc *);
     97  1.2.4.2  bouyer static void	pollon(struct hil_softc *);
     98  1.2.4.2  bouyer 
     99  1.2.4.2  bouyer static int hilwait(struct hil_softc *);
    100  1.2.4.2  bouyer static int hildatawait(struct hil_softc *);
    101  1.2.4.2  bouyer 
    102  1.2.4.2  bouyer #define	hil_process_pending(sc)	wakeup(&(sc)->sc_pending)
    103  1.2.4.2  bouyer 
    104  1.2.4.2  bouyer static __inline int
    105  1.2.4.2  bouyer hilwait(struct hil_softc *sc)
    106  1.2.4.2  bouyer {
    107  1.2.4.2  bouyer 	int cnt;
    108  1.2.4.2  bouyer 
    109  1.2.4.2  bouyer 	for (cnt = 50000; cnt != 0; cnt--) {
    110  1.2.4.2  bouyer 		DELAY(1);
    111  1.2.4.2  bouyer 		if ((bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) &
    112  1.2.4.2  bouyer 		    HIL_BUSY) == 0)
    113  1.2.4.2  bouyer 			break;
    114  1.2.4.2  bouyer 	}
    115  1.2.4.2  bouyer 
    116  1.2.4.2  bouyer 	return cnt;
    117  1.2.4.2  bouyer }
    118  1.2.4.2  bouyer 
    119  1.2.4.2  bouyer static __inline int
    120  1.2.4.2  bouyer hildatawait(struct hil_softc *sc)
    121  1.2.4.2  bouyer {
    122  1.2.4.2  bouyer 	int cnt;
    123  1.2.4.2  bouyer 
    124  1.2.4.2  bouyer 	for (cnt = 50000; cnt != 0; cnt--) {
    125  1.2.4.2  bouyer 		DELAY(1);
    126  1.2.4.2  bouyer 		if ((bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) &
    127  1.2.4.2  bouyer 		    HIL_DATA_RDY) != 0)
    128  1.2.4.2  bouyer 			break;
    129  1.2.4.2  bouyer 	}
    130  1.2.4.2  bouyer 
    131  1.2.4.2  bouyer 	return cnt;
    132  1.2.4.2  bouyer }
    133  1.2.4.2  bouyer 
    134  1.2.4.2  bouyer /*
    135  1.2.4.2  bouyer  * Common HIL bus attachment
    136  1.2.4.2  bouyer  */
    137  1.2.4.2  bouyer 
    138  1.2.4.2  bouyer void
    139  1.2.4.2  bouyer hil_attach(struct hil_softc *sc, int *hil_is_console)
    140  1.2.4.2  bouyer {
    141  1.2.4.2  bouyer 
    142  1.2.4.2  bouyer 	aprint_normal("\n");
    143  1.2.4.2  bouyer 
    144  1.2.4.2  bouyer 	/*
    145  1.2.4.2  bouyer 	 * Initialize loop information
    146  1.2.4.2  bouyer 	 */
    147  1.2.4.2  bouyer 	sc->sc_cmdending = 0;
    148  1.2.4.2  bouyer 	sc->sc_actdev = sc->sc_cmddev = 0;
    149  1.2.4.2  bouyer 	sc->sc_cmddone = 0;
    150  1.2.4.2  bouyer 	sc->sc_cmdbp = sc->sc_cmdbuf;
    151  1.2.4.2  bouyer 	sc->sc_pollbp = sc->sc_pollbuf;
    152  1.2.4.2  bouyer 	sc->sc_console = hil_is_console;
    153  1.2.4.2  bouyer }
    154  1.2.4.2  bouyer 
    155  1.2.4.2  bouyer /*
    156  1.2.4.2  bouyer  * HIL subdevice attachment
    157  1.2.4.2  bouyer  */
    158  1.2.4.2  bouyer 
    159  1.2.4.2  bouyer int
    160  1.2.4.2  bouyer hildevprint(void *aux, const char *pnp)
    161  1.2.4.2  bouyer {
    162  1.2.4.2  bouyer 	struct hil_attach_args *ha = aux;
    163  1.2.4.2  bouyer 
    164  1.2.4.2  bouyer 	if (pnp != NULL) {
    165  1.2.4.2  bouyer 		aprint_normal("\"%s\" at %s id %x",
    166  1.2.4.2  bouyer 		    ha->ha_descr, pnp, ha->ha_id);
    167  1.2.4.2  bouyer 	}
    168  1.2.4.2  bouyer 	aprint_normal(" code %d", ha->ha_code);
    169  1.2.4.2  bouyer 	if (pnp == NULL) {
    170  1.2.4.2  bouyer 		aprint_normal(": %s", ha->ha_descr);
    171  1.2.4.2  bouyer 	}
    172  1.2.4.2  bouyer 
    173  1.2.4.2  bouyer 	return UNCONF;
    174  1.2.4.2  bouyer }
    175  1.2.4.2  bouyer 
    176  1.2.4.2  bouyer int
    177  1.2.4.2  bouyer hilsubmatch(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
    178  1.2.4.2  bouyer {
    179  1.2.4.2  bouyer 	struct hil_attach_args *ha = aux;
    180  1.2.4.2  bouyer 
    181  1.2.4.2  bouyer 	if (cf->cf_loc[0] != -1 &&
    182  1.2.4.2  bouyer 	    cf->cf_loc[0] != ha->ha_code)
    183  1.2.4.2  bouyer 		return 0;
    184  1.2.4.2  bouyer 
    185  1.2.4.2  bouyer 	return config_match(parent, cf, aux);
    186  1.2.4.2  bouyer }
    187  1.2.4.2  bouyer 
    188  1.2.4.2  bouyer void
    189  1.2.4.2  bouyer hil_attach_deferred(device_t self)
    190  1.2.4.2  bouyer {
    191  1.2.4.2  bouyer 	struct hil_softc *sc = device_private(self);
    192  1.2.4.2  bouyer 	int tries;
    193  1.2.4.2  bouyer 	uint8_t db;
    194  1.2.4.2  bouyer 
    195  1.2.4.2  bouyer 	sc->sc_status = HIL_STATUS_BUSY;
    196  1.2.4.2  bouyer 
    197  1.2.4.2  bouyer 	/*
    198  1.2.4.2  bouyer 	 * Initialize the loop: reconfigure, don't report errors,
    199  1.2.4.2  bouyer 	 * put keyboard in cooked mode, and enable autopolling.
    200  1.2.4.2  bouyer 	 */
    201  1.2.4.2  bouyer 	db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL;
    202  1.2.4.2  bouyer 	send_hil_cmd(sc, HIL_WRITELPCTRL, &db, 1, NULL);
    203  1.2.4.2  bouyer 
    204  1.2.4.2  bouyer 	/*
    205  1.2.4.2  bouyer 	 * Delay one second for reconfiguration and then read the
    206  1.2.4.2  bouyer 	 * data to clear the interrupt (if the loop reconfigured).
    207  1.2.4.2  bouyer 	 */
    208  1.2.4.2  bouyer 	DELAY(1000000);
    209  1.2.4.2  bouyer 	if (bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) &
    210  1.2.4.2  bouyer 	    HIL_DATA_RDY) {
    211  1.2.4.2  bouyer 		db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
    212  1.2.4.2  bouyer 		DELAY(1);
    213  1.2.4.2  bouyer 	}
    214  1.2.4.2  bouyer 
    215  1.2.4.2  bouyer 	/*
    216  1.2.4.2  bouyer 	 * The HIL loop may have reconfigured.  If so we proceed on,
    217  1.2.4.2  bouyer 	 * if not we loop a few times until a successful reconfiguration
    218  1.2.4.2  bouyer 	 * is reported back to us. If the HIL loop is still lost after a
    219  1.2.4.2  bouyer 	 * few seconds, give up.
    220  1.2.4.2  bouyer 	 */
    221  1.2.4.2  bouyer 	for (tries = 10; tries != 0; tries--) {
    222  1.2.4.2  bouyer 		if (send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db) == 0) {
    223  1.2.4.2  bouyer 			if (db & (LPS_CONFFAIL | LPS_CONFGOOD))
    224  1.2.4.2  bouyer 				break;
    225  1.2.4.2  bouyer 		}
    226  1.2.4.2  bouyer 
    227  1.2.4.2  bouyer #ifdef HILDEBUG
    228  1.2.4.2  bouyer 		aprint_debug(self, "%s: loop not ready, retrying...\n");
    229  1.2.4.2  bouyer #endif
    230  1.2.4.2  bouyer 
    231  1.2.4.2  bouyer 		DELAY(1000000);
    232  1.2.4.2  bouyer         }
    233  1.2.4.2  bouyer 
    234  1.2.4.2  bouyer 	if (tries == 0 || (db & LPS_CONFFAIL)) {
    235  1.2.4.2  bouyer 		aprint_normal_dev(self, "no devices\n");
    236  1.2.4.2  bouyer 		sc->sc_pending = 0;
    237  1.2.4.2  bouyer 		if (tries == 0)
    238  1.2.4.2  bouyer 			return;
    239  1.2.4.2  bouyer 	}
    240  1.2.4.2  bouyer 
    241  1.2.4.2  bouyer 	/*
    242  1.2.4.2  bouyer 	 * Create asynchronous loop event handler thread.
    243  1.2.4.2  bouyer 	 */
    244  1.2.4.2  bouyer 	if (kthread_create(PRI_NONE, 0, NULL, hil_thread, sc, &sc->sc_thread,
    245  1.2.4.2  bouyer 	    "%s", device_xname(sc->sc_dev)) != 0) {
    246  1.2.4.2  bouyer 		aprint_error_dev(self, "unable to create event thread\n");
    247  1.2.4.2  bouyer 		return;
    248  1.2.4.2  bouyer 	}
    249  1.2.4.2  bouyer 
    250  1.2.4.2  bouyer 	/*
    251  1.2.4.2  bouyer 	 * Enable loop interrupts.
    252  1.2.4.2  bouyer 	 */
    253  1.2.4.2  bouyer 	send_hil_cmd(sc, HIL_INTON, NULL, 0, NULL);
    254  1.2.4.2  bouyer 
    255  1.2.4.2  bouyer 	/*
    256  1.2.4.2  bouyer 	 * Reconfigure if necessary
    257  1.2.4.2  bouyer 	 */
    258  1.2.4.2  bouyer 	sc->sc_status = HIL_STATUS_READY;
    259  1.2.4.2  bouyer 	hil_process_pending(sc);
    260  1.2.4.2  bouyer }
    261  1.2.4.2  bouyer 
    262  1.2.4.2  bouyer /*
    263  1.2.4.2  bouyer  * Asynchronous event processing
    264  1.2.4.2  bouyer  */
    265  1.2.4.2  bouyer 
    266  1.2.4.2  bouyer int
    267  1.2.4.2  bouyer hil_intr(void *v)
    268  1.2.4.2  bouyer {
    269  1.2.4.2  bouyer 	struct hil_softc *sc = v;
    270  1.2.4.2  bouyer 	uint8_t c, stat;
    271  1.2.4.2  bouyer 
    272  1.2.4.2  bouyer 	if (cold)
    273  1.2.4.2  bouyer 		return 0;
    274  1.2.4.2  bouyer 
    275  1.2.4.2  bouyer 	stat = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT);
    276  1.2.4.2  bouyer 
    277  1.2.4.2  bouyer 	/*
    278  1.2.4.2  bouyer 	 * This should never happen if the interrupt comes from the
    279  1.2.4.2  bouyer 	 * loop.
    280  1.2.4.2  bouyer 	 */
    281  1.2.4.2  bouyer 	if ((stat & HIL_DATA_RDY) == 0)
    282  1.2.4.2  bouyer 		return 0;	/* not for us */
    283  1.2.4.2  bouyer 
    284  1.2.4.2  bouyer 	c = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
    285  1.2.4.2  bouyer 	    HILP_DATA);	/* clears interrupt */
    286  1.2.4.2  bouyer 	DELAY(1);
    287  1.2.4.2  bouyer 
    288  1.2.4.2  bouyer 	hil_process_int(sc, stat, c);
    289  1.2.4.2  bouyer 
    290  1.2.4.2  bouyer 	if (sc->sc_status != HIL_STATUS_BUSY)
    291  1.2.4.2  bouyer 		hil_process_pending(sc);
    292  1.2.4.2  bouyer 
    293  1.2.4.2  bouyer 	return 1;
    294  1.2.4.2  bouyer }
    295  1.2.4.2  bouyer 
    296  1.2.4.2  bouyer void
    297  1.2.4.2  bouyer hil_process_int(struct hil_softc *sc, uint8_t stat, uint8_t c)
    298  1.2.4.2  bouyer {
    299  1.2.4.2  bouyer 	device_t child;
    300  1.2.4.2  bouyer 	struct hildev_softc *hdsc;
    301  1.2.4.2  bouyer 
    302  1.2.4.2  bouyer 	switch ((stat >> HIL_SSHIFT) & HIL_SMASK) {
    303  1.2.4.2  bouyer 	case HIL_STATUS:
    304  1.2.4.2  bouyer 		if (c & HIL_ERROR) {
    305  1.2.4.2  bouyer 		  	sc->sc_cmddone = 1;
    306  1.2.4.2  bouyer 			switch (c) {
    307  1.2.4.2  bouyer 			case HIL_RECONFIG:
    308  1.2.4.2  bouyer 				sc->sc_pending = HIL_PENDING_RECONFIG;
    309  1.2.4.2  bouyer 				break;
    310  1.2.4.2  bouyer 			case HIL_UNPLUGGED:
    311  1.2.4.2  bouyer 				sc->sc_pending = HIL_PENDING_UNPLUGGED;
    312  1.2.4.2  bouyer 				break;
    313  1.2.4.2  bouyer 			}
    314  1.2.4.2  bouyer 			break;
    315  1.2.4.2  bouyer 		}
    316  1.2.4.2  bouyer 		if (c & HIL_COMMAND) {
    317  1.2.4.2  bouyer 		  	if (c & HIL_POLLDATA) {	/* End of data */
    318  1.2.4.2  bouyer 				child = sc->sc_devices[sc->sc_actdev];
    319  1.2.4.2  bouyer 				if (child != NULL) {
    320  1.2.4.2  bouyer 					hdsc = device_private(child);
    321  1.2.4.2  bouyer 					if (hdsc->sc_fn != NULL)
    322  1.2.4.2  bouyer 						(*hdsc->sc_fn)(hdsc,
    323  1.2.4.2  bouyer 						    sc->sc_pollbp
    324  1.2.4.2  bouyer 						    - sc->sc_pollbuf,
    325  1.2.4.2  bouyer 						    sc->sc_pollbuf);
    326  1.2.4.2  bouyer 				}
    327  1.2.4.2  bouyer 			} else {		/* End of command */
    328  1.2.4.2  bouyer 			  	sc->sc_cmdending = 1;
    329  1.2.4.2  bouyer 			}
    330  1.2.4.2  bouyer 			sc->sc_actdev = 0;
    331  1.2.4.2  bouyer 		} else {
    332  1.2.4.2  bouyer 		  	if (c & HIL_POLLDATA) {	/* Start of polled data */
    333  1.2.4.2  bouyer 				sc->sc_actdev = (c & HIL_DEVMASK);
    334  1.2.4.2  bouyer 				sc->sc_pollbp = sc->sc_pollbuf;
    335  1.2.4.2  bouyer 			} else {		/* Start of command */
    336  1.2.4.2  bouyer 				if (sc->sc_cmddev == (c & HIL_DEVMASK)) {
    337  1.2.4.2  bouyer 					sc->sc_cmdbp = sc->sc_cmdbuf;
    338  1.2.4.2  bouyer 					sc->sc_actdev = 0;
    339  1.2.4.2  bouyer 				}
    340  1.2.4.2  bouyer 			}
    341  1.2.4.2  bouyer 		}
    342  1.2.4.2  bouyer 	        break;
    343  1.2.4.2  bouyer 	case HIL_DATA:
    344  1.2.4.2  bouyer 		if (sc->sc_actdev != 0)	/* Collecting poll data */
    345  1.2.4.2  bouyer 			*sc->sc_pollbp++ = c;
    346  1.2.4.2  bouyer 		else {
    347  1.2.4.2  bouyer 			if (sc->sc_cmddev != 0) {  /* Collecting cmd data */
    348  1.2.4.2  bouyer 				if (sc->sc_cmdending) {
    349  1.2.4.2  bouyer 					sc->sc_cmddone = 1;
    350  1.2.4.2  bouyer 					sc->sc_cmdending = 0;
    351  1.2.4.2  bouyer 				} else
    352  1.2.4.2  bouyer 					*sc->sc_cmdbp++ = c;
    353  1.2.4.2  bouyer 		        }
    354  1.2.4.2  bouyer 		}
    355  1.2.4.2  bouyer 		break;
    356  1.2.4.2  bouyer 	}
    357  1.2.4.2  bouyer }
    358  1.2.4.2  bouyer 
    359  1.2.4.2  bouyer /*
    360  1.2.4.2  bouyer  * Same as above, but in polled mode: return data as it gets seen, instead
    361  1.2.4.2  bouyer  * of buffering it.
    362  1.2.4.2  bouyer  */
    363  1.2.4.2  bouyer int
    364  1.2.4.2  bouyer hil_process_poll(struct hil_softc *sc, uint8_t stat, uint8_t c)
    365  1.2.4.2  bouyer {
    366  1.2.4.2  bouyer 	uint8_t db;
    367  1.2.4.2  bouyer 
    368  1.2.4.2  bouyer 	switch ((stat >> HIL_SSHIFT) & HIL_SMASK) {
    369  1.2.4.2  bouyer 	case HIL_STATUS:
    370  1.2.4.2  bouyer 		if (c & HIL_ERROR) {
    371  1.2.4.2  bouyer 		  	sc->sc_cmddone = 1;
    372  1.2.4.2  bouyer 			switch (c) {
    373  1.2.4.2  bouyer 			case HIL_RECONFIG:
    374  1.2.4.2  bouyer 				/*
    375  1.2.4.2  bouyer 				 * Remember that a configuration event
    376  1.2.4.2  bouyer 				 * occurred; it will be processed upon
    377  1.2.4.2  bouyer 				 * leaving polled mode...
    378  1.2.4.2  bouyer 				 */
    379  1.2.4.2  bouyer 				sc->sc_pending = HIL_PENDING_RECONFIG;
    380  1.2.4.2  bouyer 				/*
    381  1.2.4.2  bouyer 				 * However, the keyboard will come back as
    382  1.2.4.2  bouyer 				 * cooked, and we rely on it being in raw
    383  1.2.4.2  bouyer 				 * mode. So, put it back in raw mode right
    384  1.2.4.2  bouyer 				 * now.
    385  1.2.4.2  bouyer 				 */
    386  1.2.4.2  bouyer 				db = 0;
    387  1.2.4.2  bouyer 				send_hil_cmd(sc, HIL_WRITEKBDSADR, &db,
    388  1.2.4.2  bouyer 				    1, NULL);
    389  1.2.4.2  bouyer 				break;
    390  1.2.4.2  bouyer 			case HIL_UNPLUGGED:
    391  1.2.4.2  bouyer 				/*
    392  1.2.4.2  bouyer 				 * Remember that an unplugged event
    393  1.2.4.2  bouyer 				 * occured; it will be processed upon
    394  1.2.4.2  bouyer 				 * leaving polled mode...
    395  1.2.4.2  bouyer 				 */
    396  1.2.4.2  bouyer 				sc->sc_pending = HIL_PENDING_UNPLUGGED;
    397  1.2.4.2  bouyer 				break;
    398  1.2.4.2  bouyer 			}
    399  1.2.4.2  bouyer 			break;
    400  1.2.4.2  bouyer 		}
    401  1.2.4.2  bouyer 		if (c & HIL_COMMAND) {
    402  1.2.4.2  bouyer 		  	if (!(c & HIL_POLLDATA)) {
    403  1.2.4.2  bouyer 				/* End of command */
    404  1.2.4.2  bouyer 			  	sc->sc_cmdending = 1;
    405  1.2.4.2  bouyer 			}
    406  1.2.4.2  bouyer 			sc->sc_actdev = 0;
    407  1.2.4.2  bouyer 		} else {
    408  1.2.4.2  bouyer 		  	if (c & HIL_POLLDATA) {
    409  1.2.4.2  bouyer 				/* Start of polled data */
    410  1.2.4.2  bouyer 				sc->sc_actdev = (c & HIL_DEVMASK);
    411  1.2.4.2  bouyer 				sc->sc_pollbp = sc->sc_pollbuf;
    412  1.2.4.2  bouyer 			} else {
    413  1.2.4.2  bouyer 				/* Start of command - should not happen */
    414  1.2.4.2  bouyer 				if (sc->sc_cmddev == (c & HIL_DEVMASK)) {
    415  1.2.4.2  bouyer 					sc->sc_cmdbp = sc->sc_cmdbuf;
    416  1.2.4.2  bouyer 					sc->sc_actdev = 0;
    417  1.2.4.2  bouyer 				}
    418  1.2.4.2  bouyer 			}
    419  1.2.4.2  bouyer 		}
    420  1.2.4.2  bouyer 	        break;
    421  1.2.4.2  bouyer 	case HIL_DATA:
    422  1.2.4.2  bouyer 		if (sc->sc_actdev != 0)	/* Collecting poll data */
    423  1.2.4.2  bouyer 			return 1;
    424  1.2.4.2  bouyer 		else {
    425  1.2.4.2  bouyer 			if (sc->sc_cmddev != 0) {  /* Discarding cmd data */
    426  1.2.4.2  bouyer 				if (sc->sc_cmdending) {
    427  1.2.4.2  bouyer 					sc->sc_cmddone = 1;
    428  1.2.4.2  bouyer 					sc->sc_cmdending = 0;
    429  1.2.4.2  bouyer 				}
    430  1.2.4.2  bouyer 		        }
    431  1.2.4.2  bouyer 		}
    432  1.2.4.2  bouyer 		break;
    433  1.2.4.2  bouyer 	}
    434  1.2.4.2  bouyer 
    435  1.2.4.2  bouyer 	return 0;
    436  1.2.4.2  bouyer }
    437  1.2.4.2  bouyer 
    438  1.2.4.2  bouyer void
    439  1.2.4.2  bouyer hil_thread(void *arg)
    440  1.2.4.2  bouyer {
    441  1.2.4.2  bouyer 	struct hil_softc *sc = arg;
    442  1.2.4.2  bouyer 	int s;
    443  1.2.4.2  bouyer 
    444  1.2.4.2  bouyer 	for (;;) {
    445  1.2.4.2  bouyer 		s = splhil();
    446  1.2.4.2  bouyer 		if (sc->sc_pending == 0) {
    447  1.2.4.2  bouyer 			splx(s);
    448  1.2.4.2  bouyer 			(void)tsleep(&sc->sc_pending, PWAIT, "hil_event", 0);
    449  1.2.4.2  bouyer 			continue;
    450  1.2.4.2  bouyer 		}
    451  1.2.4.2  bouyer 
    452  1.2.4.2  bouyer 		switch (sc->sc_pending) {
    453  1.2.4.2  bouyer 		case HIL_PENDING_RECONFIG:
    454  1.2.4.2  bouyer 			sc->sc_pending = 0;
    455  1.2.4.2  bouyer 			hilconfig(sc, sc->sc_maxdev);
    456  1.2.4.2  bouyer 			break;
    457  1.2.4.2  bouyer 		case HIL_PENDING_UNPLUGGED:
    458  1.2.4.2  bouyer 			sc->sc_pending = 0;
    459  1.2.4.2  bouyer 			hilempty(sc);
    460  1.2.4.2  bouyer 			break;
    461  1.2.4.2  bouyer 		}
    462  1.2.4.2  bouyer 		splx(s);
    463  1.2.4.2  bouyer 	}
    464  1.2.4.2  bouyer }
    465  1.2.4.2  bouyer 
    466  1.2.4.2  bouyer /*
    467  1.2.4.2  bouyer  * Called after the loop has reconfigured.  Here we need to:
    468  1.2.4.2  bouyer  *	- determine how many devices are on the loop
    469  1.2.4.2  bouyer  *	  (some may have been added or removed)
    470  1.2.4.2  bouyer  *	- make sure all keyboards are in raw mode
    471  1.2.4.2  bouyer  *
    472  1.2.4.2  bouyer  * Note that our device state is now potentially invalid as
    473  1.2.4.2  bouyer  * devices may no longer be where they were.  What we should
    474  1.2.4.2  bouyer  * do here is either track where the devices went and move
    475  1.2.4.2  bouyer  * state around accordingly...
    476  1.2.4.2  bouyer  *
    477  1.2.4.2  bouyer  * Note that it is necessary that we operate the loop with the keyboards
    478  1.2.4.2  bouyer  * in raw mode: they won't cause the loop to generate an NMI if the
    479  1.2.4.2  bouyer  * ``reset'' key combination is pressed, and we do not handle the hil
    480  1.2.4.2  bouyer  * NMI interrupt...
    481  1.2.4.2  bouyer  */
    482  1.2.4.2  bouyer void
    483  1.2.4.2  bouyer hilconfig(struct hil_softc *sc, u_int knowndevs)
    484  1.2.4.2  bouyer {
    485  1.2.4.2  bouyer 	struct hil_attach_args ha;
    486  1.2.4.2  bouyer 	uint8_t db;
    487  1.2.4.2  bouyer 	int id, s;
    488  1.2.4.2  bouyer 
    489  1.2.4.2  bouyer 	s = splhil();
    490  1.2.4.2  bouyer 
    491  1.2.4.2  bouyer 	/*
    492  1.2.4.2  bouyer 	 * Determine how many devices are on the loop.
    493  1.2.4.2  bouyer 	 */
    494  1.2.4.2  bouyer 	db = 0;
    495  1.2.4.2  bouyer 	send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db);
    496  1.2.4.2  bouyer 	sc->sc_maxdev = db & LPS_DEVMASK;
    497  1.2.4.2  bouyer #ifdef HILDEBUG
    498  1.2.4.2  bouyer 	printf("%s: %d device(s)\n", device_xname(sc->sc_dev), sc->sc_maxdev);
    499  1.2.4.2  bouyer #endif
    500  1.2.4.2  bouyer 
    501  1.2.4.2  bouyer 	/*
    502  1.2.4.2  bouyer 	 * Put all keyboards in raw mode now.
    503  1.2.4.2  bouyer 	 */
    504  1.2.4.2  bouyer 	db = 0;
    505  1.2.4.2  bouyer 	send_hil_cmd(sc, HIL_WRITEKBDSADR, &db, 1, NULL);
    506  1.2.4.2  bouyer 
    507  1.2.4.2  bouyer 	/*
    508  1.2.4.2  bouyer 	 * If the loop grew, attach new devices.
    509  1.2.4.2  bouyer 	 */
    510  1.2.4.2  bouyer 	for (id = knowndevs + 1; id <= sc->sc_maxdev; id++) {
    511  1.2.4.2  bouyer 		int len;
    512  1.2.4.2  bouyer 		const struct hildevice *hd;
    513  1.2.4.2  bouyer 
    514  1.2.4.2  bouyer 		if (send_device_cmd(sc, id, HIL_IDENTIFY) != 0) {
    515  1.2.4.2  bouyer 			aprint_normal_dev(sc->sc_dev,
    516  1.2.4.2  bouyer 			    "no answer from device %d\n", id);
    517  1.2.4.2  bouyer 			continue;
    518  1.2.4.2  bouyer 		}
    519  1.2.4.2  bouyer 
    520  1.2.4.2  bouyer 		len = sc->sc_cmdbp - sc->sc_cmdbuf;
    521  1.2.4.2  bouyer 		if (len == 0) {
    522  1.2.4.2  bouyer #ifdef HILDEBUG
    523  1.2.4.2  bouyer 			printf("%s: no device at code %d\n",
    524  1.2.4.2  bouyer 			    device_xname(sc->sc_dev), id);
    525  1.2.4.2  bouyer #endif
    526  1.2.4.2  bouyer 			continue;
    527  1.2.4.2  bouyer 		}
    528  1.2.4.2  bouyer 
    529  1.2.4.2  bouyer 		/* Identify and attach device */
    530  1.2.4.2  bouyer 		for (hd = hildevs; hd->minid >= 0; hd++)
    531  1.2.4.2  bouyer 			if (sc->sc_cmdbuf[0] >= hd->minid &&
    532  1.2.4.2  bouyer 			    sc->sc_cmdbuf[0] <= hd->maxid) {
    533  1.2.4.2  bouyer 
    534  1.2.4.2  bouyer 			ha.ha_console = *sc->sc_console;
    535  1.2.4.2  bouyer 			ha.ha_code = id;
    536  1.2.4.2  bouyer 			ha.ha_type = hd->type;
    537  1.2.4.2  bouyer 			ha.ha_descr = hd->descr;
    538  1.2.4.2  bouyer 			ha.ha_infolen = len;
    539  1.2.4.2  bouyer 			memcpy(ha.ha_info, sc->sc_cmdbuf, len);
    540  1.2.4.2  bouyer 
    541  1.2.4.2  bouyer 			sc->sc_devices[id] =
    542  1.2.4.2  bouyer 			    config_found_sm_loc(sc->sc_dev, "hil", NULL,
    543  1.2.4.2  bouyer 			    &ha, hildevprint, hilsubmatch);
    544  1.2.4.2  bouyer 
    545  1.2.4.2  bouyer #if NHILKBD > 0
    546  1.2.4.2  bouyer 			/*
    547  1.2.4.2  bouyer 			 * If we just attached a keyboard as console,
    548  1.2.4.2  bouyer 			 * console choice is not indeterminate anymore.
    549  1.2.4.2  bouyer 			 */
    550  1.2.4.2  bouyer 			if (sc->sc_devices[id] != NULL &&
    551  1.2.4.2  bouyer 			    ha.ha_type == HIL_DEVICE_KEYBOARD &&
    552  1.2.4.2  bouyer 			    ha.ha_console != 0)
    553  1.2.4.2  bouyer 				*sc->sc_console = 1;
    554  1.2.4.2  bouyer #endif
    555  1.2.4.2  bouyer 		}
    556  1.2.4.2  bouyer 	}
    557  1.2.4.2  bouyer 
    558  1.2.4.2  bouyer 	/*
    559  1.2.4.2  bouyer 	 * Detach remaining devices, if the loop has shrunk.
    560  1.2.4.2  bouyer 	 */
    561  1.2.4.2  bouyer 	for (id = sc->sc_maxdev + 1; id < NHILD; id++) {
    562  1.2.4.2  bouyer 		if (sc->sc_devices[id] != NULL)
    563  1.2.4.2  bouyer 			config_detach(sc->sc_devices[id],
    564  1.2.4.2  bouyer 			    DETACH_FORCE);
    565  1.2.4.2  bouyer 		sc->sc_devices[id] = NULL;
    566  1.2.4.2  bouyer 	}
    567  1.2.4.2  bouyer 
    568  1.2.4.2  bouyer 	sc->sc_cmdbp = sc->sc_cmdbuf;
    569  1.2.4.2  bouyer 
    570  1.2.4.2  bouyer 	splx(s);
    571  1.2.4.2  bouyer }
    572  1.2.4.2  bouyer 
    573  1.2.4.2  bouyer /*
    574  1.2.4.2  bouyer  * Called after the loop has been unplugged. We simply force detach of
    575  1.2.4.2  bouyer  * all our children.
    576  1.2.4.2  bouyer  */
    577  1.2.4.2  bouyer void
    578  1.2.4.2  bouyer hilempty(struct hil_softc *sc)
    579  1.2.4.2  bouyer {
    580  1.2.4.2  bouyer 	uint8_t db;
    581  1.2.4.2  bouyer 	int id, s;
    582  1.2.4.2  bouyer 	u_int oldmaxdev;
    583  1.2.4.2  bouyer 
    584  1.2.4.2  bouyer 	s = splhil();
    585  1.2.4.2  bouyer 
    586  1.2.4.2  bouyer 	/*
    587  1.2.4.2  bouyer 	 * Wait for the loop to be stable.
    588  1.2.4.2  bouyer 	 */
    589  1.2.4.2  bouyer 	for (;;) {
    590  1.2.4.2  bouyer 		if (send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db) == 0) {
    591  1.2.4.2  bouyer 			if (db & (LPS_CONFFAIL | LPS_CONFGOOD))
    592  1.2.4.2  bouyer 				break;
    593  1.2.4.2  bouyer 		} else {
    594  1.2.4.2  bouyer 			db = LPS_CONFFAIL;
    595  1.2.4.2  bouyer 			break;
    596  1.2.4.2  bouyer 		}
    597  1.2.4.2  bouyer 	}
    598  1.2.4.2  bouyer 
    599  1.2.4.2  bouyer 	if (db & LPS_CONFFAIL) {
    600  1.2.4.2  bouyer 		sc->sc_maxdev = 0;
    601  1.2.4.2  bouyer 	} else {
    602  1.2.4.2  bouyer 		db = 0;
    603  1.2.4.2  bouyer 		send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db);
    604  1.2.4.2  bouyer 		oldmaxdev = sc->sc_maxdev;
    605  1.2.4.2  bouyer 		sc->sc_maxdev = db & LPS_DEVMASK;
    606  1.2.4.2  bouyer 
    607  1.2.4.2  bouyer 		if (sc->sc_maxdev != 0) {
    608  1.2.4.2  bouyer 			/*
    609  1.2.4.2  bouyer 			 * The loop was not unplugged after all, but its
    610  1.2.4.2  bouyer 			 * configuration has changed.
    611  1.2.4.2  bouyer 			 */
    612  1.2.4.2  bouyer 			hilconfig(sc, oldmaxdev);
    613  1.2.4.2  bouyer 			return;
    614  1.2.4.2  bouyer 		}
    615  1.2.4.2  bouyer 	}
    616  1.2.4.2  bouyer 
    617  1.2.4.2  bouyer 	/*
    618  1.2.4.2  bouyer 	 * Now detach all hil devices.
    619  1.2.4.2  bouyer 	 */
    620  1.2.4.2  bouyer 	for (id = sc->sc_maxdev + 1; id < NHILD; id++) {
    621  1.2.4.2  bouyer 		if (sc->sc_devices[id] != NULL)
    622  1.2.4.2  bouyer 			config_detach(sc->sc_devices[id],
    623  1.2.4.2  bouyer 			    DETACH_FORCE);
    624  1.2.4.2  bouyer 		sc->sc_devices[id] = NULL;
    625  1.2.4.2  bouyer 	}
    626  1.2.4.2  bouyer 
    627  1.2.4.2  bouyer 	sc->sc_cmdbp = sc->sc_cmdbuf;
    628  1.2.4.2  bouyer 
    629  1.2.4.2  bouyer 	splx(s);
    630  1.2.4.2  bouyer }
    631  1.2.4.2  bouyer 
    632  1.2.4.2  bouyer /*
    633  1.2.4.2  bouyer  * Low level routines which actually talk to the 8042 chip.
    634  1.2.4.2  bouyer  */
    635  1.2.4.2  bouyer 
    636  1.2.4.2  bouyer /*
    637  1.2.4.2  bouyer  * Send a command to the 8042 with zero or more bytes of data.
    638  1.2.4.2  bouyer  * If rdata is non-null, wait for and return a byte of data.
    639  1.2.4.2  bouyer  */
    640  1.2.4.2  bouyer int
    641  1.2.4.2  bouyer send_hil_cmd(struct hil_softc *sc, u_int cmd, uint8_t *data, u_int dlen,
    642  1.2.4.2  bouyer     uint8_t *rdata)
    643  1.2.4.2  bouyer {
    644  1.2.4.2  bouyer 	uint8_t status;
    645  1.2.4.2  bouyer 	int s;
    646  1.2.4.2  bouyer 
    647  1.2.4.2  bouyer 	s = splhil();
    648  1.2.4.2  bouyer 
    649  1.2.4.2  bouyer 	if (hilwait(sc) == 0) {
    650  1.2.4.2  bouyer #ifdef HILDEBUG
    651  1.2.4.2  bouyer 		printf("%s: no answer from the loop\n",
    652  1.2.4.2  bouyer 		    device_xname(sc->sc_dev));
    653  1.2.4.2  bouyer #endif
    654  1.2.4.2  bouyer 		splx(s);
    655  1.2.4.2  bouyer 		return EBUSY;
    656  1.2.4.2  bouyer 	}
    657  1.2.4.2  bouyer 
    658  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, cmd);
    659  1.2.4.2  bouyer 	while (dlen--) {
    660  1.2.4.2  bouyer 	  	hilwait(sc);
    661  1.2.4.2  bouyer 		bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, *data++);
    662  1.2.4.2  bouyer 		DELAY(1);
    663  1.2.4.2  bouyer 	}
    664  1.2.4.2  bouyer 	if (rdata) {
    665  1.2.4.2  bouyer 		do {
    666  1.2.4.2  bouyer 			if (hildatawait(sc) == 0) {
    667  1.2.4.2  bouyer #ifdef HILDEBUG
    668  1.2.4.2  bouyer 				printf("%s: no answer from the loop\n",
    669  1.2.4.2  bouyer 				    device_xname(sc->sc_dev));
    670  1.2.4.2  bouyer #endif
    671  1.2.4.2  bouyer 				break;
    672  1.2.4.2  bouyer 			}
    673  1.2.4.2  bouyer 			status = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
    674  1.2.4.2  bouyer 			    HILP_STAT);
    675  1.2.4.2  bouyer 			*rdata = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
    676  1.2.4.2  bouyer 			    HILP_DATA);
    677  1.2.4.2  bouyer 			DELAY(1);
    678  1.2.4.2  bouyer 		} while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K);
    679  1.2.4.2  bouyer 	}
    680  1.2.4.2  bouyer 	splx(s);
    681  1.2.4.2  bouyer 	return 0;
    682  1.2.4.2  bouyer }
    683  1.2.4.2  bouyer 
    684  1.2.4.2  bouyer /*
    685  1.2.4.2  bouyer  * Send a command to a device on the loop.
    686  1.2.4.2  bouyer  * Since only one command can be active on the loop at any time,
    687  1.2.4.2  bouyer  * we must ensure that we are not interrupted during this process.
    688  1.2.4.2  bouyer  * Hence we mask interrupts to prevent potential access from most
    689  1.2.4.2  bouyer  * interrupt routines and turn off auto-polling to disable the
    690  1.2.4.2  bouyer  * internally generated poll commands.
    691  1.2.4.2  bouyer  * Needs to be called at splhil().
    692  1.2.4.2  bouyer  */
    693  1.2.4.2  bouyer int
    694  1.2.4.2  bouyer send_device_cmd(struct hil_softc *sc, u_int device, u_int cmd)
    695  1.2.4.2  bouyer {
    696  1.2.4.2  bouyer 	uint8_t status, c;
    697  1.2.4.2  bouyer 	int rc = 0;
    698  1.2.4.2  bouyer 
    699  1.2.4.2  bouyer 	polloff(sc);
    700  1.2.4.2  bouyer 
    701  1.2.4.2  bouyer 	sc->sc_cmdbp = sc->sc_cmdbuf;
    702  1.2.4.2  bouyer 	sc->sc_cmddev = device;
    703  1.2.4.2  bouyer 
    704  1.2.4.2  bouyer 	if (hilwait(sc) == 0) {
    705  1.2.4.2  bouyer #ifdef HILDEBUG
    706  1.2.4.2  bouyer 		printf("%s: no answer from device %d\n",
    707  1.2.4.2  bouyer 		    device_xname(sc->sc_dev), device);
    708  1.2.4.2  bouyer #endif
    709  1.2.4.2  bouyer 		rc = EBUSY;
    710  1.2.4.2  bouyer 		goto out;
    711  1.2.4.2  bouyer 	}
    712  1.2.4.2  bouyer 
    713  1.2.4.2  bouyer 	/*
    714  1.2.4.2  bouyer 	 * Transfer the command and device info to the chip
    715  1.2.4.2  bouyer 	 */
    716  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_STARTCMD);
    717  1.2.4.2  bouyer   	hilwait(sc);
    718  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 8 + device);
    719  1.2.4.2  bouyer   	hilwait(sc);
    720  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, cmd);
    721  1.2.4.2  bouyer   	hilwait(sc);
    722  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, HIL_TIMEOUT);
    723  1.2.4.2  bouyer 
    724  1.2.4.2  bouyer 	/*
    725  1.2.4.2  bouyer 	 * Trigger the command and wait for completion
    726  1.2.4.2  bouyer 	 */
    727  1.2.4.2  bouyer 	hilwait(sc);
    728  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_TRIGGER);
    729  1.2.4.2  bouyer 	sc->sc_cmddone = 0;
    730  1.2.4.2  bouyer 	do {
    731  1.2.4.2  bouyer 		if (hildatawait(sc) == 0) {
    732  1.2.4.2  bouyer #ifdef HILDEBUG
    733  1.2.4.2  bouyer 			printf("%s: no answer from device %d\n",
    734  1.2.4.2  bouyer 			    device_xname(sc->sc_dev), device);
    735  1.2.4.2  bouyer #endif
    736  1.2.4.2  bouyer 			rc = EBUSY;
    737  1.2.4.2  bouyer 			break;
    738  1.2.4.2  bouyer 		}
    739  1.2.4.2  bouyer 		status = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT);
    740  1.2.4.2  bouyer 		c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
    741  1.2.4.2  bouyer 		DELAY(1);
    742  1.2.4.2  bouyer 		hil_process_int(sc, status, c);
    743  1.2.4.2  bouyer 	} while (sc->sc_cmddone == 0);
    744  1.2.4.2  bouyer out:
    745  1.2.4.2  bouyer 	sc->sc_cmddev = 0;
    746  1.2.4.2  bouyer 
    747  1.2.4.2  bouyer 	pollon(sc);
    748  1.2.4.2  bouyer 	return rc;
    749  1.2.4.2  bouyer }
    750  1.2.4.2  bouyer 
    751  1.2.4.2  bouyer int
    752  1.2.4.2  bouyer send_hildev_cmd(struct hildev_softc *hdsc, u_int cmd,
    753  1.2.4.2  bouyer     uint8_t *outbuf, u_int *outlen)
    754  1.2.4.2  bouyer {
    755  1.2.4.2  bouyer 	struct hil_softc *sc = device_private(device_parent(hdsc->sc_dev));
    756  1.2.4.2  bouyer 	int s, rc;
    757  1.2.4.2  bouyer 
    758  1.2.4.2  bouyer 	s = splhil();
    759  1.2.4.2  bouyer 
    760  1.2.4.2  bouyer 	if ((rc = send_device_cmd(sc, hdsc->sc_code, cmd)) == 0) {
    761  1.2.4.2  bouyer 		/*
    762  1.2.4.2  bouyer 		 * Return the command response in the buffer if necessary
    763  1.2.4.2  bouyer 	 	*/
    764  1.2.4.2  bouyer 		if (outbuf != NULL && outlen != NULL) {
    765  1.2.4.2  bouyer 			*outlen = min(*outlen, sc->sc_cmdbp - sc->sc_cmdbuf);
    766  1.2.4.2  bouyer 			memcpy(outbuf, sc->sc_cmdbuf, *outlen);
    767  1.2.4.2  bouyer 		}
    768  1.2.4.2  bouyer 	}
    769  1.2.4.2  bouyer 
    770  1.2.4.2  bouyer 	splx(s);
    771  1.2.4.2  bouyer 	return rc;
    772  1.2.4.2  bouyer }
    773  1.2.4.2  bouyer 
    774  1.2.4.2  bouyer /*
    775  1.2.4.2  bouyer  * Turn auto-polling off and on.
    776  1.2.4.2  bouyer  */
    777  1.2.4.2  bouyer void
    778  1.2.4.2  bouyer polloff(struct hil_softc *sc)
    779  1.2.4.2  bouyer {
    780  1.2.4.2  bouyer 	uint8_t db;
    781  1.2.4.2  bouyer 
    782  1.2.4.2  bouyer 	if (hilwait(sc) == 0)
    783  1.2.4.2  bouyer 		return;
    784  1.2.4.2  bouyer 
    785  1.2.4.2  bouyer 	/*
    786  1.2.4.2  bouyer 	 * Turn off auto repeat
    787  1.2.4.2  bouyer 	 */
    788  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_SETARR);
    789  1.2.4.2  bouyer 	hilwait(sc);
    790  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 0);
    791  1.2.4.2  bouyer 
    792  1.2.4.2  bouyer 	/*
    793  1.2.4.2  bouyer 	 * Turn off auto-polling
    794  1.2.4.2  bouyer 	 */
    795  1.2.4.2  bouyer 	hilwait(sc);
    796  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READLPCTRL);
    797  1.2.4.2  bouyer 	hildatawait(sc);
    798  1.2.4.2  bouyer 	db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
    799  1.2.4.2  bouyer 	db &= ~LPC_AUTOPOLL;
    800  1.2.4.2  bouyer 	hilwait(sc);
    801  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_WRITELPCTRL);
    802  1.2.4.2  bouyer 	hilwait(sc);
    803  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, db);
    804  1.2.4.2  bouyer 
    805  1.2.4.2  bouyer 	/*
    806  1.2.4.2  bouyer 	 * Must wait until polling is really stopped
    807  1.2.4.2  bouyer 	 */
    808  1.2.4.2  bouyer 	do {
    809  1.2.4.2  bouyer 		hilwait(sc);
    810  1.2.4.2  bouyer 		bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READBUSY);
    811  1.2.4.2  bouyer 		hildatawait(sc);
    812  1.2.4.2  bouyer 		db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
    813  1.2.4.2  bouyer 	} while (db & BSY_LOOPBUSY);
    814  1.2.4.2  bouyer 
    815  1.2.4.2  bouyer 	sc->sc_cmddone = 0;
    816  1.2.4.2  bouyer 	sc->sc_cmddev = 0;
    817  1.2.4.2  bouyer }
    818  1.2.4.2  bouyer 
    819  1.2.4.2  bouyer void
    820  1.2.4.2  bouyer pollon(struct hil_softc *sc)
    821  1.2.4.2  bouyer {
    822  1.2.4.2  bouyer 	uint8_t db;
    823  1.2.4.2  bouyer 
    824  1.2.4.2  bouyer 	if (hilwait(sc) == 0)
    825  1.2.4.2  bouyer 		return;
    826  1.2.4.2  bouyer 
    827  1.2.4.2  bouyer 	/*
    828  1.2.4.2  bouyer 	 * Turn on auto polling
    829  1.2.4.2  bouyer 	 */
    830  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READLPCTRL);
    831  1.2.4.2  bouyer 	hildatawait(sc);
    832  1.2.4.2  bouyer 	db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
    833  1.2.4.2  bouyer 	db |= LPC_AUTOPOLL;
    834  1.2.4.2  bouyer 	hilwait(sc);
    835  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_WRITELPCTRL);
    836  1.2.4.2  bouyer 	hilwait(sc);
    837  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, db);
    838  1.2.4.2  bouyer 
    839  1.2.4.2  bouyer 	/*
    840  1.2.4.2  bouyer 	 * Turn off auto repeat - we emulate this through wscons
    841  1.2.4.2  bouyer 	 */
    842  1.2.4.2  bouyer 	hilwait(sc);
    843  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_SETARR);
    844  1.2.4.2  bouyer 	hilwait(sc);
    845  1.2.4.2  bouyer 	bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 0);
    846  1.2.4.2  bouyer 	DELAY(1);
    847  1.2.4.2  bouyer }
    848  1.2.4.2  bouyer 
    849  1.2.4.2  bouyer void
    850  1.2.4.2  bouyer hil_set_poll(struct hil_softc *sc, int on)
    851  1.2.4.2  bouyer {
    852  1.2.4.2  bouyer 	if (on) {
    853  1.2.4.2  bouyer 		pollon(sc);
    854  1.2.4.2  bouyer 	} else {
    855  1.2.4.2  bouyer 		hil_process_pending(sc);
    856  1.2.4.2  bouyer 		send_hil_cmd(sc, HIL_INTON, NULL, 0, NULL);
    857  1.2.4.2  bouyer 	}
    858  1.2.4.2  bouyer }
    859  1.2.4.2  bouyer 
    860  1.2.4.2  bouyer int
    861  1.2.4.2  bouyer hil_poll_data(struct hildev_softc *hdsc, uint8_t *stat, uint8_t *data)
    862  1.2.4.2  bouyer {
    863  1.2.4.2  bouyer 	struct hil_softc *sc = device_private(device_parent(hdsc->sc_dev));
    864  1.2.4.2  bouyer 	uint8_t s, c;
    865  1.2.4.2  bouyer 
    866  1.2.4.2  bouyer 	s = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT);
    867  1.2.4.2  bouyer 	if ((s & HIL_DATA_RDY) == 0)
    868  1.2.4.2  bouyer 		return -1;
    869  1.2.4.2  bouyer 
    870  1.2.4.2  bouyer 	c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
    871  1.2.4.2  bouyer 	DELAY(1);
    872  1.2.4.2  bouyer 
    873  1.2.4.2  bouyer 	if (hil_process_poll(sc, s, c)) {
    874  1.2.4.2  bouyer 		/* Discard any data not for us */
    875  1.2.4.2  bouyer 		if (sc->sc_actdev == hdsc->sc_code) {
    876  1.2.4.2  bouyer 			*stat = s;
    877  1.2.4.2  bouyer 			*data = c;
    878  1.2.4.2  bouyer 			return 0;
    879  1.2.4.2  bouyer 		}
    880  1.2.4.2  bouyer 	}
    881  1.2.4.2  bouyer 
    882  1.2.4.2  bouyer 	return -1;
    883  1.2.4.2  bouyer }
    884