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