1.\" 2.\" This file and its contents are supplied under the terms of the 3.\" Common Development and Distribution License ("CDDL"), version 1.0. 4.\" You may only use this file in accordance with the terms of version 5.\" 1.0 of the CDDL. 6.\" 7.\" A full copy of the text of the CDDL should have accompanied this 8.\" source. A copy of the CDDL is also available via the Internet at 9.\" http://www.illumos.org/license/CDDL. 10.\" 11.\" 12.\" Copyright 2019 Robert Mustacchi 13.\" 14.Dd March 10, 2023 15.Dt DDI_DMA_COOKIE_ITER 9F 16.Os 17.Sh NAME 18.Nm ddi_dma_cookie_get , 19.Nm ddi_dma_cookie_iter , 20.Nm ddi_dma_cookie_one , 21.Nm ddi_dma_ncookies , 22.Nm ddi_dma_nextcookie 23.Nd retrieve DMA cookies 24.Sh SYNOPSIS 25.In sys/ddi.h 26.In sys/sunddi.h 27.Ft "const ddi_dma_cookie_t *" 28.Fo ddi_dma_cookie_iter 29.Fa "ddi_dma_handle_t handle" 30.Fa "const ddi_dma_cookie_t *cookiep" 31.Fc 32.Ft "const ddi_dma_cookie_t *" 33.Fo ddi_dma_cookie_get 34.Fa "ddi_dma_handle_t handle" 35.Fa "uint_t index" 36.Fc 37.Ft "const ddi_dma_cookie_t *" 38.Fo ddi_dma_cookie_one 39.Fa "ddi_dma_handle_t handle" 40.Fc 41.Ft "uint_t" 42.Fo ddi_dma_ncookies 43.Fa "ddi_dma_handle_t handle" 44.Fc 45.Ft void 46.Fo ddi_dma_nextcookie 47.Fa "ddi_dma_handle_t handle" 48.Fa "ddi_dma_cookie_t *cookiep" 49.Fc 50.Sh PARAMETERS 51.Bl -tag -width Fa 52.It Fa handle 53The DMA handle obtained by a call to 54.Xr ddi_dma_alloc_handle 9F . 55.It Fa cookie 56A pointer to a 57.Xr ddi_dma_cookie 9S 58structure. 59.It Fa index 60An unsigned integer that represents the index of a cookie to obtain. 61The first entry is at index zero. 62.El 63.Sh DESCRIPTION 64The 65.Fn ddi_dma_cookie_iter , 66.Fn ddi_dma_cookie_get , 67and 68.Fn ddi_dma_cookie_one 69functions obtain information about DMA cookies. 70When a DMA request, represented by the DMA handle 71.Fa handle , 72has been bound to a series of addresses with the 73.Xr ddi_dma_addr_bind_handle 9F 74or 75.Xr ddi_dma_buf_bind_handle 9F 76functions, the resulting addresses are stored in one or more 77.Xr ddi_dma_cookie 9S 78structures. 79the three different functions provide different ways to obtain cookies 80and are safe alternatives to the unsafe 81.Fn ddi_dma_nextcookie 82function. 83To see how to use these functions, please see the 84.Sx EXAMPLES 85section. 86.Pp 87The 88.Fn ddi_dma_cookie_iter 89function provides a way to iterate over all the cookies that are 90associated with the DMA handle 91.Fa handle . 92To get the first handle, pass 93.Dv NULL 94in 95.Fa cookiep . 96Do not use the DMA cookie returned from either of the 97.Xr ddi_dma_addr_bind_handle 9F 98or 99.Xr ddi_dma_buf_bind_handle 9F 100functions. 101To get subsequent cookies, pass the returned cookie as the argument 102.Fa cookiep . 103When the function returns 104.Dv NULL 105then that indicates that the last handle has been iterated over. 106.Pp 107The 108.Fn ddi_dma_cookie_get 109function returns a specific cookie. 110The 111.Fa index 112indicates which of the cookies should be returned. 113The first cookie is at index 114.Sy 0 . 115If an invalid index is specified, the function returns 116.Dv NULL . 117.Pp 118The 119.Ft ddi_dma_cookie_one 120function is a convenience function for DMA requests that have a single 121cookie. 122This function always returns the single cookie associated with the DMA 123handle 124.Fa handle . 125If this function is used when there is a DMA request with multiple 126cookies, then it will panic the system. 127It can never return 128.Dv NULL . 129.Pp 130The 131.Fn ddi_dma_ncookies 132function returns the number of DMA cookies that are associated with the 133DMA handle 134.Fa handle . 135If there are no DMA resources bound to the handle, then this will return 136.Sy 0 . 137.Pp 138The 139.Fn ddi_dma_nextcookie 140function was the historical function that was associated with obtaining 141DMA cookies. 142It should not be used due to several flaws. 143The 144.Fn ddi_dma_nextcookie 145function mutates the underlying DMA handle meaning that a driver cannot 146obtain a cookie a second time and thus a device driver using this 147interface must either manually keep storage of the cookie around wasting 148space or rebind the handle, wasting time. 149In addition, there is no way for the function to indicate that a driver 150has consumed all of its cookies. 151If for some reason a device driver calls the 152.Fn ddi_dma_nextcookie 153function more times than there are cookies, the results are undefined. 154In short, this function should not be used for any purpose. 155Use the 156.Fn ddi_dma_cookie_iter , 157.Fn ddi_dma_cookie_get , 158or 159.Fn ddi_dma_cookie_one 160functions instead. 161.Sh CONTEXT 162The 163.Fn ddi_dma_cookie_iter , 164.Fn ddi_dma_cookie_get , 165.Fn ddi_dma_cookie_one , 166.Fn ddi_dma_ncookies , 167and 168.Fn ddi_dma_nextcookie 169functions may be called from 170.Sy user , 171.Sy kernel , 172or 173.Sy interrupt 174context. 175.Sh RETURN VALUES 176Upon successful completion, the 177.Fn ddi_dma_cookie_iter , 178.Fn ddi_dma_cookie_get , 179.Fn ddi_dma_cookie_one 180functions will return the requested DMA cookie. 181If there are no more cookies, or 182.Fa cookiep 183is invalid, the 184.Fn ddi_dma_cookie_iter 185function will return 186.Dv NULL . 187If 188.Fa index 189does not correspond to a valid cookie, the 190.Fn ddi_dma_cookie_get 191function will return 192.Dv NULL . 193If there is not exactly one DMA cookie, or another issue occurs, then the 194.Fn ddi_dma_cookie_one 195function will panic the system. 196.Pp 197Upon successful completion, the 198.Fn ddi_dma_ncookies 199function returns the number of cookies associated with 200.Fa handle . 201If there are none, then 202.Sy 0 203is returned. 204.Pp 205The 206.Fn ddi_dma_nextcookie 207function always updates 208.Fa cookiep 209regardless of whether it is valid or not. 210.Sh EXAMPLES 211.Sy Example 1 212Using the 213.Fn ddi_dma_cookie_iter 214function to obtain all DMA cookies. 215.Bd -literal 216/* 217 * This example assumes that either ddi_dma_addr_bind_handle() or 218 * ddi_dma_buf_bind_handle() has already been successfully called. 219 */ 220void 221program_dma(ddi_dma_handle_t handle) 222{ 223 const ddi_dma_cookie_t *c; 224 225 for (cookie = ddi_dma_cookie_iter(handle, NULL); c != NULL; 226 c = ddi_dma_cookie_iter(handle, c)) { 227 /* 228 * Use the dmac_laddress and dmac_size members to 229 * properly program the device or descriptor rings. 230 */ 231 } 232} 233.Ed 234.Pp 235.Sy Example 2 236Using the 237.Fn ddi_dma_cookie_get 238function. 239.Bd -literal 240/* 241 * This example assumes that either ddi_dma_mem_alloc() has already 242 * been successfully called. 243 */ 244int 245bind_dma(ddi_dma_handle_t handle, void *addr, size_t len) 246{ 247 int ret; 248 uint_t i, ncookies; 249 ddi_dma_cookie_t first; 250 251 ret = ddi_dma_addr_bind_handle(handle, NULL, addr, len, 252 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, NULL, NULL, &first, 253 &ncookies); 254 if (ret != DDI_DMA_MAPPED) { 255 return (ret); 256 } 257 258 /* 259 * A driver doesn't need to store ncookies. It can get it again 260 * by simply calling ddi_dma_ncookies() and using the result in 261 * place of ncookies from ddi_dma_addr_bind_handle(). 262 */ 263 for (i = 0; i < ncookies; i++) { 264 const ddi_dma_cookie_t *cookie; 265 266 cookie = ddi_dma_cookie_get(handle, i); 267 /* 268 * Use the dmac_laddress and dmac_size members to 269 * properly program the device or descriptor rings. 270 */ 271 } 272} 273.Ed 274.Sh SEE ALSO 275.Xr ddi_dma_addr_bind_handle 9F , 276.Xr ddi_dma_alloc_handle 9F , 277.Xr ddi_dma_buf_bind_handle 9F , 278.Xr ddi_dma_unbind_handle 9F , 279.Xr ddi_dma_cookie 9S 280.Rs 281.%T Writing Device Drivers 282.Re 283