PERFORCE change 111716 for review
Warner Losh
imp at FreeBSD.org
Thu Dec 14 16:23:57 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=111716
Change 111716 by imp at 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);
}
More information about the p4-projects
mailing list