hil.c revision 1.8
1/* $NetBSD: hil.c,v 1.8 2024/05/06 13:27:49 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 89static void hilconfig(struct hil_softc *, u_int); 90static void hilempty(struct hil_softc *); 91static int hilsubmatch(device_t, cfdata_t, const int *, void *); 92static void hil_process_int(struct hil_softc *, uint8_t, uint8_t); 93static int hil_process_poll(struct hil_softc *, uint8_t, uint8_t); 94static void hil_thread(void *); 95static int send_device_cmd(struct hil_softc *sc, u_int device, u_int cmd); 96static void polloff(struct hil_softc *); 97static void pollon(struct hil_softc *); 98 99static int hilwait(struct hil_softc *); 100static int hildatawait(struct hil_softc *); 101 102#define hil_process_pending(sc) wakeup(&(sc)->sc_pending) 103 104static __inline int 105hilwait(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 119static __inline int 120hildatawait(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 138void 139hil_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 sc->sc_status = HIL_STATUS_BUSY; 157} 158 159/* 160 * HIL subdevice attachment 161 */ 162 163int 164hildevprint(void *aux, const char *pnp) 165{ 166 struct hil_attach_args *ha = aux; 167 168 if (pnp != NULL) { 169 aprint_normal("\"%s\" at %s id %x", 170 ha->ha_descr, pnp, ha->ha_id); 171 } 172 aprint_normal(" code %d", ha->ha_code); 173 if (pnp == NULL) { 174 aprint_normal(": %s", ha->ha_descr); 175 } 176 177 return UNCONF; 178} 179 180int 181hilsubmatch(device_t parent, cfdata_t cf, const int *ldesc, void *aux) 182{ 183 struct hil_attach_args *ha = aux; 184 185 if (cf->cf_loc[0] != -1 && 186 cf->cf_loc[0] != ha->ha_code) 187 return 0; 188 189 return config_match(parent, cf, aux); 190} 191 192void 193hil_attach_deferred(device_t self) 194{ 195 struct hil_softc *sc = device_private(self); 196 int tries; 197 uint8_t db; 198 199 sc->sc_status = HIL_STATUS_BUSY; 200 201 /* 202 * Initialize the loop: reconfigure, don't report errors, 203 * put keyboard in cooked mode, and enable autopolling. 204 */ 205 db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL; 206 send_hil_cmd(sc, HIL_WRITELPCTRL, &db, 1, NULL); 207 208 /* 209 * Delay one second for reconfiguration and then read the 210 * data to clear the interrupt (if the loop reconfigured). 211 */ 212 DELAY(1000000); 213 if (bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) & 214 HIL_DATA_RDY) { 215 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 216 DELAY(1); 217 } 218 219 /* 220 * The HIL loop may have reconfigured. If so we proceed on, 221 * if not we loop a few times until a successful reconfiguration 222 * is reported back to us. If the HIL loop is still lost after a 223 * few seconds, give up. 224 */ 225 for (tries = 10; tries != 0; tries--) { 226 if (send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db) == 0) { 227 if (db & (LPS_CONFFAIL | LPS_CONFGOOD)) 228 break; 229 } 230 231#ifdef HILDEBUG 232 aprint_debug(self, "%s: loop not ready, retrying...\n"); 233#endif 234 235 DELAY(1000000); 236 } 237 238 if (tries == 0 || (db & LPS_CONFFAIL)) { 239 aprint_normal_dev(self, "no devices\n"); 240 sc->sc_pending = 0; 241 if (tries == 0) 242 return; 243 } 244 245 /* 246 * Create asynchronous loop event handler thread. 247 */ 248 if (kthread_create(PRI_NONE, 0, NULL, hil_thread, sc, &sc->sc_thread, 249 "%s", device_xname(sc->sc_dev)) != 0) { 250 aprint_error_dev(self, "unable to create event thread\n"); 251 return; 252 } 253 254 /* 255 * Enable loop interrupts. 256 */ 257 send_hil_cmd(sc, HIL_INTON, NULL, 0, NULL); 258 259 /* 260 * Reconfigure if necessary 261 */ 262 sc->sc_status = HIL_STATUS_READY; 263 hil_process_pending(sc); 264} 265 266/* 267 * Asynchronous event processing 268 */ 269 270int 271hil_intr(void *v) 272{ 273 struct hil_softc *sc = v; 274 uint8_t c, stat; 275 276 stat = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT); 277 278 /* 279 * This should never happen if the interrupt comes from the 280 * loop. 281 */ 282 if ((stat & HIL_DATA_RDY) == 0) 283 return 0; /* not for us */ 284 285 c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 286 HILP_DATA); /* clears interrupt */ 287 DELAY(1); 288 289 hil_process_int(sc, stat, c); 290 291 if (sc->sc_status != HIL_STATUS_BUSY) 292 hil_process_pending(sc); 293 294 rnd_add_uint32(&sc->sc_rndsource, (stat << 8) | c); 295 296 return 1; 297} 298 299void 300hil_process_int(struct hil_softc *sc, uint8_t stat, uint8_t c) 301{ 302 device_t child; 303 struct hildev_softc *hdsc; 304 305 switch ((stat >> HIL_SSHIFT) & HIL_SMASK) { 306 case HIL_STATUS: 307 if (c & HIL_ERROR) { 308 sc->sc_cmddone = 1; 309 switch (c) { 310 case HIL_RECONFIG: 311 sc->sc_pending = HIL_PENDING_RECONFIG; 312 break; 313 case HIL_UNPLUGGED: 314 sc->sc_pending = HIL_PENDING_UNPLUGGED; 315 break; 316 } 317 break; 318 } 319 if (c & HIL_COMMAND) { 320 if (c & HIL_POLLDATA) { /* End of data */ 321 child = sc->sc_devices[sc->sc_actdev]; 322 if (child != NULL) { 323 hdsc = device_private(child); 324 if (hdsc->sc_fn != NULL) 325 (*hdsc->sc_fn)(hdsc, 326 sc->sc_pollbp 327 - sc->sc_pollbuf, 328 sc->sc_pollbuf); 329 } 330 } else { /* End of command */ 331 sc->sc_cmdending = 1; 332 } 333 sc->sc_actdev = 0; 334 } else { 335 if (c & HIL_POLLDATA) { /* Start of polled data */ 336 sc->sc_actdev = (c & HIL_DEVMASK); 337 sc->sc_pollbp = sc->sc_pollbuf; 338 } else { /* Start of command */ 339 if (sc->sc_cmddev == (c & HIL_DEVMASK)) { 340 sc->sc_cmdbp = sc->sc_cmdbuf; 341 sc->sc_actdev = 0; 342 } 343 } 344 } 345 break; 346 case HIL_DATA: 347 if (sc->sc_actdev != 0) /* Collecting poll data */ 348 *sc->sc_pollbp++ = c; 349 else { 350 if (sc->sc_cmddev != 0) { /* Collecting cmd data */ 351 if (sc->sc_cmdending) { 352 sc->sc_cmddone = 1; 353 sc->sc_cmdending = 0; 354 } else 355 *sc->sc_cmdbp++ = c; 356 } 357 } 358 break; 359 } 360} 361 362/* 363 * Same as above, but in polled mode: return data as it gets seen, instead 364 * of buffering it. 365 */ 366int 367hil_process_poll(struct hil_softc *sc, uint8_t stat, uint8_t c) 368{ 369 uint8_t db; 370 371 switch ((stat >> HIL_SSHIFT) & HIL_SMASK) { 372 case HIL_STATUS: 373 if (c & HIL_ERROR) { 374 sc->sc_cmddone = 1; 375 switch (c) { 376 case HIL_RECONFIG: 377 /* 378 * Remember that a configuration event 379 * occurred; it will be processed upon 380 * leaving polled mode... 381 */ 382 sc->sc_pending = HIL_PENDING_RECONFIG; 383 /* 384 * However, the keyboard will come back as 385 * cooked, and we rely on it being in raw 386 * mode. So, put it back in raw mode right 387 * now. 388 */ 389 db = 0; 390 send_hil_cmd(sc, HIL_WRITEKBDSADR, &db, 391 1, NULL); 392 break; 393 case HIL_UNPLUGGED: 394 /* 395 * Remember that an unplugged event 396 * occurred; it will be processed upon 397 * leaving polled mode... 398 */ 399 sc->sc_pending = HIL_PENDING_UNPLUGGED; 400 break; 401 } 402 break; 403 } 404 if (c & HIL_COMMAND) { 405 if (!(c & HIL_POLLDATA)) { 406 /* End of command */ 407 sc->sc_cmdending = 1; 408 } 409 sc->sc_actdev = 0; 410 } else { 411 if (c & HIL_POLLDATA) { 412 /* Start of polled data */ 413 sc->sc_actdev = (c & HIL_DEVMASK); 414 sc->sc_pollbp = sc->sc_pollbuf; 415 } else { 416 /* Start of command - should not happen */ 417 if (sc->sc_cmddev == (c & HIL_DEVMASK)) { 418 sc->sc_cmdbp = sc->sc_cmdbuf; 419 sc->sc_actdev = 0; 420 } 421 } 422 } 423 break; 424 case HIL_DATA: 425 if (sc->sc_actdev != 0) /* Collecting poll data */ 426 return 1; 427 else { 428 if (sc->sc_cmddev != 0) { /* Discarding cmd data */ 429 if (sc->sc_cmdending) { 430 sc->sc_cmddone = 1; 431 sc->sc_cmdending = 0; 432 } 433 } 434 } 435 break; 436 } 437 438 return 0; 439} 440 441void 442hil_thread(void *arg) 443{ 444 struct hil_softc *sc = arg; 445 int s; 446 447 for (;;) { 448 s = splhil(); 449 if (sc->sc_pending == 0) { 450 splx(s); 451 (void)tsleep(&sc->sc_pending, PWAIT, "hil_event", 0); 452 continue; 453 } 454 455 switch (sc->sc_pending) { 456 case HIL_PENDING_RECONFIG: 457 sc->sc_pending = 0; 458 hilconfig(sc, sc->sc_maxdev); 459 break; 460 case HIL_PENDING_UNPLUGGED: 461 sc->sc_pending = 0; 462 hilempty(sc); 463 break; 464 } 465 splx(s); 466 } 467} 468 469/* 470 * Called after the loop has reconfigured. Here we need to: 471 * - determine how many devices are on the loop 472 * (some may have been added or removed) 473 * - make sure all keyboards are in raw mode 474 * 475 * Note that our device state is now potentially invalid as 476 * devices may no longer be where they were. What we should 477 * do here is either track where the devices went and move 478 * state around accordingly... 479 * 480 * Note that it is necessary that we operate the loop with the keyboards 481 * in raw mode: they won't cause the loop to generate an NMI if the 482 * ``reset'' key combination is pressed, and we do not handle the hil 483 * NMI interrupt... 484 */ 485void 486hilconfig(struct hil_softc *sc, u_int knowndevs) 487{ 488 struct hil_attach_args ha; 489 uint8_t db; 490 int id, s; 491 492 s = splhil(); 493 494 /* 495 * Determine how many devices are on the loop. 496 */ 497 db = 0; 498 send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db); 499 sc->sc_maxdev = db & LPS_DEVMASK; 500#ifdef HILDEBUG 501 printf("%s: %d device(s)\n", device_xname(sc->sc_dev), sc->sc_maxdev); 502#endif 503 504 /* 505 * Put all keyboards in raw mode now. 506 */ 507 db = 0; 508 send_hil_cmd(sc, HIL_WRITEKBDSADR, &db, 1, NULL); 509 510 /* 511 * If the loop grew, attach new devices. 512 */ 513 for (id = knowndevs + 1; id <= sc->sc_maxdev; id++) { 514 int len; 515 const struct hildevice *hd; 516 517 if (send_device_cmd(sc, id, HIL_IDENTIFY) != 0) { 518 aprint_normal_dev(sc->sc_dev, 519 "no answer from device %d\n", id); 520 continue; 521 } 522 523 len = sc->sc_cmdbp - sc->sc_cmdbuf; 524 if (len == 0) { 525#ifdef HILDEBUG 526 printf("%s: no device at code %d\n", 527 device_xname(sc->sc_dev), id); 528#endif 529 continue; 530 } 531 532 /* Identify and attach device */ 533 for (hd = hildevs; hd->minid >= 0; hd++) 534 if (sc->sc_cmdbuf[0] >= hd->minid && 535 sc->sc_cmdbuf[0] <= hd->maxid) { 536 537 ha.ha_console = *sc->sc_console; 538 ha.ha_code = id; 539 ha.ha_type = hd->type; 540 ha.ha_descr = hd->descr; 541 ha.ha_infolen = len; 542 memcpy(ha.ha_info, sc->sc_cmdbuf, len); 543 544 sc->sc_devices[id] = 545 config_found(sc->sc_dev, &ha, hildevprint, 546 CFARGS(.submatch = hilsubmatch)); 547 548#if NHILKBD > 0 549 /* 550 * If we just attached a keyboard as console, 551 * console choice is not indeterminate anymore. 552 */ 553 if (sc->sc_devices[id] != NULL && 554 ha.ha_type == HIL_DEVICE_KEYBOARD && 555 ha.ha_console != 0) 556 *sc->sc_console = 1; 557#endif 558 } 559 } 560 561 /* 562 * Detach remaining devices, if the loop has shrunk. 563 */ 564 for (id = sc->sc_maxdev + 1; id < NHILD; id++) { 565 if (sc->sc_devices[id] != NULL) 566 config_detach(sc->sc_devices[id], 567 DETACH_FORCE); 568 sc->sc_devices[id] = NULL; 569 } 570 571 sc->sc_cmdbp = sc->sc_cmdbuf; 572 573 splx(s); 574} 575 576/* 577 * Called after the loop has been unplugged. We simply force detach of 578 * all our children. 579 */ 580void 581hilempty(struct hil_softc *sc) 582{ 583 uint8_t db; 584 int id, s; 585 u_int oldmaxdev; 586 587 s = splhil(); 588 589 /* 590 * Wait for the loop to be stable. 591 */ 592 for (;;) { 593 if (send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db) == 0) { 594 if (db & (LPS_CONFFAIL | LPS_CONFGOOD)) 595 break; 596 } else { 597 db = LPS_CONFFAIL; 598 break; 599 } 600 } 601 602 if (db & LPS_CONFFAIL) { 603 sc->sc_maxdev = 0; 604 } else { 605 db = 0; 606 send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db); 607 oldmaxdev = sc->sc_maxdev; 608 sc->sc_maxdev = db & LPS_DEVMASK; 609 610 if (sc->sc_maxdev != 0) { 611 /* 612 * The loop was not unplugged after all, but its 613 * configuration has changed. 614 */ 615 hilconfig(sc, oldmaxdev); 616 return; 617 } 618 } 619 620 /* 621 * Now detach all hil devices. 622 */ 623 for (id = sc->sc_maxdev + 1; id < NHILD; id++) { 624 if (sc->sc_devices[id] != NULL) 625 config_detach(sc->sc_devices[id], 626 DETACH_FORCE); 627 sc->sc_devices[id] = NULL; 628 } 629 630 sc->sc_cmdbp = sc->sc_cmdbuf; 631 632 splx(s); 633} 634 635/* 636 * Low level routines which actually talk to the 8042 chip. 637 */ 638 639/* 640 * Send a command to the 8042 with zero or more bytes of data. 641 * If rdata is non-null, wait for and return a byte of data. 642 */ 643int 644send_hil_cmd(struct hil_softc *sc, u_int cmd, uint8_t *data, u_int dlen, 645 uint8_t *rdata) 646{ 647 uint8_t status; 648 int s; 649 650 s = splhil(); 651 652 if (hilwait(sc) == 0) { 653#ifdef HILDEBUG 654 printf("%s: no answer from the loop\n", 655 device_xname(sc->sc_dev)); 656#endif 657 splx(s); 658 return EBUSY; 659 } 660 661 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, cmd); 662 while (dlen--) { 663 hilwait(sc); 664 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, *data++); 665 DELAY(1); 666 } 667 if (rdata) { 668 do { 669 if (hildatawait(sc) == 0) { 670#ifdef HILDEBUG 671 printf("%s: no answer from the loop\n", 672 device_xname(sc->sc_dev)); 673#endif 674 break; 675 } 676 status = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 677 HILP_STAT); 678 *rdata = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 679 HILP_DATA); 680 DELAY(1); 681 } while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K); 682 } 683 splx(s); 684 return 0; 685} 686 687/* 688 * Send a command to a device on the loop. 689 * Since only one command can be active on the loop at any time, 690 * we must ensure that we are not interrupted during this process. 691 * Hence we mask interrupts to prevent potential access from most 692 * interrupt routines and turn off auto-polling to disable the 693 * internally generated poll commands. 694 * Needs to be called at splhil(). 695 */ 696int 697send_device_cmd(struct hil_softc *sc, u_int device, u_int cmd) 698{ 699 uint8_t status, c; 700 int rc = 0; 701 702 polloff(sc); 703 704 sc->sc_cmdbp = sc->sc_cmdbuf; 705 sc->sc_cmddev = device; 706 707 if (hilwait(sc) == 0) { 708#ifdef HILDEBUG 709 printf("%s: no answer from device %d\n", 710 device_xname(sc->sc_dev), device); 711#endif 712 rc = EBUSY; 713 goto out; 714 } 715 716 /* 717 * Transfer the command and device info to the chip 718 */ 719 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_STARTCMD); 720 hilwait(sc); 721 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 8 + device); 722 hilwait(sc); 723 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, cmd); 724 hilwait(sc); 725 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, HIL_TIMEOUT); 726 727 /* 728 * Trigger the command and wait for completion 729 */ 730 hilwait(sc); 731 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_TRIGGER); 732 sc->sc_cmddone = 0; 733 do { 734 if (hildatawait(sc) == 0) { 735#ifdef HILDEBUG 736 printf("%s: no answer from device %d\n", 737 device_xname(sc->sc_dev), device); 738#endif 739 rc = EBUSY; 740 break; 741 } 742 status = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT); 743 c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 744 DELAY(1); 745 hil_process_int(sc, status, c); 746 } while (sc->sc_cmddone == 0); 747out: 748 sc->sc_cmddev = 0; 749 750 pollon(sc); 751 return rc; 752} 753 754int 755send_hildev_cmd(struct hildev_softc *hdsc, u_int cmd, 756 uint8_t *outbuf, u_int *outlen) 757{ 758 struct hil_softc *sc = device_private(device_parent(hdsc->sc_dev)); 759 int s, rc; 760 761 s = splhil(); 762 763 if ((rc = send_device_cmd(sc, hdsc->sc_code, cmd)) == 0) { 764 /* 765 * Return the command response in the buffer if necessary 766 */ 767 if (outbuf != NULL && outlen != NULL) { 768 *outlen = uimin(*outlen, sc->sc_cmdbp - sc->sc_cmdbuf); 769 memcpy(outbuf, sc->sc_cmdbuf, *outlen); 770 } 771 } 772 773 splx(s); 774 return rc; 775} 776 777/* 778 * Turn auto-polling off and on. 779 */ 780void 781polloff(struct hil_softc *sc) 782{ 783 uint8_t db; 784 785 if (hilwait(sc) == 0) 786 return; 787 788 /* 789 * Turn off auto repeat 790 */ 791 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_SETARR); 792 hilwait(sc); 793 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 0); 794 795 /* 796 * Turn off auto-polling 797 */ 798 hilwait(sc); 799 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READLPCTRL); 800 hildatawait(sc); 801 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 802 db &= ~LPC_AUTOPOLL; 803 hilwait(sc); 804 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_WRITELPCTRL); 805 hilwait(sc); 806 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, db); 807 808 /* 809 * Must wait until polling is really stopped 810 */ 811 do { 812 hilwait(sc); 813 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READBUSY); 814 hildatawait(sc); 815 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 816 } while (db & BSY_LOOPBUSY); 817 818 sc->sc_cmddone = 0; 819 sc->sc_cmddev = 0; 820} 821 822void 823pollon(struct hil_softc *sc) 824{ 825 uint8_t db; 826 827 if (hilwait(sc) == 0) 828 return; 829 830 /* 831 * Turn on auto polling 832 */ 833 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READLPCTRL); 834 hildatawait(sc); 835 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 836 db |= LPC_AUTOPOLL; 837 hilwait(sc); 838 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_WRITELPCTRL); 839 hilwait(sc); 840 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, db); 841 842 /* 843 * Turn off auto repeat - we emulate this through wscons 844 */ 845 hilwait(sc); 846 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_SETARR); 847 hilwait(sc); 848 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 0); 849 DELAY(1); 850} 851 852void 853hil_set_poll(struct hil_softc *sc, int on) 854{ 855 if (on) { 856 pollon(sc); 857 } else { 858 hil_process_pending(sc); 859 send_hil_cmd(sc, HIL_INTON, NULL, 0, NULL); 860 } 861} 862 863int 864hil_poll_data(struct hildev_softc *hdsc, uint8_t *stat, uint8_t *data) 865{ 866 struct hil_softc *sc = device_private(device_parent(hdsc->sc_dev)); 867 uint8_t s, c; 868 869 s = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT); 870 if ((s & HIL_DATA_RDY) == 0) 871 return -1; 872 873 c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA); 874 DELAY(1); 875 876 if (hil_process_poll(sc, s, c)) { 877 /* Discard any data not for us */ 878 if (sc->sc_actdev == hdsc->sc_code) { 879 *stat = s; 880 *data = c; 881 return 0; 882 } 883 } 884 885 return -1; 886} 887