*nix Documentation Project
·  Home
 +   man pages
·  Linux HOWTOs
·  FreeBSD Tips
·  *niX Forums

  man pages->OpenBSD man pages -> bus_dmamap_create (9)              
Title
Content
Arch
Section
 

BUS_DMA(9)

Contents


NAME    [Toc]    [Back]

     bus_dma - bus and machine independent DMA mapping interface

SYNOPSIS    [Toc]    [Back]

     #include <machine/bus.h>

DESCRIPTION    [Toc]    [Back]

     The bus_dma interface provides a bus and machine independent
mechanism
     for managing DMA data transfers to and from devices.

     The  basic  abstraction  is the bus_dmamap_t, a pointer to a
structure which
     contains an array of  bus_dma_segment_t's  (dm_segs)  and  a
count of how
     many are currently valid (dm_nsegs).

     Each  segment  in the array describes a single physical area
of memory
     which can be DMA'd, with a starting address (ds_addr) and  a
length
     (ds_len).  These are the values that must be communicated to
the DMA device.
  Taken together the segments  exactly  and  completely
describe the
     buffer being used to transfer data.

     bus_dma_tag_t's  are  an  opaque  type, received from higher
software layers
     and are never created, changed, deleted or even examined  in
this interface.


     The basic cycle to transfer data to/from a DMA device is:

     bus_dmamap_create();          /* get a dmamap to load/unload
*/

     for each DMA xfer {
             bus_dmamem_alloc();  /* allocate some DMA'able memory        */
             bus_dmamem_map();     /*  map it into the kernel address space */

             /*
              * Fill the allocated DMA'able memory with  whatever
data
              *  is  to  be  sent out, using the pointer obtained
with
              * bus_dmamem_map().
              */

             bus_dmamap_load();   /* initialize the  segments  of
dmamap    */
             bus_dmamap_sync();    /*  synchronize/flush  any DMA
cache      */

             for (i=0; i<dm_nsegs; i++) {
                     /*
                      * Tell the DMA device the physical address
                      *  (dmamap->dm_segs[i].ds_addr)   and   the
length
                      * (dmamap->dm_segs[i].ds_len) of the memory
to xfer.
                      *
                      * Start the DMA, wait until it's done
                      */
             }

             bus_dmamap_sync();   /*  synchronize/flush  any  DMA
cache      */
             bus_dmamap_unload();  /*  prepare  dmamap  for reuse
*/

             /*
              * Copy any data desired from  the  DMA'able  memory
using the
              * pointer created by bus_dmamem_map().
              */

             bus_dmamem_unmap();   /* free kernel virtual address
space    */
             bus_dmamem_free();     /*   free   DMA'able   memory
*/
     }

     bus_dmamap_destroy();         /*  release any resources used
by dmamap */

DATA TYPES    [Toc]    [Back]

     Individual implementations may name these structures whatever they wish,
     providing that the external representations are:

     bus_addr_t          A  device bus address to be used for CPU
access or DMA.

     bus_size_t         The size of a bus address range.

     bus_dma_tag_t      A machine-dependent opaque type  describing the implementation
  of  DMA  for a given host/bus.
Machine-dependent
  code  is  responsible  for  passing
these structures
                        to  a  bus's autoconfiguration machinery,
which in turn
                        passes it down to the device drivers.

     bus_dma_segment_t  A structure describing an individual  DMA
segment.  The
                        structure may have machine-dependent members and arbitrary
 layout, but has at least  the  following members:

                                bus_addr_t      ds_addr;
                                bus_size_t      ds_len;

                        The  values  in  ds_addr  and  ds_len are
suitable for programming
 into a DMA controller's  address
and length
                        registers.

     bus_dmamap_t        A  pointer  to a structure describing an
individual DMA
                        mapping.  The structure may have machinedependent
                        members  and arbitrary layout, but has at
least the
                        following members:

                                int                dm_nsegs;
                                bus_dma_segment_t *dm_segs;

                        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.

DMA MAPS    [Toc]    [Back]

     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);

     The  bus_dmamap_create() function allocates a DMA handle and
