pciio_dma(D3)

pciio_dma: pciio_dmatrans_addr, pciio_dmatrans_list, pciio_dmamap_alloc, pciio_dmamap_addr, pciio_dmamap_list, pciio_dmamap_done, pciio_dmamap_free, pciio_dma_addr, pciio_dmamap_drain, pciio_dmaaddr_drain, pciio_dmalist_drain - manage DMA on PCI bus

Showing IRIX 6.5.30 (default release). Last changed in IRIX 6.5.19.

NAME
     pciio_dma: pciio_dmatrans_addr, pciio_dmatrans_list, pciio_dmamap_alloc,
     pciio_dmamap_addr, pciio_dmamap_list, pciio_dmamap_done,
     pciio_dmamap_free, pciio_dma_addr, pciio_dmamap_drain,
     pciio_dmaaddr_drain, pciio_dmalist_drain - manage DMA on PCI bus

SYNOPSIS
     #include <sys/PCI/pciio.h>

     iopaddr_t
     pciio_dmatrans_addr(
          vertex_hdl_t vhdl,
          device_desc_t desc,
          paddr_t addr,
          size_t size,
          unsigned flags)

     alenlist_t
     pciio_dmatrans_list(
          vertex_hdl_t vhdl,
          device_desc_t desc,
          alenlist_t list,
          unsigned flags)

     pciio_dmamap_t
     pciio_dmamap_alloc(
          vertex_hdl_t vhdl,
          device_desc_t desc,
          size_t max,
          unsigned flags)

     iopaddr_t
     pciio_dmamap_addr(
          pciio_dmamap_t map,
          paddr_t addr,
          size_t size);

     alenlist_t
     pciio_dmamap_list(
          pciio_dmamap_t map,
          alenlist_t list,
          unsigned flags);

     void
     pciio_dmamap_done(pciio_dmamap_t map)

     void
     pciio_dmamap_free(pciio_dmamap_t map)

     iopaddr_t
     pciio_dma_addr(
          vertex_hdl_t vhdl,
         device_desc_t desc,
          paddr_t addr,
          size_t size,
          pciio_dmamap_t *mapp,
          unsigned flags)

     void
     pciio_dmamap_drain(
          pciio_dmamap_t *map)

     void
     pciio_dmaaddr_drain(
          vertex_hdl_t vhdl,
          paddr_t addr,
          size_t bytes)

     void
     pciio_dmalist_drain(
          vertex_hdl_t vhdl,
          alenlist_t *list)

   Arguments
     addr The DMA buffer address in system physical address space.

     desc A device descriptor, usually zero.

     flags
          Attributes of the mapping.

     list An address/length list as prepared by one of the alenlist
          construction functions (see alenlist(D4)).

     map  A dma map as returned by pciio_dmamap_alloc().

     mapp A place to return a map allocated as a side effect of other work;
          must be initialized to zero, or to a map that should be used instead
          of allocating one.

     max  The maximum range of addresses this map will cover at any one time.

     size The size of the mapped buffer in bytes.

     vhdl    The device connection point as passed to the attach() entry
             point.

