1.\" Copyright (c) 2002, 2003 Hiten M. Pandya. 2.\" All rights reserved. 3.\" 4.\" Redistribution and use in source and binary forms, with or without 5.\" modification, are permitted provided that the following conditions 6.\" are met: 7.\" 1. Redistributions of source code must retain the above copyright 8.\" notice, this list of conditions, and the following disclaimer, 9.\" without modification, immediately at the beginning of the file. 10.\" 2. The name of the author may not be used to endorse or promote products 11.\" derived from this software without specific prior written permission. 12.\" 13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR, CONTRIBUTORS OR THE 17.\" VOICES IN HITEN PANDYA'S HEAD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 19.\" TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20.\" PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 21.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 22.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 23.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24.\" 25.\" Copyright (c) 1996, 1997, 1998, 2001 The NetBSD Foundation, Inc. 26.\" All rights reserved. 27.\" 28.\" This code is derived from software contributed to The NetBSD Foundation 29.\" by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 30.\" NASA Ames Research Center. 31.\" 32.\" Redistribution and use in source and binary forms, with or without 33.\" modification, are permitted provided that the following conditions 34.\" are met: 35.\" 1. Redistributions of source code must retain the above copyright 36.\" notice, this list of conditions and the following disclaimer. 37.\" 2. Redistributions in binary form must reproduce the above copyright 38.\" notice, this list of conditions and the following disclaimer in the 39.\" documentation and/or other materials provided with the distribution. 40.\" 41.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 42.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 43.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 44.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 45.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 46.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 47.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 48.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 49.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 50.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 51.\" POSSIBILITY OF SUCH DAMAGE. 52.\" $NetBSD: bus_dma.9,v 1.25 2002/10/14 13:43:16 wiz Exp $ 53.\" 54.Dd May 25, 2020 55.Dt BUS_DMA 9 56.Os 57.Sh NAME 58.Nm bus_dma , 59.Nm bus_dma_tag_create , 60.Nm bus_dma_tag_destroy , 61.Nm bus_dma_template_init , 62.Nm bus_dma_template_tag , 63.Nm bus_dma_template_clone , 64.Nm bus_dma_template_fill , 65.Nm BUS_DMA_TEMPLATE_FILL , 66.Nm bus_dmamap_create , 67.Nm bus_dmamap_destroy , 68.Nm bus_dmamap_load , 69.Nm bus_dmamap_load_bio , 70.Nm bus_dmamap_load_ccb , 71.Nm bus_dmamap_load_crp , 72.Nm bus_dmamap_load_crp_buffer , 73.Nm bus_dmamap_load_mbuf , 74.Nm bus_dmamap_load_mbuf_sg , 75.Nm bus_dmamap_load_uio , 76.Nm bus_dmamap_unload , 77.Nm bus_dmamap_sync , 78.Nm bus_dmamem_alloc , 79.Nm bus_dmamem_free 80.Nd Bus and Machine Independent DMA Mapping Interface 81.Sh SYNOPSIS 82.In machine/bus.h 83.Ft int 84.Fn bus_dma_tag_create "bus_dma_tag_t parent" "bus_size_t alignment" \ 85"bus_addr_t boundary" "bus_addr_t lowaddr" "bus_addr_t highaddr" \ 86"bus_dma_filter_t *filtfunc" "void *filtfuncarg" "bus_size_t maxsize" \ 87"int nsegments" "bus_size_t maxsegsz" "int flags" "bus_dma_lock_t *lockfunc" \ 88"void *lockfuncarg" "bus_dma_tag_t *dmat" 89.Ft int 90.Fn bus_dma_tag_destroy "bus_dma_tag_t dmat" 91.Ft void 92.Fo bus_dma_template_init 93.Fa "bus_dma_template_t *template" 94.Fa "bus_dma_tag_t parent" 95.Fc 96.Ft int 97.Fo bus_dma_template_tag 98.Fa "bus_dma_template_t *template" 99.Fa "bus_dma_tag_t *dmat" 100.Fc 101.Ft void 102.Fo bus_dma_template_clone 103.Fa "bus_dma_template_t *template" 104.Fa "bus_dma_tag_t dmat" 105.Fc 106.Ft void 107.Fo bus_dma_template_fill 108.Fa "bus_dma_template_t *template" 109.Fa "bus_dma_param_t params[]" 110.Fa "u_int count" 111.Fc 112.Fo BUS_DMA_TEMPLATE_FILL 113.Fa "bus_dma_template_t *template" 114.Fa "bus_dma_param_t param ..." 115.Fc 116.Ft int 117.Fn bus_dmamap_create "bus_dma_tag_t dmat" "int flags" "bus_dmamap_t *mapp" 118.Ft int 119.Fn bus_dmamap_destroy "bus_dma_tag_t dmat" "bus_dmamap_t map" 120.Ft int 121.Fn bus_dmamap_load "bus_dma_tag_t dmat" "bus_dmamap_t map" "void *buf" \ 122"bus_size_t buflen" "bus_dmamap_callback_t *callback" "void *callback_arg" \ 123"int flags" 124.Ft int 125.Fn bus_dmamap_load_bio "bus_dma_tag_t dmat" "bus_dmamap_t map" \ 126"struct bio *bio" "bus_dmamap_callback_t *callback" "void *callback_arg" \ 127"int flags" 128.Ft int 129.Fn bus_dmamap_load_ccb "bus_dma_tag_t dmat" "bus_dmamap_t map" \ 130"union ccb *ccb" "bus_dmamap_callback_t *callback" "void *callback_arg" \ 131"int flags" 132.Ft int 133.Fn bus_dmamap_load_crp "bus_dma_tag_t dmat" "bus_dmamap_t map" \ 134"struct crypto *crp" "bus_dmamap_callback_t *callback" "void *callback_arg" \ 135"int flags" 136.Ft int 137.Fn bus_dmamap_load_crp_buffer "bus_dma_tag_t dmat" "bus_dmamap_t map" \ 138"struct crypto_buffer *cb" "bus_dmamap_callback_t *callback" \ 139"void *callback_arg" "int flags" 140.Ft int 141.Fn bus_dmamap_load_mbuf "bus_dma_tag_t dmat" "bus_dmamap_t map" \ 142"struct mbuf *mbuf" "bus_dmamap_callback2_t *callback" "void *callback_arg" \ 143"int flags" 144.Ft int 145.Fn bus_dmamap_load_mbuf_sg "bus_dma_tag_t dmat" "bus_dmamap_t map" \ 146"struct mbuf *mbuf" "bus_dma_segment_t *segs" "int *nsegs" "int flags" 147.Ft int 148.Fn bus_dmamap_load_uio "bus_dma_tag_t dmat" "bus_dmamap_t map" \ 149"struct uio *uio" "bus_dmamap_callback2_t *callback" "void *callback_arg" \ 150"int flags" 151.Ft void 152.Fn bus_dmamap_unload "bus_dma_tag_t dmat" "bus_dmamap_t map" 153.Ft void 154.Fn bus_dmamap_sync "bus_dma_tag_t dmat" "bus_dmamap_t map" \ 155"op" 156.Ft int 157.Fn bus_dmamem_alloc "bus_dma_tag_t dmat" "void **vaddr" \ 158"int flags" "bus_dmamap_t *mapp" 159.Ft void 160.Fn bus_dmamem_free "bus_dma_tag_t dmat" "void *vaddr" \ 161"bus_dmamap_t map" 162.Sh DESCRIPTION 163Direct Memory Access (DMA) is a method of transferring data 164without involving the CPU, thus providing higher performance. 165A DMA transaction can be achieved between device to memory, 166device to device, or memory to memory. 167.Pp 168The 169.Nm 170API is a bus, device, and machine-independent (MI) interface to 171DMA mechanisms. 172It provides the client with flexibility and simplicity by 173abstracting machine dependent issues like setting up 174DMA mappings, handling cache issues, bus specific features 175and limitations. 176.Sh OVERVIEW 177A tag structure 178.Vt ( bus_dma_tag_t ) 179is used to describe the properties of a group of related DMA 180transactions. 181One way to view this is that a tag describes the limitations of a DMA engine. 182For example, if a DMA engine in a device is limited to 32-bit addresses, 183that limitation is specified by a parameter when creating the tag 184for that device. 185Similarly, a tag can be marked as requiring buffers whose addresses are 186aligned to a specific boundary. 187.Pp 188Some devices may require multiple tags to describe DMA 189transactions with differing properties. 190For example, a device might require 16-byte alignment of its descriptor ring 191while permitting arbitrary alignment of I/O buffers. 192In this case, 193the driver must create one tag for the descriptor ring and a separate tag for 194I/O buffers. 195If a device has restrictions that are common to all DMA transactions 196in addition to restrictions that differ between unrelated groups of 197transactions, 198the driver can first create a 199.Dq parent 200tag that decribes the common restrictions. 201The per-group tags can then inherit these restrictions from this 202.Dq parent 203tag rather than having to list them explicitly when creating the per-group tags. 204.Pp 205A mapping structure 206.Vt ( bus_dmamap_t ) 207represents a mapping of a memory region for DMA. 208On systems with I/O MMUs, 209the mapping structure tracks any I/O MMU entries used by a request. 210For DMA requests that require bounce pages, 211the mapping tracks the bounce pages used. 212.Pp 213To prepare for one or more DMA transactions, 214a mapping must be bound to a memory region by calling one of the 215.Fn bus_dmamap_load 216functions. 217These functions configure the mapping which can include programming entries 218in an I/O MMU and/or allocating bounce pages. 219An output of these functions 220(either directly or indirectly by invoking a callback routine) 221is the list of scatter/gather address ranges a consumer can pass to a DMA 222engine to access the memory region. 223When a mapping is no longer needed, 224the mapping must be unloaded via 225.Fn bus_dmamap_unload . 226.Pp 227Before and after each DMA transaction, 228.Fn bus_dmamap_sync 229must be used to ensure that the correct data is used by the DMA engine and 230the CPU. 231If a mapping uses bounce pages, 232the sync operations copy data between the bounce pages and the memory region 233bound to the mapping. 234Sync operations also handle architecture-specific details such as CPU cache 235flushing and CPU memory operation ordering. 236.Sh STATIC VS DYNAMIC 237.Nm 238handles two types of DMA transactions: static and dynamic. 239Static transactions are used with a long-lived memory region that is reused 240for many transactions such as a descriptor ring. 241Dynamic transactions are used for transfers to or from transient buffers 242such as I/O buffers holding a network packet or disk block. 243Each transaction type uses a different subset of the 244.Nm 245API. 246.Ss Static Transactions 247Static transactions use memory regions allocated by 248.Nm . 249Each static memory region is allocated by calling 250.Fn bus_dmamem_alloc . 251This function requires a valid tag describing the properties of the 252DMA transactions to this region such as alignment or address restrictions. 253Multiple regions can share a single tag if they share the same restrictions. 254.Pp 255.Fn bus_dmamem_alloc 256allocates a memory region along with a mapping object. 257The associated tag, memory region, and mapping object must then be passed to 258.Fn bus_dmamap_load 259to bind the mapping to the allocated region and obtain the 260scatter/gather list. 261.Pp 262It is expected that 263.Fn bus_dmamem_alloc 264will attempt to allocate memory requiring less expensive sync operations 265(for example, implementations should not allocate regions requiring bounce 266pages), 267but sync operations should still be used. 268For example, a driver should use 269.Fn bus_dmamap_sync 270in an interrupt handler before reading descriptor ring entries written by the 271device prior to the interrupt. 272.Pp 273When a consumer is finished with a memory region, 274it should unload the mapping via 275.Fn bus_dmamap_unload 276and then release the memory region and mapping object via 277.Fn bus_dmamem_free . 278.Ss Dynamic Transactions 279Dynamic transactions map memory regions provided by other parts of the system. 280A tag must be created via 281.Fn bus_dma_tag_create 282to describe the DMA transactions to and from these memory regions, 283and a pool of mapping objects must be allocated via 284.Fn bus_dmamap_create 285to track the mappings of any in-flight transactions. 286.Pp 287When a consumer wishes to schedule a transaction for a memory region, 288the consumer must first obtain an unused mapping object from its pool 289of mapping objects. 290The memory region must be bound to the mapping object via one of the 291.Fn bus_dmamap_load 292functions. 293Before scheduling the transaction, 294the consumer should sync the memory region via 295.Fn bus_dmamap_sync 296with one or more of the 297.Dq PRE 298flags. 299After the transaction has completed, 300the consumer should sync the memory region via 301.Fn bus_dmamap_sync 302with one or more of the 303.Dq POST 304flags. 305The mapping can then be unloaded via 306.Fn bus_dmamap_unload , 307and the mapping object can be returned to the pool of unused mapping objects. 308.Pp 309When a consumer is no longer scheduling DMA transactions, 310the mapping objects should be freed via 311.Fn bus_dmamap_destroy , 312and the tag should be freed via 313.Fn bus_dma_tag_destroy . 314.Sh STRUCTURES AND TYPES 315.Bl -tag -width indent 316.It Vt bus_dma_tag_t 317A machine-dependent (MD) opaque type that describes the 318characteristics of a group of DMA transactions. 319DMA tags are organized into a hierarchy, with each child 320tag inheriting the restrictions of its parent. 321This allows all devices along the path of DMA transactions 322to contribute to the constraints of those transactions. 323.It Vt bus_dma_template_t 324A template is a structure for creating a 325.Fa bus_dma_tag_t 326from a set of defaults. 327Once initialized with 328.Fn bus_dma_template_init , 329a driver can over-ride individual fields to suit its needs. 330The following fields start with the indicated default values: 331.Bd -literal 332 alignment 1 333 boundary 0 334 lowaddr BUS_SPACE_MAXADDR 335 highaddr BUS_SPACE_MAXADDR 336 maxsize BUS_SPACE_MAXSIZE 337 nsegments BUS_SPACE_UNRESTRICTED 338 maxsegsize BUS_SPACE_MAXSIZE 339 flags 0 340 lockfunc NULL 341 lockfuncarg NULL 342.Ed 343.Pp 344Descriptions of each field are documented with 345.Fn bus_dma_tag_create . 346Note that the 347.Fa filtfunc 348and 349.Fa filtfuncarg 350attributes of the DMA tag are not supported with templates. 351.It Vt bus_dma_filter_t 352Client specified address filter having the format: 353.Bl -tag -width indent 354.It Ft int 355.Fn "client_filter" "void *filtarg" "bus_addr_t testaddr" 356.El 357.Pp 358Address filters can be specified during tag creation to allow 359for devices whose DMA address restrictions cannot be specified 360by a single window. 361The 362.Fa filtarg 363argument is specified by the client during tag creation to be passed to all 364invocations of the callback. 365The 366.Fa testaddr 367argument contains a potential starting address of a DMA mapping. 368The filter function operates on the set of addresses from 369.Fa testaddr 370to 371.Ql trunc_page(testaddr) + PAGE_SIZE - 1 , 372inclusive. 373The filter function should return zero if any mapping in this range 374can be accommodated by the device and non-zero otherwise. 375.Pp 376.Em Note: The use of filters is deprecated. Proper operation is not guaranteed. 377.It Vt bus_dma_segment_t 378A machine-dependent type that describes individual 379DMA segments. 380It contains the following fields: 381.Bd -literal 382 bus_addr_t ds_addr; 383 bus_size_t ds_len; 384.Ed 385.Pp 386The 387.Fa ds_addr 388field contains the device visible address of the DMA segment, and 389.Fa ds_len 390contains the length of the DMA segment. 391Although the DMA segments returned by a mapping call will adhere to 392all restrictions necessary for a successful DMA operation, some conversion 393(e.g.\& a conversion from host byte order to the device's byte order) is 394almost always required when presenting segment information to the device. 395.It Vt bus_dmamap_t 396A machine-dependent opaque type describing an individual mapping. 397One map is used for each memory allocation that will be loaded. 398Maps can be reused once they have been unloaded. 399Multiple maps can be associated with one DMA tag. 400While the value of the map may evaluate to 401.Dv NULL 402on some platforms under certain conditions, 403it should never be assumed that it will be 404.Dv NULL 405in all cases. 406.It Vt bus_dmamap_callback_t 407Client specified callback for receiving mapping information resulting from 408the load of a 409.Vt bus_dmamap_t 410via 411.Fn bus_dmamap_load , 412.Fn bus_dmamap_load_bio , 413.Fn bus_dmamap_load_ccb , 414.Fn bus_dmamap_load_crp , 415or 416.Fn bus_dmamap_load_crp_buffer . 417Callbacks are of the format: 418.Bl -tag -width indent 419.It Ft void 420.Fn "client_callback" "void *callback_arg" "bus_dma_segment_t *segs" \ 421"int nseg" "int error" 422.El 423.Pp 424The 425.Fa callback_arg 426is the callback argument passed to dmamap load functions. 427The 428.Fa segs 429and 430.Fa nseg 431arguments describe an array of 432.Vt bus_dma_segment_t 433structures that represent the mapping. 434This array is only valid within the scope of the callback function. 435The success or failure of the mapping is indicated by the 436.Fa error 437argument. 438More information on the use of callbacks can be found in the 439description of the individual dmamap load functions. 440.It Vt bus_dmamap_callback2_t 441Client specified callback for receiving mapping information resulting from 442the load of a 443.Vt bus_dmamap_t 444via 445.Fn bus_dmamap_load_uio 446or 447.Fn bus_dmamap_load_mbuf . 448.Pp 449Callback2s are of the format: 450.Bl -tag -width indent 451.It Ft void 452.Fn "client_callback2" "void *callback_arg" "bus_dma_segment_t *segs" \ 453"int nseg" "bus_size_t mapsize" "int error" 454.El 455.Pp 456Callback2's behavior is the same as 457.Vt bus_dmamap_callback_t 458with the addition that the length of the data mapped is provided via 459.Fa mapsize . 460.It Vt bus_dmasync_op_t 461Memory synchronization operation specifier. 462Bus DMA requires explicit synchronization of memory with its device 463visible mapping in order to guarantee memory coherency. 464The 465.Vt bus_dmasync_op_t 466allows the type of DMA operation that will be or has been performed 467to be communicated to the system so that the correct coherency measures 468are taken. 469The operations are represented as bitfield flags that can be combined together, 470though it only makes sense to combine PRE flags or POST flags, not both. 471See the 472.Fn bus_dmamap_sync 473description below for more details on how to use these operations. 474.Pp 475All operations specified below are performed from the host memory point of view, 476where a read implies data coming from the device to the host memory, and a write 477implies data going from the host memory to the device. 478Alternatively, the operations can be thought of in terms of driver operations, 479where reading a network packet or storage sector corresponds to a read operation 480in 481.Nm . 482.Bl -tag -width ".Dv BUS_DMASYNC_POSTWRITE" 483.It Dv BUS_DMASYNC_PREREAD 484Perform any synchronization required prior to an update of host memory by the 485device. 486.It Dv BUS_DMASYNC_PREWRITE 487Perform any synchronization required after an update of host memory by the CPU 488and prior to device access to host memory. 489.It Dv BUS_DMASYNC_POSTREAD 490Perform any synchronization required after an update of host memory by the 491device and prior to CPU access to host memory. 492.It Dv BUS_DMASYNC_POSTWRITE 493Perform any synchronization required after device access to host memory. 494.El 495.It Vt bus_dma_lock_t 496Client specified lock/mutex manipulation method. 497This will be called from 498within busdma whenever a client lock needs to be manipulated. 499In its current form, the function will be called immediately before 500the callback for a DMA load operation that has been deferred with 501.Dv BUS_DMA_LOCK 502and immediately after with 503.Dv BUS_DMA_UNLOCK . 504If the load operation does not need to be deferred, then it 505will not be called since the function loading the map should 506be holding the appropriate locks. 507This method is of the format: 508.Bl -tag -width indent 509.It Ft void 510.Fn "lockfunc" "void *lockfunc_arg" "bus_dma_lock_op_t op" 511.El 512.Pp 513The 514.Fa lockfuncarg 515argument is specified by the client during tag creation to be passed to all 516invocations of the callback. 517The 518.Fa op 519argument specifies the lock operation to perform. 520.Pp 521Two 522.Vt lockfunc 523implementations are provided for convenience. 524.Fn busdma_lock_mutex 525performs standard mutex operations on the sleep mutex provided via 526.Fa lockfuncarg . 527.Fn dflt_lock 528will generate a system panic if it is called. 529It is substituted into the tag when 530.Fa lockfunc 531is passed as 532.Dv NULL 533to 534.Fn bus_dma_tag_create 535and is useful for tags that should not be used with deferred load operations. 536.It Vt bus_dma_lock_op_t 537Operations to be performed by the client-specified 538.Fn lockfunc . 539.Bl -tag -width ".Dv BUS_DMA_UNLOCK" 540.It Dv BUS_DMA_LOCK 541Acquires and/or locks the client locking primitive. 542.It Dv BUS_DMA_UNLOCK 543Releases and/or unlocks the client locking primitive. 544.El 545.El 546.Sh FUNCTIONS 547.Bl -tag -width indent 548.It Fn bus_dma_tag_create "parent" "alignment" "boundary" "lowaddr" \ 549"highaddr" "*filtfunc" "*filtfuncarg" "maxsize" "nsegments" "maxsegsz" \ 550"flags" "lockfunc" "lockfuncarg" "*dmat" 551Allocates a DMA tag, and initializes it according to 552the arguments provided: 553.Bl -tag -width ".Fa filtfuncarg" 554.It Fa parent 555A parent tag from which to inherit restrictions. 556The restrictions passed in other arguments can only further tighten the 557restrictions inherited from the parent tag. 558.Pp 559All tags created by a device driver must inherit from the tag returned by 560.Fn bus_get_dma_tag 561to honor restrictions between the parent bridge, CPU memory, and the 562device. 563.It Fa alignment 564Alignment constraint, in bytes, of any mappings created using this tag. 565The alignment must be a power of 2. 566Hardware that can DMA starting at any address would specify 567.Em 1 568for byte alignment. 569Hardware requiring DMA transfers to start on a multiple of 4K 570would specify 571.Em 4096 . 572.It Fa boundary 573Boundary constraint, in bytes, of the target DMA memory region. 574The boundary indicates the set of addresses, all multiples of the 575boundary argument, that cannot be crossed by a single 576.Vt bus_dma_segment_t . 577The boundary must be a power of 2 and must be no smaller than the 578maximum segment size. 579.Ql 0 580indicates that there are no boundary restrictions. 581.It Fa lowaddr , highaddr 582Bounds of the window of bus address space that 583.Em cannot 584be directly accessed by the device. 585The window contains all addresses greater than 586.Fa lowaddr 587and less than or equal to 588.Fa highaddr . 589For example, a device incapable of DMA above 4GB, would specify a 590.Fa highaddr 591of 592.Dv BUS_SPACE_MAXADDR 593and a 594.Fa lowaddr 595of 596.Dv BUS_SPACE_MAXADDR_32BIT . 597Similarly a device that can only perform DMA to addresses below 59816MB would specify a 599.Fa highaddr 600of 601.Dv BUS_SPACE_MAXADDR 602and a 603.Fa lowaddr 604of 605.Dv BUS_SPACE_MAXADDR_24BIT . 606Some implementations require that some region of device visible 607address space, overlapping available host memory, be outside the 608window. 609This area of 610.Ql safe memory 611is used to bounce requests that would otherwise conflict with 612the exclusion window. 613.It Fa filtfunc 614Optional filter function (may be 615.Dv NULL ) 616to be called for any attempt to 617map memory into the window described by 618.Fa lowaddr 619and 620.Fa highaddr . 621A filter function is only required when the single window described 622by 623.Fa lowaddr 624and 625.Fa highaddr 626cannot adequately describe the constraints of the device. 627The filter function will be called for every machine page 628that overlaps the exclusion window. 629.Pp 630.Em Note: The use of filters is deprecated. Proper operation is not guaranteed. 631.It Fa filtfuncarg 632Argument passed to all calls to the filter function for this tag. 633May be 634.Dv NULL . 635.It Fa maxsize 636Maximum size, in bytes, of the sum of all segment lengths in a given 637DMA mapping associated with this tag. 638.It Fa nsegments 639Number of discontinuities (scatter/gather segments) allowed 640in a DMA mapped region. 641.It Fa maxsegsz 642Maximum size, in bytes, of a segment in any DMA mapped region associated 643with 644.Fa dmat . 645.It Fa flags 646Are as follows: 647.Bl -tag -width ".Dv BUS_DMA_ALLOCNOW" 648.It Dv BUS_DMA_ALLOCNOW 649Pre-allocate enough resources to handle at least one map load operation on 650this tag. 651If sufficient resources are not available, 652.Er ENOMEM 653is returned. 654This should not be used for tags that only describe buffers that will be 655allocated with 656.Fn bus_dmamem_alloc . 657Also, due to resource sharing with other tags, this flag does not guarantee 658that resources will be allocated or reserved exclusively for this tag. 659It should be treated only as a minor optimization. 660.It Dv BUS_DMA_COHERENT 661Indicate that the DMA engine and CPU are cache-coherent. 662Cached memory may be used to back allocations created by 663.Fn bus_dmamem_alloc . 664For 665.Fn bus_dma_tag_create , 666the 667.Dv BUS_DMA_COHERENT 668flag is currently implemented on arm64. 669.El 670.It Fa lockfunc 671Optional lock manipulation function (may be 672.Dv NULL ) 673to be called when busdma 674needs to manipulate a lock on behalf of the client. 675If 676.Dv NULL 677is specified, 678.Fn dflt_lock 679is used. 680.It Fa lockfuncarg 681Optional argument to be passed to the function specified by 682.Fa lockfunc . 683.It Fa dmat 684Pointer to a bus_dma_tag_t where the resulting DMA tag will 685be stored. 686.El 687.Pp 688Returns 689.Er ENOMEM 690if sufficient memory is not available for tag creation 691or allocating mapping resources. 692.It Fn bus_dma_tag_destroy "dmat" 693Deallocate the DMA tag 694.Fa dmat 695that was created by 696.Fn bus_dma_tag_create . 697.Pp 698Returns 699.Er EBUSY 700if any DMA maps remain associated with 701.Fa dmat 702or 703.Ql 0 704on success. 705.It Fn bus_dma_template_init "*template" "parent" 706Initializes a 707.Fa bus_dma_template_t 708structure. 709If the 710.Fa parent 711argument is non-NULL, this parent tag is associated with the template and 712will be compiled into the dma tag that is later created. 713The values of the parent are not copied into the template. 714During tag creation in 715.Fn bus_dma_tag_template , 716any parameters from the parent tag that are more restrictive than what is 717in the provided template will overwrite what goes into the new tag. 718.It Fn bus_dma_template_tag "*template" "*dmat" 719Unpacks a template into a tag, and returns the tag via the 720.Fa dmat . 721All return values are identical to 722.Fn bus_dma_tag_create . 723The template is not modified by this function, and can be reused and/or 724freed upon return. 725.It Fn bus_dma_template_clone "*template" "dmat" 726Copies the fields from an existing tag to a template. 727The template does not need to be initialized first. 728All of its fields will be overwritten by the values contained in the tag. 729When paired with 730.Fn bus_dma_template_tag , 731this function is useful for creating copies of tags. 732.It Fn bus_dma_template_fill "*template" "params[]" "count" 733Fills in the selected fields of the template with the keyed values from the 734.Fa params 735array. 736This is not meant to be called directly, use 737.Fn BUS_DMA_TEMPLATE_FILL 738instead. 739.It Fn BUS_DMA_TEMPLATE_FILL "*template" "param ..." 740Fills in the selected fields of the template with a variable number of 741key-value parameters. 742The macros listed below take an argument of the specified type and encapsulate 743it into a key-value structure that is directly usable as a parameter argument. 744Muliple parameters may be provided at once. 745.Bd -literal 746 BD_PARENT() void * 747 BD_ALIGNMENT() uintmax_t 748 BD_BOUNDARY() uintmax_t 749 BD_LOWADDR() vm_paddr_t 750 BD_HIGHADDR() vm_paddr_t 751 BD_MAXSIZE() uintmax_t 752 BD_NSEGMENTS() uintmax_t 753 BD_MAXSEGSIZE() uintmax_t 754 BD_FLAGS() uintmax_t 755 BD_LOCKFUNC() void * 756 BD_LOCKFUNCARG() void * 757.Ed 758.It Fn bus_dmamap_create "dmat" "flags" "*mapp" 759Allocates and initializes a DMA map. 760Arguments are as follows: 761.Bl -tag -width ".Fa nsegments" 762.It Fa dmat 763DMA tag. 764.It Fa flags 765Are as follows: 766.Bl -tag -width ".Dv BUS_DMA_COHERENT" 767.It Dv BUS_DMA_COHERENT 768Attempt to map the memory loaded with this map such that cache sync 769operations are as cheap as possible. 770This flag is typically set on maps when the memory loaded with these will 771be accessed by both a CPU and a DMA engine, frequently such as control data 772and as opposed to streamable data such as receive and transmit buffers. 773Use of this flag does not remove the requirement of using 774.Fn bus_dmamap_sync , 775but it may reduce the cost of performing these operations. 776.El 777.It Fa mapp 778Pointer to a 779.Vt bus_dmamap_t 780where the resulting DMA map will be stored. 781.El 782.Pp 783Returns 784.Er ENOMEM 785if sufficient memory is not available for creating the 786map or allocating mapping resources. 787.It Fn bus_dmamap_destroy "dmat" "map" 788Frees all resources associated with a given DMA map. 789Arguments are as follows: 790.Bl -tag -width ".Fa dmat" 791.It Fa dmat 792DMA tag used to allocate 793.Fa map . 794.It Fa map 795The DMA map to destroy. 796.El 797.Pp 798Returns 799.Er EBUSY 800if a mapping is still active for 801.Fa map . 802.It Fn bus_dmamap_load "dmat" "map" "buf" "buflen" "*callback" \ 803"callback_arg" "flags" 804Creates a mapping in device visible address space of 805.Fa buflen 806bytes of 807.Fa buf , 808associated with the DMA map 809.Fa map . 810This call will always return immediately and will not block for any reason. 811Arguments are as follows: 812.Bl -tag -width ".Fa buflen" 813.It Fa dmat 814DMA tag used to allocate 815.Fa map . 816.It Fa map 817A DMA map without a currently active mapping. 818.It Fa buf 819A kernel virtual address pointer to a contiguous (in KVA) buffer, to be 820mapped into device visible address space. 821.It Fa buflen 822The size of the buffer. 823.It Fa callback Fa callback_arg 824The callback function, and its argument. 825This function is called once sufficient mapping resources are available for 826the DMA operation. 827If resources are temporarily unavailable, this function will be deferred until 828later, but the load operation will still return immediately to the caller. 829Thus, callers should not assume that the callback will be called before the 830load returns, and code should be structured appropriately to handle this. 831See below for specific flags and error codes that control this behavior. 832.It Fa flags 833Are as follows: 834.Bl -tag -width ".Dv BUS_DMA_NOWAIT" 835.It Dv BUS_DMA_NOWAIT 836The load should not be deferred in case of insufficient mapping resources, 837and instead should return immediately with an appropriate error. 838.It Dv BUS_DMA_NOCACHE 839The generated transactions to and from the virtual page are non-cacheable. 840.El 841.El 842.Pp 843Return values to the caller are as follows: 844.Bl -tag -width ".Er EINPROGRESS" 845.It 0 846The callback has been called and completed. 847The status of the mapping has been delivered to the callback. 848.It Er EINPROGRESS 849The mapping has been deferred for lack of resources. 850The callback will be called as soon as resources are available. 851Callbacks are serviced in FIFO order. 852.Pp 853Note that subsequent load operations for the same tag that do not require 854extra resources will still succeed. 855This may result in out-of-order processing of requests. 856If the caller requires the order of requests to be preserved, 857then the caller is required to stall subsequent requests until a pending 858request's callback is invoked. 859.It Er ENOMEM 860The load request has failed due to insufficient resources, and the caller 861specifically used the 862.Dv BUS_DMA_NOWAIT 863flag. 864.It Er EINVAL 865The load request was invalid. 866The callback has been called and has been provided the same error. 867This error value may indicate that 868.Fa dmat , 869.Fa map , 870.Fa buf , 871or 872.Fa callback 873were invalid, or 874.Fa buflen 875was larger than the 876.Fa maxsize 877argument used to create the dma tag 878.Fa dmat . 879.El 880.Pp 881When the callback is called, it is presented with an error value 882indicating the disposition of the mapping. 883Error may be one of the following: 884.Bl -tag -width ".Er EINPROGRESS" 885.It 0 886The mapping was successful and the 887.Fa dm_segs 888callback argument contains an array of 889.Vt bus_dma_segment_t 890elements describing the mapping. 891This array is only valid during the scope of the callback function. 892.It Er EFBIG 893A mapping could not be achieved within the segment constraints provided 894in the tag even though the requested allocation size was less than maxsize. 895.El 896.It Fn bus_dmamap_load_bio "dmat" "map" "bio" "callback" "callback_arg" "flags" 897This is a variation of 898.Fn bus_dmamap_load 899which maps buffers pointed to by 900.Fa bio 901for DMA transfers. 902.Fa bio 903may point to either a mapped or unmapped buffer. 904.It Fn bus_dmamap_load_ccb "dmat" "map" "ccb" "callback" "callback_arg" "flags" 905This is a variation of 906.Fn bus_dmamap_load 907which maps data pointed to by 908.Fa ccb 909for DMA transfers. 910The data for 911.Fa ccb 912may be any of the following types: 913.Bl -tag -width ".Er CAM_DATA_SG_PADDR" 914.It CAM_DATA_VADDR 915The data is a single KVA buffer. 916.It CAM_DATA_PADDR 917The data is a single bus address range. 918.It CAM_DATA_SG 919The data is a scatter/gather list of KVA buffers. 920.It CAM_DATA_SG_PADDR 921The data is a scatter/gather list of bus address ranges. 922.It CAM_DATA_BIO 923The data is contained in a 924.Vt struct bio 925attached to the CCB. 926.El 927.Pp 928.Fn bus_dmamap_load_ccb 929supports the following CCB XPT function codes: 930.Pp 931.Bl -item -offset indent -compact 932.It 933XPT_ATA_IO 934.It 935XPT_CONT_TARGET_IO 936.It 937XPT_SCSI_IO 938.El 939.It Fn bus_dmamap_load_crp "dmat" "map" "crp" "callback" "callback_arg" "flags" 940This is a variation of 941.Fn bus_dmamap_load 942which maps the input buffer pointed to by 943.Fa crp 944for DMA transfers. 945The 946.Dv BUS_DMA_NOWAIT 947flag is implied, thus no callback deferral will happen. 948.It Fn bus_dmamap_load_crp_buffer "dmat" "map" "cb" "callback" "callback_arg" \ 949"flags" 950This is a variation of 951.Fn bus_dmamap_load 952which maps the crypto data buffer pointed to by 953.Fa cb 954for DMA transfers. 955The 956.Dv BUS_DMA_NOWAIT 957flag is implied, thus no callback deferral will happen. 958.It Fn bus_dmamap_load_mbuf "dmat" "map" "mbuf" "callback2" "callback_arg" \ 959"flags" 960This is a variation of 961.Fn bus_dmamap_load 962which maps mbuf chains 963for DMA transfers. 964A 965.Vt bus_size_t 966argument is also passed to the callback routine, which 967contains the mbuf chain's packet header length. 968The 969.Dv BUS_DMA_NOWAIT 970flag is implied, thus no callback deferral will happen. 971.Pp 972Mbuf chains are assumed to be in kernel virtual address space. 973.Pp 974Beside the error values listed for 975.Fn bus_dmamap_load , 976.Er EINVAL 977will be returned if the size of the mbuf chain exceeds the maximum limit of the 978DMA tag. 979.It Fn bus_dmamap_load_mbuf_sg "dmat" "map" "mbuf" "segs" "nsegs" "flags" 980This is just like 981.Fn bus_dmamap_load_mbuf 982except that it returns immediately without calling a callback function. 983It is provided for efficiency. 984The scatter/gather segment array 985.Va segs 986is provided by the caller and filled in directly by the function. 987The 988.Va nsegs 989argument is returned with the number of segments filled in. 990Returns the same errors as 991.Fn bus_dmamap_load_mbuf . 992.It Fn bus_dmamap_load_uio "dmat" "map" "uio" "callback2" "callback_arg" "flags" 993This is a variation of 994.Fn bus_dmamap_load 995which maps buffers pointed to by 996.Fa uio 997for DMA transfers. 998A 999.Vt bus_size_t 1000argument is also passed to the callback routine, which contains the size of 1001.Fa uio , 1002i.e. 1003.Fa uio->uio_resid . 1004The 1005.Dv BUS_DMA_NOWAIT 1006flag is implied, thus no callback deferral will happen. 1007Returns the same errors as 1008.Fn bus_dmamap_load . 1009.Pp 1010If 1011.Fa uio->uio_segflg 1012is 1013.Dv UIO_USERSPACE , 1014then it is assumed that the buffer, 1015.Fa uio 1016is in 1017.Fa "uio->uio_td->td_proc" Ns 's 1018address space. 1019User space memory must be in-core and wired prior to attempting a map 1020load operation. 1021Pages may be locked using 1022.Xr vslock 9 . 1023.It Fn bus_dmamap_unload "dmat" "map" 1024Unloads a DMA map. 1025Arguments are as follows: 1026.Bl -tag -width ".Fa dmam" 1027.It Fa dmat 1028DMA tag used to allocate 1029.Fa map . 1030.It Fa map 1031The DMA map that is to be unloaded. 1032.El 1033.Pp 1034.Fn bus_dmamap_unload 1035will not perform any implicit synchronization of DMA buffers. 1036This must be done explicitly by a call to 1037.Fn bus_dmamap_sync 1038prior to unloading the map. 1039.It Fn bus_dmamap_sync "dmat" "map" "op" 1040Performs synchronization of a device visible mapping with the CPU visible 1041memory referenced by that mapping. 1042Arguments are as follows: 1043.Bl -tag -width ".Fa dmat" 1044.It Fa dmat 1045DMA tag used to allocate 1046.Fa map . 1047.It Fa map 1048The DMA mapping to be synchronized. 1049.It Fa op 1050Type of synchronization operation to perform. 1051See the definition of 1052.Vt bus_dmasync_op_t 1053for a description of the acceptable values for 1054.Fa op . 1055.El 1056.Pp 1057The 1058.Fn bus_dmamap_sync 1059function 1060is the method used to ensure that CPU's and device's direct 1061memory access (DMA) to shared 1062memory is coherent. 1063For example, the CPU might be used to set up the contents of a buffer 1064that is to be made available to a device. 1065To ensure that the data are visible via the device's mapping of that 1066memory, the buffer must be loaded and a DMA sync operation of 1067.Dv BUS_DMASYNC_PREWRITE 1068must be performed after the CPU has updated the buffer and before the device 1069access is initiated. 1070If the CPU modifies this buffer again later, another 1071.Dv BUS_DMASYNC_PREWRITE 1072sync operation must be performed before an additional device 1073access. 1074Conversely, suppose a device updates memory that is to be read by a CPU. 1075In this case, the buffer must be loaded, and a DMA sync operation of 1076.Dv BUS_DMASYNC_PREREAD 1077must be performed before the device access is initiated. 1078The CPU will only be able to see the results of this memory update 1079once the DMA operation has completed and a 1080.Dv BUS_DMASYNC_POSTREAD 1081sync operation has been performed. 1082.Pp 1083If read and write operations are not preceded and followed by the 1084appropriate synchronization operations, behavior is undefined. 1085.It Fn bus_dmamem_alloc "dmat" "**vaddr" "flags" "*mapp" 1086Allocates memory that is mapped into KVA at the address returned 1087in 1088.Fa vaddr 1089and that is permanently loaded into the newly created 1090.Vt bus_dmamap_t 1091returned via 1092.Fa mapp . 1093Arguments are as follows: 1094.Bl -tag -width ".Fa alignment" 1095.It Fa dmat 1096DMA tag describing the constraints of the DMA mapping. 1097.It Fa vaddr 1098Pointer to a pointer that will hold the returned KVA mapping of 1099the allocated region. 1100.It Fa flags 1101Flags are defined as follows: 1102.Bl -tag -width ".Dv BUS_DMA_NOWAIT" 1103.It Dv BUS_DMA_WAITOK 1104The routine can safely wait (sleep) for resources. 1105.It Dv BUS_DMA_NOWAIT 1106The routine is not allowed to wait for resources. 1107If resources are not available, 1108.Dv ENOMEM 1109is returned. 1110.It Dv BUS_DMA_COHERENT 1111Attempt to map this memory in a coherent fashion. 1112See 1113.Fn bus_dmamap_create 1114above for a description of this flag. 1115For 1116.Fn bus_dmamem_alloc , 1117the 1118.Dv BUS_DMA_COHERENT 1119flag is currently implemented on arm and arm64. 1120.It Dv BUS_DMA_ZERO 1121Causes the allocated memory to be set to all zeros. 1122.It Dv BUS_DMA_NOCACHE 1123The allocated memory will not be cached in the processor caches. 1124All memory accesses appear on the bus and are executed 1125without reordering. 1126For 1127.Fn bus_dmamem_alloc , 1128the 1129.Dv BUS_DMA_NOCACHE 1130flag is currently implemented on amd64 and i386 where it results in the 1131Strong Uncacheable PAT to be set for the allocated virtual address range. 1132.El 1133.It Fa mapp 1134Pointer to a 1135.Vt bus_dmamap_t 1136where the resulting DMA map will be stored. 1137.El 1138.Pp 1139The size of memory to be allocated is 1140.Fa maxsize 1141as specified in the call to 1142.Fn bus_dma_tag_create 1143for 1144.Fa dmat . 1145.Pp 1146The current implementation of 1147.Fn bus_dmamem_alloc 1148will allocate all requests as a single segment. 1149.Pp 1150An initial load operation is required to obtain the bus address of the allocated 1151memory, and an unload operation is required before freeing the memory, as 1152described below in 1153.Fn bus_dmamem_free . 1154Maps are automatically handled by this function and should not be explicitly 1155allocated or destroyed. 1156.Pp 1157Although an explicit load is not required for each access to the memory 1158referenced by the returned map, the synchronization requirements 1159as described in the 1160.Fn bus_dmamap_sync 1161section still apply and should be used to achieve portability on architectures 1162without coherent buses. 1163.Pp 1164Returns 1165.Er ENOMEM 1166if sufficient memory is not available for completing 1167the operation. 1168.It Fn bus_dmamem_free "dmat" "*vaddr" "map" 1169Frees memory previously allocated by 1170.Fn bus_dmamem_alloc . 1171Any mappings 1172will be invalidated. 1173Arguments are as follows: 1174.Bl -tag -width ".Fa vaddr" 1175.It Fa dmat 1176DMA tag. 1177.It Fa vaddr 1178Kernel virtual address of the memory. 1179.It Fa map 1180DMA map to be invalidated. 1181.El 1182.El 1183.Sh RETURN VALUES 1184Behavior is undefined if invalid arguments are passed to 1185any of the above functions. 1186If sufficient resources cannot be allocated for a given 1187transaction, 1188.Er ENOMEM 1189is returned. 1190All 1191routines that are not of type 1192.Vt void 1193will return 0 on success or an error 1194code on failure as discussed above. 1195.Pp 1196All 1197.Vt void 1198routines will succeed if provided with valid arguments. 1199.Sh LOCKING 1200Two locking protocols are used by 1201.Nm . 1202The first is a private global lock that is used to synchronize access to the 1203bounce buffer pool on the architectures that make use of them. 1204This lock is strictly a leaf lock that is only used internally to 1205.Nm 1206and is not exposed to clients of the API. 1207.Pp 1208The second protocol involves protecting various resources stored in the tag. 1209Since almost all 1210.Nm 1211operations are done through requests from the driver that created the tag, 1212the most efficient way to protect the tag resources is through the lock that 1213the driver uses. 1214In cases where 1215.Nm 1216acts on its own without being called by the driver, the lock primitive 1217specified in the tag is acquired and released automatically. 1218An example of this is when the 1219.Fn bus_dmamap_load 1220callback function is called from a deferred context instead of the driver 1221context. 1222This means that certain 1223.Nm 1224functions must always be called with the same lock held that is specified in the 1225tag. 1226These functions include: 1227.Pp 1228.Bl -item -offset indent -compact 1229.It 1230.Fn bus_dmamap_load 1231.It 1232.Fn bus_dmamap_load_bio 1233.It 1234.Fn bus_dmamap_load_ccb 1235.It 1236.Fn bus_dmamap_load_mbuf 1237.It 1238.Fn bus_dmamap_load_mbuf_sg 1239.It 1240.Fn bus_dmamap_load_uio 1241.It 1242.Fn bus_dmamap_unload 1243.It 1244.Fn bus_dmamap_sync 1245.El 1246.Pp 1247There is one exception to this rule. 1248It is common practice to call some of these functions during driver start-up 1249without any locks held. 1250So long as there is a guarantee of no possible concurrent use of the tag by 1251different threads during this operation, it is safe to not hold a lock for 1252these functions. 1253.Pp 1254Certain 1255.Nm 1256operations should not be called with the driver lock held, either because 1257they are already protected by an internal lock, or because they might sleep 1258due to memory or resource allocation. 1259The following functions must not be 1260called with any non-sleepable locks held: 1261.Pp 1262.Bl -item -offset indent -compact 1263.It 1264.Fn bus_dma_tag_create 1265.It 1266.Fn bus_dmamap_create 1267.It 1268.Fn bus_dmamem_alloc 1269.El 1270.Pp 1271All other functions do not have a locking protocol and can thus be 1272called with or without any system or driver locks held. 1273.Sh SEE ALSO 1274.Xr devclass 9 , 1275.Xr device 9 , 1276.Xr driver 9 , 1277.Xr rman 9 , 1278.Xr vslock 9 1279.Pp 1280.Rs 1281.%A "Jason R. Thorpe" 1282.%T "A Machine-Independent DMA Framework for NetBSD" 1283.%J "Proceedings of the Summer 1998 USENIX Technical Conference" 1284.%Q "USENIX Association" 1285.%D "June 1998" 1286.Re 1287.Sh HISTORY 1288The 1289.Nm 1290interface first appeared in 1291.Nx 1.3 . 1292.Pp 1293The 1294.Nm 1295API was adopted from 1296.Nx 1297for use in the CAM SCSI subsystem. 1298The alterations to the original API were aimed to remove the need for 1299a 1300.Vt bus_dma_segment_t 1301array stored in each 1302.Vt bus_dmamap_t 1303while allowing callers to queue up on scarce resources. 1304.Sh AUTHORS 1305The 1306.Nm 1307interface was designed and implemented by 1308.An Jason R. Thorpe 1309of the Numerical Aerospace Simulation Facility, NASA Ames Research Center. 1310Additional input on the 1311.Nm 1312design was provided by 1313.An -nosplit 1314.An Chris Demetriou , 1315.An Charles Hannum , 1316.An Ross Harvey , 1317.An Matthew Jacob , 1318.An Jonathan Stone , 1319and 1320.An Matt Thomas . 1321.Pp 1322The 1323.Nm 1324interface in 1325.Fx 1326benefits from the contributions of 1327.An Justin T. Gibbs , 1328.An Peter Wemm , 1329.An Doug Rabson , 1330.An Matthew N. Dodd , 1331.An Sam Leffler , 1332.An Maxime Henrion , 1333.An Jake Burkholder , 1334.An Takahashi Yoshihiro , 1335.An Scott Long 1336and many others. 1337.Pp 1338This manual page was written by 1339.An Hiten M. Pandya 1340and 1341.An Justin T. Gibbs . 1342