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
As shipped in IRIX 6.5.15. Last changed in IRIX 6.5.15.
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, iopaddr_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, iopaddr_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, iopaddr_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.