Annotation of 43BSDReno/sys/hpdev/hil.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 University of Utah.
        !             3:  * Copyright (c) 1990 The Regents of the University of California.
        !             4:  * All rights reserved.
        !             5:  *
        !             6:  * This code is derived from software contributed to Berkeley by
        !             7:  * the Systems Programming Group of the University of Utah Computer
        !             8:  * Science Department.
        !             9:  *
        !            10:  * Redistribution is only permitted until one year after the first shipment
        !            11:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
        !            12:  * binary forms are permitted provided that: (1) source distributions retain
        !            13:  * this entire copyright notice and comment, and (2) distributions including
        !            14:  * binaries display the following acknowledgement:  This product includes
        !            15:  * software developed by the University of California, Berkeley and its
        !            16:  * contributors'' in the documentation or other materials provided with the
        !            17:  * distribution and in all advertising materials mentioning features or use
        !            18:  * of this software.  Neither the name of the University nor the names of
        !            19:  * its contributors may be used to endorse or promote products derived from
        !            20:  * this software without specific prior written permission.
        !            21:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
        !            22:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
        !            23:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
        !            24:  *
        !            25:  * from: Utah $Hdr: hil.c 1.33 89/12/22$
        !            26:  *
        !            27:  *     @(#)hil.c       7.4 (Berkeley) 6/22/90
        !            28:  */
        !            29: 
        !            30: #include "param.h"
        !            31: #include "conf.h"
        !            32: #include "user.h"
        !            33: #include "proc.h"
        !            34: #include "ioctl.h"
        !            35: #include "file.h"
        !            36: #include "tty.h"
        !            37: #include "systm.h"
        !            38: #include "uio.h"
        !            39: #include "kernel.h"
        !            40: #include "mapmem.h"
        !            41: 
        !            42: #include "hilreg.h"
        !            43: #include "hilioctl.h"
        !            44: #include "hilvar.h"
        !            45: #include "kbdmap.h"
        !            46: 
        !            47: #include "machine/cpu.h"
        !            48: 
        !            49: struct hilloop hil0;
        !            50: struct _hilbell default_bell = { BELLDUR, BELLFREQ };
        !            51: 
        !            52: #ifdef MAPMEM
        !            53: int    hilqfork(), hilqvfork(), hilqexit();
        !            54: struct mapmemops hilqops = { hilqfork, hilqvfork, hilqexit, hilqexit };
        !            55: #endif
        !            56: 
        !            57: #ifdef DEBUG
        !            58: int    hildebug = 0;
        !            59: #define HDB_FOLLOW     0x01
        !            60: #define HDB_MMAP       0x02
        !            61: #define HDB_MASK       0x04
        !            62: #define HDB_CONFIG     0x08
        !            63: #define HDB_KEYBOARD   0x10
        !            64: #define HDB_IDMODULE   0x20
        !            65: #define HDB_EVENTS     0x80
        !            66: #endif
        !            67: 
        !            68: /* symbolic sleep message strings */
        !            69: char hilin[] = "hilin";
        !            70: 
        !            71: hilinit()
        !            72: {
        !            73:        register struct hilloop *hilp = &hil0;  /* XXX */
        !            74:        register int i;
        !            75: 
        !            76:        /*
        !            77:         * Initialize loop information
        !            78:         */
        !            79:        hilp->hl_addr = HILADDR;
        !            80:        hilp->hl_cmdending = FALSE;
        !            81:        hilp->hl_actdev = hilp->hl_cmddev = 0;
        !            82:        hilp->hl_cmddone = FALSE;
        !            83:        hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !            84:        hilp->hl_pollbp = hilp->hl_pollbuf;
        !            85:        hilp->hl_kbddev = 0;
        !            86:        hilp->hl_kbdlang = KBD_DEFAULT;
        !            87:        hilp->hl_kbdflags = 0;
        !            88:        /*
        !            89:         * Clear all queues and device associations with queues
        !            90:         */
        !            91:        for (i = 0; i < NHILQ; i++) {
        !            92:                hilp->hl_queue[i].hq_eventqueue = NULL;
        !            93:                hilp->hl_queue[i].hq_procp = NULL;
        !            94:                hilp->hl_queue[i].hq_devmask = 0;
        !            95:        }
        !            96:        for (i = 0; i < NHILD; i++)
        !            97:                hilp->hl_device[i].hd_qmask = 0;
        !            98:        hilp->hl_device[HILLOOPDEV].hd_flags = (HIL_ALIVE|HIL_PSEUDO);
        !            99:        /*
        !           100:         * Reset the loop hardware, and collect keyboard/id info
        !           101:         */
        !           102:        hilreset(hilp);
        !           103:        hilinfo(hilp);
        !           104:        kbdenable();
        !           105: }
        !           106: 
        !           107: hilopen(dev, flags)
        !           108:        dev_t dev;
        !           109: {
        !           110:        struct proc *p = u.u_procp;             /* XXX */
        !           111:        register struct hilloop *hilp = &hil0;  /* XXX */
        !           112:        register struct hilloopdev *dptr;
        !           113:        u_char device = HILUNIT(dev);
        !           114: 
        !           115: #ifdef DEBUG
        !           116:        if (hildebug & HDB_FOLLOW)
        !           117:                printf("hilopen(%d): device %x\n", p->p_pid, device);
        !           118: #endif
        !           119:        
        !           120:        if ((hilp->hl_device[HILLOOPDEV].hd_flags & HIL_ALIVE) == 0)
        !           121:                return(ENXIO);
        !           122: 
        !           123:        dptr = &hilp->hl_device[device];
        !           124:        if ((dptr->hd_flags & HIL_ALIVE) == 0)
        !           125:                return(ENODEV);
        !           126: 
        !           127:        /*
        !           128:         * Pseudo-devices cannot be read, nothing more to do.
        !           129:         */
        !           130:        if (dptr->hd_flags & HIL_PSEUDO)
        !           131:                return(0);
        !           132: 
        !           133:        /*
        !           134:         * Open semantics:
        !           135:         * 1.   Open devices have only one of HIL_READIN/HIL_QUEUEIN.
        !           136:         * 2.   HPUX processes always get read syscall interface and
        !           137:         *      must have exclusive use of the device.
        !           138:         * 3.   BSD processes default to shared queue interface.
        !           139:         *      Multiple processes can open the device.
        !           140:         */
        !           141:        if (p->p_flag & SHPUX) {
        !           142:                if (dptr->hd_flags & (HIL_READIN|HIL_QUEUEIN))
        !           143:                        return(EBUSY);
        !           144:                dptr->hd_flags |= HIL_READIN;
        !           145:        } else {
        !           146:                if (dptr->hd_flags & HIL_READIN)
        !           147:                        return(EBUSY);
        !           148:                dptr->hd_flags |= HIL_QUEUEIN;
        !           149:        }
        !           150:        if (flags & FNDELAY)
        !           151:                dptr->hd_flags |= HIL_NOBLOCK;
        !           152:        /*
        !           153:         * It is safe to flush the read buffer as we are guarenteed
        !           154:         * that no one else is using it.
        !           155:         */
        !           156:        ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc);
        !           157: 
        !           158:        send_hil_cmd(hilp->hl_addr, HIL_INTON, NULL, 0, NULL);
        !           159:        /*
        !           160:         * Opened the keyboard, put in raw mode.
        !           161:         */
        !           162:        (void) splhil();
        !           163:        if (device == hilp->hl_kbddev) {
        !           164:                u_char mask = 0;
        !           165:                send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL);
        !           166:                hilp->hl_kbdflags |= KBD_RAW;
        !           167: #ifdef DEBUG
        !           168:                if (hildebug & HDB_KEYBOARD)
        !           169:                        printf("hilopen: keyboard %d raw\n", hilp->hl_kbddev);
        !           170: #endif
        !           171:        }
        !           172:        (void) spl0();
        !           173:        return (0);
        !           174: }
        !           175: 
        !           176: /* ARGSUSED */
        !           177: hilclose(dev, flags)
        !           178:        dev_t dev;
        !           179: {
        !           180:        struct proc *p = u.u_procp;             /* XXX */
        !           181:        register struct hilloop *hilp = &hil0;  /* XXX */
        !           182:        register struct hilloopdev *dptr;
        !           183:        register int i;
        !           184:        u_char device = HILUNIT(dev);
        !           185:        char mask, lpctrl;
        !           186: 
        !           187: #ifdef DEBUG
        !           188:        if (hildebug & HDB_FOLLOW)
        !           189:                printf("hilclose(%d): device %x\n", p->p_pid, device);
        !           190: #endif
        !           191: 
        !           192:        dptr = &hilp->hl_device[device];
        !           193:        if (device && (dptr->hd_flags & HIL_PSEUDO))
        !           194:                return (0);
        !           195: 
        !           196:        if ((p->p_flag & SHPUX) == 0) {
        !           197:                /*
        !           198:                 * If this is the loop device,
        !           199:                 * free up all queues belonging to this process.
        !           200:                 */
        !           201:                if (device == 0) {
        !           202:                        for (i = 0; i < NHILQ; i++)
        !           203:                                if (hilp->hl_queue[i].hq_procp == p)
        !           204:                                        (void) hilqfree(i);
        !           205:                } else {
        !           206:                        mask = ~hildevmask(device);
        !           207:                        (void) splhil();
        !           208:                        for (i = 0; i < NHILQ; i++)
        !           209:                                if (hilp->hl_queue[i].hq_procp == p) {
        !           210:                                        dptr->hd_qmask &= ~hilqmask(i);
        !           211:                                        hilp->hl_queue[i].hq_devmask &= mask;
        !           212:                                }
        !           213:                        (void) spl0();
        !           214:                }
        !           215:        }
        !           216:        /*
        !           217:         * Always flush the read buffer
        !           218:         */
        !           219:        dptr->hd_flags &= ~(HIL_QUEUEIN|HIL_READIN|HIL_NOBLOCK);
        !           220:        ndflush(&dptr->hd_queue, dptr->hd_queue.c_cc);
        !           221:        /*
        !           222:         * Set keyboard back to cooked mode when closed.
        !           223:         */
        !           224:        (void) splhil();
        !           225:        if (device && device == hilp->hl_kbddev) {
        !           226:                mask = 1 << (hilp->hl_kbddev - 1);
        !           227:                send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &mask, 1, NULL);
        !           228:                hilp->hl_kbdflags &= ~(KBD_RAW|KBD_AR1|KBD_AR2);
        !           229:                /*
        !           230:                 * XXX: We have had trouble with keyboards remaining raw
        !           231:                 * after close due to the LPC_KBDCOOK bit getting cleared
        !           232:                 * somewhere along the line.  Hence we check and reset
        !           233:                 * LPCTRL if necessary.
        !           234:                 */
        !           235:                send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &lpctrl);
        !           236:                if ((lpctrl & LPC_KBDCOOK) == 0) {
        !           237:                        printf("hilclose: bad LPCTRL %x, reset to %x\n",
        !           238:                               lpctrl, lpctrl|LPC_KBDCOOK);
        !           239:                        lpctrl |= LPC_KBDCOOK;
        !           240:                        send_hil_cmd(hilp->hl_addr, HIL_WRITELPCTRL,
        !           241:                                        &lpctrl, 1, NULL);
        !           242:                }
        !           243: #ifdef DEBUG
        !           244:                if (hildebug & HDB_KEYBOARD)
        !           245:                        printf("hilclose: keyboard %d cooked\n",
        !           246:                               hilp->hl_kbddev);
        !           247: #endif
        !           248:                kbdenable();
        !           249:        }
        !           250:        (void) spl0();
        !           251:        return (0);
        !           252: }
        !           253: 
        !           254: /*
        !           255:  * Read interface to HIL device.
        !           256:  */
        !           257: hilread(dev, uio)
        !           258:        dev_t dev;
        !           259:        register struct uio *uio;
        !           260: {
        !           261:        struct hilloop *hilp = &hil0;           /* XXX */
        !           262:        register struct hilloopdev *dptr;
        !           263:        register int cc;
        !           264:        u_char device = HILUNIT(dev);
        !           265:        char buf[HILBUFSIZE];
        !           266:        int error;
        !           267: 
        !           268: #if 0
        !           269:        /*
        !           270:         * XXX: Don't do this since HP-UX doesn't.
        !           271:         *
        !           272:         * Check device number.
        !           273:         * This check is necessary since loop can reconfigure.
        !           274:         */
        !           275:        if (device > hilp->hl_maxdev)
        !           276:                return(ENODEV);
        !           277: #endif
        !           278: 
        !           279:        dptr = &hilp->hl_device[device];
        !           280:        if ((dptr->hd_flags & HIL_READIN) == 0)
        !           281:                return(ENODEV);
        !           282: 
        !           283:        (void) splhil();
        !           284:        while (dptr->hd_queue.c_cc == 0) {
        !           285:                if (dptr->hd_flags & HIL_NOBLOCK) {
        !           286:                        spl0();
        !           287:                        return(EWOULDBLOCK);
        !           288:                }
        !           289:                dptr->hd_flags |= HIL_ASLEEP;
        !           290:                if (error = tsleep((caddr_t)dptr, TTIPRI | PCATCH, hilin, 0)) {
        !           291:                        (void) spl0();
        !           292:                        return (error);
        !           293:                }
        !           294:        }
        !           295:        (void) spl0();
        !           296: 
        !           297:        error = 0;
        !           298:        while (uio->uio_resid > 0 && error == 0) {
        !           299:                cc = hilq_to_b(&dptr->hd_queue, buf,
        !           300:                               MIN(uio->uio_resid, HILBUFSIZE));
        !           301:                if (cc <= 0)
        !           302:                        break;
        !           303:                error = uiomove(buf, cc, uio);
        !           304:        }
        !           305:        return(error);
        !           306: }
        !           307: 
        !           308: hilioctl(dev, cmd, data, flag)
        !           309:        dev_t dev;
        !           310:        caddr_t data;
        !           311: {
        !           312:        struct proc *p = u.u_procp;             /* XXX */
        !           313:        register struct hilloop *hilp = &hil0;  /* XXX */
        !           314:        char device = HILUNIT(dev);
        !           315:        struct hilloopdev *dptr;
        !           316:        register int i;
        !           317:        u_char hold;
        !           318:        int error;
        !           319: 
        !           320: #ifdef DEBUG
        !           321:        if (hildebug & HDB_FOLLOW)
        !           322:                printf("hilioctl(%d): dev %x cmd %x\n",
        !           323:                       p->p_pid, device, cmd);
        !           324: #endif
        !           325: 
        !           326:        dptr = &hilp->hl_device[device];
        !           327:        if ((dptr->hd_flags & HIL_ALIVE) == 0)
        !           328:                return (ENODEV);
        !           329: 
        !           330:        /*
        !           331:         * Don't allow hardware ioctls on virtual devices.
        !           332:         * Note that though these are the BSD names, they have the same
        !           333:         * values as the HP-UX equivalents so we catch them as well.
        !           334:         */
        !           335:        if (dptr->hd_flags & HIL_PSEUDO) {
        !           336:                switch (cmd) {
        !           337:                case HILIOCSC:
        !           338:                case HILIOCID:
        !           339:                case HILIOCRN:
        !           340:                case HILIOCRS:
        !           341:                case HILIOCED:
        !           342:                        return(ENODEV);
        !           343: 
        !           344:                /*
        !           345:                 * XXX: should also return ENODEV but HP-UX compat
        !           346:                 * breaks if we do.  They work ok right now because
        !           347:                 * we only recognize one keyboard on the loop.  This
        !           348:                 * will have to change if we remove that restriction.
        !           349:                 */
        !           350:                case HILIOCAROFF:
        !           351:                case HILIOCAR1:
        !           352:                case HILIOCAR2:
        !           353:                        break;
        !           354: 
        !           355:                default:
        !           356:                        break;
        !           357:                }
        !           358:        }
        !           359: 
        !           360: #ifdef HPUXCOMPAT
        !           361:        if (p->p_flag & SHPUX)
        !           362:                return(hpuxhilioctl(dev, cmd, data, flag));
        !           363: #endif
        !           364: 
        !           365:        hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !           366:        bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE);
        !           367:        hilp->hl_cmddev = device;
        !           368:        error = 0;
        !           369:        switch (cmd) {
        !           370: 
        !           371:        case HILIOCSBP:
        !           372:                /* Send four data bytes to the tone gererator. */
        !           373:                send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL);
        !           374:                /* Send the trigger beeper command to the 8042. */
        !           375:                send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
        !           376:                break;
        !           377: 
        !           378:        case HILIOCRRT:
        !           379:                /* Transfer the real time to the 8042 data buffer */
        !           380:                send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
        !           381:                /* Read each byte of the real time */
        !           382:                for (i = 0; i < 5; i++) {
        !           383:                        send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL,
        !           384:                                        0, &hold);
        !           385:                        data[4-i] = hold;
        !           386:                }
        !           387:                break;
        !           388:                
        !           389:        case HILIOCRT:
        !           390:                for (i = 0; i < 4; i++) {
        !           391:                        send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i,
        !           392:                                        NULL, 0, &hold);
        !           393:                        data[i] = hold;
        !           394:                }
        !           395:                break;
        !           396: 
        !           397:        case HILIOCID:
        !           398:        case HILIOCSC:
        !           399:        case HILIOCRN:
        !           400:        case HILIOCRS:
        !           401:        case HILIOCED:
        !           402:                send_hildev_cmd(hilp, device, (cmd & 0xFF));
        !           403:                bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf);
        !           404:                break;
        !           405: 
        !           406:         case HILIOCAROFF:
        !           407:         case HILIOCAR1:
        !           408:         case HILIOCAR2:
        !           409:                if (hilp->hl_kbddev) {
        !           410:                        hilp->hl_cmddev = hilp->hl_kbddev;
        !           411:                        send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF));
        !           412:                        hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2);
        !           413:                        if (cmd == HILIOCAR1)
        !           414:                                hilp->hl_kbdflags |= KBD_AR1;
        !           415:                        else if (cmd == HILIOCAR2)
        !           416:                                hilp->hl_kbdflags |= KBD_AR2;
        !           417:                }
        !           418:                break;
        !           419: 
        !           420:        case HILIOCBEEP:
        !           421:                hilbeep(hilp, (struct _hilbell *)data);
        !           422:                break;
        !           423: 
        !           424:        case FIONBIO:
        !           425:                dptr = &hilp->hl_device[device];
        !           426:                if (*(int *)data)
        !           427:                        dptr->hd_flags |= HIL_NOBLOCK;
        !           428:                else
        !           429:                        dptr->hd_flags &= ~HIL_NOBLOCK;
        !           430:                break;
        !           431: 
        !           432:        /*
        !           433:         * FIOASYNC must be present for FIONBIO above to work!
        !           434:         * (See fcntl in kern_descrip.c).
        !           435:         */
        !           436:        case FIOASYNC:
        !           437:                break;
        !           438: 
        !           439:         case HILIOCALLOCQ:
        !           440:                error = hilqalloc((struct hilqinfo *)data);
        !           441:                break;
        !           442: 
        !           443:         case HILIOCFREEQ:
        !           444:                error = hilqfree(((struct hilqinfo *)data)->qid);
        !           445:                break;
        !           446: 
        !           447:         case HILIOCMAPQ:
        !           448:                error = hilqmap(*(int *)data, device);
        !           449:                break;
        !           450: 
        !           451:         case HILIOCUNMAPQ:
        !           452:                error = hilqunmap(*(int *)data, device);
        !           453:                break;
        !           454: 
        !           455:        case HILIOCHPUX:
        !           456:                dptr = &hilp->hl_device[device];
        !           457:                dptr->hd_flags |= HIL_READIN;
        !           458:                dptr->hd_flags &= ~HIL_QUEUEIN;
        !           459:                break;
        !           460: 
        !           461:         case HILIOCRESET:
        !           462:                hilreset(hilp);
        !           463:                break;
        !           464:                
        !           465: #ifdef DEBUG
        !           466:         case HILIOCTEST:
        !           467:                hildebug = *(int *) data;
        !           468:                break;
        !           469: #endif
        !           470: 
        !           471:         default:
        !           472:                error = EINVAL;
        !           473:                break;
        !           474: 
        !           475:        }
        !           476:        hilp->hl_cmddev = 0;
        !           477:        return(error);
        !           478: }
        !           479: 
        !           480: #ifdef HPUXCOMPAT
        !           481: /* ARGSUSED */
        !           482: hpuxhilioctl(dev, cmd, data, flag)
        !           483:        dev_t dev;
        !           484:        caddr_t data;
        !           485: {
        !           486:        register struct hilloop *hilp = &hil0;  /* XXX */
        !           487:        char device = HILUNIT(dev);
        !           488:        struct hilloopdev *dptr;
        !           489:        register int i;
        !           490:        u_char hold;
        !           491: 
        !           492:        hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !           493:        bzero((caddr_t)hilp->hl_cmdbuf, HILBUFSIZE);
        !           494:        hilp->hl_cmddev = device;
        !           495:        switch (cmd) {
        !           496: 
        !           497:        case HILSC:
        !           498:        case HILID:
        !           499:        case HILRN:
        !           500:        case HILRS:
        !           501:        case HILED:
        !           502:        case HILP1:
        !           503:        case HILP2:
        !           504:        case HILP3:
        !           505:        case HILP4:
        !           506:        case HILP5:
        !           507:        case HILP6:
        !           508:        case HILP7:
        !           509:        case HILP:
        !           510:        case HILA1:
        !           511:        case HILA2:
        !           512:        case HILA3:
        !           513:        case HILA4:
        !           514:        case HILA5:
        !           515:        case HILA6:
        !           516:        case HILA7:
        !           517:        case HILA:
        !           518:                send_hildev_cmd(hilp, device, (cmd & 0xFF));
        !           519:                bcopy(hilp->hl_cmdbuf, data, hilp->hl_cmdbp-hilp->hl_cmdbuf);
        !           520:                break;
        !           521: 
        !           522:         case HILDKR:
        !           523:         case HILER1:
        !           524:         case HILER2:
        !           525:                if (hilp->hl_kbddev) {
        !           526:                        hilp->hl_cmddev = hilp->hl_kbddev;
        !           527:                        send_hildev_cmd(hilp, hilp->hl_kbddev, (cmd & 0xFF));
        !           528:                        hilp->hl_kbdflags &= ~(KBD_AR1|KBD_AR2);
        !           529:                        if (cmd == HILIOCAR1)
        !           530:                                hilp->hl_kbdflags |= KBD_AR1;
        !           531:                        else if (cmd == HILIOCAR2)
        !           532:                                hilp->hl_kbdflags |= KBD_AR2;
        !           533:                }
        !           534:                break;
        !           535: 
        !           536:        case EFTSBP:
        !           537:                /* Send four data bytes to the tone gererator. */
        !           538:                send_hil_cmd(hilp->hl_addr, HIL_STARTCMD, data, 4, NULL);
        !           539:                /* Send the trigger beeper command to the 8042. */
        !           540:                send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
        !           541:                break;
        !           542: 
        !           543:        case EFTRRT:
        !           544:                /* Transfer the real time to the 8042 data buffer */
        !           545:                send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, NULL);
        !           546:                /* Read each byte of the real time */
        !           547:                for (i = 0; i < 5; i++) {
        !           548:                        send_hil_cmd(hilp->hl_addr, HIL_READTIME + i, NULL,
        !           549:                                        0, &hold);
        !           550:                        data[4-i] = hold;
        !           551:                }
        !           552:                break;
        !           553:                
        !           554:        case EFTRT:
        !           555:                for (i = 0; i < 4; i++) {
        !           556:                        send_hil_cmd(hilp->hl_addr, (cmd & 0xFF) + i,
        !           557:                                        NULL, 0, &hold);
        !           558:                        data[i] = hold;
        !           559:                }
        !           560:                break;
        !           561: 
        !           562:         case EFTRLC:
        !           563:         case EFTRCC:
        !           564:                send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), NULL, 0, &hold);
        !           565:                *data = hold;
        !           566:                break;
        !           567:                
        !           568:         case EFTSRPG:
        !           569:         case EFTSRD:
        !           570:         case EFTSRR:
        !           571:                send_hil_cmd(hilp->hl_addr, (cmd & 0xFF), data, 1, NULL);
        !           572:                break;
        !           573:                
        !           574:        case EFTSBI:
        !           575:                hilbeep(hilp, (struct _hilbell *)data);
        !           576:                break;
        !           577: 
        !           578:        case FIONBIO:
        !           579:                dptr = &hilp->hl_device[device];
        !           580:                if (*(int *)data)
        !           581:                        dptr->hd_flags |= HIL_NOBLOCK;
        !           582:                else
        !           583:                        dptr->hd_flags &= ~HIL_NOBLOCK;
        !           584:                break;
        !           585: 
        !           586:        case FIOASYNC:
        !           587:                break;
        !           588: 
        !           589:         default:
        !           590:                hilp->hl_cmddev = 0;
        !           591:                return(EINVAL);
        !           592:        }
        !           593:        hilp->hl_cmddev = 0;
        !           594:        return(0);
        !           595: }
        !           596: #endif
        !           597: 
        !           598: /*
        !           599:  * XXX: the mmap inteface for HIL devices should be rethought.
        !           600:  * We used it only briefly in conjuntion with shared queues
        !           601:  * (instead of HILIOCMAPQ ioctl).  Perhaps mmap()ing a device
        !           602:  * should give a single queue per process.
        !           603:  */
        !           604: /* ARGSUSED */
        !           605: hilmap(dev, off, prot)
        !           606:        dev_t dev;
        !           607:        register int off;
        !           608: {
        !           609: #ifdef MMAP
        !           610:        struct proc *p = u.u_procp;             /* XXX */
        !           611:        register struct hilloop *hilp = &hil0;  /* XXX */
        !           612:        register struct hiliqueue *qp;
        !           613:        register int qnum;
        !           614: 
        !           615:        /*
        !           616:         * Only allow mmap() on loop device
        !           617:         */
        !           618:        if (HILUNIT(dev) != 0 || off >= NHILQ*sizeof(HILQ))
        !           619:                return(-1);
        !           620:        /*
        !           621:         * Determine which queue we want based on the offset.
        !           622:         * Queue must belong to calling process.
        !           623:         */
        !           624:        qp = &hilp->hl_queue[off / sizeof(HILQ)];
        !           625:        if (qp->hq_procp != p)
        !           626:                return(-1);
        !           627: 
        !           628:        off %= sizeof(HILQ);
        !           629:        return(kvtop((u_int)qp->hq_eventqueue + off) >> PGSHIFT);
        !           630: #endif
        !           631: }
        !           632: 
        !           633: /*ARGSUSED*/
        !           634: hilselect(dev, rw)
        !           635:        dev_t dev;
        !           636: {
        !           637:        struct proc *p = u.u_procp;             /* XXX */
        !           638:        register struct hilloop *hilp = &hil0;  /* XXX */
        !           639:        register struct hilloopdev *dptr;
        !           640:        register struct hiliqueue *qp;
        !           641:        register int mask;
        !           642:        int s, device;
        !           643:        
        !           644:        if (rw == FWRITE)
        !           645:                return (1);
        !           646:        device = HILUNIT(dev);
        !           647: 
        !           648:        /*
        !           649:         * Read interface.
        !           650:         * Return 1 if there is something in the queue, 0 ow.
        !           651:         */
        !           652:        dptr = &hilp->hl_device[device];
        !           653:        if (dptr->hd_flags & HIL_READIN) {
        !           654:                s = splhil();
        !           655:                if (dptr->hd_queue.c_cc) {
        !           656:                        splx(s);
        !           657:                        return (1);
        !           658:                }
        !           659:                if (dptr->hd_selr &&
        !           660:                    dptr->hd_selr->p_wchan == (caddr_t)&selwait)
        !           661:                        dptr->hd_flags |= HIL_SELCOLL;
        !           662:                else
        !           663:                        dptr->hd_selr = p;
        !           664:                splx(s);
        !           665:                return (0);
        !           666:        }
        !           667: 
        !           668:        /*
        !           669:         * Make sure device is alive and real (or the loop device).
        !           670:         * Note that we do not do this for the read interface.
        !           671:         * This is primarily to be consistant with HP-UX.
        !           672:         */
        !           673:        if (device && (dptr->hd_flags & (HIL_ALIVE|HIL_PSEUDO)) != HIL_ALIVE)
        !           674:                return (1);
        !           675: 
        !           676:        /*
        !           677:         * Select on loop device is special.
        !           678:         * Check to see if there are any data for any loop device
        !           679:         * provided it is associated with a queue belonging to this user.
        !           680:         */
        !           681:        if (device == 0)
        !           682:                mask = -1;
        !           683:        else
        !           684:                mask = hildevmask(device);
        !           685:        /*
        !           686:         * Must check everybody with interrupts blocked to prevent races.
        !           687:         */
        !           688:        s = splhil();
        !           689:        for (qp = hilp->hl_queue; qp < &hilp->hl_queue[NHILQ]; qp++)
        !           690:                if (qp->hq_procp == p && (mask & qp->hq_devmask) &&
        !           691:                    qp->hq_eventqueue->hil_evqueue.head !=
        !           692:                    qp->hq_eventqueue->hil_evqueue.tail) {
        !           693:                        splx(s);
        !           694:                        return (1);
        !           695:                }
        !           696: 
        !           697:        if (dptr->hd_selr && dptr->hd_selr->p_wchan == (caddr_t)&selwait)
        !           698:                dptr->hd_flags |= HIL_SELCOLL;
        !           699:        else
        !           700:                dptr->hd_selr = p;
        !           701:        splx(s);
        !           702:        return (0);
        !           703: }
        !           704: 
        !           705: hilint()
        !           706: {
        !           707:        struct hilloop *hilp = &hil0;           /* XXX */
        !           708:        register struct hil_dev *hildevice = hilp->hl_addr;
        !           709:        u_char c, stat;
        !           710: 
        !           711:        stat = hildevice->hil_stat;
        !           712:        c = hildevice->hil_data;                /* clears interrupt */
        !           713:        hil_process_int(stat, c);
        !           714: }
        !           715: 
        !           716: #include "ite.h"
        !           717: 
        !           718: hil_process_int(stat, c)
        !           719:        register u_char stat, c;
        !           720: {
        !           721:        register struct hilloop *hilp;
        !           722: 
        !           723: #ifdef DEBUG
        !           724:        if (hildebug & HDB_EVENTS)
        !           725:                printf("hilint: %x %x\n", stat, c);
        !           726: #endif
        !           727: 
        !           728:        /* the shift enables the compiler to generate a jump table */
        !           729:        switch ((stat>>HIL_SSHIFT) & HIL_SMASK) {
        !           730: 
        !           731: #if NITE > 0
        !           732:        case HIL_KEY:
        !           733:        case HIL_SHIFT:
        !           734:        case HIL_CTRL:
        !           735:        case HIL_CTRLSHIFT:
        !           736:                itefilter(stat, c);
        !           737:                return;
        !           738: #endif
        !           739:                
        !           740:        case HIL_STATUS:                        /* The status info. */
        !           741:                hilp = &hil0;                   /* XXX */
        !           742:                if (c & HIL_ERROR) {
        !           743:                        hilp->hl_cmddone = TRUE;
        !           744:                        if (c == HIL_RECONFIG)
        !           745:                                hilconfig(hilp);
        !           746:                        break;
        !           747:                }
        !           748:                if (c & HIL_COMMAND) {
        !           749:                        if (c & HIL_POLLDATA)   /* End of data */
        !           750:                                hilevent(hilp);
        !           751:                        else                    /* End of command */
        !           752:                                hilp->hl_cmdending = TRUE;
        !           753:                        hilp->hl_actdev = 0;
        !           754:                } else {
        !           755:                        if (c & HIL_POLLDATA) { /* Start of polled data */
        !           756:                                if (hilp->hl_actdev != 0)
        !           757:                                        hilevent(hilp);
        !           758:                                hilp->hl_actdev = (c & HIL_DEVMASK);
        !           759:                                hilp->hl_pollbp = hilp->hl_pollbuf;
        !           760:                        } else {                /* Start of command */
        !           761:                                if (hilp->hl_cmddev == (c & HIL_DEVMASK)) {
        !           762:                                        hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !           763:                                        hilp->hl_actdev = 0;
        !           764:                                }
        !           765:                        }
        !           766:                }
        !           767:                return;
        !           768: 
        !           769:        case HIL_DATA:
        !           770:                hilp = &hil0;                   /* XXX */
        !           771:                if (hilp->hl_actdev != 0)       /* Collecting poll data */
        !           772:                        *hilp->hl_pollbp++ = c;
        !           773:                else if (hilp->hl_cmddev != 0)  /* Collecting cmd data */
        !           774:                        if (hilp->hl_cmdending) {
        !           775:                                hilp->hl_cmddone = TRUE;
        !           776:                                hilp->hl_cmdending = FALSE;
        !           777:                        } else  
        !           778:                                *hilp->hl_cmdbp++ = c;
        !           779:                return;
        !           780:                
        !           781:        case 0:         /* force full jump table */
        !           782:        default:
        !           783:                return;
        !           784:        }
        !           785: }
        !           786: 
        !           787: #if defined(DEBUG) && !defined(PANICBUTTON)
        !           788: #define PANICBUTTON
        !           789: #endif
        !           790: 
        !           791: /*
        !           792:  * Optimized macro to compute:
        !           793:  *     eq->head == (eq->tail + 1) % eq->size
        !           794:  * i.e. has tail caught up with head.  We do this because 32 bit long
        !           795:  * remaidering is expensive (a function call with our compiler).
        !           796:  */
        !           797: #define HQFULL(eq)     (((eq)->head?(eq)->head:(eq)->size) == (eq)->tail+1)
        !           798: #define HQVALID(eq) \
        !           799:        ((eq)->size == HEVQSIZE && (eq)->tail >= 0 && (eq)->tail < HEVQSIZE)
        !           800: 
        !           801: hilevent(hilp)
        !           802:        struct hilloop *hilp;
        !           803: {
        !           804:        register struct hilloopdev *dptr = &hilp->hl_device[hilp->hl_actdev];
        !           805:        register int len, mask, qnum;
        !           806:        register u_char *cp, *pp;
        !           807:        register HILQ *hq;
        !           808:        struct timeval ourtime;
        !           809:        hil_packet *proto;
        !           810:        int s, len0;
        !           811:        long tenths;
        !           812: 
        !           813: #ifdef PANICBUTTON
        !           814:        static int first;
        !           815:        extern int panicbutton;
        !           816: 
        !           817:        cp = hilp->hl_pollbuf;
        !           818:        if (panicbutton && (*cp & HIL_KBDDATA)) {
        !           819:                if (*++cp == 0x4E)
        !           820:                        first = 1;
        !           821:                else if (first && *cp == 0x46 && !panicstr)
        !           822:                        panic("are we having fun yet?");
        !           823:                else
        !           824:                        first = 0;
        !           825:        }
        !           826: #endif
        !           827: #ifdef DEBUG
        !           828:        if (hildebug & HDB_EVENTS) {
        !           829:                printf("hilevent: dev %d pollbuf: ", hilp->hl_actdev);
        !           830:                printhilpollbuf(hilp);
        !           831:                printf("\n");
        !           832:        }
        !           833: #endif
        !           834: 
        !           835:        /*
        !           836:         * Note that HIL_READIN effectively "shuts off" any queues
        !           837:         * that may have been in use at the time of an HILIOCHPUX call.
        !           838:         */
        !           839:        if (dptr->hd_flags & HIL_READIN) {
        !           840:                hpuxhilevent(hilp, dptr);
        !           841:                return;
        !           842:        }
        !           843: 
        !           844:        /*
        !           845:         * If this device isn't on any queue or there are no data
        !           846:         * in the packet (can this happen?) do nothing.
        !           847:         */
        !           848:        if (dptr->hd_qmask == 0 ||
        !           849:            (len0 = hilp->hl_pollbp - hilp->hl_pollbuf) <= 0)
        !           850:                return;
        !           851: 
        !           852:        /*
        !           853:         * Everybody gets the same time stamp
        !           854:         */
        !           855:        s = splclock();
        !           856:        ourtime = time;
        !           857:        splx(s);
        !           858:        tenths = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000);
        !           859: 
        !           860:        proto = NULL;
        !           861:        mask = dptr->hd_qmask;
        !           862:        for (qnum = 0; mask; qnum++) {
        !           863:                if ((mask & hilqmask(qnum)) == 0)
        !           864:                        continue;
        !           865:                mask &= ~hilqmask(qnum);
        !           866:                hq = hilp->hl_queue[qnum].hq_eventqueue;
        !           867:                
        !           868:                /*
        !           869:                 * Ensure that queue fields that we rely on are valid
        !           870:                 * and that there is space in the queue.  If either
        !           871:                 * test fails, we just skip this queue.
        !           872:                 */
        !           873:                if (!HQVALID(&hq->hil_evqueue) || HQFULL(&hq->hil_evqueue))
        !           874:                        continue;
        !           875: 
        !           876:                /*
        !           877:                 * Copy data to queue.
        !           878:                 * If this is the first queue we construct the packet
        !           879:                 * with length, timestamp and poll buffer data.
        !           880:                 * For second and sucessive packets we just duplicate
        !           881:                 * the first packet.
        !           882:                 */
        !           883:                pp = (u_char *) &hq->hil_event[hq->hil_evqueue.tail];
        !           884:                if (proto == NULL) {
        !           885:                        proto = (hil_packet *)pp;
        !           886:                        cp = hilp->hl_pollbuf;
        !           887:                        len = len0;
        !           888:                        *pp++ = len + 6;
        !           889:                        *pp++ = hilp->hl_actdev;
        !           890:                        *(long *)pp = tenths;
        !           891:                        pp += sizeof(long);
        !           892:                        do *pp++ = *cp++; while (--len);
        !           893:                } else
        !           894:                        *(hil_packet *)pp = *proto;
        !           895: 
        !           896:                if (++hq->hil_evqueue.tail == hq->hil_evqueue.size)
        !           897:                        hq->hil_evqueue.tail = 0;
        !           898:        }
        !           899: 
        !           900:        /*
        !           901:         * Wake up anyone selecting on this device or the loop itself
        !           902:         */
        !           903:        if (dptr->hd_selr) {
        !           904:                selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL);
        !           905:                dptr->hd_selr = NULL;
        !           906:                dptr->hd_flags &= ~HIL_SELCOLL;
        !           907:        }
        !           908:        dptr = &hilp->hl_device[HILLOOPDEV];
        !           909:        if (dptr->hd_selr) {
        !           910:                selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL);
        !           911:                dptr->hd_selr = NULL;
        !           912:                dptr->hd_flags &= ~HIL_SELCOLL;
        !           913:        }
        !           914: }
        !           915: 
        !           916: #undef HQFULL
        !           917: 
        !           918: hpuxhilevent(hilp, dptr)
        !           919:        register struct hilloop *hilp;
        !           920:        register struct hilloopdev *dptr;
        !           921: {
        !           922:        register int len;
        !           923:        struct timeval ourtime;
        !           924:        long tstamp;
        !           925:        int s;
        !           926: 
        !           927:        /*
        !           928:         * Everybody gets the same time stamp
        !           929:         */
        !           930:        s = splclock();
        !           931:        ourtime = time;
        !           932:        splx(s);
        !           933:        tstamp = (ourtime.tv_sec * 100) + (ourtime.tv_usec / 10000);
        !           934: 
        !           935:        /*
        !           936:         * Each packet that goes into the buffer must be preceded by the
        !           937:         * number of bytes in the packet, and the timestamp of the packet.
        !           938:         * This adds 5 bytes to the packet size. Make sure there is enough
        !           939:         * room in the buffer for it, and if not, toss the packet.
        !           940:         */
        !           941:        len = hilp->hl_pollbp - hilp->hl_pollbuf;
        !           942:        if (dptr->hd_queue.c_cc <= (HILMAXCLIST - (len+5))) {
        !           943:                putc(len+5, &dptr->hd_queue);
        !           944:                (void) b_to_q((char *)&tstamp, sizeof tstamp, &dptr->hd_queue);
        !           945:                (void) b_to_q((char *)hilp->hl_pollbuf, len, &dptr->hd_queue);
        !           946:        }
        !           947: 
        !           948:        /*
        !           949:         * Wake up any one blocked on a read or select
        !           950:         */
        !           951:        if (dptr->hd_flags & HIL_ASLEEP) {
        !           952:                dptr->hd_flags &= ~HIL_ASLEEP;
        !           953:                wakeup((caddr_t)dptr);
        !           954:        }
        !           955:        if (dptr->hd_selr) {
        !           956:                selwakeup(dptr->hd_selr, dptr->hd_flags & HIL_SELCOLL);
        !           957:                dptr->hd_selr = NULL;
        !           958:                dptr->hd_flags &= ~HIL_SELCOLL;
        !           959:        }
        !           960: }
        !           961: 
        !           962: /*
        !           963:  * Shared queue manipulation routines
        !           964:  */
        !           965: 
        !           966: hilqalloc(qip)
        !           967:        struct hilqinfo *qip;
        !           968: {
        !           969: #ifdef MAPMEM
        !           970:        struct proc *p = u.u_procp;             /* XXX */
        !           971:        register struct hilloop *hilp = &hil0;  /* XXX */
        !           972:        register HILQ *hq;
        !           973:        register int qnum;
        !           974:        struct mapmem *mp;
        !           975:        int error, hilqmapin();
        !           976: 
        !           977: #ifdef DEBUG
        !           978:        if (hildebug & HDB_FOLLOW)
        !           979:                printf("hilqalloc(%d): addr %x\n",
        !           980:                       p->p_pid, qip->addr);
        !           981: #endif
        !           982:        /*
        !           983:         * Find a free queue
        !           984:         */
        !           985:        for (qnum = 0; qnum < NHILQ; qnum++)
        !           986:                if (hilp->hl_queue[qnum].hq_procp == NULL)
        !           987:                        break;
        !           988:        if (qnum == NHILQ)
        !           989:                return(EMFILE);
        !           990: 
        !           991:        /*
        !           992:         * Allocate and clear memory for the queue
        !           993:         */
        !           994:        if (hilp->hl_queue[qnum].hq_eventqueue)
        !           995:                panic("hilqalloc");
        !           996:        hq = (HILQ *) cialloc(sizeof(HILQ));
        !           997:        if (hq == NULL)
        !           998:                return(ENOMEM);
        !           999:        bzero((caddr_t)hq, sizeof(HILQ));
        !          1000:        hilp->hl_queue[qnum].hq_eventqueue = hq;
        !          1001:        hq->hil_evqueue.size = HEVQSIZE;
        !          1002: 
        !          1003:        /*
        !          1004:         * Map queue into user address space as instructed
        !          1005:         */
        !          1006:        error = mmalloc(p, qnum, &qip->addr, sizeof(HILQ), MM_RW|MM_CI,
        !          1007:                        &hilqops, &mp);
        !          1008:        if (error) {
        !          1009:                cifree((caddr_t)hq, sizeof(HILQ));
        !          1010:                hilp->hl_queue[qnum].hq_eventqueue = NULL;
        !          1011:                return(error);
        !          1012:        }
        !          1013:        qip->qid = qnum;
        !          1014:        if (error = mmmapin(p, mp, hilqmapin)) {
        !          1015:                (void) mmfree(p, mp);
        !          1016:                cifree((caddr_t)hq, sizeof(HILQ));
        !          1017:                hilp->hl_queue[qnum].hq_eventqueue = NULL;
        !          1018:                return(error);
        !          1019:        }
        !          1020:        hilp->hl_queue[qnum].hq_procp = p;
        !          1021:        hilp->hl_queue[qnum].hq_devmask = 0;
        !          1022:        return(0);
        !          1023: #else
        !          1024:        return(EINVAL);
        !          1025: #endif
        !          1026: }
        !          1027: 
        !          1028: hilqfree(qnum)
        !          1029:        register int qnum;
        !          1030: {
        !          1031: #ifdef MAPMEM
        !          1032:        struct proc *p = u.u_procp;             /* XXX */
        !          1033:        register struct hilloop *hilp = &hil0;  /* XXX */
        !          1034:        register struct mapmem *mp;
        !          1035: 
        !          1036: #ifdef DEBUG
        !          1037:        if (hildebug & HDB_FOLLOW)
        !          1038:                printf("hilqfree(%d): qnum %d\n",
        !          1039:                       p->p_pid, qnum);
        !          1040: #endif
        !          1041:        if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p)
        !          1042:                return(EINVAL);
        !          1043:        for (mp = u.u_mmap; mp; mp = mp->mm_next)
        !          1044:                if (qnum == mp->mm_id && mp->mm_ops == &hilqops) {
        !          1045:                        (void) hilqexit(mp);
        !          1046:                        return(0);
        !          1047:                }
        !          1048:        panic("hilqfree");
        !          1049:        /* NOTREACHED */
        !          1050: #else
        !          1051:        return(EINVAL);
        !          1052: #endif
        !          1053: }
        !          1054: 
        !          1055: hilqmap(qnum, device)
        !          1056:        register int qnum, device;
        !          1057: {
        !          1058:        struct proc *p = u.u_procp;             /* XXX */
        !          1059:        register struct hilloop *hilp = &hil0;  /* XXX */
        !          1060:        register struct hilloopdev *dptr = &hilp->hl_device[device];
        !          1061:        int s;
        !          1062: 
        !          1063: #ifdef DEBUG
        !          1064:        if (hildebug & HDB_FOLLOW)
        !          1065:                printf("hilqmap(%d): qnum %d device %x\n",
        !          1066:                       p->p_pid, qnum, device);
        !          1067: #endif
        !          1068:        if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p)
        !          1069:                return(EINVAL);
        !          1070:        if ((dptr->hd_flags & HIL_QUEUEIN) == 0)
        !          1071:                return(EINVAL);
        !          1072:        if (dptr->hd_qmask && u.u_uid && u.u_uid != dptr->hd_uid)
        !          1073:                return(EPERM);
        !          1074: 
        !          1075:        hilp->hl_queue[qnum].hq_devmask |= hildevmask(device);
        !          1076:        if (dptr->hd_qmask == 0)
        !          1077:                dptr->hd_uid = u.u_uid;
        !          1078:        s = splhil();
        !          1079:        dptr->hd_qmask |= hilqmask(qnum);
        !          1080:        splx(s);
        !          1081: #ifdef DEBUG
        !          1082:        if (hildebug & HDB_MASK)
        !          1083:                printf("hilqmap(%d): devmask %x qmask %x\n",
        !          1084:                       p->p_pid, hilp->hl_queue[qnum].hq_devmask,
        !          1085:                       dptr->hd_qmask);
        !          1086: #endif
        !          1087:        return(0);
        !          1088: }
        !          1089: 
        !          1090: hilqunmap(qnum, device)
        !          1091:        register int qnum, device;
        !          1092: {
        !          1093:        struct proc *p = u.u_procp;             /* XXX */
        !          1094:        register struct hilloop *hilp = &hil0;  /* XXX */
        !          1095:        int s;
        !          1096: 
        !          1097: #ifdef DEBUG
        !          1098:        if (hildebug & HDB_FOLLOW)
        !          1099:                printf("hilqunmap(%d): qnum %d device %x\n",
        !          1100:                       p->p_pid, qnum, device);
        !          1101: #endif
        !          1102: 
        !          1103:        if (qnum >= NHILQ || hilp->hl_queue[qnum].hq_procp != p)
        !          1104:                return(EINVAL);
        !          1105: 
        !          1106:        hilp->hl_queue[qnum].hq_devmask &= ~hildevmask(device);
        !          1107:        s = splhil();
        !          1108:        hilp->hl_device[device].hd_qmask &= ~hilqmask(qnum);
        !          1109:        splx(s);
        !          1110: #ifdef DEBUG
        !          1111:        if (hildebug & HDB_MASK)
        !          1112:                printf("hilqunmap(%d): devmask %x qmask %x\n",
        !          1113:                       p->p_pid, hilp->hl_queue[qnum].hq_devmask,
        !          1114:                       hilp->hl_device[device].hd_qmask);
        !          1115: #endif
        !          1116:        return(0);
        !          1117: }
        !          1118: 
        !          1119: #ifdef MAPMEM
        !          1120: hilqmapin(mp, off)
        !          1121:        struct mapmem *mp;
        !          1122: {
        !          1123:        struct hilloop *hilp = &hil0;           /* XXX */
        !          1124:        register HILQ *hq = hilp->hl_queue[mp->mm_id].hq_eventqueue;
        !          1125: 
        !          1126:        if (hq == NULL || off >= sizeof(HILQ))
        !          1127:                return(-1);
        !          1128:        return(kvtop((u_int)hq + off) >> PGSHIFT);
        !          1129: }
        !          1130: 
        !          1131: /*
        !          1132:  * Fork hook.
        !          1133:  * Unmap queue from child's address space
        !          1134:  */
        !          1135: hilqfork(mp, ischild)
        !          1136:        struct mapmem *mp;
        !          1137: {
        !          1138:        struct proc *p = u.u_procp;             /* XXX */
        !          1139: #ifdef DEBUG
        !          1140:        if (hildebug & HDB_MMAP)
        !          1141:                printf("hilqfork(%d): %s qnum %d\n", p->p_pid,
        !          1142:                       ischild ? "child" : "parent", mp->mm_id);
        !          1143: #endif
        !          1144:        if (ischild) {
        !          1145:                mmmapout(p, mp);
        !          1146:                (void) mmfree(p, mp);
        !          1147:        }
        !          1148: }
        !          1149: 
        !          1150: /*
        !          1151:  * Vfork hook.
        !          1152:  * Associate queue with child when VM resources are passed.
        !          1153:  */
        !          1154: hilqvfork(mp, fup, tup)
        !          1155:        struct mapmem *mp;
        !          1156:        struct user *fup, *tup;
        !          1157: {
        !          1158:        struct hilloop *hilp = &hil0;           /* XXX */
        !          1159:        register struct hiliqueue *qp = &hilp->hl_queue[mp->mm_id];
        !          1160: 
        !          1161: #ifdef DEBUG
        !          1162:        if (hildebug & HDB_MMAP)
        !          1163:                printf("hilqvfork(%d): from %x to %x qnum %d, qprocp %x\n",
        !          1164:                       u.u_procp->p_pid, fup->u_procp, tup->u_procp,
        !          1165:                       mp->mm_id, qp->hq_procp);
        !          1166: #endif
        !          1167:        if (qp->hq_procp == fup->u_procp)
        !          1168:                qp->hq_procp = tup->u_procp;
        !          1169: }
        !          1170: 
        !          1171: /*
        !          1172:  * Exit hook.
        !          1173:  * Unmap all devices and free all queues.
        !          1174:  */
        !          1175: hilqexit(mp)
        !          1176:        struct mapmem *mp;
        !          1177: {
        !          1178:        struct proc *p = u.u_procp;             /* XXX */
        !          1179:        register struct hilloop *hilp = &hil0;  /* XXX */
        !          1180:        register int mask, i;
        !          1181:        int s;
        !          1182: 
        !          1183: #ifdef DEBUG
        !          1184:        if (hildebug & HDB_MMAP)
        !          1185:                printf("hilqexit(%d): qnum %d\n", p->p_pid, mp->mm_id);
        !          1186: #endif
        !          1187:        /*
        !          1188:         * Atomically take all devices off the queue
        !          1189:         */
        !          1190:        mask = ~hilqmask(mp->mm_id);
        !          1191:        s = splhil();
        !          1192:        for (i = 0; i < NHILD; i++)
        !          1193:                hilp->hl_device[i].hd_qmask &= mask;
        !          1194:        splx(s);
        !          1195:        /*
        !          1196:         * Now unmap from user address space and free queue
        !          1197:         */
        !          1198:        i = mp->mm_id;
        !          1199:        cifree((caddr_t)hilp->hl_queue[i].hq_eventqueue, sizeof(HILQ));
        !          1200:        hilp->hl_queue[i].hq_eventqueue = NULL;
        !          1201:        hilp->hl_queue[i].hq_procp = NULL;
        !          1202:        return(mmfree(p, mp));
        !          1203: }
        !          1204: #endif
        !          1205: 
        !          1206: #include "clist.h"
        !          1207: 
        !          1208: /*
        !          1209:  * This is just a copy of the virgin q_to_b routine with minor
        !          1210:  * optimizations for HIL use.  It is used for two reasons:
        !          1211:  * 1. If we have PAGE mode defined, the normal q_to_b processes
        !          1212:  *    chars one at a time and breaks on newlines.
        !          1213:  * 2. We don't have to raise the priority to spltty() for most
        !          1214:  *    of the clist manipulations.
        !          1215:  */
        !          1216: hilq_to_b(q, cp, cc)
        !          1217:        register struct clist *q;
        !          1218:        register char *cp;
        !          1219: {
        !          1220:        register struct cblock *bp;
        !          1221:        register int nc;
        !          1222:        char *acp;
        !          1223:        int s;
        !          1224:        extern char cwaiting;
        !          1225: 
        !          1226:        if (cc <= 0)
        !          1227:                return (0);
        !          1228:        s = splhil();
        !          1229:        if (q->c_cc <= 0) {
        !          1230:                q->c_cc = 0;
        !          1231:                q->c_cf = q->c_cl = NULL;
        !          1232:                splx(s);
        !          1233:                return (0);
        !          1234:        }
        !          1235:        acp = cp;
        !          1236: 
        !          1237:        while (cc) {
        !          1238:                nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND);
        !          1239:                nc = MIN(nc, cc);
        !          1240:                nc = MIN(nc, q->c_cc);
        !          1241:                (void) bcopy(q->c_cf, cp, (unsigned)nc);
        !          1242:                q->c_cf += nc;
        !          1243:                q->c_cc -= nc;
        !          1244:                cc -= nc;
        !          1245:                cp += nc;
        !          1246:                if (q->c_cc <= 0) {
        !          1247:                        bp = (struct cblock *)(q->c_cf - 1);
        !          1248:                        bp = (struct cblock *)((int)bp & ~CROUND);
        !          1249:                        q->c_cf = q->c_cl = NULL;
        !          1250:                        spltty();
        !          1251:                        bp->c_next = cfreelist;
        !          1252:                        cfreelist = bp;
        !          1253:                        cfreecount += CBSIZE;
        !          1254:                        if (cwaiting) {
        !          1255:                                wakeup(&cwaiting);
        !          1256:                                cwaiting = 0;
        !          1257:                        }
        !          1258:                        break;
        !          1259:                }
        !          1260:                if (((int)q->c_cf & CROUND) == 0) {
        !          1261:                        bp = (struct cblock *)(q->c_cf);
        !          1262:                        bp--;
        !          1263:                        q->c_cf = bp->c_next->c_info;
        !          1264:                        spltty();
        !          1265:                        bp->c_next = cfreelist;
        !          1266:                        cfreelist = bp;
        !          1267:                        cfreecount += CBSIZE;
        !          1268:                        if (cwaiting) {
        !          1269:                                wakeup(&cwaiting);
        !          1270:                                cwaiting = 0;
        !          1271:                        }
        !          1272:                        splhil();
        !          1273:                }
        !          1274:        }
        !          1275:        splx(s);
        !          1276:        return (cp-acp);
        !          1277: }
        !          1278: 
        !          1279: /*
        !          1280:  * Cooked keyboard functions for ite driver.
        !          1281:  * There is only one "cooked" ITE keyboard (the first keyboard found)
        !          1282:  * per loop.  There may be other keyboards, but they will always be "raw".
        !          1283:  */
        !          1284: 
        !          1285: kbdbell()
        !          1286: {
        !          1287:        struct hilloop *hilp = &hil0;           /* XXX */
        !          1288: 
        !          1289:        hilbeep(hilp, &default_bell);
        !          1290: }
        !          1291: 
        !          1292: kbdenable()
        !          1293: {
        !          1294:        struct hilloop *hilp = &hil0;   /* XXX */
        !          1295:        register struct hil_dev *hildevice = hilp->hl_addr;
        !          1296:        char db;
        !          1297: 
        !          1298:        /* Set the autorepeat rate register */
        !          1299:        db = ar_format(KBD_ARR);
        !          1300:        send_hil_cmd(hildevice, HIL_SETARR, &db, 1, NULL);
        !          1301: 
        !          1302:        /* Set the autorepeat delay register */
        !          1303:        db = ar_format(KBD_ARD);
        !          1304:        send_hil_cmd(hildevice, HIL_SETARD, &db, 1, NULL);
        !          1305: 
        !          1306:        /* Enable interrupts */
        !          1307:        send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL);
        !          1308: }
        !          1309: 
        !          1310: kbddisable()
        !          1311: {
        !          1312: }
        !          1313: 
        !          1314: /*
        !          1315:  * XXX: read keyboard directly and return code.
        !          1316:  * Used by console getchar routine.  Could really screw up anybody
        !          1317:  * reading from the keyboard in the normal, interrupt driven fashion.
        !          1318:  */
        !          1319: kbdgetc(statp)
        !          1320:        int *statp;
        !          1321: {
        !          1322:        struct hilloop *hilp = &hil0;           /* XXX */
        !          1323:        register struct hil_dev *hildevice = hilp->hl_addr;
        !          1324:        register int c, stat;
        !          1325:        int s;
        !          1326: 
        !          1327:        s = splhil();
        !          1328:        while (((stat = hildevice->hil_stat) & HIL_DATA_RDY) == 0)
        !          1329:                ;
        !          1330:        c = hildevice->hil_data;
        !          1331:        splx(s);
        !          1332:        *statp = stat;
        !          1333:        return(c);
        !          1334: }
        !          1335: 
        !          1336: /*
        !          1337:  * Recoginize and clear keyboard generated NMIs.
        !          1338:  * Returns 1 if it was ours, 0 otherwise.  Note that we cannot use
        !          1339:  * send_hil_cmd() to issue the clear NMI command as that would actually
        !          1340:  * lower the priority to splimp() and it doesn't wait for the completion
        !          1341:  * of the command.  Either of these conditions could result in the
        !          1342:  * interrupt reoccuring.  Note that we issue the CNMT command twice.
        !          1343:  * This seems to be needed, once is not always enough!?!
        !          1344:  */
        !          1345: kbdnmi()
        !          1346: {
        !          1347:        register struct hilloop *hilp = &hil0;          /* XXX */
        !          1348: 
        !          1349:        if ((*KBDNMISTAT & KBDNMI) == 0)
        !          1350:                return(0);
        !          1351:        HILWAIT(hilp->hl_addr);
        !          1352:        hilp->hl_addr->hil_cmd = HIL_CNMT;
        !          1353:        HILWAIT(hilp->hl_addr);
        !          1354:        hilp->hl_addr->hil_cmd = HIL_CNMT;
        !          1355:        HILWAIT(hilp->hl_addr);
        !          1356:        return(1);
        !          1357: }
        !          1358: 
        !          1359: #define HILSECURITY    0x33
        !          1360: #define HILIDENTIFY    0x03
        !          1361: #define HILSCBIT       0x04
        !          1362: 
        !          1363: /*
        !          1364:  * Called at boot time to print out info about interesting devices
        !          1365:  */
        !          1366: hilinfo(hilp)
        !          1367:        register struct hilloop *hilp;
        !          1368: {
        !          1369:        register int id, len;
        !          1370:        register struct kbdmap *km;
        !          1371: 
        !          1372:        /*
        !          1373:         * Keyboard info.
        !          1374:         */
        !          1375:        if (hilp->hl_kbddev) {
        !          1376:                printf("hil%d: ", hilp->hl_kbddev);
        !          1377:                for (km = kbd_map; km->kbd_code; km++)
        !          1378:                        if (km->kbd_code == hilp->hl_kbdlang) {
        !          1379:                                printf("%s ", km->kbd_desc);
        !          1380:                                break;
        !          1381:                        }
        !          1382:                printf("keyboard\n");
        !          1383:        }
        !          1384:        /*
        !          1385:         * ID module.
        !          1386:         * Attempt to locate the first ID module and print out its
        !          1387:         * security code.  Is this a good idea??
        !          1388:         */
        !          1389:        id = hiliddev(hilp);
        !          1390:        if (id) {
        !          1391:                hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !          1392:                hilp->hl_cmddev = id;
        !          1393:                send_hildev_cmd(hilp, id, HILSECURITY);
        !          1394:                len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
        !          1395:                hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !          1396:                hilp->hl_cmddev = 0;
        !          1397:                printf("hil%d: security code", id);
        !          1398:                for (id = 0; id < len; id++)
        !          1399:                        printf(" %x", hilp->hl_cmdbuf[id]);
        !          1400:                while (id++ < 16)
        !          1401:                        printf(" 0");
        !          1402:                printf("\n");
        !          1403:        }
        !          1404: }
        !          1405: 
        !          1406: #define HILAR1 0x3E
        !          1407: #define HILAR2 0x3F
        !          1408: 
        !          1409: /*
        !          1410:  * Called after the loop has reconfigured.  Here we need to:
        !          1411:  *     - determine how many devices are on the loop
        !          1412:  *       (some may have been added or removed)
        !          1413:  *     - locate the ITE keyboard (if any) and ensure
        !          1414:  *       that it is in the proper state (raw or cooked)
        !          1415:  *       and is set to use the proper language mapping table
        !          1416:  *     - ensure all other keyboards are raw
        !          1417:  * Note that our device state is now potentially invalid as
        !          1418:  * devices may no longer be where they were.  What we should
        !          1419:  * do here is either track where the devices went and move
        !          1420:  * state around accordingly or, more simply, just mark all
        !          1421:  * devices as HIL_DERROR and don't allow any further use until
        !          1422:  * they are closed.  This is a little too brutal for my tastes,
        !          1423:  * we prefer to just assume people won't move things around.
        !          1424:  */
        !          1425: hilconfig(hilp)
        !          1426:        register struct hilloop *hilp;
        !          1427: {
        !          1428:        u_char db;
        !          1429:        int s;
        !          1430: 
        !          1431:        s = splhil();
        !          1432: #ifdef DEBUG
        !          1433:        if (hildebug & HDB_CONFIG) {
        !          1434:                printf("hilconfig: reconfigured: ");
        !          1435:                send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db);
        !          1436:                printf("LPSTAT %x, ", db);
        !          1437:                send_hil_cmd(hilp->hl_addr, HIL_READLPCTRL, NULL, 0, &db);
        !          1438:                printf("LPCTRL %x, ", db);
        !          1439:                send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db);
        !          1440:                printf("KBDSADR %x\n", db);
        !          1441:                hilreport(hilp);
        !          1442:        }
        !          1443: #endif
        !          1444:        /*
        !          1445:         * Determine how many devices are on the loop.
        !          1446:         * Mark those as alive and real, all others as dead.
        !          1447:         */
        !          1448:        db = 0;
        !          1449:        send_hil_cmd(hilp->hl_addr, HIL_READLPSTAT, NULL, 0, &db);
        !          1450:        hilp->hl_maxdev = db & LPS_DEVMASK;
        !          1451:        for (db = 1; db < NHILD; db++) {
        !          1452:                if (db <= hilp->hl_maxdev)
        !          1453:                        hilp->hl_device[db].hd_flags |= HIL_ALIVE;
        !          1454:                else
        !          1455:                        hilp->hl_device[db].hd_flags &= ~HIL_ALIVE;
        !          1456:                hilp->hl_device[db].hd_flags &= ~HIL_PSEUDO;
        !          1457:        }
        !          1458: #ifdef DEBUG
        !          1459:        if (hildebug & (HDB_CONFIG|HDB_KEYBOARD))
        !          1460:                printf("hilconfig: max device %d\n", hilp->hl_maxdev);
        !          1461: #endif
        !          1462:        if (hilp->hl_maxdev == 0) {
        !          1463:                hilp->hl_kbddev = 0;
        !          1464:                splx(s);
        !          1465:                return;
        !          1466:        }
        !          1467:        /*
        !          1468:         * Find out where the keyboards are and record the ITE keyboard
        !          1469:         * (first one found).  If no keyboards found, we are all done.
        !          1470:         */
        !          1471:        db = 0;
        !          1472:        send_hil_cmd(hilp->hl_addr, HIL_READKBDSADR, NULL, 0, &db);
        !          1473: #ifdef DEBUG
        !          1474:        if (hildebug & HDB_KEYBOARD)
        !          1475:                printf("hilconfig: keyboard: KBDSADR %x, old %d, new %d\n",
        !          1476:                       db, hilp->hl_kbddev, ffs((int)db));
        !          1477: #endif
        !          1478:        hilp->hl_kbddev = ffs((int)db);
        !          1479:        if (hilp->hl_kbddev == 0) {
        !          1480:                splx(s);
        !          1481:                return;
        !          1482:        }
        !          1483:        /*
        !          1484:         * Determine if the keyboard should be cooked or raw and configure it.
        !          1485:         */
        !          1486:        db = (hilp->hl_kbdflags & KBD_RAW) ? 0 : 1 << (hilp->hl_kbddev - 1);
        !          1487:        send_hil_cmd(hilp->hl_addr, HIL_WRITEKBDSADR, &db, 1, NULL);
        !          1488:        /*
        !          1489:         * Re-enable autorepeat in raw mode, cooked mode AR is not affected.
        !          1490:         */
        !          1491:        if (hilp->hl_kbdflags & (KBD_AR1|KBD_AR2)) {
        !          1492:                db = (hilp->hl_kbdflags & KBD_AR1) ? HILAR1 : HILAR2;
        !          1493:                hilp->hl_cmddev = hilp->hl_kbddev;
        !          1494:                send_hildev_cmd(hilp, hilp->hl_kbddev, db);
        !          1495:                hilp->hl_cmddev = 0;
        !          1496:        }
        !          1497:        /*
        !          1498:         * Determine the keyboard language configuration, but don't
        !          1499:         * override a user-specified setting.
        !          1500:         */
        !          1501:        db = 0;
        !          1502:        send_hil_cmd(hilp->hl_addr, HIL_READKBDLANG, NULL, 0, &db);
        !          1503: #ifdef DEBUG
        !          1504:        if (hildebug & HDB_KEYBOARD)
        !          1505:                printf("hilconfig: language: old %x new %x\n",
        !          1506:                       hilp->hl_kbdlang, db);
        !          1507: #endif
        !          1508:        if (hilp->hl_kbdlang != KBD_SPECIAL) {
        !          1509:                struct kbdmap *km;
        !          1510: 
        !          1511:                for (km = kbd_map; km->kbd_code; km++)
        !          1512:                        if (km->kbd_code == db) {
        !          1513:                                hilp->hl_kbdlang = db;
        !          1514:                                /* XXX */
        !          1515:                                kbd_keymap = km->kbd_keymap;
        !          1516:                                kbd_shiftmap = km->kbd_shiftmap;
        !          1517:                                kbd_ctrlmap = km->kbd_ctrlmap;
        !          1518:                                kbd_ctrlshiftmap = km->kbd_ctrlshiftmap;
        !          1519:                                kbd_stringmap = km->kbd_stringmap;
        !          1520:                        }
        !          1521:        }
        !          1522:        splx(s);
        !          1523: }
        !          1524: 
        !          1525: hilreset(hilp)
        !          1526:        struct hilloop *hilp;
        !          1527: {
        !          1528:        register struct hil_dev *hildevice = hilp->hl_addr;
        !          1529:        u_char db;
        !          1530: 
        !          1531:        /*
        !          1532:         * Initialize the loop: reconfigure, don't report errors,
        !          1533:         * cook keyboards, and enable autopolling.
        !          1534:         */
        !          1535:        db = LPC_RECONF | LPC_KBDCOOK | LPC_NOERROR | LPC_AUTOPOLL;
        !          1536:        send_hil_cmd(hildevice, HIL_WRITELPCTRL, &db, 1, NULL);
        !          1537:        /*
        !          1538:         * Delay one second for reconfiguration and then read the the
        !          1539:         * data register to clear the interrupt (if the loop reconfigured).
        !          1540:         */
        !          1541:        DELAY(1000000);
        !          1542:        if (hildevice->hil_stat & HIL_DATA_RDY)
        !          1543:                db = hildevice->hil_data;
        !          1544:        /*
        !          1545:         * The HIL loop may have reconfigured.  If so we proceed on,
        !          1546:         * if not we loop until a successful reconfiguration is reported
        !          1547:         * back to us.  The HIL loop will continue to attempt forever.
        !          1548:         * Probably not very smart.
        !          1549:         */
        !          1550:        do {
        !          1551:                send_hil_cmd(hildevice, HIL_READLPSTAT, NULL, 0, &db);
        !          1552:         } while ((db & (LPS_CONFFAIL|LPS_CONFGOOD)) == 0);
        !          1553:        /*
        !          1554:         * At this point, the loop should have reconfigured.
        !          1555:         * The reconfiguration interrupt has already called hilconfig()
        !          1556:         * so the keyboard has been determined.
        !          1557:         */
        !          1558:        send_hil_cmd(hildevice, HIL_INTON, NULL, 0, NULL);
        !          1559: }
        !          1560: 
        !          1561: hilbeep(hilp, bp)
        !          1562:        struct hilloop *hilp;
        !          1563:        register struct _hilbell *bp;
        !          1564: {
        !          1565:        u_char buf[2];
        !          1566: 
        !          1567:        buf[0] = ~((bp->duration - 10) / 10);
        !          1568:        buf[1] = bp->frequency;
        !          1569:        send_hil_cmd(hilp->hl_addr, HIL_SETTONE, buf, 2, NULL);
        !          1570: }
        !          1571: 
        !          1572: /*
        !          1573:  * Locate and return the address of the first ID module, 0 if none present.
        !          1574:  */
        !          1575: hiliddev(hilp)
        !          1576:        register struct hilloop *hilp;
        !          1577: {
        !          1578:        register int i, len;
        !          1579: 
        !          1580: #ifdef DEBUG
        !          1581:        if (hildebug & HDB_IDMODULE)
        !          1582:                printf("hiliddev(%x): looking for idmodule...", hilp);
        !          1583: #endif
        !          1584:        for (i = 1; i <= hilp->hl_maxdev; i++) {
        !          1585:                hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !          1586:                hilp->hl_cmddev = i;
        !          1587:                send_hildev_cmd(hilp, i, HILIDENTIFY);
        !          1588:                /*
        !          1589:                 * XXX: the final condition checks to ensure that the
        !          1590:                 * device ID byte is in the range of the ID module (0x30-0x3F)
        !          1591:                 */
        !          1592:                len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
        !          1593:                if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT) &&
        !          1594:                    (hilp->hl_cmdbuf[0] & 0xF0) == 0x30) {
        !          1595:                        hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !          1596:                        hilp->hl_cmddev = i;
        !          1597:                        send_hildev_cmd(hilp, i, HILSECURITY);
        !          1598:                        break;
        !          1599:                }
        !          1600:        }               
        !          1601:        hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !          1602:        hilp->hl_cmddev = 0;
        !          1603: #ifdef DEBUG
        !          1604:        if (hildebug & HDB_IDMODULE)
        !          1605:                if (i <= hilp->hl_maxdev)
        !          1606:                        printf("found at %d\n", i);
        !          1607:                else
        !          1608:                        printf("not found\n");
        !          1609: #endif
        !          1610:        return(i <= hilp->hl_maxdev ? i : 0);
        !          1611: }
        !          1612: 
        !          1613: /*
        !          1614:  * Low level routines which actually talk to the 8042 chip.
        !          1615:  */
        !          1616: 
        !          1617: /*
        !          1618:  * Send a command to the 8042 with zero or more bytes of data.
        !          1619:  * If rdata is non-null, wait for and return a byte of data.
        !          1620:  * We run at splimp() to make the transaction as atomic as
        !          1621:  * possible without blocking the clock (is this necessary?)
        !          1622:  */
        !          1623: send_hil_cmd(hildevice, cmd, data, dlen, rdata)
        !          1624:        register struct hil_dev *hildevice;
        !          1625:        u_char cmd, *data, dlen;
        !          1626:        u_char *rdata;
        !          1627: {
        !          1628:        u_char status;
        !          1629:        int s = splimp();
        !          1630: 
        !          1631:        HILWAIT(hildevice);
        !          1632:        hildevice->hil_cmd = cmd;
        !          1633:        while (dlen--) {
        !          1634:                HILWAIT(hildevice);
        !          1635:                hildevice->hil_data = *data++;
        !          1636:        }
        !          1637:        if (rdata) {
        !          1638:                do {
        !          1639:                        HILDATAWAIT(hildevice);
        !          1640:                        status = hildevice->hil_stat;
        !          1641:                        *rdata = hildevice->hil_data;
        !          1642:                } while (((status >> HIL_SSHIFT) & HIL_SMASK) != HIL_68K);
        !          1643:        }
        !          1644:        splx(s);
        !          1645: }
        !          1646: 
        !          1647: /*
        !          1648:  * Send a command to a device on the loop.
        !          1649:  * Since only one command can be active on the loop at any time,
        !          1650:  * we must ensure that we are not interrupted during this process.
        !          1651:  * Hence we mask interrupts to prevent potential access from most
        !          1652:  * interrupt routines and turn off auto-polling to disable the
        !          1653:  * internally generated poll commands.
        !          1654:  *
        !          1655:  * splhigh is extremely conservative but insures atomic operation,
        !          1656:  * splimp (clock only interrupts) seems to be good enough in practice.
        !          1657:  */
        !          1658: send_hildev_cmd(hilp, device, cmd)
        !          1659:        register struct hilloop *hilp;
        !          1660:        char device, cmd;
        !          1661: {
        !          1662:        register struct hil_dev *hildevice = hilp->hl_addr;
        !          1663:        u_char status, c;
        !          1664:        int s = splimp();
        !          1665: 
        !          1666:        polloff(hildevice);
        !          1667: 
        !          1668:        /*
        !          1669:         * Transfer the command and device info to the chip
        !          1670:         */
        !          1671:        HILWAIT(hildevice);
        !          1672:        hildevice->hil_cmd = HIL_STARTCMD;
        !          1673:        HILWAIT(hildevice);
        !          1674:        hildevice->hil_data = 8 + device;
        !          1675:        HILWAIT(hildevice);
        !          1676:        hildevice->hil_data = cmd;
        !          1677:        HILWAIT(hildevice);
        !          1678:        hildevice->hil_data = HIL_TIMEOUT;
        !          1679:        /*
        !          1680:         * Trigger the command and wait for completion
        !          1681:         */
        !          1682:        HILWAIT(hildevice);
        !          1683:        hildevice->hil_cmd = HIL_TRIGGER;
        !          1684:        hilp->hl_cmddone = FALSE;
        !          1685:        do {
        !          1686:                HILDATAWAIT(hildevice);
        !          1687:                status = hildevice->hil_stat;
        !          1688:                c = hildevice->hil_data;
        !          1689:                hil_process_int(status, c);
        !          1690:        } while (!hilp->hl_cmddone);
        !          1691: 
        !          1692:        pollon(hildevice);
        !          1693:        splx(s);
        !          1694: }
        !          1695: 
        !          1696: /*
        !          1697:  * Turn auto-polling off and on.
        !          1698:  * Also disables and enable auto-repeat.  Why?
        !          1699:  */
        !          1700: polloff(hildevice)
        !          1701:        register struct hil_dev *hildevice;
        !          1702: {
        !          1703:        register char db;
        !          1704: 
        !          1705:        /*
        !          1706:         * Turn off auto repeat
        !          1707:         */
        !          1708:        HILWAIT(hildevice);
        !          1709:        hildevice->hil_cmd = HIL_SETARR;
        !          1710:        HILWAIT(hildevice);
        !          1711:        hildevice->hil_data = 0;
        !          1712:        /*
        !          1713:         * Turn off auto-polling
        !          1714:         */
        !          1715:        HILWAIT(hildevice);
        !          1716:        hildevice->hil_cmd = HIL_READLPCTRL;
        !          1717:        HILDATAWAIT(hildevice);
        !          1718:        db = hildevice->hil_data;
        !          1719:        db &= ~LPC_AUTOPOLL;
        !          1720:        HILWAIT(hildevice);
        !          1721:        hildevice->hil_cmd = HIL_WRITELPCTRL;
        !          1722:        HILWAIT(hildevice);
        !          1723:        hildevice->hil_data = db;
        !          1724:        /*
        !          1725:         * Must wait til polling is really stopped
        !          1726:         */
        !          1727:        do {    
        !          1728:                HILWAIT(hildevice);
        !          1729:                hildevice->hil_cmd = HIL_READBUSY;
        !          1730:                HILDATAWAIT(hildevice);
        !          1731:                db = hildevice->hil_data;
        !          1732:        } while (db & BSY_LOOPBUSY);
        !          1733: }
        !          1734: 
        !          1735: pollon(hildevice)
        !          1736:        register struct hil_dev *hildevice;
        !          1737: {
        !          1738:        register char db;
        !          1739: 
        !          1740:        /*
        !          1741:         * Turn on auto polling
        !          1742:         */
        !          1743:        HILWAIT(hildevice);
        !          1744:        hildevice->hil_cmd = HIL_READLPCTRL;
        !          1745:        HILDATAWAIT(hildevice);
        !          1746:        db = hildevice->hil_data;
        !          1747:        db |= LPC_AUTOPOLL;
        !          1748:        HILWAIT(hildevice);
        !          1749:        hildevice->hil_cmd = HIL_WRITELPCTRL;
        !          1750:        HILWAIT(hildevice);
        !          1751:        hildevice->hil_data = db;
        !          1752:        /*
        !          1753:         * Turn on auto repeat
        !          1754:         */
        !          1755:        HILWAIT(hildevice);
        !          1756:        hildevice->hil_cmd = HIL_SETARR;
        !          1757:        HILWAIT(hildevice);
        !          1758:        hildevice->hil_data = ar_format(KBD_ARR);
        !          1759: }
        !          1760: 
        !          1761: #ifdef DEBUG
        !          1762: printhilpollbuf(hilp)
        !          1763:        register struct hilloop *hilp;
        !          1764: {
        !          1765:        register u_char *cp;
        !          1766:        register int i, len;
        !          1767: 
        !          1768:        cp = hilp->hl_pollbuf;
        !          1769:        len = hilp->hl_pollbp - cp;
        !          1770:        for (i = 0; i < len; i++)
        !          1771:                printf("%x ", hilp->hl_pollbuf[i]);
        !          1772:        printf("\n");
        !          1773: }
        !          1774: 
        !          1775: printhilcmdbuf(hilp)
        !          1776:        register struct hilloop *hilp;
        !          1777: {
        !          1778:        register u_char *cp;
        !          1779:        register int i, len;
        !          1780: 
        !          1781:        cp = hilp->hl_cmdbuf;
        !          1782:        len = hilp->hl_cmdbp - cp;
        !          1783:        for (i = 0; i < len; i++)
        !          1784:                printf("%x ", hilp->hl_cmdbuf[i]);
        !          1785:        printf("\n");
        !          1786: }
        !          1787: 
        !          1788: hilreport(hilp)
        !          1789:        register struct hilloop *hilp;
        !          1790: {
        !          1791:        register int i, len;
        !          1792:        int s = splhil();
        !          1793: 
        !          1794:        for (i = 1; i <= hilp->hl_maxdev; i++) {
        !          1795:                hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !          1796:                hilp->hl_cmddev = i;
        !          1797:                send_hildev_cmd(hilp, i, HILIDENTIFY);
        !          1798:                printf("hil%d: id: ", i);
        !          1799:                printhilcmdbuf(hilp);
        !          1800:                len = hilp->hl_cmdbp - hilp->hl_cmdbuf;
        !          1801:                if (len > 1 && (hilp->hl_cmdbuf[1] & HILSCBIT)) {
        !          1802:                        hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !          1803:                        hilp->hl_cmddev = i;
        !          1804:                        send_hildev_cmd(hilp, i, HILSECURITY);
        !          1805:                        printf("hil%d: sc: ", i);
        !          1806:                        printhilcmdbuf(hilp);
        !          1807:                }
        !          1808:        }               
        !          1809:        hilp->hl_cmdbp = hilp->hl_cmdbuf;
        !          1810:        hilp->hl_cmddev = 0;
        !          1811:        splx(s);
        !          1812: }
        !          1813: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.