| 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_WAITOKBUS_DMA_NOWAITBUS_DMA_ALLOCNOWbus_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_WAITOKBUS_DMA_NOWAITBUS_DMA_STREAMINGbus_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_READBUS_DMA_WRITEBUS_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:
EFBIGEINVALENOMEMbus_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_PREREADBUS_DMASYNC_POSTREADBUS_DMASYNC_PREWRITEBUS_DMASYNC_POSTWRITEMore 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_WAITOKBUS_DMA_NOWAITBUS_DMA_STREAMINGBUS_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_WAITOKBUS_DMA_NOWAITBUS_DMA_BUS[1-4]BUS_DMA_COHERENTLater, 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_NOCACHEBehavior 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_WAITOKBUS_DMA_NOWAITBUS_DMA_BUS[1-4]BUS_DMA_COHERENTbus_dmamem_map() above for a
              description of this flag.BUS_DMA_NOCACHEbus_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_WAITOKBUS_DMA_NOWAITbus_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.3 |