874 lines
26 KiB
Groff
874 lines
26 KiB
Groff
.\" $NetBSD: bus_dma.9,v 1.68 2024/02/17 08:27:46 skrll Exp $
|
|
.\"
|
|
.\" Copyright (c) 1996, 1997, 1998, 2001, 2005, 2006 The NetBSD Foundation, Inc.
|
|
.\" All rights reserved.
|
|
.\"
|
|
.\" This code is derived from software contributed to The NetBSD Foundation
|
|
.\" by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
|
|
.\" NASA Ames Research Center.
|
|
.\"
|
|
.\" Redistribution and use in source and binary forms, with or without
|
|
.\" modification, are permitted provided that the following conditions
|
|
.\" are met:
|
|
.\" 1. Redistributions of source code must retain the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer.
|
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
|
.\" notice, this list of conditions and the following disclaimer in the
|
|
.\" documentation and/or other materials provided with the distribution.
|
|
.\"
|
|
.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
|
.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
|
.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
|
.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
|
.\"
|
|
.Dd February 17, 2024
|
|
.Dt BUS_DMA 9
|
|
.Os
|
|
.Sh NAME
|
|
.Nm bus_dma ,
|
|
.Nm bus_dmamap_create ,
|
|
.Nm bus_dmamap_destroy ,
|
|
.Nm bus_dmamap_load ,
|
|
.Nm bus_dmamap_load_mbuf ,
|
|
.Nm bus_dmamap_load_uio ,
|
|
.Nm bus_dmamap_load_raw ,
|
|
.Nm bus_dmamap_unload ,
|
|
.Nm bus_dmamap_sync ,
|
|
.Nm bus_dmamem_alloc ,
|
|
.Nm bus_dmamem_free ,
|
|
.Nm bus_dmamem_map ,
|
|
.Nm bus_dmamem_unmap ,
|
|
.Nm bus_dmamem_mmap ,
|
|
.Nm bus_dmatag_subregion ,
|
|
.Nm bus_dmatag_destroy
|
|
.Nd Bus and Machine Independent DMA Mapping Interface
|
|
.Sh SYNOPSIS
|
|
.In sys/bus.h
|
|
.Ft int
|
|
.Fn 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"
|
|
.Ft void
|
|
.Fn bus_dmamap_destroy "bus_dma_tag_t tag" "bus_dmamap_t dmam"
|
|
.Ft int
|
|
.Fn bus_dmamap_load "bus_dma_tag_t tag" "bus_dmamap_t dmam" "void *buf" \
|
|
"bus_size_t buflen" "struct proc *p" "int flags"
|
|
.Ft int
|
|
.Fn bus_dmamap_load_mbuf "bus_dma_tag_t tag" "bus_dmamap_t dmam" \
|
|
"struct mbuf *chain" "int flags"
|
|
.Ft int
|
|
.Fn bus_dmamap_load_uio "bus_dma_tag_t tag" "bus_dmamap_t dmam" \
|
|
"struct uio *uio" "int flags"
|
|
.Ft int
|
|
.Fn 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"
|
|
.Ft void
|
|
.Fn bus_dmamap_unload "bus_dma_tag_t tag" "bus_dmamap_t dmam"
|
|
.Ft void
|
|
.Fn bus_dmamap_sync "bus_dma_tag_t tag" "bus_dmamap_t dmam" \
|
|
"bus_addr_t offset" "bus_size_t len" "int ops"
|
|
.Ft int
|
|
.Fn 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"
|
|
.Ft void
|
|
.Fn bus_dmamem_free "bus_dma_tag_t tag" "bus_dma_segment_t *segs" "int nsegs"
|
|
.Ft int
|
|
.Fn bus_dmamem_map "bus_dma_tag_t tag" "bus_dma_segment_t *segs" "int nsegs" \
|
|
"size_t size" "void **kvap" "int flags"
|
|
.Ft void
|
|
.Fn bus_dmamem_unmap "bus_dma_tag_t tag" "void *kva" "size_t size"
|
|
.Ft paddr_t
|
|
.Fn bus_dmamem_mmap "bus_dma_tag_t tag" "bus_dma_segment_t *segs" \
|
|
"int nsegs" "off_t off" "int prot" "int flags"
|
|
.Ft int
|
|
.Fn 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"
|
|
.Ft void
|
|
.Fn bus_dmatag_destroy "bus_dma_tag_t tag"
|
|
.Sh DESCRIPTION
|
|
Provide a bus- and machine-independent "DMA mapping interface."
|
|
.Sh IMPLEMENTATION NOTES
|
|
All data types and constants will be defined
|
|
by the port-specific header
|
|
.In machine/bus_defs.h .
|
|
All functions will be defined
|
|
by the port-specific header
|
|
.In machine/bus_funcs.h .
|
|
Note that this document
|
|
assumes the existence of types already defined by the current "bus.h"
|
|
interface.
|
|
.Pp
|
|
Unless otherwise noted, all function calls in this interface may be
|
|
defined as
|
|
.Xr cpp 1
|
|
macros.
|
|
.Sh DATA TYPES
|
|
Individual implementations may name these structures whatever they
|
|
wish, providing that the external representations are:
|
|
.Bl -tag -width compact
|
|
.It Fa bus_dma_tag_t
|
|
A machine-dependent opaque type describing the implementation of
|
|
DMA for a given bus.
|
|
.It Fa bus_dma_segment_t
|
|
A structure with at least the following members:
|
|
.Bd -literal
|
|
bus_addr_t ds_addr;
|
|
bus_size_t ds_len;
|
|
.Ed
|
|
.Pp
|
|
The structure may have machine-dependent members and arbitrary layout.
|
|
The values in
|
|
.Fa ds_addr
|
|
and
|
|
.Fa ds_len
|
|
are suitable for programming into
|
|
DMA controller address and length registers.
|
|
.It Fa bus_dmamap_t
|
|
A pointer to a structure with at least the following members:
|
|
.Bd -literal
|
|
bus_size_t dm_maxsegsz;
|
|
bus_size_t dm_mapsize;
|
|
int dm_nsegs;
|
|
bus_dma_segment_t *dm_segs;
|
|
.Ed
|
|
.Pp
|
|
The structure may have machine-dependent members and arbitrary layout.
|
|
The
|
|
.Fa dm_maxsegsz
|
|
member indicates the maximum number of bytes that may be transferred by
|
|
any given DMA segment.
|
|
The
|
|
.Fa dm_mapsize
|
|
member indicates the size of the mapping.
|
|
A value of 0 indicates the mapping is invalid.
|
|
The
|
|
.Fa dm_segs
|
|
member may be an array of segments or a pointer to an
|
|
array of segments.
|
|
The
|
|
.Fa dm_nsegs
|
|
member indicates the number of segments in
|
|
.Fa dm_segs .
|
|
.El
|
|
.Sh FUNCTIONS
|
|
.Bl -tag -width compact
|
|
.It Fn bus_dmamap_create "tag" "size" "nsegments" "maxsegsz" "boundary" "flags" "dmamp"
|
|
Allocates a DMA handle and initializes it according to the parameters
|
|
provided.
|
|
Arguments are as follows:
|
|
.Bl -tag -width nsegments -compact
|
|
.It Fa tag
|
|
This is the bus_dma_tag_t passed down from the parent driver via
|
|
.Fa <bus>_attach_args .
|
|
.It Fa size
|
|
This is the maximum DMA transfer that can be mapped by the handle.
|
|
.It Fa nsegments
|
|
Number of segments the device can support in a single DMA transaction.
|
|
This may be the number of scatter-gather descriptors supported by the
|
|
device.
|
|
.It Fa maxsegsz
|
|
The maximum number of bytes that may be transferred by any given DMA
|
|
segment and will be assigned to the
|
|
.Fa dm_maxsegsz
|
|
member.
|
|
.It Fa boundary
|
|
Some DMA controllers are not able to transfer data that crosses a
|
|
particular boundary.
|
|
This argument allows this boundary to be specified.
|
|
The boundary lines begin at 0, and occur every
|
|
.Fa 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
|
|
.Fa boundary
|
|
argument of 0 should be used.
|
|
.It Fa flags
|
|
Flags are defined as follows:
|
|
.Bl -tag -width BUS_DMA_ALLOCNOW -compact
|
|
.It Dv BUS_DMA_WAITOK
|
|
It is safe to wait (sleep) for resources during this call.
|
|
.It Dv BUS_DMA_NOWAIT
|
|
It is not safe to wait (sleep) for resources during this call.
|
|
.It Dv BUS_DMA_ALLOCNOW
|
|
Perform any resource allocation this handle may need now.
|
|
If this is not specified, the allocation may be deferred to
|
|
.Fn bus_dmamap_load .
|
|
If this flag is specified,
|
|
.Fn bus_dmamap_load
|
|
will not block on resource
|
|
allocation.
|
|
.It Dv BUS_DMA_BUS[1-4]
|
|
These flags are placeholders, and may be used by busses to provide
|
|
bus-dependent functionality.
|
|
.El
|
|
.It Fa dmamp
|
|
This is a pointer to a bus_dmamap_t.
|
|
A DMA map will be allocated and pointed to by
|
|
.Fa dmamp
|
|
upon successful completion of this routine.
|
|
.Fa dmamp
|
|
is undefined if this routine fails.
|
|
.El
|
|
.Pp
|
|
Behavior is not defined if invalid arguments are passed to
|
|
.Fn bus_dmamap_create .
|
|
.Pp
|
|
Returns 0 on success, or an error code to indicate mode of failure.
|
|
.It Fn bus_dmamap_destroy "tag" "dmam"
|
|
Frees all resources associated with a given DMA handle.
|
|
Arguments are as follows:
|
|
.Bl -tag -width dmam -compact
|
|
.It Fa tag
|
|
This is the bus_dma_tag_t passed down from the parent driver via
|
|
.Fa <bus>_attach_args .
|
|
.It Fa dmam
|
|
The DMA handle to destroy.
|
|
.El
|
|
.Pp
|
|
In the event that the DMA handle contains a valid mapping,
|
|
the mapping will be unloaded via the same mechanism used by
|
|
.Fn bus_dmamap_unload .
|
|
.Pp
|
|
Behavior is not defined if invalid arguments are passed to
|
|
.Fn bus_dmamap_destroy .
|
|
.Pp
|
|
If given valid arguments,
|
|
.Fn bus_dmamap_destroy
|
|
always succeeds.
|
|
.It Fn bus_dmamap_load "tag" "dmam" "buf" "buflen" "p" "flags"
|
|
Loads a DMA handle with mappings for a DMA transfer.
|
|
It assumes that all pages involved in a DMA transfer are wired.
|
|
Arguments are as follows:
|
|
.Bl -tag -width buflen -compact
|
|
.It Fa tag
|
|
This is the bus_dma_tag_t passed down from the parent driver via
|
|
.Fa <bus>_attach_args .
|
|
.It Fa dmam
|
|
The DMA handle with which to map the transfer.
|
|
.It Fa buf
|
|
The buffer to be used for the DMA transfer.
|
|
.It Fa buflen
|
|
The size of the buffer.
|
|
.It Fa p
|
|
Used to indicate the address space in which the buffer is located.
|
|
If
|
|
.Dv NULL ,
|
|
the buffer is assumed to be in kernel space.
|
|
Otherwise, the buffer is assumed to be in proc
|
|
.Fa p Ap s
|
|
address space.
|
|
.It Fa flags
|
|
are defined as follows:
|
|
.Bl -tag -width "BUS_DMA_STREAMING" -compact
|
|
.It Dv BUS_DMA_WAITOK
|
|
It is safe to wait (sleep) for resources during this call.
|
|
.It Dv BUS_DMA_NOWAIT
|
|
It is not safe to wait (sleep) for resources during this call.
|
|
.It Dv BUS_DMA_STREAMING
|
|
By default, the
|
|
.Nm
|
|
API assumes that there is coherency between memory and the device
|
|
performing the DMA transaction.
|
|
Some platforms, however, have special hardware, such as an
|
|
.Dq 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
|
|
.Fn bus_dmamem_alloc
|
|
function.
|
|
.It Dv BUS_DMA_READ
|
|
This is a hint to the machine-dependent back-end that indicates the
|
|
mapping will be used only for a
|
|
.Em "device -> memory"
|
|
transaction.
|
|
The back-end may perform optimizations based on this information.
|
|
.It Dv BUS_DMA_WRITE
|
|
This is a hint to the machine-dependent back-end that indicates the
|
|
mapping will be used only for a
|
|
.Em "memory -> device"
|
|
transaction.
|
|
The back-end may perform optimizations based on this information.
|
|
.It Dv BUS_DMA_BUS[1-4]
|
|
These flags are placeholders, and may be used by busses to
|
|
provide bus-dependent functionality.
|
|
.El
|
|
.El
|
|
.Pp
|
|
As noted above, if a DMA handle is created with
|
|
.Dv BUS_DMA_ALLOCNOW ,
|
|
.Fn bus_dmamap_load
|
|
will never block.
|
|
.Pp
|
|
If a call to
|
|
.Fn 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.
|
|
.Pp
|
|
Behavior is not defined if invalid arguments are passed to
|
|
.Fn bus_dmamap_load .
|
|
.Pp
|
|
Returns 0 on success, or an error code to indicate mode of failure.
|
|
Possible error codes include the following:
|
|
.Pp
|
|
.Bl -tag -width dmam -compact
|
|
.It Er EFBIG
|
|
Too many segments.
|
|
.It Er EINVAL
|
|
.Fa buflen
|
|
is too large for the DMA map.
|
|
.It Er ENOMEM
|
|
Could not allocate memory for, e.g., a bounce buffer.
|
|
.El
|
|
.It Fn bus_dmamap_load_mbuf "tag" "dmam" "chain" "flags"
|
|
This is a variation of
|
|
.Fn bus_dmamap_load
|
|
which maps mbuf chains
|
|
for DMA transfers.
|
|
Mbuf chains are assumed to be in kernel virtual address space.
|
|
.It Fn bus_dmamap_load_uio "tag" "dmam" "uio" "flags"
|
|
This is a variation of
|
|
.Fn bus_dmamap_load
|
|
which maps buffers pointed to by
|
|
.Fa uio
|
|
for DMA transfers.
|
|
Determination if the buffers are in user or kernel virtual address space
|
|
is done internally, according to
|
|
.Fa "uio->uio_vmspace" .
|
|
See
|
|
.Xr uiomove 9
|
|
for details of the
|
|
.Dv uio
|
|
structure.
|
|
.It Fn bus_dmamap_load_raw "tag" "dmam" "segs" "nsegs" "size" "flags"
|
|
This is a variation of
|
|
.Fn bus_dmamap_load
|
|
which maps buffers
|
|
allocated by
|
|
.Fn bus_dmamem_alloc
|
|
(see below).
|
|
The
|
|
.Fa segs
|
|
argument is an array of bus_dma_segment_t's filled in
|
|
by
|
|
.Fn bus_dmamem_alloc .
|
|
The
|
|
.Fa nsegs
|
|
argument is the number of segments in the array.
|
|
The
|
|
.Fa size
|
|
argument is the size of the DMA transfer.
|
|
.It Fn bus_dmamap_unload "tag" "dmam"
|
|
Deletes the mappings for a given DMA handle.
|
|
Arguments are as follows:
|
|
.Bl -tag -width dmam -compact
|
|
.It Fa tag
|
|
This is the bus_dma_tag_t passed down from the parent driver via
|
|
.Fa <bus>_attach_args .
|
|
.It Fa dmam
|
|
The DMA handle containing the mappings which are to be deleted.
|
|
.El
|
|
.Pp
|
|
If the DMA handle was created with
|
|
.Dv BUS_DMA_ALLOCNOW ,
|
|
.Fn bus_dmamap_unload
|
|
will not free the corresponding
|
|
resources which were allocated by
|
|
.Fn bus_dmamap_create .
|
|
This is to ensure that
|
|
.Fn bus_dmamap_load
|
|
will never block
|
|
on resources if the handle was created with
|
|
.Dv BUS_DMA_ALLOCNOW .
|
|
.Pp
|
|
.Fn bus_dmamap_unload
|
|
will not perform any implicit synchronization of DMA buffers.
|
|
This must be done explicitly by
|
|
.Fn bus_dmamap_sync .
|
|
.Pp
|
|
.Fn bus_dmamap_unload
|
|
will restore the
|
|
.Fa dm_maxsegsz
|
|
member to its initial value assigned by
|
|
.Fn bus_dmamap_create .
|
|
.Pp
|
|
Behavior is not defined if invalid arguments are passed to
|
|
.Fn bus_dmamap_unload .
|
|
.Pp
|
|
If given valid arguments,
|
|
.Fn bus_dmamap_unload
|
|
always succeeds.
|
|
.It Fn bus_dmamap_sync "tag" "dmam" "offset" "len" "ops"
|
|
Performs pre- and post-DMA operation cache and/or buffer synchronization.
|
|
Arguments are as follows:
|
|
.Bl -tag -width offset -compact
|
|
.It Fa tag
|
|
This is the bus_dma_tag_t passed down from the parent driver via
|
|
.Fa <bus>_attach_args .
|
|
.It Fa dmam
|
|
The DMA mapping to be synchronized.
|
|
.It Fa offset
|
|
The offset into the DMA mapping to synchronize.
|
|
.It Fa len
|
|
The length of the mapping from
|
|
.Fa offset
|
|
to synchronize.
|
|
.It Fa ops
|
|
One or more synchronization operation to perform.
|
|
The following DMA synchronization operations are defined:
|
|
.Bl -tag -width BUS_DMASYNC_POSTWRITE -compact
|
|
.It Dv BUS_DMASYNC_PREREAD
|
|
Perform any synchronization required prior to an update of host memory by the
|
|
device.
|
|
.It Dv BUS_DMASYNC_POSTREAD
|
|
Perform any synchronization required after an update of host memory by the
|
|
device and prior to CPU access to host memory.
|
|
.It Dv BUS_DMASYNC_PREWRITE
|
|
Perform any synchronization required after an update of host memory by the CPU
|
|
and prior to device access to host memory.
|
|
.It Dv BUS_DMASYNC_POSTWRITE
|
|
Perform any synchronization required after device access to host memory.
|
|
.El
|
|
where each operation may involve cache flush/invalidation, bounce buffer
|
|
copying, and/or memory barriers.
|
|
.Pp
|
|
More than one operation may performed in a given synchronization call.
|
|
Mixing of
|
|
.Em PRE
|
|
and
|
|
.Em POST
|
|
operations is not allowed, and behavior is undefined if this is attempted.
|
|
.El
|
|
.Pp
|
|
Synchronization operations are expressed from the perspective of
|
|
the host RAM, e.g., a
|
|
.Em "device -> memory"
|
|
operation is a
|
|
.Em READ
|
|
and a
|
|
.Em "memory -> device"
|
|
operation is a
|
|
.Em WRITE .
|
|
.Pp
|
|
.Fn 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,
|
|
.Fn bus_dmamap_sync
|
|
may elect to skip certain expensive operations, such as flushing
|
|
of the data cache.
|
|
See
|
|
.Fn bus_dmamem_map
|
|
for more information on this subject.
|
|
.Pp
|
|
On platforms which implement a weak memory access ordering model,
|
|
.Fn bus_dmamap_sync
|
|
will always cause the appropriate memory barriers to be issued.
|
|
.Pp
|
|
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.
|
|
.Pp
|
|
An example of using
|
|
.Fn bus_dmamap_sync ,
|
|
involving multiple read-write use of a single mapping
|
|
might look like this:
|
|
.Bd -literal
|
|
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(...);
|
|
.Ed
|
|
.Pp
|
|
This function
|
|
.Em must
|
|
be called to synchronize DMA buffers before and after a DMA operation.
|
|
Other
|
|
.Nm
|
|
functions can
|
|
.Em 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.
|
|
.Pp
|
|
Behavior is not defined if invalid arguments are passed to
|
|
.Fn bus_dmamap_sync .
|
|
.Pp
|
|
If given valid arguments,
|
|
.Fn bus_dmamap_sync
|
|
always succeeds.
|
|
.It Fn bus_dmamem_alloc "tag" "size" "alignment" "boundary" "segs" "nsegs" "rsegs" "flags"
|
|
Allocates memory that is "DMA safe" for the bus corresponding to the
|
|
given tag.
|
|
.Pp
|
|
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
|
|
.Fa segs
|
|
can thus not be used to program DMA controller address registers.
|
|
Only the values in the
|
|
.Fa dm_segs
|
|
array of a successfully loaded DMA map (using
|
|
.Fn bus_dmamap_load )
|
|
can be used for this purpose.
|
|
.Pp
|
|
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:
|
|
.Bl -tag -width alignment -compact
|
|
.It Fa tag
|
|
This is the bus_dma_tag_t passed down from the parent driver via
|
|
.Fa <bus>_attach_args .
|
|
.It Fa size
|
|
The amount of memory to allocate.
|
|
.It Fa alignment
|
|
Each segment in the allocated memory will be aligned to this value.
|
|
If the alignment is less than a hardware page size, it will be rounded up
|
|
to the hardware page size.
|
|
This value must be a power of two.
|
|
.It Fa boundary
|
|
Each segment in the allocated memory must not cross this boundary
|
|
(relative to zero).
|
|
This value must be a power of two.
|
|
A boundary value less than the size of the allocation is invalid.
|
|
If no boundary condition needs to be observed, a
|
|
.Fa boundary
|
|
argument of 0 should be used.
|
|
.It Fa segs
|
|
An array of bus_dma_segment_t's, filled in as memory is allocated,
|
|
representing the opaque addresses of the memory chunks.
|
|
.It Fa nsegs
|
|
Specifies the number of segments in
|
|
.Fa segs ,
|
|
and this is the maximum number
|
|
of segments that the allocated memory may contain.
|
|
.It Fa rsegs
|
|
Used to return the actual number of segments the memory contains.
|
|
.It Fa flags
|
|
Flags are defined as follows:
|
|
.Bl -tag -width BUS_DMA_STREAMING -compact
|
|
.It Dv BUS_DMA_WAITOK
|
|
It is safe to wait (sleep) for resources during this call.
|
|
.It Dv BUS_DMA_NOWAIT
|
|
It is not safe to wait (sleep) for resources during this call.
|
|
.It Dv BUS_DMA_STREAMING
|
|
Adjusts, if necessary, the size, alignment, and boundary constrains
|
|
to conform to the platform-dependent requirements for the use of the
|
|
.Dv BUS_DMA_STREAMING
|
|
flag with the
|
|
.Fn bus_dmamap_load
|
|
function.
|
|
If the platform does not support the
|
|
.Dv 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
|
|
.Dv BUS_DMA_STREAMING
|
|
flag will never relax the constraints specified in the call.
|
|
.It Dv BUS_DMA_BUS[1-4]
|
|
These flags are placeholders, and may be used by busses to provide
|
|
bus-dependent functionality.
|
|
.El
|
|
.El
|
|
.Pp
|
|
All pages allocated by
|
|
.Fn bus_dmamem_alloc
|
|
will be wired down
|
|
until they are freed by
|
|
.Fn bus_dmamem_free .
|
|
.Pp
|
|
Behavior is undefined if invalid arguments are passed to
|
|
.Fn bus_dmamem_alloc .
|
|
.Pp
|
|
Returns 0 on success, or an error code indicating mode of failure.
|
|
.It Fn bus_dmamem_free "tag" "segs" "nsegs"
|
|
Frees memory previously allocated by
|
|
.Fn bus_dmamem_alloc .
|
|
Any mappings
|
|
will be invalidated.
|
|
Arguments are as follows:
|
|
.Bl -tag -width nsegs -compact
|
|
.It Fa tag
|
|
This is the bus_dma_tag_t passed down from the parent driver via
|
|
.Fa <bus>_attach_args .
|
|
.It Fa segs
|
|
The array of bus_dma_segment_t's filled in by
|
|
.Fn bus_dmamem_alloc .
|
|
.It Fa nsegs
|
|
The number of segments in
|
|
.Fa segs .
|
|
.El
|
|
.Pp
|
|
Behavior is undefined if invalid arguments are passed to
|
|
.Fn bus_dmamem_free .
|
|
.Pp
|
|
If given valid arguments,
|
|
.Fn bus_dmamem_free
|
|
always succeeds.
|
|
.It Fn bus_dmamem_map "tag" "segs" "nsegs" "size" "kvap" "flags"
|
|
Maps memory allocated with
|
|
.Fn bus_dmamem_alloc
|
|
into kernel virtual address space.
|
|
Arguments are as follows:
|
|
.Bl -tag -width flags -compact
|
|
.It Fa tag
|
|
This is the bus_dma_tag_t passed down from the parent driver via
|
|
.Fa <bus>_attach_args .
|
|
.It Fa segs
|
|
The array of bus_dma_segment_t's filled in by
|
|
.Fn bus_dmamem_alloc ,
|
|
representing the memory regions to map.
|
|
.It Fa nsegs
|
|
The number of segments in
|
|
.Fa segs .
|
|
.It Fa size
|
|
The size of the mapping.
|
|
.It Fa kvap
|
|
Filled in to specify the kernel virtual address where the memory is mapped.
|
|
.It Fa flags
|
|
Flags are defined as follows:
|
|
.Bl -tag -width BUS_DMA_COHERENT -compact
|
|
.It Dv BUS_DMA_WAITOK
|
|
It is safe to wait (sleep) for resources during this call.
|
|
.It Dv BUS_DMA_NOWAIT
|
|
It is not safe to wait (sleep) for resources during this call.
|
|
.It Dv BUS_DMA_BUS[1-4]
|
|
These flags are placeholders, and may be used by busses to provide
|
|
bus-dependent functionality.
|
|
.It Dv BUS_DMA_COHERENT
|
|
This flag is a
|
|
.Em hint
|
|
to machine-dependent code.
|
|
If possible, map the memory in such a way as it will be DMA coherent.
|
|
This may include mapping the pages into uncached address space or
|
|
setting the cache-inhibit bits in page table entries.
|
|
If DMA coherent mappings are impossible, this flag is silently ignored.
|
|
.Pp
|
|
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
|
|
.Fn bus_dmamap_sync .
|
|
.Pp
|
|
Note that a device driver must not rely on
|
|
.Dv BUS_DMA_COHERENT
|
|
for correct operation.
|
|
All calls to
|
|
.Fn bus_dmamap_sync
|
|
must still be made.
|
|
This flag is provided only as an optimization hint to machine-dependent code.
|
|
.Pp
|
|
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
|
|
.Fn bus_dmamap_load
|
|
function.
|
|
.It Dv BUS_DMA_NOCACHE
|
|
This flag is a
|
|
.Em hint
|
|
to machine-dependent code.
|
|
If possible, map the uncached memory.
|
|
This flag may be useful in the case that the memory cache causes unexpected
|
|
behavior of the device.
|
|
.El
|
|
.El
|
|
.Pp
|
|
Behavior is undefined if invalid arguments are passed to
|
|
.Fn bus_dmamem_map .
|
|
.Pp
|
|
Returns 0 on success, or an error code indicating mode of failure.
|
|
.It Fn bus_dmamem_unmap "tag" "kva" "size"
|
|
Unmaps memory previously mapped with
|
|
.Fn bus_dmamem_map ,
|
|
freeing the
|
|
kernel virtual address space used by the mapping.
|
|
The arguments are as follows:
|
|
.Bl -tag -width size -compact
|
|
.It Fa tag
|
|
This is the bus_dma_tag_t passed down from the parent driver via
|
|
.Fa <bus>_attach_args .
|
|
.It Fa kva
|
|
The kernel virtual address of the mapped memory.
|
|
.It Fa size
|
|
The size of the mapping.
|
|
.El
|
|
.Pp
|
|
Behavior is undefined if invalid arguments are passed to
|
|
.Fn bus_dmamem_unmap .
|
|
.Pp
|
|
If given valid arguments,
|
|
.Fn bus_dmamem_unmap
|
|
always succeeds.
|
|
.It Fn bus_dmamem_mmap "tag" "segs" "nsegs" "off" "prot" "flags"
|
|
Provides support for user
|
|
.Xr mmap 2 Ap ing
|
|
of DMA-safe memory.
|
|
This function is to be called by a device driver's (*d_mmap)() entry
|
|
point, which is called by the device pager for each page to be mapped.
|
|
The arguments are as follows:
|
|
.Bl -tag -width nsegs -compact
|
|
.It Fa tag
|
|
This is the bus_dma_tag_t passed down from the parent driver via
|
|
.Fa <bus>_attach_args .
|
|
.It Fa segs
|
|
The array of bus_dma_segment_t's filled in by
|
|
.Fn bus_dmamem_alloc ,
|
|
representing the memory to be
|
|
.Xr mmap 2 Ap ed .
|
|
.It Fa nsegs
|
|
The number of elements in the
|
|
.Fa segs
|
|
array.
|
|
.It Fa off
|
|
The offset of the page in DMA memory which is to be mapped.
|
|
.It Fa prot
|
|
The protection codes for the mapping.
|
|
.It Fa flags
|
|
Flags are defined as follows:
|
|
.Bl -tag -width BUS_DMA_COHERENT -compact
|
|
.It Dv BUS_DMA_WAITOK
|
|
It is safe to wait (sleep) for resources during this call.
|
|
.It Dv BUS_DMA_NOWAIT
|
|
It is not safe to wait (sleep) for resources during this call.
|
|
.It Dv BUS_DMA_BUS[1-4]
|
|
These flags are placeholders, and may be used by busses to provide
|
|
bus-dependent functionality.
|
|
.It Dv BUS_DMA_COHERENT
|
|
See
|
|
.Fn bus_dmamem_map
|
|
above for a description of this flag.
|
|
.It Dv BUS_DMA_NOCACHE
|
|
See
|
|
.Fn bus_dmamem_map
|
|
above for a description of this flag.
|
|
.El
|
|
.El
|
|
.Pp
|
|
Behavior is undefined if invalid arguments are passed
|
|
to
|
|
.Fn bus_dmamem_mmap .
|
|
.Pp
|
|
Returns -1 to indicate failure.
|
|
Otherwise, returns an opaque value to be interpreted by the device pager.
|
|
.It Fn bus_dmatag_subregion "tag" "min_addr" "max_addr" "newtag" "flags"
|
|
Given a bus_dma_tag_t
|
|
create a new bus_dma_tag_t with a limited bus address space.
|
|
This function should not normally be used, but is useful for devices
|
|
that do not support the full address space of the parent bus.
|
|
Not all ports implement this method; on ports where it is unavailable,
|
|
.Er EOPNOTSUPP
|
|
is returned.
|
|
The arguments are as follows:
|
|
.Bl -tag -width max_addr -compact
|
|
.It Fa tag
|
|
This is the bus_dma_tag_t to subregion.
|
|
.It Fa min_addr
|
|
The smallest address this new tag can address.
|
|
.It Fa max_addr
|
|
The largest address this new tag can address.
|
|
.It Fa newtag
|
|
Pointer filled in with the address of the new bus_dma_tag_t.
|
|
.It Fa flags
|
|
Flags are defined as follows:
|
|
.Bl -tag -width BUS_DMA_WAITOK -compact
|
|
.It Dv BUS_DMA_WAITOK
|
|
It is safe to wait (sleep) for resources during this call.
|
|
.It Dv BUS_DMA_NOWAIT
|
|
It is not safe to wait (sleep) for resources during this call.
|
|
.El
|
|
.El
|
|
The address range
|
|
.Fa min_addr
|
|
to
|
|
.Fa max_addr
|
|
is inclusive of both addresses.
|
|
.It Fn bus_dmatag_destroy "tag"
|
|
Free a tag created by
|
|
.Fn bus_dmatag_subregion .
|
|
.El
|
|
.Sh SEE ALSO
|
|
.Xr membar_ops 3 ,
|
|
.Xr bus_space 9
|
|
.Rs
|
|
.%A Jason Thorpe
|
|
.%T "A Machine-Independent DMA Framework for NetBSD"
|
|
.%I USENIX Association
|
|
.%B Proceedings of the FREENIX Track: 1998 USENIX Annual Technical Conference
|
|
.%P 1-12
|
|
.%D June 15-19, 1998
|
|
.%U http://www.usenix.org/publications/library/proceedings/usenix98/freenix/thorpe_dma.pdf
|
|
.Re
|
|
.Sh HISTORY
|
|
The
|
|
.Nm
|
|
interface appeared in
|
|
.Nx 1.3 .
|
|
.Sh AUTHORS
|
|
.An -nosplit
|
|
The
|
|
.Nm
|
|
interface was designed and implemented by
|
|
.An Jason R. Thorpe
|
|
of the
|
|
Numerical Aerospace Simulation Facility, NASA Ames Research Center.
|
|
Additional input on the
|
|
.Nm
|
|
design was provided by
|
|
.An Chris Demetriou ,
|
|
.An Charles Hannum ,
|
|
.An Ross Harvey ,
|
|
.An Matthew Jacob ,
|
|
.An Jonathan Stone ,
|
|
and
|
|
.An Matt Thomas .
|