1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate /*
30*0Sstevel@tonic-gate  * av1394 asynchronous module
31*0Sstevel@tonic-gate  */
32*0Sstevel@tonic-gate #include <sys/stat.h>
33*0Sstevel@tonic-gate #include <sys/file.h>
34*0Sstevel@tonic-gate #include <sys/ddi.h>
35*0Sstevel@tonic-gate #include <sys/sunddi.h>
36*0Sstevel@tonic-gate #include <sys/1394/targets/av1394/av1394_impl.h>
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate /* configuration routines */
39*0Sstevel@tonic-gate static void	av1394_async_cleanup(av1394_inst_t *, int);
40*0Sstevel@tonic-gate static int	av1394_async_create_minor_node(av1394_inst_t *);
41*0Sstevel@tonic-gate static void	av1394_async_remove_minor_node(av1394_inst_t *);
42*0Sstevel@tonic-gate static int	av1394_async_update_targetinfo(av1394_inst_t *);
43*0Sstevel@tonic-gate static int	av1394_async_db2arq_type(int);
44*0Sstevel@tonic-gate static void	av1394_async_putbq(av1394_queue_t *, mblk_t *);
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate static int	av1394_ioctl_arq_get_ibuf_size(av1394_inst_t *, void *, int);
47*0Sstevel@tonic-gate static int	av1394_ioctl_arq_set_ibuf_size(av1394_inst_t *, void *, int);
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate #define	AV1394_TNF_ENTER(func)	\
50*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(func##_enter, AV1394_TNF_ASYNC_STACK, "");
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate #define	AV1394_TNF_EXIT(func)	\
53*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(func##_exit, AV1394_TNF_ASYNC_STACK, "");
54*0Sstevel@tonic-gate 
55*0Sstevel@tonic-gate /* tunables */
56*0Sstevel@tonic-gate int av1394_ibuf_size_default = 64 * 1024;	/* default ibuf size */
57*0Sstevel@tonic-gate int av1394_ibuf_size_max = 1024 * 1024;		/* max ibuf size */
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate /*
60*0Sstevel@tonic-gate  *
61*0Sstevel@tonic-gate  * --- configuration entry points
62*0Sstevel@tonic-gate  *
63*0Sstevel@tonic-gate  */
64*0Sstevel@tonic-gate int
av1394_async_attach(av1394_inst_t * avp)65*0Sstevel@tonic-gate av1394_async_attach(av1394_inst_t *avp)
66*0Sstevel@tonic-gate {
67*0Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
68*0Sstevel@tonic-gate 	ddi_iblock_cookie_t ibc = avp->av_attachinfo.iblock_cookie;
69*0Sstevel@tonic-gate 
70*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_async_attach);
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate 	mutex_init(&ap->a_mutex, NULL, MUTEX_DRIVER, ibc);
73*0Sstevel@tonic-gate 	av1394_initq(&ap->a_rq, ibc, av1394_ibuf_size_default);
74*0Sstevel@tonic-gate 
75*0Sstevel@tonic-gate 	if (av1394_fcp_attach(avp) != DDI_SUCCESS) {
76*0Sstevel@tonic-gate 		av1394_async_cleanup(avp, 1);
77*0Sstevel@tonic-gate 		AV1394_TNF_EXIT(av1394_async_attach);
78*0Sstevel@tonic-gate 		return (DDI_FAILURE);
79*0Sstevel@tonic-gate 	}
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate 	if (av1394_cfgrom_init(avp) != DDI_SUCCESS) {
82*0Sstevel@tonic-gate 		av1394_async_cleanup(avp, 2);
83*0Sstevel@tonic-gate 		AV1394_TNF_EXIT(av1394_async_attach);
84*0Sstevel@tonic-gate 		return (DDI_FAILURE);
85*0Sstevel@tonic-gate 	}
86*0Sstevel@tonic-gate 
87*0Sstevel@tonic-gate 	if (av1394_async_create_minor_node(avp) != DDI_SUCCESS) {
88*0Sstevel@tonic-gate 		av1394_async_cleanup(avp, 3);
89*0Sstevel@tonic-gate 		AV1394_TNF_EXIT(av1394_async_attach);
90*0Sstevel@tonic-gate 		return (DDI_FAILURE);
91*0Sstevel@tonic-gate 	}
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate 	if (av1394_async_update_targetinfo(avp) != DDI_SUCCESS) {
94*0Sstevel@tonic-gate 		av1394_async_cleanup(avp, 4);
95*0Sstevel@tonic-gate 		AV1394_TNF_EXIT(av1394_async_attach);
96*0Sstevel@tonic-gate 		return (DDI_FAILURE);
97*0Sstevel@tonic-gate 	}
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_async_attach);
100*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
101*0Sstevel@tonic-gate }
102*0Sstevel@tonic-gate 
103*0Sstevel@tonic-gate void
av1394_async_detach(av1394_inst_t * avp)104*0Sstevel@tonic-gate av1394_async_detach(av1394_inst_t *avp)
105*0Sstevel@tonic-gate {
106*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_async_detach);
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 	av1394_async_cleanup(avp, AV1394_CLEANUP_LEVEL_MAX);
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_async_detach);
111*0Sstevel@tonic-gate }
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate void
av1394_async_bus_reset(av1394_inst_t * avp)114*0Sstevel@tonic-gate av1394_async_bus_reset(av1394_inst_t *avp)
115*0Sstevel@tonic-gate {
116*0Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
117*0Sstevel@tonic-gate 	mblk_t		*bp;
118*0Sstevel@tonic-gate 
119*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_async_bus_reset);
120*0Sstevel@tonic-gate 
121*0Sstevel@tonic-gate 	(void) av1394_async_update_targetinfo(avp);
122*0Sstevel@tonic-gate 
123*0Sstevel@tonic-gate 	mutex_enter(&ap->a_mutex);
124*0Sstevel@tonic-gate 	if (ap->a_nopen > 0) {
125*0Sstevel@tonic-gate 		mutex_exit(&ap->a_mutex);
126*0Sstevel@tonic-gate 		return;
127*0Sstevel@tonic-gate 	}
128*0Sstevel@tonic-gate 	mutex_exit(&ap->a_mutex);
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	/* queue up a bus reset message */
131*0Sstevel@tonic-gate 	if ((bp = allocb(1, BPRI_HI)) == NULL) {
132*0Sstevel@tonic-gate 		TNF_PROBE_0(av1394_async_bus_reset_error_allocb,
133*0Sstevel@tonic-gate 		    AV1394_TNF_ASYNC_ERROR, "");
134*0Sstevel@tonic-gate 	} else {
135*0Sstevel@tonic-gate 		DB_TYPE(bp) = AV1394_M_BUS_RESET;
136*0Sstevel@tonic-gate 		av1394_async_putq_rq(avp, bp);
137*0Sstevel@tonic-gate 	}
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_async_bus_reset);
140*0Sstevel@tonic-gate }
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate int
av1394_async_cpr_resume(av1394_inst_t * avp)143*0Sstevel@tonic-gate av1394_async_cpr_resume(av1394_inst_t *avp)
144*0Sstevel@tonic-gate {
145*0Sstevel@tonic-gate 	int	ret;
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_async_cpr_resume);
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate 	ret = av1394_async_update_targetinfo(avp);
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_async_cpr_resume);
152*0Sstevel@tonic-gate 	return (ret);
153*0Sstevel@tonic-gate }
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate void
av1394_async_reconnect(av1394_inst_t * avp)156*0Sstevel@tonic-gate av1394_async_reconnect(av1394_inst_t *avp)
157*0Sstevel@tonic-gate {
158*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_async_reconnect);
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 	(void) av1394_async_update_targetinfo(avp);
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_async_reconnect);
163*0Sstevel@tonic-gate }
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate int
av1394_async_open(av1394_inst_t * avp,int flag)166*0Sstevel@tonic-gate av1394_async_open(av1394_inst_t *avp, int flag)
167*0Sstevel@tonic-gate {
168*0Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
169*0Sstevel@tonic-gate 
170*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_async_open);
171*0Sstevel@tonic-gate 
172*0Sstevel@tonic-gate 	mutex_enter(&ap->a_mutex);
173*0Sstevel@tonic-gate 	if (ap->a_nopen == 0) {
174*0Sstevel@tonic-gate 		ap->a_pollevents = 0;
175*0Sstevel@tonic-gate 	}
176*0Sstevel@tonic-gate 	ap->a_nopen++;
177*0Sstevel@tonic-gate 	ap->a_oflag = flag;
178*0Sstevel@tonic-gate 	mutex_exit(&ap->a_mutex);
179*0Sstevel@tonic-gate 
180*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_async_open);
181*0Sstevel@tonic-gate 	return (0);
182*0Sstevel@tonic-gate }
183*0Sstevel@tonic-gate 
184*0Sstevel@tonic-gate /*ARGSUSED*/
185*0Sstevel@tonic-gate int
av1394_async_close(av1394_inst_t * avp,int flag)186*0Sstevel@tonic-gate av1394_async_close(av1394_inst_t *avp, int flag)
187*0Sstevel@tonic-gate {
188*0Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
189*0Sstevel@tonic-gate 
190*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_async_close);
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate 	av1394_cfgrom_close(avp);
193*0Sstevel@tonic-gate 
194*0Sstevel@tonic-gate 	av1394_flushq(&ap->a_rq);
195*0Sstevel@tonic-gate 
196*0Sstevel@tonic-gate 	mutex_enter(&ap->a_mutex);
197*0Sstevel@tonic-gate 	ap->a_nopen = 0;
198*0Sstevel@tonic-gate 	ap->a_pollevents = 0;
199*0Sstevel@tonic-gate 	mutex_exit(&ap->a_mutex);
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_async_close);
202*0Sstevel@tonic-gate 	return (0);
203*0Sstevel@tonic-gate }
204*0Sstevel@tonic-gate 
205*0Sstevel@tonic-gate int
av1394_async_read(av1394_inst_t * avp,struct uio * uiop)206*0Sstevel@tonic-gate av1394_async_read(av1394_inst_t *avp, struct uio *uiop)
207*0Sstevel@tonic-gate {
208*0Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
209*0Sstevel@tonic-gate 	av1394_queue_t	*q = &ap->a_rq;
210*0Sstevel@tonic-gate 	iec61883_arq_t	arq;
211*0Sstevel@tonic-gate 	int		ret = 0;
212*0Sstevel@tonic-gate 	mblk_t		*mp;
213*0Sstevel@tonic-gate 	int		dbtype;
214*0Sstevel@tonic-gate 	int		len;
215*0Sstevel@tonic-gate 
216*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_async_read);
217*0Sstevel@tonic-gate 
218*0Sstevel@tonic-gate 	/* copyout as much as we can */
219*0Sstevel@tonic-gate 	while ((uiop->uio_resid > 0) && (ret == 0)) {
220*0Sstevel@tonic-gate 		/*
221*0Sstevel@tonic-gate 		 * if data is available, copy it out. otherwise wait until
222*0Sstevel@tonic-gate 		 * data arrives, unless opened with non-blocking flag
223*0Sstevel@tonic-gate 		 */
224*0Sstevel@tonic-gate 		if ((mp = av1394_getq(q)) == NULL) {
225*0Sstevel@tonic-gate 			if (ap->a_oflag & FNDELAY) {
226*0Sstevel@tonic-gate 				AV1394_TNF_EXIT(av1394_async_read);
227*0Sstevel@tonic-gate 				return (EAGAIN);
228*0Sstevel@tonic-gate 			}
229*0Sstevel@tonic-gate 			if (av1394_qwait_sig(q) <= 0) {
230*0Sstevel@tonic-gate 				ret = EINTR;
231*0Sstevel@tonic-gate 			}
232*0Sstevel@tonic-gate 			continue;
233*0Sstevel@tonic-gate 		}
234*0Sstevel@tonic-gate 		dbtype = AV1394_DBTYPE(mp);
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate 		/* generate and copyout ARQ header, if not already */
237*0Sstevel@tonic-gate 		if (!AV1394_IS_NOHDR(mp)) {
238*0Sstevel@tonic-gate 			/* headers cannot be partially read */
239*0Sstevel@tonic-gate 			if (uiop->uio_resid < sizeof (arq)) {
240*0Sstevel@tonic-gate 				av1394_async_putbq(q, mp);
241*0Sstevel@tonic-gate 				ret = EINVAL;
242*0Sstevel@tonic-gate 				break;
243*0Sstevel@tonic-gate 			}
244*0Sstevel@tonic-gate 
245*0Sstevel@tonic-gate 			arq.arq_type = av1394_async_db2arq_type(dbtype);
246*0Sstevel@tonic-gate 			arq.arq_len = MBLKL(mp);
247*0Sstevel@tonic-gate 			arq.arq_data.octlet = 0;
248*0Sstevel@tonic-gate 
249*0Sstevel@tonic-gate 			/* copy ARQ-embedded data */
250*0Sstevel@tonic-gate 			len = min(arq.arq_len, sizeof (arq.arq_data));
251*0Sstevel@tonic-gate 			bcopy(mp->b_rptr, &arq.arq_data.buf[0], len);
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 			/* copyout the ARQ */
254*0Sstevel@tonic-gate 			ret = uiomove(&arq, sizeof (arq), UIO_READ, uiop);
255*0Sstevel@tonic-gate 			if (ret != 0) {
256*0Sstevel@tonic-gate 				av1394_async_putbq(q, mp);
257*0Sstevel@tonic-gate 				break;
258*0Sstevel@tonic-gate 			}
259*0Sstevel@tonic-gate 			mp->b_rptr += len;
260*0Sstevel@tonic-gate 			AV1394_MARK_NOHDR(mp);
261*0Sstevel@tonic-gate 		}
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 		/* any data left? */
264*0Sstevel@tonic-gate 		if (MBLKL(mp) == 0) {
265*0Sstevel@tonic-gate 			freemsg(mp);
266*0Sstevel@tonic-gate 			continue;
267*0Sstevel@tonic-gate 		}
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 		/* now we have some data and some user buffer space to fill */
270*0Sstevel@tonic-gate 		len = min(uiop->uio_resid, MBLKL(mp));
271*0Sstevel@tonic-gate 		if (len > 0) {
272*0Sstevel@tonic-gate 			ret = uiomove(mp->b_rptr, len, UIO_READ, uiop);
273*0Sstevel@tonic-gate 			if (ret != 0) {
274*0Sstevel@tonic-gate 				av1394_async_putbq(q, mp);
275*0Sstevel@tonic-gate 				break;
276*0Sstevel@tonic-gate 			}
277*0Sstevel@tonic-gate 			mp->b_rptr += len;
278*0Sstevel@tonic-gate 		}
279*0Sstevel@tonic-gate 
280*0Sstevel@tonic-gate 		/* save the rest of the data for later */
281*0Sstevel@tonic-gate 		if (MBLKL(mp) > 0) {
282*0Sstevel@tonic-gate 			av1394_async_putbq(q, mp);
283*0Sstevel@tonic-gate 		}
284*0Sstevel@tonic-gate 	}
285*0Sstevel@tonic-gate 
286*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_async_read);
287*0Sstevel@tonic-gate 	return (0);
288*0Sstevel@tonic-gate }
289*0Sstevel@tonic-gate 
290*0Sstevel@tonic-gate int
av1394_async_write(av1394_inst_t * avp,struct uio * uiop)291*0Sstevel@tonic-gate av1394_async_write(av1394_inst_t *avp, struct uio *uiop)
292*0Sstevel@tonic-gate {
293*0Sstevel@tonic-gate 	iec61883_arq_t	arq;
294*0Sstevel@tonic-gate 	int		ret;
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_async_write);
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate 	/* all data should arrive in ARQ format */
299*0Sstevel@tonic-gate 	while (uiop->uio_resid >= sizeof (arq)) {
300*0Sstevel@tonic-gate 		if ((ret = uiomove(&arq, sizeof (arq), UIO_WRITE, uiop)) != 0) {
301*0Sstevel@tonic-gate 			break;
302*0Sstevel@tonic-gate 		}
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate 		switch (arq.arq_type) {
305*0Sstevel@tonic-gate 		case IEC61883_ARQ_FCP_CMD:
306*0Sstevel@tonic-gate 		case IEC61883_ARQ_FCP_RESP:
307*0Sstevel@tonic-gate 			ret = av1394_fcp_write(avp, &arq, uiop);
308*0Sstevel@tonic-gate 			break;
309*0Sstevel@tonic-gate 		default:
310*0Sstevel@tonic-gate 			ret = EINVAL;
311*0Sstevel@tonic-gate 		}
312*0Sstevel@tonic-gate 		if (ret != 0) {
313*0Sstevel@tonic-gate 			break;
314*0Sstevel@tonic-gate 		}
315*0Sstevel@tonic-gate 	}
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_async_write);
318*0Sstevel@tonic-gate 	return (ret);
319*0Sstevel@tonic-gate }
320*0Sstevel@tonic-gate 
321*0Sstevel@tonic-gate /*ARGSUSED*/
322*0Sstevel@tonic-gate int
av1394_async_ioctl(av1394_inst_t * avp,int cmd,intptr_t arg,int mode,int * rvalp)323*0Sstevel@tonic-gate av1394_async_ioctl(av1394_inst_t *avp, int cmd, intptr_t arg, int mode,
324*0Sstevel@tonic-gate 		int *rvalp)
325*0Sstevel@tonic-gate {
326*0Sstevel@tonic-gate 	int	ret = EINVAL;
327*0Sstevel@tonic-gate 
328*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_async_ioctl);
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate 	switch (cmd) {
331*0Sstevel@tonic-gate 	case IEC61883_ARQ_GET_IBUF_SIZE:
332*0Sstevel@tonic-gate 		ret = av1394_ioctl_arq_get_ibuf_size(avp, (void *)arg, mode);
333*0Sstevel@tonic-gate 		break;
334*0Sstevel@tonic-gate 	case IEC61883_ARQ_SET_IBUF_SIZE:
335*0Sstevel@tonic-gate 		ret = av1394_ioctl_arq_set_ibuf_size(avp, (void *)arg, mode);
336*0Sstevel@tonic-gate 		break;
337*0Sstevel@tonic-gate 	case IEC61883_NODE_GET_BUS_NAME:
338*0Sstevel@tonic-gate 		ret = av1394_ioctl_node_get_bus_name(avp, (void *)arg, mode);
339*0Sstevel@tonic-gate 		break;
340*0Sstevel@tonic-gate 	case IEC61883_NODE_GET_UID:
341*0Sstevel@tonic-gate 		ret = av1394_ioctl_node_get_uid(avp, (void *)arg, mode);
342*0Sstevel@tonic-gate 		break;
343*0Sstevel@tonic-gate 	case IEC61883_NODE_GET_TEXT_LEAF:
344*0Sstevel@tonic-gate 		ret = av1394_ioctl_node_get_text_leaf(avp, (void *)arg, mode);
345*0Sstevel@tonic-gate 	}
346*0Sstevel@tonic-gate 
347*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_async_ioctl);
348*0Sstevel@tonic-gate 	return (ret);
349*0Sstevel@tonic-gate }
350*0Sstevel@tonic-gate 
351*0Sstevel@tonic-gate /*ARGSUSED*/
352*0Sstevel@tonic-gate int
av1394_async_poll(av1394_inst_t * avp,short events,int anyyet,short * reventsp,struct pollhead ** phpp)353*0Sstevel@tonic-gate av1394_async_poll(av1394_inst_t *avp, short events, int anyyet, short *reventsp,
354*0Sstevel@tonic-gate 		struct pollhead **phpp)
355*0Sstevel@tonic-gate {
356*0Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
357*0Sstevel@tonic-gate 	av1394_queue_t	*rq = &ap->a_rq;
358*0Sstevel@tonic-gate 
359*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_async_poll);
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 	if (events & POLLIN) {
362*0Sstevel@tonic-gate 		if (av1394_peekq(rq)) {
363*0Sstevel@tonic-gate 			*reventsp |= POLLIN;
364*0Sstevel@tonic-gate 		} else if (!anyyet) {
365*0Sstevel@tonic-gate 			mutex_enter(&ap->a_mutex);
366*0Sstevel@tonic-gate 			ap->a_pollevents |= POLLIN;
367*0Sstevel@tonic-gate 			*phpp = &ap->a_pollhead;
368*0Sstevel@tonic-gate 			mutex_exit(&ap->a_mutex);
369*0Sstevel@tonic-gate 		}
370*0Sstevel@tonic-gate 	}
371*0Sstevel@tonic-gate 
372*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_async_poll);
373*0Sstevel@tonic-gate 	return (0);
374*0Sstevel@tonic-gate }
375*0Sstevel@tonic-gate 
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate /*
378*0Sstevel@tonic-gate  * put a message on the read queue, take care of polling
379*0Sstevel@tonic-gate  */
380*0Sstevel@tonic-gate void
av1394_async_putq_rq(av1394_inst_t * avp,mblk_t * mp)381*0Sstevel@tonic-gate av1394_async_putq_rq(av1394_inst_t *avp, mblk_t *mp)
382*0Sstevel@tonic-gate {
383*0Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
384*0Sstevel@tonic-gate 
385*0Sstevel@tonic-gate 	if (!av1394_putq(&ap->a_rq, mp)) {
386*0Sstevel@tonic-gate 		freemsg(mp);
387*0Sstevel@tonic-gate 		TNF_PROBE_0(av1394_async_putq_rq_error_putq,
388*0Sstevel@tonic-gate 		    AV1394_TNF_ASYNC_ERROR, "");
389*0Sstevel@tonic-gate 	} else {
390*0Sstevel@tonic-gate 		mutex_enter(&ap->a_mutex);
391*0Sstevel@tonic-gate 		if (ap->a_pollevents & POLLIN) {
392*0Sstevel@tonic-gate 			ap->a_pollevents &= ~POLLIN;
393*0Sstevel@tonic-gate 			mutex_exit(&ap->a_mutex);
394*0Sstevel@tonic-gate 			pollwakeup(&ap->a_pollhead, POLLIN);
395*0Sstevel@tonic-gate 		} else {
396*0Sstevel@tonic-gate 			mutex_exit(&ap->a_mutex);
397*0Sstevel@tonic-gate 		}
398*0Sstevel@tonic-gate 	}
399*0Sstevel@tonic-gate }
400*0Sstevel@tonic-gate 
401*0Sstevel@tonic-gate /*
402*0Sstevel@tonic-gate  *
403*0Sstevel@tonic-gate  * --- configuration routines
404*0Sstevel@tonic-gate  *
405*0Sstevel@tonic-gate  * av1394_async_cleanup()
406*0Sstevel@tonic-gate  *    Cleanup after attach
407*0Sstevel@tonic-gate  */
408*0Sstevel@tonic-gate static void
av1394_async_cleanup(av1394_inst_t * avp,int level)409*0Sstevel@tonic-gate av1394_async_cleanup(av1394_inst_t *avp, int level)
410*0Sstevel@tonic-gate {
411*0Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
412*0Sstevel@tonic-gate 
413*0Sstevel@tonic-gate 	ASSERT((level > 0) && (level <= AV1394_CLEANUP_LEVEL_MAX));
414*0Sstevel@tonic-gate 
415*0Sstevel@tonic-gate 	switch (level) {
416*0Sstevel@tonic-gate 	default:
417*0Sstevel@tonic-gate 		av1394_async_remove_minor_node(avp);
418*0Sstevel@tonic-gate 		/* FALLTHRU */
419*0Sstevel@tonic-gate 	case 3:
420*0Sstevel@tonic-gate 		av1394_cfgrom_fini(avp);
421*0Sstevel@tonic-gate 		/* FALLTHRU */
422*0Sstevel@tonic-gate 	case 2:
423*0Sstevel@tonic-gate 		av1394_fcp_detach(avp);
424*0Sstevel@tonic-gate 		/* FALLTHRU */
425*0Sstevel@tonic-gate 	case 1:
426*0Sstevel@tonic-gate 		av1394_destroyq(&ap->a_rq);
427*0Sstevel@tonic-gate 		mutex_destroy(&ap->a_mutex);
428*0Sstevel@tonic-gate 	}
429*0Sstevel@tonic-gate }
430*0Sstevel@tonic-gate 
431*0Sstevel@tonic-gate /*
432*0Sstevel@tonic-gate  * av1394_async_create_minor_node()
433*0Sstevel@tonic-gate  *    Create async minor node
434*0Sstevel@tonic-gate  */
435*0Sstevel@tonic-gate static int
av1394_async_create_minor_node(av1394_inst_t * avp)436*0Sstevel@tonic-gate av1394_async_create_minor_node(av1394_inst_t *avp)
437*0Sstevel@tonic-gate {
438*0Sstevel@tonic-gate 	int	ret;
439*0Sstevel@tonic-gate 
440*0Sstevel@tonic-gate 	ret = ddi_create_minor_node(avp->av_dip, "async",
441*0Sstevel@tonic-gate 		S_IFCHR, AV1394_ASYNC_INST2MINOR(avp->av_instance),
442*0Sstevel@tonic-gate 		DDI_NT_AV_ASYNC, NULL);
443*0Sstevel@tonic-gate 	if (ret != DDI_SUCCESS) {
444*0Sstevel@tonic-gate 		TNF_PROBE_0(av1394_async_create_minor_node_error,
445*0Sstevel@tonic-gate 		    AV1394_TNF_ASYNC_ERROR, "");
446*0Sstevel@tonic-gate 	}
447*0Sstevel@tonic-gate 	return (ret);
448*0Sstevel@tonic-gate }
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate /*
451*0Sstevel@tonic-gate  * av1394_async_remove_minor_node()
452*0Sstevel@tonic-gate  *    Remove async minor node
453*0Sstevel@tonic-gate  */
454*0Sstevel@tonic-gate static void
av1394_async_remove_minor_node(av1394_inst_t * avp)455*0Sstevel@tonic-gate av1394_async_remove_minor_node(av1394_inst_t *avp)
456*0Sstevel@tonic-gate {
457*0Sstevel@tonic-gate 	ddi_remove_minor_node(avp->av_dip, "async");
458*0Sstevel@tonic-gate }
459*0Sstevel@tonic-gate 
460*0Sstevel@tonic-gate /*
461*0Sstevel@tonic-gate  * av1394_async_update_targetinfo()
462*0Sstevel@tonic-gate  *    Retrieve target info and bus generation
463*0Sstevel@tonic-gate  */
464*0Sstevel@tonic-gate static int
av1394_async_update_targetinfo(av1394_inst_t * avp)465*0Sstevel@tonic-gate av1394_async_update_targetinfo(av1394_inst_t *avp)
466*0Sstevel@tonic-gate {
467*0Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
468*0Sstevel@tonic-gate 	uint_t		bg;
469*0Sstevel@tonic-gate 	int		ret;
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 	mutex_enter(&avp->av_mutex);
472*0Sstevel@tonic-gate 	bg = avp->av_attachinfo.localinfo.bus_generation;
473*0Sstevel@tonic-gate 	mutex_exit(&avp->av_mutex);
474*0Sstevel@tonic-gate 
475*0Sstevel@tonic-gate 	mutex_enter(&ap->a_mutex);
476*0Sstevel@tonic-gate 	ret = t1394_get_targetinfo(avp->av_t1394_hdl, bg, 0, &ap->a_targetinfo);
477*0Sstevel@tonic-gate 	ap->a_bus_generation = bg;
478*0Sstevel@tonic-gate 	mutex_exit(&ap->a_mutex);
479*0Sstevel@tonic-gate 
480*0Sstevel@tonic-gate 	return (ret);
481*0Sstevel@tonic-gate }
482*0Sstevel@tonic-gate 
483*0Sstevel@tonic-gate static int
av1394_async_db2arq_type(int dbtype)484*0Sstevel@tonic-gate av1394_async_db2arq_type(int dbtype)
485*0Sstevel@tonic-gate {
486*0Sstevel@tonic-gate 	int	arq_type;
487*0Sstevel@tonic-gate 
488*0Sstevel@tonic-gate 	switch (dbtype) {
489*0Sstevel@tonic-gate 	case AV1394_M_FCP_RESP:
490*0Sstevel@tonic-gate 		arq_type = IEC61883_ARQ_FCP_RESP;
491*0Sstevel@tonic-gate 		break;
492*0Sstevel@tonic-gate 	case AV1394_M_FCP_CMD:
493*0Sstevel@tonic-gate 		arq_type = IEC61883_ARQ_FCP_CMD;
494*0Sstevel@tonic-gate 		break;
495*0Sstevel@tonic-gate 	case AV1394_M_BUS_RESET:
496*0Sstevel@tonic-gate 		arq_type = IEC61883_ARQ_BUS_RESET;
497*0Sstevel@tonic-gate 		break;
498*0Sstevel@tonic-gate 	default:
499*0Sstevel@tonic-gate 		ASSERT(0);	/* cannot happen */
500*0Sstevel@tonic-gate 	}
501*0Sstevel@tonic-gate 	return (arq_type);
502*0Sstevel@tonic-gate }
503*0Sstevel@tonic-gate 
504*0Sstevel@tonic-gate static void
av1394_async_putbq(av1394_queue_t * q,mblk_t * mp)505*0Sstevel@tonic-gate av1394_async_putbq(av1394_queue_t *q, mblk_t *mp)
506*0Sstevel@tonic-gate {
507*0Sstevel@tonic-gate 	if (!av1394_putbq(q, mp)) {
508*0Sstevel@tonic-gate 		freemsg(mp);
509*0Sstevel@tonic-gate 		TNF_PROBE_0(av1394_async_putbq_error,
510*0Sstevel@tonic-gate 		    AV1394_TNF_ASYNC_ERROR, "");
511*0Sstevel@tonic-gate 	}
512*0Sstevel@tonic-gate }
513*0Sstevel@tonic-gate 
514*0Sstevel@tonic-gate /*ARGSUSED*/
515*0Sstevel@tonic-gate static int
av1394_ioctl_arq_get_ibuf_size(av1394_inst_t * avp,void * arg,int mode)516*0Sstevel@tonic-gate av1394_ioctl_arq_get_ibuf_size(av1394_inst_t *avp, void *arg, int mode)
517*0Sstevel@tonic-gate {
518*0Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
519*0Sstevel@tonic-gate 	int		sz;
520*0Sstevel@tonic-gate 	int		ret = 0;
521*0Sstevel@tonic-gate 
522*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_ioctl_arq_get_ibuf_size);
523*0Sstevel@tonic-gate 
524*0Sstevel@tonic-gate 	sz = av1394_getmaxq(&ap->a_rq);
525*0Sstevel@tonic-gate 
526*0Sstevel@tonic-gate 	if (ddi_copyout(&sz, arg, sizeof (sz), mode) != 0) {
527*0Sstevel@tonic-gate 		ret = EFAULT;
528*0Sstevel@tonic-gate 	}
529*0Sstevel@tonic-gate 
530*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_ioctl_arq_get_ibuf_size);
531*0Sstevel@tonic-gate 	return (ret);
532*0Sstevel@tonic-gate }
533*0Sstevel@tonic-gate 
534*0Sstevel@tonic-gate /*ARGSUSED*/
535*0Sstevel@tonic-gate static int
av1394_ioctl_arq_set_ibuf_size(av1394_inst_t * avp,void * arg,int mode)536*0Sstevel@tonic-gate av1394_ioctl_arq_set_ibuf_size(av1394_inst_t *avp, void *arg, int mode)
537*0Sstevel@tonic-gate {
538*0Sstevel@tonic-gate 	av1394_async_t	*ap = &avp->av_a;
539*0Sstevel@tonic-gate 	int		sz;
540*0Sstevel@tonic-gate 	int		ret = 0;
541*0Sstevel@tonic-gate 
542*0Sstevel@tonic-gate 	AV1394_TNF_ENTER(av1394_ioctl_arq_set_ibuf_size);
543*0Sstevel@tonic-gate 
544*0Sstevel@tonic-gate 	sz = (int)(intptr_t)arg;
545*0Sstevel@tonic-gate 
546*0Sstevel@tonic-gate 	if ((sz < 0) || (sz > av1394_ibuf_size_max)) {
547*0Sstevel@tonic-gate 		ret = EINVAL;
548*0Sstevel@tonic-gate 	} else {
549*0Sstevel@tonic-gate 		av1394_setmaxq(&ap->a_rq, sz);
550*0Sstevel@tonic-gate 	}
551*0Sstevel@tonic-gate 
552*0Sstevel@tonic-gate 	AV1394_TNF_EXIT(av1394_ioctl_arq_set_ibuf_size);
553*0Sstevel@tonic-gate 	return (ret);
554*0Sstevel@tonic-gate }
555