[BACK]Return to hil.c CVS log [TXT][DIR] Up to [local] / sys / dev / hil

Annotation of sys/dev/hil/hil.c, Revision 1.1.1.1

1.1       nbrk        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: }

CVSweb