[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     ! 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