initializes
     it according to the parameters provided.  This function  returns 0 on success,
 an error code otherwise.

     The bus_dmamap_create() arguments are as follows:
     tag         This  is  the bus_dma_tag_t passed down from the
parent driver
                via <bus>_attach_args.
     size       This is the maximum  DMA  transfer  that  can  be
mapped by the
                handle.
     nsegments   Number  of  segments the device can support in a
single DMA
                transaction.  This may be the number of  scattergather descriptors
 supported by the device.
     maxsegsz    The  maximum  number of bytes that may be transferred by any
                given DMA segment.
     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
  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      Flags are defined as follows:
                BUS_DMA_WAITOK    It is safe to wait (sleep)  for
resources
                                  during this call.
                BUS_DMA_NOWAIT     It is not safe to wait (sleep)
for resources
                                  during this call.
                BUS_DMA_ALLOCNOW  Perform any resource allocation
this handle
                                  may  need  now.  If this is not
specified, the
                                  allocation may be deferred to
                                  bus_dmamap_load().    If   this
flag is specified,
   bus_dmamap_load()  will
not block on
                                  resource allocation.
                BUS_DMA_BUS[1-4]  These flags  are  placeholders,
and may be
                                  used  by busses to provide busdependent
                                  functionality.
     dmamp      This is a pointer to a bus_dmamap_t.  A  DMA  map
will be allocated
  and  pointed  to  by dmamp upon successful
completion of
                this routine.

     The bus_dmamap_destroy() function frees all resources  associated with a
     given  DMA  handle.   This function always succeeds if given
valid arguments.


     The bus_dmamap_destroy() arguments are as follows:
     tag   This is the bus_dma_tag_t passed down from the  parent
driver via
           <bus>_attach_args.
     dmam  The DMA handle to destroy.

     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().

DMA MAP SEGMENTS    [Toc]    [Back]

     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);

     The  bus_dmamap_load() function loads a DMA handle with mappings for a DMA
     transfer.  It assumes that  all  pages  involved  in  a  DMA
transfer are
     wired.   This  function  returns 0 on success, an error code
otherwise.

     The bus_dmamap_load() arguments are as follows:
     tag     This is the bus_dma_tag_t passed down from the  parent driver via
             <bus>_attach_args.
     dmam    The DMA handle with which to map the transfer.
     buf     The buffer to be used for the DMA transfer.
     buflen  The size of the buffer.
     p        Used  to  indicate  the  address space in which the
buffer is located.
  If NULL, the buffer is assumed to be in  kernel
space.  Otherwise,
  the  buffer is assumed to be in process p's
address space.
     flags   Flags are defined as follows:
             BUS_DMA_WAITOK     It is safe to  wait  (sleep)  for
resources during
 this call.
             BUS_DMA_NOWAIT      It  is  not safe to wait (sleep)
for resources
                                during this call.
             BUS_DMA_BUS[1-4]   These flags are placeholders, and
may be used
                                by  busses  to provide bus-dependent functionality.

             BUS_DMA_STREAMING  By default, the 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       This is a hint to the machine-dependent backend
 that  indicates  the  mapping
will be used
                                only   for  a  device  ->  memory
transaction.  The
                                back-end  may  perform  optimizations based on
                                this information.
             BUS_DMA_WRITE      This is a hint to the machine-dependent backend
 that  indicates  the  mapping
will be used
                                only   for  a  memory  ->  device
transaction.  The
                                back-end  may  perform  optimizations based on
                                this information.

     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.

     The   bus_dmamap_load_mbuf()  function  is  a  variation  of
bus_dmamap_load()
     which maps mbuf chains for DMA transfers.  Mbuf  chains  are
assumed to be
     in kernel virtual address space.

     The   bus_dmamap_load_uio()   function  is  a  variation  of
bus_dmamap_load()
     which maps buffers pointed to by uio for DMA transfers.  The
value of
     uio->uio_segflg will determine if the buffers are in user or
kernel virtual
 address space.  If the  buffers  are  in  user  address
space, the
     buffers are assumed to be in uio->uio_procp's address space.

     The  bus_dmamap_load_raw()  function  is  a   variation   of
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.

     The  bus_dmamap_unload() function deletes the mappings for a
