Annotation of sys/arch/sparc/dev/daadio.c, Revision 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)®s->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