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