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