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"
index | next in thread | previous in thread | raw e-mail
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 [[
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199612030057.LAA06521>
