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" "int 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 exising 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. 194.Pp 195The 196.Nm sglist_append 197function appends the physical address ranges described by a single kernel 198virtual address range to the scatter/gather list 199.Fa sg . 200The kernel virtual address range starts at 201.Fa buf 202and is 203.Fa len 204bytes long. 205.Pp 206The 207.Nm sglist_append_mbuf 208function appends the physical address ranges described by an entire mbuf 209chain 210.Fa m 211to the scatter/gather list 212.Fa sg . 213.Pp 214The 215.Nm sglist_append_phys 216function appends a single physical address range to the scatter/gather list 217.Fa sg . 218The physical address range starts at 219.Fa paddr 220and is 221.Fa len 222bytes long. 223.Pp 224The 225.Nm sglist_append_uio 226function appends the physical address ranges described by a 227.Xr uio 9 228object to the scatter/gather list 229.Fa sg . 230Note that it is the caller's responsibility to ensure that the pages backing 231the I/O request are wired for the lifetime of 232.Fa sg . 233Note also that this routine does not modify 234.Fa uio . 235.Pp 236The 237.Nm sglist_append_user 238function appends the physical address ranges described by a single user 239virtual address range to the scatter/gather list 240.Fa sg . 241The user virtual address range is relative to the address space of the thread 242.Fa td . 243It starts at 244.Fa buf 245and is 246.Fa len 247bytes long. 248Note that it is the caller's responsibility to ensure that the pages backing 249the user buffer are wired for the lifetime of 250.Fa sg . 251.Pp 252The 253.Nm sglist_consume_uio 254function is a variation of 255.Nm sglist_append_uio . 256As with 257.Nm sglist_append_uio , 258it appends the physical address ranges described by 259.Fa uio 260to the scatter/gather list 261.Fa sg . 262Unlike 263.Nm sglist_append_uio , 264however, 265.Nm sglist_consume_uio 266modifies the I/O request to indicate that the appended address ranges have 267been processed similar to calling 268.Xr uiomove 9 . 269This routine will only append ranges that describe up to 270.Fa resid 271total bytes in length. 272If the available segments in the scatter/gather list are exhausted before 273.Fa resid 274bytes are processed, 275then the 276.Fa uio 277structure will be updated to reflect the actual number of bytes processed, 278and 279.Nm sglist_consume_io 280will return zero to indicate success. 281In effect, this function will perform partial reads or writes. 282The caller can compare the 283.Fa uio_resid 284member of 285.Fa uio 286before and after calling 287.Nm sglist_consume_uio 288to determine the actual number of bytes processed. 289.Ss Manipulating Scatter/Gather Lists 290The 291.Nm sglist_join 292function appends physical address ranges from the scatter/gather list 293.Fa second 294onto 295.Fa first 296and then resets 297.Fa second 298to an empty list. 299It returns zero on success or an error on failure. 300.Pp 301The 302.Nm sglist_split 303function splits an existing scatter/gather list into two lists. 304The first 305.Fa length 306bytes described by the list 307.Fa original 308are moved to a new list 309.Fa *head . 310If 311.Fa original 312describes a total address range that is smaller than 313.Fa length 314bytes, 315then all of the address ranges will be moved to the new list at 316.Fa *head 317and 318.Fa original 319will be an empty list. 320The caller may supply an existing scatter/gather list in 321.Fa *head . 322If so, the list must be empty. 323Otherwise, the caller may set 324.Fa *head 325to 326.Dv NULL 327in which case a new scatter/gather list will be allocated. 328In that case, 329.Fa mflags 330may be set to either 331.Dv M_NOWAIT 332or 333.Dv M_WAITOK . 334Note that since the 335.Fa original 336list is modified by this call, it must be a private list with no other 337references. 338The 339.Nm sglist_split 340function returns zero on success or an error on failure. 341.Pp 342The 343.Nm sglist_slice 344function generates a new scatter/gather list from a sub-range of an existing 345scatter/gather list 346.Fa original . 347The sub-range to extract is specified by the 348.Fa offset 349and 350.Fa length 351parameters. 352The new scatter/gather list is stored in 353.Fa *slice . 354As with 355.Fa head 356for 357.Nm sglist_join , 358the caller may either provide an empty scatter/gather list, 359or it may set 360.Fa *slice 361to 362.Dv NULL 363in which case 364.Nm sglist_slice 365will allocate a new list subject to 366.Fa mflags . 367Unlike 368.Nm sglist_split , 369.Nm sglist_slice 370does not modify 371.Fa original 372and does not require it to be a private list. 373The 374.Nm sglist_split 375function returns zero on success or an error on failure. 376.Ss Miscellaneous Routines 377The 378.Nm sglist_reset 379function clears the scatter/gather list 380.Fa sg 381so that it no longer maps any address ranges. 382This can allow reuse of a single scatter/gather list object for multiple 383requests. 384.Pp 385The 386.Nm sglist_length 387function returns the total length of the physical address ranges described 388by the scatter/gather list 389.Fa sg . 390.Sh RETURN VALUES 391The 392.Nm sglist_alloc , 393.Nm sglist_build , 394and 395.Nm sglist_clone 396functions return a new scatter/gather list on success or 397.Dv NULL 398on failure. 399.Pp 400The 401.Nm sglist_append 402family of functions and the 403.Nm sglist_consume_uio , 404.Nm sglist_join , 405.Nm sglist_slice , 406and 407.Nm sglist_split 408functions return zero on success or an error on failure. 409.Pp 410The 411.Nm sglist_count 412function returns a count of scatter/gather list elements. 413.Pp 414The 415.Nm sglist_length 416function returns a count of address space described by a scatter/gather list 417in bytes. 418.Sh ERRORS 419The 420.Nm sglist_append 421functions return the following errors on failure: 422.Bl -tag -width Er 423.It Bq Er EINVAL 424The scatter/gather list has zero segments. 425.It Bq Er EFBIG 426There are not enough available segments in the scatter/gather list to append 427the specified physical address ranges. 428.El 429.Pp 430The 431.Nm sglist_consume_uio 432function returns the following error on failure: 433.Bl -tag -width Er 434.It Bq Er EINVAL 435The scatter/gather list has zero segments. 436.El 437.Pp 438The 439.Nm sglist_join 440function returns the following error on failure: 441.Bl -tag -width Er 442.It Bq Er EFBIG 443There are not enough available segments in the scatter/gather list 444.Fa first 445to append the physical address ranges from 446.Fa second . 447.El 448The 449.Nm sglist_slice 450function returns the following errors on failure: 451.Bl -tag -width Er 452.It Bq Er EINVAL 453The 454.Fa original 455scatter/gather list does not describe enough address space to cover the 456requested sub-range. 457.It Bq Er EINVAL 458The caller-supplied scatter/gather list in 459.Fa *slice 460is not empty. 461.It Bq Er ENOMEM 462An attempt to allocate a new scatter/gather list with 463.Dv M_NOWAIT 464set in 465.Fa mflags 466failed. 467.It Bq Er EFBIG 468There are not enough available segments in the caller-supplied scatter/gather 469list in 470.Fa *slice 471to describe the requested physical address ranges. 472.El 473The 474.Nm sglist_split 475function returns the following errors on failure: 476.Bl -tag -width Er 477.It Bq Er EDOOFUS 478The 479.Fa original 480scatter/gather list has more than one reference. 481.It Bq Er EINVAL 482The caller-supplied scatter/gather list in 483.Fa *head 484is not empty. 485.It Bq Er ENOMEM 486An attempt to allocate a new scatter/gather list with 487.Dv M_NOWAIT 488set in 489.Fa mflags 490failed. 491.It Bq Er EFBIG 492There are not enough available segments in the caller-supplied scatter/gather 493list in 494.Fa *head 495to describe the requested physical address ranges. 496.El 497.Sh SEE ALSO 498.Xr malloc 9 , 499.Xr mbuf 9 , 500.Xr uio 9 501.Sh HISTORY 502This API was first introduced in 503.Fx 8.0 . 504