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