1.\" 2.\" Copyright (c) 2009 Advanced Computing Technologies LLC 3.\" Written by: John H. Baldwin <jhb@FreeBSD.org> 4.\" All rights reserved. 5.\" 6.\" Redistribution and use in source and binary forms, with or without 7.\" modification, are permitted provided that the following conditions 8.\" are met: 9.\" 1. Redistributions of source code must retain the above copyright 10.\" notice, this list of conditions and the following disclaimer. 11.\" 2. Redistributions in binary form must reproduce the above copyright 12.\" notice, this list of conditions and the following disclaimer in the 13.\" documentation and/or other materials provided with the distribution. 14.\" 15.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25.\" SUCH DAMAGE. 26.\" 27.\" $FreeBSD$ 28.\" 29.Dd May 15, 2009 30.Dt SGLIST 9 31.Os 32.Sh NAME 33.Nm sglist , 34.Nm sglist_alloc , 35.Nm sglist_append , 36.Nm sglist_append_mbuf , 37.Nm sglist_append_phys , 38.Nm sglist_append_uio , 39.Nm sglist_append_user , 40.Nm sglist_build , 41.Nm sglist_clone , 42.Nm sglist_consume_uio , 43.Nm sglist_count , 44.Nm sglist_free , 45.Nm sglist_hold , 46.Nm sglist_init , 47.Nm sglist_join , 48.Nm sglist_length , 49.Nm sglist_reset , 50.Nm sglist_slice , 51.Nm sglist_split 52.Nd manage a scatter/gather list of physical memory addresses 53.Sh SYNOPSIS 54.In sys/types.h 55.In sys/sglist.h 56.Ft struct sglist * 57.Fn sglist_alloc "int nsegs" "int mflags" 58.Ft int 59.Fn sglist_append "struct sglist *sg" "void *buf" "size_t len" 60.Ft int 61.Fn sglist_append_mbuf "struct sglist *sg" "struct mbuf *m" 62.Ft int 63.Fn sglist_append_phys "struct sglist *sg" "vm_paddr_t paddr" "size_t len" 64.Ft int 65.Fn sglist_append_uio "struct sglist *sg" "struct uio *uio" 66.Ft int 67.Fn sglist_append_user "struct sglist *sg" "void *buf" "size_t len" "struct thread *td" 68.Ft struct sglist * 69.Fn sglist_build "void *buf" "size_t len" "int mflags" 70.Ft struct sglist * 71.Fn sglist_clone "struct sglist *sg" "int mflags" 72.Ft int 73.Fn sglist_consume_uio "struct sglist *sg" "struct uio *uio" "size_t resid" 74.Ft int 75.Fn sglist_count "void *buf" "size_t len" 76.Ft void 77.Fn sglist_free "struct sglist *sg" 78.Ft struct sglist * 79.Fn sglist_hold "struct sglist *sg" 80.Ft void 81.Fn sglist_init "struct sglist *sg" "int maxsegs" "struct sglist_seg *segs" 82.Ft int 83.Fn sglist_join "struct sglist *first" "struct sglist *second" 84.Ft size_t 85.Fn sglist_length "struct sglist *sg" 86.Ft void 87.Fn sglist_reset "struct sglist *sg" 88.Ft int 89.Fn sglist_slice "struct sglist *original" "struct sglist **slice" "size_t offset" "size_t length" "int mflags" 90.Ft int 91.Fn sglist_split "struct sglist *original" "struct sglist **head" "size_t length" "int mflags" 92.Sh DESCRIPTION 93The 94.Nm 95API manages physical address ranges. 96Each list contains one or more elements. 97Each element contains a starting physical address and a length. 98Scatter/gather lists are read-only while they are shared. 99If one wishes to alter an existing scatter/gather list and does not hold the 100sole reference to the list, 101then one should create a new list instead of modifying the existing list. 102.Pp 103Each scatter/gather list object contains a reference count. 104New lists are created with a single reference. 105New references are obtained by calling 106.Nm sglist_hold 107and are released by calling 108.Nm sglist_free . 109.Ss Allocating and Initializing Lists 110Each 111.Nm 112object consists of a header structure and a variable-length array of 113scatter/gather list elements. 114The 115.Nm sglist_alloc 116function allocates a new list that contains a header and 117.Fa nsegs 118scatter/gather list elements. 119The 120.Fa mflags 121argument can be set to either 122.Dv M_NOWAIT 123or 124.Dv M_WAITOK . 125.Pp 126The 127.Nm sglist_count 128function returns the number of scatter/gather list elements needed to describe 129the physical address ranges mapped by a single kernel virtual address range. 130The kernel virtual address range starts at 131.Fa buf 132and is 133.Fa len 134bytes long. 135.Pp 136The 137.Nm sglist_build 138function allocates a new scatter/gather list object that describes the physical 139address ranges mapped by a single kernel virtual address range. 140The kernel virtual address range starts at 141.Fa buf 142and is 143.Fa len 144bytes long. 145The 146.Fa mflags 147argument can be set to either 148.Dv M_NOWAIT 149or 150.Dv M_WAITOK . 151.Pp 152The 153.Nm sglist_clone 154function returns a copy of an existing scatter/gather list object 155.Fa sg . 156The 157.Fa mflags 158argument can be set to either 159.Dv M_NOWAIT 160or 161.Dv M_WAITOK . 162This can be used to obtain a private copy of a scatter/gather list before 163modifying it. 164.Pp 165The 166.Nm sglist_init 167function initializes a scatter/gather list header. 168The header is pointed to by 169.Fa sg 170and is initialized to manage an array of 171.Fa maxsegs 172scatter/gather list elements pointed to by 173.Fa segs . 174This can be used to initialize a scatter/gather list header whose storage 175is not provided by 176.Nm sglist_alloc . 177In that case, the caller should not call 178.Nm sglist_free 179to release its own reference and is responsible for ensuring all other 180references to the list are dropped before it releases the storage for 181.Fa sg 182and 183.Fa segs . 184.Ss Constructing Scatter/Gather Lists 185The 186.Nm 187API provides several routines for building a scatter/gather list to describe 188one or more objects. 189Specifically, the 190.Nm sglist_append 191family of routines can be used to append the physical address ranges described 192by an object to the end of a scatter/gather list. 193All of these routines return 0 on success or an error on failure. 194If a request to append an address range to a scatter/gather list fails, 195the scatter/gather list will remain unchanged. 196.Pp 197The 198.Nm sglist_append 199function appends the physical address ranges described by a single kernel 200virtual address range to the scatter/gather list 201.Fa sg . 202The kernel virtual address range starts at 203.Fa buf 204and is 205.Fa len 206bytes long. 207.Pp 208The 209.Nm sglist_append_mbuf 210function appends the physical address ranges described by an entire mbuf 211chain 212.Fa m 213to the scatter/gather list 214.Fa sg . 215.Pp 216The 217.Nm sglist_append_phys 218function appends a single physical address range to the scatter/gather list 219.Fa sg . 220The physical address range starts at 221.Fa paddr 222and is 223.Fa len 224bytes long. 225.Pp 226The 227.Nm sglist_append_uio 228function appends the physical address ranges described by a 229.Xr uio 9 230object to the scatter/gather list 231.Fa sg . 232Note that it is the caller's responsibility to ensure that the pages backing 233the I/O request are wired for the lifetime of 234.Fa sg . 235Note also that this routine does not modify 236.Fa uio . 237.Pp 238The 239.Nm sglist_append_user 240function appends the physical address ranges described by a single user 241virtual address range to the scatter/gather list 242.Fa sg . 243The user virtual address range is relative to the address space of the thread 244.Fa td . 245It starts at 246.Fa buf 247and is 248.Fa len 249bytes long. 250Note that it is the caller's responsibility to ensure that the pages backing 251the user buffer are wired for the lifetime of 252.Fa sg . 253.Pp 254The 255.Nm sglist_consume_uio 256function is a variation of 257.Nm sglist_append_uio . 258As with 259.Nm sglist_append_uio , 260it appends the physical address ranges described by 261.Fa uio 262to the scatter/gather list 263.Fa sg . 264Unlike 265.Nm sglist_append_uio , 266however, 267.Nm sglist_consume_uio 268modifies the I/O request to indicate that the appended address ranges have 269been processed similar to calling 270.Xr uiomove 9 . 271This routine will only append ranges that describe up to 272.Fa resid 273total bytes in length. 274If the available segments in the scatter/gather list are exhausted before 275.Fa resid 276bytes are processed, 277then the 278.Fa uio 279structure will be updated to reflect the actual number of bytes processed, 280and 281.Nm sglist_consume_io 282will return zero to indicate success. 283In effect, this function will perform partial reads or writes. 284The caller can compare the 285.Fa uio_resid 286member of 287.Fa uio 288before and after calling 289.Nm sglist_consume_uio 290to determine the actual number of bytes processed. 291.Ss Manipulating Scatter/Gather Lists 292The 293.Nm sglist_join 294function appends physical address ranges from the scatter/gather list 295.Fa second 296onto 297.Fa first 298and then resets 299.Fa second 300to an empty list. 301It returns zero on success or an error on failure. 302.Pp 303The 304.Nm sglist_split 305function splits an existing scatter/gather list into two lists. 306The first 307.Fa length 308bytes described by the list 309.Fa original 310are moved to a new list 311.Fa *head . 312If 313.Fa original 314describes a total address range that is smaller than 315.Fa length 316bytes, 317then all of the address ranges will be moved to the new list at 318.Fa *head 319and 320.Fa original 321will be an empty list. 322The caller may supply an existing scatter/gather list in 323.Fa *head . 324If so, the list must be empty. 325Otherwise, the caller may set 326.Fa *head 327to 328.Dv NULL 329in which case a new scatter/gather list will be allocated. 330In that case, 331.Fa mflags 332may be set to either 333.Dv M_NOWAIT 334or 335.Dv M_WAITOK . 336Note that since the 337.Fa original 338list is modified by this call, it must be a private list with no other 339references. 340The 341.Nm sglist_split 342function returns zero on success or an error on failure. 343.Pp 344The 345.Nm sglist_slice 346function generates a new scatter/gather list from a sub-range of an existing 347scatter/gather list 348.Fa original . 349The sub-range to extract is specified by the 350.Fa offset 351and 352.Fa length 353parameters. 354The new scatter/gather list is stored in 355.Fa *slice . 356As with 357.Fa head 358for 359.Nm sglist_join , 360the caller may either provide an empty scatter/gather list, 361or it may set 362.Fa *slice 363to 364.Dv NULL 365in which case 366.Nm sglist_slice 367will allocate a new list subject to 368.Fa mflags . 369Unlike 370.Nm sglist_split , 371.Nm sglist_slice 372does not modify 373.Fa original 374and does not require it to be a private list. 375The 376.Nm sglist_split 377function returns zero on success or an error on failure. 378.Ss Miscellaneous Routines 379The 380.Nm sglist_reset 381function clears the scatter/gather list 382.Fa sg 383so that it no longer maps any address ranges. 384This can allow reuse of a single scatter/gather list object for multiple 385requests. 386.Pp 387The 388.Nm sglist_length 389function returns the total length of the physical address ranges described 390by the scatter/gather list 391.Fa sg . 392.Sh RETURN VALUES 393The 394.Nm sglist_alloc , 395.Nm sglist_build , 396and 397.Nm sglist_clone 398functions return a new scatter/gather list on success or 399.Dv NULL 400on failure. 401.Pp 402The 403.Nm sglist_append 404family of functions and the 405.Nm sglist_consume_uio , 406.Nm sglist_join , 407.Nm sglist_slice , 408and 409.Nm sglist_split 410functions return zero on success or an error on failure. 411.Pp 412The 413.Nm sglist_count 414function returns a count of scatter/gather list elements. 415.Pp 416The 417.Nm sglist_length 418function returns a count of address space described by a scatter/gather list 419in bytes. 420.Sh ERRORS 421The 422.Nm sglist_append 423functions return the following errors on failure: 424.Bl -tag -width Er 425.It Bq Er EINVAL 426The scatter/gather list has zero segments. 427.It Bq Er EFBIG 428There are not enough available segments in the scatter/gather list to append 429the specified physical address ranges. 430.El 431.Pp 432The 433.Nm sglist_consume_uio 434function returns the following error on failure: 435.Bl -tag -width Er 436.It Bq Er EINVAL 437The scatter/gather list has zero segments. 438.El 439.Pp 440The 441.Nm sglist_join 442function returns the following error on failure: 443.Bl -tag -width Er 444.It Bq Er EFBIG 445There are not enough available segments in the scatter/gather list 446.Fa first 447to append the physical address ranges from 448.Fa second . 449.El 450.Pp 451The 452.Nm sglist_slice 453function returns the following errors on failure: 454.Bl -tag -width Er 455.It Bq Er EINVAL 456The 457.Fa original 458scatter/gather list does not describe enough address space to cover the 459requested sub-range. 460.It Bq Er EINVAL 461The caller-supplied scatter/gather list in 462.Fa *slice 463is not empty. 464.It Bq Er ENOMEM 465An attempt to allocate a new scatter/gather list with 466.Dv M_NOWAIT 467set in 468.Fa mflags 469failed. 470.It Bq Er EFBIG 471There are not enough available segments in the caller-supplied scatter/gather 472list in 473.Fa *slice 474to describe the requested physical address ranges. 475.El 476.Pp 477The 478.Nm sglist_split 479function returns the following errors on failure: 480.Bl -tag -width Er 481.It Bq Er EDOOFUS 482The 483.Fa original 484scatter/gather list has more than one reference. 485.It Bq Er EINVAL 486The caller-supplied scatter/gather list in 487.Fa *head 488is not empty. 489.It Bq Er ENOMEM 490An attempt to allocate a new scatter/gather list with 491.Dv M_NOWAIT 492set in 493.Fa mflags 494failed. 495.It Bq Er EFBIG 496There are not enough available segments in the caller-supplied scatter/gather 497list in 498.Fa *head 499to describe the requested physical address ranges. 500.El 501.Sh SEE ALSO 502.Xr malloc 9 , 503.Xr mbuf 9 , 504.Xr uio 9 505.Sh HISTORY 506This API was first introduced in 507.Fx 8.0 . 508