summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/sys/1394/adapters/hci1394_async.h
blob: 6043d1c982458d5d37ae5761eb6ab79cd93281bd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#ifndef _SYS_1394_ADAPTERS_HCI1394_ASYNC_H
#define	_SYS_1394_ADAPTERS_HCI1394_ASYNC_H

#pragma ident	"%Z%%M%	%I%	%E% SMI"

/*
 * hci1394_async.h
 *   These routines the 1394 asynchronous dma engines.  These include incoming
 *   and outgoing reads, writes, and lock and their associated responses.
 */

#ifdef __cplusplus
extern "C" {
#endif

#include <sys/ddi.h>
#include <sys/modctl.h>
#include <sys/sunddi.h>
#include <sys/types.h>

#include <sys/1394/h1394.h>

#include <sys/1394/adapters/hci1394_def.h>
#include <sys/1394/adapters/hci1394_tlist.h>
#include <sys/1394/adapters/hci1394_q.h>


/*
 * Async descriptor and data buffer sizes. The AR descriptor buffers do not need
 * to be very big.  There will be 1 16 byte IM for every AR data buffer.  If we
 * alloc a 16KByte ARRESP data buffer on X86, we could get 4 4KByte cookies.
 * This would use up 64 bytes in the descriptor buffer. We will never need more
 * space than that.  A 256 byte descriptor should handle a 64K buffer on x86
 * if it is broken into 16 cookies.
 */
#define	ASYNC_ATREQ_DESC_SIZE		16384
#define	ASYNC_ATREQ_DATA_SIZE		16384
#define	ASYNC_ARRESP_DESC_SIZE		256
#define	ASYNC_ARRESP_DATA_SIZE		16384
#define	ASYNC_ARREQ_DESC_SIZE		256
#define	ASYNC_ARREQ_DATA_SIZE		16384
#define	ASYNC_ATRESP_DESC_SIZE		16384
#define	ASYNC_ATRESP_DATA_SIZE		16384


/* handle passed back from init() and used for rest of functions */
typedef struct hci1394_async_s	*hci1394_async_handle_t;

/*
 * Async Command State. This state is used to catch a race condition between
 * the ATREQ complete interrupt handler and the ARRESP interrupt handler. The
 * ATREQ will always complete before the ARRESP arrives, but SW may not see it
 * that way. See hci1394_async_atreq_process() for more information on this.
 */
typedef enum {
	HCI1394_CMD_STATE_IN_PROGRESS,
	HCI1394_CMD_STATE_PENDING,
	HCI1394_CMD_STATE_COMPLETED
} hci1394_async_cstate_t;


typedef struct hci1394_async_cmd_s {
	/* Pointer to framework command allocted by services layer */
	cmd1394_cmd_t 		*ac_cmd;

	/*
	 * Pointer to HAL/SL private area in the command. This is private info
	 * shared between the HAL and Services Layer on a per command basis.
	 */
	h1394_cmd_priv_t	*ac_priv;

	/*
	 * Status on if we allocated a tlabel for an ATREQ. Normally we will
	 * allocate a tlabel with every ATREQ. But, we will not allocate a
	 * tlabel for a PHY packet. When we initialize the command, we will
	 * assume that we are going to allocate a tlabel.  The async phy command
	 * will "override" this setting and set ac_tlabel_alloc to b_false.
	 */
	boolean_t		ac_tlabel_alloc;

	/* handle for tlabel logic */
	hci1394_tlabel_info_t	ac_tlabel;

	/*
	 * This is used for ARREQs. When we get a block read or write request,
	 * we allocate a mblk to put the data into. After the ATRESP has been
	 * sent out and has completed, hci1394_async_response_complete() is
	 * called to free up the ARREQ resources which were allocated. This
	 * routine will free the mblk if we allocated it in ARREQ. If an ARREQ
	 * block write is received and the target driver wishes to keep the
	 * mblk w/ the data (to pass it up a stream), but releases the command,
	 * it can set the mblk pointer in the command to null.  We will check
	 * for mblk being == to NULL even if ac_mblk_alloc is set to true.
	 */
	boolean_t		ac_mblk_alloc;

	/*
	 * ac_status contains the 1394 RESP for an ARRESP or the ACK for ARREQ.
	 * This status is set in either hci1394_async_arresp_read() or
	 * hci1394_arreq_read()
	 */
	int			ac_status;

	/*
	 * Destination packet was sent to. This is used to determine if the
	 * packet was broadcast or not in hci1394_async_arreq_read().
	 */
	uint_t			ac_dest;

	/*
	 * Async command state. See comments above for more information. Other
	 * than initialization, this field is only accessed in the ISR. State
	 * is only used in ATREQ/ARRESP processing.
	 */
	hci1394_async_cstate_t	ac_state;

	/*
	 * Pointer back to the Async private state. This allows us to access
	 * the async state structures if all we have is a pointer to the async
	 * command.
	 */
	struct hci1394_async_s	*ac_async;

	/*
	 * pending list node structure.  If a command is pended, this node is
	 * what's passed to the tlist code to add the node to the pending list.
	 * It contains all the pointers the linked list needs so that we do not
	 * need to allocate any space every time we add something to the list.
	 */
	hci1394_tlist_node_t	ac_plist_node;

	/*
	 * hci1394_q information about this command.  This is used for AT
	 * commands.  It contains information passed down to the hci1394_q_at*()
	 * routines like qc_timestamp which is used to tell the HW when an
	 * ATRESP has timed out out.  The status of the AT command is returned
	 * in qc_status after calling hci1394_q_at_next(). The rest of the
	 * structure members are private members used to track the descriptor
	 * and data buffer usage.
	 */
	hci1394_q_cmd_t		ac_qcmd;
} hci1394_async_cmd_t;

_NOTE(SCHEME_PROTECTS_DATA("Used only by one thread", hci1394_async_cmd_s \
	hci1394_async_cmd_s::ac_qcmd.qc_arg \
	hci1394_async_cmd_s::ac_qcmd.qc_generation \
	hci1394_async_cmd_s::ac_qcmd.qc_timestamp \
	hci1394_async_cmd_s::ac_tlabel_alloc \
	hci1394_async_cmd_s::ac_tlabel.tbi_destination \
	hci1394_async_cmd_s::ac_tlabel.tbi_tlabel))

/*
 * async private state information.  It contains handles for the various modules
 * that async uses.
 */
typedef struct hci1394_async_s {
	hci1394_tlist_handle_t	as_pending_list;
	hci1394_ohci_handle_t	as_ohci;
	hci1394_tlabel_handle_t	as_tlabel;
	hci1394_csr_handle_t	as_csr;
	hci1394_q_handle_t	as_atreq_q;
	hci1394_q_handle_t	as_arresp_q;
	hci1394_q_handle_t	as_arreq_q;
	hci1394_q_handle_t	as_atresp_q;
	hci1394_drvinfo_t	*as_drvinfo;

	/*
	 * as_flushing_arreq is used in bus reset processing. It is set by
	 * hci1394_async_arreq_flush() and tells hci1394_async_arreq_process()
	 * not to send the ARREQ up to the Services Layer. It will be set to
	 * FALSE by hci1394_async_arreq_read_phy() when a bus reset token with
	 * the current bus generation is found. as_phy_reset is used to store
	 * the last PHY packet generation seen in the ARREQ Q. The HW puts a
	 * token in the ARREQ Q so that the SW can flush the Q up to and
	 * including the token.
	 */
	boolean_t		as_flushing_arreq;
	uint_t			as_phy_reset;

	/*
	 * as_atomic_lookup is used to protect the cmd from a race condition
	 * between the ARRESP and the Pending Timeout callback. This is
	 * explained in more detail in hci1394_async_atreq_process().
	 */
	kmutex_t		as_atomic_lookup;
} hci1394_async_t;

_NOTE(SCHEME_PROTECTS_DATA("Used only by one thread", \
	hci1394_async_s::as_flushing_arreq hci1394_async_s::as_phy_reset))

int hci1394_async_init(hci1394_drvinfo_t *drvinfo,
    hci1394_ohci_handle_t ohci_handle, hci1394_csr_handle_t csr_handle,
    hci1394_async_handle_t *async_handle);
void hci1394_async_fini(hci1394_async_handle_t *async_handle);
void hci1394_async_suspend(hci1394_async_handle_t async_handle);
int hci1394_async_resume(hci1394_async_handle_t async_handle);
uint_t hci1394_async_cmd_overhead();

void hci1394_async_flush(hci1394_async_handle_t async_handle);
void hci1394_async_atreq_reset(hci1394_async_handle_t async_handle);
void hci1394_async_atresp_reset(hci1394_async_handle_t async_handle);
void hci1394_async_pending_timeout_update(hci1394_async_handle_t async_handle,
    hrtime_t timeout);

int hci1394_async_atreq_process(hci1394_async_handle_t async_handle,
    boolean_t flush_q, boolean_t *request_available);
int hci1394_async_arresp_process(hci1394_async_handle_t async_handle,
    boolean_t *response_available);
int hci1394_async_arreq_process(hci1394_async_handle_t async_handle,
    boolean_t *request_available);
int hci1394_async_atresp_process(hci1394_async_handle_t async_handle,
    boolean_t flush_q, boolean_t *response_available);

int hci1394_async_phy(hci1394_async_handle_t async_handle,
    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
int hci1394_async_write(hci1394_async_handle_t async_handle,
    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
int hci1394_async_read(hci1394_async_handle_t async_handle,
    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
int hci1394_async_lock(hci1394_async_handle_t async_handle,
    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
int hci1394_async_write_response(hci1394_async_handle_t async_handle,
    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
int hci1394_async_read_response(hci1394_async_handle_t async_handle,
    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
int hci1394_async_lock_response(hci1394_async_handle_t async_handle,
    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv, int *result);
void hci1394_async_response_complete(hci1394_async_handle_t async_handle,
    cmd1394_cmd_t *cmd, h1394_cmd_priv_t *cmd_priv);


#ifdef __cplusplus
}
#endif

#endif	/* _SYS_1394_ADAPTERS_HCI1394_ASYNC_H */