|Return to 3.me CVS log||Up to [cvs.NetBSD.org] / src / share / doc / papers / bus_dma|
|File: [cvs.NetBSD.org] / src / share / doc / papers / bus_dma / 3.me (download)
Revision 1.2, Wed Feb 5 00:02:26 2003 UTC (18 years, 2 months ago) by perry
"Utilize" has exactly the same meaning as "use," but it is more difficult to read and understand. Most manuals of English style therefore say that you should use "use".
.\" $NetBSD: 3.me,v 1.2 2003/02/05 00:02:26 perry Exp $ .\" .\" Copyright (c) 1998 Jason R. Thorpe. .\" All rights reserved. .\" .\" 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. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgements: .\" This product includes software developed for the NetBSD Project .\" by Jason R. Thorpe. .\" 4. The name of the author may not be used to endorse or promote products .\" derived from this software without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. .\" .sh 1 "The \fIbus_dma\fB interface" .pp What follows is a description of \fIbus_dma\fR, the DMA portion of the machine-independent bus access interface in NetBSD, commonly referred to as \fIbus.h\fR\**. The DMA portion of the interface is comprised of three DMA-specific data types and thirteen function calls. The \fIbus_dma\fR interface also shares two data types with the \fIbus_space\fR interface. .(f \**The name is derived from the name of the include file that exports the interface. .)f .pp The \fIbus_dma\fR functional interface is split into two categories: mapping calls and memory handling calls. The function calls themselves may be implemented as \fIcpp(1)\fR macros. .sh 2 "Data types" .pp The first of the two data types shared with the \fIbus_space\fR interface is the \fIbus_addr_t\fR type, which represents device bus addresses to be used for CPU access or DMA, and must be large enough to specify the largest possible bus address on the system. The second is the \fIbus_size_t\fR type, which represents sizes of bus address ranges. .pp The implementation of DMA on a given host/bus combination is described by the \fIbus_dma_tag_t\fR. This opaque type is passed to a bus's autoconfiguration machinery by machine-dependent code. The bus layer in turn passes it down to the device drivers. This tag is the first argument to every function in the interface. .pp Individual DMA segments are described by the \fIbus_dma_segment_t\fR. This type is a structure with two publicly accessible members. The first member, \fIds_addr\fR, is a \fIbus_addr_t\fR containing the address of a DMA segment. The second, \fIds_len\fR, is a \fIbus_size_t\fR containing the length of the segment. .pp The third, and probably most important, data type is the \fIbus_dmamap_t\fR. This type is a pointer to a structure which describes an individual DMA mapping. The structure has three public members. The first member, \fIdm_mapsize\fR is a \fIbus_size_t\fR describing the length of the mapping, when valid. A \fIdm_mapsize\fR of 0 indicates that the mapping is invalid. The second member, \fIdm_nsegs\fR, is an \fIint\fR which contains the number of DMA segments that comprise the mapping. The third public member, \fIdm_segs\fR, is an array or a pointer to an array of \fIbus_dma_segment_t\fR structures. .pp In addition to data types, the \fIbus_dma\fR interface also defines a set of flags which are passed to some of the interface's functions. Two of these flags, \fBBUS_DMA_WAITOK\fR and \fBBUS_DMA_NOWAIT\fR, indicate to the function that waiting for resources to become available is or is not allowed\**. There are also four placeholder flags, \fBBUS_DMA_BUS1\fR through \fBBUS_DMA_BUS4\fR. These flags are reserved for the individual bus layers, which may need to define special semantics specific to that bus. An example of this is the ability of VESA local bus devices to use 32-bit DMA addresses; while the kernel considers such devices to be logically connected to the ISA bus, they are not limited to the addressing constraints of other ISA devices. The placeholder flags allow such special cases to be handled on a bus-by-bus basis. .(f \**Waiting (also called "blocking") is allowed only if the kernel is running in a process context, as opposed to the interrupt context used when handling device interrupts. .)f .sh 2 "Mapping functions" .pp There are eight functions in the \fIbus_dma\fR interface that operate on DMA maps. These can be sub-categorized into functions that create and destroy maps, functions that load and unload mappings, and functions that synchronize maps. .pp The first two functions fall into the create/destroy sub-category. The \fIbus_dmamap_create()\fR function creates a DMA map and initializes it according to the parameters provided. The parameters include the maximum DMA transfer size the DMA map will map, the maximum number of DMA segments, the maximum size of any given segment, and any DMA boundary limitations. In addition to the standard flags, \fIbus_dmamap_create()\fR also takes the flag \fBBUS_DMA_ALLOCNOW\fR. This flag indicates that all resources necessary to map the maximum size transfer should be allocated when the map is created, and is useful in case the driver must load the DMA map at a time where blocking is not allowed, such as in interrupt context. The \fIbus_dmamap_destroy()\fR function destroys a DMA map, and frees any resources that may be assigned to it. .pp The next five functions fall into the load/unload sub-category. The two basic functions are \fIbus_dmamap_load()\fR and \fIbus_dmamap_unload()\fR. The former maps a DMA transfer to or from a linear buffer. This linear buffer may be mapped into either kernel or a process's virtual address space. The latter unloads the mappings previously loaded into the DMA map. If the \fBBUS_DMA_ALLOCNOW\fR flag was specified when the map was created, \fIbus_dmamap_load()\fR will not block or fail on resource allocation. Similarly, when the map is unloaded, the mapping resources will not be freed. .pp In addition to linear buffers handled by the basic \fIbus_dmamap_load()\fR, there are three alternate data buffer structures handled by the interface. The \fIbus_dmamap_load_mbuf()\fR function operates on mbuf chains. The individual data buffers are assumed to be in kernel virtual address space. The \fIbus_dmamap_load_uio()\fR function operates on \fIuio\fR structures, from which it extracts information about the address space in which the data resides. Finally, the \fIbus_dmamap_load_raw()\fR function operates on raw memory, which is not mapped into any virtual address space. All DMA maps loaded with these functions are unloaded with the \fIbus_dmamap_unload()\fR function. .pp Finally, the map synchronization sub-category includes one function: \fIbus_dmamap_sync()\fR. This function performs the four DMA synchronization operations necessary to handle caches and DMA bouncing. The four operations are: .(b .b BUS_DMASYNC_PREREAD BUS_DMASYNC_POSTREAD BUS_DMASYNC_PREWRITE BUS_DMASYNC_POSTWRITE .r .)b The direction is expressed from the perspective of the host's memory. In other words, a device-to-memory transfer is a read, and a memory-to-device transfer is a write. The synchronization operations are expressed as flags, so it is possible to combine \fBREAD\fR and \fBWRITE\fR operations in a single call. This is especially useful for synchronizing mappings of device control descriptors. Mixing of \fBPRE\fR and \fBPOST\fR operations is not allowed. .pp In addition to the map and operation arguments, \fIbus_dmamap_sync()\fR also takes offset and length arguments. This is done in order to support partial syncs. In the case where a control descriptor is DMA'd to a device, it may be undesirable to synchronize the entire mapping, as doing so may be inefficient or even destructive to other control descriptors. Synchronizing the entire mapping is supported by passing an offset of 0 and the length specified by the map's \fIdm_mapsize\fR. .sh 2 "Memory handling functions" .pp There are two sub-categories of functions that handle DMA-safe memory in the \fIbus_dma\fR interface: memory allocation and memory mapping. .pp The first function in the memory allocation sub-category, \fIbus_dmamem_alloc()\fR, allocates memory which has the specified attributes. The attributes that may be specified are: the size of the memory region to allocate, the alignment of each segment in the allocation, any boundary limitations, and the maximum number of DMA segments that may make up the allocation. The function fills in a provided array of \fIbus_dma_segment_t\fRs and indicates the number of valid segments in the array. Memory allocated by this interface is raw memory\**; it is not mapped into any virtual address space. Once it is no longer in use, it may be freed with the \fIbus_dmamem_free()\fR function. .(f \**This implies that \fIbus_dmamap_load_raw()\fR is an appropriate interface for mapping a DMA transfer to or from memory allocated by this interface. .)f .pp In order for the kernel or a user process to access the memory, it must be mapped either into the kernel address space or the process's address space. These operations are performed by the memory mapping sub-category of DMA-safe memory handling functions. The \fIbus_dmamem_map()\fR function maps the specified DMA-safe raw memory into the kernel address space. The address of the mapping is returned by filling in a pointer passed by reference. Memory mapped in this manner may be unmapped by calling \fIbus_dmamem_unmap()\fR. .pp DMA-safe raw memory may be mapped into a process's address space via a device driver's \fImmap()\fR entry point. In order to do this, the VM system's device pager repeatedly calls the driver, once for each page that is to be mapped. The driver translates the user-specified mmap offset into a DMA memory offset, and calls the \fIbus_dmamem_mmap()\fR function to translate the memory offset into an opaque value to be interpreted by the \fIpmap module\**\fR. The device pager invokes the pmap module to translate the mmap cookie into a physical page address which is then mapped into the process's address space. .(f \**The pmap module is the machine-dependent layer of the NetBSD virtual memory system. .)f .pp There are currently no methods for the virtual memory system to specify that an mmap'd area is being unmapped, or for the device driver to specify to the virtual memory system that a mmap'd region must be forcibly unmapped (for example, if a hot-swapable device has been removed from the system). This is widely regarded as a bug, and may be addressed in a future version of the NetBSD virtual memory system. If a change to this effect is made, the \fIbus_dma\fR interface will have to be adjusted accordingly.