[BACK]Return to satlink.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / isa

Annotation of src/sys/dev/isa/satlink.c, Revision 1.13.2.1

1.13.2.1! fvdl        1: /*     $NetBSD: satlink.c,v 1.13 2001/07/18 20:52:48 thorpej Exp $     */
1.4       thorpej     2:
1.1       hpeyerl     3: /*-
                      4:  * Copyright (c) 1997 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Canada Connect Corp.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the NetBSD
                     21:  *     Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
1.2       jtc        29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1.1       hpeyerl    31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
                     38:
                     39: /*
                     40:  * Device driver for SatLink interface.
                     41:  *
                     42:  * This thing is really simple.  We essentially DMA into a ring buffer
                     43:  * which the user then reads from, and provide an ioctl interface to
                     44:  * reset the card, etc.
                     45:  */
                     46:
                     47: #include <sys/param.h>
                     48: #include <sys/systm.h>
1.9       thorpej    49: #include <sys/callout.h>
1.1       hpeyerl    50: #include <sys/errno.h>
                     51: #include <sys/ioctl.h>
                     52: #include <sys/device.h>
                     53: #include <sys/conf.h>
                     54: #include <sys/proc.h>
                     55: #include <sys/uio.h>
                     56: #include <sys/select.h>
                     57: #include <sys/poll.h>
                     58: #include <sys/kernel.h>
                     59: #include <sys/file.h>
                     60: #include <sys/tty.h>
1.13.2.1! fvdl       61: #include <sys/vnode.h>
1.1       hpeyerl    62:
                     63: #include <machine/cpu.h>
                     64: #include <machine/bus.h>
                     65: #include <machine/intr.h>
                     66:
                     67: #include <dev/isa/isareg.h>
                     68: #include <dev/isa/isavar.h>
                     69: #include <dev/isa/isadmavar.h>
                     70:
                     71: #include <dev/isa/satlinkreg.h>
                     72: #include <dev/isa/satlinkio.h>
                     73:
                     74: struct satlink_softc {
                     75:        struct  device sc_dev;          /* device glue */
                     76:        bus_space_tag_t sc_iot;         /* space tag */
                     77:        bus_space_handle_t sc_ioh;      /* space handle */
1.6       thorpej    78:        isa_chipset_tag_t sc_ic;        /* ISA chipset info */
1.1       hpeyerl    79:        int     sc_drq;                 /* the DRQ we're using */
1.8       thorpej    80:        bus_size_t sc_bufsize;          /* DMA buffer size */
1.1       hpeyerl    81:        caddr_t sc_buf;                 /* ring buffer for incoming data */
                     82:        int     sc_uptr;                /* user index into ring buffer */
                     83:        int     sc_sptr;                /* satlink index into ring buffer */
                     84:        int     sc_flags;               /* misc. flags. */
                     85:        int     sc_lastresid;           /* residual */
                     86:        struct selinfo sc_selq;         /* our select/poll queue */
                     87:        struct  satlink_id sc_id;       /* ID cached at attach time */
1.9       thorpej    88:        struct callout sc_ch;           /* callout pseudo-interrupt */
1.1       hpeyerl    89: };
                     90:
                     91: /* sc_flags */
                     92: #define        SATF_ISOPEN             0x01    /* device is open */
                     93: #define        SATF_DATA               0x02    /* waiting for data */
                     94:
                     95: /*
                     96:  * Our pesudo-interrupt.  Since up to 328 bytes can arrive in 1/100 of
                     97:  * a second, this gives us 3280 bytes per timeout.
                     98:  */
1.8       thorpej    99: #define        SATLINK_TIMEOUT         (hz/10)
1.1       hpeyerl   100:
                    101: int    satlinkprobe __P((struct device *, struct cfdata *, void *));
                    102: void   satlinkattach __P((struct device *, struct device *, void *));
                    103: void   satlinktimeout __P((void *));
                    104:
                    105: struct cfattach satlink_ca = {
                    106:        sizeof(struct satlink_softc), satlinkprobe, satlinkattach
                    107: };
                    108:
