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 */ 98struct 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 109struct 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 139static int sackbc_match(struct device *, struct cfdata *, void *); 140static void sackbc_attach(struct device *, struct device *, void *); 141static int sackbc_cmdresponse( struct sackbc_softc *, int ); 142 143CFATTACH_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 160static void sackbc_poll_cmd1( struct sackbc_softc *, struct pckbc_devcmd * ); 161 162 163 164static int 165sackbc_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 177static int 178sackbc_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 188static int 189sackbc_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 214static int 215sackbcprint(void *aux, const char *pnp) 216{ 217 return (QUIET); 218} 219 220static void 221sackbc_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 234static void 235sackbc_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 245static int 246sackbc_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 258static void 259sackbc_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 337static inline int 338sackbc_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 351static int 352sackbc_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 384static int 385sackbc_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 */ 398static void 399sackbc_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 */ 422static void 423sackbc_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 */ 449static void 450sackbc_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 */ 484static int 485sackbc_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); 530restart: 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 */ 539static void 540sackbc_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 616void 617pckbc_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 */ 636int 637pckbc_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; 641struct 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 */ 668int 669pckbc_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 675void 676pckbc_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 689void 690pckbc_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 698int 699sackbc_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 716void 717pckbc_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 */ 750int 751pckbc_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 814int 815pckbc_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