xref: /onnv-gate/usr/src/uts/common/io/1394/adapters/hci1394_isoch.c (revision 0:68f95e015346)
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 2001-2002 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  * hci1394_isoch.c
31*0Sstevel@tonic-gate  *    HCI HAL isochronous interface routines.  Contains routines used
32*0Sstevel@tonic-gate  *    internally within the HAL to manage isochronous contexts, and
33*0Sstevel@tonic-gate  *    also routines called from the Services Layer to manage an isochronous
34*0Sstevel@tonic-gate  *    DMA resource.
35*0Sstevel@tonic-gate  */
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #include <sys/types.h>
38*0Sstevel@tonic-gate #include <sys/kmem.h>
39*0Sstevel@tonic-gate #include <sys/conf.h>
40*0Sstevel@tonic-gate #include <sys/ddi.h>
41*0Sstevel@tonic-gate #include <sys/sunddi.h>
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate #include <sys/1394/h1394.h>
44*0Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h>
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate /*
47*0Sstevel@tonic-gate  * Patchable variable used to indicate the number of microseconds to wait
48*0Sstevel@tonic-gate  * for an isoch ctxt to stop ("active" goes low) after clearing the "run"
49*0Sstevel@tonic-gate  * bit
50*0Sstevel@tonic-gate  */
51*0Sstevel@tonic-gate uint_t hci1394_iso_ctxt_stop_delay_uS = 1000;
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate /*
54*0Sstevel@tonic-gate  * Number of microseconds to wait in hci1394_do_stop() for an isoch ctxt
55*0Sstevel@tonic-gate  * interrupt handler to complete. Experiments showed that in some cases
56*0Sstevel@tonic-gate  * the timeout needed was as long as 2 seconds. This is probably due to
57*0Sstevel@tonic-gate  * significant interrupt processing overhead for certain IXL chains.
58*0Sstevel@tonic-gate  */
59*0Sstevel@tonic-gate uint_t hci1394_iso_ctxt_stop_intr_timeout_uS = 5 * 1000000;
60*0Sstevel@tonic-gate 
61*0Sstevel@tonic-gate /*
62*0Sstevel@tonic-gate  * hci1394_isoch_init()
63*0Sstevel@tonic-gate  *    Initialize the isochronous dma soft state.
64*0Sstevel@tonic-gate  */
65*0Sstevel@tonic-gate void
hci1394_isoch_init(hci1394_drvinfo_t * drvinfo,hci1394_ohci_handle_t ohci,hci1394_isoch_handle_t * isoch_hdl)66*0Sstevel@tonic-gate hci1394_isoch_init(hci1394_drvinfo_t *drvinfo,  hci1394_ohci_handle_t ohci,
67*0Sstevel@tonic-gate     hci1394_isoch_handle_t *isoch_hdl)
68*0Sstevel@tonic-gate {
69*0Sstevel@tonic-gate 	hci1394_isoch_t *isochp;
70*0Sstevel@tonic-gate 	int i;
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate 	ASSERT(drvinfo != NULL);
73*0Sstevel@tonic-gate 	ASSERT(isoch_hdl != NULL);
74*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_isoch_init_enter, HCI1394_TNF_HAL_STACK_ISOCH,
75*0Sstevel@tonic-gate 	    "");
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate 	isochp = kmem_alloc(sizeof (hci1394_isoch_t), KM_SLEEP);
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate 	/* initialize contexts */
80*0Sstevel@tonic-gate 	for (i = 0; i < HCI1394_MAX_ISOCH_CONTEXTS; i++) {
81*0Sstevel@tonic-gate 		isochp->ctxt_xmit[i].ctxt_index = i;
82*0Sstevel@tonic-gate 
83*0Sstevel@tonic-gate 		/* init context flags to 0 */
84*0Sstevel@tonic-gate 		isochp->ctxt_xmit[i].ctxt_flags = 0;
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate 		mutex_init(&isochp->ctxt_xmit[i].intrprocmutex, NULL,
87*0Sstevel@tonic-gate 		    MUTEX_DRIVER, drvinfo->di_iblock_cookie);
88*0Sstevel@tonic-gate 		cv_init(&isochp->ctxt_xmit[i].intr_cv, NULL,
89*0Sstevel@tonic-gate 		    CV_DRIVER, NULL);
90*0Sstevel@tonic-gate 
91*0Sstevel@tonic-gate 		isochp->ctxt_recv[i].ctxt_index = i;
92*0Sstevel@tonic-gate 		isochp->ctxt_recv[i].ctxt_flags = HCI1394_ISO_CTXT_RECV;
93*0Sstevel@tonic-gate 		mutex_init(&isochp->ctxt_recv[i].intrprocmutex, NULL,
94*0Sstevel@tonic-gate 		    MUTEX_DRIVER, drvinfo->di_iblock_cookie);
95*0Sstevel@tonic-gate 		cv_init(&isochp->ctxt_recv[i].intr_cv, NULL,
96*0Sstevel@tonic-gate 		    CV_DRIVER, NULL);
97*0Sstevel@tonic-gate 	}
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate 	/* initialize the count for allocated isoch dma */
100*0Sstevel@tonic-gate 	isochp->isoch_dma_alloc_cnt = 0;
101*0Sstevel@tonic-gate 
102*0Sstevel@tonic-gate 	/* initialize the cycle_lost_thresh struct */
103*0Sstevel@tonic-gate 	isochp->cycle_lost_thresh.last_intr_time  = 0;
104*0Sstevel@tonic-gate 	isochp->cycle_lost_thresh.delta_t_counter = 0;
105*0Sstevel@tonic-gate 	isochp->cycle_lost_thresh.delta_t_thresh  = HCI1394_CYC_LOST_DELTA;
106*0Sstevel@tonic-gate 	isochp->cycle_lost_thresh.counter_thresh  = HCI1394_CYC_LOST_COUNT;
107*0Sstevel@tonic-gate 
108*0Sstevel@tonic-gate 	/* initialize the cycle_incon_thresh struct */
109*0Sstevel@tonic-gate 	isochp->cycle_incon_thresh.last_intr_time  = 0;
110*0Sstevel@tonic-gate 	isochp->cycle_incon_thresh.delta_t_counter = 0;
111*0Sstevel@tonic-gate 	isochp->cycle_incon_thresh.delta_t_thresh  = HCI1394_CYC_INCON_DELTA;
112*0Sstevel@tonic-gate 	isochp->cycle_incon_thresh.counter_thresh  = HCI1394_CYC_INCON_COUNT;
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate 	/* determine number of contexts supported */
115*0Sstevel@tonic-gate 	isochp->ctxt_xmit_count = hci1394_ohci_it_ctxt_count_get(ohci);
116*0Sstevel@tonic-gate 	isochp->ctxt_recv_count = hci1394_ohci_ir_ctxt_count_get(ohci);
117*0Sstevel@tonic-gate 
118*0Sstevel@tonic-gate 	/* the isochronous context mutex is used during some error interrupts */
119*0Sstevel@tonic-gate 	mutex_init(&isochp->ctxt_list_mutex, NULL, MUTEX_DRIVER,
120*0Sstevel@tonic-gate 	    drvinfo->di_iblock_cookie);
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	*isoch_hdl = isochp;
123*0Sstevel@tonic-gate 
124*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_isoch_init_exit, HCI1394_TNF_HAL_STACK_ISOCH,
125*0Sstevel@tonic-gate 	    "");
126*0Sstevel@tonic-gate }
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate /*
129*0Sstevel@tonic-gate  * hci1394_isoch_fini()
130*0Sstevel@tonic-gate  *    Cleanup after hci1394_isoch_init.  This should be called during detach.
131*0Sstevel@tonic-gate  */
132*0Sstevel@tonic-gate void
hci1394_isoch_fini(hci1394_isoch_handle_t * isoch_hdl)133*0Sstevel@tonic-gate hci1394_isoch_fini(hci1394_isoch_handle_t *isoch_hdl)
134*0Sstevel@tonic-gate {
135*0Sstevel@tonic-gate 	hci1394_isoch_t *isochp;
136*0Sstevel@tonic-gate 	int i;
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate 	ASSERT(isoch_hdl != NULL);
139*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_isoch_fini_enter, HCI1394_TNF_HAL_STACK_ISOCH,
140*0Sstevel@tonic-gate 	    "");
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	isochp = *isoch_hdl;
143*0Sstevel@tonic-gate 
144*0Sstevel@tonic-gate 	for (i = 0; i < HCI1394_MAX_ISOCH_CONTEXTS; i++) {
145*0Sstevel@tonic-gate 		mutex_destroy(&isochp->ctxt_xmit[i].intrprocmutex);
146*0Sstevel@tonic-gate 		mutex_destroy(&isochp->ctxt_recv[i].intrprocmutex);
147*0Sstevel@tonic-gate 		cv_destroy(&isochp->ctxt_xmit[i].intr_cv);
148*0Sstevel@tonic-gate 		cv_destroy(&isochp->ctxt_recv[i].intr_cv);
149*0Sstevel@tonic-gate 	}
150*0Sstevel@tonic-gate 
151*0Sstevel@tonic-gate 	mutex_destroy(&isochp->ctxt_list_mutex);
152*0Sstevel@tonic-gate 	kmem_free(isochp, sizeof (hci1394_isoch_t));
153*0Sstevel@tonic-gate 	*isoch_hdl = NULL;
154*0Sstevel@tonic-gate 
155*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_isoch_fini_exit, HCI1394_TNF_HAL_STACK_ISOCH,
156*0Sstevel@tonic-gate 	    "");
157*0Sstevel@tonic-gate }
158*0Sstevel@tonic-gate 
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate /*
161*0Sstevel@tonic-gate  * hci1394_isoch_resume()
162*0Sstevel@tonic-gate  *    There is currently nothing to do for resume.  This is a placeholder.
163*0Sstevel@tonic-gate  */
164*0Sstevel@tonic-gate /* ARGSUSED */
165*0Sstevel@tonic-gate int
hci1394_isoch_resume(hci1394_state_t * soft_state)166*0Sstevel@tonic-gate hci1394_isoch_resume(hci1394_state_t *soft_state)
167*0Sstevel@tonic-gate {
168*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_isoch_resume_enter,
169*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
170*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_isoch_resume_exit,
171*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
172*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
173*0Sstevel@tonic-gate }
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate /*
176*0Sstevel@tonic-gate  * hci1394_alloc_isoch_dma ()
177*0Sstevel@tonic-gate  *    Called by the Services Layer. Used to allocate a local Isoch DMA context.
178*0Sstevel@tonic-gate  *    Goes through appropriate context list (either transmit or receive)
179*0Sstevel@tonic-gate  *    looking for an unused context.  Fails if none found.
180*0Sstevel@tonic-gate  *    Then compiles the provided IXL program.
181*0Sstevel@tonic-gate  */
182*0Sstevel@tonic-gate int
hci1394_alloc_isoch_dma(void * hal_private,id1394_isoch_dmainfo_t * idi,void ** hal_idma_handlep,int * resultp)183*0Sstevel@tonic-gate hci1394_alloc_isoch_dma(void *hal_private, id1394_isoch_dmainfo_t *idi,
184*0Sstevel@tonic-gate     void **hal_idma_handlep, int *resultp)
185*0Sstevel@tonic-gate {
186*0Sstevel@tonic-gate 	int		    i;
187*0Sstevel@tonic-gate 	int		    err;
188*0Sstevel@tonic-gate 	hci1394_state_t	    *soft_statep = (hci1394_state_t *)hal_private;
189*0Sstevel@tonic-gate 	hci1394_isoch_t	    *isochp;
190*0Sstevel@tonic-gate 	hci1394_iso_ctxt_t  *ctxtp;
191*0Sstevel@tonic-gate 
192*0Sstevel@tonic-gate 
193*0Sstevel@tonic-gate 	ASSERT(soft_statep != NULL);
194*0Sstevel@tonic-gate 	ASSERT(hal_idma_handlep != NULL);
195*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_alloc_isoch_dma_enter,
196*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
197*0Sstevel@tonic-gate 
198*0Sstevel@tonic-gate 	isochp = soft_statep->isoch;
199*0Sstevel@tonic-gate 	*hal_idma_handlep = NULL;
200*0Sstevel@tonic-gate 
201*0Sstevel@tonic-gate 	/*
202*0Sstevel@tonic-gate 	 * find context to use based on whether talking(send) or listening(recv)
203*0Sstevel@tonic-gate 	 */
204*0Sstevel@tonic-gate 	mutex_enter(&isochp->ctxt_list_mutex);
205*0Sstevel@tonic-gate 	if ((idi->idma_options & ID1394_TALK) != 0) {
206*0Sstevel@tonic-gate 		/* TRANSMIT */
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate 		TNF_PROBE_1_DEBUG(hci1394_alloc_isoch_dma_transmit,
209*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_INFO_ISOCH, "", tnf_string, msg,
210*0Sstevel@tonic-gate 		    "Allocating isoch transmit context");
211*0Sstevel@tonic-gate 
212*0Sstevel@tonic-gate 		/*
213*0Sstevel@tonic-gate 		 * search through list of hardware supported contexts for
214*0Sstevel@tonic-gate 		 * one that's not inuse
215*0Sstevel@tonic-gate 		 */
216*0Sstevel@tonic-gate 		for (i = 0; i < isochp->ctxt_xmit_count; i++) {
217*0Sstevel@tonic-gate 			if ((isochp->ctxt_xmit[i].ctxt_flags &
218*0Sstevel@tonic-gate 			    HCI1394_ISO_CTXT_INUSE) == 0) {
219*0Sstevel@tonic-gate 				break;
220*0Sstevel@tonic-gate 			}
221*0Sstevel@tonic-gate 		}
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate 		/* if there aren't any left, return an error */
224*0Sstevel@tonic-gate 		if (i >= isochp->ctxt_xmit_count) {
225*0Sstevel@tonic-gate 			TNF_PROBE_1(hci1394_alloc_isoch_dma_xmit_rsrc_error,
226*0Sstevel@tonic-gate 			    HCI1394_TNF_HAL_ERROR_ISOCH, "", tnf_string, errmsg,
227*0Sstevel@tonic-gate 			    "Out of isoch transmit resources");
228*0Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(hci1394_alloc_isoch_dma_exit,
229*0Sstevel@tonic-gate 			    HCI1394_TNF_HAL_STACK_ISOCH, "");
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate 			mutex_exit(&isochp->ctxt_list_mutex);
232*0Sstevel@tonic-gate 			*resultp = IXL1394_ENO_DMA_RESRCS;
233*0Sstevel@tonic-gate 			return (DDI_FAILURE);
234*0Sstevel@tonic-gate 		}
235*0Sstevel@tonic-gate 
236*0Sstevel@tonic-gate 		TNF_PROBE_1_DEBUG(t1394_alloc_isoch_dma_it_ctxtnum,
237*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_INFO_ISOCH, "", tnf_int, it_ctxt_num, i);
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 		/* mark inuse and set up handle to context */
240*0Sstevel@tonic-gate 		isochp->ctxt_xmit[i].ctxt_flags |= HCI1394_ISO_CTXT_INUSE;
241*0Sstevel@tonic-gate 		ctxtp = &isochp->ctxt_xmit[i];
242*0Sstevel@tonic-gate 		isochp->ctxt_xmit[i].ctxt_regsp =
243*0Sstevel@tonic-gate 		    &soft_statep->ohci->ohci_regs->it[i];
244*0Sstevel@tonic-gate 	} else {
245*0Sstevel@tonic-gate 		/* RECEIVE */
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 		TNF_PROBE_1_DEBUG(hci1394_alloc_isoch_dma_receive,
248*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_INFO_ISOCH, "", tnf_string, msg,
249*0Sstevel@tonic-gate 		    "Allocating isoch receive context");
250*0Sstevel@tonic-gate 
251*0Sstevel@tonic-gate 		/* search thru implemented contexts for one that's available */
252*0Sstevel@tonic-gate 		for (i = 0; i < isochp->ctxt_recv_count; i++) {
253*0Sstevel@tonic-gate 			if ((isochp->ctxt_recv[i].ctxt_flags &
254*0Sstevel@tonic-gate 			    HCI1394_ISO_CTXT_INUSE) == 0) {
255*0Sstevel@tonic-gate 				break;
256*0Sstevel@tonic-gate 			}
257*0Sstevel@tonic-gate 		}
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 		/* if there aren't any left, return an error */
260*0Sstevel@tonic-gate 		/* XXX support for multi-chan could go here */
261*0Sstevel@tonic-gate 		if (i >= isochp->ctxt_recv_count) {
262*0Sstevel@tonic-gate 
263*0Sstevel@tonic-gate 			TNF_PROBE_1(t1394_alloc_isoch_dma_ir_rsrc_error,
264*0Sstevel@tonic-gate 			    HCI1394_TNF_HAL_ERROR_ISOCH, "", tnf_string, errmsg,
265*0Sstevel@tonic-gate 			    "Out of isoch receive resources");
266*0Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(hci1394_alloc_isoch_dma_exit,
267*0Sstevel@tonic-gate 			    HCI1394_TNF_HAL_STACK_ISOCH, "");
268*0Sstevel@tonic-gate 
269*0Sstevel@tonic-gate 			mutex_exit(&isochp->ctxt_list_mutex);
270*0Sstevel@tonic-gate 			*resultp = IXL1394_ENO_DMA_RESRCS;
271*0Sstevel@tonic-gate 			return (DDI_FAILURE);
272*0Sstevel@tonic-gate 		}
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 		/* set up receive mode flags */
275*0Sstevel@tonic-gate 		if ((idi->idma_options & ID1394_LISTEN_BUF_MODE) != 0) {
276*0Sstevel@tonic-gate 			isochp->ctxt_recv[i].ctxt_flags |=
277*0Sstevel@tonic-gate 			    HCI1394_ISO_CTXT_BFFILL;
278*0Sstevel@tonic-gate 		}
279*0Sstevel@tonic-gate 		if ((idi->idma_options & ID1394_RECV_HEADERS) != 0) {
280*0Sstevel@tonic-gate 			isochp->ctxt_recv[i].ctxt_flags |=
281*0Sstevel@tonic-gate 			    HCI1394_ISO_CTXT_RHDRS;
282*0Sstevel@tonic-gate 		}
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 		TNF_PROBE_1_DEBUG(hci1394_alloc_isoch_dma_recv_ctxtnum,
285*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_INFO_ISOCH, "", tnf_int, recv_ctxt_num, i);
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate 		/* mark inuse and set up handle to context */
288*0Sstevel@tonic-gate 		isochp->ctxt_recv[i].ctxt_flags |= HCI1394_ISO_CTXT_INUSE;
289*0Sstevel@tonic-gate 		ctxtp = &isochp->ctxt_recv[i];
290*0Sstevel@tonic-gate 
291*0Sstevel@tonic-gate 		isochp->ctxt_recv[i].ctxt_regsp = (hci1394_ctxt_regs_t *)
292*0Sstevel@tonic-gate 		    &soft_statep->ohci->ohci_regs->ir[i];
293*0Sstevel@tonic-gate 	}
294*0Sstevel@tonic-gate 	mutex_exit(&isochp->ctxt_list_mutex);
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 	/* before compiling, set up some default context values */
297*0Sstevel@tonic-gate 	ctxtp->isochan = idi->channel_num;
298*0Sstevel@tonic-gate 	ctxtp->default_tag = idi->default_tag;
299*0Sstevel@tonic-gate 	ctxtp->default_sync = idi->default_sync;
300*0Sstevel@tonic-gate 	ctxtp->global_callback_arg = idi->global_callback_arg;
301*0Sstevel@tonic-gate 	ctxtp->isoch_dma_stopped = idi->isoch_dma_stopped;
302*0Sstevel@tonic-gate 	ctxtp->idma_evt_arg = idi->idma_evt_arg;
303*0Sstevel@tonic-gate 	ctxtp->isospd = idi->it_speed;
304*0Sstevel@tonic-gate 	ctxtp->default_skipmode = idi->it_default_skip;
305*0Sstevel@tonic-gate 	ctxtp->default_skiplabelp = idi->it_default_skiplabel;
306*0Sstevel@tonic-gate 
307*0Sstevel@tonic-gate 	err = hci1394_compile_ixl(soft_statep, ctxtp, idi->ixlp, resultp);
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate 
310*0Sstevel@tonic-gate 	/*
311*0Sstevel@tonic-gate 	 * if the compile failed, clear the appropriate flags.
312*0Sstevel@tonic-gate 	 * Note that the context mutex is needed to eliminate race condition
313*0Sstevel@tonic-gate 	 * with cycle_inconsistent and other error intrs.
314*0Sstevel@tonic-gate 	 */
315*0Sstevel@tonic-gate 	if (err != DDI_SUCCESS) {
316*0Sstevel@tonic-gate 
317*0Sstevel@tonic-gate 		mutex_enter(&isochp->ctxt_list_mutex);
318*0Sstevel@tonic-gate 		if ((ctxtp->ctxt_flags & HCI1394_ISO_CTXT_RECV) != 0) {
319*0Sstevel@tonic-gate 			/* undo the set up of receive mode flags */
320*0Sstevel@tonic-gate 			isochp->ctxt_recv[i].ctxt_flags &=
321*0Sstevel@tonic-gate 			    ~HCI1394_ISO_CTXT_BFFILL;
322*0Sstevel@tonic-gate 			isochp->ctxt_recv[i].ctxt_flags &=
323*0Sstevel@tonic-gate 			    ~HCI1394_ISO_CTXT_RHDRS;
324*0Sstevel@tonic-gate 		}
325*0Sstevel@tonic-gate 		ctxtp->ctxt_flags &= ~HCI1394_ISO_CTXT_INUSE;
326*0Sstevel@tonic-gate 		mutex_exit(&isochp->ctxt_list_mutex);
327*0Sstevel@tonic-gate 
328*0Sstevel@tonic-gate 		TNF_PROBE_2(t1394_alloc_isoch_dma_compile_fail,
329*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_ERROR_ISOCH, "", tnf_string, errmsg,
330*0Sstevel@tonic-gate 		    "IXL compilation error", tnf_int, ixl_error, *resultp);
331*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_alloc_isoch_dma_exit,
332*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK_ISOCH, "");
333*0Sstevel@tonic-gate 		return (DDI_FAILURE);
334*0Sstevel@tonic-gate 	}
335*0Sstevel@tonic-gate 
336*0Sstevel@tonic-gate 	/*
337*0Sstevel@tonic-gate 	 * Update count of allocated isoch dma (and enable interrupts
338*0Sstevel@tonic-gate 	 * if necessary)
339*0Sstevel@tonic-gate 	 */
340*0Sstevel@tonic-gate 	mutex_enter(&isochp->ctxt_list_mutex);
341*0Sstevel@tonic-gate 	if (isochp->isoch_dma_alloc_cnt == 0) {
342*0Sstevel@tonic-gate 		hci1394_ohci_intr_clear(soft_statep->ohci,
343*0Sstevel@tonic-gate 		    OHCI_INTR_CYC_LOST | OHCI_INTR_CYC_INCONSISTENT);
344*0Sstevel@tonic-gate 		hci1394_ohci_intr_enable(soft_statep->ohci,
345*0Sstevel@tonic-gate 		    OHCI_INTR_CYC_LOST | OHCI_INTR_CYC_INCONSISTENT);
346*0Sstevel@tonic-gate 	}
347*0Sstevel@tonic-gate 	isochp->isoch_dma_alloc_cnt++;
348*0Sstevel@tonic-gate 	mutex_exit(&isochp->ctxt_list_mutex);
349*0Sstevel@tonic-gate 
350*0Sstevel@tonic-gate 	/* No errors, so all set to go.  initialize interrupt/execution flags */
351*0Sstevel@tonic-gate 	ctxtp->intr_flags = 0;
352*0Sstevel@tonic-gate 
353*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_alloc_isoch_dma_exit,
354*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
355*0Sstevel@tonic-gate 
356*0Sstevel@tonic-gate 	*hal_idma_handlep = ctxtp;
357*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
358*0Sstevel@tonic-gate }
359*0Sstevel@tonic-gate 
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate /*
362*0Sstevel@tonic-gate  * hci1394_start_isoch_dma()
363*0Sstevel@tonic-gate  *    Used to start an allocated isochronous dma resource.
364*0Sstevel@tonic-gate  *    Sets the context's command ptr to start at the first IXL,
365*0Sstevel@tonic-gate  *    sets up IR match register (if IR), and enables the context_control
366*0Sstevel@tonic-gate  *    register RUN bit.
367*0Sstevel@tonic-gate  */
368*0Sstevel@tonic-gate /* ARGSUSED */
369*0Sstevel@tonic-gate int
hci1394_start_isoch_dma(void * hal_private,void * hal_isoch_dma_handle,id1394_isoch_dma_ctrlinfo_t * idma_ctrlinfop,uint_t flags,int * result)370*0Sstevel@tonic-gate hci1394_start_isoch_dma(void *hal_private, void *hal_isoch_dma_handle,
371*0Sstevel@tonic-gate     id1394_isoch_dma_ctrlinfo_t *idma_ctrlinfop, uint_t flags, int *result)
372*0Sstevel@tonic-gate {
373*0Sstevel@tonic-gate 	hci1394_state_t	    *soft_statep = (hci1394_state_t *)hal_private;
374*0Sstevel@tonic-gate 	hci1394_iso_ctxt_t  *ctxtp;
375*0Sstevel@tonic-gate 	int		    tag0, tag1, tag2, tag3;
376*0Sstevel@tonic-gate 
377*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_start_isoch_dma_enter,
378*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
379*0Sstevel@tonic-gate 
380*0Sstevel@tonic-gate 	/* pick up the context pointer from the private idma data */
381*0Sstevel@tonic-gate 	ctxtp = (hci1394_iso_ctxt_t *)hal_isoch_dma_handle;
382*0Sstevel@tonic-gate 
383*0Sstevel@tonic-gate 	ASSERT(hal_private != NULL);
384*0Sstevel@tonic-gate 	ASSERT(ctxtp != NULL);
385*0Sstevel@tonic-gate 	ASSERT(idma_ctrlinfop != NULL);
386*0Sstevel@tonic-gate 	TNF_PROBE_4_DEBUG(hci1394_start_isoch_dma_ctxt_info,
387*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_INFO_ISOCH, "", tnf_opaque, ctxt_ptr, ctxtp,
388*0Sstevel@tonic-gate 	    tnf_int, ctxt_index, ctxtp->ctxt_index, tnf_opaque, ctxt_flags,
389*0Sstevel@tonic-gate 	    ctxtp->ctxt_flags, tnf_opaque, first_ixl, ctxtp->ixl_firstp);
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 
392*0Sstevel@tonic-gate 	/* if the context is already running, just exit.  else set running */
393*0Sstevel@tonic-gate 	mutex_enter(&soft_statep->isoch->ctxt_list_mutex);
394*0Sstevel@tonic-gate 	if ((ctxtp->ctxt_flags & HCI1394_ISO_CTXT_RUNNING) != 0) {
395*0Sstevel@tonic-gate 
396*0Sstevel@tonic-gate 		mutex_exit(&soft_statep->isoch->ctxt_list_mutex);
397*0Sstevel@tonic-gate 
398*0Sstevel@tonic-gate 		TNF_PROBE_1_DEBUG(hci1394_start_isoch_dma_exit,
399*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK_ISOCH, "", tnf_string, msg,
400*0Sstevel@tonic-gate 		    "context already running");
401*0Sstevel@tonic-gate 		return (DDI_SUCCESS);
402*0Sstevel@tonic-gate 	}
403*0Sstevel@tonic-gate 	ctxtp->ctxt_flags |= HCI1394_ISO_CTXT_RUNNING;
404*0Sstevel@tonic-gate 	mutex_exit(&soft_statep->isoch->ctxt_list_mutex);
405*0Sstevel@tonic-gate 
406*0Sstevel@tonic-gate 	ctxtp->intr_flags &= ~HCI1394_ISO_CTXT_STOP;
407*0Sstevel@tonic-gate 
408*0Sstevel@tonic-gate 	/* initialize context values */
409*0Sstevel@tonic-gate 	ctxtp->ixl_execp = ctxtp->ixl_firstp;	/* start of ixl chain */
410*0Sstevel@tonic-gate 	ctxtp->ixl_exec_depth = 0;
411*0Sstevel@tonic-gate 	ctxtp->dma_last_time = 0;
412*0Sstevel@tonic-gate 	ctxtp->rem_noadv_intrs = ctxtp->max_noadv_intrs;
413*0Sstevel@tonic-gate 
414*0Sstevel@tonic-gate 	/*
415*0Sstevel@tonic-gate 	 * clear out hci DMA descriptor status to start with clean slate.
416*0Sstevel@tonic-gate 	 * note that statuses could be set if context was previously started
417*0Sstevel@tonic-gate 	 * then stopped.
418*0Sstevel@tonic-gate 	 */
419*0Sstevel@tonic-gate 	hci1394_ixl_reset_status(ctxtp);
420*0Sstevel@tonic-gate 
421*0Sstevel@tonic-gate 	/* set up registers, and start isoch */
422*0Sstevel@tonic-gate 	if (ctxtp->ctxt_flags & HCI1394_ISO_CTXT_RECV) {
423*0Sstevel@tonic-gate 
424*0Sstevel@tonic-gate 		/* set context's command ptr to the first descriptor */
425*0Sstevel@tonic-gate 		hci1394_ohci_ir_cmd_ptr_set(soft_statep->ohci,
426*0Sstevel@tonic-gate 		    ctxtp->ctxt_index, ctxtp->dma_mem_execp);
427*0Sstevel@tonic-gate 
428*0Sstevel@tonic-gate 		TNF_PROBE_2_DEBUG(hci1394_start_isoch_dma_index_info,
429*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_INFO_ISOCH, "", tnf_string, msg,
430*0Sstevel@tonic-gate 		    "starting IR ctxt", tnf_int, ctxt_num, ctxtp->ctxt_index);
431*0Sstevel@tonic-gate 
432*0Sstevel@tonic-gate 		/*
433*0Sstevel@tonic-gate 		 * determine correct tag values.  map target's requested 2-bit
434*0Sstevel@tonic-gate 		 * tag into one of the 4 openHCI tag bits.
435*0Sstevel@tonic-gate 		 * XXX for now the t1394 api only supports a single tag setting,
436*0Sstevel@tonic-gate 		 * whereas openhci supports a set of (non-mutually exclusive)
437*0Sstevel@tonic-gate 		 * valid tags. if the api changes to support multiple
438*0Sstevel@tonic-gate 		 * simultaneous tags, then this code must be changed.
439*0Sstevel@tonic-gate 		 */
440*0Sstevel@tonic-gate 		tag0 = 0;
441*0Sstevel@tonic-gate 		tag1 = 1;
442*0Sstevel@tonic-gate 		tag2 = 2;
443*0Sstevel@tonic-gate 		tag3 = 3;
444*0Sstevel@tonic-gate 		if (ctxtp->default_tag == 0x0)
445*0Sstevel@tonic-gate 			tag0 = 1;
446*0Sstevel@tonic-gate 		else if (ctxtp->default_tag == 0x1)
447*0Sstevel@tonic-gate 			tag1 = 1;
448*0Sstevel@tonic-gate 		else if (ctxtp->default_tag == 0x2)
449*0Sstevel@tonic-gate 			tag2 = 1;
450*0Sstevel@tonic-gate 		else if (ctxtp->default_tag == 0x3)
451*0Sstevel@tonic-gate 			tag3 = 1;
452*0Sstevel@tonic-gate 
453*0Sstevel@tonic-gate 		/* set match register as desired */
454*0Sstevel@tonic-gate 		HCI1394_IRCTXT_MATCH_WRITE(soft_statep, ctxtp->ctxt_index, tag3,
455*0Sstevel@tonic-gate 		    tag2, tag1, tag0,
456*0Sstevel@tonic-gate 		    idma_ctrlinfop->start_cycle /* cycleMatch */,
457*0Sstevel@tonic-gate 		    ctxtp->default_sync /* sync */, 0 /* tag1sync */,
458*0Sstevel@tonic-gate 		    ctxtp->isochan /* chan */);
459*0Sstevel@tonic-gate 
460*0Sstevel@tonic-gate 		/* clear all bits in context ctrl reg to init to known state */
461*0Sstevel@tonic-gate 		HCI1394_IRCTXT_CTRL_CLR(soft_statep, ctxtp->ctxt_index,
462*0Sstevel@tonic-gate 		    (uint32_t)1, 1, 1, 1, 1);
463*0Sstevel@tonic-gate 
464*0Sstevel@tonic-gate 		/* set desired values in context control register */
465*0Sstevel@tonic-gate 		HCI1394_IRCTXT_CTRL_SET(soft_statep, ctxtp->ctxt_index,
466*0Sstevel@tonic-gate 		    (ctxtp->ctxt_flags & HCI1394_ISO_CTXT_BFFILL) != 0 /* bf */,
467*0Sstevel@tonic-gate 		    (ctxtp->ctxt_flags & HCI1394_ISO_CTXT_RHDRS) != 0 /* hdr */,
468*0Sstevel@tonic-gate 		    (flags & ID1394_START_ON_CYCLE) != 0 /* match enbl */,
469*0Sstevel@tonic-gate 		    0 /* multi-chan mode */, 1 /* run */, 0 /* wake */);
470*0Sstevel@tonic-gate 
471*0Sstevel@tonic-gate 		/*
472*0Sstevel@tonic-gate 		 * before enabling interrupts, make sure any vestige interrupt
473*0Sstevel@tonic-gate 		 * event (from a previous use) is cleared.
474*0Sstevel@tonic-gate 		 */
475*0Sstevel@tonic-gate 		hci1394_ohci_ir_intr_clear(soft_statep->ohci,
476*0Sstevel@tonic-gate 		    (uint32_t)(0x1 << ctxtp->ctxt_index));
477*0Sstevel@tonic-gate 
478*0Sstevel@tonic-gate 		/* enable interrupts for this IR context */
479*0Sstevel@tonic-gate 		hci1394_ohci_ir_intr_enable(soft_statep->ohci,
480*0Sstevel@tonic-gate 		    (uint32_t)(0x1 << ctxtp->ctxt_index));
481*0Sstevel@tonic-gate 
482*0Sstevel@tonic-gate 	} else {
483*0Sstevel@tonic-gate 		/* TRANSMIT */
484*0Sstevel@tonic-gate 
485*0Sstevel@tonic-gate 		/* set context's command ptr to the first descriptor */
486*0Sstevel@tonic-gate 		hci1394_ohci_it_cmd_ptr_set(soft_statep->ohci,
487*0Sstevel@tonic-gate 		    ctxtp->ctxt_index, ctxtp->dma_mem_execp);
488*0Sstevel@tonic-gate 
489*0Sstevel@tonic-gate 		TNF_PROBE_2_DEBUG(hci1394_start_isoch_dma_index_info,
490*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_INFO_ISOCH, "", tnf_string, msg,
491*0Sstevel@tonic-gate 		    "starting IT ctxt", tnf_int, ctxt_num, ctxtp->ctxt_index);
492*0Sstevel@tonic-gate 
493*0Sstevel@tonic-gate 		/* set desired values in context control register */
494*0Sstevel@tonic-gate 		HCI1394_ITCTXT_CTRL_SET(soft_statep, ctxtp->ctxt_index,
495*0Sstevel@tonic-gate 		    ((flags & ID1394_START_ON_CYCLE) != 0) /* match enable */,
496*0Sstevel@tonic-gate 		    idma_ctrlinfop->start_cycle /* cycle Match */,
497*0Sstevel@tonic-gate 		    1 /* run */, 0 /* wake */);
498*0Sstevel@tonic-gate 
499*0Sstevel@tonic-gate 		/*
500*0Sstevel@tonic-gate 		 * before enabling interrupts, make sure any vestige interrupt
501*0Sstevel@tonic-gate 		 * event (from a previous use) is cleared.
502*0Sstevel@tonic-gate 		 */
503*0Sstevel@tonic-gate 		hci1394_ohci_it_intr_clear(soft_statep->ohci,
504*0Sstevel@tonic-gate 		    (uint32_t)(0x1 << ctxtp->ctxt_index));
505*0Sstevel@tonic-gate 
506*0Sstevel@tonic-gate 		/* enable interrupts for this IT context */
507*0Sstevel@tonic-gate 		hci1394_ohci_it_intr_enable(soft_statep->ohci,
508*0Sstevel@tonic-gate 		    (uint32_t)(0x1 << ctxtp->ctxt_index));
509*0Sstevel@tonic-gate 	}
510*0Sstevel@tonic-gate 
511*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_start_isoch_dma_exit,
512*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
513*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
514*0Sstevel@tonic-gate }
515*0Sstevel@tonic-gate 
516*0Sstevel@tonic-gate /*
517*0Sstevel@tonic-gate  * hci1394_update_isoch_dma()
518*0Sstevel@tonic-gate  *
519*0Sstevel@tonic-gate  * Returns DDI_SUCCESS, or DDI_FAILURE.  If DDI_FAILURE, then resultp
520*0Sstevel@tonic-gate  * contains the error code.
521*0Sstevel@tonic-gate  */
522*0Sstevel@tonic-gate /* ARGSUSED */
523*0Sstevel@tonic-gate int
hci1394_update_isoch_dma(void * hal_private,void * hal_isoch_dma_handle,id1394_isoch_dma_updateinfo_t * idma_updateinfop,uint_t flags,int * resultp)524*0Sstevel@tonic-gate hci1394_update_isoch_dma(void *hal_private, void *hal_isoch_dma_handle,
525*0Sstevel@tonic-gate     id1394_isoch_dma_updateinfo_t *idma_updateinfop, uint_t flags, int *resultp)
526*0Sstevel@tonic-gate {
527*0Sstevel@tonic-gate 	hci1394_state_t	    *soft_statep = (hci1394_state_t *)hal_private;
528*0Sstevel@tonic-gate 	hci1394_iso_ctxt_t  *ctxtp;
529*0Sstevel@tonic-gate 	ixl1394_command_t   *cur_new_ixlp;
530*0Sstevel@tonic-gate 	ixl1394_command_t   *cur_orig_ixlp;
531*0Sstevel@tonic-gate 	int		    ii;
532*0Sstevel@tonic-gate 	int		    err = DDI_SUCCESS;
533*0Sstevel@tonic-gate 
534*0Sstevel@tonic-gate 
535*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_update_isoch_dma_enter,
536*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
537*0Sstevel@tonic-gate 
538*0Sstevel@tonic-gate 	/* pick up the context pointer from the private idma data */
539*0Sstevel@tonic-gate 	ctxtp = (hci1394_iso_ctxt_t *)hal_isoch_dma_handle;
540*0Sstevel@tonic-gate 
541*0Sstevel@tonic-gate 	ASSERT(hal_private != NULL);
542*0Sstevel@tonic-gate 	ASSERT(ctxtp != NULL);
543*0Sstevel@tonic-gate 	ASSERT(idma_updateinfop != NULL);
544*0Sstevel@tonic-gate 
545*0Sstevel@tonic-gate 	/*
546*0Sstevel@tonic-gate 	 * regardless of the type of context (IR or IT), loop through each
547*0Sstevel@tonic-gate 	 * command pair (one from new, one from orig), updating the relevant
548*0Sstevel@tonic-gate 	 * fields of orig with those from new.
549*0Sstevel@tonic-gate 	 */
550*0Sstevel@tonic-gate 	cur_new_ixlp = idma_updateinfop->temp_ixlp;
551*0Sstevel@tonic-gate 	cur_orig_ixlp = idma_updateinfop->orig_ixlp;
552*0Sstevel@tonic-gate 
553*0Sstevel@tonic-gate 	ASSERT(cur_new_ixlp != NULL);
554*0Sstevel@tonic-gate 	ASSERT(cur_orig_ixlp != NULL);
555*0Sstevel@tonic-gate 
556*0Sstevel@tonic-gate 	/* lots of debug trace info */
557*0Sstevel@tonic-gate 	TNF_PROBE_4_DEBUG(hci1394_update_isoch_dma_ctxt_info,
558*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_INFO_ISOCH, "", tnf_opaque, ctxt_ptr, ctxtp,
559*0Sstevel@tonic-gate 	    tnf_int, ixlcount, idma_updateinfop->ixl_count,
560*0Sstevel@tonic-gate 	    tnf_opaque, new_ixl, cur_new_ixlp, tnf_opaque, orig_ixl,
561*0Sstevel@tonic-gate 	    cur_orig_ixlp);
562*0Sstevel@tonic-gate 
563*0Sstevel@tonic-gate 	for (ii = 0; (ii < idma_updateinfop->ixl_count) && (err == DDI_SUCCESS);
564*0Sstevel@tonic-gate 	    ii++) {
565*0Sstevel@tonic-gate 
566*0Sstevel@tonic-gate 		/* error if hit a null ixl command too soon */
567*0Sstevel@tonic-gate 		if ((cur_new_ixlp == NULL) || (cur_orig_ixlp == NULL)) {
568*0Sstevel@tonic-gate 			*resultp = IXL1394_ECOUNT_MISMATCH;
569*0Sstevel@tonic-gate 			err = DDI_FAILURE;
570*0Sstevel@tonic-gate 
571*0Sstevel@tonic-gate 			TNF_PROBE_3_DEBUG(hci1394_update_isoch_dma_mismatch,
572*0Sstevel@tonic-gate 			    HCI1394_TNF_HAL_ERROR_ISOCH, "", tnf_opaque, new,
573*0Sstevel@tonic-gate 			    cur_new_ixlp, tnf_opaque, orig, cur_orig_ixlp,
574*0Sstevel@tonic-gate 			    tnf_int, iteration, ii);
575*0Sstevel@tonic-gate 			break;
576*0Sstevel@tonic-gate 		}
577*0Sstevel@tonic-gate 
578*0Sstevel@tonic-gate 		/* proceed with the update */
579*0Sstevel@tonic-gate 		err = hci1394_ixl_update(soft_statep, ctxtp, cur_new_ixlp,
580*0Sstevel@tonic-gate 		    cur_orig_ixlp, 0, resultp);
581*0Sstevel@tonic-gate 
582*0Sstevel@tonic-gate 		/* advance new and orig chains */
583*0Sstevel@tonic-gate 		cur_new_ixlp = cur_new_ixlp->next_ixlp;
584*0Sstevel@tonic-gate 		cur_orig_ixlp = cur_orig_ixlp->next_ixlp;
585*0Sstevel@tonic-gate 	}
586*0Sstevel@tonic-gate 
587*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_update_isoch_dma_exit,
588*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
589*0Sstevel@tonic-gate 	return (err);
590*0Sstevel@tonic-gate }
591*0Sstevel@tonic-gate 
592*0Sstevel@tonic-gate 
593*0Sstevel@tonic-gate /*
594*0Sstevel@tonic-gate  * hci1394_stop_isoch_dma()
595*0Sstevel@tonic-gate  *    Used to stop a "running" isochronous dma resource.
596*0Sstevel@tonic-gate  *    This is a wrapper which calls the hci1394_do_stop to do the actual work,
597*0Sstevel@tonic-gate  *    but NOT to invoke the target's isoch_dma_stopped().
598*0Sstevel@tonic-gate  */
599*0Sstevel@tonic-gate /* ARGSUSED */
600*0Sstevel@tonic-gate void
hci1394_stop_isoch_dma(void * hal_private,void * hal_isoch_dma_handle,int * result)601*0Sstevel@tonic-gate hci1394_stop_isoch_dma(void *hal_private, void *hal_isoch_dma_handle,
602*0Sstevel@tonic-gate     int	*result)
603*0Sstevel@tonic-gate {
604*0Sstevel@tonic-gate 	hci1394_state_t	    *soft_statep = (hci1394_state_t *)hal_private;
605*0Sstevel@tonic-gate 	hci1394_iso_ctxt_t  *ctxtp;
606*0Sstevel@tonic-gate 
607*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_stop_isoch_dma_enter,
608*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
609*0Sstevel@tonic-gate 
610*0Sstevel@tonic-gate 	/* pick up the context pointer from the private idma data */
611*0Sstevel@tonic-gate 	ctxtp = (hci1394_iso_ctxt_t *)hal_isoch_dma_handle;
612*0Sstevel@tonic-gate 
613*0Sstevel@tonic-gate 	ASSERT(hal_private != NULL);
614*0Sstevel@tonic-gate 	ASSERT(ctxtp != NULL);
615*0Sstevel@tonic-gate 
616*0Sstevel@tonic-gate 	/* stop the context, do not invoke target's stop callback */
617*0Sstevel@tonic-gate 	hci1394_do_stop(soft_statep, ctxtp, B_FALSE, 0);
618*0Sstevel@tonic-gate 
619*0Sstevel@tonic-gate 	/*
620*0Sstevel@tonic-gate 	 * call interrupt processing functions to bring callbacks and
621*0Sstevel@tonic-gate 	 * store_timestamps upto date.  Don't care about errors.
622*0Sstevel@tonic-gate 	 */
623*0Sstevel@tonic-gate 	hci1394_ixl_interrupt(soft_statep, ctxtp, B_TRUE);
624*0Sstevel@tonic-gate 
625*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_stop_isoch_dma_exit,
626*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
627*0Sstevel@tonic-gate }
628*0Sstevel@tonic-gate 
629*0Sstevel@tonic-gate /*
630*0Sstevel@tonic-gate  * hci1394_do_stop()
631*0Sstevel@tonic-gate  *    Used to stop a "running" isochronous dma resource.
632*0Sstevel@tonic-gate  *    Disables interrupts for the context, clears the context_control register's
633*0Sstevel@tonic-gate  *    RUN bit, and makes sure the ixl is up-to-date with where the hardware is
634*0Sstevel@tonic-gate  *    in the DMA chain.
635*0Sstevel@tonic-gate  *    If do_callback is B_TRUE, the target's isoch_dma_stopped() callback is
636*0Sstevel@tonic-gate  *    invoked.  Caller must not hold mutex(es) if calling with
637*0Sstevel@tonic-gate  *    do_callback==B_TRUE, otherwise mutex(es) will be held during callback.
638*0Sstevel@tonic-gate  *    If do_callback is B_FALSE, the isoch_dma_stopped() callback is NOT
639*0Sstevel@tonic-gate  *    invoked and stop_args is ignored.
640*0Sstevel@tonic-gate  */
641*0Sstevel@tonic-gate void
hci1394_do_stop(hci1394_state_t * soft_statep,hci1394_iso_ctxt_t * ctxtp,boolean_t do_callback,id1394_isoch_dma_stopped_t stop_args)642*0Sstevel@tonic-gate hci1394_do_stop(hci1394_state_t *soft_statep, hci1394_iso_ctxt_t *ctxtp,
643*0Sstevel@tonic-gate     boolean_t do_callback, id1394_isoch_dma_stopped_t stop_args)
644*0Sstevel@tonic-gate {
645*0Sstevel@tonic-gate 	int	count;
646*0Sstevel@tonic-gate 	clock_t	upto;
647*0Sstevel@tonic-gate 
648*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_do_stop_enter, HCI1394_TNF_HAL_STACK_ISOCH,
649*0Sstevel@tonic-gate 	    "");
650*0Sstevel@tonic-gate 
651*0Sstevel@tonic-gate 	TNF_PROBE_4_DEBUG(hci1394_do_stop_info,
652*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_INFO_ISOCH, "", tnf_opaque, ctxt_ptr, ctxtp,
653*0Sstevel@tonic-gate 	    tnf_int, ctxt_index, ctxtp->ctxt_index, tnf_opaque, ctxt_flags,
654*0Sstevel@tonic-gate 	    ctxtp->ctxt_flags, tnf_string, reason,
655*0Sstevel@tonic-gate 	    (stop_args == ID1394_DONE) ? "DONE":"FAIL");
656*0Sstevel@tonic-gate 
657*0Sstevel@tonic-gate 	/* already stopped? if yes, done, else set state to not-running */
658*0Sstevel@tonic-gate 	mutex_enter(&soft_statep->isoch->ctxt_list_mutex);
659*0Sstevel@tonic-gate 	if ((ctxtp->ctxt_flags & HCI1394_ISO_CTXT_RUNNING) == 0) {
660*0Sstevel@tonic-gate 		mutex_exit(&soft_statep->isoch->ctxt_list_mutex);
661*0Sstevel@tonic-gate 
662*0Sstevel@tonic-gate 		TNF_PROBE_1_DEBUG(hci1394_do_stop_exit,
663*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK_ISOCH, "", tnf_string, msg,
664*0Sstevel@tonic-gate 		    "context already stopped");
665*0Sstevel@tonic-gate 		return;
666*0Sstevel@tonic-gate 	}
667*0Sstevel@tonic-gate 	ctxtp->ctxt_flags &= ~HCI1394_ISO_CTXT_RUNNING;
668*0Sstevel@tonic-gate 	mutex_exit(&soft_statep->isoch->ctxt_list_mutex);
669*0Sstevel@tonic-gate 
670*0Sstevel@tonic-gate 	/* turn off context control register's run bit */
671*0Sstevel@tonic-gate 	if (ctxtp->ctxt_flags & HCI1394_ISO_CTXT_RECV) {
672*0Sstevel@tonic-gate 		/* RECEIVE */
673*0Sstevel@tonic-gate 
674*0Sstevel@tonic-gate 		/* disable interrupts for this IR context */
675*0Sstevel@tonic-gate 		hci1394_ohci_ir_intr_disable(soft_statep->ohci,
676*0Sstevel@tonic-gate 		    (uint32_t)(0x1 << ctxtp->ctxt_index));
677*0Sstevel@tonic-gate 
678*0Sstevel@tonic-gate 		/* turn off run bit */
679*0Sstevel@tonic-gate 		HCI1394_IRCTXT_CTRL_CLR(soft_statep, ctxtp->ctxt_index,
680*0Sstevel@tonic-gate 		    0 /* bffill */, 0 /* iso hdrs */, 0 /* match enbl */,
681*0Sstevel@tonic-gate 		    0 /* multi-chan mode (not implemented) */, 1 /* run */);
682*0Sstevel@tonic-gate 	} else {
683*0Sstevel@tonic-gate 		/* TRANSMIT */
684*0Sstevel@tonic-gate 
685*0Sstevel@tonic-gate 		/* disable interrupts for this IT context */
686*0Sstevel@tonic-gate 		hci1394_ohci_it_intr_disable(soft_statep->ohci,
687*0Sstevel@tonic-gate 		    (uint32_t)(0x1 << ctxtp->ctxt_index));
688*0Sstevel@tonic-gate 
689*0Sstevel@tonic-gate 		/* turn of run bit */
690*0Sstevel@tonic-gate 		HCI1394_ITCTXT_CTRL_CLR(soft_statep, ctxtp->ctxt_index,
691*0Sstevel@tonic-gate 		    0 /* match enbl */, 0 /* match */, 1 /* run */);
692*0Sstevel@tonic-gate 	}
693*0Sstevel@tonic-gate 
694*0Sstevel@tonic-gate 	/*
695*0Sstevel@tonic-gate 	 * If interrupt is already in progress, wait until it's over.
696*0Sstevel@tonic-gate 	 * Otherwise, set flag to prevent the new interrupt.
697*0Sstevel@tonic-gate 	 */
698*0Sstevel@tonic-gate 	mutex_enter(&ctxtp->intrprocmutex);
699*0Sstevel@tonic-gate 	ctxtp->intr_flags |= HCI1394_ISO_CTXT_STOP;
700*0Sstevel@tonic-gate 	if (ctxtp->intr_flags & HCI1394_ISO_CTXT_ININTR) {
701*0Sstevel@tonic-gate 		upto = ddi_get_lbolt() +
702*0Sstevel@tonic-gate 		    drv_usectohz(hci1394_iso_ctxt_stop_intr_timeout_uS);
703*0Sstevel@tonic-gate 		while (ctxtp->intr_flags & HCI1394_ISO_CTXT_ININTR) {
704*0Sstevel@tonic-gate 			if (cv_timedwait(&ctxtp->intr_cv, &ctxtp->intrprocmutex,
705*0Sstevel@tonic-gate 			    upto) <= 0) {
706*0Sstevel@tonic-gate 				break;
707*0Sstevel@tonic-gate 			}
708*0Sstevel@tonic-gate 		}
709*0Sstevel@tonic-gate 
710*0Sstevel@tonic-gate 		if (ctxtp->intr_flags & HCI1394_ISO_CTXT_ININTR) {
711*0Sstevel@tonic-gate 			TNF_PROBE_1(hci1394_do_stop_error,
712*0Sstevel@tonic-gate 			    HCI1394_TNF_HAL_ERROR_ISOCH, "",
713*0Sstevel@tonic-gate 			    tnf_string, msg, "intr completion timeout");
714*0Sstevel@tonic-gate 		}
715*0Sstevel@tonic-gate 	}
716*0Sstevel@tonic-gate 	mutex_exit(&ctxtp->intrprocmutex);
717*0Sstevel@tonic-gate 
718*0Sstevel@tonic-gate 	/* Wait until "active" bit is cleared before continuing */
719*0Sstevel@tonic-gate 	count = 0;
720*0Sstevel@tonic-gate 	while (count < hci1394_iso_ctxt_stop_delay_uS) {
721*0Sstevel@tonic-gate 		/* Has the "active" bit gone low yet? */
722*0Sstevel@tonic-gate 		if (HCI1394_ISOCH_CTXT_ACTIVE(soft_statep, ctxtp) == 0)
723*0Sstevel@tonic-gate 			break;
724*0Sstevel@tonic-gate 
725*0Sstevel@tonic-gate 		/*
726*0Sstevel@tonic-gate 		 * The context did not stop yet.  Wait 1us, increment the
727*0Sstevel@tonic-gate 		 * count and try again.
728*0Sstevel@tonic-gate 		 */
729*0Sstevel@tonic-gate 		drv_usecwait(1);
730*0Sstevel@tonic-gate 		count++;
731*0Sstevel@tonic-gate 	}
732*0Sstevel@tonic-gate 
733*0Sstevel@tonic-gate 	/* Check to see if we timed out or not */
734*0Sstevel@tonic-gate 	if (count >= hci1394_iso_ctxt_stop_delay_uS) {
735*0Sstevel@tonic-gate 		h1394_error_detected(soft_statep->drvinfo.di_sl_private,
736*0Sstevel@tonic-gate 		    H1394_SELF_INITIATED_SHUTDOWN, NULL);
737*0Sstevel@tonic-gate 		cmn_err(CE_WARN, "hci1394(%d): driver shutdown: "
738*0Sstevel@tonic-gate 		    "unable to stop isoch context",
739*0Sstevel@tonic-gate 		    soft_statep->drvinfo.di_instance);
740*0Sstevel@tonic-gate 		hci1394_shutdown(soft_statep->drvinfo.di_dip);
741*0Sstevel@tonic-gate 
742*0Sstevel@tonic-gate 		TNF_PROBE_1_DEBUG(hci1394_do_stop_exit,
743*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK_ISOCH, "", tnf_string, msg,
744*0Sstevel@tonic-gate 		    "context timed out trying to stop");
745*0Sstevel@tonic-gate 		return;
746*0Sstevel@tonic-gate 	}
747*0Sstevel@tonic-gate 
748*0Sstevel@tonic-gate 	/*
749*0Sstevel@tonic-gate 	 * invoke callback as directed.  Note that the CTXT_INCALL flag is NOT
750*0Sstevel@tonic-gate 	 * needed here.  That flag is only used when we have to drop a mutex
751*0Sstevel@tonic-gate 	 * that we want to grab back again. We're not doing that here.
752*0Sstevel@tonic-gate 	 */
753*0Sstevel@tonic-gate 	if (do_callback == B_TRUE) {
754*0Sstevel@tonic-gate 		if (ctxtp->isoch_dma_stopped != NULL) {
755*0Sstevel@tonic-gate 			ctxtp->isoch_dma_stopped(
756*0Sstevel@tonic-gate 			    (struct isoch_dma_handle *)ctxtp,
757*0Sstevel@tonic-gate 			    ctxtp->idma_evt_arg, stop_args);
758*0Sstevel@tonic-gate 		}
759*0Sstevel@tonic-gate 	}
760*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_do_stop_exit, HCI1394_TNF_HAL_STACK_ISOCH,
761*0Sstevel@tonic-gate 	    "");
762*0Sstevel@tonic-gate }
763*0Sstevel@tonic-gate 
764*0Sstevel@tonic-gate /*
765*0Sstevel@tonic-gate  * hci1394_free_isoch_dma()
766*0Sstevel@tonic-gate  *    Used to free up usage of an isochronous context and any other
767*0Sstevel@tonic-gate  *    system resources acquired during IXL compilation.
768*0Sstevel@tonic-gate  *    This does NOT free up the IXL and it's data buffers which is
769*0Sstevel@tonic-gate  *    the target driver's responsibility.
770*0Sstevel@tonic-gate  */
771*0Sstevel@tonic-gate void
hci1394_free_isoch_dma(void * hal_private,void * hal_isoch_dma_handle)772*0Sstevel@tonic-gate hci1394_free_isoch_dma(void *hal_private, void *hal_isoch_dma_handle)
773*0Sstevel@tonic-gate {
774*0Sstevel@tonic-gate 	hci1394_state_t	    *soft_statep = (hci1394_state_t *)hal_private;
775*0Sstevel@tonic-gate 	hci1394_iso_ctxt_t  *ctxtp;
776*0Sstevel@tonic-gate 	hci1394_isoch_t	    *isochp;
777*0Sstevel@tonic-gate 
778*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_free_isoch_dma_enter,
779*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
780*0Sstevel@tonic-gate 
781*0Sstevel@tonic-gate 	/* pick up the context pointer from the private idma data */
782*0Sstevel@tonic-gate 	ctxtp = (hci1394_iso_ctxt_t *)hal_isoch_dma_handle;
783*0Sstevel@tonic-gate 
784*0Sstevel@tonic-gate 	ASSERT(soft_statep);
785*0Sstevel@tonic-gate 	ASSERT(ctxtp);
786*0Sstevel@tonic-gate 
787*0Sstevel@tonic-gate 	isochp = soft_statep->isoch;
788*0Sstevel@tonic-gate 
789*0Sstevel@tonic-gate 	/* lots of debug trace info */
790*0Sstevel@tonic-gate 	TNF_PROBE_4_DEBUG(hci1394_free_isoch_dma_ctxt_info,
791*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_INFO_ISOCH, "", tnf_opaque, ctxt_ptr, ctxtp,
792*0Sstevel@tonic-gate 	    tnf_int, ctxt_index, ctxtp->ctxt_index, tnf_opaque, ctxt_flags,
793*0Sstevel@tonic-gate 	    ctxtp->ctxt_flags, tnf_opaque, first_ixl, ctxtp->ixl_firstp);
794*0Sstevel@tonic-gate 
795*0Sstevel@tonic-gate 	mutex_enter(&soft_statep->isoch->ctxt_list_mutex);
796*0Sstevel@tonic-gate 
797*0Sstevel@tonic-gate 	/* delete xfer_ctl structs and pages of allocated hci_desc memory */
798*0Sstevel@tonic-gate 	hci1394_ixl_cleanup(soft_statep, ctxtp);
799*0Sstevel@tonic-gate 
800*0Sstevel@tonic-gate 	/*
801*0Sstevel@tonic-gate 	 * free context. no need to determine if xmit or recv. clearing of recv
802*0Sstevel@tonic-gate 	 * flags is harmless for xmit.
803*0Sstevel@tonic-gate 	 */
804*0Sstevel@tonic-gate 	ctxtp->ctxt_flags &= ~(HCI1394_ISO_CTXT_INUSE |
805*0Sstevel@tonic-gate 	    HCI1394_ISO_CTXT_BFFILL | HCI1394_ISO_CTXT_RHDRS);
806*0Sstevel@tonic-gate 
807*0Sstevel@tonic-gate 	/*
808*0Sstevel@tonic-gate 	 * Update count of allocated isoch dma (and disable interrupts
809*0Sstevel@tonic-gate 	 * if necessary)
810*0Sstevel@tonic-gate 	 */
811*0Sstevel@tonic-gate 	ASSERT(isochp->isoch_dma_alloc_cnt > 0);
812*0Sstevel@tonic-gate 	isochp->isoch_dma_alloc_cnt--;
813*0Sstevel@tonic-gate 	if (isochp->isoch_dma_alloc_cnt == 0) {
814*0Sstevel@tonic-gate 		hci1394_ohci_intr_disable(soft_statep->ohci,
815*0Sstevel@tonic-gate 		    OHCI_INTR_CYC_LOST | OHCI_INTR_CYC_INCONSISTENT);
816*0Sstevel@tonic-gate 	}
817*0Sstevel@tonic-gate 
818*0Sstevel@tonic-gate 	mutex_exit(&soft_statep->isoch->ctxt_list_mutex);
819*0Sstevel@tonic-gate 
820*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_free_isoch_dma_exit,
821*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
822*0Sstevel@tonic-gate }
823*0Sstevel@tonic-gate 
824*0Sstevel@tonic-gate /*
825*0Sstevel@tonic-gate  * hci1394_isoch_recv_count_get()
826*0Sstevel@tonic-gate  *    returns the number of supported isoch receive contexts.
827*0Sstevel@tonic-gate  */
828*0Sstevel@tonic-gate int
hci1394_isoch_recv_count_get(hci1394_isoch_handle_t isoch_hdl)829*0Sstevel@tonic-gate hci1394_isoch_recv_count_get(hci1394_isoch_handle_t isoch_hdl)
830*0Sstevel@tonic-gate {
831*0Sstevel@tonic-gate 	ASSERT(isoch_hdl != NULL);
832*0Sstevel@tonic-gate 	return (isoch_hdl->ctxt_recv_count);
833*0Sstevel@tonic-gate }
834*0Sstevel@tonic-gate 
835*0Sstevel@tonic-gate /*
836*0Sstevel@tonic-gate  * hci1394_isoch_recv_ctxt_get()
837*0Sstevel@tonic-gate  *    given a context index, returns its isoch receive context struct
838*0Sstevel@tonic-gate  */
839*0Sstevel@tonic-gate hci1394_iso_ctxt_t *
hci1394_isoch_recv_ctxt_get(hci1394_isoch_handle_t isoch_hdl,int num)840*0Sstevel@tonic-gate hci1394_isoch_recv_ctxt_get(hci1394_isoch_handle_t isoch_hdl, int num)
841*0Sstevel@tonic-gate {
842*0Sstevel@tonic-gate 	ASSERT(isoch_hdl != NULL);
843*0Sstevel@tonic-gate 	return (&isoch_hdl->ctxt_recv[num]);
844*0Sstevel@tonic-gate }
845*0Sstevel@tonic-gate 
846*0Sstevel@tonic-gate /*
847*0Sstevel@tonic-gate  * hci1394_isoch_xmit_count_get()
848*0Sstevel@tonic-gate  *    returns the number of supported isoch transmit contexts.
849*0Sstevel@tonic-gate  */
850*0Sstevel@tonic-gate int
hci1394_isoch_xmit_count_get(hci1394_isoch_handle_t isoch_hdl)851*0Sstevel@tonic-gate hci1394_isoch_xmit_count_get(hci1394_isoch_handle_t isoch_hdl)
852*0Sstevel@tonic-gate {
853*0Sstevel@tonic-gate 	ASSERT(isoch_hdl != NULL);
854*0Sstevel@tonic-gate 	return (isoch_hdl->ctxt_xmit_count);
855*0Sstevel@tonic-gate }
856*0Sstevel@tonic-gate 
857*0Sstevel@tonic-gate /*
858*0Sstevel@tonic-gate  * hci1394_isoch_xmit_ctxt_get()
859*0Sstevel@tonic-gate  *    given a context index, returns its isoch transmit context struct
860*0Sstevel@tonic-gate  */
861*0Sstevel@tonic-gate hci1394_iso_ctxt_t *
hci1394_isoch_xmit_ctxt_get(hci1394_isoch_handle_t isoch_hdl,int num)862*0Sstevel@tonic-gate hci1394_isoch_xmit_ctxt_get(hci1394_isoch_handle_t isoch_hdl, int num)
863*0Sstevel@tonic-gate {
864*0Sstevel@tonic-gate 	ASSERT(isoch_hdl != NULL);
865*0Sstevel@tonic-gate 	return (&isoch_hdl->ctxt_xmit[num]);
866*0Sstevel@tonic-gate }
867*0Sstevel@tonic-gate 
868*0Sstevel@tonic-gate /*
869*0Sstevel@tonic-gate  * hci1394_isoch_error_ints_enable()
870*0Sstevel@tonic-gate  *    after bus reset, reenable CYCLE_LOST and CYCLE_INCONSISTENT
871*0Sstevel@tonic-gate  *    interrupts (if necessary).
872*0Sstevel@tonic-gate  */
873*0Sstevel@tonic-gate void
hci1394_isoch_error_ints_enable(hci1394_state_t * soft_statep)874*0Sstevel@tonic-gate hci1394_isoch_error_ints_enable(hci1394_state_t *soft_statep)
875*0Sstevel@tonic-gate {
876*0Sstevel@tonic-gate 	ASSERT(soft_statep);
877*0Sstevel@tonic-gate 
878*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_isoch_error_ints_enable_enter,
879*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
880*0Sstevel@tonic-gate 
881*0Sstevel@tonic-gate 	mutex_enter(&soft_statep->isoch->ctxt_list_mutex);
882*0Sstevel@tonic-gate 
883*0Sstevel@tonic-gate 	if (soft_statep->isoch->isoch_dma_alloc_cnt != 0) {
884*0Sstevel@tonic-gate 		soft_statep->isoch->cycle_lost_thresh.delta_t_counter  = 0;
885*0Sstevel@tonic-gate 		soft_statep->isoch->cycle_incon_thresh.delta_t_counter = 0;
886*0Sstevel@tonic-gate 		hci1394_ohci_intr_clear(soft_statep->ohci,
887*0Sstevel@tonic-gate 		    OHCI_INTR_CYC_LOST | OHCI_INTR_CYC_INCONSISTENT);
888*0Sstevel@tonic-gate 		hci1394_ohci_intr_enable(soft_statep->ohci,
889*0Sstevel@tonic-gate 		    OHCI_INTR_CYC_LOST | OHCI_INTR_CYC_INCONSISTENT);
890*0Sstevel@tonic-gate 	}
891*0Sstevel@tonic-gate 	mutex_exit(&soft_statep->isoch->ctxt_list_mutex);
892*0Sstevel@tonic-gate 
893*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_isoch_error_ints_enable_exit,
894*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
895*0Sstevel@tonic-gate }
896