Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 09 Nov 1998 12:33:57 -0800
From:      Mike Smith <mike@smith.net.au>
To:        lcremean@tidalwave.net
Cc:        hackers@FreeBSD.ORG
Subject:   Re: Encryption coprocessor, part 2. 
Message-ID:  <199811092033.MAA00693@dingo.cdrom.com>
In-Reply-To: Your message of "Mon, 09 Nov 1998 15:14:23 EST." <19981109151423.A2157@tidalwave.net> 

next in thread | previous in thread | raw e-mail | index | archive | help
> All right, I've figured out what I want to do with the packets (though a
> zero-copy implementation would be faster, I doubt it's easy to do here). I'm
> going to set up a list of buffers in memory, then feed their address to the
> chip as needed...(actually, it'll be four rings, since there are 4 DMA
> channels). What I need to know now is what the best way would be to get the
> user buffers into the kernel (I'm assuming we'd be trying to send pointers
> to all four at once, then copying).

Er, this is really list management 101.  For each buffer set you have:

 - a free list, populated at startup
 - a work queue
 - a done queue

It sounds from your previous messages as though the control buffers are 
actually associated with the data buffers, so you might want to unify 
them.

In the write routine, assuming that you mandate atomic writes of single 
packets, you do something like this:


	if (uio->uio_resid != WRITE_SIZE)
		return(ENOSPC);
	bufp = getbuf_free();
	if ((error = uiomove(bufp->data, WRITE_SIZE, uio)) != 0) {
		putbuf_free(bufp);
		return(error);
	}
	putbuf_work(bufp);
	foointr();

the interurpt handler should do something like:

	if (interrupt_reason & WORK_DONE) {
		bufp = sc->busybuf;
		putbuf_done(bufp);
	}
	if (device_status & CHANNEL_FREE) {
		bufp = getbuf_work();
		if (bufp != NULL) {
			sc->busybuf = bufp;
			stuff_buffer_into_device();
		}
	}

and the read routine should look like this:

	if (uio->uio_resid != READ_SIZE)
		return(ENOSPC);
	bufp = getbuf_done();
	if ((error = uiomove(bufp->data, READ_SIZE, uio)) != 0) {
		putbuf_done(bufp);	/* XXX push onto head of list */
		return(error);
	}
	putbuf_free(bufp);

Then you just need to arrange for the getbuf_done and getbuf_free 
functions to sleep if there's no buffer on the head of the queue.

-- 
\\  Sometimes you're ahead,       \\  Mike Smith
\\  sometimes you're behind.      \\  mike@smith.net.au
\\  The race is long, and in the  \\  msmith@freebsd.org
\\  end it's only with yourself.  \\  msmith@cdrom.com



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199811092033.MAA00693>