1 /* $OpenBSD: pckbc.c,v 1.29 2012/02/02 21:40:20 deraadt Exp $ */ 2 /* $NetBSD: pckbc.c,v 1.5 2000/06/09 04:58:35 soda Exp $ */ 3 4 /* 5 * Copyright (c) 1998 6 * Matthias Drochner. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/timeout.h> 32 #include <sys/kernel.h> 33 #include <sys/proc.h> 34 #include <sys/device.h> 35 #include <sys/malloc.h> 36 #include <sys/errno.h> 37 #include <sys/queue.h> 38 #include <sys/lock.h> 39 40 #include <machine/bus.h> 41 42 #include <dev/ic/i8042reg.h> 43 #include <dev/ic/pckbcvar.h> 44 45 #include "pckbd.h" 46 47 #if NPCKBD > 0 48 #include <dev/pckbc/pckbdvar.h> 49 #endif 50 51 /* descriptor for one device command */ 52 struct pckbc_devcmd { 53 TAILQ_ENTRY(pckbc_devcmd) next; 54 int flags; 55 #define KBC_CMDFLAG_SYNC 1 /* give descriptor back to caller */ 56 #define KBC_CMDFLAG_SLOW 2 57 u_char cmd[4]; 58 int cmdlen, cmdidx, retries; 59 u_char response[4]; 60 int status, responselen, responseidx; 61 }; 62 63 /* data per slave device */ 64 struct pckbc_slotdata { 65 int polling; /* don't read data port in interrupt handler */ 66 TAILQ_HEAD(, pckbc_devcmd) cmdqueue; /* active commands */ 67 TAILQ_HEAD(, pckbc_devcmd) freequeue; /* free commands */ 68 #define NCMD 5 69 struct pckbc_devcmd cmds[NCMD]; 70 }; 71 72 #define CMD_IN_QUEUE(q) (!TAILQ_EMPTY(&(q)->cmdqueue)) 73 74 void pckbc_init_slotdata(struct pckbc_slotdata *); 75 int pckbc_attach_slot(struct pckbc_softc *, pckbc_slot_t, int); 76 int pckbc_submatch_locators(struct device *, void *, void *); 77 int pckbc_submatch(struct device *, void *, void *); 78 int pckbcprint(void *, const char *); 79 80 struct pckbc_internal pckbc_consdata; 81 int pckbc_console_attached; 82 83 static int pckbc_console; 84 static struct pckbc_slotdata pckbc_cons_slotdata; 85 86 static int pckbc_wait_output(bus_space_tag_t, bus_space_handle_t); 87 88 static int pckbc_get8042cmd(struct pckbc_internal *); 89 static int pckbc_put8042cmd(struct pckbc_internal *); 90 static int pckbc_send_devcmd(struct pckbc_internal *, pckbc_slot_t, 91 u_char); 92 static void pckbc_poll_cmd1(struct pckbc_internal *, pckbc_slot_t, 93 struct pckbc_devcmd *); 94 95 void pckbc_cleanqueue(struct pckbc_slotdata *); 96 void pckbc_cleanup(void *); 97 void pckbc_poll(void *); 98 int pckbc_cmdresponse(struct pckbc_internal *, pckbc_slot_t, u_char); 99 void pckbc_start(struct pckbc_internal *, pckbc_slot_t); 100 int pckbcintr_internal(struct pckbc_internal *, struct pckbc_softc *); 101 102 const char *pckbc_slot_names[] = { "kbd", "aux" }; 103 104 #define KBC_DEVCMD_ACK 0xfa 105 #define KBC_DEVCMD_RESEND 0xfe 106 #define KBC_DEVCMD_BAT 0xaa 107 108 #define KBD_DELAY DELAY(8) 109 110 static inline int 111 pckbc_wait_output(bus_space_tag_t iot, bus_space_handle_t ioh_c) 112 { 113 u_int i; 114 115 for (i = 100000; i; i--) 116 if (!(bus_space_read_1(iot, ioh_c, 0) & KBS_IBF)) { 117 KBD_DELAY; 118 return (1); 119 } 120 return (0); 121 } 122 123 int 124 pckbc_send_cmd(bus_space_tag_t iot, bus_space_handle_t ioh_c, u_char val) 125 { 126 if (!pckbc_wait_output(iot, ioh_c)) 127 return (0); 128 bus_space_write_1(iot, ioh_c, 0, val); 129 return (1); 130 } 131 132 int 133 pckbc_poll_data1(bus_space_tag_t iot, bus_space_handle_t ioh_d, 134 bus_space_handle_t ioh_c, pckbc_slot_t slot, int checkaux) 135 { 136 int i; 137 u_char stat; 138 139 /* polls for ~100ms */ 140 for (i = 100; i; i--, delay(1000)) { 141 stat = bus_space_read_1(iot, ioh_c, 0); 142 if (stat & KBS_DIB) { 143 register u_char c; 144 145 KBD_DELAY; 146 c = bus_space_read_1(iot, ioh_d, 0); 147 if (checkaux && (stat & 0x20)) { /* aux data */ 148 if (slot != PCKBC_AUX_SLOT) { 149 #ifdef PCKBCDEBUG 150 printf("lost aux 0x%x\n", c); 151 #endif 152 continue; 153 } 154 } else { 155 if (slot == PCKBC_AUX_SLOT) { 156 #ifdef PCKBCDEBUG 157 printf("lost kbd 0x%x\n", c); 158 #endif 159 continue; 160 } 161 } 162 return (c); 163 } 164 } 165 return (-1); 166 } 167 168 /* 169 * Get the current command byte. 170 */ 171 static int 172 pckbc_get8042cmd(struct pckbc_internal *t) 173 { 174 bus_space_tag_t iot = t->t_iot; 175 bus_space_handle_t ioh_d = t->t_ioh_d; 176 bus_space_handle_t ioh_c = t->t_ioh_c; 177 int data; 178 179 if (!pckbc_send_cmd(iot, ioh_c, K_RDCMDBYTE)) 180 return (0); 181 data = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 182 t->t_haveaux); 183 if (data == -1) 184 return (0); 185 t->t_cmdbyte = data; 186 return (1); 187 } 188 189 /* 190 * Pass command byte to keyboard controller (8042). 191 */ 192 static int 193 pckbc_put8042cmd(struct pckbc_internal *t) 194 { 195 bus_space_tag_t iot = t->t_iot; 196 bus_space_handle_t ioh_d = t->t_ioh_d; 197 bus_space_handle_t ioh_c = t->t_ioh_c; 198 199 if (!pckbc_send_cmd(iot, ioh_c, K_LDCMDBYTE)) 200 return (0); 201 if (!pckbc_wait_output(iot, ioh_c)) 202 return (0); 203 bus_space_write_1(iot, ioh_d, 0, t->t_cmdbyte); 204 return (1); 205 } 206 207 static int 208 pckbc_send_devcmd(struct pckbc_internal *t, pckbc_slot_t slot, u_char val) 209 { 210 bus_space_tag_t iot = t->t_iot; 211 bus_space_handle_t ioh_d = t->t_ioh_d; 212 bus_space_handle_t ioh_c = t->t_ioh_c; 213 214 if (slot == PCKBC_AUX_SLOT) { 215 if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXWRITE)) 216 return (0); 217 } 218 if (!pckbc_wait_output(iot, ioh_c)) 219 return (0); 220 bus_space_write_1(iot, ioh_d, 0, val); 221 return (1); 222 } 223 224 int 225 pckbc_is_console(bus_space_tag_t iot, bus_addr_t addr) 226 { 227 if (pckbc_console && !pckbc_console_attached && 228 pckbc_consdata.t_iot == iot && 229 pckbc_consdata.t_addr == addr) 230 return (1); 231 return (0); 232 } 233 234 int 235 pckbc_submatch_locators(struct device *parent, void *match, void *aux) 236 { 237 struct cfdata *cf = match; 238 struct pckbc_attach_args *pa = aux; 239 240 if (cf->cf_loc[PCKBCCF_SLOT] != PCKBCCF_SLOT_DEFAULT && 241 cf->cf_loc[PCKBCCF_SLOT] != pa->pa_slot) 242 return (0); 243 return (1); 244 } 245 246 int 247 pckbc_submatch(struct device *parent, void *match, void *aux) 248 { 249 struct cfdata *cf = match; 250 251 if (pckbc_submatch_locators(parent, match, aux) == 0) 252 return (0); 253 return ((*cf->cf_attach->ca_match)(parent, cf, aux)); 254 } 255 256 int 257 pckbc_attach_slot(struct pckbc_softc *sc, pckbc_slot_t slot, int force) 258 { 259 struct pckbc_internal *t = sc->id; 260 struct pckbc_attach_args pa; 261 int found; 262 263 pa.pa_tag = t; 264 pa.pa_slot = slot; 265 found = (config_found_sm((struct device *)sc, &pa, pckbcprint, 266 force ? pckbc_submatch_locators : pckbc_submatch) != NULL); 267 268 if (found && !t->t_slotdata[slot]) { 269 t->t_slotdata[slot] = malloc(sizeof(struct pckbc_slotdata), 270 M_DEVBUF, M_NOWAIT); 271 if (t->t_slotdata[slot] == NULL) 272 return 0; 273 pckbc_init_slotdata(t->t_slotdata[slot]); 274 } 275 return (found); 276 } 277 278 void 279 pckbc_attach(struct pckbc_softc *sc, int flags) 280 { 281 struct pckbc_internal *t; 282 bus_space_tag_t iot; 283 bus_space_handle_t ioh_d, ioh_c; 284 int haskbd = 0, res; 285 u_char cmdbits = 0; 286 287 t = sc->id; 288 iot = t->t_iot; 289 ioh_d = t->t_ioh_d; 290 ioh_c = t->t_ioh_c; 291 292 if (pckbc_console == 0) { 293 timeout_set(&t->t_cleanup, pckbc_cleanup, t); 294 timeout_set(&t->t_poll, pckbc_poll, t); 295 } 296 297 /* flush */ 298 (void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); 299 300 /* set initial cmd byte */ 301 if (!pckbc_put8042cmd(t)) { 302 printf("kbc: cmd word write error\n"); 303 return; 304 } 305 306 /* 307 * XXX Don't check the keyboard port. There are broken keyboard controllers 308 * which don't pass the test but work normally otherwise. 309 */ 310 #if 0 311 /* 312 * check kbd port ok 313 */ 314 if (!pckbc_send_cmd(iot, ioh_c, KBC_KBDTEST)) 315 return; 316 res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); 317 318 /* 319 * Normally, we should get a "0" here. 320 * But there are keyboard controllers behaving differently. 321 */ 322 if (res == 0 || res == 0xfa || res == 0x01 || res == 0xab) { 323 #ifdef PCKBCDEBUG 324 if (res != 0) 325 printf("kbc: returned %x on kbd slot test\n", res); 326 #endif 327 if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT, 0)) { 328 cmdbits |= KC8_KENABLE; 329 haskbd = 1; 330 } 331 } else { 332 printf("kbc: kbd port test: %x\n", res); 333 return; 334 } 335 #else 336 if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT, 0)) { 337 cmdbits |= KC8_KENABLE; 338 haskbd = 1; 339 } 340 #endif /* 0 */ 341 342 /* 343 * Check aux port ok. 344 * Avoid KBC_AUXTEST because it hangs some older controllers 345 * (eg UMC880?). 346 */ 347 if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXECHO)) { 348 printf("kbc: aux echo error 1\n"); 349 goto nomouse; 350 } 351 if (!pckbc_wait_output(iot, ioh_c)) { 352 printf("kbc: aux echo error 2\n"); 353 goto nomouse; 354 } 355 bus_space_write_1(iot, ioh_d, 0, 0x5a); /* a random value */ 356 res = pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_AUX_SLOT, 1); 357 358 if (ISSET(t->t_flags, PCKBC_NEED_AUXWRITE)) { 359 /* 360 * The following code is necessary to find the aux port on the 361 * oqo-1 machine, among others. However if confuses old 362 * (non-ps/2) keyboard controllers (at least UMC880x again). 363 */ 364 if (res == -1) { 365 /* Read of aux echo timed out, try again */ 366 if (!pckbc_send_cmd(iot, ioh_c, KBC_AUXWRITE)) 367 goto nomouse; 368 if (!pckbc_wait_output(iot, ioh_c)) 369 goto nomouse; 370 bus_space_write_1(iot, ioh_d, 0, 0x5a); 371 res = pckbc_poll_data1(iot, ioh_d, ioh_c, 372 PCKBC_AUX_SLOT, 1); 373 #ifdef PCKBCDEBUG 374 printf("kbc: aux echo: %x\n", res); 375 #endif 376 } 377 } 378 379 if (res != -1) { 380 /* 381 * In most cases, the 0x5a gets echoed. 382 * Some old controllers (Gateway 2000 circa 1993) 383 * return 0xfe here. 384 * We are satisfied if there is anything in the 385 * aux output buffer. 386 */ 387 #ifdef PCKBCDEBUG 388 printf("kbc: aux echo: %x\n", res); 389 #endif 390 t->t_haveaux = 1; 391 if (pckbc_attach_slot(sc, PCKBC_AUX_SLOT, 0)) 392 cmdbits |= KC8_MENABLE; 393 } 394 #ifdef PCKBCDEBUG 395 else 396 printf("kbc: aux echo test failed\n"); 397 #endif 398 399 #if defined(__i386__) || defined(__amd64__) 400 if (haskbd == 0 && !ISSET(flags, PCKBCF_FORCE_KEYBOARD_PRESENT)) { 401 /* 402 * If there is no keyboard present, yet we are the console, 403 * we might be on a legacy-free PC where the PS/2 emulated 404 * keyboard was elected as console, but went away as soon 405 * as the USB controller drivers attached. 406 * 407 * In that case, we want to release ourselves from console 408 * duties, unless we have been able to attach a mouse, 409 * which would mean this is a real PS/2 controller 410 * afterwards. 411 */ 412 413 if (t->t_haveaux) { 414 if (pckbc_attach_slot(sc, PCKBC_KBD_SLOT, 1)) 415 cmdbits |= KC8_KENABLE; 416 } else { 417 if (pckbc_console != 0) { 418 extern void wscn_input_init(int); 419 420 pckbc_console = 0; 421 wscn_input_init(1); 422 } 423 } 424 } 425 #endif 426 427 nomouse: 428 /* enable needed interrupts */ 429 t->t_cmdbyte |= cmdbits; 430 if (!pckbc_put8042cmd(t)) 431 printf("kbc: cmd word write error\n"); 432 } 433 434 int 435 pckbcprint(void *aux, const char *pnp) 436 { 437 struct pckbc_attach_args *pa = aux; 438 439 if (!pnp) 440 printf(" (%s slot)", pckbc_slot_names[pa->pa_slot]); 441 return (QUIET); 442 } 443 444 void 445 pckbc_init_slotdata(struct pckbc_slotdata *q) 446 { 447 int i; 448 TAILQ_INIT(&q->cmdqueue); 449 TAILQ_INIT(&q->freequeue); 450 451 for (i = 0; i < NCMD; i++) { 452 TAILQ_INSERT_TAIL(&q->freequeue, &(q->cmds[i]), next); 453 } 454 q->polling = 0; 455 } 456 457 void 458 pckbc_flush(pckbc_tag_t self, pckbc_slot_t slot) 459 { 460 struct pckbc_internal *t = self; 461 462 (void) pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_c, 463 slot, t->t_haveaux); 464 } 465 466 int 467 pckbc_poll_data(pckbc_tag_t self, pckbc_slot_t slot) 468 { 469 struct pckbc_internal *t = self; 470 struct pckbc_slotdata *q = t->t_slotdata[slot]; 471 int c; 472 473 c = pckbc_poll_data1(t->t_iot, t->t_ioh_d, t->t_ioh_c, 474 slot, t->t_haveaux); 475 if (c != -1 && q && CMD_IN_QUEUE(q)) { 476 /* we jumped into a running command - try to 477 deliver the response */ 478 if (pckbc_cmdresponse(t, slot, c)) 479 return (-1); 480 } 481 return (c); 482 } 483 484 /* 485 * switch scancode translation on / off 486 * return nonzero on success 487 */ 488 int 489 pckbc_xt_translation(pckbc_tag_t self, pckbc_slot_t slot, int on) 490 { 491 struct pckbc_internal *t = self; 492 int ison; 493 494 if (ISSET(t->t_flags, PCKBC_CANT_TRANSLATE) || 495 slot != PCKBC_KBD_SLOT) { 496 /* translation only for kbd slot */ 497 if (on) 498 return (0); 499 else 500 return (1); 501 } 502 503 ison = t->t_cmdbyte & KC8_TRANS; 504 if ((on && ison) || (!on && !ison)) 505 return (1); 506 507 t->t_cmdbyte ^= KC8_TRANS; 508 if (!pckbc_put8042cmd(t)) 509 return (0); 510 511 /* read back to be sure */ 512 if (!pckbc_get8042cmd(t)) 513 return (0); 514 515 ison = t->t_cmdbyte & KC8_TRANS; 516 if ((on && ison) || (!on && !ison)) 517 return (1); 518 return (0); 519 } 520 521 static struct pckbc_portcmd { 522 u_char cmd_en, cmd_dis; 523 } pckbc_portcmd[2] = { 524 { 525 KBC_KBDENABLE, KBC_KBDDISABLE, 526 }, { 527 KBC_AUXENABLE, KBC_AUXDISABLE, 528 } 529 }; 530 531 void 532 pckbc_slot_enable(pckbc_tag_t self, pckbc_slot_t slot, int on) 533 { 534 struct pckbc_internal *t = (struct pckbc_internal *)self; 535 struct pckbc_portcmd *cmd; 536 537 cmd = &pckbc_portcmd[slot]; 538 539 if (!pckbc_send_cmd(t->t_iot, t->t_ioh_c, 540 on ? cmd->cmd_en : cmd->cmd_dis)) 541 printf("pckbc_slot_enable(%d) failed\n", on); 542 543 if (slot == PCKBC_KBD_SLOT) { 544 if (on) 545 timeout_add_sec(&t->t_poll, 1); 546 else 547 timeout_del(&t->t_poll); 548 } 549 } 550 551 void 552 pckbc_set_poll(pckbc_tag_t self, pckbc_slot_t slot, int on) 553 { 554 struct pckbc_internal *t = (struct pckbc_internal *)self; 555 556 t->t_slotdata[slot]->polling = on; 557 558 if (!on) { 559 int s; 560 561 /* 562 * If disabling polling on a device that's been configured, 563 * make sure there are no bytes left in the FIFO, holding up 564 * the interrupt line. Otherwise we won't get any further 565 * interrupts. 566 */ 567 if (t->t_sc) { 568 s = spltty(); 569 pckbcintr_internal(t, t->t_sc); 570 splx(s); 571 } 572 } 573 } 574 575 /* 576 * Pass command to device, poll for ACK and data. 577 * to be called at spltty() 578 */ 579 static void 580 pckbc_poll_cmd1(struct pckbc_internal *t, pckbc_slot_t slot, 581 struct pckbc_devcmd *cmd) 582 { 583 bus_space_tag_t iot = t->t_iot; 584 bus_space_handle_t ioh_d = t->t_ioh_d; 585 bus_space_handle_t ioh_c = t->t_ioh_c; 586 int i, c = 0; 587 588 while (cmd->cmdidx < cmd->cmdlen) { 589 if (!pckbc_send_devcmd(t, slot, cmd->cmd[cmd->cmdidx])) { 590 printf("pckbc_cmd: send error\n"); 591 cmd->status = EIO; 592 return; 593 } 594 for (i = 10; i; i--) { /* 1s ??? */ 595 c = pckbc_poll_data1(iot, ioh_d, ioh_c, slot, 596 t->t_haveaux); 597 if (c != -1) 598 break; 599 } 600 601 if (c == KBC_DEVCMD_ACK) { 602 cmd->cmdidx++; 603 continue; 604 } 605 /* 606 * Some legacy free PCs keep returning Basic Assurance Test 607 * (BAT) instead of something usable, so fail gracefully. 608 */ 609 if (c == KBC_DEVCMD_RESEND || c == KBC_DEVCMD_BAT) { 610 #ifdef PCKBCDEBUG 611 printf("pckbc_cmd: %s\n", 612 c == KBC_DEVCMD_RESEND ? "RESEND": "BAT"); 613 #endif 614 if (cmd->retries++ < 5) 615 continue; 616 else { 617 #ifdef PCKBCDEBUG 618 printf("pckbc: cmd failed\n"); 619 #endif 620 cmd->status = ENXIO; 621 return; 622 } 623 } 624 if (c == -1) { 625 #ifdef PCKBCDEBUG 626 printf("pckbc_cmd: timeout\n"); 627 #endif 628 cmd->status = EIO; 629 return; 630 } 631 #ifdef PCKBCDEBUG 632 printf("pckbc_cmd: lost 0x%x\n", c); 633 #endif 634 } 635 636 while (cmd->responseidx < cmd->responselen) { 637 if (cmd->flags & KBC_CMDFLAG_SLOW) 638 i = 100; /* 10s ??? */ 639 else 640 i = 10; /* 1s ??? */ 641 while (i--) { 642 c = pckbc_poll_data1(iot, ioh_d, ioh_c, slot, 643 t->t_haveaux); 644 if (c != -1) 645 break; 646 } 647 if (c == -1) { 648 #ifdef PCKBCDEBUG 649 printf("pckbc_cmd: no data\n"); 650 #endif 651 cmd->status = ETIMEDOUT; 652 return; 653 } else 654 cmd->response[cmd->responseidx++] = c; 655 } 656 } 657 658 /* for use in autoconfiguration */ 659 int 660 pckbc_poll_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len, 661 int responselen, u_char *respbuf, int slow) 662 { 663 struct pckbc_devcmd nc; 664 665 if ((len > 4) || (responselen > 4)) 666 return (EINVAL); 667 668 bzero(&nc, sizeof(nc)); 669 bcopy(cmd, nc.cmd, len); 670 nc.cmdlen = len; 671 nc.responselen = responselen; 672 nc.flags = (slow ? KBC_CMDFLAG_SLOW : 0); 673 674 pckbc_poll_cmd1(self, slot, &nc); 675 676 if (nc.status == 0 && respbuf) 677 bcopy(nc.response, respbuf, responselen); 678 679 return (nc.status); 680 } 681 682 /* 683 * Clean up a command queue, throw away everything. 684 */ 685 void 686 pckbc_cleanqueue(struct pckbc_slotdata *q) 687 { 688 struct pckbc_devcmd *cmd; 689 #ifdef PCKBCDEBUG 690 int i; 691 #endif 692 693 while ((cmd = TAILQ_FIRST(&q->cmdqueue))) { 694 TAILQ_REMOVE(&q->cmdqueue, cmd, next); 695 #ifdef PCKBCDEBUG 696 printf("pckbc_cleanqueue: removing"); 697 for (i = 0; i < cmd->cmdlen; i++) 698 printf(" %02x", cmd->cmd[i]); 699 printf("\n"); 700 #endif 701 TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); 702 } 703 } 704 705 /* 706 * Timeout error handler: clean queues and data port. 707 * XXX could be less invasive. 708 */ 709 void 710 pckbc_cleanup(void *self) 711 { 712 struct pckbc_internal *t = self; 713 int s; 714 715 printf("pckbc: command timeout\n"); 716 717 s = spltty(); 718 719 if (t->t_slotdata[PCKBC_KBD_SLOT]) 720 pckbc_cleanqueue(t->t_slotdata[PCKBC_KBD_SLOT]); 721 if (t->t_slotdata[PCKBC_AUX_SLOT]) 722 pckbc_cleanqueue(t->t_slotdata[PCKBC_AUX_SLOT]); 723 724 while (bus_space_read_1(t->t_iot, t->t_ioh_c, 0) & KBS_DIB) { 725 KBD_DELAY; 726 (void) bus_space_read_1(t->t_iot, t->t_ioh_d, 0); 727 } 728 729 /* reset KBC? */ 730 731 splx(s); 732 } 733 734 /* 735 * Stop the keyboard controller when we are going to suspend 736 */ 737 void 738 pckbc_stop(struct pckbc_softc *sc) 739 { 740 struct pckbc_internal *t = sc->id; 741 742 timeout_del(&t->t_poll); 743 } 744 745 /* 746 * Reset the keyboard controller in a violent fashion; normally done 747 * after suspend/resume when we do not trust the machine. 748 */ 749 void 750 pckbc_reset(struct pckbc_softc *sc) 751 { 752 struct pckbc_internal *t = sc->id; 753 bus_space_tag_t iot = t->t_iot; 754 bus_space_handle_t ioh_d = t->t_ioh_d, ioh_c = t->t_ioh_c; 755 756 pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); 757 /* KBC selftest */ 758 if (pckbc_send_cmd(iot, ioh_c, KBC_SELFTEST) == 0) 759 return; 760 pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); 761 (void)pckbc_put8042cmd(t); 762 pckbcintr_internal(t->t_sc->id, t->t_sc); 763 } 764 765 /* 766 * Pass command to device during normal operation. 767 * to be called at spltty() 768 */ 769 void 770 pckbc_start(struct pckbc_internal *t, pckbc_slot_t slot) 771 { 772 struct pckbc_slotdata *q = t->t_slotdata[slot]; 773 struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue); 774 775 if (q->polling) { 776 do { 777 pckbc_poll_cmd1(t, slot, cmd); 778 if (cmd->status) 779 printf("pckbc_start: command error\n"); 780 781 if (cmd->flags & KBC_CMDFLAG_SYNC) { 782 wakeup(cmd); 783 cmd = TAILQ_NEXT(cmd, next); 784 } else { 785 TAILQ_REMOVE(&q->cmdqueue, cmd, next); 786 timeout_del(&t->t_cleanup); 787 TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); 788 cmd = TAILQ_FIRST(&q->cmdqueue); 789 } 790 } while (cmd); 791 return; 792 } 793 794 if (!pckbc_send_devcmd(t, slot, cmd->cmd[cmd->cmdidx])) { 795 printf("pckbc_start: send error\n"); 796 /* XXX what now? */ 797 return; 798 } 799 } 800 801 /* 802 * Handle command responses coming in asynchronously, 803 * return nonzero if valid response. 804 * to be called at spltty() 805 */ 806 int 807 pckbc_cmdresponse(struct pckbc_internal *t, pckbc_slot_t slot, u_char data) 808 { 809 struct pckbc_slotdata *q = t->t_slotdata[slot]; 810 struct pckbc_devcmd *cmd = TAILQ_FIRST(&q->cmdqueue); 811 #ifdef DIAGNOSTIC 812 if (!cmd) 813 panic("pckbc_cmdresponse: no active command"); 814 #endif 815 if (cmd->cmdidx < cmd->cmdlen) { 816 if (data != KBC_DEVCMD_ACK && data != KBC_DEVCMD_RESEND) 817 return (0); 818 819 if (data == KBC_DEVCMD_RESEND) { 820 if (cmd->retries++ < 5) { 821 /* try again last command */ 822 goto restart; 823 } else { 824 #ifdef PCKBCDEBUG 825 printf("pckbc: cmd failed\n"); 826 #endif 827 cmd->status = ENXIO; 828 /* dequeue */ 829 } 830 } else { 831 if (++cmd->cmdidx < cmd->cmdlen) 832 goto restart; 833 if (cmd->responselen) 834 return (1); 835 /* else dequeue */ 836 } 837 } else if (cmd->responseidx < cmd->responselen) { 838 cmd->response[cmd->responseidx++] = data; 839 if (cmd->responseidx < cmd->responselen) 840 return (1); 841 /* else dequeue */ 842 } else 843 return (0); 844 845 /* dequeue: */ 846 if (cmd->flags & KBC_CMDFLAG_SYNC) { 847 wakeup(cmd); 848 cmd = TAILQ_NEXT(cmd, next); 849 } else { 850 TAILQ_REMOVE(&q->cmdqueue, cmd, next); 851 timeout_del(&t->t_cleanup); 852 TAILQ_INSERT_TAIL(&q->freequeue, cmd, next); 853 cmd = TAILQ_FIRST(&q->cmdqueue); 854 } 855 if (cmd == NULL) 856 return (1); 857 restart: 858 pckbc_start(t, slot); 859 return (1); 860 } 861 862 /* 863 * Put command into the device's command queue, return zero or errno. 864 */ 865 int 866 pckbc_enqueue_cmd(pckbc_tag_t self, pckbc_slot_t slot, u_char *cmd, int len, 867 int responselen, int sync, u_char *respbuf) 868 { 869 struct pckbc_internal *t = self; 870 struct pckbc_slotdata *q = t->t_slotdata[slot]; 871 struct pckbc_devcmd *nc; 872 int s, isactive, res = 0; 873 874 if ((len > 4) || (responselen > 4)) 875 return (EINVAL); 876 s = spltty(); 877 nc = TAILQ_FIRST(&q->freequeue); 878 if (nc) { 879 TAILQ_REMOVE(&q->freequeue, nc, next); 880 } 881 splx(s); 882 if (!nc) 883 return (ENOMEM); 884 885 bzero(nc, sizeof(*nc)); 886 bcopy(cmd, nc->cmd, len); 887 nc->cmdlen = len; 888 nc->responselen = responselen; 889 nc->flags = (sync ? KBC_CMDFLAG_SYNC : 0); 890 891 s = spltty(); 892 893 if (q->polling && sync) { 894 /* 895 * XXX We should poll until the queue is empty. 896 * But we don't come here normally, so make 897 * it simple and throw away everything. 898 */ 899 pckbc_cleanqueue(q); 900 } 901 902 isactive = CMD_IN_QUEUE(q); 903 TAILQ_INSERT_TAIL(&q->cmdqueue, nc, next); 904 if (!isactive) 905 pckbc_start(t, slot); 906 907 if (q->polling) 908 res = (sync ? nc->status : 0); 909 else if (sync) { 910 if ((res = tsleep(nc, 0, "kbccmd", 1*hz))) { 911 TAILQ_REMOVE(&q->cmdqueue, nc, next); 912 pckbc_cleanup(t); 913 } else { 914 TAILQ_REMOVE(&q->cmdqueue, nc, next); 915 res = nc->status; 916 } 917 } else 918 timeout_add_sec(&t->t_cleanup, 1); 919 920 if (sync) { 921 if (respbuf) 922 bcopy(nc->response, respbuf, responselen); 923 TAILQ_INSERT_TAIL(&q->freequeue, nc, next); 924 } 925 926 splx(s); 927 928 return (res); 929 } 930 931 void 932 pckbc_set_inputhandler(pckbc_tag_t self, pckbc_slot_t slot, pckbc_inputfcn func, 933 void *arg, char *name) 934 { 935 struct pckbc_internal *t = (struct pckbc_internal *)self; 936 struct pckbc_softc *sc = t->t_sc; 937 938 if (slot >= PCKBC_NSLOTS) 939 panic("pckbc_set_inputhandler: bad slot %d", slot); 940 941 (*sc->intr_establish)(sc, slot); 942 943 sc->inputhandler[slot] = func; 944 sc->inputarg[slot] = arg; 945 sc->subname[slot] = name; 946 947 if (pckbc_console && slot == PCKBC_KBD_SLOT) 948 timeout_add_sec(&t->t_poll, 1); 949 } 950 951 void 952 pckbc_poll(void *v) 953 { 954 struct pckbc_internal *t = v; 955 int s; 956 957 s = spltty(); 958 (void)pckbcintr_internal(t, t->t_sc); 959 timeout_add_sec(&t->t_poll, 1); 960 splx(s); 961 } 962 963 int 964 pckbcintr(void *vsc) 965 { 966 struct pckbc_softc *sc = (struct pckbc_softc *)vsc; 967 968 return (pckbcintr_internal(sc->id, sc)); 969 } 970 971 int 972 pckbcintr_internal(struct pckbc_internal *t, struct pckbc_softc *sc) 973 { 974 u_char stat; 975 pckbc_slot_t slot; 976 struct pckbc_slotdata *q; 977 int served = 0, data; 978 979 /* reschedule timeout further into the idle times */ 980 if (timeout_pending(&t->t_poll)) 981 timeout_add_sec(&t->t_poll, 1); 982 983 for(;;) { 984 stat = bus_space_read_1(t->t_iot, t->t_ioh_c, 0); 985 if (!(stat & KBS_DIB)) 986 break; 987 988 served = 1; 989 990 slot = (t->t_haveaux && (stat & 0x20)) ? 991 PCKBC_AUX_SLOT : PCKBC_KBD_SLOT; 992 q = t->t_slotdata[slot]; 993 994 if (!q) { 995 /* XXX do something for live insertion? */ 996 printf("pckbcintr: no dev for slot %d\n", slot); 997 KBD_DELAY; 998 (void) bus_space_read_1(t->t_iot, t->t_ioh_d, 0); 999 continue; 1000 } 1001 1002 if (q->polling) 1003 break; /* pckbc_poll_data() will get it */ 1004 1005 KBD_DELAY; 1006 data = bus_space_read_1(t->t_iot, t->t_ioh_d, 0); 1007 1008 if (CMD_IN_QUEUE(q) && pckbc_cmdresponse(t, slot, data)) 1009 continue; 1010 1011 if (sc != NULL) { 1012 if (sc->inputhandler[slot]) 1013 (*sc->inputhandler[slot])(sc->inputarg[slot], 1014 data); 1015 #ifdef PCKBCDEBUG 1016 else 1017 printf("pckbcintr: slot %d lost %d\n", 1018 slot, data); 1019 #endif 1020 } 1021 } 1022 1023 return (served); 1024 } 1025 1026 int 1027 pckbc_cnattach(bus_space_tag_t iot, bus_addr_t addr, bus_size_t cmd_offset, 1028 int flags) 1029 { 1030 bus_space_handle_t ioh_d, ioh_c; 1031 int res = 0; 1032 1033 if (bus_space_map(iot, addr + KBDATAP, 1, 0, &ioh_d)) 1034 return (ENXIO); 1035 if (bus_space_map(iot, addr + cmd_offset, 1, 0, &ioh_c)) { 1036 bus_space_unmap(iot, ioh_d, 1); 1037 return (ENXIO); 1038 } 1039 1040 pckbc_consdata.t_iot = iot; 1041 pckbc_consdata.t_ioh_d = ioh_d; 1042 pckbc_consdata.t_ioh_c = ioh_c; 1043 pckbc_consdata.t_addr = addr; 1044 pckbc_consdata.t_flags = flags; 1045 timeout_set(&pckbc_consdata.t_cleanup, pckbc_cleanup, &pckbc_consdata); 1046 timeout_set(&pckbc_consdata.t_poll, pckbc_poll, &pckbc_consdata); 1047 1048 /* flush */ 1049 (void) pckbc_poll_data1(iot, ioh_d, ioh_c, PCKBC_KBD_SLOT, 0); 1050 1051 /* selftest? */ 1052 1053 /* init cmd byte, enable ports */ 1054 pckbc_consdata.t_cmdbyte = KC8_CPU; 1055 if (!pckbc_put8042cmd(&pckbc_consdata)) { 1056 printf("kbc: cmd word write error\n"); 1057 res = EIO; 1058 } 1059 1060 if (!res) { 1061 #if (NPCKBD > 0) 1062 res = pckbd_cnattach(&pckbc_consdata); 1063 #else 1064 res = ENXIO; 1065 #endif /* NPCKBD > 0 */ 1066 } 1067 1068 if (res) { 1069 bus_space_unmap(iot, pckbc_consdata.t_ioh_d, 1); 1070 bus_space_unmap(iot, pckbc_consdata.t_ioh_c, 1); 1071 } else { 1072 pckbc_consdata.t_slotdata[PCKBC_KBD_SLOT] = &pckbc_cons_slotdata; 1073 pckbc_init_slotdata(&pckbc_cons_slotdata); 1074 pckbc_console = 1; 1075 } 1076 1077 return (res); 1078 } 1079 1080 struct cfdriver pckbc_cd = { 1081 NULL, "pckbc", DV_DULL 1082 }; 1083