xref: /illumos-gate/usr/src/uts/common/sys/dcopy.h (revision 17169044)
1*17169044Sbrutus /*
2*17169044Sbrutus  * CDDL HEADER START
3*17169044Sbrutus  *
4*17169044Sbrutus  * The contents of this file are subject to the terms of the
5*17169044Sbrutus  * Common Development and Distribution License (the "License").
6*17169044Sbrutus  * You may not use this file except in compliance with the License.
7*17169044Sbrutus  *
8*17169044Sbrutus  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*17169044Sbrutus  * or http://www.opensolaris.org/os/licensing.
10*17169044Sbrutus  * See the License for the specific language governing permissions
11*17169044Sbrutus  * and limitations under the License.
12*17169044Sbrutus  *
13*17169044Sbrutus  * When distributing Covered Code, include this CDDL HEADER in each
14*17169044Sbrutus  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*17169044Sbrutus  * If applicable, add the following below this CDDL HEADER, with the
16*17169044Sbrutus  * fields enclosed by brackets "[]" replaced with your own identifying
17*17169044Sbrutus  * information: Portions Copyright [yyyy] [name of copyright owner]
18*17169044Sbrutus  *
19*17169044Sbrutus  * CDDL HEADER END
20*17169044Sbrutus  */
21*17169044Sbrutus 
22*17169044Sbrutus /*
23*17169044Sbrutus  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*17169044Sbrutus  * Use is subject to license terms.
25*17169044Sbrutus  */
26*17169044Sbrutus 
27*17169044Sbrutus #ifndef _SYS_DCOPY_H
28*17169044Sbrutus #define	_SYS_DCOPY_H
29*17169044Sbrutus 
30*17169044Sbrutus #pragma ident	"%Z%%M%	%I%	%E% SMI"
31*17169044Sbrutus 
32*17169044Sbrutus #ifdef __cplusplus
33*17169044Sbrutus extern "C" {
34*17169044Sbrutus #endif
35*17169044Sbrutus 
36*17169044Sbrutus #include <sys/types.h>
37*17169044Sbrutus 
38*17169044Sbrutus /*
39*17169044Sbrutus  * *** This interface is for private use by the IP stack only ***
40*17169044Sbrutus  */
41*17169044Sbrutus 
42*17169044Sbrutus /* Private dcopy/uioa interface for dcopy to enable/disable dcopy KAPI */
43*17169044Sbrutus extern void uioa_dcopy_enable();
44*17169044Sbrutus extern void uioa_dcopy_disable();
45*17169044Sbrutus 
46*17169044Sbrutus /* Function return status */
47*17169044Sbrutus #define	DCOPY_FAILURE		(-1)
48*17169044Sbrutus #define	DCOPY_SUCCESS		(0)
49*17169044Sbrutus #define	DCOPY_NORESOURCES	(1) /* _alloc & _cmd_alloc, _cmd_post only */
50*17169044Sbrutus #define	DCOPY_PENDING		(0x10) /* dcopy_poll(), dcopy_unregister() */
51*17169044Sbrutus #define	DCOPY_COMPLETED		(0x20) /* dcopy_poll() only */
52*17169044Sbrutus 
53*17169044Sbrutus 
54*17169044Sbrutus /* dq_version */
55*17169044Sbrutus #define	DCOPY_QUERY_V0	0
56*17169044Sbrutus 
57*17169044Sbrutus typedef struct dcopy_query_s {
58*17169044Sbrutus 	int		dq_version; /* DCOPY_QUERY_V0 */
59*17169044Sbrutus 	uint_t		dq_num_channels; /* number of dma channels */
60*17169044Sbrutus } dcopy_query_t;
61*17169044Sbrutus 
62*17169044Sbrutus /*
63*17169044Sbrutus  * dcopy_query()
64*17169044Sbrutus  *   query for the number of DMA engines usable in the system.
65*17169044Sbrutus  */
66*17169044Sbrutus void dcopy_query(dcopy_query_t *query);
67*17169044Sbrutus 
68*17169044Sbrutus 
69*17169044Sbrutus typedef struct dcopy_channel_s *dcopy_handle_t;
70*17169044Sbrutus 
71*17169044Sbrutus /* dcopy_alloc() and dcopy_cmd_alloc() common flags */
72*17169044Sbrutus #define	DCOPY_SLEEP	(0)
73*17169044Sbrutus #define	DCOPY_NOSLEEP	(1 << 0)
74*17169044Sbrutus 
75*17169044Sbrutus /*
76*17169044Sbrutus  * dcopy_alloc()
77*17169044Sbrutus  *   Allocate a DMA channel which is used for posting DMA requests. Note: this
78*17169044Sbrutus  *   does not give the caller exclusive access to the DMA engine. Commands
79*17169044Sbrutus  *   posted to a channel will complete in order.
80*17169044Sbrutus  *     flags - (DCOPY_SLEEP, DCOPY_NOSLEEP)
81*17169044Sbrutus  *     returns => DCOPY_FAILURE, DCOPY_SUCCESS, DCOPY_NORESOURCES
82*17169044Sbrutus  */
83*17169044Sbrutus int dcopy_alloc(int flags, dcopy_handle_t *handle);
84*17169044Sbrutus 
85*17169044Sbrutus /*
86*17169044Sbrutus  * dcopy_free()
87*17169044Sbrutus  *   Free the DMA channel. The client can no longer use the handle to post or
88*17169044Sbrutus  *   poll for status on posts which were previously done on this channel.
89*17169044Sbrutus  */
90*17169044Sbrutus void dcopy_free(dcopy_handle_t *handle);
91*17169044Sbrutus 
92*17169044Sbrutus /* dq_version */
93*17169044Sbrutus #define	DCOPY_QUERY_CHANNEL_V0	0
94*17169044Sbrutus 
95*17169044Sbrutus /* Per DMA channel info */
96*17169044Sbrutus typedef struct dcopy_query_channel_s {
97*17169044Sbrutus 	int		qc_version; /* DCOPY_QUERY_CHANNEL_V0 */
98*17169044Sbrutus 
99*17169044Sbrutus 	/* Does DMA channel support DCA */
100*17169044Sbrutus 	boolean_t	qc_dca_supported;
101*17169044Sbrutus 
102*17169044Sbrutus 	/* device id and device specific capabilities */
103*17169044Sbrutus 	uint64_t	qc_id;
104*17169044Sbrutus 	uint64_t	qc_capabilities;
105*17169044Sbrutus 
106*17169044Sbrutus 	/*
107*17169044Sbrutus 	 * DMA channel size. This may not be the same as the number of posts
108*17169044Sbrutus 	 * that the DMA channel can handle since a post may consume 1 or more
109*17169044Sbrutus 	 * entries.
110*17169044Sbrutus 	 */
111*17169044Sbrutus 	uint64_t	qc_channel_size;
112*17169044Sbrutus 
113*17169044Sbrutus 	/* DMA channel number within the device. Not unique across devices */
114*17169044Sbrutus 	uint64_t	qc_chan_num;
115*17169044Sbrutus } dcopy_query_channel_t;
116*17169044Sbrutus 
117*17169044Sbrutus /*
118*17169044Sbrutus  * dcopy_query_channel()
119*17169044Sbrutus  *   query DMA engines capabilities
120*17169044Sbrutus  */
121*17169044Sbrutus void dcopy_query_channel(dcopy_handle_t handle, dcopy_query_channel_t *query);
122*17169044Sbrutus 
123*17169044Sbrutus 
124*17169044Sbrutus /* dp_version */
125*17169044Sbrutus #define	DCOPY_CMD_V0	0
126*17169044Sbrutus 
127*17169044Sbrutus /* dp_cmd */
128*17169044Sbrutus #define	DCOPY_CMD_COPY	0x1
129*17169044Sbrutus 
130*17169044Sbrutus /* dp_flags */
131*17169044Sbrutus /*
132*17169044Sbrutus  * DCOPY_CMD_QUEUE
133*17169044Sbrutus  *    Hint to queue up the post but don't notify the DMA engine. This can be
134*17169044Sbrutus  *    used as an optimization when multiple posts are going to be queued up and
135*17169044Sbrutus  *    you only want notify the DMA engine after the last post. Note, this does
136*17169044Sbrutus  *    not mean the DMA engine won't process the request since it could notice
137*17169044Sbrutus  *    it anyway.
138*17169044Sbrutus  * DCOPY_CMD_NOSTAT
139*17169044Sbrutus  *    Don't generate a status. If this flag is used, You cannot poll for
140*17169044Sbrutus  *    completion status on this command. This can be a useful performance
141*17169044Sbrutus  *    optimization if your posting multiple commands and just want to poll on
142*17169044Sbrutus  *    the last command.
143*17169044Sbrutus  * DCOPY_CMD_DCA
144*17169044Sbrutus  *    If DCA is supported, direct this and all future command data (until the
145*17169044Sbrutus  *    next command with DCOPY_POST_DCA set) to the processor specified in
146*17169044Sbrutus  *    dp_dca_id. This flag is ignored if DCA is not supported.
147*17169044Sbrutus  * DCOPY_CMD_INTR
148*17169044Sbrutus  *    Generate an interrupt when command completes. This flag is required if
149*17169044Sbrutus  *    the caller is going to call dcopy_cmd_poll(() with DCOPY_POLL_BLOCK set
150*17169044Sbrutus  *    for this command.
151*17169044Sbrutus  */
152*17169044Sbrutus #define	DCOPY_CMD_NOFLAGS	(0)
153*17169044Sbrutus #define	DCOPY_CMD_QUEUE		(1 << 0)
154*17169044Sbrutus #define	DCOPY_CMD_NOSTAT	(1 << 1)
155*17169044Sbrutus #define	DCOPY_CMD_DCA		(1 << 2)
156*17169044Sbrutus #define	DCOPY_CMD_INTR		(1 << 3)
157*17169044Sbrutus 
158*17169044Sbrutus typedef struct dcopy_cmd_copy_s {
159*17169044Sbrutus 	uint64_t	cc_source; /* Source physical address */
160*17169044Sbrutus 	uint64_t	cc_dest; /* Destination physical address */
161*17169044Sbrutus 	size_t		cc_size;
162*17169044Sbrutus } dcopy_cmd_copy_t;
163*17169044Sbrutus 
164*17169044Sbrutus typedef union dcopy_cmd_u {
165*17169044Sbrutus 	dcopy_cmd_copy_t	copy;
166*17169044Sbrutus } dcopy_cmd_u_t;
167*17169044Sbrutus 
168*17169044Sbrutus typedef struct dcopy_cmd_priv_s *dcopy_cmd_priv_t;
169*17169044Sbrutus 
170*17169044Sbrutus struct dcopy_cmd_s {
171*17169044Sbrutus 	uint_t			dp_version; /* DCOPY_CMD_V0 */
172*17169044Sbrutus 	uint_t			dp_flags;
173*17169044Sbrutus 	uint64_t		dp_cmd;
174*17169044Sbrutus 	dcopy_cmd_u_t   	dp;
175*17169044Sbrutus 	uint32_t		dp_dca_id;
176*17169044Sbrutus 	dcopy_cmd_priv_t	dp_private;
177*17169044Sbrutus };
178*17169044Sbrutus typedef struct dcopy_cmd_s *dcopy_cmd_t;
179*17169044Sbrutus 
180*17169044Sbrutus 
181*17169044Sbrutus /*
182*17169044Sbrutus  * dcopy_cmd_alloc() specific flags
183*17169044Sbrutus  *   DCOPY_ALLOC_LINK - when set, the caller passes in a previously alloced
184*17169044Sbrutus  *     command in cmd. dcopy_cmd_alloc() will allocate a new command and
185*17169044Sbrutus  *     link it to the old command. The caller can use this to build a
186*17169044Sbrutus  *     chain of commands, keeping only the last cmd alloced. calling
187*17169044Sbrutus  *     dcopy_cmd_free() with the last cmd alloced in the chain will free all of
188*17169044Sbrutus  *     the commands in the chain. dcopy_cmd_post() and dcopy_cmd_poll() have
189*17169044Sbrutus  *     no knowledge of a chain of commands.  It's only used for alloc/free.
190*17169044Sbrutus  */
191*17169044Sbrutus #define	DCOPY_ALLOC_LINK	(1 << 16)
192*17169044Sbrutus 
193*17169044Sbrutus /*
194*17169044Sbrutus  * dcopy_cmd_alloc()
195*17169044Sbrutus  *   allocate a command. A command can be re-used after it completes.
196*17169044Sbrutus  *     flags - (DCOPY_SLEEP || DCOPY_NOSLEEP), DCOPY_ALLOC_LINK
197*17169044Sbrutus  *     returns => DCOPY_FAILURE, DCOPY_SUCCESS, DCOPY_NORESOURCES
198*17169044Sbrutus  */
199*17169044Sbrutus int dcopy_cmd_alloc(dcopy_handle_t handle, int flags, dcopy_cmd_t *cmd);
200*17169044Sbrutus 
201*17169044Sbrutus /*
202*17169044Sbrutus  * dcopy_cmd_free()
203*17169044Sbrutus  *   free the command. This call cannot be called after dcopy_free().
204*17169044Sbrutus  */
205*17169044Sbrutus void dcopy_cmd_free(dcopy_cmd_t *cmd);
206*17169044Sbrutus 
207*17169044Sbrutus /*
208*17169044Sbrutus  * dcopy_cmd_post()
209*17169044Sbrutus  *   post a command (allocated from dcopy_cmd_alloc()) to the DMA channel
210*17169044Sbrutus  *     returns => DCOPY_FAILURE, DCOPY_SUCCESS, DCOPY_NORESOURCES
211*17169044Sbrutus  */
212*17169044Sbrutus int dcopy_cmd_post(dcopy_cmd_t cmd);
213*17169044Sbrutus 
214*17169044Sbrutus /* dcopy_cmd_poll() flags */
215*17169044Sbrutus #define	DCOPY_POLL_NOFLAGS	(0)
216*17169044Sbrutus #define	DCOPY_POLL_BLOCK	(1 << 0)
217*17169044Sbrutus 
218*17169044Sbrutus /*
219*17169044Sbrutus  * dcopy_cmd_poll()
220*17169044Sbrutus  *   poll on completion status of a previous post. This call cannot be called
221*17169044Sbrutus  *   after dcopy_free().
222*17169044Sbrutus  *
223*17169044Sbrutus  *   if flags == DCOPY_POLL_NOFLAGS, return status can be DCOPY_FAILURE,
224*17169044Sbrutus  *   DCOPY_PENDING, or DCOPY_COMPLETED.
225*17169044Sbrutus  *
226*17169044Sbrutus  *   if flags & DCOPY_POLL_BLOCK, return status can be DCOPY_FAILURE or
227*17169044Sbrutus  *   DCOPY_COMPLETED. DCOPY_POLL_BLOCK can only be set in base context.
228*17169044Sbrutus  *
229*17169044Sbrutus  *   The command cannot be re-used or freed until the command has completed
230*17169044Sbrutus  *   (e.g. DCOPY_FAILURE or DCOPY_COMPLETED).
231*17169044Sbrutus  */
232*17169044Sbrutus int dcopy_cmd_poll(dcopy_cmd_t cmd, int flags);
233*17169044Sbrutus 
234*17169044Sbrutus 
235*17169044Sbrutus #ifdef __cplusplus
236*17169044Sbrutus }
237*17169044Sbrutus #endif
238*17169044Sbrutus 
239*17169044Sbrutus #endif /* _SYS_DCOPY_H */
240