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

Annotation of sys/arch/hp300/dev/ppi.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: ppi.c,v 1.16 2006/04/13 20:08:12 miod Exp $   */
        !             2: /*     $NetBSD: ppi.c,v 1.13 1997/04/02 22:37:33 scottr Exp $  */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1996, 1997 Jason R. Thorpe.  All rights reserved.
        !             6:  * Copyright (c) 1982, 1990, 1993
        !             7:  *     The Regents of the University of California.  All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  *
        !            33:  *     @(#)ppi.c       8.1 (Berkeley) 6/16/93
        !            34:  */
        !            35:
        !            36: /*
        !            37:  * Printer/Plotter HPIB interface
        !            38:  */
        !            39:
        !            40: #include <sys/param.h>
        !            41: #include <sys/systm.h>
        !            42: #include <sys/conf.h>
        !            43: #include <sys/device.h>
        !            44: #include <sys/errno.h>
        !            45: #include <sys/kernel.h>
        !            46: #include <sys/malloc.h>
        !            47: #include <sys/proc.h>
        !            48: #include <sys/timeout.h>
        !            49: #include <sys/uio.h>
        !            50:
        !            51: #include <hp300/dev/hpibvar.h>
        !            52:
        !            53: #include <hp300/dev/ppiioctl.h>
        !            54:
        !            55: struct ppi_softc {
        !            56:        struct device sc_dev;
        !            57:        int     sc_flags;
        !            58:        struct  hpibqueue sc_hq;        /* HP-IB job queue entry */
        !            59:        struct  ppiparam sc_param;
        !            60: #define sc_burst sc_param.burst
        !            61: #define sc_timo  sc_param.timo
        !            62: #define sc_delay sc_param.delay
        !            63:        int     sc_sec;
        !            64:        int     sc_slave;               /* HP-IB slave address */
        !            65:        struct timeout sc_to;           /* ppitimo timeout */
        !            66:        struct timeout sc_start_to;     /* ppistart timeout */
        !            67: };
        !            68:
        !            69: /* sc_flags values */
        !            70: #define        PPIF_ALIVE      0x01
        !            71: #define        PPIF_OPEN       0x02
        !            72: #define PPIF_UIO       0x04
        !            73: #define PPIF_TIMO      0x08
        !            74: #define PPIF_DELAY     0x10
        !            75:
        !            76: int    ppimatch(struct device *, void *, void *);
        !            77: void   ppiattach(struct device *, struct device *, void *);
        !            78:
        !            79: struct cfattach ppi_ca = {
        !            80:        sizeof(struct ppi_softc), ppimatch, ppiattach
        !            81: };
        !            82:
        !            83: struct cfdriver ppi_cd = {
        !            84:        NULL, "ppi", DV_DULL
        !            85: };
        !            86:
        !            87: void   ppistart(void *);
        !            88: void   ppinoop(void *);
        !            89:
        !            90: void   ppitimo(void *);
        !            91: int    ppirw(dev_t, struct uio *);
        !            92: int    ppihztoms(int);
        !            93: int    ppimstohz(int);
        !            94:
        !            95: cdev_decl(ppi);
        !            96:
        !            97: #define UNIT(x)                minor(x)
        !            98:
        !            99: #ifdef DEBUG
        !           100: int    ppidebug = 0x80;
        !           101: #define PDB_FOLLOW     0x01
        !           102: #define PDB_IO         0x02
        !           103: #define PDB_NOCHECK    0x80
        !           104: #endif
        !           105:
        !           106: int
        !           107: ppimatch(parent, match, aux)
        !           108:        struct device *parent;
        !           109:        void *match, *aux;
        !           110: {
        !           111:        struct cfdata *cf = match;
        !           112:        struct hpibbus_attach_args *ha = aux;
        !           113:
        !           114:        /*
        !           115:         * The printer/plotter doesn't return an ID tag.
        !           116:         * The check below prevents us from matching a CS80
        !           117:         * device by mistake.
        !           118:         */
        !           119:        if (ha->ha_id & 0x200)
        !           120:                return (0);
        !           121:
        !           122:        /*
        !           123:         * To prevent matching all unused slots on the bus, we
        !           124:         * don't allow wildcarded locators.
        !           125:         */
        !           126:        if (cf->hpibbuscf_slave == HPIBBUS_SLAVE_UNK ||
        !           127:            cf->hpibbuscf_punit == HPIBBUS_PUNIT_UNK)
        !           128:                return (0);
        !           129:
        !           130:        return (1);
        !           131: }
        !           132:
        !           133: void
        !           134: ppiattach(parent, self, aux)
        !           135:        struct device *parent, *self;
        !           136:        void *aux;
        !           137: {
        !           138:        struct ppi_softc *sc = (struct ppi_softc *)self;
        !           139:        struct hpibbus_attach_args *ha = aux;
        !           140:
        !           141:        printf("\n");
        !           142:
        !           143:        sc->sc_slave = ha->ha_slave;
        !           144:
        !           145:        /* Initialize the hpib queue entry. */
        !           146:        sc->sc_hq.hq_softc = sc;
        !           147:        sc->sc_hq.hq_slave = sc->sc_slave;
        !           148:        sc->sc_hq.hq_start = ppistart;
        !           149:        sc->sc_hq.hq_go = ppinoop;
        !           150:        sc->sc_hq.hq_intr = ppinoop;
        !           151:
        !           152:        sc->sc_flags = PPIF_ALIVE;
        !           153:
        !           154:        /* Initialize timeout structures */
        !           155:        timeout_set(&sc->sc_to, ppitimo, sc);
        !           156:        timeout_set(&sc->sc_start_to, ppistart, sc);
        !           157: }
        !           158:
        !           159: void
        !           160: ppinoop(arg)
        !           161:        void *arg;
        !           162: {
        !           163:        /* Noop! */
        !           164: }
        !           165:
        !           166: int
        !           167: ppiopen(dev, flags, fmt, p)
        !           168:        dev_t dev;
        !           169:        int flags, fmt;
        !           170:        struct proc *p;
        !           171: {
        !           172:        int unit = UNIT(dev);
        !           173:        struct ppi_softc *sc;
        !           174:
        !           175:        if (unit >= ppi_cd.cd_ndevs ||
        !           176:            (sc = ppi_cd.cd_devs[unit]) == NULL ||
        !           177:            (sc->sc_flags & PPIF_ALIVE) == 0)
        !           178:                return (ENXIO);
        !           179:
        !           180: #ifdef DEBUG
        !           181:        if (ppidebug & PDB_FOLLOW)
        !           182:                printf("ppiopen(%x, %x): flags %x\n",
        !           183:                       dev, flags, sc->sc_flags);
        !           184: #endif
        !           185:        if (sc->sc_flags & PPIF_OPEN)
        !           186:                return (EBUSY);
        !           187:        sc->sc_flags |= PPIF_OPEN;
        !           188:        sc->sc_burst = PPI_BURST;
        !           189:        sc->sc_timo = ppimstohz(PPI_TIMO);
        !           190:        sc->sc_delay = ppimstohz(PPI_DELAY);
        !           191:        sc->sc_sec = -1;
        !           192:        return(0);
        !           193: }
        !           194:
        !           195: int
        !           196: ppiclose(dev, flags, fmt, p)
        !           197:        dev_t dev;
        !           198:        int flags, fmt;
        !           199:        struct proc *p;
        !           200: {
        !           201:        int unit = UNIT(dev);
        !           202:        struct ppi_softc *sc = ppi_cd.cd_devs[unit];
        !           203:
        !           204: #ifdef DEBUG
        !           205:        if (ppidebug & PDB_FOLLOW)
        !           206:                printf("ppiclose(%x, %x): flags %x\n",
        !           207:                       dev, flags, sc->sc_flags);
        !           208: #endif
        !           209:        sc->sc_flags &= ~PPIF_OPEN;
        !           210:        return(0);
        !           211: }
        !           212:
        !           213: void
        !           214: ppistart(arg)
        !           215:        void *arg;
        !           216: {
        !           217:        struct ppi_softc *sc = arg;
        !           218:
        !           219: #ifdef DEBUG
        !           220:        if (ppidebug & PDB_FOLLOW)
        !           221:                printf("ppistart(%x)\n", sc->sc_dev.dv_unit);
        !           222: #endif
        !           223:        sc->sc_flags &= ~PPIF_DELAY;
        !           224:        wakeup(sc);
        !           225: }
        !           226:
        !           227: void
        !           228: ppitimo(arg)
        !           229:        void *arg;
        !           230: {
        !           231:        struct ppi_softc *sc = arg;
        !           232:
        !           233: #ifdef DEBUG
        !           234:        if (ppidebug & PDB_FOLLOW)
        !           235:                printf("ppitimo(%x)\n", sc->sc_dev.dv_unit);
        !           236: #endif
        !           237:        sc->sc_flags &= ~(PPIF_UIO|PPIF_TIMO);
        !           238:        wakeup(sc);
        !           239: }
        !           240:
        !           241: int
        !           242: ppiread(dev, uio, flags)
        !           243:        dev_t dev;
        !           244:        struct uio *uio;
        !           245:        int flags;
        !           246: {
        !           247:
        !           248: #ifdef DEBUG
        !           249:        if (ppidebug & PDB_FOLLOW)
        !           250:                printf("ppiread(%x, %p)\n", dev, uio);
        !           251: #endif
        !           252:        return (ppirw(dev, uio));
        !           253: }
        !           254:
        !           255: int
        !           256: ppiwrite(dev, uio, flags)
        !           257:        dev_t dev;
        !           258:        struct uio *uio;
        !           259:        int flags;
        !           260: {
        !           261:
        !           262: #ifdef DEBUG
        !           263:        if (ppidebug & PDB_FOLLOW)
        !           264:                printf("ppiwrite(%x, %p)\n", dev, uio);
        !           265: #endif
        !           266:        return (ppirw(dev, uio));
        !           267: }
        !           268:
        !           269: int
        !           270: ppirw(dev, uio)
        !           271:        dev_t dev;
        !           272:        struct uio *uio;
        !           273: {
        !           274:        int unit = UNIT(dev);
        !           275:        struct ppi_softc *sc = ppi_cd.cd_devs[unit];
        !           276:        int s, len, cnt;
        !           277:        char *cp;
        !           278:        int error = 0, gotdata = 0;
        !           279:        int buflen, ctlr, slave;
        !           280:        char *buf;
        !           281:
        !           282:        if (uio->uio_resid == 0)
        !           283:                return(0);
        !           284:
        !           285:        ctlr = sc->sc_dev.dv_parent->dv_unit;
        !           286:        slave = sc->sc_slave;
        !           287:
        !           288: #ifdef DEBUG
        !           289:        if (ppidebug & (PDB_FOLLOW|PDB_IO))
        !           290:                printf("ppirw(%x, %p, %c): burst %d, timo %d, resid %x\n",
        !           291:                       dev, uio, uio->uio_rw == UIO_READ ? 'R' : 'W',
        !           292:                       sc->sc_burst, sc->sc_timo, uio->uio_resid);
        !           293: #endif
        !           294:        buflen = min(sc->sc_burst, uio->uio_resid);
        !           295:        buf = (char *)malloc(buflen, M_DEVBUF, M_WAITOK);
        !           296:        sc->sc_flags |= PPIF_UIO;
        !           297:        if (sc->sc_timo > 0) {
        !           298:                sc->sc_flags |= PPIF_TIMO;
        !           299:                timeout_add(&sc->sc_to, sc->sc_timo);
        !           300:        }
        !           301:        len = cnt = 0;
        !           302:        while (uio->uio_resid > 0) {
        !           303:                len = min(buflen, uio->uio_resid);
        !           304:                cp = buf;
        !           305:                if (uio->uio_rw == UIO_WRITE) {
        !           306:                        error = uiomove(cp, len, uio);
        !           307:                        if (error)
        !           308:                                break;
        !           309:                }
        !           310: again:
        !           311:                s = splbio();
        !           312:                if ((sc->sc_flags & PPIF_UIO) &&
        !           313:                    hpibreq(sc->sc_dev.dv_parent, &sc->sc_hq) == 0)
        !           314:                        tsleep(sc, PRIBIO+1, "ppirw", 0);
        !           315:                /*
        !           316:                 * Check if we timed out during sleep or uiomove
        !           317:                 */
        !           318:                if ((sc->sc_flags & PPIF_UIO) == 0) {
        !           319: #ifdef DEBUG
        !           320:                        if (ppidebug & PDB_IO)
        !           321:                                printf("ppirw: uiomove/sleep timo, flags %x\n",
        !           322:                                       sc->sc_flags);
        !           323: #endif
        !           324:                        if (sc->sc_flags & PPIF_TIMO) {
        !           325:                                timeout_del(&sc->sc_to);
        !           326:                                sc->sc_flags &= ~PPIF_TIMO;
        !           327:                        }
        !           328:                        splx(s);
        !           329:                        break;
        !           330:                }
        !           331:                /*
        !           332:                 * Perform the operation
        !           333:                 */
        !           334:                if (uio->uio_rw == UIO_WRITE)
        !           335:                        cnt = hpibsend(ctlr, slave, sc->sc_sec, cp, len);
        !           336:                else
        !           337:                        cnt = hpibrecv(ctlr, slave, sc->sc_sec, cp, len);
        !           338:                hpibfree(sc->sc_dev.dv_parent, &sc->sc_hq);
        !           339: #ifdef DEBUG
        !           340:                if (ppidebug & PDB_IO)
        !           341:                        printf("ppirw: %s(%d, %d, %x, %p, %d) -> %d\n",
        !           342:                               uio->uio_rw == UIO_READ ? "recv" : "send",
        !           343:                               ctlr, slave, sc->sc_sec, cp, len, cnt);
        !           344: #endif
        !           345:                if (uio->uio_rw == UIO_READ) {
        !           346:                        if (cnt) {
        !           347:                                error = uiomove(cp, cnt, uio);
        !           348:                                if (error) {
        !           349:                                        splx(s);
        !           350:                                        break;
        !           351:                                }
        !           352:                                gotdata++;
        !           353:                        }
        !           354:                        /*
        !           355:                         * Didn't get anything this time, but did in the past.
        !           356:                         * Consider us done.
        !           357:                         */
        !           358:                        else if (gotdata) {
        !           359:                                splx(s);
        !           360:                                break;
        !           361:                        }
        !           362:                }
        !           363:                /*
        !           364:                 * Operation timeout (or non-blocking), quit now.
        !           365:                 */
        !           366:                if ((sc->sc_flags & PPIF_UIO) == 0) {
        !           367: #ifdef DEBUG
        !           368:                        if (ppidebug & PDB_IO)
        !           369:                                printf("ppirw: timeout/done\n");
        !           370: #endif
        !           371:                        splx(s);
        !           372:                        break;
        !           373:                }
        !           374:                /*
        !           375:                 * Implement inter-read delay
        !           376:                 */
        !           377:                if (sc->sc_delay > 0) {
        !           378:                        sc->sc_flags |= PPIF_DELAY;
        !           379:                        timeout_add(&sc->sc_start_to, sc->sc_delay);
        !           380:                        error = tsleep(sc, (PCATCH|PZERO) + 1, "hpib", 0);
        !           381:                        if (error) {
        !           382:                                splx(s);
        !           383:                                break;
        !           384:                        }
        !           385:                }
        !           386:                /*
        !           387:                 * Must not call uiomove again til we've used all data
        !           388:                 * that we already grabbed.
        !           389:                 */
        !           390:                if (uio->uio_rw == UIO_WRITE && cnt != len) {
        !           391:                        cp += cnt;
        !           392:                        len -= cnt;
        !           393:                        cnt = 0;
        !           394:                        splx(s);
        !           395:                        goto again;
        !           396:                }
        !           397:                splx(s);
        !           398:        }
        !           399:        if (sc->sc_flags & PPIF_TIMO) {
        !           400:                timeout_del(&sc->sc_to);
        !           401:                sc->sc_flags &= ~PPIF_TIMO;
        !           402:        }
        !           403:        if (sc->sc_flags & PPIF_DELAY) {
        !           404:                timeout_del(&sc->sc_start_to);
        !           405:                sc->sc_flags &= ~PPIF_DELAY;
        !           406:        }
        !           407:        /*
        !           408:         * Adjust for those chars that we uiomove'ed but never wrote
        !           409:         */
        !           410:        if (uio->uio_rw == UIO_WRITE && cnt != len) {
        !           411:                uio->uio_resid += (len - cnt);
        !           412: #ifdef DEBUG
        !           413:                if (ppidebug & PDB_IO)
        !           414:                        printf("ppirw: short write, adjust by %d\n",
        !           415:                               len-cnt);
        !           416: #endif
        !           417:        }
        !           418:        free(buf, M_DEVBUF);
        !           419: #ifdef DEBUG
        !           420:        if (ppidebug & (PDB_FOLLOW|PDB_IO))
        !           421:                printf("ppirw: return %d, resid %d\n", error, uio->uio_resid);
        !           422: #endif
        !           423:        return (error);
        !           424: }
        !           425:
        !           426: int
        !           427: ppiioctl(dev, cmd, data, flag, p)
        !           428:        dev_t dev;
        !           429:        u_long cmd;
        !           430:        caddr_t data;
        !           431:        int flag;
        !           432:        struct proc *p;
        !           433: {
        !           434:        struct ppi_softc *sc = ppi_cd.cd_devs[UNIT(dev)];
        !           435:        struct ppiparam *pp, *upp;
        !           436:        int tmp;
        !           437:        int error = 0;
        !           438:
        !           439:        switch (cmd) {
        !           440:        case PPIIOCGPARAM:
        !           441:                pp = &sc->sc_param;
        !           442:                upp = (struct ppiparam *)data;
        !           443:                upp->burst = pp->burst;
        !           444:                upp->timo = ppihztoms(pp->timo);
        !           445:                upp->delay = ppihztoms(pp->delay);
        !           446:                break;
        !           447:        case PPIIOCSPARAM:
        !           448:                pp = &sc->sc_param;
        !           449:                upp = (struct ppiparam *)data;
        !           450:                if (upp->burst < PPI_BURST_MIN || upp->burst > PPI_BURST_MAX ||
        !           451:                    upp->delay < PPI_DELAY_MIN || upp->delay > PPI_DELAY_MAX)
        !           452:                        return(EINVAL);
        !           453:                pp->burst = upp->burst;
        !           454:                pp->timo = ppimstohz(upp->timo);
        !           455:                pp->delay = ppimstohz(upp->delay);
        !           456:                break;
        !           457:        case PPIIOCSSEC:
        !           458:                tmp = *(int *)data;
        !           459:                if (tmp == -1 || (tmp >= 0 && tmp <= 0x1f))
        !           460:                        sc->sc_sec = tmp;
        !           461:                else
        !           462:                        error = EINVAL;
        !           463:                break;
        !           464:        default:
        !           465:                return (ENOTTY);
        !           466:        }
        !           467:        return (error);
        !           468: }
        !           469:
        !           470: int
        !           471: ppihztoms(h)
        !           472:        int h;
        !           473: {
        !           474:        int m = h;
        !           475:
        !           476:        if (m > 0)
        !           477:                m = m * 1000 / hz;
        !           478:        return(m);
        !           479: }
        !           480:
        !           481: int
        !           482: ppimstohz(m)
        !           483:        int m;
        !           484: {
        !           485:        int h = m;
        !           486:
        !           487:        if (h > 0) {
        !           488:                h = h * hz / 1000;
        !           489:                if (h == 0)
        !           490:                        h = 1000 / hz;
        !           491:        }
        !           492:        return(h);
        !           493: }

CVSweb