DESCRIPTION
     When a device driver wishes to use Direct Memory Access (DMA) to
     communicate with a device, the system needs to have a chance to set up
     any appropriate mapping registers.  The work to be done varies with the
     available hardware and with the version of IRIX.  The functions described
     here provide an abstract interface to the creation of DMA mapping objects
     that is consistent across most hardware.  These functions always do the
     least possible work given the available hardware.

     There are two different models for setting up a DMA map, one simple but
     fallible and the other more general.  In both models, the final goal is
     to retrieve an address in PCI bus address space that can be used by a PCI
     device to write into, or read from, system physical memory.

   Simple Model
     The simple model provides permanent mappings through fixed mapping
     resources that may or may not exist in a given system at a given time.
     pciio_dmatrans_addr() is the one-stop shopping place for using system
     fixed shareable mapping resources to construct a DMA address.  This is
     not always possible.  When it is not, the function returns NULL.

     pciio_dmatrans_list() is similar, but operates on a list of blocks of
     memory and returns a list of blocks in PCI address space.

     When they work, these functions allow the driver to set up DMA with the
     fewest complications.  Typically the functions always succeed in some
     platforms (those having simple hardware mappings of PCI to memory), and
     always fail in other platforms (where multiple layers of hardware
     mappings must be configured dynamically).  However, drivers that use them
     should be coded as if the functions could succeed or fail alternately in
     the same system (which they could).

   General Model
     It is not always possible to establish DMA mappings using common shared
     system resources, so the concept of a DMA channel that preallocates
     scarce mapping resources is provided.

     Such a channel is allocated using pciio_dmamap_alloc(), which is given
     the maximum size to be mapped.  pciio_dmamap_addr() or
     pciio_dmamap_list() is then applied to the map to actually establish the
     proper mappings for a DMA target.  Given the base address and block size
     of the buffer for DMA (or a list of buffers), the functions hand back the
     base PCI address to use for accessing that buffer (or a list of PCI
     addresses).

     pciio_dmamap_drain(), pciio_dmaaddr_drain() or pciio_dmalist_drain() are
     used (depending on how the mapping was created) after a device reports it
     has completed DMA, to ensure that all data along the DMA path has in fact
     reached its destination.

     When all DMA to a given buffer (or list) is complete, pciio_dmamap_done()
     should be called to idle any mapping hardware (and possibly flush out any
     pipes or buffers along the path that might do unexpected things when
     mapping registers are modified).  Later, pciio_dmamap_addr() or
     pciio_dmamap_list() can again be called, specifying the same or another
     buffer area.

     When a driver is completely finished with a DMA channel -- because the
     channel is used only for initialization of the device, because the
     driver's close() entry point is called so it is known that the device
     will be idle for some time, or because the device or the driver is being
     shut down -- the DMA channel resources should be released using
     pciio_dmamap_free().

     pciio_dma_addr() combines pciio_dmatrans_addr() and the
     pciio_dmamap_alloc() / pciio_dmamap_addr() facilities; it attempts to do
     the direct translation, and if that fails, allocates a dmamap and
     attempts to map through it.  The mapp parameter should point to a
     pciio_dmamap_t which has been either set to NULL, or set to a map that
     should be used if one is needed.  On return, the value will be cleared if
     the direct translation worked, or set to the map that was used.

   DMA Attribute Flags
     The following attributes are specified in the flags argument:

     PCIIO_FIXED specifies that all DMA translations are done using fixed
                 shared resources.  The results of those translations remain
                 valid permanently, even if the map resource is subsequently
                 used to obtain additional mappings.  Fixed shared resources
                 are not always available.

     PCIIO_NOSLEEP
                 specifies that any resources that are needed from the system
                 are allocated without sleeping.  If any resource allocation
                 would require the infrastructure to sleep, the service call
                 returns a failure code.

     PCIIO_INPLACE
                 on a list operation requests that the input list be modified
                 in place.  When this flag is not specified, a new list is
                 allocated for the translated addresses.  Allocating a new
                 list preserves the contents of the input list.  However, it
                 can take longer, may require sleeping, and may fail
                 (especially if PCIIO_NOSLEEP is specified).

     PCIIO_DMA_CMD
                 specifies that the DMA channel will be used for command-type
                 transactions.  The channel is set up to optimize short
                 transactions with frequent changes of direction.  Unless a
                 more specific request is made using one of the other flags,
                 any prefetch and write-gatherer hardware in the path is
                 disabled.

     PCIIO_DMA_DATA
                 specifies that the DMA channel will be used for data-type
                 transactions.  The channel is set up to optimize longer
                 transfers.  Unless a more specific request is made using one
                 of the other flags, any prefetch and write-gatherer hardware
                 in the path may be enabled.
     PCIIO_DMA_A64
                 indicates that the device is capable of using 64-bit PCI
                 addresses for DMA.  If this flag is not specified, only DMA
                 addresses in the low 4GB of PCI address space can be
                 generated.  On some systems, 32-bit PCI addresses are a
                 limited resource.  The map request fails if a 32-bit region
                 cannot be allocated.

     PCIIO_WRITE_GATHER
                 indicates that the device driver believes turning on write-
                 gather hardware for this DMA channel is a good thing.  The
                 flag overrides the write-gather choice from PCIIO_DMA_CMD.

     PCIIO_NOWRITE_GATHER
                 indicates that the device driver believes turning on write-
                 gather hardware for this DMA channel is a bad thing.  The
                 flag overrides the write gather choice from PCIIO_DMA_DATA.

     PCIIO_PREFETCH
                 indicates that the device driver believes turning on
                 prefetching hardware for this DMA channel is a good thing.
                 The flag overrides the prefetch choice from PCIIO_DMA_CMD.

     PCIIO_NOPREFETCH
                 indicates that the device driver believes turning on
                 prefetching hardware for this DMA channel is a bad thing.
                 The flag overrides the prefetch settings from PCIIO_DMA_DATA.

     PCIIO_BYTE_STREAM
                 demands that any byte-swapping hardware along this DMA path
                 be organized so that an ordered stream of bytes from the
                 device are deposited in order in system memory.  This is the
                 typical setting for data streams.  If this endianness cannot
                 be supplied, then the service call fails.

     PCIIO_WORD_VALUES
                 demands that any byte-swapping hardware along this DMA path
                 be initialized so that 32-bit quantities on PCI-bus 32-bit
                 boundaries maintain their binary values.  This is the typical
                 setting for command-type transactions because command words
                 exchanged with a little-endian PCI device retain their binary
                 values.  If this endianness cannot be supplied, then the
                 service call fails.

     When PCIIO_BYTE_STREAM is used, the bytes of multibyte values embedded in
     input data are found at their original offsets.  Multibyte values from
     little-endian devices may require programmed swapping before use.

     When PCIIO_WORD_VALUES is used,

     o   Single bytes in input data are found at the offset the device places
         them, exclusive-or with 3.

     o   16-bit quantities in input data are found at the offset used by the
         device, exclusive-or with 2, and do not need to be byteswapped.

     o   32-bit values are found at the expected offset, and do not need to be
         byteswapped.

     o   64-bit values are found at the expected offset, and their 32-bit
         halves need to be swapped before use.

