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 2002-2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _SYS_1394_TARGETS_AV1394_IMPL_H
28 #define	_SYS_1394_TARGETS_AV1394_IMPL_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /*
33  * av1394 driver definitions
34  */
35 
36 #include <sys/note.h>
37 #include <sys/ddi.h>
38 #include <sys/sunddi.h>
39 #include <sys/strsun.h>
40 #include <sys/mkdev.h>
41 #include <sys/tnf_probe.h>
42 #include <sys/av/iec61883.h>
43 #include <sys/1394/t1394.h>
44 #include <sys/1394/targets/av1394/av1394_isoch.h>
45 
46 #ifdef __cplusplus
47 extern "C" {
48 #endif
49 
50 /*
51  * double-linked list
52  */
53 typedef struct av1394_list_item_s {
54 	struct av1394_list_item_s	*i_next;
55 	struct av1394_list_item_s	*i_prev;
56 } av1394_list_item_t;
57 
58 typedef struct av1394_list_s {
59 	av1394_list_item_t	*l_head;	/* first item */
60 	av1394_list_item_t	*l_tail;	/* last item */
61 	int			l_cnt;		/* number of items */
62 } av1394_list_t;
63 
64 
65 /*
66  * queue
67  */
68 typedef struct av1394_queue_s {
69 	kmutex_t	q_mutex;	/* mutex */
70 	av1394_list_t	q_list;		/* list of mblk's */
71 	int		q_size;		/* current data size */
72 	int		q_max;		/* max data size */
73 	kcondvar_t	q_cv;		/* data cv */
74 } av1394_queue_t;
75 
76 _NOTE(MUTEX_PROTECTS_DATA(av1394_queue_s::q_mutex, av1394_queue_s))
77 
78 #define	AV1394_ENTERQ(q)	mutex_enter(&(q)->q_mutex)
79 #define	AV1394_LEAVEQ(q)	mutex_exit(&(q)->q_mutex)
80 
81 
82 /*
83  * asynchronous module definitions
84  *
85  *
86  * command structure
87  */
88 typedef struct av1394_fcp_cmd_s {
89 	cmd1394_cmd_t	*fc_cmd;	/* 1394 command */
90 	boolean_t	fc_busy;	/* command is in use */
91 	kcondvar_t	fc_busy_cv;	/* busy cv */
92 	boolean_t	fc_xmit;	/* transmit in progress */
93 	kcondvar_t	fc_xmit_cv;	/* transmit completion cv */
94 } av1394_fcp_cmd_t;
95 
96 /*
97  * per-instance FCP structure
98  */
99 typedef struct av1394_fcp_s {
100 	av1394_fcp_cmd_t	fcp_cmd;	/* outgoing FCP command */
101 	av1394_fcp_cmd_t	fcp_resp;	/* outgoing FCP response */
102 } av1394_fcp_t;
103 
104 enum {
105 	AV1394_FCP_ARQ_LEN_MAX	 = 0x200	/* maximum FCP ARQ length */
106 };
107 
108 
109 /*
110  * configuration ROM
111  */
112 #define	AV1394_CFGROM_INFO_LEN_ADDR	(IEEE1394_CONFIG_ROM_ADDR + 0x00)
113 #define	AV1394_CFGROM_BUS_NAME_ADDR	(IEEE1394_CONFIG_ROM_ADDR + 0x04)
114 #define	AV1394_CFGROM_EUI64_HI_ADDR	(IEEE1394_CONFIG_ROM_ADDR + 0x0c)
115 #define	AV1394_CFGROM_EUI64_LO_ADDR	(IEEE1394_CONFIG_ROM_ADDR + 0x10)
116 
117 /* offsets in quadlets */
118 #define	AV1394_CFGROM_BUS_NAME_OFF	1
119 #define	AV1394_CFGROM_EUI64_HI_OFF	3
120 #define	AV1394_CFGROM_EUI64_LO_OFF	4
121 
122 typedef struct av1394_cfgrom_text_leaf_s {
123 	uint64_t	tl_addr;	/* leaf entry address */
124 	uint32_t	tl_desc_entry;	/* entry described by this leaf */
125 } av1394_cfgrom_text_leaf_t;
126 
127 typedef struct av1394_cfgrom_parsed_dir_s {
128 	av1394_cfgrom_text_leaf_t *pd_tl;	/* text leaf array */
129 	int			pd_tl_size;	/* total # of array entries */
130 	int			pd_tl_next;	/* first unused entry index */
131 } av1394_cfgrom_parsed_dir_t;
132 
133 typedef struct av1394_cfgrom_parse_arg_s {
134 	int			pa_depth;	/* parser depth */
135 	uint32_t		pa_desc_entry;	/* described entry */
136 	uint8_t			pa_parent_k;	/* parent entry's key value */
137 	uint64_t		pa_addr;	/* directory address */
138 	uint16_t		pa_len;		/* directory length */
139 	av1394_cfgrom_parsed_dir_t *pa_dir;	/* current directory */
140 } av1394_cfgrom_parse_arg_t;
141 
142 enum {
143 	AV1394_CFGROM_PARSE_MAX_DEPTH	= 5	/* maximum parse depth */
144 };
145 
146 typedef struct av1394_cfgrom_s {
147 	krwlock_t		cr_rwlock;	/* structure lock */
148 	boolean_t		cr_parsed;	/* node ConfigROM was parsed */
149 	av1394_cfgrom_parsed_dir_t cr_root_dir;	/* root directory */
150 	av1394_cfgrom_parsed_dir_t cr_unit_dir;	/* unit directory */
151 } av1394_cfgrom_t;
152 
153 
154 /*
155  * async command
156  */
157 typedef struct av1394_async_cmd_s {
158 	kmutex_t	ac_mutex;
159 	boolean_t	ac_busy;
160 	kcondvar_t	ac_cv;
161 	cmd1394_cmd_t	*ac_cmd;
162 } av1394_async_cmd_t;
163 
164 /*
165  * per-instance soft state structure
166  */
167 typedef struct av1394_async_s {
168 	kmutex_t		a_mutex;	/* structure mutex */
169 	int			a_nopen;	/* number of opens */
170 	int			a_oflag;	/* open flags */
171 	t1394_targetinfo_t	a_targetinfo;	/* target info */
172 	uint_t			a_bus_generation; /* bus generation */
173 	av1394_fcp_t		a_fcp;		/* FCP module */
174 	av1394_cfgrom_t		a_cfgrom;	/* config ROM module */
175 	av1394_queue_t		a_rq;		/* read queue */
176 	struct pollhead		a_pollhead;	/* poll(2) support */
177 	short			a_pollevents;	/* polled events */
178 } av1394_async_t;
179 
180 _NOTE(MUTEX_PROTECTS_DATA(av1394_async_s::a_mutex, av1394_async_s))
181 _NOTE(DATA_READABLE_WITHOUT_LOCK(av1394_async_s::{
182 	a_oflag
183 }))
184 
185 
186 /* we use special message types for the read queue */
187 enum {
188 	AV1394_M_FCP_RESP	= 0x01,	/* FCP response */
189 	AV1394_M_FCP_CMD	= 0x02,	/* FCP command */
190 	AV1394_M_BUS_RESET	= 0x03,	/* bus reset event */
191 	/*
192 	 * For efficiency, we only store 1394 request data on the read queue.
193 	 * ARQ headers (iec61883_arq_t) are generated when an application
194 	 * calls read(2). Because applications may read header separately
195 	 * from the data, we need to mark each mblk when its header was read
196 	 * but not the data - the following flag is used for this purpose.
197 	 */
198 	AV1394_M_NOHDR		= 0x80
199 };
200 
201 #define	AV1394_DBTYPE(bp)	(DB_TYPE(bp) & ~AV1394_M_NOHDR)
202 #define	AV1394_MARK_NOHDR(bp)	(DB_TYPE(bp) |= AV1394_M_NOHDR)
203 #define	AV1394_IS_NOHDR(bp)	(DB_TYPE(bp) & AV1394_M_NOHDR)
204 
205 
206 /*
207  * device state:
208  *
209  *                     AV1394_DEV_DISCONNECTED
210  *                     |                |   ^
211  *                     |                |   |
212  *                  detach       reconnect disconnect
213  *                     |                |   |
214  *                     v                v   |
215  *       AV1394_DEV_INIT ----attach---> AV1394_DEV_ONLINE
216  *      (initial state)  <---detach---  |   ^
217  *                                      |   |
218  *                             cpr suspend cpr resume
219  *                                      |   |
220  *                                      v   |
221  *                        AV1394_DEV_SUSPENDED
222  */
223 typedef enum {
224 	AV1394_DEV_INIT		= 0,
225 	AV1394_DEV_ONLINE,
226 	AV1394_DEV_SUSPENDED,
227 	AV1394_DEV_DISCONNECTED
228 } av1394_dev_state_t;
229 
230 /*
231  * per-instance soft state structure
232  */
233 typedef struct av1394_inst_s {
234 	kmutex_t		av_mutex;	/* structure mutex */
235 	dev_info_t		*av_dip;	/* device information */
236 	int			av_instance;	/* instance number */
237 	av1394_dev_state_t	av_dev_state;	/* device state */
238 	av1394_dev_state_t	av_prev_dev_state; /* previous device state */
239 	t1394_attachinfo_t	av_attachinfo;	/* 1394 attach info */
240 	t1394_handle_t		av_t1394_hdl;	/* 1394 handle */
241 	av1394_async_t		av_a;		/* asynchronous module */
242 	av1394_isoch_t		av_i;		/* isochronous module */
243 	ddi_callback_id_t	av_reset_cb;	/* reset event cb id */
244 	ddi_callback_id_t	av_remove_cb; 	/* remove event cb id */
245 	ddi_callback_id_t	av_insert_cb;	/* insert event cb id */
246 } av1394_inst_t;
247 
248 _NOTE(MUTEX_PROTECTS_DATA(av1394_inst_s::av_mutex, av1394_inst_s::{
249 	av_dip
250 	av_instance
251 	av_attachinfo
252 	av_t1394_hdl
253 }))
254 /* these are set during attach (single-threaded) and don't change afterwards */
255 _NOTE(DATA_READABLE_WITHOUT_LOCK(av1394_inst_s::{
256 	av_dip
257 	av_instance
258 	av_attachinfo
259 	av_t1394_hdl
260 }))
261 
262 _NOTE(SCHEME_PROTECTS_DATA("one per call", msgb datab cmd1394_cmd
263 	iec61883_arq_t iec61883_isoch_init_t iec61883_plug_init_t))
264 
265 /*
266  * minor <-> instance mapping
267  */
268 #define	AV1394_MINOR_TYPE_MASK		(1 << (NBITSMINOR32 - 1))
269 #define	AV1394_ISOCH_INST2MINOR(inst)	(inst)
270 #define	AV1394_ASYNC_INST2MINOR(inst)	((inst) | AV1394_MINOR_TYPE_MASK)
271 #define	AV1394_DEV_IS_ISOCH(dev)	\
272 		((getminor(dev) & AV1394_MINOR_TYPE_MASK) == 0)
273 #define	AV1394_DEV_IS_ASYNC(dev)	\
274 		((getminor(dev) & AV1394_MINOR_TYPE_MASK) != 0)
275 #define	AV1394_DEV2INST(dev)		\
276 		((getminor(dev)) & ~AV1394_MINOR_TYPE_MASK)
277 
278 /* misc constants */
279 enum {
280 	AV1394_CLEANUP_LEVEL_MAX	= 256
281 };
282 
283 /* current interface version */
284 #define	AV1394_IEC61883_VER		IEC61883_V1_0
285 
286 /* TNF probes */
287 #define	AV1394_TNF_FCP			"1394 av1394 fcp "
288 #define	AV1394_TNF_FCP_STACK		"1394 av1394 fcp stacktrace "
289 #define	AV1394_TNF_FCP_ERROR		"1394 av1394 fcp error "
290 #define	AV1394_TNF_ASYNC		"1394 av1394 async "
291 #define	AV1394_TNF_ASYNC_STACK		"1394 av1394 async stacktrace "
292 #define	AV1394_TNF_ASYNC_ERROR		"1394 av1394 async error "
293 #define	AV1394_TNF_INST			"1394 av1394 inst "
294 #define	AV1394_TNF_INST_STACK		"1394 av1394 inst stacktrace "
295 #define	AV1394_TNF_INST_ERROR		"1394 av1394 inst error "
296 
297 /* misc */
298 #define	NELEM(a)	(sizeof (a) / sizeof (*(a)))
299 
300 
301 /* double-linked list */
302 void	av1394_list_init(av1394_list_t *lp);
303 void	*av1394_list_head(av1394_list_t *lp);
304 void	av1394_list_put_tail(av1394_list_t *lp, void *item);
305 void	av1394_list_put_head(av1394_list_t *lp, void *item);
306 void	*av1394_list_get_head(av1394_list_t *lp);
307 
308 /* queue */
309 void	av1394_initq(av1394_queue_t *q, ddi_iblock_cookie_t ibc, int max);
310 void	av1394_destroyq(av1394_queue_t *q);
311 void	av1394_setmaxq(av1394_queue_t *q, int max);
312 int	av1394_getmaxq(av1394_queue_t *q);
313 void	av1394_flushq(av1394_queue_t *q);
314 int	av1394_putq(av1394_queue_t *q, mblk_t *bp);
315 int	av1394_putbq(av1394_queue_t *q, mblk_t *bp);
316 mblk_t	*av1394_getq(av1394_queue_t *q);
317 mblk_t	*av1394_peekq(av1394_queue_t *q);
318 mblk_t	*av1394_peekq_locked(av1394_queue_t *q);
319 int	av1394_qwait_sig(av1394_queue_t *q);
320 
321 /* FCP */
322 int	av1394_fcp_attach(av1394_inst_t *);
323 void	av1394_fcp_detach(av1394_inst_t *);
324 int	av1394_fcp_open(av1394_inst_t *, int);
325 int	av1394_fcp_close(av1394_inst_t *, int);
326 int	av1394_fcp_write(av1394_inst_t *, iec61883_arq_t *, struct uio *);
327 
328 /* config ROM */
329 int	av1394_cfgrom_init(av1394_inst_t *);
330 void	av1394_cfgrom_fini(av1394_inst_t *);
331 void	av1394_cfgrom_close(av1394_inst_t *);
332 int	av1394_ioctl_node_get_bus_name(av1394_inst_t *, void *, int);
333 int	av1394_ioctl_node_get_uid(av1394_inst_t *, void *, int);
334 int	av1394_ioctl_node_get_text_leaf(av1394_inst_t *, void *, int);
335 
336 /* async module */
337 int	av1394_async_attach(av1394_inst_t *);
338 void	av1394_async_detach(av1394_inst_t *);
339 int	av1394_async_cpr_suspend(av1394_inst_t *);
340 int	av1394_async_cpr_resume(av1394_inst_t *);
341 void	av1394_async_bus_reset(av1394_inst_t *);
342 void	av1394_async_disconnect(av1394_inst_t *);
343 void	av1394_async_reconnect(av1394_inst_t *);
344 int	av1394_async_open(av1394_inst_t *, int);
345 int	av1394_async_close(av1394_inst_t *, int);
346 int	av1394_async_read(av1394_inst_t *, struct uio *);
347 int	av1394_async_write(av1394_inst_t *, struct uio *);
348 int	av1394_async_ioctl(av1394_inst_t *, int, intptr_t, int, int *);
349 int	av1394_async_poll(av1394_inst_t *, short, int, short *,
350 		struct pollhead **);
351 void	av1394_async_putq_rq(av1394_inst_t *, mblk_t *);
352 
353 #ifdef __cplusplus
354 }
355 #endif
356 
357 #endif /* _SYS_1394_TARGETS_AV1394_IMPL_H */
358