xref: /illumos-gate/usr/src/man/man9f/ddi_dma_cookie_iter.9f (revision 012e6ce759c490003aed29439cc47d3d73a99ad3)
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