EXAMPLES
     Here is one way that a driver might make use of dmamap and dmatrans
     calls.

          pcifoo_attach(vertex_hdl_t vhdl)
          {
               pciio_dmamap_t command_map;
               iopaddr_t command_dma;
               struct pcifoo_regs  *reg_pio;
               struct pcifoo_ring  *command_ring;
               ...
               /*
                * This driver has decided to use a dmamap
                * to get to its command rings, which contain
                * things like DMA addresses and counts; we
                * set PCIIO_WORD_VALUES so we don't have to
                * byteswap the 32-bit values.
                *
                * We still have to swap the upper and lower
                * halves of the 64-bit values.
                */
               /* allocate the channel
                */
               command_map = pciio_dmamap_alloc(
                    vhdl, 0,
                    RINGBYTES,
                    PCIIO_DMA_CMD |
                    PCIIO_WORD_VALUES);
               command_dma = pciio_dmamap_addr(
                    command_map,
                    kvtophys(command_ring),
                    RINGBYTES);
               /* tell the device where it can find
                * it's command rings.
                */
               reg_pio->command_dma = command_dma;
               ...
          }
          {
               caddr_t   data_buffer;
              size_t     data_size;
               ...
               data_dma = pciio_dmatrans_addr(
                    vhdl, 0,
                    kvtophys(data_buffer), data_size,
                    PCIIO_DMA_DATA|
                    PCIIO_DMA_A64|
                    PCIIO_BYTE_STREAM);
               command_ring->data_dma_lo = data_dma & 0xFFFFFFFF;
               command_ring->data_dma_hi = data_dma >> 32;
               command_ring->data_dma_size = data_size;
               command_ring->ready = 1;
          }


SEE ALSO
     alenlist(D3), pcibr_get_dmatrans_node(D3), pciio(D3), pciio_config(D3),
     pciio_error(D3), pciio_get(D3), pciio_intr(D3), pciio_pio(D3).

NOTE
     Do not point the mapp parameter to the pciio_dma_addr() function at your
     only copy of a map pointer, since it will write a NULL through this
     pointer when direct translations work.

     In IRIX 6.3, pciio_dmatrans_list() is declared and implemented with two
     arguments only, taking no flags argument.  When porting a driver from
     IRIX 6.3, add a third argument of NULL (or other flag values as desired).

DIAGNOSTICS
     pciio_dmatrans_addr() returns zero if shared (fixed) resources can not be
     used to construct a valid PCI address that maps to the desired range of
     physical addresses.

     pciio_dmatrans_list() returns a null pointer if any of the requested
     physical address blocks can not be reached using shared fixed resources,
     or if unable to allocate a return list.

     pciio_dmamap_alloc() returns a null pointer if resources can not be
     allocated to establish DMA mappings of the requested size, or if the
     parameters are inconsistent.

     pciio_dmamap_addr() returns zero if the specified target address can not
     be mapped using the specified DMA channel.  This would usually be due to
     specifying a target block that is outside the previously specified target
     area or is larger than the previously specified maximum mapping size.  It
     may also return a null pointer if the DMA channel is currently in use and
     has not been marked idle by a call to pciio_dmamap_done().

     pciio_dmamap_list() can return a null pointer for all the reasons
     mentioned above, or if it is unable to allocate the return list.