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>