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
39extern "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 */
73typedef 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 */
81typedef enum {
82	HCI1394_CMD_STATE_IN_PROGRESS,
83	HCI1394_CMD_STATE_PENDING,
84	HCI1394_CMD_STATE_COMPLETED
85} hci1394_async_cstate_t;
86
87
88typedef 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 */
182typedef 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
217int 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);
220void hci1394_async_fini(hci1394_async_handle_t *async_handle);
221void hci1394_async_suspend(hci1394_async_handle_t async_handle);
222int hci1394_async_resume(hci1394_async_handle_t async_handle);
223uint_t hci1394_async_cmd_overhead();
224
225void hci1394_async_flush(hci1394_async_handle_t async_handle);
226void hci1394_async_atreq_reset(hci1394_async_handle_t async_handle);
227void hci1394_async_atresp_reset(hci1394_async_handle_t async_handle);
228void hci1394_async_pending_timeout_update(hci1394_async_handle_t async_handle,
229    hrtime_t timeout);
230
231int hci1394_async_atreq_process(hci1394_async_handle_t async_handle,
232    boolean_t flush_q, boolean_t *request_available);
233int hci1394_async_arresp_process(hci1394_async_handle_t async_handle,
234    boolean_t *response_available);
235int hci1394_async_arreq_process(hci1394_async_handle_t async_handle,
236    boolean_t *request_available);
237int hci1394_async_atresp_process(hci1394_async_handle_t async_handle,
238    boolean_t flush_q, boolean_t *response_available);
239
240int hci1394_async_phy(hci1394_async_handle_t async_handle,
241    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
242int hci1394_async_write(hci1394_async_handle_t async_handle,
243    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
244int hci1394_async_read(hci1394_async_handle_t async_handle,
245    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
246int hci1394_async_lock(hci1394_async_handle_t async_handle,
247    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
248int hci1394_async_write_response(hci1394_async_handle_t async_handle,
249    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
250int hci1394_async_read_response(hci1394_async_handle_t async_handle,
251    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
252int hci1394_async_lock_response(hci1394_async_handle_t async_handle,
253    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
254void 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