1.4       thorpej   109: extern struct cfdriver satlink_cd;
1.1       hpeyerl   110:
                    111: cdev_decl(satlink);
                    112:
                    113: int
                    114: satlinkprobe(parent, match, aux)
                    115:        struct device *parent;
                    116:        struct cfdata *match;
                    117:        void *aux;
                    118: {
                    119:        struct isa_attach_args *ia = aux;
                    120:        bus_space_tag_t iot = ia->ia_iot;
                    121:        bus_space_handle_t ioh;
                    122:        int rv = 0;
                    123:
                    124:        /* Don't allow wildcarding of iobase or drq. */
1.3       thorpej   125:        if (ia->ia_iobase == ISACF_PORT_DEFAULT)
1.1       hpeyerl   126:                return (0);
1.3       thorpej   127:        if (ia->ia_drq == ISACF_DRQ_DEFAULT)
1.1       hpeyerl   128:                return (0);
                    129:
                    130:        if (bus_space_map(iot, ia->ia_iobase, SATLINK_IOSIZE, 0, &ioh))
                    131:                return (0);
                    132:
                    133:        /*
                    134:         * XXX Should check manufacturer ID here, or something.
                    135:         */
                    136:
                    137:        rv = 1;
                    138:        ia->ia_iosize = SATLINK_IOSIZE;
                    139:        ia->ia_msize = 0;
                    140:
                    141:        bus_space_unmap(iot, ioh, SATLINK_IOSIZE);
                    142:        return (rv);
                    143: }
                    144:
                    145: void
                    146: satlinkattach(parent, self, aux)
                    147:        struct device *parent, *self;
                    148:        void *aux;
                    149: {
                    150:        struct satlink_softc *sc = (struct satlink_softc *)self;
                    151:        struct isa_attach_args *ia = aux;
                    152:        bus_space_tag_t iot = ia->ia_iot;
                    153:        bus_space_handle_t ioh;
                    154:        bus_addr_t ringaddr;
                    155:
                    156:        printf("\n");
                    157:
                    158:        /* Map the card. */
                    159:        if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) {
                    160:                printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
                    161:                return;
                    162:        }
                    163:
                    164:        sc->sc_iot = iot;
                    165:        sc->sc_ioh = ioh;
1.6       thorpej   166:        sc->sc_ic = ia->ia_ic;
1.1       hpeyerl   167:        sc->sc_drq = ia->ia_drq;
                    168:
                    169:        /* Reset the card. */
                    170:        bus_space_write_1(iot, ioh, SATLINK_COMMAND, SATLINK_CMD_RESET);
                    171:
                    172:        /* Read ID from the card. */
                    173:        sc->sc_id.sid_mfrid =
                    174:            bus_space_read_1(iot, ioh, SATLINK_MFRID_L) |
                    175:            (bus_space_read_1(iot, ioh, SATLINK_MFRID_H) << 8);
                    176:        sc->sc_id.sid_grpid = bus_space_read_1(iot, ioh, SATLINK_GRPID);
                    177:        sc->sc_id.sid_userid =
                    178:            bus_space_read_1(iot, ioh, SATLINK_USERID_L) |
                    179:            (bus_space_read_1(iot, ioh, SATLINK_USERID_H) << 8);
                    180:        sc->sc_id.sid_serial =
                    181:            bus_space_read_1(iot, ioh, SATLINK_SER_L) |
                    182:            (bus_space_read_1(iot, ioh, SATLINK_SER_M0) << 8) |
                    183:            (bus_space_read_1(iot, ioh, SATLINK_SER_M1) << 16) |
                    184:            (bus_space_read_1(iot, ioh, SATLINK_SER_H) << 24);
                    185:
                    186:        printf("%s: mfrid 0x%x, grpid 0x%x, userid 0x%x, serial %d\n",
                    187:            sc->sc_dev.dv_xname, sc->sc_id.sid_mfrid,
                    188:            sc->sc_id.sid_grpid, sc->sc_id.sid_userid,
                    189:            sc->sc_id.sid_serial);
                    190:
1.10      thorpej   191:        callout_init(&sc->sc_ch);
1.9       thorpej   192:
1.8       thorpej   193:        sc->sc_bufsize = isa_dmamaxsize(sc->sc_ic, sc->sc_drq);
                    194:
