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