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 lwp *l
, 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.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_dma_tag_t
bus_dma_segment_t
bus_addr_t ds_addr;
bus_size_t ds_len;
ds_addr
and
ds_len
are suitable for programming into
DMA controller address and length registers.
bus_dmamap_t
bus_size_t dm_maxsegsz;
bus_size_t dm_mapsize;
int dm_nsegs;
bus_dma_segment_t *dm_segs;
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
.
tag
, size
, nsegments
, maxsegsz
, boundary
, flags
, dmamp
)
tag
<bus>_attach_args
.
size
nsegments
maxsegsz
dm_maxsegsz
member.
boundary
boundary
bytes.
Mappings may begin on a boundary line but may not end on or
cross a boundary line.
If no boundary condition needs to be observed, a
boundary
argument of 0 should be used.
flags
BUS_DMA_WAITOK
BUS_DMA_NOWAIT
BUS_DMA_ALLOCNOW
).
If this flag is specified,
bus_dmamap_load(
)
will not block on resource
allocation.
BUS_DMA_BUS[1-4]
dmamp
dmamp
upon successful completion of this routine.
dmamp
is undefined if this routine fails.
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.
tag
, dmam
)
tag
<bus>_attach_args
.
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.
tag
, dmam
, buf
, buflen
, l
, flags
)
tag
<bus>_attach_args
.
dmam
buf
buflen
l
NULL
,
the buffer is assumed to be in kernel space.
Otherwise, the buffer is assumed to be in lwp
l
Ap
s
address space.
flags
BUS_DMA_WAITOK
BUS_DMA_NOWAIT
BUS_DMA_STREAMING
)
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.
tag
, dmam
, chain
, flags
)
)
which maps mbuf chains
for DMA transfers.
Mbuf chains are assumed to be in kernel virtual address space.
tag
, dmam
, uio
, flags
)
)
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.
tag
, dmam
, segs
, nsegs
, size
, flags
)
)
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.
tag
, dmam
)
tag
<bus>_attach_args
.
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.
tag
, dmam
, offset
, len
, ops
)
tag
<bus>_attach_args
.
dmam
offset
len
offset
to synchronize.
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(
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(...);
),
involving multiple read-write use of a single mapping
might look like this:
bus_dmamap_load(...);
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.
tag
, size
, alignment
, boundary
, segs
, ...
)
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:
tag
<bus>_attach_args
.
size
alignment
boundary
segs
nsegs
segs
,
and this is the maximum number
of segments that the allocated memory may contain.
rsegs
flags
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.
tag
, segs
, nsegs
)
).
Any mappings
will be invalidated.
Arguments are as follows:
tag
<bus>_attach_args
.
segs
).
nsegs
segs
.
Behavior is undefined if invalid arguments are passed to
bus_dmamem_free().
If given valid arguments,
bus_dmamem_free()
always succeeds.
tag
, segs
, nsegs
, size
, kvap
, flags
)
)
into kernel virtual address space.
Arguments are as follows:
tag
<bus>_attach_args
.
segs
),
representing the memory regions to map.
nsegs
segs
.
size
kvap
flags
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.
tag
, kva
, size
)
),
freeing the
kernel virtual address space used by the mapping.
The arguments are as follows:
tag
<bus>_attach_args
.
kva
size
Behavior is undefined if invalid arguments are passed to
bus_dmamem_unmap().
If given valid arguments,
bus_dmamem_unmap()
always succeeds.
tag
, segs
, nsegs
, off
, prot
, flags
)
tag
<bus>_attach_args
.
segs
),
representing the memory to be
mmap(2)Ap ed.
nsegs
segs
array.
off
prot
flags
BUS_DMA_WAITOK
BUS_DMA_NOWAIT
BUS_DMA_BUS[1-4]
BUS_DMA_COHERENT
)
above for a description of this flag.
BUS_DMA_NOCACHE
)
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.
tag
, min_addr
, max_addr
, newtag
, flags
)
tag
min_addr
max_addr
newtag
flags
BUS_DMA_WAITOK
BUS_DMA_NOWAIT
tag
)
).