1 /* $NetBSD: hil.c,v 1.7 2022/06/25 02:36:27 tsutsui Exp $ */ 2 /* $OpenBSD: hil.c,v 1.24 2010/11/20 16:45:46 miod Exp $ */ 3 /* 4 * Copyright (c) 2003, 2004, Miodrag Vallat. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 * 28 */ 29 30 /* 31 * Copyright (c) 1988 University of Utah. 32 * Copyright (c) 1990, 1993 33 * The Regents of the University of California. All rights reserved. 34 * 35 * This code is derived from software contributed to Berkeley by 36 * the Systems Programming Group of the University of Utah Computer 37 * Science Department. 38 * 39 * Redistribution and use in source and binary forms, with or without 40 * modification, are permitted provided that the following conditions 41 * are met: 42 * 1. Redistributions of source code must retain the above copyright 43 * notice, this list of conditions and the following disclaimer. 44 * 2. Redistributions in binary form must reproduce the above copyright 45 * notice, this list of conditions and the following disclaimer in the 46 * documentation and/or other materials provided with the distribution. 47 * 3. Neither the name of the University nor the names of its contributors 48 * may be used to endorse or promote products derived from this software 49 * without specific prior written permission. 50 * 51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 61 * SUCH DAMAGE. 62 * 63 * from: Utah $Hdr: hil.c 1.38 92/01/21$ 64 * 65 * @(#)hil.c 8.2 (Berkeley) 1/12/94 66 */ 67 68 #include <sys/param.h> 69 #include <sys/systm.h> 70 #include <sys/conf.h> 71 #include <sys/device.h> 72 #include <sys/file.h> 73 #include <sys/ioctl.h> 74 #include <sys/kernel.h> 75 #include <sys/proc.h> 76 #include <sys/kthread.h> 77 #include <sys/bus.h> 78 #include <sys/cpu.h> 79 80 #include <machine/autoconf.h> 81 82 #include <dev/hil/hilreg.h> 83 #include <dev/hil/hilvar.h> 84 #include <dev/hil/hildevs.h> 85 #include <dev/hil/hildevs_data.h> 86 87 #include "hilkbd.h" 88 89 static void hilconfig(struct hil_softc *, u_int); 90 static void hilempty(struct hil_softc *); 91 static int hilsubmatch(device_t, cfdata_t, const int *, void *); 92 static void hil_process_int(struct hil_softc *, uint8_t, uint8_t); 93 static int hil_process_poll(struct hil_softc *, uint8_t, uint8_t); 94 static void hil_thread(void *); 95 static int send_device_cmd(struct hil_softc *sc, u_int device, u_int cmd); 96 static void polloff(struct hil_softc *); 97 static void pollon(struct hil_softc *); 98 99 static int hilwait(struct hil_softc *); 100 static int hildatawait(struct hil_softc *); 101 102 #define hil_process_pending(sc) wakeup(&(sc)->sc_pending) 103 104 static __inline int 105 hilwait(struct hil_softc *sc) 106 { 107 int cnt; 108 109 for (cnt = 50000; cnt != 0; cnt--) { 110 DELAY(1); 111 if ((bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) & 112 HIL_BUSY) == 0) 113 break; 114 } 115 116 return cnt; 117 } 118 119 static __inline int 120 hildatawait(struct hil_softc *sc) 121 { 122 int cnt; 123 124 for (cnt = 50000; cnt != 0; cnt--) { 125 DELAY(1); 126 if ((bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) & 127 HIL_DATA_RDY) != 0) 128 break; 129 } 130 131 return cnt; 132 } 133 134 /* 135 * Common HIL bus attachment 136 */ 137 138 void 139 hil_attach(struct hil_softc *sc, int *hil_is_console) 140 { 141 142 rnd_attach_source(&sc->sc_rndsource, device_xname(sc->sc_dev), 143 RND_TYPE_TTY, RND_FLAG_DEFAULT); 144 145 aprint_normal("\n"); 146 147 /* 148 * Initialize loop information 149 */ 150 sc->sc_cmdending = 0; 151 sc->sc_actdev = sc->sc_cmddev = 0; 152 sc->sc_cmddone = 0; 153 sc->sc_cmdbp = sc->sc_cmdbuf; 154 sc->sc_pollbp = sc->sc_pollbuf; 155 sc->sc_console = hil_is_console; 156 } 157 158 /* 159 * HIL subdevice attachment 160 */ 161 162 int 163 hildevprint(void *aux, const char *pnp) 164 { 165 struct hil_attach_args *ha = aux; 166 167 if (pnp != NULL) { 168 aprint_normal("\"%s\" at %s id %x", 169 ha->ha_descr, pnp, ha->ha_id); 170 } 171 aprint_normal(" code %d", ha->ha_code); 172 if (pnp == NULL) { 173 aprint_normal(": %s", ha->ha_descr); 174 } 175 176 return UNCONF; 177 } 178 179 int 180 hilsubmatch(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 181 { 182 struct hil_attach_args *ha = aux; 183 184 if (cf->cf_loc[0] != -1 && 185 cf->cf_loc[0] != ha->ha_code) 186 return 0; 187 188 return config_match(parent, cf, aux); 189 } 190 191 void 192 hil_attach_deferred(device_t self) 193 { 194 struct hil_softc *sc = device_private(self); 195 int tries; 196 uint8_t db; 197 198 sc->sc_status = HIL_STATUS_BUSY; 199 200 /* 201 * Initialize the loop: reconfigure, don't report errors, 202 * put keyboard in cooked mode, and enable autopolling. 203 */ 204 db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL; 205 send_hil_cmd(sc, HIL_WRITELPCTRL, &db, 1, NULL); 206 207 /* 208 * Delay one second for reconfiguration and then read the 209 * data to clear the interrupt (if the loop reconfigured). 210 */ 211 DELAY(1000000); 212 if (bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) & 213 HIL_DATA_RDY) { 214 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 215 DELAY(1); 216 } 217 218 /* 219 * The HIL loop may have reconfigured. If so we proceed on, 220 * if not we loop a few times until a successful reconfiguration 221 * is reported back to us. If the HIL loop is still lost after a 222 * few seconds, give up. 223 */ 224 for (tries = 10; tries != 0; tries--) { 225 if (send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db) == 0) { 226 if (db & (LPS_CONFFAIL | LPS_CONFGOOD)) 227 break; 228 } 229 230 #ifdef HILDEBUG 231 aprint_debug(self, "%s: loop not ready, retrying...\n"); 232 #endif 233 234 DELAY(1000000); 235 } 236 237 if (tries == 0 || (db & LPS_CONFFAIL)) { 238 aprint_normal_dev(self, "no devices\n"); 239 sc->sc_pending = 0; 240 if (tries == 0) 241 return; 242 } 243 244 /* 245 * Create asynchronous loop event handler thread. 246 */ 247 if (kthread_create(PRI_NONE, 0, NULL, hil_thread, sc, &sc->sc_thread, 248 "%s", device_xname(sc->sc_dev)) != 0) { 249 aprint_error_dev(self, "unable to create event thread\n"); 250 return; 251 } 252 253 /* 254 * Enable loop interrupts. 255 */ 256 send_hil_cmd(sc, HIL_INTON, NULL, 0, NULL); 257 258 /* 259 * Reconfigure if necessary 260 */ 261 sc->sc_status = HIL_STATUS_READY; 262 hil_process_pending(sc); 263 } 264 265 /* 266 * Asynchronous event processing 267 */ 268 269 int 270 hil_intr(void *v) 271 { 272 struct hil_softc *sc = v; 273 uint8_t c, stat; 274 275 if (cold) 276 return 0; 277 278 stat = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT); 279 280 /* 281 * This should never happen if the interrupt comes from the 282 * loop. 283 */ 284 if ((stat & HIL_DATA_RDY) == 0) 285 return 0; /* not for us */ 286 287 c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 288 HILP_DATA); /* clears interrupt */ 289 DELAY(1); 290 291 hil_process_int(sc, stat, c); 292 293 if (sc->sc_status != HIL_STATUS_BUSY) 294 hil_process_pending(sc); 295 296 rnd_add_uint32(&sc->sc_rndsource, (stat << 8) | c); 297 298 return 1; 299 } 300 301 void 302 hil_process_int(struct hil_softc *sc, uint8_t stat, uint8_t c) 303 { 304 device_t child; 305 struct hildev_softc *hdsc; 306 307 switch ((stat >> HIL_SSHIFT) & HIL_SMASK) { 308 case HIL_STATUS: 309 if (c & HIL_ERROR) { 310 sc->sc_cmddone = 1; 311 switch (c) { 312 case HIL_RECONFIG: 313 sc->sc_pending = HIL_PENDING_RECONFIG; 314 break; 315 case HIL_UNPLUGGED: 316 sc->sc_pending = HIL_PENDING_UNPLUGGED; 317 break; 318 } 319 break; 320 } 321 if (c & HIL_COMMAND) { 322 if (c & HIL_POLLDATA) { /* End of data */ 323 child = sc->sc_devices[sc->sc_actdev]; 324 if (child != NULL) { 325 hdsc = device_private(child); 326 if (hdsc->sc_fn != NULL) 327 (*hdsc->sc_fn)(hdsc, 328 sc->sc_pollbp 329 - sc->sc_pollbuf, 330 sc->sc_pollbuf); 331 } 332 } else { /* End of command */ 333 sc->sc_cmdending = 1; 334 } 335 sc->sc_actdev = 0; 336 } else { 337 if (c & HIL_POLLDATA) { /* Start of polled data */ 338 sc->sc_actdev = (c & HIL_DEVMASK); 339 sc->sc_pollbp = sc->sc_pollbuf; 340 } else { /* Start of command */ 341 if (sc->sc_cmddev == (c & HIL_DEVMASK)) { 342 sc->sc_cmdbp = sc->sc_cmdbuf; 343 sc->sc_actdev = 0; 344 } 345 } 346 } 347 break; 348 case HIL_DATA: 349 if (sc->sc_actdev != 0) /* Collecting poll data */ 350 *sc->sc_pollbp++ = c; 351 else { 352 if (sc->sc_cmddev != 0) { /* Collecting cmd data */ 353 if (sc->sc_cmdending) { 354 sc->sc_cmddone = 1; 355 sc->sc_cmdending = 0; 356 } else 357 *sc->sc_cmdbp++ = c; 358 } 359 } 360 break; 361 } 362 } 363 364 /* 365 * Same as above, but in polled mode: return data as it gets seen, instead 366 * of buffering it. 367 */ 368 int 369 hil_process_poll(struct hil_softc *sc, uint8_t stat, uint8_t c) 370 { 371 uint8_t db; 372 373 switch ((stat >> HIL_SSHIFT) & HIL_SMASK) { 374 case HIL_STATUS: 375 if (c & HIL_ERROR) { 376 sc->sc_cmddone = 1; 377 switch (c) { 378 case HIL_RECONFIG: 379 /* 380 * Remember that a configuration event 381 * occurred; it will be processed upon 382 * leaving polled mode... 383 */ 384 sc->sc_pending = HIL_PENDING_RECONFIG; 385 /* 386 * However, the keyboard will come back as 387 * cooked, and we rely on it being in raw 388 * mode. So, put it back in raw mode right 389 * now. 390 */ 391 db = 0; 392 send_hil_cmd(sc, HIL_WRITEKBDSADR, &db, 393 1, NULL); 394 break; 395 case HIL_UNPLUGGED: 396 /* 397 * Remember that an unplugged event 398 * occurred; it will be processed upon 399 * leaving polled mode... 400 */ 401 sc->sc_pending = HIL_PENDING_UNPLUGGED; 402 break; 403 } 404 break; 405 } 406 if (c & HIL_COMMAND) { 407 if (!(c & HIL_POLLDATA)) { 408 /* End of command */ 409 sc->sc_cmdending = 1; 410 } 411 sc->sc_actdev = 0; 412 } else { 413 if (c & HIL_POLLDATA) { 414 /* Start of polled data */ 415 sc->sc_actdev = (c & HIL_DEVMASK); 416 sc->sc_pollbp = sc->sc_pollbuf; 417 } else { 418 /* Start of command - should not happen */ 419 if (sc->sc_cmddev == (c & HIL_DEVMASK)) { 420 sc->sc_cmdbp = sc->sc_cmdbuf; 421 sc->sc_actdev = 0; 422 } 423 } 424 } 425 break; 426 case HIL_DATA: 427 if (sc->sc_actdev != 0) /* Collecting poll data */ 428 return 1; 429 else { 430 if (sc->sc_cmddev != 0) { /* Discarding cmd data */ 431 if (sc->sc_cmdending) { 432 sc->sc_cmddone = 1; 433 sc->sc_cmdending = 0; 434 } 435 } 436 } 437 break; 438 } 439 440 return 0; 441 } 442 443 void 444 hil_thread(void *arg) 445 { 446 struct hil_softc *sc = arg; 447 int s; 448 449 for (;;) { 450 s = splhil(); 451 if (sc->sc_pending == 0) { 452 splx(s); 453 (void)tsleep(&sc->sc_pending, PWAIT, "hil_event", 0); 454 continue; 455 } 456 457 switch (sc->sc_pending) { 458 case HIL_PENDING_RECONFIG: 459 sc->sc_pending = 0; 460 hilconfig(sc, sc->sc_maxdev); 461 break; 462 case HIL_PENDING_UNPLUGGED: 463 sc->sc_pending = 0; 464 hilempty(sc); 465 break; 466 } 467 splx(s); 468 } 469 } 470 471 /* 472 * Called after the loop has reconfigured. Here we need to: 473 * - determine how many devices are on the loop 474 * (some may have been added or removed) 475 * - make sure all keyboards are in raw mode 476 * 477 * Note that our device state is now potentially invalid as 478 * devices may no longer be where they were. What we should 479 * do here is either track where the devices went and move 480 * state around accordingly... 481 * 482 * Note that it is necessary that we operate the loop with the keyboards 483 * in raw mode: they won't cause the loop to generate an NMI if the 484 * ``reset'' key combination is pressed, and we do not handle the hil 485 * NMI interrupt... 486 */ 487 void 488 hilconfig(struct hil_softc *sc, u_int knowndevs) 489 { 490 struct hil_attach_args ha; 491 uint8_t db; 492 int id, s; 493 494 s = splhil(); 495 496 /* 497 * Determine how many devices are on the loop. 498 */ 499 db = 0; 500 send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db); 501 sc->sc_maxdev = db & LPS_DEVMASK; 502 #ifdef HILDEBUG 503 printf("%s: %d device(s)\n", device_xname(sc->sc_dev), sc->sc_maxdev); 504 #endif 505 506 /* 507 * Put all keyboards in raw mode now. 508 */ 509 db = 0; 510 send_hil_cmd(sc, HIL_WRITEKBDSADR, &db, 1, NULL); 511 512 /* 513 * If the loop grew, attach new devices. 514 */ 515 for (id = knowndevs + 1; id <= sc->sc_maxdev; id++) { 516 int len; 517 const struct hildevice *hd; 518 519 if (send_device_cmd(sc, id, HIL_IDENTIFY) != 0) { 520 aprint_normal_dev(sc->sc_dev, 521 "no answer from device %d\n", id); 522 continue; 523 } 524 525 len = sc->sc_cmdbp - sc->sc_cmdbuf; 526 if (len == 0) { 527 #ifdef HILDEBUG 528 printf("%s: no device at code %d\n", 529 device_xname(sc->sc_dev), id); 530 #endif 531 continue; 532 } 533 534 /* Identify and attach device */ 535 for (hd = hildevs; hd->minid >= 0; hd++) 536 if (sc->sc_cmdbuf[0] >= hd->minid && 537 sc->sc_cmdbuf[0] <= hd->maxid) { 538 539 ha.ha_console = *sc->sc_console; 540 ha.ha_code = id; 541 ha.ha_type = hd->type; 542 ha.ha_descr = hd->descr; 543 ha.ha_infolen = len; 544 memcpy(ha.ha_info, sc->sc_cmdbuf, len); 545 546 sc->sc_devices[id] = 547 config_found(sc->sc_dev, &ha, hildevprint, 548 CFARGS(.submatch = hilsubmatch)); 549 550 #if NHILKBD > 0 551 /* 552 * If we just attached a keyboard as console, 553 * console choice is not indeterminate anymore. 554 */ 555 if (sc->sc_devices[id] != NULL && 556 ha.ha_type == HIL_DEVICE_KEYBOARD && 557 ha.ha_console != 0) 558 *sc->sc_console = 1; 559 #endif 560 } 561 } 562 563 /* 564 * Detach remaining devices, if the loop has shrunk. 565 */ 566 for (id = sc->sc_maxdev + 1; id < NHILD; id++) { 567 if (sc->sc_devices[id] != NULL) 568 config_detach(sc->sc_devices[id], 569 DETACH_FORCE); 570 sc->sc_devices[id] = NULL; 571 } 572 573 sc->sc_cmdbp = sc->sc_cmdbuf; 574 575 splx(s); 576 } 577 578 /* 579 * Called after the loop has been unplugged. We simply force detach of 580 * all our children. 581 */ 582 void 583 hilempty(struct hil_softc *sc) 584 { 585 uint8_t db; 586 int id, s; 587 u_int oldmaxdev; 588 589 s = splhil(); 590 591 /* 592 * Wait for the loop to be stable. 593 */ 594 for (;;) { 595 if (send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db) == 0) { 596 if (db & (LPS_CONFFAIL | LPS_CONFGOOD)) 597 break; 598 } else { 599 db = LPS_CONFFAIL; 600 break; 601 } 602 } 603 604 if (db & LPS_CONFFAIL) { 605 sc->sc_maxdev = 0; 606 } else { 607 db = 0; 608 send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db); 609 oldmaxdev = sc->sc_maxdev; 610 sc->sc_maxdev = db & LPS_DEVMASK; 611 612 if (sc->sc_maxdev != 0) { 613 /* 614 * The loop was not unplugged after all, but its 615 * configuration has changed. 616 */ 617 hilconfig(sc, oldmaxdev); 618 return; 619 } 620 } 621 622 /* 623 * Now detach all hil devices. 624 */ 625 for (id = sc->sc_maxdev + 1; id < NHILD; id++) { 626 if (sc->sc_devices[id] != NULL) 627 config_detach(sc->sc_devices[id], 628 DETACH_FORCE); 629 sc->sc_devices[id] = NULL; 630 } 631 632 sc->sc_cmdbp = sc->sc_cmdbuf; 633 634 splx(s); 635 } 636 637 /* 638 * Low level routines which actually talk to the 8042 chip. 639 */ 640 641 /* 642 * Send a command to the 8042 with zero or more bytes of data. 643 * If rdata is non-null, wait for and return a byte of data. 644 */ 645 int 646 send_hil_cmd(struct hil_softc *sc, u_int cmd, uint8_t *data, u_int dlen, 647 uint8_t *rdata) 648 { 649 uint8_t status; 650 int s; 651 652 s = splhil(); 653 654 if (hilwait(sc) == 0) { 655 #ifdef HILDEBUG 656 printf("%s: no answer from the loop\n", 657 device_xname(sc->sc_dev)); 658 #endif 659 splx(s); 660 return EBUSY; 661 } 662 663 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, cmd); 664 while (dlen--) { 665 hilwait(sc); 666 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, *data++); 667 DELAY(1); 668 } 669 if (rdata) { 670 do { 671 if (hildatawait(sc) == 0) { 672 #ifdef HILDEBUG 673 printf("%s: no answer from the loop\n", 674 device_xname(sc->sc_dev)); 675 #endif 676 break; 677 } 678 status = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 679 HILP_STAT); 680 *rdata = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 681 HILP_DATA); 682 DELAY(1); 683 } while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K); 684 } 685 splx(s); 686 return 0; 687 } 688 689 /* 690 * Send a command to a device on the loop. 691 * Since only one command can be active on the loop at any time, 692 * we must ensure that we are not interrupted during this process. 693 * Hence we mask interrupts to prevent potential access from most 694 * interrupt routines and turn off auto-polling to disable the 695 * internally generated poll commands. 696 * Needs to be called at splhil(). 697 */ 698 int 699 send_device_cmd(struct hil_softc *sc, u_int device, u_int cmd) 700 { 701 uint8_t status, c; 702 int rc = 0; 703 704 polloff(sc); 705 706 sc->sc_cmdbp = sc->sc_cmdbuf; 707 sc->sc_cmddev = device; 708 709 if (hilwait(sc) == 0) { 710 #ifdef HILDEBUG 711 printf("%s: no answer from device %d\n", 712 device_xname(sc->sc_dev), device); 713 #endif 714 rc = EBUSY; 715 goto out; 716 } 717 718 /* 719 * Transfer the command and device info to the chip 720 */ 721 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_STARTCMD); 722 hilwait(sc); 723 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 8 + device); 724 hilwait(sc); 725 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, cmd); 726 hilwait(sc); 727 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, HIL_TIMEOUT); 728 729 /* 730 * Trigger the command and wait for completion 731 */ 732 hilwait(sc); 733 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_TRIGGER); 734 sc->sc_cmddone = 0; 735 do { 736 if (hildatawait(sc) == 0) { 737 #ifdef HILDEBUG 738 printf("%s: no answer from device %d\n", 739 device_xname(sc->sc_dev), device); 740 #endif 741 rc = EBUSY; 742 break; 743 } 744 status = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT); 745 c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 746 DELAY(1); 747 hil_process_int(sc, status, c); 748 } while (sc->sc_cmddone == 0); 749 out: 750 sc->sc_cmddev = 0; 751 752 pollon(sc); 753 return rc; 754 } 755 756 int 757 send_hildev_cmd(struct hildev_softc *hdsc, u_int cmd, 758 uint8_t *outbuf, u_int *outlen) 759 { 760 struct hil_softc *sc = device_private(device_parent(hdsc->sc_dev)); 761 int s, rc; 762 763 s = splhil(); 764 765 if ((rc = send_device_cmd(sc, hdsc->sc_code, cmd)) == 0) { 766 /* 767 * Return the command response in the buffer if necessary 768 */ 769 if (outbuf != NULL && outlen != NULL) { 770 *outlen = uimin(*outlen, sc->sc_cmdbp - sc->sc_cmdbuf); 771 memcpy(outbuf, sc->sc_cmdbuf, *outlen); 772 } 773 } 774 775 splx(s); 776 return rc; 777 } 778 779 /* 780 * Turn auto-polling off and on. 781 */ 782 void 783 polloff(struct hil_softc *sc) 784 { 785 uint8_t db; 786 787 if (hilwait(sc) == 0) 788 return; 789 790 /* 791 * Turn off auto repeat 792 */ 793 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_SETARR); 794 hilwait(sc); 795 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 0); 796 797 /* 798 * Turn off auto-polling 799 */ 800 hilwait(sc); 801 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READLPCTRL); 802 hildatawait(sc); 803 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 804 db &= ~LPC_AUTOPOLL; 805 hilwait(sc); 806 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_WRITELPCTRL); 807 hilwait(sc); 808 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, db); 809 810 /* 811 * Must wait until polling is really stopped 812 */ 813 do { 814 hilwait(sc); 815 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READBUSY); 816 hildatawait(sc); 817 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 818 } while (db & BSY_LOOPBUSY); 819 820 sc->sc_cmddone = 0; 821 sc->sc_cmddev = 0; 822 } 823 824 void 825 pollon(struct hil_softc *sc) 826 { 827 uint8_t db; 828 829 if (hilwait(sc) == 0) 830 return; 831 832 /* 833 * Turn on auto polling 834 */ 835 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READLPCTRL); 836 hildatawait(sc); 837 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 838 db |= LPC_AUTOPOLL; 839 hilwait(sc); 840 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_WRITELPCTRL); 841 hilwait(sc); 842 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, db); 843 844 /* 845 * Turn off auto repeat - we emulate this through wscons 846 */ 847 hilwait(sc); 848 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_SETARR); 849 hilwait(sc); 850 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 0); 851 DELAY(1); 852 } 853 854 void 855 hil_set_poll(struct hil_softc *sc, int on) 856 { 857 if (on) { 858 pollon(sc); 859 } else { 860 hil_process_pending(sc); 861 send_hil_cmd(sc, HIL_INTON, NULL, 0, NULL); 862 } 863 } 864 865 int 866 hil_poll_data(struct hildev_softc *hdsc, uint8_t *stat, uint8_t *data) 867 { 868 struct hil_softc *sc = device_private(device_parent(hdsc->sc_dev)); 869 uint8_t s, c; 870 871 s = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT); 872 if ((s & HIL_DATA_RDY) == 0) 873 return -1; 874 875 c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 876 DELAY(1); 877 878 if (hil_process_poll(sc, s, c)) { 879 /* Discard any data not for us */ 880 if (sc->sc_actdev == hdsc->sc_code) { 881 *stat = s; 882 *data = c; 883 return 0; 884 } 885 } 886 887 return -1; 888 } 889