From owner-freebsd-hackers Mon Dec 2 16:57:19 1996 Return-Path: owner-hackers Received: (from root@localhost) by freefall.freebsd.org (8.7.5/8.7.3) id QAA25389 for hackers-outgoing; Mon, 2 Dec 1996 16:57:19 -0800 (PST) Received: from genesis.atrad.adelaide.edu.au (genesis.atrad.adelaide.edu.au [129.127.96.120]) by freefall.freebsd.org (8.7.5/8.7.3) with ESMTP id QAA25381 for ; Mon, 2 Dec 1996 16:57:14 -0800 (PST) Received: (from msmith@localhost) by genesis.atrad.adelaide.edu.au (8.8.2/8.7.3) id LAA06521; Tue, 3 Dec 1996 11:27:07 +1030 (CST) From: Michael Smith Message-Id: <199612030057.LAA06521@genesis.atrad.adelaide.edu.au> Subject: Re: Driver help In-Reply-To: <199612030014.QAA15245@nlanr.net> from Tony Sterrett at "Dec 2, 96 04:14:35 pm" To: tony@nlanr.net (Tony Sterrett) Date: Tue, 3 Dec 1996 11:27:06 +1030 (CST) Cc: hackers@FreeBSD.org X-Mailer: ELM [version 2.4ME+ PL28 (25)] MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit Sender: owner-hackers@FreeBSD.org X-Loop: FreeBSD.org Precedence: bulk Tony Sterrett stands accused of saying: > > How does one address the u for a driver. I have the code > which copies into the u area but how do I declare it. Um, that depends on what you're trying to achieve; if you're writing the back half of a read() routine, use uiomove(). Here's a pared version from a driver using a ringbuffer for input. Some notes: - The handling for the rinbuffer split case makes this a little harder to read. - I've left the sleep code in on the off chance it's useful. - It's probably not actually necessary to disable tty interrupts while doing any of the read in this particular driver, but for many the possibility of conflict is real. - The comments got pruned to make this readable as a mail message (the original is formatted for 120 columns). - You should use uiomove because it's wise to the type of the destination; for destinations in kernel space it will use bcopy() rather than copyout(), and it understands fragmented destinations (ie. readv()/writev()). IMHO, using copyin/out in drivers is bogus in most cases. int mdsioread(dev_t dev, struct uio *uio, int flag) { MDIF *md; int unit; int s; int rv = 0; u_int hmuch; int frag; unit = minor(dev); if (unit > NMDSIO) /* not configured */ return(ENXIO); md = mdsio_unit(unit); s = spltty(); if (rxbuflen(md) == 0) { /* no data ready, must sleep */ if (flag & IO_NDELAY) { /* can't sleep, return to caller */ splx(s); return(EAGAIN); } md->state |= MD_READSLEEP; /* make it so */ rv = tsleep((caddr_t)md, PRIBIO | PCATCH, "mdsioread", 0); md->state &= ~MD_READSLEEP; /* yawn */ } splx(s); if (rv) /* nonzero means interrupted? */ return(EINTR); s = spltty(); /* lock out interference from interrupt handler */ hmuch = rxbuflen(md); /* this much is available */ if (uio->uio_resid < hmuch) /* compare with requested read size */ hmuch = uio->uio_resid; /* only want this much */ if ((md->rxtail + hmuch) > MDSIO_RXBUF) { /* buffer wrap */ frag = (md->rxtail + hmuch) - MDSIO_RXBUF; /* size of fragment */ rv = uiomove((caddr_t)(md->rxbuf + md->rxtail),/* move first frag */ frag, uio); if (!rv) /* OK so far? */ rv = uiomove((caddr_t)md->rxbuf, /* move second frag */ (hmuch - frag), uio); } else { rv = uiomove((caddr_t)(md->rxbuf + md->rxtail),/* move all together */ hmuch, uio); } if (rv) { debug("uiomove returned %d",rv); } else { /* read OK, move the tail */ md->rxtail = (md->rxtail + hmuch) % MDSIO_RXBUF; debug("OK"); } splx(s); /* interrupts safe now */ return(rv); } -- ]] Mike Smith, Software Engineer msmith@gsoft.com.au [[ ]] Genesis Software genesis@gsoft.com.au [[ ]] High-speed data acquisition and (GSM mobile) 0411-222-496 [[ ]] realtime instrument control. (ph) +61-8-8267-3493 [[ ]] Unix hardware collector. "Where are your PEZ?" The Tick [[