[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

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