Date: Fri, 15 Dec 2006 00:13:12 GMT From: Warner Losh <imp@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 111716 for review Message-ID: <200612150013.kBF0DCvV055007@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=111716 Change 111716 by imp@imp_lighthouse on 2006/12/15 00:12:31 Implement kinky interrupt read channel. Affected files ... .. //depot/projects/arm/src/sys/arm/at91/at91_pio.c#24 edit Differences ... ==== //depot/projects/arm/src/sys/arm/at91/at91_pio.c#24 (text+ko) ==== @@ -37,12 +37,15 @@ #include <sys/module.h> #include <sys/mutex.h> #include <sys/rman.h> +#include <sys/uio.h> #include <machine/bus.h> #include <arm/at91/at91rm92reg.h> #include <arm/at91/at91_pioreg.h> #include <arm/at91/at91_piovar.h> +#define MAX_CHANGE 64 + struct at91_pio_softc { device_t dev; /* Myself */ @@ -51,6 +54,8 @@ struct resource *mem_res; /* Memory resource */ struct mtx sc_mtx; /* basically a perimeter lock */ struct cdev *cdev; + int buflen; + uint8_t buf[MAX_CHANGE]; int flags; #define OPENED 1 }; @@ -93,6 +98,7 @@ /* cdev routines */ static d_open_t at91_pio_open; static d_close_t at91_pio_close; +static d_read_t at91_pio_read; static d_ioctl_t at91_pio_ioctl; static struct cdevsw at91_pio_cdevsw = @@ -100,6 +106,7 @@ .d_version = D_VERSION, .d_open = at91_pio_open, .d_close = at91_pio_close, + .d_read = at91_pio_read, .d_ioctl = at91_pio_ioctl }; @@ -222,16 +229,24 @@ at91_pio_intr(void *xsc) { struct at91_pio_softc *sc = xsc; -#if 0 uint32_t status; + int i; /* Reading the status also clears the interrupt */ - status = RD4(sc, PIO_SR); + status = RD4(sc, PIO_ISR) & RD4(sc, PIO_IMR); if (status == 0) return; AT91_PIO_LOCK(sc); + i = 0; + while (status) { + if (sc->buflen >= MAX_CHANGE) + break; + if (status & 1) + sc->buf[sc->buflen++] = (uint8_t)i; + i++; + status >>= 1; + } AT91_PIO_UNLOCK(sc); -#endif wakeup(sc); return; } @@ -245,9 +260,6 @@ AT91_PIO_LOCK(sc); if (!(sc->flags & OPENED)) { sc->flags |= OPENED; -#if 0 - // Enable interrupts -#endif } AT91_PIO_UNLOCK(sc); return (0); @@ -261,14 +273,48 @@ sc = CDEV2SOFTC(dev); AT91_PIO_LOCK(sc); sc->flags &= ~OPENED; -#if 0 - // Disable interrupts -#endif AT91_PIO_UNLOCK(sc); return (0); } static int +at91_pio_read(struct cdev *dev, struct uio *uio, int flag) +{ + struct at91_pio_softc *sc; + int err, ret, len; + + sc = CDEV2SOFTC(dev); + AT91_PIO_LOCK(sc); + err = 0; + ret = 0; + while (uio->uio_resid) { + // XXX non-blocking I/O support? + while (sc->buflen == 0 && err == 0) + err = msleep(sc, &sc->sc_mtx, PCATCH | PZERO, "prd", 0); + if (err != 0) + break; + len = MIN(sc->buflen, uio->uio_resid); + err = uiomove(sc->buf, len, uio); + if (err != 0) + break; + // If we read the whole thing, no datacopy is needed, + // otherwise we move the data down. + ret += len; + if (sc->buflen == len) + sc->buflen = 0; + else { + bcopy(sc->buf + len, sc->buf, sc->buflen - len); + sc->buflen -= len; + } + // IF there's no data left, end the read. + if (sc->buflen == 0) + break; + } + AT91_PIO_UNLOCK(sc); + return (err); +} + +static int at91_pio_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag, struct thread *td) { @@ -326,7 +372,7 @@ info->glitch_status = RD4(sc, PIO_IFSR); info->enabled_status = RD4(sc, PIO_PSR); info->periph_status = RD4(sc, PIO_ABSR); - info->intr_status = RD4(sc, PIO_ISR); + info->intr_status = RD4(sc, PIO_IMR); memset(info->extra_status, 0, sizeof(info->extra_status)); return (0); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200612150013.kBF0DCvV055007>