root/dev/hil/hil.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hilwait
  2. hildatawait
  3. hil_attach
  4. hildevprint
  5. hilsubmatch
  6. hil_attach_deferred
  7. hil_intr
  8. hil_process_int
  9. hil_process_poll
  10. hil_thread
  11. hilconfig
  12. hilempty
  13. send_hil_cmd
  14. send_device_cmd
  15. send_hildev_cmd
  16. polloff
  17. pollon
  18. hil_set_poll
  19. hil_poll_data

    1 /*      $OpenBSD: hil.c,v 1.23 2006/12/16 20:07:13 miod Exp $   */
    2 /*
    3  * Copyright (c) 2003, 2004, Miodrag Vallat.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   25  * POSSIBILITY OF SUCH DAMAGE.
   26  *
   27  */
   28 
   29 /*
   30  * Copyright (c) 1988 University of Utah.
   31  * Copyright (c) 1990, 1993
   32  *      The Regents of the University of California.  All rights reserved.
   33  *
   34  * This code is derived from software contributed to Berkeley by
   35  * the Systems Programming Group of the University of Utah Computer
   36  * Science Department.
   37  *
   38  * Redistribution and use in source and binary forms, with or without
   39  * modification, are permitted provided that the following conditions
   40  * are met:
   41  * 1. Redistributions of source code must retain the above copyright
   42  *    notice, this list of conditions and the following disclaimer.
   43  * 2. Redistributions in binary form must reproduce the above copyright
   44  *    notice, this list of conditions and the following disclaimer in the
   45  *    documentation and/or other materials provided with the distribution.
   46  * 3. Neither the name of the University nor the names of its contributors
   47  *    may be used to endorse or promote products derived from this software
   48  *    without specific prior written permission.
   49  *
   50  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   51  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   52  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   53  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   54  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   55  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   56  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   57  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   58  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   59  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   60  * SUCH DAMAGE.
   61  *
   62  * from: Utah $Hdr: hil.c 1.38 92/01/21$
   63  *
   64  *      @(#)hil.c       8.2 (Berkeley) 1/12/94
   65  */
   66 
   67 #include <sys/param.h>
   68 #include <sys/systm.h>
   69 #include <sys/conf.h>
   70 #include <sys/device.h>
   71 #include <sys/file.h>
   72 #include <sys/ioctl.h>
   73 #include <sys/kernel.h>
   74 #include <sys/proc.h>
   75 #include <sys/kthread.h>
   76 
   77 #include <machine/autoconf.h>
   78 #include <machine/bus.h>
   79 #include <machine/cpu.h>
   80 
   81 #include <dev/hil/hilreg.h>
   82 #include <dev/hil/hilvar.h>
   83 #include <dev/hil/hildevs.h>
   84 #include <dev/hil/hildevs_data.h>
   85 
   86 #include "hilkbd.h"
   87 
   88 /*
   89  * splhigh is extremely conservative but insures atomic operation,
   90  * splvm (clock only interrupts) seems to be good enough in practice.
   91  */
   92 #define splhil  splvm
   93 
   94 struct cfdriver hil_cd = {
   95         NULL, "hil", DV_DULL
   96 };
   97 
   98 void    hilconfig(struct hil_softc *, u_int);
   99 void    hilempty(struct hil_softc *);
  100 int     hilsubmatch(struct device *, void *, void *);
  101 void    hil_process_int(struct hil_softc *, u_int8_t, u_int8_t);
  102 int     hil_process_poll(struct hil_softc *, u_int8_t, u_int8_t);
  103 void    hil_thread(void *);
  104 int     send_device_cmd(struct hil_softc *sc, u_int device, u_int cmd);
  105 void    polloff(struct hil_softc *);
  106 void    pollon(struct hil_softc *);
  107 
  108 static int hilwait(struct hil_softc *);
  109 static int hildatawait(struct hil_softc *);
  110 
  111 #define hil_process_pending(sc) wakeup(&(sc)->sc_pending)
  112 
  113 static __inline int
  114 hilwait(struct hil_softc *sc)
  115 {
  116         int cnt;
  117 
  118         for (cnt = 50000; cnt != 0; cnt--) {
  119                 DELAY(1);
  120                 if ((bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) &
  121                     HIL_BUSY) == 0)
  122                         break;
  123         }
  124 
  125         return (cnt);
  126 }
  127 
  128 static __inline int
  129 hildatawait(struct hil_softc *sc)
  130 {
  131         int cnt;
  132 
  133         for (cnt = 50000; cnt != 0; cnt--) {
  134                 DELAY(1);
  135                 if ((bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) &
  136                     HIL_DATA_RDY) != 0)
  137                         break;
  138         }
  139 
  140         return (cnt);
  141 }
  142 
  143 /*
  144  * Common HIL bus attachment
  145  */
  146 
  147 void
  148 hil_attach(struct hil_softc *sc, int *hil_is_console)
  149 {
  150         printf("\n");
  151 
  152         /*
  153          * Initialize loop information
  154          */
  155         sc->sc_cmdending = 0;
  156         sc->sc_actdev = sc->sc_cmddev = 0;
  157         sc->sc_cmddone = 0;
  158         sc->sc_cmdbp = sc->sc_cmdbuf;
  159         sc->sc_pollbp = sc->sc_pollbuf;
  160         sc->sc_console = hil_is_console;
  161 }
  162 
  163 /*
  164  * HIL subdevice attachment
  165  */
  166 
  167 int
  168 hildevprint(void *aux, const char *pnp)
  169 {
  170         struct hil_attach_args *ha = aux;
  171 
  172         if (pnp != NULL) {
  173                 printf("\"%s\" at %s id %x",
  174                     ha->ha_descr, pnp, ha->ha_id);
  175         }
  176         printf(" code %d", ha->ha_code);
  177         if (pnp == NULL) {
  178                 printf(": %s", ha->ha_descr);
  179         }
  180 
  181         return (UNCONF);
  182 }
  183 
  184 int
  185 hilsubmatch(struct device *parent, void *vcf, void *aux)
  186 {
  187         struct hil_attach_args *ha = aux;
  188         struct cfdata *cf = vcf;
  189 
  190         if (cf->cf_loc[0] != -1 &&
  191             cf->cf_loc[0] != ha->ha_code)
  192                 return (0);
  193 
  194         return ((*cf->cf_attach->ca_match)(parent, vcf, aux));
  195 }
  196 
  197 void
  198 hil_attach_deferred(void *v)
  199 {
  200         struct hil_softc *sc = v;
  201         int tries;
  202         u_int8_t db;
  203 
  204         sc->sc_status = HIL_STATUS_BUSY;
  205 
  206         /*
  207          * Initialize the loop: reconfigure, don't report errors,
  208          * put keyboard in cooked mode, and enable autopolling.
  209          */
  210         db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL;
  211         send_hil_cmd(sc, HIL_WRITELPCTRL, &db, 1, NULL);
  212 
  213         /*
  214          * Delay one second for reconfiguration and then read the
  215          * data to clear the interrupt (if the loop reconfigured).
  216          */
  217         DELAY(1000000);
  218         if (bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT) &
  219             HIL_DATA_RDY) {
  220                 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
  221                 DELAY(1);
  222         }
  223 
  224         /*
  225          * The HIL loop may have reconfigured.  If so we proceed on,
  226          * if not we loop a few times until a successful reconfiguration
  227          * is reported back to us. If the HIL loop is still lost after a
  228          * few seconds, give up.
  229          */
  230         for (tries = 10; tries != 0; tries--) {
  231                 if (send_hil_cmd(sc, HIL_READLPSTAT, NULL, 0, &db) == 0) {
  232                         if (db & (LPS_CONFFAIL | LPS_CONFGOOD))
  233                                 break;
  234                 }
  235 
  236 #ifdef HILDEBUG
  237                 printf("%s: loop not ready, retrying...\n",
  238                     sc->sc_dev.dv_xname);
  239 #endif
  240 
  241                 DELAY(1000000);
  242         }
  243 
  244         if (tries == 0 || (db & LPS_CONFFAIL)) {
  245                 printf("%s: no devices\n", sc->sc_dev.dv_xname);
  246                 sc->sc_pending = 0;
  247                 if (tries == 0)
  248                         return;
  249         }
  250 
  251         /*
  252          * Create asynchronous loop event handler thread.
  253          */
  254         if (kthread_create(hil_thread, sc, &sc->sc_thread,
  255             "%s", sc->sc_dev.dv_xname) != 0) {
  256                 printf("%s: unable to create event thread\n",
  257                     sc->sc_dev.dv_xname);
  258                 return;
  259         }
  260 
  261         /*
  262          * Enable loop interrupts.
  263          */
  264         send_hil_cmd(sc, HIL_INTON, NULL, 0, NULL);
  265 
  266         /*
  267          * Reconfigure if necessary
  268          */
  269         sc->sc_status = HIL_STATUS_READY;
  270         hil_process_pending(sc);
  271 }
  272 
  273 /*
  274  * Asynchronous event processing
  275  */
  276 
  277 int
  278 hil_intr(void *v)
  279 {
  280         struct hil_softc *sc = v;
  281         u_int8_t c, stat;
  282 
  283         if (cold)
  284                 return (0);
  285 
  286         stat = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT);
  287 
  288         /*
  289          * This should never happen if the interrupt comes from the
  290          * loop.
  291          */
  292         if ((stat & HIL_DATA_RDY) == 0)
  293                 return (0);     /* not for us */
  294 
  295         c = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
  296             HILP_DATA); /* clears interrupt */
  297         DELAY(1);
  298 
  299         hil_process_int(sc, stat, c);
  300 
  301         if (sc->sc_status != HIL_STATUS_BUSY)
  302                 hil_process_pending(sc);
  303 
  304         return (1);
  305 }
  306 
  307 void
  308 hil_process_int(struct hil_softc *sc, u_int8_t stat, u_int8_t c)
  309 {
  310         struct hildev_softc *dev;
  311 
  312         switch ((stat >> HIL_SSHIFT) & HIL_SMASK) {
  313         case HIL_STATUS:
  314                 if (c & HIL_ERROR) {
  315                         sc->sc_cmddone = 1;
  316                         switch (c) {
  317                         case HIL_RECONFIG:
  318                                 sc->sc_pending = HIL_PENDING_RECONFIG;
  319                                 break;
  320                         case HIL_UNPLUGGED:
  321                                 sc->sc_pending = HIL_PENDING_UNPLUGGED;
  322                                 break;
  323                         }
  324                         break;
  325                 }
  326                 if (c & HIL_COMMAND) {
  327                         if (c & HIL_POLLDATA) { /* End of data */
  328                                 dev = sc->sc_devices[sc->sc_actdev];
  329                                 if (dev != NULL && dev->sc_fn != NULL)
  330                                         dev->sc_fn(dev,
  331                                             sc->sc_pollbp - sc->sc_pollbuf,
  332                                             sc->sc_pollbuf);
  333                         } else {                /* End of command */
  334                                 sc->sc_cmdending = 1;
  335                         }
  336                         sc->sc_actdev = 0;
  337                 } else {
  338                         if (c & HIL_POLLDATA) { /* Start of polled data */
  339                                 sc->sc_actdev = (c & HIL_DEVMASK);
  340                                 sc->sc_pollbp = sc->sc_pollbuf;
  341                         } else {                /* Start of command */
  342                                 if (sc->sc_cmddev == (c & HIL_DEVMASK)) {
  343                                         sc->sc_cmdbp = sc->sc_cmdbuf;
  344                                         sc->sc_actdev = 0;
  345                                 }
  346                         }
  347                 }
  348                 break;
  349         case HIL_DATA:
  350                 if (sc->sc_actdev != 0) /* Collecting poll data */
  351                         *sc->sc_pollbp++ = c;
  352                 else {
  353                         if (sc->sc_cmddev != 0) {  /* Collecting cmd data */
  354                                 if (sc->sc_cmdending) {
  355                                         sc->sc_cmddone = 1;
  356                                         sc->sc_cmdending = 0;
  357                                 } else  
  358                                         *sc->sc_cmdbp++ = c;
  359                         }
  360                 }
  361                 break;
  362         }
  363 }
  364 
  365 /*
  366  * Same as above, but in polled mode: return data as it gets seen, instead
  367  * of buffering it.
  368  */
  369 int
  370 hil_process_poll(struct hil_softc *sc, u_int8_t stat, u_int8_t c)
  371 {
  372         u_int8_t db;
  373 
  374         switch ((stat >> HIL_SSHIFT) & HIL_SMASK) {
  375         case HIL_STATUS:
  376                 if (c & HIL_ERROR) {
  377                         sc->sc_cmddone = 1;
  378                         switch (c) {
  379                         case HIL_RECONFIG:
  380                                 /*
  381                                  * Remember that a configuration event
  382                                  * occurred; it will be processed upon
  383                                  * leaving polled mode...
  384                                  */
  385                                 sc->sc_pending = HIL_PENDING_RECONFIG;
  386                                 /*
  387                                  * However, the keyboard will come back as
  388                                  * cooked, and we rely on it being in raw
  389                                  * mode. So, put it back in raw mode right
  390                                  * now.
  391                                  */
  392                                 db = 0;
  393                                 send_hil_cmd(sc, HIL_WRITEKBDSADR, &db,
  394                                     1, NULL);
  395                                 break;
  396                         case HIL_UNPLUGGED:
  397                                 /*
  398                                  * Remember that an unplugged event
  399                                  * occured; it will be processed upon
  400                                  * leaving polled mode...
  401                                  */
  402                                 sc->sc_pending = HIL_PENDING_UNPLUGGED;
  403                                 break;
  404                         }
  405                         break;
  406                 }
  407                 if (c & HIL_COMMAND) {
  408                         if (!(c & HIL_POLLDATA)) {
  409                                 /* End of command */
  410                                 sc->sc_cmdending = 1;
  411                         }
  412                         sc->sc_actdev = 0;
  413                 } else {
  414                         if (c & HIL_POLLDATA) {
  415                                 /* Start of polled data */
  416                                 sc->sc_actdev = (c & HIL_DEVMASK);
  417                                 sc->sc_pollbp = sc->sc_pollbuf;
  418                         } else {
  419                                 /* Start of command - should not happen */
  420                                 if (sc->sc_cmddev == (c & HIL_DEVMASK)) {
  421                                         sc->sc_cmdbp = sc->sc_cmdbuf;
  422                                         sc->sc_actdev = 0;
  423                                 }
  424                         }
  425                 }
  426                 break;
  427         case HIL_DATA:
  428                 if (sc->sc_actdev != 0) /* Collecting poll data */
  429                         return 1;
  430                 else {
  431                         if (sc->sc_cmddev != 0) {  /* Discarding cmd data */
  432                                 if (sc->sc_cmdending) {
  433                                         sc->sc_cmddone = 1;
  434                                         sc->sc_cmdending = 0;
  435                                 }
  436                         }
  437                 }
  438                 break;
  439         }
  440 
  441         return 0;
  442 }
  443 
  444 void
  445 hil_thread(void *arg)
  446 {
  447         struct hil_softc *sc = arg;
  448         int s;
  449 
  450         for (;;) {
  451                 s = splhil();
  452                 if (sc->sc_pending == 0) {
  453                         splx(s);
  454                         (void)tsleep(&sc->sc_pending, PWAIT, "hil_event", 0);
  455                         continue;
  456                 }
  457 
  458                 switch (sc->sc_pending) {
  459                 case HIL_PENDING_RECONFIG:
  460                         sc->sc_pending = 0;
  461                         hilconfig(sc, sc->sc_maxdev);
  462                         break;
  463                 case HIL_PENDING_UNPLUGGED:
  464                         sc->sc_pending = 0;
  465                         hilempty(sc);
  466                         break;
  467                 }
  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         u_int8_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", sc->sc_dev.dv_xname, 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                         printf("%s: no answer from device %d\n",
  521                             sc->sc_dev.dv_xname, 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                             sc->sc_dev.dv_xname, 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                         bcopy(sc->sc_cmdbuf, ha.ha_info, len);
  545 
  546                         sc->sc_devices[id] = (struct hildev_softc *)
  547                             config_found_sm(&sc->sc_dev, &ha, hildevprint,
  548                                 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((struct device *)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         u_int8_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((struct device *)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, u_int8_t *data, u_int dlen,
  647     u_int8_t *rdata)
  648 {
  649         u_int8_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", sc->sc_dev.dv_xname);
  657 #endif
  658                 splx(s);
  659                 return (EBUSY);
  660         }
  661 
  662         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, cmd);
  663         while (dlen--) {
  664                 hilwait(sc);
  665                 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, *data++);
  666                 DELAY(1);
  667         }
  668         if (rdata) {
  669                 do {
  670                         if (hildatawait(sc) == 0) {
  671 #ifdef HILDEBUG
  672                                 printf("%s: no answer from the loop\n",
  673                                     sc->sc_dev.dv_xname);
  674 #endif
  675                                 break;
  676                         }
  677                         status = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
  678                             HILP_STAT);
  679                         *rdata = bus_space_read_1(sc->sc_bst, sc->sc_bsh,
  680                             HILP_DATA);
  681                         DELAY(1);
  682                 } while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K);
  683         }
  684         splx(s);
  685         return (0);
  686 }
  687 
  688 /*
  689  * Send a command to a device on the loop.
  690  * Since only one command can be active on the loop at any time,
  691  * we must ensure that we are not interrupted during this process.
  692  * Hence we mask interrupts to prevent potential access from most
  693  * interrupt routines and turn off auto-polling to disable the
  694  * internally generated poll commands.
  695  * Needs to be called at splhil().
  696  */
  697 int
  698 send_device_cmd(struct hil_softc *sc, u_int device, u_int cmd)
  699 {
  700         u_int8_t status, c;
  701         int rc = 0;
  702 
  703         polloff(sc);
  704 
  705         sc->sc_cmdbp = sc->sc_cmdbuf;
  706         sc->sc_cmddev = device;
  707 
  708         if (hilwait(sc) == 0) {
  709 #ifdef HILDEBUG
  710                 printf("%s: no answer from device %d\n",
  711                     sc->sc_dev.dv_xname, device);
  712 #endif
  713                 rc = EBUSY;
  714                 goto out;
  715         }
  716 
  717         /*
  718          * Transfer the command and device info to the chip
  719          */
  720         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_STARTCMD);
  721         hilwait(sc);
  722         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 8 + device);
  723         hilwait(sc);
  724         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, cmd);
  725         hilwait(sc);
  726         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, HIL_TIMEOUT);
  727 
  728         /*
  729          * Trigger the command and wait for completion
  730          */
  731         hilwait(sc);
  732         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_TRIGGER);
  733         sc->sc_cmddone = 0;
  734         do {
  735                 if (hildatawait(sc) == 0) {
  736 #ifdef HILDEBUG
  737                         printf("%s: no answer from device %d\n",
  738                             sc->sc_dev.dv_xname, device);
  739 #endif
  740                         rc = EBUSY;
  741                         break;
  742                 }
  743                 status = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT);
  744                 c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
  745                 DELAY(1);
  746                 hil_process_int(sc, status, c);
  747         } while (sc->sc_cmddone == 0);
  748 out:
  749         sc->sc_cmddev = 0;
  750 
  751         pollon(sc);
  752         return (rc);
  753 }
  754 
  755 int
  756 send_hildev_cmd(struct hildev_softc *dev, u_int cmd,
  757     u_int8_t *outbuf, u_int *outlen)
  758 {
  759         struct hil_softc *sc = (struct hil_softc *)dev->sc_dev.dv_parent;
  760         int s, rc;
  761        
  762         s = splhil();
  763 
  764         if ((rc = send_device_cmd(sc, dev->sc_code, cmd)) == 0) {
  765                 /*
  766                  * Return the command response in the buffer if necessary
  767                 */
  768                 if (outbuf != NULL && outlen != NULL) {
  769                         *outlen = min(*outlen, sc->sc_cmdbp - sc->sc_cmdbuf);
  770                         bcopy(sc->sc_cmdbuf, outbuf, *outlen);
  771                 }
  772         }
  773 
  774         splx(s);
  775         return (rc);
  776 }
  777 
  778 /*
  779  * Turn auto-polling off and on.
  780  */
  781 void
  782 polloff(struct hil_softc *sc)
  783 {
  784         u_int8_t db;
  785 
  786         if (hilwait(sc) == 0)
  787                 return;
  788 
  789         /*
  790          * Turn off auto repeat
  791          */
  792         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_SETARR);
  793         hilwait(sc);
  794         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 0);
  795 
  796         /*
  797          * Turn off auto-polling
  798          */
  799         hilwait(sc);
  800         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READLPCTRL);
  801         hildatawait(sc);
  802         db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
  803         db &= ~LPC_AUTOPOLL;
  804         hilwait(sc);
  805         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_WRITELPCTRL);
  806         hilwait(sc);
  807         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, db);
  808 
  809         /*
  810          * Must wait until polling is really stopped
  811          */
  812         do {    
  813                 hilwait(sc);
  814                 bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READBUSY);
  815                 hildatawait(sc);
  816                 db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
  817         } while (db & BSY_LOOPBUSY);
  818 
  819         sc->sc_cmddone = 0;
  820         sc->sc_cmddev = 0;
  821 }
  822 
  823 void
  824 pollon(struct hil_softc *sc)
  825 {
  826         u_int8_t db;
  827 
  828         if (hilwait(sc) == 0)
  829                 return;
  830 
  831         /*
  832          * Turn on auto polling
  833          */
  834         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_READLPCTRL);
  835         hildatawait(sc);
  836         db = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
  837         db |= LPC_AUTOPOLL;
  838         hilwait(sc);
  839         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_WRITELPCTRL);
  840         hilwait(sc);
  841         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, db);
  842 
  843         /*
  844          * Turn off auto repeat - we emulate this through wscons
  845          */
  846         hilwait(sc);
  847         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_CMD, HIL_SETARR);
  848         hilwait(sc);
  849         bus_space_write_1(sc->sc_bst, sc->sc_bsh, HILP_DATA, 0);
  850         DELAY(1);
  851 }
  852 
  853 void
  854 hil_set_poll(struct hil_softc *sc, int on)
  855 {
  856         if (on) {
  857                 pollon(sc);
  858         } else {
  859                 hil_process_pending(sc);
  860                 send_hil_cmd(sc, HIL_INTON, NULL, 0, NULL);
  861         }
  862 }
  863 
  864 int
  865 hil_poll_data(struct hildev_softc *dev, u_int8_t *stat, u_int8_t *data)
  866 {
  867         struct hil_softc *sc = (struct hil_softc *)dev->sc_dev.dv_parent;
  868         u_int8_t s, c;
  869 
  870         s = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_STAT);
  871         if ((s & HIL_DATA_RDY) == 0)
  872                 return -1;
  873 
  874         c = bus_space_read_1(sc->sc_bst, sc->sc_bsh, HILP_DATA);
  875         DELAY(1);
  876 
  877         if (hil_process_poll(sc, s, c)) {
  878                 /* Discard any data not for us */
  879                 if (sc->sc_actdev == dev->sc_code) {
  880                         *stat = s;
  881                         *data = c;
  882                         return 0;
  883                 }
  884         }
  885 
  886         return -1;
  887 }

/* [<][>][^][v][top][bottom][index][help] */