Subject: Re: Machine-independent bus DMA interface proposal
To: Jason Thorpe <>
From: Chris G Demetriou <>
List: tech-kern
Date: 09/22/1996 22:41:13
> I was going to send this rev to just the 3 afore-mentioned folks, but
> Chris is out for several says, and since I've addressed most of the
> concernes Chris raised with the previous rev, I thought I toss this out
> to the lions, and solicit opinions/thoughts from the general public now.

Well, i'm not quite gone yet.  MROW!

some comments (with irrelevant sections trimmed):

> typedef struct {
> 	bus_dma_segment_t *dh_segments;	/* dma segment(s) */
> 	int		dh_nsegments;	/* number of valid segments
> 					   in mapping */

I'd like it to be permissible for dh_segments to be an array.
No real big practical difference...  8-)

I'd can see implementations (e.g. mine! 8-) allocating DMA handles as
variable-sized objects with the segment list at the end.

> int	bus_dmamap_create __P((bus_dma_tag_t tag, bus_size_t size,
> 	    int nsegments, int flags, bus_dma_handle_t *dmahp));
> [ ... ]
> 		BUS_DMA_ALLOCNOW	Perform any resource allocation
> 					this handle may need now.
> 					If this is not specified, the
> 					allocation may be deferred to
> 					the first call to bus_dmamap_load().
> 					If this flag is specified,
> 					bus_dmamap_load() will not block
> 					on resource allocation.

Actually, s/the first call//.  If you don't specify BUS_DMA_ALLOCNOW,
resource allocation may be done on _every_ bus_dmamap_load(), since
resources can be freed on evern bus_dmamap_unload().

The notion here is that you might want to allocate a bunch of DMA
handles well in advance, but might not want to tie up the mapping
resources for the entire time they handles are in existence.  On the
other hand, you may be allocating DMA handles with the explicit
knowledge that they'll be used in time-critical or resource-short
situations, so you might want to allocate the mapping resources in

> int	bus_dmamap_load __P((bus_dma_tag_t tag, bus_dma_handle_t dmah,
> 	    caddr_t kva, size_t size, int flags));
> [ ... ]
> 	size		The size of the DMA transfer.

size must be <= the size given to bus_dmamap_alloc(), when the handle
was allocated.

> [ ... ]
> 	After a succssful call to bus_dmamap_load(), the publicly
> 	accessible members of the dma handle will conatain the

s/conatain/contain/  8-)

> void	bus_dmamap_sync __P((bus_dma_tag_t tag, bus_dma_handle_t dmah,
> 	    bus_dmasync_op_t op));
> 	bus_dmamap_sync() performs pre- and post-DMA operation
> 	synchronization.  Arguments are as follows:

s,synchronization,cache and/or buffer &,

> [ ... ]

This function exists so that multiple read and write transfers can be
performed with the same buffer, and so that drivers can explicitly
inform the bus DMA code when their data is 'ready' in its DMA buffer.

An example of multiple read-write use of a single mapping might look

    load(handle, buffer)

    while (not done) {
	sync(handle, pre-read);		/* invalidate soon-to-be-stale
					 * cache blocks */
	do read DMA.
	sync(handle, post-read);	/* copy from bounce */
	< read data now in driver-provided buffer >

	< computation >

	< data to be written now in driver-provided buffer >
	sync(handle, pre-write);	/* flush write buffers and writeback,
					 * copy to bounce */
	do write DMA.
	sync(handle, post-write);	/* probably a no-op */