Date: Tue, 3 Dec 1996 11:27:06 +1030 (CST) From: Michael Smith <msmith@atrad.adelaide.edu.au> To: tony@nlanr.net (Tony Sterrett) Cc: hackers@FreeBSD.org Subject: Re: Driver help Message-ID: <199612030057.LAA06521@genesis.atrad.adelaide.edu.au> In-Reply-To: <199612030014.QAA15245@nlanr.net> from Tony Sterrett at "Dec 2, 96 04:14:35 pm"
next in thread | previous in thread | raw e-mail | index | archive | help
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 [[
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199612030057.LAA06521>