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. If the 711.Fa parent 712argument is non-NULL, this parent tag is associated with the template and 713will be compiled into the dma tag that is later created. The values 714of the parent are not copied into the template. During 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. All of its fields will 728be overwritten by the values contained in the tag. When paired with 729.Fn bus_dma_template_tag , 730this function is useful for creating copies of tags. 731.It Fn bus_dma_template_fill "*template" "params[]" "count" 732Fills in the selected fields of the template with the keyed values from the 733.Fa params 734array. This is not meant to be called directly, use 735.Fn BUS_DMA_TEMPLATE_FILL 736instead. 737.It Fn BUS_DMA_TEMPLATE_FILL "*template" "param ..." 738Fills in the selected fields of the template with a variable number of 739key-value parameters. The macros listed below take an argument of the 740specified type and encapsulate it into a key-value structure that is directly 741usable as a parameter argument. Muliple parameters may be provided at once. 742.Bd -literal 743 BD_PARENT() void * 744 BD_ALIGNMENT() uintmax_t 745 BD_BOUNDARY() uintmax_t 746 BD_LOWADDR() vm_paddr_t 747 BD_HIGHADDR() vm_paddr_t 748 BD_MAXSIZE() uintmax_t 749 BD_NSEGMENTS() uintmax_t 750 BD_MAXSEGSIZE() uintmax_t 751 BD_FLAGS() uintmax_t 752 BD_LOCKFUNC() void * 753 BD_LOCKFUNCARG() void * 754.Ed 755.Pp 756.It Fn bus_dmamap_create "dmat" "flags" "*mapp" 757Allocates and initializes a DMA map. 758Arguments are as follows: 759.Bl -tag -width ".Fa nsegments" 760.It Fa dmat 761DMA tag. 762.It Fa flags 763Are as follows: 764.Bl -tag -width ".Dv BUS_DMA_COHERENT" 765.It Dv BUS_DMA_COHERENT 766Attempt to map the memory loaded with this map such that cache sync 767operations are as cheap as possible. 768This flag is typically set on maps when the memory loaded with these will 769be accessed by both a CPU and a DMA engine, frequently such as control data 770and as opposed to streamable data such as receive and transmit buffers. 771Use of this flag does not remove the requirement of using 772.Fn bus_dmamap_sync , 773but it may reduce the cost of performing these operations. 774.El 775.It Fa mapp 776Pointer to a 777.Vt bus_dmamap_t 778where the resulting DMA map will be stored. 779.El 780.Pp 781Returns 782.Er ENOMEM 783if sufficient memory is not available for creating the 784map or allocating mapping resources. 785.It Fn bus_dmamap_destroy "dmat" "map" 786Frees all resources associated with a given DMA map. 787Arguments are as follows: 788.Bl -tag -width ".Fa dmat" 789.It Fa dmat 790DMA tag used to allocate 791.Fa map . 792.It Fa map 793The DMA map to destroy. 794.El 795.Pp 796Returns 797.Er EBUSY 798if a mapping is still active for 799.Fa map . 800.It Fn bus_dmamap_load "dmat" "map" "buf" "buflen" "*callback" \ 801"callback_arg" "flags" 802Creates a mapping in device visible address space of 803.Fa buflen 804bytes of 805.Fa buf , 806associated with the DMA map 807.Fa map . 808This call will always return immediately and will not block for any reason. 809Arguments are as follows: 810.Bl -tag -width ".Fa buflen" 811.It Fa dmat 812DMA tag used to allocate 813.Fa map . 814.It Fa map 815A DMA map without a currently active mapping. 816.It Fa buf 817A kernel virtual address pointer to a contiguous (in KVA) buffer, to be 818mapped into device visible address space. 819.It Fa buflen 820The size of the buffer. 821.It Fa callback Fa callback_arg 822The callback function, and its argument. 823This function is called once sufficient mapping resources are available for 824the DMA operation. 825If resources are temporarily unavailable, this function will be deferred until 826later, but the load operation will still return immediately to the caller. 827Thus, callers should not assume that the callback will be called before the 828load returns, and code should be structured appropriately to handle this. 829See below for specific flags and error codes that control this behavior. 830.It Fa flags 831Are as follows: 832.Bl -tag -width ".Dv BUS_DMA_NOWAIT" 833.It Dv BUS_DMA_NOWAIT 834The load should not be deferred in case of insufficient mapping resources, 835and instead should return immediately with an appropriate error. 836.It Dv BUS_DMA_NOCACHE 837The generated transactions to and from the virtual page are non-cacheable. 838.El 839.El 840.Pp 841Return values to the caller are as follows: 842.Bl -tag -width ".Er EINPROGRESS" 843.It 0 844The callback has been called and completed. 845The status of the mapping has been delivered to the callback. 846.It Er EINPROGRESS 847The mapping has been deferred for lack of resources. 848The callback will be called as soon as resources are available. 849Callbacks are serviced in FIFO order. 850.Pp 851Note that subsequent load operations for the same tag that do not require 852extra resources will still succeed. 853This may result in out-of-order processing of requests. 854If the caller requires the order of requests to be preserved, 855then the caller is required to stall subsequent requests until a pending 856request's callback is invoked. 857.It Er ENOMEM 858The load request has failed due to insufficient resources, and the caller 859specifically used the 860.Dv BUS_DMA_NOWAIT 861flag. 862.It Er EINVAL 863The load request was invalid. 864The callback has been called and has been provided the same error. 865This error value may indicate that 866.Fa dmat , 867.Fa map , 868.Fa buf , 869or 870.Fa callback 871were invalid, or 872.Fa buflen 873was larger than the 874.Fa maxsize 875argument used to create the dma tag 876.Fa dmat . 877.El 878.Pp 879When the callback is called, it is presented with an error value 880indicating the disposition of the mapping. 881Error may be one of the following: 882.Bl -tag -width ".Er EINPROGRESS" 883.It 0 884The mapping was successful and the 885.Fa dm_segs 886callback argument contains an array of 887.Vt bus_dma_segment_t 888elements describing the mapping. 889This array is only valid during the scope of the callback function. 890.It Er EFBIG 891A mapping could not be achieved within the segment constraints provided 892in the tag even though the requested allocation size was less than maxsize. 893.El 894.It Fn bus_dmamap_load_bio "dmat" "map" "bio" "callback" "callback_arg" "flags" 895This is a variation of 896.Fn bus_dmamap_load 897which maps buffers pointed to by 898.Fa bio 899for DMA transfers. 900.Fa bio 901may point to either a mapped or unmapped buffer. 902.It Fn bus_dmamap_load_ccb "dmat" "map" "ccb" "callback" "callback_arg" "flags" 903This is a variation of 904.Fn bus_dmamap_load 905which maps data pointed to by 906.Fa ccb 907for DMA transfers. 908The data for 909.Fa ccb 910may be any of the following types: 911.Bl -tag -width ".Er CAM_DATA_SG_PADDR" 912.It CAM_DATA_VADDR 913The data is a single KVA buffer. 914.It CAM_DATA_PADDR 915The data is a single bus address range. 916.It CAM_DATA_SG 917The data is a scatter/gather list of KVA buffers. 918.It CAM_DATA_SG_PADDR 919The data is a scatter/gather list of bus address ranges. 920.It CAM_DATA_BIO 921The data is contained in a 922.Vt struct bio 923attached to the CCB. 924.El 925.Pp 926.Fn bus_dmamap_load_ccb 927supports the following CCB XPT function codes: 928.Pp 929.Bl -item -offset indent -compact 930.It 931XPT_ATA_IO 932.It 933XPT_CONT_TARGET_IO 934.It 935XPT_SCSI_IO 936.El 937.It Fn bus_dmamap_load_crp "dmat" "map" "crp" "callback" "callback_arg" "flags" 938This is a variation of 939.Fn bus_dmamap_load 940which maps the input buffer pointed to by 941.Fa crp 942for DMA transfers. 943The 944.Dv BUS_DMA_NOWAIT 945flag is implied, thus no callback deferral will happen. 946.It Fn bus_dmamap_load_crp_buffer "dmat" "map" "cb" "callback" "callback_arg" \ 947"flags" 948This is a variation of 949.Fn bus_dmamap_load 950which maps the crypto data buffer pointed to by 951.Fa cb 952for DMA transfers. 953The 954.Dv BUS_DMA_NOWAIT 955flag is implied, thus no callback deferral will happen. 956.It Fn bus_dmamap_load_mbuf "dmat" "map" "mbuf" "callback2" "callback_arg" \ 957"flags" 958This is a variation of 959.Fn bus_dmamap_load 960which maps mbuf chains 961for DMA transfers. 962A 963.Vt bus_size_t 964argument is also passed to the callback routine, which 965contains the mbuf chain's packet header length. 966The 967.Dv BUS_DMA_NOWAIT 968flag is implied, thus no callback deferral will happen. 969.Pp 970Mbuf chains are assumed to be in kernel virtual address space. 971.Pp 972Beside the error values listed for 973.Fn bus_dmamap_load , 974.Er EINVAL 975will be returned if the size of the mbuf chain exceeds the maximum limit of the 976DMA tag. 977.It Fn bus_dmamap_load_mbuf_sg "dmat" "map" "mbuf" "segs" "nsegs" "flags" 978This is just like 979.Fn bus_dmamap_load_mbuf 980except that it returns immediately without calling a callback function. 981It is provided for efficiency. 982The scatter/gather segment array 983.Va segs 984is provided by the caller and filled in directly by the function. 985The 986.Va nsegs 987argument is returned with the number of segments filled in. 988Returns the same errors as 989.Fn bus_dmamap_load_mbuf . 990.It Fn bus_dmamap_load_uio "dmat" "map" "uio" "callback2" "callback_arg" "flags" 991This is a variation of 992.Fn bus_dmamap_load 993which maps buffers pointed to by 994.Fa uio 995for DMA transfers. 996A 997.Vt bus_size_t 998argument is also passed to the callback routine, which contains the size of 999.Fa uio , 1000i.e. 1001.Fa uio->uio_resid . 1002The 1003.Dv BUS_DMA_NOWAIT 1004flag is implied, thus no callback deferral will happen. 1005Returns the same errors as 1006.Fn bus_dmamap_load . 1007.Pp 1008If 1009.Fa uio->uio_segflg 1010is 1011.Dv UIO_USERSPACE , 1012then it is assumed that the buffer, 1013.Fa uio 1014is in 1015.Fa "uio->uio_td->td_proc" Ns 's 1016address space. 1017User space memory must be in-core and wired prior to attempting a map 1018load operation. 1019Pages may be locked using 1020.Xr vslock 9 . 1021.It Fn bus_dmamap_unload "dmat" "map" 1022Unloads a DMA map. 1023Arguments are as follows: 1024.Bl -tag -width ".Fa dmam" 1025.It Fa dmat 1026DMA tag used to allocate 1027.Fa map . 1028.It Fa map 1029The DMA map that is to be unloaded. 1030.El 1031.Pp 1032.Fn bus_dmamap_unload 1033will not perform any implicit synchronization of DMA buffers. 1034This must be done explicitly by a call to 1035.Fn bus_dmamap_sync 1036prior to unloading the map. 1037.It Fn bus_dmamap_sync "dmat" "map" "op" 1038Performs synchronization of a device visible mapping with the CPU visible 1039memory referenced by that mapping. 1040Arguments are as follows: 1041.Bl -tag -width ".Fa dmat" 1042.It Fa dmat 1043DMA tag used to allocate 1044.Fa map . 1045.It Fa map 1046The DMA mapping to be synchronized. 1047.It Fa op 1048Type of synchronization operation to perform. 1049See the definition of 1050.Vt bus_dmasync_op_t 1051for a description of the acceptable values for 1052.Fa op . 1053.El 1054.Pp 1055The 1056.Fn bus_dmamap_sync 1057function 1058is the method used to ensure that CPU's and device's direct 1059memory access (DMA) to shared 1060memory is coherent. 1061For example, the CPU might be used to set up the contents of a buffer 1062that is to be made available to a device. 1063To ensure that the data are visible via the device's mapping of that 1064memory, the buffer must be loaded and a DMA sync operation of 1065.Dv BUS_DMASYNC_PREWRITE 1066must be performed after the CPU has updated the buffer and before the device 1067access is initiated. 1068If the CPU modifies this buffer again later, another 1069.Dv BUS_DMASYNC_PREWRITE 1070sync operation must be performed before an additional device 1071access. 1072Conversely, suppose a device updates memory that is to be read by a CPU. 1073In this case, the buffer must be loaded, and a DMA sync operation of 1074.Dv BUS_DMASYNC_PREREAD 1075must be performed before the device access is initiated. 1076The CPU will only be able to see the results of this memory update 1077once the DMA operation has completed and a 1078.Dv BUS_DMASYNC_POSTREAD 1079sync operation has been performed. 1080.Pp 1081If read and write operations are not preceded and followed by the 1082appropriate synchronization operations, behavior is undefined. 1083.It Fn bus_dmamem_alloc "dmat" "**vaddr" "flags" "*mapp" 1084Allocates memory that is mapped into KVA at the address returned 1085in 1086.Fa vaddr 1087and that is permanently loaded into the newly created 1088.Vt bus_dmamap_t 1089returned via 1090.Fa mapp . 1091Arguments are as follows: 1092.Bl -tag -width ".Fa alignment" 1093.It Fa dmat 1094DMA tag describing the constraints of the DMA mapping. 1095.It Fa vaddr 1096Pointer to a pointer that will hold the returned KVA mapping of 1097the allocated region. 1098.It Fa flags 1099Flags are defined as follows: 1100.Bl -tag -width ".Dv BUS_DMA_NOWAIT" 1101.It Dv BUS_DMA_WAITOK 1102The routine can safely wait (sleep) for resources. 1103.It Dv BUS_DMA_NOWAIT 1104The routine is not allowed to wait for resources. 1105If resources are not available, 1106.Dv ENOMEM 1107is returned. 1108.It Dv BUS_DMA_COHERENT 1109Attempt to map this memory in a coherent fashion. 1110See 1111.Fn bus_dmamap_create 1112above for a description of this flag. 1113For 1114.Fn bus_dmamem_alloc , 1115the 1116.Dv BUS_DMA_COHERENT 1117flag is currently implemented on arm and arm64. 1118.It Dv BUS_DMA_ZERO 1119Causes the allocated memory to be set to all zeros. 1120.It Dv BUS_DMA_NOCACHE 1121The allocated memory will not be cached in the processor caches. 1122All memory accesses appear on the bus and are executed 1123without reordering. 1124For 1125.Fn bus_dmamem_alloc , 1126the 1127.Dv BUS_DMA_NOCACHE 1128flag is currently implemented on amd64 and i386 where it results in the 1129Strong Uncacheable PAT to be set for the allocated virtual address range. 1130.El 1131.It Fa mapp 1132Pointer to a 1133.Vt bus_dmamap_t 1134where the resulting DMA map will be stored. 1135.El 1136.Pp 1137The size of memory to be allocated is 1138.Fa maxsize 1139as specified in the call to 1140.Fn bus_dma_tag_create 1141for 1142.Fa dmat . 1143.Pp 1144The current implementation of 1145.Fn bus_dmamem_alloc 1146will allocate all requests as a single segment. 1147.Pp 1148An initial load operation is required to obtain the bus address of the allocated 1149memory, and an unload operation is required before freeing the memory, as 1150described below in 1151.Fn bus_dmamem_free . 1152Maps are automatically handled by this function and should not be explicitly 1153allocated or destroyed. 1154.Pp 1155Although an explicit load is not required for each access to the memory 1156referenced by the returned map, the synchronization requirements 1157as described in the 1158.Fn bus_dmamap_sync 1159section still apply and should be used to achieve portability on architectures 1160without coherent buses. 1161.Pp 1162Returns 1163.Er ENOMEM 1164if sufficient memory is not available for completing 1165the operation. 1166.It Fn bus_dmamem_free "dmat" "*vaddr" "map" 1167Frees memory previously allocated by 1168.Fn bus_dmamem_alloc . 1169Any mappings 1170will be invalidated. 1171Arguments are as follows: 1172.Bl -tag -width ".Fa vaddr" 1173.It Fa dmat 1174DMA tag. 1175.It Fa vaddr 1176Kernel virtual address of the memory. 1177.It Fa map 1178DMA map to be invalidated. 1179.El 1180.El 1181.Sh RETURN VALUES 1182Behavior is undefined if invalid arguments are passed to 1183any of the above functions. 1184If sufficient resources cannot be allocated for a given 1185transaction, 1186.Er ENOMEM 1187is returned. 1188All 1189routines that are not of type 1190.Vt void 1191will return 0 on success or an error 1192code on failure as discussed above. 1193.Pp 1194All 1195.Vt void 1196routines will succeed if provided with valid arguments. 1197.Sh LOCKING 1198Two locking protocols are used by 1199.Nm . 1200The first is a private global lock that is used to synchronize access to the 1201bounce buffer pool on the architectures that make use of them. 1202This lock is strictly a leaf lock that is only used internally to 1203.Nm 1204and is not exposed to clients of the API. 1205.Pp 1206The second protocol involves protecting various resources stored in the tag. 1207Since almost all 1208.Nm 1209operations are done through requests from the driver that created the tag, 1210the most efficient way to protect the tag resources is through the lock that 1211the driver uses. 1212In cases where 1213.Nm 1214acts on its own without being called by the driver, the lock primitive 1215specified in the tag is acquired and released automatically. 1216An example of this is when the 1217.Fn bus_dmamap_load 1218callback function is called from a deferred context instead of the driver 1219context. 1220This means that certain 1221.Nm 1222functions must always be called with the same lock held that is specified in the 1223tag. 1224These functions include: 1225.Pp 1226.Bl -item -offset indent -compact 1227.It 1228.Fn bus_dmamap_load 1229.It 1230.Fn bus_dmamap_load_bio 1231.It 1232.Fn bus_dmamap_load_ccb 1233.It 1234.Fn bus_dmamap_load_mbuf 1235.It 1236.Fn bus_dmamap_load_mbuf_sg 1237.It 1238.Fn bus_dmamap_load_uio 1239.It 1240.Fn bus_dmamap_unload 1241.It 1242.Fn bus_dmamap_sync 1243.El 1244.Pp 1245There is one exception to this rule. 1246It is common practice to call some of these functions during driver start-up 1247without any locks held. 1248So long as there is a guarantee of no possible concurrent use of the tag by 1249different threads during this operation, it is safe to not hold a lock for 1250these functions. 1251.Pp 1252Certain 1253.Nm 1254operations should not be called with the driver lock held, either because 1255they are already protected by an internal lock, or because they might sleep 1256due to memory or resource allocation. 1257The following functions must not be 1258called with any non-sleepable locks held: 1259.Pp 1260.Bl -item -offset indent -compact 1261.It 1262.Fn bus_dma_tag_create 1263.It 1264.Fn bus_dmamap_create 1265.It 1266.Fn bus_dmamem_alloc 1267.El 1268.Pp 1269All other functions do not have a locking protocol and can thus be 1270called with or without any system or driver locks held. 1271.Sh SEE ALSO 1272.Xr devclass 9 , 1273.Xr device 9 , 1274.Xr driver 9 , 1275.Xr rman 9 , 1276.Xr vslock 9 1277.Pp 1278.Rs 1279.%A "Jason R. Thorpe" 1280.%T "A Machine-Independent DMA Framework for NetBSD" 1281.%J "Proceedings of the Summer 1998 USENIX Technical Conference" 1282.%Q "USENIX Association" 1283.%D "June 1998" 1284.Re 1285.Sh HISTORY 1286The 1287.Nm 1288interface first appeared in 1289.Nx 1.3 . 1290.Pp 1291The 1292.Nm 1293API was adopted from 1294.Nx 1295for use in the CAM SCSI subsystem. 1296The alterations to the original API were aimed to remove the need for 1297a 1298.Vt bus_dma_segment_t 1299array stored in each 1300.Vt bus_dmamap_t 1301while allowing callers to queue up on scarce resources. 1302.Sh AUTHORS 1303The 1304.Nm 1305interface was designed and implemented by 1306.An Jason R. Thorpe 1307of the Numerical Aerospace Simulation Facility, NASA Ames Research Center. 1308Additional input on the 1309.Nm 1310design was provided by 1311.An -nosplit 1312.An Chris Demetriou , 1313.An Charles Hannum , 1314.An Ross Harvey , 1315.An Matthew Jacob , 1316.An Jonathan Stone , 1317and 1318.An Matt Thomas . 1319.Pp 1320The 1321.Nm 1322interface in 1323.Fx 1324benefits from the contributions of 1325.An Justin T. Gibbs , 1326.An Peter Wemm , 1327.An Doug Rabson , 1328.An Matthew N. Dodd , 1329.An Sam Leffler , 1330.An Maxime Henrion , 1331.An Jake Burkholder , 1332.An Takahashi Yoshihiro , 1333.An Scott Long 1334and many others. 1335.Pp 1336This manual page was written by 1337.An Hiten M. Pandya 1338and 1339.An Justin T. Gibbs . 1340