From owner-p4-projects@FreeBSD.ORG Fri Dec 15 00:23:57 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7E3EE16A47C; Fri, 15 Dec 2006 00:23:57 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 289EB16A4C8 for ; Fri, 15 Dec 2006 00:23:57 +0000 (UTC) (envelope-from imp@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.FreeBSD.org (Postfix) with ESMTP id AF31144176 for ; Fri, 15 Dec 2006 00:11:37 +0000 (GMT) (envelope-from imp@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id kBF0DCZo055013 for ; Fri, 15 Dec 2006 00:13:12 GMT (envelope-from imp@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id kBF0DCvV055007 for perforce@freebsd.org; Fri, 15 Dec 2006 00:13:12 GMT (envelope-from imp@freebsd.org) Date: Fri, 15 Dec 2006 00:13:12 GMT Message-Id: <200612150013.kBF0DCvV055007@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to imp@freebsd.org using -f From: Warner Losh To: Perforce Change Reviews Cc: Subject: PERFORCE change 111716 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 15 Dec 2006 00:23:57 -0000 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 #include #include +#include #include #include #include #include +#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); }