Home | History | Annotate | Line # | Download | only in sa11x0
sa1111_kbc.c revision 1.1
      1 /*      $NetBSD: sa1111_kbc.c,v 1.1 2002/12/20 04:12:51 bsh Exp $ */
      2 
      3 /*
      4  * Copyright (c) 2002  Genetec Corporation.  All rights reserved.
      5  * Written by Hiroyuki Bessho for Genetec Corporation.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. The name of Genetec Corporation may not be used to endorse or
     16  *    promote products derived from this software without specific prior
     17  *    written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL GENETEC CORPORATION
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  *
     31  * Driver for keyboard controller in SA-1111 companion chip.
     32  *
     33  * PC keyboard driver (sys/dev/pckbc/pckbd.c) works only with 8042
     34  * keyboard controller driver (sys/dev/ic/pckbc.c).  This file
     35  * provides same functions as those of 8042 driver.
     36  *
     37  * XXX: we need cleaner interface between the keyboard driver and
     38  *      keyboard controller drivers.
     39  */
     40 /*
     41  * Copyright (c) 1998
     42  *	Matthias Drochner.  All rights reserved.
     43  *
     44  * Redistribution and use in source and binary forms, with or without
     45  * modification, are permitted provided that the following conditions
     46  * are met:
     47  * 1. Redistributions of source code must retain the above copyright
     48  *    notice, this list of conditions and the following disclaimer.
     49  * 2. Redistributions in binary form must reproduce the above copyright
     50  *    notice, this list of conditions and the following disclaimer in the
     51  *    documentation and/or other materials provided with the distribution.
     52  * 3. All advertising materials mentioning features or use of this software
     53  *    must display the following acknowledgement:
     54  *	This product includes software developed for the NetBSD Project
     55  *	by Matthias Drochner.
     56  * 4. The name of the author may not be used to endorse or promote products
     57  *    derived from this software without specific prior written permission.
     58  *
     59  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     60  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     61  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     62  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     63  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     64  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     65  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     66  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     67  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     68  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     69  */
     70 
     71 #include <sys/param.h>
     72 #include <sys/systm.h>
     73 #include <sys/types.h>
     74 #include <sys/callout.h>
     75 #include <sys/kernel.h>
     76 #include <sys/proc.h>
     77 #include <sys/conf.h>
     78 #include <sys/device.h>
     79 #include <sys/malloc.h>
     80 #include <sys/errno.h>
     81 #include <sys/queue.h>
     82 #include <sys/lock.h>
     83 
     84 #include <machine/bus.h>
     85 #include <arm/sa11x0/sa1111_reg.h>
     86 #include <arm/sa11x0/sa1111_var.h>
     87 
     88 #include <dev/ic/pckbcvar.h>		/* for prototypes */
     89 
     90 #include "pckbd.h"
     91 #include "rnd.h"
     92 #include "locators.h"
     93 
     94 /* descriptor for one device command */
     95 struct pckbc_devcmd {
     96 	TAILQ_ENTRY(pckbc_devcmd) next;
     97 	int flags;
     98 #define KBC_CMDFLAG_SYNC 1 /* give descriptor back to caller */
     99 #define KBC_CMDFLAG_SLOW 2
    100 	u_char cmd[4];
    101 	int cmdlen, cmdidx, retries;
    102 	u_char response[4];
    103 	int status, responselen, responseidx;
    104 };
    105 
    106 struct sackbc_softc {
    107 	struct device dev;
    108 
    109 	bus_space_tag_t    iot;
    110 	bus_space_handle_t ioh;
    111 
    112 	void	*ih_rx;			/* receive interrupt */
    113 	int	intr;			/* interrupt number */
    114 
    115 	int	polling;	/* don't process data in interrupt handler */
    116 	int	poll_stat;	/* data read from inr handler if polling */
    117 	int	poll_data;	/* status read from intr handler if polling */
    118 
    119 	TAILQ_HEAD(, pckbc_devcmd) cmdqueue; /* active commands */
    120 	TAILQ_HEAD(, pckbc_devcmd) freequeue; /* free commands */
    121 #define NCMD  5
    122 	struct pckbc_devcmd cmd[NCMD];
    123 
    124 	struct callout t_cleanup;
    125 	pckbc_inputfcn inputhandler;
    126 	void *inputarg;
    127 	const char *subname;
    128 
    129 };
    130 
    131 #define CMD_IN_QUEUE(q) (TAILQ_FIRST(&(q)->cmdqueue) != NULL)
    132 
    133 #define N_KBC_SLOTS  2
    134 /*static struct sackbc_softc *sackbc_slot[N_KBC_SLOTS] = { NULL, NULL };*/
    135 
    136 static	int	sackbc_match(struct device *, struct cfdata *, void *);
    137 static	void	sackbc_attach(struct device *, struct device *, void *);
    138 static int	 sackbc_cmdresponse( struct sackbc_softc *, int );
    139 
    140 CFATTACH_DECL(sackbc, sizeof(struct sackbc_softc), sackbc_match,
    141     sackbc_attach, NULL, NULL);
    142 
    143 /* XXX should not be here */
    144 #define KBC_DEVCMD_ACK 0xfa
    145 #define KBC_DEVCMD_RESEND 0xfe
    146 
    147 #define	KBD_DELAY	DELAY(8)
    148 
    149 /*#define SACKBCDEBUG*/
    150 
    151 #ifdef SACKBCDEBUG
    152 #define DPRINTF(arg)  printf arg
    153 #else
    154 #define DPRINTF(arg)
    155 #endif
    156 
    157 static void sackbc_poll_cmd1( struct sackbc_softc *, struct pckbc_devcmd * );
    158 
    159 
    160 
    161 static int
    162 sackbc_match(struct device *parent, struct cfdata *cf, void *aux)
    163 {
    164 	struct sa1111_attach_args *aa = (struct sa1111_attach_args *)aux;
    165 
    166 	switch( aa->sa_addr ){
    167 	case SACC_KBD0: case SACC_KBD1:
    168 		return 1;
    169 	}
    170 	return 0;
    171 }
    172 
    173 #if 0
    174 static int
    175 sackbc_txint( void *cookie )
    176 {
    177 	struct sackbc_softc *sc = cookie;
    178 
    179 	bus_space_read_4( sc->iot, sc->ioh, SACCKBD_STAT );
    180 
    181 	return 0;
    182 }
    183 #endif
    184 
    185 static int
    186 sackbc_rxint( void *cookie )
    187 {
    188 	struct sackbc_softc *sc = cookie;
    189 	int stat, code=-1;
    190 
    191 	stat = bus_space_read_4( sc->iot, sc->ioh, SACCKBD_STAT );
    192 	DPRINTF(( "sackbc_rxint stat=%x\n", stat ));
    193 	if( stat & KBDSTAT_RXF ){
    194 		code = bus_space_read_4( sc->iot, sc->ioh, SACCKBD_DATA );
    195 
    196 		if( sc->polling ){
    197 			sc->poll_data = code;
    198 			sc->poll_stat = stat;
    199 		}
    200 		else if (CMD_IN_QUEUE(sc) && sackbc_cmdresponse(sc, code))
    201 			;
    202 		else if( sc->inputhandler ){
    203 			(* sc->inputhandler)( sc->inputarg, code );
    204 		}
    205 		return 1;
    206 	}
    207 
    208 	return 0;
    209 }
    210 
    211 static int
    212 sackbcprint(void *aux, const char *pnp)
    213 {
    214 	return (QUIET);
    215 }
    216 
    217 static void
    218 sackbc_setup_intrhandler(struct sackbc_softc *sc)
    219 {
    220 	if( !(sc->polling) && sc->ih_rx==NULL ){
    221 		sc->ih_rx = sacc_intr_establish(
    222 			(sacc_chipset_tag_t *)(sc->dev.dv_parent),
    223 			sc->intr+1, IST_EDGE_RAISE, IPL_TTY, sackbc_rxint, sc );
    224 		if( sc->ih_rx == NULL ){
    225 			printf( "%s: can't establish interrupt\n",
    226 			    sc->dev.dv_xname );
    227 		}
    228 	}
    229 }
    230 
    231 static void
    232 sackbc_disable_intrhandler( struct sackbc_softc *sc )
    233 {
    234 	if( sc->polling && sc->ih_rx ){
    235 		sacc_intr_disestablish(
    236 			(sacc_chipset_tag_t *)(sc->dev.dv_parent),
    237 			sc->ih_rx );
    238 		sc->ih_rx = NULL;
    239 	}
    240 }
    241 
    242 static int
    243 sackbc_submatch(struct device *parent, struct cfdata *cf, void *aux)
    244 {
    245 	struct pckbc_attach_args *pa = aux;
    246 
    247 	DPRINTF(( "slot = %d ", cf->cf_loc[SACKBCCF_SLOT] ));
    248 
    249 	if( pa->pa_slot == PCKBCCF_SLOT_DEFAULT )
    250 		pa->pa_slot = cf->cf_loc[SACKBCCF_SLOT];
    251 
    252 	return config_match(parent, cf, aux);
    253 }
    254 
    255 static	void
    256 sackbc_attach(struct device *parent, struct device *self, void *aux)
    257 {
    258 	struct sackbc_softc *sc = (struct sackbc_softc *)self;
    259 	struct sacc_softc *psc = (struct sacc_softc *)parent;
    260 	struct sa1111_attach_args *aa = (struct sa1111_attach_args *)aux;
    261 	uint32_t tmp, clock_bit;
    262 	int i, found, intr;
    263 
    264 	switch( aa->sa_addr ){
    265 	case SACC_KBD0: clock_bit = (1<<6); intr = 21; break;
    266 	case SACC_KBD1: clock_bit = (1<<5); intr = 18; break;
    267 	default:
    268 		return;
    269 	}
    270 
    271 	if( aa->sa_size <= 0 )
    272 		aa->sa_size = SACCKBD_SIZE;
    273 	if( aa->sa_intr == SACCCF_INTR_DEFAULT )
    274 		aa->sa_intr = intr;
    275 
    276 	sc->iot = psc->sc_iot;
    277 	if( bus_space_subregion( psc->sc_iot, psc->sc_ioh,
    278 	    aa->sa_addr, aa->sa_size, &sc->ioh ) ){
    279 		printf( ": can't map subregion\n" );
    280 		return;
    281 	}
    282 
    283 	/* enable clock for PS/2 kbd or mouse */
    284 	tmp = bus_space_read_4( psc->sc_iot, psc->sc_ioh, SACCSC_SKPCR );
    285 	bus_space_write_4( psc->sc_iot, psc->sc_ioh, SACCSC_SKPCR,
    286 	    tmp | clock_bit );
    287 
    288 	sc->ih_rx = NULL;
    289 	sc->intr = aa->sa_intr;
    290 	sc->inputhandler = NULL;
    291 	sc->subname = sc->dev.dv_xname;
    292 
    293 	TAILQ_INIT(&sc->cmdqueue);
    294 	TAILQ_INIT(&sc->freequeue);
    295 
    296 	for (i = 0; i < NCMD; i++) {
    297 		TAILQ_INSERT_TAIL(&sc->freequeue, &(sc->cmd[i]), next);
    298 	}
    299 	sc->polling = 0;
    300 
    301 	tmp = bus_space_read_4( sc->iot, sc->ioh, SACCKBD_CR );
    302 	bus_space_write_4( sc->iot, sc->ioh, SACCKBD_CR, tmp | KBDCR_ENA );
    303 
    304 	/* XXX: this is necessary to get keyboard working. but I don't know why */
    305 	bus_space_write_4( sc->iot, sc->ioh, SACCKBD_CLKDIV, 2 );
    306 
    307 	tmp = bus_space_read_4( sc->iot, sc->ioh, SACCKBD_STAT );
    308 	if( (tmp & KBDSTAT_ENA) == 0 ){
    309 		printf("??? can't enable KBD controller\n");
    310 		return;
    311 	}
    312 
    313 	printf("\n");
    314 
    315 	{
    316 		struct pckbc_attach_args pa;
    317 
    318 		pa.pa_tag = sc;
    319 		pa.pa_slot = PCKBCCF_SLOT_DEFAULT; /* Bogus */
    320 
    321 		found = (config_found_sm(self, &pa,
    322 		    sackbcprint, sackbc_submatch) != NULL);
    323 
    324 #if 0 && NRND > 0			/* XXX: not yet */
    325 		if (found && (t->t_slotdata[slot] != NULL))
    326 			rnd_attach_source(&t->t_slotdata[slot]->rnd_source,
    327 			    sc->subname[slot], RND_TYPE_TTY, 0);
    328 #endif
    329 	}
    330 
    331 }
    332 
    333 
    334 static inline int
    335 sackbc_wait_output( struct sackbc_softc *sc )
    336 {
    337 	u_int i, stat;
    338 
    339 	for (i = 100000; i; i--){
    340 		stat = bus_space_read_4(sc->iot, sc->ioh, SACCKBD_STAT);
    341 		delay(100);
    342 		if( stat & KBDSTAT_TXE)
    343 			return 1;
    344 	}
    345 	return 0;
    346 }
    347 
    348 static int
    349 sackbc_poll_data1( struct sackbc_softc *sc )
    350 {
    351 	int i, s, stat, c = -1;
    352 
    353 	s = spltty();
    354 
    355 	if (sc->polling){
    356 		stat	= sc->poll_stat;
    357 		c	= sc->poll_data;
    358 		sc->poll_data = -1;
    359 		sc->poll_stat = -1;
    360 		if( stat >= 0 &&
    361 		    (stat & (KBDSTAT_RXF|KBDSTAT_STP)) == KBDSTAT_RXF ){
    362 			splx(s);
    363 			return c;
    364 		}
    365 	}
    366 
    367 	/* if 1 port read takes 1us (?), this polls for 100ms */
    368 	for (i = 100000; i; i--) {
    369 		stat = bus_space_read_4(sc->iot, sc->ioh, SACCKBD_STAT);
    370 		if( (stat & (KBDSTAT_RXF|KBDSTAT_STP)) == KBDSTAT_RXF ){
    371 			KBD_DELAY;
    372 			c = bus_space_read_4(sc->iot, sc->ioh, SACCKBD_DATA);
    373 			break;
    374 		}
    375 	}
    376 
    377 	splx(s);
    378 	return (c);
    379 }
    380 
    381 static int
    382 sackbc_send_cmd( struct sackbc_softc *sc, int val )
    383 {
    384 	if ( !sackbc_wait_output(sc) )
    385 		return (0);
    386 	bus_space_write_1( sc->iot, sc->ioh, SACCKBD_DATA, val );
    387 	return (1);
    388 }
    389 
    390 #define sackbc_send_devcmd	sackbc_send_cmd
    391 
    392 /*
    393  * Clean up a command queue, throw away everything.
    394  */
    395 static void
    396 sackbc_cleanqueue( struct sackbc_softc *sc )
    397 {
    398 	struct pckbc_devcmd *cmd;
    399 #ifdef SACKBCDEBUG
    400 	int i;
    401 #endif
    402 
    403 	while ((cmd = TAILQ_FIRST(&sc->cmdqueue))) {
    404 		TAILQ_REMOVE(&sc->cmdqueue, cmd, next);
    405 #ifdef SACKBCDEBUG
    406 		printf("sackbc_cleanqueue: removing");
    407 		for (i = 0; i < cmd->cmdlen; i++)
    408 			printf(" %02x", cmd->cmd[i]);
    409 		printf("\n");
    410 #endif
    411 		TAILQ_INSERT_TAIL(&sc->freequeue, cmd, next);
    412 	}
    413 }
    414 
    415 /*
    416  * Timeout error handler: clean queues and data port.
    417  * XXX could be less invasive.
    418  */
    419 static void
    420 sackbc_cleanup(void *self)
    421 {
    422 	struct sackbc_softc *sc = self;
    423 	int s;
    424 
    425 	printf("sackbc: command timeout\n");
    426 
    427 	s = spltty();
    428 
    429 	sackbc_cleanqueue(sc);
    430 
    431 	while (bus_space_read_4(sc->iot, sc->ioh, SACCKBD_STAT) & KBDSTAT_RXF) {
    432 		KBD_DELAY;
    433 		(void) bus_space_read_4(sc->iot, sc->ioh, SACCKBD_DATA);
    434 	}
    435 
    436 	/* reset KBC? */
    437 
    438 	splx(s);
    439 }
    440 
    441 
    442 /*
    443  * Pass command to device during normal operation.
    444  * to be called at spltty()
    445  */
    446 static void
    447 sackbc_start( struct sackbc_softc *sc )
    448 {
    449 	struct pckbc_devcmd *cmd = TAILQ_FIRST(&sc->cmdqueue);
    450 
    451 	if (sc->polling) {
    452 		while(cmd){
    453 			sackbc_poll_cmd1(sc, cmd);
    454 			if (cmd->status)
    455 				printf("sackbc_start: command error\n");
    456 
    457 			TAILQ_REMOVE(&sc->cmdqueue, cmd, next);
    458 			if (cmd->flags & KBC_CMDFLAG_SYNC)
    459 				wakeup(cmd);
    460 			else {
    461 				callout_stop(&sc->t_cleanup);
    462 				TAILQ_INSERT_TAIL(&sc->freequeue, cmd, next);
    463 			}
    464 			cmd = TAILQ_FIRST(&sc->cmdqueue);
    465 		}
    466 		return;
    467 	}
    468 
    469 	if (!sackbc_send_devcmd(sc, cmd->cmd[cmd->cmdidx])) {
    470 		printf("sackbc_start: send error\n");
    471 		/* XXX what now? */
    472 		return;
    473 	}
    474 }
    475 
    476 /*
    477  * Handle command responses coming in asynchonously,
    478  * return nonzero if valid response.
    479  * to be called at spltty()
    480  */
    481 static int
    482 sackbc_cmdresponse( struct sackbc_softc *sc, int data)
    483 {
    484 	struct pckbc_devcmd *cmd = TAILQ_FIRST(&sc->cmdqueue);
    485 #ifdef DIAGNOSTIC
    486 	if (!cmd)
    487 		panic("sackbc_cmdresponse: no active command");
    488 #endif
    489 	if (cmd->cmdidx < cmd->cmdlen) {
    490 		if (data != KBC_DEVCMD_ACK && data != KBC_DEVCMD_RESEND)
    491 			return (0);
    492 
    493 		if (data == KBC_DEVCMD_RESEND) {
    494 			if (cmd->retries++ < 5) {
    495 				/* try again last command */
    496 				goto restart;
    497 			} else {
    498 				printf("pckbc: cmd failed\n");
    499 				cmd->status = EIO;
    500 				/* dequeue */
    501 			}
    502 		} else {
    503 			if (++cmd->cmdidx < cmd->cmdlen)
    504 				goto restart;
    505 			if (cmd->responselen)
    506 				return (1);
    507 			/* else dequeue */
    508 		}
    509 	} else if (cmd->responseidx < cmd->responselen) {
    510 		cmd->response[cmd->responseidx++] = data;
    511 		if (cmd->responseidx < cmd->responselen)
    512 			return (1);
    513 		/* else dequeue */
    514 	} else
    515 		return (0);
    516 
    517 	/* dequeue: */
    518 	TAILQ_REMOVE(&sc->cmdqueue, cmd, next);
    519 	if (cmd->flags & KBC_CMDFLAG_SYNC)
    520 		wakeup(cmd);
    521 	else {
    522 		callout_stop(&sc->t_cleanup);
    523 		TAILQ_INSERT_TAIL(&sc->freequeue, cmd, next);
    524 	}
    525 	if (!CMD_IN_QUEUE(sc))
    526 		return (1);
    527 restart:
    528 	sackbc_start(sc);
    529 	return (1);
    530 }
    531 
    532 /*
    533  * Pass command to device, poll for ACK and data.
    534  * to be called at spltty()
    535  */
    536 static void
    537 sackbc_poll_cmd1( struct sackbc_softc *sc, struct pckbc_devcmd *cmd )
    538 {
    539 	int i, c = 0;
    540 
    541 	while (cmd->cmdidx < cmd->cmdlen) {
    542 		DPRINTF((" tx: %x ", cmd->cmd[cmd->cmdidx]));
    543 		if (!sackbc_send_devcmd(sc, cmd->cmd[cmd->cmdidx])) {
    544 			printf("sackbc_cmd: send error\n");
    545 			cmd->status = EIO;
    546 			return;
    547 		}
    548 		delay(1000);
    549 		for (i = 10; i; i--) { /* 1s ??? */
    550 			c = sackbc_poll_data1(sc);
    551 			if (c != -1){
    552 				DPRINTF((" rx: %x", c ));
    553 				break;
    554 			}
    555 		}
    556 
    557 		if (c == KBC_DEVCMD_ACK) {
    558 			cmd->cmdidx++;
    559 			continue;
    560 		}
    561 		if (c == KBC_DEVCMD_RESEND) {
    562 			DPRINTF(("sackbc_cmd: RESEND\n"));
    563 
    564 			if (cmd->retries++ < 5)
    565 				continue;
    566 			else {
    567 				DPRINTF(("sackbc: cmd failed\n"));
    568 
    569 				cmd->status = EIO;
    570 				return;
    571 			}
    572 		}
    573 		if (c == -1) {
    574 			DPRINTF(("pckbc_cmd: timeout\n"));
    575 
    576 			cmd->status = EIO;
    577 			return;
    578 		}
    579 		DPRINTF(("pckbc_cmd: lost 0x%x\n", c));
    580 
    581 	}
    582 
    583 	while (cmd->responseidx < cmd->responselen) {
    584 		if (cmd->flags & KBC_CMDFLAG_SLOW)
    585 			i = 100; /* 10s ??? */
    586 		else
    587 			i = 10; /* 1s ??? */
    588 		while (i--) {
    589 			c = sackbc_poll_data1(sc);
    590 			if (c != -1){
    591 				DPRINTF((" resp: %x", c));
    592 				break;
    593 			}
    594 		}
    595 		if (c == -1) {
    596 			DPRINTF(("pckbc_cmd: no response"));
    597 
    598 			cmd->status = ETIMEDOUT;
    599 			return;
    600 		} else
    601 			cmd->response[cmd->responseidx++] = c;
    602 	}
    603 	DPRINTF(("\n"));
    604 }
    605 
    606 
    607 /*
    608  * Glue functions for pckbd on sackbc.
    609  * These functions emulate those in dev/ic/pckbc.c.
    610  *
    611  */
    612 
    613 void
    614 pckbc_set_inputhandler( pckbc_tag_t self, pckbc_slot_t slot,
    615     pckbc_inputfcn func, void *arg, char *name)
    616 {
    617 	struct sackbc_softc *sc = (struct sackbc_softc *) self;
    618 
    619 	if( sc == NULL )
    620 		return;
    621 
    622 	DPRINTF(( "set_inputhandler %p %p\n", func, arg ));
    623 
    624 	sc->inputhandler = func;
    625 	sc->inputarg = arg;
    626 	sc->subname = name;
    627 
    628 	sackbc_setup_intrhandler(sc);
    629 }
    630 
    631 
    632 /* for use in autoconfiguration */
    633 int
    634 pckbc_poll_cmd(pckbc_tag_t self, pckbc_slot_t slot,
    635     u_char *cmd, int len, int responselen, u_char *respbuf, int slow)
    636 {
    637 	struct pckbc_devcmd nc;
    638 struct sackbc_softc *sc = (struct sackbc_softc *) self;
    639 
    640 	if( sc == NULL )
    641 		return EINVAL;
    642 
    643 	if ((len > 4) || (responselen > 4))
    644 		return EINVAL;
    645 
    646 	memset(&nc, 0, sizeof(nc));
    647 	memcpy(nc.cmd, cmd, len);
    648 	nc.cmdlen = len;
    649 	nc.responselen = responselen;
    650 	nc.flags = (slow ? KBC_CMDFLAG_SLOW : 0);
    651 
    652 	sackbc_poll_cmd1(sc, &nc);
    653 
    654 	if (nc.status == 0 && respbuf)
    655 		memcpy(respbuf, nc.response, responselen);
    656 
    657 	return (nc.status);
    658 }
    659 
    660 
    661 /*
    662  * switch scancode translation on / off
    663  * return nonzero on success
    664  */
    665 int
    666 pckbc_xt_translation(pckbc_tag_t self, pckbc_slot_t slot, int on)
    667 {
    668 	/* KBD/Mouse controller doesn't have scancode translation */
    669 	return !on;
    670 }
    671 
    672 void
    673 pckbc_slot_enable(pckbc_tag_t self, pckbc_slot_t slot, int on)
    674 {
    675 #if 0
    676 	struct sackbc_softc *sc = (struct sackbc_softc *) self;
    677 	int cmd;
    678 
    679 	cmd = on ? KBC_KBDENABLE : KBC_KBDDISABLE;
    680 	if ( !sackbc_send_cmd(sc, cmd ) )
    681 		printf("sackbc_slot_enable(%d) failed\n", on);
    682 #endif
    683 }
    684 
    685 
    686 void
    687 pckbc_flush(pckbc_tag_t self, pckbc_slot_t slot)
    688 {
    689 	struct sackbc_softc *sc  = (struct sackbc_softc *)self;
    690 
    691 	(void) sackbc_poll_data1(sc);
    692 }
    693 
    694 #if 0
    695 int
    696 sackbc_poll_data( struct sackbc_softc *sc )
    697 {
    698 	struct pckbc_internal *t = self;
    699 	struct pckbc_slotdata *q = t->t_slotdata[slot];
    700 	int c;
    701 
    702 	c = pckbc_poll_data1(t, slot, t->t_haveaux);
    703 	if (c != -1 && q && CMD_IN_QUEUE(q)) {
    704 		/* we jumped into a running command - try to
    705 		 deliver the response */
    706 		if (pckbc_cmdresponse(t, slot, c))
    707 			return (-1);
    708 	}
    709 	return (c);
    710 }
    711 #endif
    712 
    713 void
    714 pckbc_set_poll(pckbc_tag_t self, pckbc_slot_t slot, int on)
    715 {
    716 	struct sackbc_softc *sc = (struct sackbc_softc *)self;
    717 	int s;
    718 
    719 	s = spltty();
    720 
    721 	if( sc->polling != on ){
    722 
    723 		sc->polling = on;
    724 
    725 		if( on ){
    726 			sc->poll_data = sc->poll_stat = -1;
    727 			sackbc_disable_intrhandler(sc);
    728 		}
    729 		else {
    730 			/*
    731 			 * If disabling polling on a device that's
    732 			 * been configured, make sure there are no
    733 			 * bytes left in the FIFO, holding up the
    734 			 * interrupt line.  Otherwise we won't get any
    735 			 * further interrupts.
    736 			 */
    737 			sackbc_rxint(sc);
    738 			sackbc_setup_intrhandler(sc);
    739 		}
    740 	}
    741 	splx(s);
    742 }
    743 
    744 /*
    745  * Put command into the device's command queue, return zero or errno.
    746  */
    747 int
    748 pckbc_enqueue_cmd( pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd,
    749     int len, int responselen, int sync, u_char *respbuf)
    750 {
    751 	struct sackbc_softc *sc = (struct sackbc_softc *)self;
    752 	struct pckbc_devcmd *nc;
    753 	int s, isactive, res = 0;
    754 
    755 	if ( sc == NULL || (len > 4) || (responselen > 4) )
    756 		return (EINVAL);
    757 
    758 	s = spltty();
    759 	nc = TAILQ_FIRST(&sc->freequeue);
    760 	if (nc) {
    761 		TAILQ_REMOVE(&sc->freequeue, nc, next);
    762 	}
    763 	splx(s);
    764 	if (!nc)
    765 		return (ENOMEM);
    766 
    767 	memset(nc, 0, sizeof(*nc));
    768 	memcpy(nc->cmd, cmd, len);
    769 	nc->cmdlen = len;
    770 	nc->responselen = responselen;
    771 	nc->flags = (sync ? KBC_CMDFLAG_SYNC : 0);
    772 
    773 	s = spltty();
    774 
    775 	if (sc->polling && sync) {
    776 		/*
    777 		 * XXX We should poll until the queue is empty.
    778 		 * But we don't come here normally, so make
    779 		 * it simple and throw away everything.
    780 		 */
    781 		sackbc_cleanqueue(sc);
    782 	}
    783 
    784 	isactive = CMD_IN_QUEUE(sc);
    785 	TAILQ_INSERT_TAIL(&sc->cmdqueue, nc, next);
    786 	if (!isactive)
    787 		sackbc_start(sc);
    788 
    789 	if (sc->polling)
    790 		res = (sync ? nc->status : 0);
    791 	else if (sync) {
    792 		if ((res = tsleep(nc, 0, "kbccmd", 1*hz))) {
    793 			TAILQ_REMOVE(&sc->cmdqueue, nc, next);
    794 			sackbc_cleanup(sc);
    795 		} else
    796 			res = nc->status;
    797 	} else
    798 		callout_reset(&sc->t_cleanup, hz, sackbc_cleanup, sc);
    799 
    800 	if (sync) {
    801 		if (respbuf)
    802 			memcpy(respbuf, nc->response, responselen);
    803 		TAILQ_INSERT_TAIL(&sc->freequeue, nc, next);
    804 	}
    805 
    806 	splx(s);
    807 
    808 	return (res);
    809 }
    810 
    811 int
    812 pckbc_poll_data(pckbc_tag_t self, pckbc_slot_t slot)
    813 {
    814 	struct sackbc_softc *sc = (struct sackbc_softc *)self;
    815 	int c;
    816 
    817 	c = sackbc_poll_data1(sc);
    818 	if (c != -1 && CMD_IN_QUEUE(sc)) {
    819 		/* we jumped into a running command - try to
    820 		 deliver the response */
    821 		if (sackbc_cmdresponse(sc, c))
    822 			return -1;
    823 	}
    824 	return (c);
    825 }
    826