1*8e50dcc9Sbrutus /*
2*8e50dcc9Sbrutus  * CDDL HEADER START
3*8e50dcc9Sbrutus  *
4*8e50dcc9Sbrutus  * The contents of this file are subject to the terms of the
5*8e50dcc9Sbrutus  * Common Development and Distribution License (the "License").
6*8e50dcc9Sbrutus  * You may not use this file except in compliance with the License.
7*8e50dcc9Sbrutus  *
8*8e50dcc9Sbrutus  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*8e50dcc9Sbrutus  * or http://www.opensolaris.org/os/licensing.
10*8e50dcc9Sbrutus  * See the License for the specific language governing permissions
11*8e50dcc9Sbrutus  * and limitations under the License.
12*8e50dcc9Sbrutus  *
13*8e50dcc9Sbrutus  * When distributing Covered Code, include this CDDL HEADER in each
14*8e50dcc9Sbrutus  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*8e50dcc9Sbrutus  * If applicable, add the following below this CDDL HEADER, with the
16*8e50dcc9Sbrutus  * fields enclosed by brackets "[]" replaced with your own identifying
17*8e50dcc9Sbrutus  * information: Portions Copyright [yyyy] [name of copyright owner]
18*8e50dcc9Sbrutus  *
19*8e50dcc9Sbrutus  * CDDL HEADER END
20*8e50dcc9Sbrutus  */
21*8e50dcc9Sbrutus 
22*8e50dcc9Sbrutus /*
23*8e50dcc9Sbrutus  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*8e50dcc9Sbrutus  * Use is subject to license terms.
25*8e50dcc9Sbrutus  */
26*8e50dcc9Sbrutus 
27*8e50dcc9Sbrutus #ifndef _SYS_DCOPY_DEVICE_H
28*8e50dcc9Sbrutus #define	_SYS_DCOPY_DEVICE_H
29*8e50dcc9Sbrutus 
30*8e50dcc9Sbrutus #ifdef __cplusplus
31*8e50dcc9Sbrutus extern "C" {
32*8e50dcc9Sbrutus #endif
33*8e50dcc9Sbrutus 
34*8e50dcc9Sbrutus #include <sys/types.h>
35*8e50dcc9Sbrutus #include <sys/dcopy.h>
36*8e50dcc9Sbrutus 
37*8e50dcc9Sbrutus /*
38*8e50dcc9Sbrutus  * private command state. Space for this structure should be allocated during
39*8e50dcc9Sbrutus  * (*cb_cmd_alloc). The DMA driver must set dp_private in dcopy_cmd_t to point
40*8e50dcc9Sbrutus  * to the memory it allocated. Other than pr_device_cmd_private, the DMA driver
41*8e50dcc9Sbrutus  * should not touch any of the fields in this structure. pr_device_cmd_private
42*8e50dcc9Sbrutus  * is a private pointer for the DMA engine to use.
43*8e50dcc9Sbrutus  */
44*8e50dcc9Sbrutus struct dcopy_cmd_priv_s {
45*8e50dcc9Sbrutus 	/*
46*8e50dcc9Sbrutus 	 * we only init the state used to track a command which blocks when it
47*8e50dcc9Sbrutus 	 * actually blocks. pr_block_init tells us when we need to clean it
48*8e50dcc9Sbrutus 	 * up during a cmd_free.
49*8e50dcc9Sbrutus 	 */
50*8e50dcc9Sbrutus 	boolean_t		pr_block_init;
51*8e50dcc9Sbrutus 
52*8e50dcc9Sbrutus 	/* dcopy_poll blocking state */
53*8e50dcc9Sbrutus 	list_node_t		pr_poll_list_node;
54*8e50dcc9Sbrutus 	volatile boolean_t	pr_wait;
55*8e50dcc9Sbrutus 	kmutex_t		pr_mutex;
56*8e50dcc9Sbrutus 	kcondvar_t		pr_cv;
57*8e50dcc9Sbrutus 
58*8e50dcc9Sbrutus 	/* back pointer to the command */
59*8e50dcc9Sbrutus 	dcopy_cmd_t		pr_cmd;
60*8e50dcc9Sbrutus 
61*8e50dcc9Sbrutus 	/* shortcut to the channel we're on */
62*8e50dcc9Sbrutus 	struct dcopy_channel_s	*pr_channel;
63*8e50dcc9Sbrutus 
64*8e50dcc9Sbrutus 	/* DMA driver private pointer */
65*8e50dcc9Sbrutus 	void			*pr_device_cmd_private;
66*8e50dcc9Sbrutus };
67*8e50dcc9Sbrutus 
68*8e50dcc9Sbrutus /* cb_version */
69*8e50dcc9Sbrutus #define	DCOPY_DEVICECB_V0	0
70*8e50dcc9Sbrutus 
71*8e50dcc9Sbrutus typedef struct dcopy_device_chaninfo_s {
72*8e50dcc9Sbrutus 	uint_t	di_chan_num;
73*8e50dcc9Sbrutus } dcopy_device_chaninfo_t;
74*8e50dcc9Sbrutus 
75*8e50dcc9Sbrutus typedef struct dcopy_device_cb_s {
76*8e50dcc9Sbrutus 	int	cb_version;
77*8e50dcc9Sbrutus 	int	cb_res1;
78*8e50dcc9Sbrutus 
79*8e50dcc9Sbrutus 	/* allocate/free a DMA channel. See dcopy.h for return status  */
80*8e50dcc9Sbrutus 	int	(*cb_channel_alloc)(void *device_private,
81*8e50dcc9Sbrutus 		    dcopy_handle_t handle, int flags, uint_t size,
82*8e50dcc9Sbrutus 		    dcopy_query_channel_t *info, void *channel_private);
83*8e50dcc9Sbrutus 	void	(*cb_channel_free)(void *channel_private);
84*8e50dcc9Sbrutus 
85*8e50dcc9Sbrutus 	/* allocate/free a command. See dcopy.h for return status  */
86*8e50dcc9Sbrutus 	int	(*cb_cmd_alloc)(void *channel_private, int flags,
87*8e50dcc9Sbrutus 		    dcopy_cmd_t *cmd);
88*8e50dcc9Sbrutus 	void	(*cb_cmd_free)(void *channel_private, dcopy_cmd_t *cmd);
89*8e50dcc9Sbrutus 
90*8e50dcc9Sbrutus 	/*
91*8e50dcc9Sbrutus 	 * post a command/poll for command status. See dcopy.h for return
92*8e50dcc9Sbrutus 	 * status
93*8e50dcc9Sbrutus 	 */
94*8e50dcc9Sbrutus 	int	(*cb_cmd_post)(void *channel_private, dcopy_cmd_t cmd);
95*8e50dcc9Sbrutus 	int	(*cb_cmd_poll)(void *channel_private, dcopy_cmd_t cmd);
96*8e50dcc9Sbrutus 
97*8e50dcc9Sbrutus 	/*
98*8e50dcc9Sbrutus 	 * if dcopy_device_unregister() returns DCOPY_PENDING, dcopy will
99*8e50dcc9Sbrutus 	 * call this routine when all the channels are no longer being
100*8e50dcc9Sbrutus 	 * used and have been free'd up. e.g. it's safe for the DMA driver
101*8e50dcc9Sbrutus 	 * to detach.
102*8e50dcc9Sbrutus 	 *   status = DCOPY_SUCCESS || DCOPY_FAILURE
103*8e50dcc9Sbrutus 	 */
104*8e50dcc9Sbrutus 	void	(*cb_unregister_complete)(void *device_private, int status);
105*8e50dcc9Sbrutus } dcopy_device_cb_t;
106*8e50dcc9Sbrutus 
107*8e50dcc9Sbrutus 
108*8e50dcc9Sbrutus typedef struct dcopy_device_info_s {
109*8e50dcc9Sbrutus 	dev_info_t		*di_dip;
110*8e50dcc9Sbrutus 	dcopy_device_cb_t	*di_cb; /* must be a static array */
111*8e50dcc9Sbrutus 	uint_t			di_num_dma;
112*8e50dcc9Sbrutus 	uint_t			di_maxxfer;
113*8e50dcc9Sbrutus 	uint_t			di_capabilities;
114*8e50dcc9Sbrutus 	uint64_t		di_id;
115*8e50dcc9Sbrutus } dcopy_device_info_t;
116*8e50dcc9Sbrutus 
117*8e50dcc9Sbrutus typedef struct dcopy_device_s *dcopy_device_handle_t;
118*8e50dcc9Sbrutus 
119*8e50dcc9Sbrutus /* dcopy_device_notify() status */
120*8e50dcc9Sbrutus #define	DCOPY_COMPLETION	0
121*8e50dcc9Sbrutus 
122*8e50dcc9Sbrutus /*
123*8e50dcc9Sbrutus  * dcopy_device_register()
124*8e50dcc9Sbrutus  *   register the DMA device with dcopy.
125*8e50dcc9Sbrutus  *    return status => DCOPY_FAILURE, DCOPY_SUCCESS
126*8e50dcc9Sbrutus  */
127*8e50dcc9Sbrutus int dcopy_device_register(void *device_private, dcopy_device_info_t *info,
128*8e50dcc9Sbrutus     dcopy_device_handle_t *handle);
129*8e50dcc9Sbrutus 
130*8e50dcc9Sbrutus /*
131*8e50dcc9Sbrutus  * dcopy_device_unregister()
132*8e50dcc9Sbrutus  *   try to unregister the DMA device with dcopy. If the DMA engines are
133*8e50dcc9Sbrutus  *   still being used by upper layer modules, DCOPY_PENDING will be returned.
134*8e50dcc9Sbrutus  *    return status => DCOPY_FAILURE, DCOPY_SUCCESS, DCOPY_PENDING
135*8e50dcc9Sbrutus  *      if DCOPY_PENDING, (*cb_unregister_complete)() will be called when
136*8e50dcc9Sbrutus  *      completed.
137*8e50dcc9Sbrutus  */
138*8e50dcc9Sbrutus int dcopy_device_unregister(dcopy_device_handle_t *handle);
139*8e50dcc9Sbrutus 
140*8e50dcc9Sbrutus /*
141*8e50dcc9Sbrutus  * dcopy_device_channel_notify()
142*8e50dcc9Sbrutus  *   Notify dcopy of an event.
143*8e50dcc9Sbrutus  *     dcopy_handle_t handle => what was passed into (*cb_alloc)()
144*8e50dcc9Sbrutus  *     status => DCOPY_COMPLETION
145*8e50dcc9Sbrutus  */
146*8e50dcc9Sbrutus void dcopy_device_channel_notify(dcopy_handle_t handle, int status);
147*8e50dcc9Sbrutus 
148*8e50dcc9Sbrutus #ifdef __cplusplus
149*8e50dcc9Sbrutus }
150*8e50dcc9Sbrutus #endif
151*8e50dcc9Sbrutus 
152*8e50dcc9Sbrutus #endif /* _SYS_DCOPY_DEVICE_H */
153