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