1.1       hpeyerl   195:        /* Allocate and map the ring buffer. */
1.8       thorpej   196:        if (isa_dmamem_alloc(sc->sc_ic, sc->sc_drq, sc->sc_bufsize,
1.1       hpeyerl   197:            &ringaddr, BUS_DMA_NOWAIT)) {
                    198:                printf("%s: can't allocate ring buffer\n",
                    199:                    sc->sc_dev.dv_xname);
                    200:                return;
                    201:        }
1.8       thorpej   202:        if (isa_dmamem_map(sc->sc_ic, sc->sc_drq, ringaddr, sc->sc_bufsize,
1.5       thorpej   203:            &sc->sc_buf, BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) {
1.1       hpeyerl   204:                printf("%s: can't map ring buffer\n", sc->sc_dev.dv_xname);
1.6       thorpej   205:                isa_dmamem_free(sc->sc_ic, sc->sc_drq, ringaddr,
1.8       thorpej   206:                    sc->sc_bufsize);
1.1       hpeyerl   207:                return;
                    208:        }
                    209:
                    210:        /* Create the DMA map. */
1.8       thorpej   211:        if (isa_dmamap_create(sc->sc_ic, sc->sc_drq, sc->sc_bufsize,
1.1       hpeyerl   212:            BUS_DMA_NOWAIT)) {
                    213:                printf("%s: can't create DMA map\n", sc->sc_dev.dv_xname);
1.6       thorpej   214:                isa_dmamem_unmap(sc->sc_ic, sc->sc_drq, sc->sc_buf,
1.8       thorpej   215:                    sc->sc_bufsize);
1.6       thorpej   216:                isa_dmamem_free(sc->sc_ic, sc->sc_drq, ringaddr,
1.8       thorpej   217:                    sc->sc_bufsize);
1.1       hpeyerl   218:                return;
                    219:        }
                    220: }
                    221:
                    222: int
1.13.2.1! fvdl      223: satlinkopen(devvp, flags, fmt, p)
        !           224:        struct vnode *devvp;
1.1       hpeyerl   225:        int flags, fmt;
                    226:        struct proc *p;
                    227: {
                    228:        struct satlink_softc *sc;
1.11      thorpej   229:        int error;
1.13.2.1! fvdl      230:        dev_t dev;
1.1       hpeyerl   231:
1.13.2.1! fvdl      232:        dev = vdev_rdev(devvp);
1.11      thorpej   233:        sc = device_lookup(&satlink_cd, minor(dev));
                    234:        if (sc == NULL)
1.1       hpeyerl   235:                return (ENXIO);
                    236:
                    237:        if (sc->sc_flags & SATF_ISOPEN)
                    238:                return (EBUSY);
                    239:
                    240:        bus_space_write_1(sc->sc_iot, sc->sc_ioh, SATLINK_COMMAND,
                    241:                    SATLINK_CMD_RESET);
                    242:
                    243:        /* Reset the ring buffer, and start the DMA loop. */
                    244:        sc->sc_uptr = 0;
                    245:        sc->sc_sptr = 0;
1.8       thorpej   246:        sc->sc_lastresid = sc->sc_bufsize;
1.12      thorpej   247:        memset(sc->sc_buf, 0, sc->sc_bufsize);
1.6       thorpej   248:        error = isa_dmastart(sc->sc_ic, sc->sc_drq, sc->sc_buf,
1.8       thorpej   249:            sc->sc_bufsize, NULL, DMAMODE_READ|DMAMODE_LOOP, BUS_DMA_WAITOK);
1.1       hpeyerl   250:        if (error)
                    251:                return (error);
                    252:
1.13.2.1! fvdl      253:        vdev_setprivdata(devvp, sc);
        !           254:
1.1       hpeyerl   255:        sc->sc_flags |= SATF_ISOPEN;
                    256:
1.9       thorpej   257:        callout_reset(&sc->sc_ch, SATLINK_TIMEOUT, satlinktimeout, sc);
1.1       hpeyerl   258:
                    259:        return (0);
                    260: }
                    261:
                    262: int
