diff usr/src/man/man9f/ddi_dma_cookie_iter.9f @ 19431:5599be23ae32

12183 Want new IPD 13 DMA Cookie APIs Reviewed by: Alex Wilson <alex@uq.edu.au> Reviewed by: Paul Winder <paul@winders.demon.co.uk> Reviewed by: Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org> Reviewed by: Garrett D'Amore <garrett@damore.org> Approved by: Garrett D'Amore <garrett@damore.org>
author Robert Mustacchi <rm@fingolfin.org>
date Wed, 18 Dec 2019 06:18:35 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/man/man9f/ddi_dma_cookie_iter.9f	Wed Dec 18 06:18:35 2019 +0000
@@ -0,0 +1,282 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source.  A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\"
+.\" Copyright 2019 Robert Mustacchi
+.\"
+.Dd December 9, 2019
+.Dt DDI_DMA_COOKIE_ITER 9F
+.Os
+.Sh NAME
+.Nm ddi_dma_cookie_get ,
+.Nm ddi_dma_cookie_iter ,
+.Nm ddi_dma_cookie_one ,
+.Nm ddi_dma_ncookies ,
+.Nm ddi_dma_nextcookie
+.Nd retrieve DMA cookies
+.Sh SYNOPSIS
+.In sys/ddi.h
+.In sys/sunddi.h
+.Ft "const ddi_dma_cookie_t *"
+.Fo ddi_dma_cookie_iter
+.Fa "ddi_dma_handle_t handle"
+.Fa "const ddi_dma_cookie_t *cookiep"
+.Fc
+.Ft "const ddi_dma_cookie_t *"
+.Fo ddi_dma_cookie_get
+.Fa "ddi_dma_handle_t handle"
+.Fa "uint_t index"
+.Fc
+.Ft "const ddi_dma_cookie_t *"
+.Fo ddi_dma_cookie_one
+.Fa "ddi_dma_handle_t handle"
+.Fc
+.Ft "uint_t"
+.Fo ddi_dma_ncookies
+.Fa "ddi_dma_handle_t handle"
+.Fc
+.Ft void
+.Fo ddi_dma_nextcookie
+.Fa "ddi_dma_handle_t handle"
+.Fa "ddi_dma_cookie_t *cookiep"
+.Fc
+.Sh PARAMETERS
+.Bl -tag -width Fa
+.It Fa handle
+The DMA handle obtained by a call to
+.Xr ddi_dma_alloc_handle 9F .
+.It Fa cookie
+A pointer to a
+.Xr ddi_dma_cookie 9S
+structure.
+.It Fa index
+An unsigned integer that represents the index of a cookie to obtain.
+The first entry is at index zero.
+.El
+.Sh DESCRIPTION
+The
+.Fn ddi_dma_cookie_iter ,
+.Fn ddi_dma_cookie_get ,
+and
+.Fn ddi_dma_cookie_one
+functions obtain information about DMA cookies.
+When a DMA request, represented by the DMA handle
+.Fa handle ,
+has been bound to a series of addresses with the
+.Xr ddi_dma_addr_bind_handle 9F
+or
+.Xr ddi_dma_buf_bind_handle 9F
+functions, the resulting addresses are stored in one or more
+.Xr ddi_dma_cookie 9S
+structures.
+the three different functions provide different ways to obtain cookies
+and are safe alternatives to the unsafe
+.Fn ddi_dma_nextcookie
+function.
+To see how to use these functions, please see the
+.Sx EXAMPLES
+section.
+.Pp
+The
+.Fn ddi_dma_cookie_iter
+function provides a way to iterate over all the cookies that are
+associated with the DMA handle
+.Fa handle .
+To get the first handle, pass
+.Dv NULL
+in
+.Fa cookiep .
+Do not use the DMA cookie returned from either of the
+.Xr ddi_dma_addr_bind_handle 9F
+or
+.Xr ddi_dma_buf_bind_handle 9F
+functions.
+To get subsequent cookies, pass the returned cookie as the argument
+.Fa cookiep .
+When the function returns
+.Dv NULL
+then that indicates that the last handle has been iterated over.
+.Pp
+The
+.Fn ddi_dma_cookie_get
+function returns a specific cookie.
+The
+.Fa index
+indicates which of the cookies should be returned.
+The first cookie is at index
+.Sy 0 .
+If an invalid index is specified, the function returns
+.Dv NULL .
+.Pp
+The
+.Ft ddi_dma_cookie_one
+function is a convenience function for DMA requests that have a single
+cookie.
+This function always returns the single cookie assosciated with the DMA
+handle
+.Fa handle .
+If this function is used when there is a DMA request with multiple
+cookies, then it will panic the system.
+It can never return
+.Dv NULL .
+.Pp
+The
+.Fn ddi_dma_ncookies
+function returns the number of DMA cookies that are associated with the
+DMA handle
+.Fa handle .
+If there are no DMA resources bound to the handle, then this will return
+.Sy 0 .
+.Pp
+The
+.Fn ddi_dma_nextcookie
+function was the historical function that was associated with obtaining
+DMA cookies.
+It should not be used due to several flaws.
+The
+.Fn ddi_dma_nextcookie
+function mutates the underlying DMA handle meaning that a driver cannot
+obtain a cookie a second time and thus a device driver using this
+interface must either manually keep storage of the cookie around wasting
+space or rebind the handle, wasting time.
+In addition, there is no way for the function to indicate that a driver
+has consumed all of its cookies.
+If for some reason a device driver calls the
+.Fn ddi_dma_nextcookie
+function more times than there are cookies, the results are undefined.
+In short, this function should not be used for any purpose.
+Use the
+.Fn ddi_dma_cookie_iter ,
+.Fn ddi_dma_cookie_get ,
+or
+.Fn ddi_dma_cookie_one
+functions instead.
+.Sh CONTEXT
+The
+.Fn ddi_dma_cookie_iter ,
+.Fn ddi_dma_cookie_get ,
+.Fn ddi_dma_cookie_one ,
+.Fn ddi_dma_ncookies ,
+and
+.Fn ddi_dma_nextcookie
+functions may be called from
+.Sy user ,
+.Sy kernel ,
+or
+.Sy interrupt
+context.
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn ddi_dma_cookie_iter ,
+.Fn ddi_dma_cookie_get ,
+.Fn ddi_dma_cookie_one
+functions will return the requested DMA cookie.
+If there are no more cookies, or
+.Fa coookiep
+is invalid, the
+.Fn ddi_dma_cookie_iter
+function will return
+.Dv NULL .
+If
+.Fa index
+does not correspond to a valid cookie, the
+.Fn ddi_dma_cookie_get
+function will return
+.Dv NULL .
+If there is not exactly one DMA cookie, or another issue occurs, then the
+.Fn ddi_dma_cookie_one
+function will panic the system.
+.Pp
+Upon successful completion, the
+.Fn ddi_dma_ncookies
+function returns the number of cookies associated with
+.Fa handle .
+If there are none, then
+.Sy 0
+is returned.
+.Pp
+The
+.Fn ddi_dma_nextcookie
+function always updates
+.Fa cookiep
+regardless of whether it is valid or not.
+.Sh EXAMPLES
+.Sy Example 1
+Using the
+.Fn ddi_dma_cookie_iter
+function to obtain all DMA cookies.
+.Bd -literal
+/*
+ * This example assumes that either ddi_dma_addr_bind_handle() or
+ * ddi_dma_buf_bind_handle() has already been successfully called.
+ */
+void
+program_dma(ddi_dma_handle_t handle)
+{
+	const ddi_dma_cookie_t *c;
+
+	for (cookie = ddi_dma_cookie_iter(handle, NULL); c != NULL;
+	    c = ddi_dma_cookie_iter(handle, c)) {
+		/*
+		 * Use the dmac_laddress and dmac_size members to
+		 * properly program the device or descriptor rings.
+		 */
+	}
+}
+.Ed
+.Pp
+.Sy Example 2
+Using the
+.Fn ddi_dma_cookie_get
+function.
+.Bd -literal
+/*
+ * This example assumes that either ddi_dma_mem_alloc() has already
+ * been successfully called.
+ */
+int
+bind_dma(ddi_dma_handle_t handle, void *addr, size_t len)
+{
+	int ret;
+	uint_t i, ncookies;
+	ddi_dma_cookie_t first;
+
+	ret = ddi_dma_addr_bind_handle(handle, NULL, addr, len,
+	    DDI_DMA_RDWR | DDI_DMA_CONSISTENT, NULL, NULL, &first,
+	    &ncookies);
+	if (ret != DDI_DMA_MAPPED) {
+		return (ret);
+	}
+
+	/*
+	 * A driver doesn't need to store ncookies. It can get it again
+	 * by simply calling ddi_dma_ncookies() and using the result in
+	 * place of ncookies from ddi_dma_addr_bind_handle().
+	 */
+	for (i = 0; i < ncookies; i++) {
+		const ddi_dma_cookie_t *cookie;
+
+		cookie = ddi_dma_coookie_get(handle, i);
+		/*
+		 * Use the dmac_laddress and dmac_size members to
+		 * properly program the device or descriptor rings.
+		 */
+	}
+}
+.Ed
+.Sh SEE ALSO
+.Xr ddi_dma_addr_bind_handle 9F ,
+.Xr ddi_dma_alloc_handle 9F ,
+.Xr ddi_dma_buf_bind_handle 9F ,
+.Xr ddi_dma_unbind_handle 9F ,
+.Xr ddi_dma_cookie 9S
+.Rs
+.%T Writing Device Drivers
+.Re