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)®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