BUS_DMA(9) | Kernel Developer's Manual | BUS_DMA(9) |
bus_dma
, bus_dmamap_create
,
bus_dmamap_destroy
,
bus_dmamap_load
,
bus_dmamap_load_mbuf
,
bus_dmamap_load_uio
,
bus_dmamap_load_raw
,
bus_dmamap_unload
,
bus_dmamap_sync
,
bus_dmamem_alloc
,
bus_dmamem_free
,
bus_dmamem_map
,
bus_dmamem_unmap
,
bus_dmamem_mmap
,
bus_dmatag_subregion
,
bus_dmatag_destroy
—
#include <sys/bus.h>
int
bus_dmamap_create
(bus_dma_tag_t
tag, bus_size_t
size, int
nsegments, bus_size_t
maxsegsz, bus_size_t
boundary, int
flags, bus_dmamap_t
*dmamp);
void
bus_dmamap_destroy
(bus_dma_tag_t
tag, bus_dmamap_t
dmam);
int
bus_dmamap_load
(bus_dma_tag_t
tag, bus_dmamap_t
dmam, void *buf,
bus_size_t buflen,
struct proc *p,
int flags);
int
bus_dmamap_load_mbuf
(bus_dma_tag_t
tag, bus_dmamap_t
dmam, struct mbuf
*chain, int
flags);
int
bus_dmamap_load_uio
(bus_dma_tag_t
tag, bus_dmamap_t
dmam, struct uio
*uio, int
flags);
int
bus_dmamap_load_raw
(bus_dma_tag_t
tag, bus_dmamap_t
dmam, bus_dma_segment_t
*segs, int nsegs,
bus_size_t size,
int flags);
void
bus_dmamap_unload
(bus_dma_tag_t
tag, bus_dmamap_t
dmam);
void
bus_dmamap_sync
(bus_dma_tag_t
tag, bus_dmamap_t
dmam, bus_addr_t
offset, bus_size_t
len, int ops);
int
bus_dmamem_alloc
(bus_dma_tag_t
tag, bus_size_t
size, bus_size_t
alignment, bus_size_t
boundary,
bus_dma_segment_t *segs,
int nsegs,
int *rsegs,
int flags);
void
bus_dmamem_free
(bus_dma_tag_t
tag, bus_dma_segment_t
*segs, int
nsegs);
int
bus_dmamem_map
(bus_dma_tag_t
tag, bus_dma_segment_t
*segs, int nsegs,
size_t size,
void **kvap,
int flags);
void
bus_dmamem_unmap
(bus_dma_tag_t
tag, void *kva,
size_t size);
paddr_t
bus_dmamem_mmap
(bus_dma_tag_t
tag, bus_dma_segment_t
*segs, int nsegs,
off_t off,
int prot,
int flags);
int
bus_dmatag_subregion
(bus_dma_tag_t
tag, bus_addr_t
min_addr, bus_addr_t
max_addr, bus_dma_tag_t
*newtag, int
flags);
void
bus_dmatag_destroy
(bus_dma_tag_t
tag);
<machine/bus_defs.h>
. All
functions will be defined by the port-specific header
<machine/bus_funcs.h>
. Note
that this document assumes the existence of types already defined by the
current "bus.h" interface.
Unless otherwise noted, all function calls in this interface may be defined as cpp(1) macros.
bus_addr_t ds_addr; bus_size_t ds_len;
The structure may have machine-dependent members and arbitrary layout. The values in ds_addr and ds_len are suitable for programming into DMA controller address and length registers.
bus_size_t dm_maxsegsz; bus_size_t dm_mapsize; int dm_nsegs; bus_dma_segment_t *dm_segs;
The structure may have machine-dependent members and arbitrary layout. The dm_maxsegsz member indicates the maximum number of bytes that may be transferred by any given DMA segment. The dm_mapsize member indicates the size of the mapping. A value of 0 indicates the mapping is invalid. The dm_segs member may be an array of segments or a pointer to an array of segments. The dm_nsegs member indicates the number of segments in dm_segs.
bus_dmamap_create
(tag,
size, nsegments,
maxsegsz, boundary,
flags, dmamp)BUS_DMA_WAITOK
BUS_DMA_NOWAIT
BUS_DMA_ALLOCNOW
bus_dmamap_load
(). If this flag is
specified, bus_dmamap_load
() will not
block on resource allocation.BUS_DMA_BUS[1-4]
Behavior is not defined if invalid arguments are passed to
bus_dmamap_create
().
Returns 0 on success, or an error code to indicate mode of failure.
bus_dmamap_destroy
(tag,
dmam)In the event that the DMA handle contains a valid mapping, the
mapping will be unloaded via the same mechanism used by
bus_dmamap_unload
().
Behavior is not defined if invalid arguments are passed to
bus_dmamap_destroy
().
If given valid arguments,
bus_dmamap_destroy
() always succeeds.
bus_dmamap_load
(tag,
dmam, buf,
buflen, p,
flags)NULL
, the buffer is assumed to be in kernel
space. Otherwise, the buffer is assumed to be in proc
p's address space.BUS_DMA_WAITOK
BUS_DMA_NOWAIT
BUS_DMA_STREAMING
bus_dma
API assumes that
there is coherency between memory and the device performing the
DMA transaction. Some platforms, however, have special hardware,
such as an “I/O cache”, which may improve
performance of some types of DMA transactions, but which break the
assumption that there is coherency between memory and the device
performing the DMA transaction. This flag allows the use of this
special hardware, provided that the device is doing sequential,
unidirectional transfers which conform to certain alignment and
size constraints defined by the platform. If the platform does not
support the feature, or if the buffer being loaded into the DMA
map does not conform to the constraints required for use of the
feature, then this flag will be silently ignored. Also refer to
the use of this flag with the
bus_dmamem_alloc
() function.BUS_DMA_READ
BUS_DMA_WRITE
BUS_DMA_BUS[1-4]
As noted above, if a DMA handle is created with
BUS_DMA_ALLOCNOW
,
bus_dmamap_load
() will never block.
If a call to bus_dmamap_load
() fails,
the mapping in the DMA handle will be invalid. It is the responsibility
of the caller to clean up any inconsistent device state resulting from
incomplete iteration through the uio.
Behavior is not defined if invalid arguments are passed to
bus_dmamap_load
().
Returns 0 on success, or an error code to indicate mode of failure. Possible error codes include the following:
EFBIG
EINVAL
ENOMEM
bus_dmamap_load_mbuf
(tag,
dmam, chain,
flags)bus_dmamap_load
() which
maps mbuf chains for DMA transfers. Mbuf chains are assumed to be in
kernel virtual address space.bus_dmamap_load_uio
(tag,
dmam, uio,
flags)bus_dmamap_load
() which
maps buffers pointed to by uio for DMA transfers.
Determination if the buffers are in user or kernel virtual address space
is done internally, according to
uio->uio_vmspace. See
uiomove(9) for details of
the uio
structure.bus_dmamap_load_raw
(tag,
dmam, segs,
nsegs, size,
flags)bus_dmamap_load
() which
maps buffers allocated by bus_dmamem_alloc
() (see
below). The segs argument is an array of
bus_dma_segment_t's filled in by
bus_dmamem_alloc
(). The
nsegs argument is the number of segments in the
array. The size argument is the size of the DMA
transfer.bus_dmamap_unload
(tag,
dmam)If the DMA handle was created with
BUS_DMA_ALLOCNOW
,
bus_dmamap_unload
() will not free the
corresponding resources which were allocated by
bus_dmamap_create
(). This is to ensure that
bus_dmamap_load
() will never block on resources
if the handle was created with
BUS_DMA_ALLOCNOW
.
bus_dmamap_unload
() will not perform
any implicit synchronization of DMA buffers. This must be done
explicitly by bus_dmamap_sync
().
bus_dmamap_unload
() will restore the
dm_maxsegsz member to its initial value assigned
by bus_dmamap_create
().
Behavior is not defined if invalid arguments are passed to
bus_dmamap_unload
().
If given valid arguments,
bus_dmamap_unload
() always succeeds.
bus_dmamap_sync
(tag,
dmam, offset,
len, ops)BUS_DMASYNC_PREREAD
BUS_DMASYNC_POSTREAD
BUS_DMASYNC_PREWRITE
BUS_DMASYNC_POSTWRITE
More than one operation may performed in a given synchronization call. Mixing of PRE and POST operations is not allowed, and behavior is undefined if this is attempted.
Synchronization operations are expressed from the perspective of the host RAM, e.g., a device -> memory operation is a READ and a memory -> device operation is a WRITE.
bus_dmamap_sync
() may consult state
kept within the DMA map to determine if the memory is mapped in a DMA
coherent fashion. If so, bus_dmamap_sync
() may
elect to skip certain expensive operations, such as flushing of the data
cache. See bus_dmamem_map
() for more information
on this subject.
On platforms which implement a weak memory access ordering
model, bus_dmamap_sync
() will always cause the
appropriate memory barriers to be issued.
This function exists to ensure that the host and the device have a consistent view of a range of DMA memory, before and after a DMA operation.
An example of using bus_dmamap_sync
(),
involving multiple read-write use of a single mapping might look like
this:
bus_dmamap_load(...); while (not done) { /* invalidate soon-to-be-stale cache blocks */ bus_dmamap_sync(..., BUS_DMASYNC_PREREAD); [ do read DMA ] /* copy from bounce */ bus_dmamap_sync(..., BUS_DMASYNC_POSTREAD); /* read data now in driver-provided buffer */ [ computation ] /* data to be written now in driver-provided buffer */ /* flush write buffers and writeback, copy to bounce */ bus_dmamap_sync(..., BUS_DMASYNC_PREWRITE); [ do write DMA ] /* probably a no-op, but provided for consistency */ bus_dmamap_sync(..., BUS_DMASYNC_POSTWRITE); } bus_dmamap_unload(...);
This function must be called to synchronize
DMA buffers before and after a DMA operation. Other
bus_dma
functions can not be
relied on to do this synchronization implicitly. If DMA read and write
operations are not preceded and followed by the appropriate
synchronization operations, behavior is undefined.
Behavior is not defined if invalid arguments are passed to
bus_dmamap_sync
().
If given valid arguments,
bus_dmamap_sync
() always succeeds.
bus_dmamem_alloc
(tag,
size, alignment,
boundary, segs,
nsegs, rsegs,
flags)The mapping of this memory is machine-dependent (or
"opaque"); machine-independent code is not to assume that the
addresses returned are valid in kernel virtual address space, or that
the addresses returned are system physical addresses. The address value
returned as part of segs can thus not be used to
program DMA controller address registers. Only the values in the
dm_segs array of a successfully loaded DMA map
(using bus_dmamap_load
()) can be used for this
purpose.
Allocations will always be rounded to the hardware page size. Callers may wish to take advantage of this, and cluster allocation of small data structures. Arguments are as follows:
BUS_DMA_WAITOK
BUS_DMA_NOWAIT
BUS_DMA_STREAMING
BUS_DMA_STREAMING
flag with
the bus_dmamap_load
() function. If the
platform does not support the
BUS_DMA_STREAMING
feature, or if the size,
alignment, and boundary constraints would already satisfy the
platform's requirements, this flag is silently ignored. The
BUS_DMA_STREAMING
flag will never relax
the constraints specified in the call.BUS_DMA_BUS[1-4]
All pages allocated by
bus_dmamem_alloc
() will be wired down until they
are freed by bus_dmamem_free
().
Behavior is undefined if invalid arguments are passed to
bus_dmamem_alloc
().
Returns 0 on success, or an error code indicating mode of failure.
bus_dmamem_free
(tag,
segs, nsegs)bus_dmamem_alloc
(). Any mappings will be
invalidated. Arguments are as follows:
bus_dmamem_alloc
().Behavior is undefined if invalid arguments are passed to
bus_dmamem_free
().
If given valid arguments,
bus_dmamem_free
() always succeeds.
bus_dmamem_map
(tag,
segs, nsegs,
size, kvap,
flags)bus_dmamem_alloc
() into
kernel virtual address space. Arguments are as follows:
bus_dmamem_alloc
(), representing the memory
regions to map.BUS_DMA_WAITOK
BUS_DMA_NOWAIT
BUS_DMA_BUS[1-4]
BUS_DMA_COHERENT
Later, when this memory is loaded into a DMA map,
machine-dependent code will take whatever steps are necessary to
determine if the memory was mapped in a DMA coherent fashion.
This may include checking if the kernel virtual address lies
within uncached address space or if the cache-inhibit bits are
set in page table entries. If it is determined that the mapping
is DMA coherent, state may be placed into the DMA map for use by
later calls to bus_dmamap_sync
().
Note that a device driver must not rely on
BUS_DMA_COHERENT
for correct operation.
All calls to bus_dmamap_sync
() must
still be made. This flag is provided only as an optimization
hint to machine-dependent code.
Also note that this flag only applies to coherency
between the CPU and memory. Coherency between memory and the
device is controlled with a different flag. See the description
of the bus_dmamap_load
() function.
BUS_DMA_NOCACHE
Behavior is undefined if invalid arguments are passed to
bus_dmamem_map
().
Returns 0 on success, or an error code indicating mode of failure.
bus_dmamem_unmap
(tag,
kva, size)bus_dmamem_map
(), freeing the kernel virtual
address space used by the mapping. The arguments are as follows:
Behavior is undefined if invalid arguments are passed to
bus_dmamem_unmap
().
If given valid arguments,
bus_dmamem_unmap
() always succeeds.
bus_dmamem_mmap
(tag,
segs, nsegs,
off, prot,
flags)bus_dmamem_alloc
(), representing the memory to
be mmap(2)'ed.BUS_DMA_WAITOK
BUS_DMA_NOWAIT
BUS_DMA_BUS[1-4]
BUS_DMA_COHERENT
bus_dmamem_map
() above for a
description of this flag.BUS_DMA_NOCACHE
bus_dmamem_map
() above for a
description of this flag.Behavior is undefined if invalid arguments are passed to
bus_dmamem_mmap
().
Returns -1 to indicate failure. Otherwise, returns an opaque value to be interpreted by the device pager.
bus_dmatag_subregion
(tag,
min_addr, max_addr,
newtag, flags)EOPNOTSUPP
is returned. The arguments are as
follows:
BUS_DMA_WAITOK
BUS_DMA_NOWAIT
bus_dmatag_destroy
(tag)bus_dmatag_subregion
().Jason Thorpe, A Machine-Independent DMA Framework for NetBSD, Proceedings of the FREENIX Track: 1998 USENIX Annual Technical Conference, USENIX Association, http://www.usenix.org/publications/library/proceedings/usenix98/freenix/thorpe_dma.pdf, 1-12, June 15-19, 1998.
bus_dma
interface appeared in
NetBSD 1.3.
bus_dma
interface was designed and implemented by
Jason R. Thorpe of the Numerical Aerospace Simulation
Facility, NASA Ames Research Center. Additional input on the
bus_dma
design was provided by Chris
Demetriou, Charles Hannum,
Ross Harvey, Matthew Jacob,
Jonathan Stone, and Matt
Thomas.
January 2, 2017 | NetBSD 9.0 |