xref: /illumos-gate/usr/src/uts/common/sys/1394/adapters/hci1394_async.h (revision 45ede40b2394db7967e59f19288fae9b62efd4aa)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #ifndef _SYS_1394_ADAPTERS_HCI1394_ASYNC_H
28 #define	_SYS_1394_ADAPTERS_HCI1394_ASYNC_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /*
33  * hci1394_async.h
34  *   These routines the 1394 asynchronous dma engines.  These include incoming
35  *   and outgoing reads, writes, and lock and their associated responses.
36  */
37 
38 #ifdef __cplusplus
39 extern "C" {
40 #endif
41 
42 #include <sys/ddi.h>
43 #include <sys/modctl.h>
44 #include <sys/sunddi.h>
45 #include <sys/types.h>
46 
47 #include <sys/1394/h1394.h>
48 
49 #include <sys/1394/adapters/hci1394_def.h>
50 #include <sys/1394/adapters/hci1394_tlist.h>
51 #include <sys/1394/adapters/hci1394_q.h>
52 
53 
54 /*
55  * Async descriptor and data buffer sizes. The AR descriptor buffers do not need
56  * to be very big.  There will be 1 16 byte IM for every AR data buffer.  If we
57  * alloc a 16KByte ARRESP data buffer on X86, we could get 4 4KByte cookies.
58  * This would use up 64 bytes in the descriptor buffer. We will never need more
59  * space than that.  A 256 byte descriptor should handle a 64K buffer on x86
60  * if it is broken into 16 cookies.
61  */
62 #define	ASYNC_ATREQ_DESC_SIZE		16384
63 #define	ASYNC_ATREQ_DATA_SIZE		16384
64 #define	ASYNC_ARRESP_DESC_SIZE		256
65 #define	ASYNC_ARRESP_DATA_SIZE		16384
66 #define	ASYNC_ARREQ_DESC_SIZE		256
67 #define	ASYNC_ARREQ_DATA_SIZE		16384
68 #define	ASYNC_ATRESP_DESC_SIZE		16384
69 #define	ASYNC_ATRESP_DATA_SIZE		16384
70 
71 
72 /* handle passed back from init() and used for rest of functions */
73 typedef struct hci1394_async_s	*hci1394_async_handle_t;
74 
75 /*
76  * Async Command State. This state is used to catch a race condition between
77  * the ATREQ complete interrupt handler and the ARRESP interrupt handler. The
78  * ATREQ will always complete before the ARRESP arrives, but SW may not see it
79  * that way. See hci1394_async_atreq_process() for more information on this.
80  */
81 typedef enum {
82 	HCI1394_CMD_STATE_IN_PROGRESS,
83 	HCI1394_CMD_STATE_PENDING,
84 	HCI1394_CMD_STATE_COMPLETED
85 } hci1394_async_cstate_t;
86 
87 
88 typedef struct hci1394_async_cmd_s {
89 	/* Pointer to framework command allocted by services layer */
90 	cmd1394_cmd_t 		*ac_cmd;
91 
92 	/*
93 	 * Pointer to HAL/SL private area in the command. This is private info
94 	 * shared between the HAL and Services Layer on a per command basis.
95 	 */
96 	h1394_cmd_priv_t	*ac_priv;
97 
98 	/*
99 	 * Status on if we allocated a tlabel for an ATREQ. Normally we will
100 	 * allocate a tlabel with every ATREQ. But, we will not allocate a
101 	 * tlabel for a PHY packet. When we initialize the command, we will
102 	 * assume that we are going to allocate a tlabel.  The async phy command
103 	 * will "override" this setting and set ac_tlabel_alloc to b_false.
104 	 */
105 	boolean_t		ac_tlabel_alloc;
106 
107 	/* handle for tlabel logic */
108 	hci1394_tlabel_info_t	ac_tlabel;
109 
110 	/*
111 	 * This is used for ARREQs. When we get a block read or write request,
112 	 * we allocate a mblk to put the data into. After the ATRESP has been
113 	 * sent out and has completed, hci1394_async_response_complete() is
114 	 * called to free up the ARREQ resources which were allocated. This
115 	 * routine will free the mblk if we allocated it in ARREQ. If an ARREQ
116 	 * block write is received and the target driver wishes to keep the
117 	 * mblk w/ the data (to pass it up a stream), but releases the command,
118 	 * it can set the mblk pointer in the command to null.  We will check
119 	 * for mblk being == to NULL even if ac_mblk_alloc is set to true.
120 	 */
121 	boolean_t		ac_mblk_alloc;
122 
123 	/*
124 	 * ac_status contains the 1394 RESP for an ARRESP or the ACK for ARREQ.
125 	 * This status is set in either hci1394_async_arresp_read() or
126 	 * hci1394_arreq_read()
127 	 */
128 	int			ac_status;
129 
130 	/*
131 	 * Destination packet was sent to. This is used to determine if the
132 	 * packet was broadcast or not in hci1394_async_arreq_read().
133 	 */
134 	uint_t			ac_dest;
135 
136 	/*
137 	 * Async command state. See comments above for more information. Other
138 	 * than initialization, this field is only accessed in the ISR. State
139 	 * is only used in ATREQ/ARRESP processing.
140 	 */
141 	hci1394_async_cstate_t	ac_state;
142 
143 	/*
144 	 * Pointer back to the Async private state. This allows us to access
145 	 * the async state structures if all we have is a pointer to the async
146 	 * command.
147 	 */
148 	struct hci1394_async_s	*ac_async;
149 
150 	/*
151 	 * pending list node structure.  If a command is pended, this node is
152 	 * what's passed to the tlist code to add the node to the pending list.
153 	 * It contains all the pointers the linked list needs so that we do not
154 	 * need to allocate any space every time we add something to the list.
155 	 */
156 	hci1394_tlist_node_t	ac_plist_node;
157 
158 	/*
159 	 * hci1394_q information about this command.  This is used for AT
160 	 * commands.  It contains information passed down to the hci1394_q_at*()
161 	 * routines like qc_timestamp which is used to tell the HW when an
162 	 * ATRESP has timed out out.  The status of the AT command is returned
163 	 * in qc_status after calling hci1394_q_at_next(). The rest of the
164 	 * structure members are private members used to track the descriptor
165 	 * and data buffer usage.
166 	 */
167 	hci1394_q_cmd_t		ac_qcmd;
168 } hci1394_async_cmd_t;
169 
170 _NOTE(SCHEME_PROTECTS_DATA("Used only by one thread", hci1394_async_cmd_s \
171 	hci1394_async_cmd_s::ac_qcmd.qc_arg \
172 	hci1394_async_cmd_s::ac_qcmd.qc_generation \
173 	hci1394_async_cmd_s::ac_qcmd.qc_timestamp \
174 	hci1394_async_cmd_s::ac_tlabel_alloc \
175 	hci1394_async_cmd_s::ac_tlabel.tbi_destination \
176 	hci1394_async_cmd_s::ac_tlabel.tbi_tlabel))
177 
178 /*
179  * async private state information.  It contains handles for the various modules
180  * that async uses.
181  */
182 typedef struct hci1394_async_s {
183 	hci1394_tlist_handle_t	as_pending_list;
184 	hci1394_ohci_handle_t	as_ohci;
185 	hci1394_tlabel_handle_t	as_tlabel;
186 	hci1394_csr_handle_t	as_csr;
187 	hci1394_q_handle_t	as_atreq_q;
188 	hci1394_q_handle_t	as_arresp_q;
189 	hci1394_q_handle_t	as_arreq_q;
190 	hci1394_q_handle_t	as_atresp_q;
191 	hci1394_drvinfo_t	*as_drvinfo;
192 
193 	/*
194 	 * as_flushing_arreq is used in bus reset processing. It is set by
195 	 * hci1394_async_arreq_flush() and tells hci1394_async_arreq_process()
196 	 * not to send the ARREQ up to the Services Layer. It will be set to
197 	 * FALSE by hci1394_async_arreq_read_phy() when a bus reset token with
198 	 * the current bus generation is found. as_phy_reset is used to store
199 	 * the last PHY packet generation seen in the ARREQ Q. The HW puts a
200 	 * token in the ARREQ Q so that the SW can flush the Q up to and
201 	 * including the token.
202 	 */
203 	boolean_t		as_flushing_arreq;
204 	uint_t			as_phy_reset;
205 
206 	/*
207 	 * as_atomic_lookup is used to protect the cmd from a race condition
208 	 * between the ARRESP and the Pending Timeout callback. This is
209 	 * explained in more detail in hci1394_async_atreq_process().
210 	 */
211 	kmutex_t		as_atomic_lookup;
212 } hci1394_async_t;
213 
214 _NOTE(SCHEME_PROTECTS_DATA("Used only by one thread", \
215 	hci1394_async_s::as_flushing_arreq hci1394_async_s::as_phy_reset))
216 
217 int hci1394_async_init(hci1394_drvinfo_t *drvinfo,
218     hci1394_ohci_handle_t ohci_handle, hci1394_csr_handle_t csr_handle,
219     hci1394_async_handle_t *async_handle);
220 void hci1394_async_fini(hci1394_async_handle_t *async_handle);
221 void hci1394_async_suspend(hci1394_async_handle_t async_handle);
222 int hci1394_async_resume(hci1394_async_handle_t async_handle);
223 uint_t hci1394_async_cmd_overhead();
224 
225 void hci1394_async_flush(hci1394_async_handle_t async_handle);
226 void hci1394_async_atreq_reset(hci1394_async_handle_t async_handle);
227 void hci1394_async_atresp_reset(hci1394_async_handle_t async_handle);
228 void hci1394_async_pending_timeout_update(hci1394_async_handle_t async_handle,
229     hrtime_t timeout);
230 
231 int hci1394_async_atreq_process(hci1394_async_handle_t async_handle,
232     boolean_t flush_q, boolean_t *request_available);
233 int hci1394_async_arresp_process(hci1394_async_handle_t async_handle,
234     boolean_t *response_available);
235 int hci1394_async_arreq_process(hci1394_async_handle_t async_handle,
236     boolean_t *request_available);
237 int hci1394_async_atresp_process(hci1394_async_handle_t async_handle,
238     boolean_t flush_q, boolean_t *response_available);
239 
240 int hci1394_async_phy(hci1394_async_handle_t async_handle,
241     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
242 int hci1394_async_write(hci1394_async_handle_t async_handle,
243     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
244 int hci1394_async_read(hci1394_async_handle_t async_handle,
245     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
246 int hci1394_async_lock(hci1394_async_handle_t async_handle,
247     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
248 int hci1394_async_write_response(hci1394_async_handle_t async_handle,
249     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
250 int hci1394_async_read_response(hci1394_async_handle_t async_handle,
251     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
252 int hci1394_async_lock_response(hci1394_async_handle_t async_handle,
253     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
254 void hci1394_async_response_complete(hci1394_async_handle_t async_handle,
255     cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv);
256 
257 
258 #ifdef __cplusplus
259 }
260 #endif
261 
262 #endif	/* _SYS_1394_ADAPTERS_HCI1394_ASYNC_H */
263