1.13.2.1! fvdl      263: satlinkclose(devvp, flags, fmt, p)
        !           264:        struct vnode *devvp;
1.1       hpeyerl   265:        int flags, fmt;
                    266:        struct proc *p;
                    267: {
1.13.2.1! fvdl      268:        struct satlink_softc *sc = vdev_privdata(devvp);
1.1       hpeyerl   269:        int s;
                    270:
                    271:        s = splsoftclock();
                    272:        sc->sc_flags &= ~SATF_ISOPEN;
                    273:        splx(s);
                    274:
1.6       thorpej   275:        isa_dmaabort(sc->sc_ic, sc->sc_drq);
1.9       thorpej   276:        callout_stop(&sc->sc_ch);
1.1       hpeyerl   277:
                    278:        return (0);
                    279: }
                    280:
                    281: int
1.13.2.1! fvdl      282: satlinkread(devvp, uio, flags)
        !           283:        struct vnode *devvp;
1.1       hpeyerl   284:        struct uio *uio;
                    285:        int flags;
                    286: {
1.13.2.1! fvdl      287:        struct satlink_softc *sc = vdev_privdata(devvp);
1.1       hpeyerl   288:        int error, s, count, sptr;
                    289:        int wrapcnt, oresid;
                    290:
                    291:        s = splsoftclock();
                    292:
                    293:        /* Wait for data to be available. */
                    294:        while (sc->sc_sptr == sc->sc_uptr) {
                    295:                if (flags & O_NONBLOCK) {
                    296:                        splx(s);
                    297:                        return (EWOULDBLOCK);
                    298:                }
                    299:                sc->sc_flags |= SATF_DATA;
                    300:                if ((error = tsleep(sc, TTIPRI | PCATCH, "satio", 0)) != 0) {
                    301:                        splx(s);
                    302:                        return (error);
                    303:                }
                    304:        }
                    305:
                    306:        sptr = sc->sc_sptr;
                    307:        splx(s);
                    308:
                    309:        /* Compute number of readable bytes. */
                    310:        if (sptr > sc->sc_uptr)
                    311:                count = sptr - sc->sc_uptr;
                    312:        else
1.8       thorpej   313:                count = sc->sc_bufsize - sc->sc_uptr + sptr;
1.1       hpeyerl   314:
                    315:        if (count > uio->uio_resid)
                    316:                count = uio->uio_resid;
                    317:
                    318:        /* Send data out to user. */
                    319:        if (sptr > sc->sc_uptr) {
                    320:                /*
                    321:                 * Easy case - no wrap-around.
                    322:                 */
                    323:                error = uiomove(&sc->sc_buf[sc->sc_uptr], count, uio);
                    324:                if (error == 0) {
                    325:                        sc->sc_uptr += count;
1.8       thorpej   326:                        if (sc->sc_uptr == sc->sc_bufsize)
1.1       hpeyerl   327:                                sc->sc_uptr = 0;
                    328:                }
                    329:                return (error);
                    330:        }
                    331:
                    332:        /*
                    333:         * We wrap around.  Copy to the end of the ring...
                    334:         */
1.8       thorpej   335:        wrapcnt = sc->sc_bufsize - sc->sc_uptr;
1.1       hpeyerl   336:        oresid = uio->uio_resid;
                    337:        if (wrapcnt > uio->uio_resid)
                    338:                wrapcnt = uio->uio_resid;
                    339:        error = uiomove(&sc->sc_buf[sc->sc_uptr], wrapcnt, uio);
                    340:        sc->sc_uptr = 0;
                    341:        if (error != 0 || wrapcnt == oresid)
                    342:                return (error);
                    343:
                    344:        /* ...and the rest. */
                    345:        count -= wrapcnt;
                    346:        error = uiomove(sc->sc_buf, count, uio);
                    347:        sc->sc_uptr += count;
1.8       thorpej   348:        if (sc->sc_uptr == sc->sc_bufsize)
1.1       hpeyerl   349:                sc->sc_uptr = 0;
                    350:
                    351:        return (error);
                    352: }
                    353:
                    354: int
1.13.2.1! fvdl      355: satlinkwrite(devvp, uio, flags)
        !           356:        struct vnode *devvp;
