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

Annotation of sys/arch/sparc/dev/daadio.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: daadio.c,v 1.6 2004/09/29 07:35:11 miod Exp $ */
                      2:
                      3: /*
                      4:  * Copyright (c) 1999 Jason L. Wright (jason@thought.net)
                      5:  * All rights reserved.
                      6:  *
                      7:  * This software was developed by Jason L. Wright under contract with
                      8:  * RTMX Incorporated (http://www.rtmx.com).
                      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:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     20:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     21:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     22:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     23:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     24:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     25:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     27:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     28:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: /*
                     33:  * Driver for the MATRIX Corporation MD-DAADIO digital->analog,
                     34:  * analog->digial, parallel i/o VME board.
                     35:  */
                     36:
                     37: #include <sys/param.h>
                     38: #include <sys/systm.h>
                     39: #include <sys/kernel.h>
                     40: #include <sys/errno.h>
                     41: #include <sys/ioctl.h>
                     42: #include <sys/syslog.h>
                     43: #include <sys/device.h>
                     44: #include <sys/malloc.h>
                     45: #include <sys/conf.h>
                     46: #include <sys/fcntl.h>
                     47: #include <sys/proc.h>
                     48:
                     49: #include <machine/autoconf.h>
                     50: #include <sparc/cpu.h>
                     51: #include <sparc/sparc/cpuvar.h>
                     52: #include <sparc/dev/sbusvar.h>
                     53: #include <sparc/dev/dmareg.h>  /* for SBUS_BURST_* */
                     54: #include <machine/daadioio.h>
                     55:
                     56: #include <sparc/dev/fgareg.h>
                     57: #include <sparc/dev/fgavar.h>
                     58: #include <sparc/dev/daadioreg.h>
                     59:
                     60: int    daadiomatch(struct device *, void *, void *);
                     61: void   daadioattach(struct device *, struct device *, void *);
                     62: int    daadiointr(void *);
                     63:
                     64: struct daadio_softc {
                     65:        struct          device sc_dv;           /* base device */
                     66:        struct          daadioregs *sc_regs;    /* registers */
                     67:        struct          intrhand sc_ih;         /* interrupt vectoring */
                     68:        struct          daadio_adc *sc_adc_p;
                     69:        int             sc_adc_done;
                     70:        int             sc_flags;               /* flags */
                     71: #define        DAF_LOCKED      0x1
                     72: #define        DAF_WANTED      0x2
                     73:        u_int16_t       sc_adc_val;
                     74:        u_int8_t        sc_ier;                 /* software copy of ier */
                     75: };
                     76:
                     77: struct cfattach daadio_ca = {
                     78:        sizeof (struct daadio_softc), daadiomatch, daadioattach
                     79: };
                     80:
                     81: struct cfdriver daadio_cd = {
                     82:        NULL, "daadio", DV_DULL
                     83: };
                     84:
                     85: void   daadio_ier_setbit(struct daadio_softc *, u_int8_t);
                     86: void   daadio_ier_clearbit(struct daadio_softc *, u_int8_t);
                     87: int    daadio_adc(struct daadio_softc *, struct daadio_adc *);
                     88:
                     89: int    daadioopen(dev_t, int, int, struct proc *);
                     90: int    daadioclose(dev_t, int, int, struct proc *);
                     91: int    daadioioctl(dev_t, u_long, caddr_t, int, struct proc *);
                     92:
                     93: int
                     94: daadiomatch(parent, vcf, aux)
                     95:        struct device *parent;
                     96:        void *vcf, *aux;
                     97: {
                     98:        struct cfdata *cf = vcf;
                     99:        struct confargs *ca = aux;
                    100:        struct daadioregs *regs;
                    101:
                    102:        if (ca->ca_bustype != BUS_FGA_A16D16)
                    103:                return (0);
                    104:
                    105:        if (strcmp(ca->ca_ra.ra_name, cf->cf_driver->cd_name))
                    106:                return (0);
                    107:
                    108:        if (ca->ca_ra.ra_reg[0].rr_len < sizeof(struct daadioboard))
                    109:                return (0);
                    110:
                    111:        regs = ca->ca_ra.ra_reg[0].rr_paddr;
                    112:        if (probeget((caddr_t)&regs->sid, 1) != -1)
                    113:                return (1);
                    114:
                    115:        return (0);
                    116: }
                    117:
                    118: void
                    119: daadioattach(parent, self, aux)
                    120:        struct device *parent, *self;
                    121:        void *aux;
                    122: {
                    123:        struct confargs *ca = aux;
                    124:        struct daadio_softc *sc = (struct daadio_softc *)self;
                    125:
                    126:        sc->sc_regs = mapiodev(&(ca->ca_ra.ra_reg[0]), 0,
                    127:            sizeof(struct daadioboard));
                    128:
                    129:        sc->sc_regs->pio_pattern = sc->sc_regs->pio_porta;
                    130:        sc->sc_regs->sid = ca->ca_ra.ra_intr[0].int_vec;
                    131:        sc->sc_regs->gvrilr &= ~ILR_IRQ_MASK;
                    132:        sc->sc_regs->gvrilr |= (ca->ca_ra.ra_intr[0].int_pri << ILR_IRQ_SHIFT)
                    133:            & ILR_IRQ_MASK;
                    134:        sc->sc_ih.ih_fun = daadiointr;
                    135:        sc->sc_ih.ih_arg = sc;
                    136:        fvmeintrestablish(parent, ca->ca_ra.ra_intr[0].int_vec,
                    137:            ca->ca_ra.ra_intr[0].int_pri, &sc->sc_ih, self->dv_xname);
                    138:        daadio_ier_setbit(sc, IER_PIOEVENT);
                    139:        daadio_ier_setbit(sc, IER_CONVERSION);
                    140:
                    141:        printf(": level %d vec 0x%x\n",
                    142:            ca->ca_ra.ra_intr[0].int_pri, ca->ca_ra.ra_intr[0].int_vec);
                    143: }
                    144:
                    145: int
                    146: daadiointr(vsc)
                    147:        void *vsc;
                    148: {
                    149:        struct daadio_softc *sc = vsc;
                    150:        struct daadioregs *regs = sc->sc_regs;
                    151:        u_int8_t val, isr;
                    152:        int r = 0;
                    153:
                    154:        isr = regs->isr;
                    155:
                    156:        if (isr & ISR_PIOEVENT) {
                    157:                val = regs->pio_porta;
                    158:                printf("pio value: %x\n", val);
                    159:                r = 1;
                    160:                regs->pio_pattern = val;
                    161:        }
                    162:
                    163:        if (isr & ISR_CONVERSION) {
                    164:                r = 1;
                    165:                sc->sc_adc_val = sc->sc_regs->adc12bit[0];
                    166:                sc->sc_adc_done = 1;
                    167:                if (sc->sc_adc_p != NULL)
                    168:                        wakeup(sc->sc_adc_p);
                    169:        }
                    170:
                    171:        return (r);
                    172: }
                    173:
                    174: void
                    175: daadio_ier_setbit(sc, v)
                    176:        struct daadio_softc *sc;
                    177:        u_int8_t v;
                    178: {
                    179:        sc->sc_ier |= v;
                    180:        sc->sc_regs->ier = sc->sc_ier;
                    181: }
                    182:
                    183: void
                    184: daadio_ier_clearbit(sc, v)
                    185:        struct daadio_softc *sc;
                    186:        u_int8_t v;
                    187: {
                    188:        sc->sc_ier &= ~v;
                    189:        sc->sc_regs->ier = sc->sc_ier;
                    190: }
                    191:
                    192: #define        DAADIO_CARD(d)  ((minor(d) >> 6) & 3)
                    193:
                    194: int
                    195: daadioopen(dev, flags, mode, p)
                    196:        dev_t dev;
                    197:        int flags, mode;
                    198:        struct proc *p;
                    199: {
                    200:        struct daadio_softc *sc;
                    201:        int card = DAADIO_CARD(dev);
                    202:
                    203:        if (card >= daadio_cd.cd_ndevs)
                    204:                return (ENXIO);
                    205:        sc = daadio_cd.cd_devs[card];
                    206:        if (sc == NULL)
                    207:                return (ENXIO);
                    208:        return (0);
                    209: }
                    210:
                    211: int
                    212: daadioclose(dev, flags, mode, p)
                    213:        dev_t dev;
                    214:        int flags, mode;
                    215:        struct proc *p;
                    216: {
                    217:        return (0);
                    218: }
                    219:
                    220: int
                    221: daadioioctl(dev, cmd, data, flags, p)
                    222:        dev_t dev;
                    223:        u_long cmd;
                    224:        caddr_t data;
                    225:        int flags;
                    226:        struct proc *p;
                    227: {
                    228:        struct daadio_softc *sc = daadio_cd.cd_devs[DAADIO_CARD(dev)];
                    229:        struct daadio_adc *adc = (struct daadio_adc *)data;
                    230:        struct daadio_dac *dac = (struct daadio_dac *)data;
                    231:        struct daadio_pio *pio = (struct daadio_pio *)data;
                    232:        int error = 0;
                    233:        u_int8_t reg, val;
                    234:
                    235:        switch (cmd) {
                    236:        case DIOGADC:
                    237:                error = daadio_adc(sc, adc);
                    238:                break;
                    239:        case DIOGPIO:
                    240:                switch (pio->dap_reg) {
                    241:                case 0:
                    242:                        pio->dap_val = sc->sc_regs->pio_porta;
                    243:                        break;
                    244:                case 1:
                    245:                        pio->dap_val = sc->sc_regs->pio_portb;
                    246:                        break;
                    247:                case 2:
                    248:                        pio->dap_val = sc->sc_regs->pio_portc;
                    249:                        break;
                    250:                case 3:
                    251:                        pio->dap_val = sc->sc_regs->pio_portd;
                    252:                        break;
                    253:                case 4:
                    254:                        pio->dap_val = sc->sc_regs->pio_porte;
                    255:                        break;
                    256:                case 5:
                    257:                        pio->dap_val = sc->sc_regs->pio_portf;
                    258:                        break;
                    259:                default:
                    260:                        error = EINVAL;
                    261:                        break;
                    262:                }
                    263:                break;
                    264:        case DIOSPIO:
                    265:                if ((flags & FWRITE) == 0) {
                    266:                        error = EPERM;
                    267:                        break;
                    268:                }
                    269:                switch (pio->dap_reg) {
                    270:                case 0:
                    271:                        sc->sc_regs->pio_porta = pio->dap_val;
                    272:                        break;
                    273:                case 1:
                    274:                        sc->sc_regs->pio_portb = pio->dap_val;
                    275:                        break;
                    276:                case 2:
                    277:                        sc->sc_regs->pio_portc = pio->dap_val;
                    278:                        break;
                    279:                case 3:
                    280:                        sc->sc_regs->pio_portd = pio->dap_val;
                    281:                        break;
                    282:                case 4:
                    283:                        sc->sc_regs->pio_porte = pio->dap_val;
                    284:                        break;
                    285:                case 5:
                    286:                        sc->sc_regs->pio_portf = pio->dap_val;
                    287:                        break;
                    288:                default:
                    289:                        error = EINVAL;
                    290:                        break;
                    291:                }
                    292:                break;
                    293:        case DIOSOPIO:
                    294:                if ((flags & FWRITE) == 0) {
                    295:                        error = EPERM;
                    296:                        break;
                    297:                }
                    298:                if (pio->dap_reg >= 6) {
                    299:                        error = EINVAL;
                    300:                        break;
                    301:                }
                    302:
                    303:                reg = sc->sc_regs->pio_oc;
                    304:                val = (1 << pio->dap_reg);
                    305:
                    306:                if (pio->dap_val)
                    307:                        reg |= val;
                    308:                else
                    309:                        reg &= ~val;
                    310:
                    311:                sc->sc_regs->pio_oc = reg;
                    312:                break;
                    313:        case DIOGOPIO:
                    314:                if (pio->dap_reg >= 6) {
                    315:                        error = EINVAL;
                    316:                        break;
                    317:                }
                    318:
                    319:                reg = sc->sc_regs->pio_oc;
                    320:                val = (1 << pio->dap_reg);
                    321:
                    322:                if ((reg & val) != 0)
                    323:                        pio->dap_val = 1;
                    324:                else
                    325:                        pio->dap_val = 0;
                    326:                break;
                    327:        case DIOSDAC:
                    328:                if ((flags & FWRITE) == 0) {
                    329:                        error = EPERM;
                    330:                        break;
                    331:                }
                    332:                if (dac->dac_reg >= 8) {
                    333:                        error = EINVAL;
                    334:                        break;
                    335:                }
                    336:                sc->sc_regs->dac_channel[dac->dac_reg] = dac->dac_val;
                    337:                break;
                    338:        default:
                    339:                error = ENOTTY;
                    340:        }
                    341:
                    342:        return (error);
                    343: }
                    344:
                    345: int
                    346: daadio_adc(sc, adc)
                    347:        struct daadio_softc *sc;
                    348:        struct daadio_adc *adc;
                    349: {
                    350:        int s, err = 0;
                    351:
                    352:        if (adc->dad_reg >= 32)
                    353:                return (EINVAL);
                    354:
                    355:        s = splhigh();
                    356:
                    357:        /* Lock device. */
                    358:        while ((sc->sc_flags & DAF_LOCKED) != 0) {
                    359:                sc->sc_flags |= DAF_WANTED;
                    360:                if ((err = tsleep(sc, PWAIT, "daadio", 0)) != 0)
                    361:                        goto out;
                    362:        }
                    363:        sc->sc_flags |= DAF_LOCKED;
                    364:
                    365:        /* Start conversion. */
                    366:        sc->sc_adc_done = 0;
                    367:        sc->sc_adc_p = adc;
                    368:        sc->sc_regs->adc12bit[adc->dad_reg] = 0;
                    369:
                    370:        /* Wait for conversion. */
                    371:        while (sc->sc_adc_done == 0)
                    372:                if ((err = tsleep(sc->sc_adc_p, PWAIT, "daadio", 0)) != 0)
                    373:                        goto out;
                    374:        sc->sc_adc_p = NULL;
                    375:        adc->dad_val = sc->sc_adc_val;
                    376:
                    377:        /* Unlock device. */
                    378:        sc->sc_flags &= ~DAF_LOCKED;
                    379:        if (sc->sc_flags & DAF_WANTED) {
                    380:                sc->sc_flags &= ~DAF_WANTED;
                    381:                wakeup(sc);
                    382:        }
                    383:
                    384: out:
                    385:        splx(s);
                    386:        return (err);
                    387: }

CVSweb