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