given DMA
     handle.  This function always succeeds if given valid  arguments.

     The bus_dmamap_unload() arguments are as follows:
     tag    This is the bus_dma_tag_t passed down from the parent
driver via
           <bus>_attach_args.
     dmam  The DMA handle containing the mappings which are to be
deleted.

     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.

SYNCHRONIZATION    [Toc]    [Back]

     void
     bus_dmamap_sync(bus_dma_tag_t    tag,   bus_dmamap_t   dmam,
bus_addr_t offset,
             bus_size_t size, bus_dmasync_op_t ops);

     The bus_dmamap_sync() function performs  pre-  and  post-DMA
operation cache
     and/or  buffer  synchronization.   This function always succeeds if given
     valid arguments.

     The bus_dmamap_sync() arguments are as follows:
     tag   This is the bus_dma_tag_t passed down from the  parent
driver via
           <bus>_attach_args.
     dmam  The DMA mapping to be synchronized.
     offset
           Offset in the DMA mapping to be synchronized.
     size  The size of the region to be synchronized.
     ops    One  or  more  synchronization operations to perform.
The following
           DMA synchronization operations are defined:
           BUS_DMASYNC_PREREAD    Perform any pre-read DMA  cache
and/or bounce
                                  operations.
           BUS_DMASYNC_POSTREAD   Perform any post-read DMA cache
and/or
                                  bounce operations.
           BUS_DMASYNC_PREWRITE   Perform any pre-write DMA cache
and/or
                                  bounce operations.
           BUS_DMASYNC_POSTWRITE    Perform  any  post-write  DMA
cache and/or
                                  bounce operations.

           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    reordered   stores,
bus_dmamap_sync() will always
 cause the store buffer to be flushed.

     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
     like:

     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(...);

     If  DMA  read and write operations are not preceded and followed by the appropriate
 synchronization operations, behavior is undefined.

DMA-SAFE MEMORY    [Toc]    [Back]

     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);

     The  bus_dmamem_alloc()  function  allocates  memory that is
"DMA safe" for
     the bus corresponding to the given tag.  This  function  returns 0 on success,
 or an error code indicating mode of failure.

     The   mapping   of  this  memory  is  machine-dependent  (or
"opaque"); machineindependent
 code should not 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.

     The bus_dmamem_alloc() arguments are as follows:
     tag         This  is  the bus_dma_tag_t passed down from the
parent driver
                via <bus>_attach_args.
     size       The amount of memory to allocate.
     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.
     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.
     segs       An array of  bus_dma_segment_t's,  filled  in  as
memory is allocated,
  representing  the opaque addresses of the
memory chunks.
     nsegs      Specifies the number of  segments  in  segs,  and
this is the maximum
 number of segments that the allocated memory
may contain.
     rsegs      Used to return the actual number of segments  the
memory contains.

     flags      Flags are defined as follows:
                BUS_DMA_WAITOK     It is safe to wait (sleep) for
resources
                                   during this call.
                BUS_DMA_NOWAIT     It is not safe to wait (sleep)
for resources
 during this call.
                BUS_DMA_STREAMING   Adjusts,  if  necessary,  the
size, alignment,
                                   and  boundary  constraints  to
conform to the
                                   platform-dependent    requirements for the use
                                   of the 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]   These flags are  placeholders,
and may be
                                   used by busses to provide busdependent
                                   functionality.

     All pages allocated by bus_dmamem_alloc() will be wired down
until they
     are freed by bus_dmamem_free().

     The bus_dmamem_free() function frees memory previously allocated by
     bus_dmamem_alloc(), invalidating any mapping.  This function
always succeeds
 if given valid arguments.

     The bus_dmamem_free() arguments are as follows:
     tag    This is the bus_dma_tag_t passed down from the parent
driver via
            <bus>_attach_args.
     segs    The  array  of  bus_dma_segment_t's  filled  in   by
bus_dmamem_alloc().
     nsegs  The number of segments in segs.

