Skip site navigation (1)Skip section navigation (2)
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>