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