1.1       hpeyerl   357:        struct uio *uio;
                    358:        int flags;
                    359: {
                    360:
                    361:        return (ENODEV);
                    362: }
                    363:
                    364: int
1.13.2.1! fvdl      365: satlinkioctl(devvp, cmd, data, flags, p)
        !           366:        struct vnode *devvp;
1.1       hpeyerl   367:        u_long cmd;
                    368:        caddr_t data;
                    369:        int flags;
                    370:        struct proc *p;
                    371: {
1.13.2.1! fvdl      372:        struct satlink_softc *sc = vdev_privdata(devvp);
1.1       hpeyerl   373:
                    374:        switch (cmd) {
                    375:        case SATIORESET:
                    376:                bus_space_write_1(sc->sc_iot, sc->sc_ioh, SATLINK_COMMAND,
                    377:                    SATLINK_CMD_RESET);
1.6       thorpej   378:                sc->sc_uptr = isa_dmacount(sc->sc_ic, sc->sc_drq);
1.1       hpeyerl   379:                sc->sc_sptr = sc->sc_uptr;
                    380:                break;
                    381:
                    382:        case SATIOGID:
1.13      thorpej   383:                memcpy(data, &sc->sc_id, sizeof(sc->sc_id));
1.1       hpeyerl   384:                break;
                    385:
                    386:        default:
                    387:                return (ENOTTY);
                    388:        }
                    389:
                    390:        return (0);
                    391: }
                    392:
                    393: int
1.13.2.1! fvdl      394: satlinkpoll(devvp, events, p)
        !           395:        struct vnode *devvp;
1.1       hpeyerl   396:        int events;
                    397:        struct proc *p;
                    398: {
1.13.2.1! fvdl      399:        struct satlink_softc *sc = vdev_privdata(devvp);
1.1       hpeyerl   400:        int s, revents;
                    401:
                    402:        revents = events & (POLLOUT | POLLWRNORM);
                    403:
                    404:        /* Attempt to save some work. */
                    405:        if ((events & (POLLIN | POLLRDNORM)) == 0)
                    406:                return (revents);
                    407:
                    408:        /* We're timeout-driven, so must block the clock. */
                    409:        s = splsoftclock();
                    410:        if (sc->sc_uptr != sc->sc_sptr)
                    411:                revents |= events & (POLLIN | POLLRDNORM);
                    412:        else
                    413:                selrecord(p, &sc->sc_selq);
                    414:        splx(s);
                    415:
                    416:        return (revents);
                    417: }
                    418:
                    419: void
                    420: satlinktimeout(arg)
                    421:        void *arg;
                    422: {
                    423:        struct satlink_softc *sc = arg;
                    424:        bus_size_t resid;
                    425:        int newidx;
                    426:
                    427:        if ((sc->sc_flags & SATF_ISOPEN) == 0)
                    428:                return;
                    429:
                    430:        /*
                    431:         * Get the current residual count from the DMA controller
                    432:         * and compute the satlink's index into the ring buffer.
                    433:         */
1.6       thorpej   434:        resid = isa_dmacount(sc->sc_ic, sc->sc_drq);
1.8       thorpej   435:        newidx = sc->sc_bufsize - resid;
                    436:        if (newidx == sc->sc_bufsize)
1.1       hpeyerl   437:                newidx = 0;
                    438:
                    439:        if (newidx == sc->sc_sptr)
                    440:                goto out;
                    441:
                    442:        sc->sc_sptr = newidx;
                    443:
                    444:        /* Wake up anyone blocked in read... */
                    445:        if (sc->sc_flags & SATF_DATA) {
                    446:                sc->sc_flags &= ~SATF_DATA;
                    447:                wakeup(sc);
                    448:        }
                    449:
                    450:        /* Wake up anyone blocked in poll... */
                    451:        selwakeup(&sc->sc_selq);
                    452:
                    453:  out:
1.9       thorpej   454:        callout_reset(&sc->sc_ch, SATLINK_TIMEOUT, satlinktimeout, sc);
1.1       hpeyerl   455: }

CVSweb <webmaster@jp.NetBSD.org>