MAPPING DMA-SAFE MEMORY    [Toc]    [Back]

     int
     bus_dmamem_map(bus_dma_tag_t  tag,  bus_dma_segment_t *segs,
int nsegs,
             size_t size, caddr_t *kvap, int flags);

     void
     bus_dmamem_unmap(bus_dma_tag_t  tag,  caddr_t  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);

     The bus_dmamem_map() function maps memory allocated with
     bus_dmamem_alloc() into kernel virtual address space.   This
function returns
 0 on success, an error code otherwise, and must not be
called from
     an interrupt context.

     The bus_dmamem_map() arguments are as follows:
     tag    This is the bus_dma_tag_t passed down from the parent
driver via
            <bus>_attach_args.
     segs     The  array  of  bus_dma_segment_t's  filled  in  by
bus_dmamem_alloc(),
            representing the memory regions to map.
     nsegs  The number of segments in segs.
     size   The size of the mapping.
     kvap   Filled in to specify the kernel virtual address where
the memory
            is mapped.
     flags  Flags are defined as follows:
            BUS_DMA_WAITOK     It is safe to wait (sleep) for resources during
                              this call.
            BUS_DMA_NOWAIT    It is not safe to wait (sleep)  for
resources
                              during this call.
            BUS_DMA_BUS[1-4]   These  flags are placeholders, and
may be used by
                              busses  to  provide   bus-dependent
functionality.
            BUS_DMA_COHERENT   This flag is a 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 implementation of  DMA  coherent
mappings is
                              impossible, this is ignored.

                              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().

     The  bus_dmamem_unmap()  function  unmaps  memory previously
mapped with
     bus_dmamem_map(), freeing the kernel virtual  address  space
used by the
     mapping.  This function always succeeds if given valid arguments, but
     must not be called from an interrupt context.

     bus_dmamem_unmap() arguments are as follows:
     tag   This is the bus_dma_tag_t passed down from the  parent
driver via
           <bus>_attach_args.
     kva   The kernel virtual address of the mapped memory.
     size  The size of the mapping.

     The  bus_dmamem_mmap()  function  provides  support for user
mmap(2)'ing of
     DMA-safe memory.  bus_dmamem_mmap() 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.  This function returns an opaque value to
be interpreted
   by   the   device   pager,   or   -1   on  failure.
bus_dmamem_mmap() arguments
 are as follows:
     tag    This is the bus_dma_tag_t passed down from the parent
driver via
            <bus>_attach_args.
     segs     The  array  of  bus_dma_segment_t's  filled  in  by
bus_dmamem_alloc(),
            representing the memory to be mmap(2)'ed.
     nsegs  The number of elements in the segs array.
     off    The offset of the page in DMA memory which is  to  be
mapped.
     prot   The protection codes for the mapping.
     flags  Flags are defined as follows:
            BUS_DMA_WAITOK     It is safe to wait (sleep) for resources during
                              this call.
            BUS_DMA_NOWAIT    It is not safe to wait (sleep)  for
resources
                              during this call.
            BUS_DMA_BUS[1-4]   These  flags are placeholders, and
may be used by
                              busses  to  provide   bus-dependent
functionality.
            BUS_DMA_COHERENT   See  bus_dmamem_map()  above for a
description of
                              this flag.

SEE ALSO    [Toc]    [Back]

      
      
     bus_space(9)

HISTORY    [Toc]    [Back]

     The bus_dma interface appeared in NetBSD 1.3.

AUTHORS    [Toc]    [Back]

     The 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.

OpenBSD     3.6                        November     23,      2000
[ Back ]
 Similar pages
Name OS Title
wscons NetBSD machine-independent console support
wdc NetBSD machine-independent IDE/ATAPI driver
softintr NetBSD machine-independent software interrupt framework
softintr_disestablish NetBSD machine-independent software interrupt framework
softintr_schedule NetBSD machine-independent software interrupt framework
softintr_establish NetBSD machine-independent software interrupt framework
eisa OpenBSD introduction to EISA bus machine-independent drivers and support
pmap_update OpenBSD machine dependent interface to the MMU
pmap_init OpenBSD machine dependent interface to the MMU
pmap_virtual_space OpenBSD machine dependent interface to the MMU
Copyright © 2004-2005 DeniX Solutions SRL
newsletter delivery service