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 1999-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_ixl_misc.c
31*0Sstevel@tonic-gate  *    Isochronous IXL miscellaneous routines.
32*0Sstevel@tonic-gate  *    Contains common routines used by the ixl compiler, interrupt handler and
33*0Sstevel@tonic-gate  *    dynamic update.
34*0Sstevel@tonic-gate  */
35*0Sstevel@tonic-gate 
36*0Sstevel@tonic-gate #include <sys/kmem.h>
37*0Sstevel@tonic-gate #include <sys/types.h>
38*0Sstevel@tonic-gate #include <sys/conf.h>
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate #include <sys/tnf_probe.h>
41*0Sstevel@tonic-gate 
42*0Sstevel@tonic-gate #include <sys/1394/h1394.h>
43*0Sstevel@tonic-gate #include <sys/1394/ixl1394.h>
44*0Sstevel@tonic-gate #include <sys/1394/adapters/hci1394.h>
45*0Sstevel@tonic-gate 
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate /* local routines */
48*0Sstevel@tonic-gate static void hci1394_delete_dma_desc_mem(hci1394_state_t *soft_statep,
49*0Sstevel@tonic-gate     hci1394_idma_desc_mem_t *);
50*0Sstevel@tonic-gate static void hci1394_delete_xfer_ctl(hci1394_xfer_ctl_t *);
51*0Sstevel@tonic-gate 
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate /*
54*0Sstevel@tonic-gate  * hci1394_ixl_set_start()
55*0Sstevel@tonic-gate  *    Set up the context structure with the first ixl command to process
56*0Sstevel@tonic-gate  *    and the first hci descriptor to execute.
57*0Sstevel@tonic-gate  *
58*0Sstevel@tonic-gate  *    This function assumes the current context is stopped!
59*0Sstevel@tonic-gate  *
60*0Sstevel@tonic-gate  *    If ixlstp IS NOT null AND is not the first compiled ixl command and
61*0Sstevel@tonic-gate  *    is not an ixl label command, returns an error.
62*0Sstevel@tonic-gate  *    If ixlstp IS null, uses the first compiled ixl command (ixl_firstp)
63*0Sstevel@tonic-gate  *    in place of ixlstp.
64*0Sstevel@tonic-gate  *
65*0Sstevel@tonic-gate  *    If no executeable xfer found along exec path from ixlstp, returns error.
66*0Sstevel@tonic-gate  */
67*0Sstevel@tonic-gate int
hci1394_ixl_set_start(hci1394_iso_ctxt_t * ctxtp,ixl1394_command_t * ixlstp)68*0Sstevel@tonic-gate hci1394_ixl_set_start(hci1394_iso_ctxt_t *ctxtp, ixl1394_command_t *ixlstp)
69*0Sstevel@tonic-gate {
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate 	ixl1394_command_t  *ixl_exec_startp;
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_ixl_set_start_enter,
74*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate 	/* if ixl start command is null, use first compiled ixl command */
77*0Sstevel@tonic-gate 	if (ixlstp == NULL) {
78*0Sstevel@tonic-gate 		ixlstp = ctxtp->ixl_firstp;
79*0Sstevel@tonic-gate 	}
80*0Sstevel@tonic-gate 
81*0Sstevel@tonic-gate 	/*
82*0Sstevel@tonic-gate 	 * if ixl start command is not first ixl compiled and is not a label,
83*0Sstevel@tonic-gate 	 * error
84*0Sstevel@tonic-gate 	 */
85*0Sstevel@tonic-gate 	if ((ixlstp != ctxtp->ixl_firstp) && (ixlstp->ixl_opcode !=
86*0Sstevel@tonic-gate 	    IXL1394_OP_LABEL)) {
87*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_ixl_set_start_exit,
88*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK_ISOCH, "");
89*0Sstevel@tonic-gate 		return (-1);
90*0Sstevel@tonic-gate 	}
91*0Sstevel@tonic-gate 
92*0Sstevel@tonic-gate 	/* follow exec path to find first ixl command that's an xfer command */
93*0Sstevel@tonic-gate 	(void) hci1394_ixl_find_next_exec_xfer(ixlstp, NULL, &ixl_exec_startp);
94*0Sstevel@tonic-gate 
95*0Sstevel@tonic-gate 	/*
96*0Sstevel@tonic-gate 	 * if there was one, then in it's compiler private, its
97*0Sstevel@tonic-gate 	 * hci1394_xfer_ctl structure has the appropriate bound address
98*0Sstevel@tonic-gate 	 */
99*0Sstevel@tonic-gate 	if (ixl_exec_startp != NULL) {
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate 		/* set up for start of context and return done */
102*0Sstevel@tonic-gate 		ctxtp->dma_mem_execp = (uint32_t)((hci1394_xfer_ctl_t *)
103*0Sstevel@tonic-gate 			ixl_exec_startp->compiler_privatep)->dma[0].dma_bound;
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate 		ctxtp->dma_last_time = 0;
106*0Sstevel@tonic-gate 		ctxtp->ixl_exec_depth = 0;
107*0Sstevel@tonic-gate 		ctxtp->ixl_execp = ixlstp;
108*0Sstevel@tonic-gate 		ctxtp->rem_noadv_intrs = ctxtp->max_noadv_intrs;
109*0Sstevel@tonic-gate 
110*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_ixl_set_start_exit,
111*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK_ISOCH, "");
112*0Sstevel@tonic-gate 		return (0);
113*0Sstevel@tonic-gate 	}
114*0Sstevel@tonic-gate 
115*0Sstevel@tonic-gate 	/* else no executeable xfer command found, return error */
116*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_ixl_set_start_exit,
117*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
118*0Sstevel@tonic-gate 	return (1);
119*0Sstevel@tonic-gate }
120*0Sstevel@tonic-gate #ifdef _KERNEL
121*0Sstevel@tonic-gate /*
122*0Sstevel@tonic-gate  * hci1394_ixl_reset_status()
123*0Sstevel@tonic-gate  * Reset all statuses in all hci descriptor blocks associated with the
124*0Sstevel@tonic-gate  * current linked list of compiled ixl commands.
125*0Sstevel@tonic-gate  *
126*0Sstevel@tonic-gate  * This function assumes the current context is stopped!
127*0Sstevel@tonic-gate  */
128*0Sstevel@tonic-gate void
hci1394_ixl_reset_status(hci1394_iso_ctxt_t * ctxtp)129*0Sstevel@tonic-gate hci1394_ixl_reset_status(hci1394_iso_ctxt_t *ctxtp)
130*0Sstevel@tonic-gate {
131*0Sstevel@tonic-gate 	ixl1394_command_t	*ixlcur;
132*0Sstevel@tonic-gate 	ixl1394_command_t	*ixlnext;
133*0Sstevel@tonic-gate 	hci1394_xfer_ctl_t	*xferctlp;
134*0Sstevel@tonic-gate 	uint_t			ixldepth;
135*0Sstevel@tonic-gate 	uint16_t		timestamp;
136*0Sstevel@tonic-gate 
137*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_ixl_reset_status_enter,
138*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
139*0Sstevel@tonic-gate 
140*0Sstevel@tonic-gate 	ixlnext = ctxtp->ixl_firstp;
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate 	/*
143*0Sstevel@tonic-gate 	 * Scan for next ixl xfer start command along ixl link path.
144*0Sstevel@tonic-gate 	 * Once xfer command found, clear its hci descriptor block's
145*0Sstevel@tonic-gate 	 * status. If is composite ixl xfer command, clear statuses
146*0Sstevel@tonic-gate 	 * in each of its hci descriptor blocks.
147*0Sstevel@tonic-gate 	 */
148*0Sstevel@tonic-gate 	while (ixlnext != NULL) {
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate 		/* set current and next ixl command */
151*0Sstevel@tonic-gate 		ixlcur = ixlnext;
152*0Sstevel@tonic-gate 		ixlnext = ixlcur->next_ixlp;
153*0Sstevel@tonic-gate 
154*0Sstevel@tonic-gate 		/* skip to examine next if this is not xfer start ixl command */
155*0Sstevel@tonic-gate 		if (((ixlcur->ixl_opcode & IXL1394_OPF_ISXFER) == 0) ||
156*0Sstevel@tonic-gate 		    ((ixlcur->ixl_opcode & IXL1394_OPTY_MASK) == 0)) {
157*0Sstevel@tonic-gate 			continue;
158*0Sstevel@tonic-gate 		}
159*0Sstevel@tonic-gate 
160*0Sstevel@tonic-gate 		/* get control struct for this xfer start ixl command */
161*0Sstevel@tonic-gate 		xferctlp = (hci1394_xfer_ctl_t *)ixlcur->compiler_privatep;
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate 		/* clear status in each hci descriptor block for this ixl cmd */
164*0Sstevel@tonic-gate 		ixldepth = 0;
165*0Sstevel@tonic-gate 		while (ixldepth < xferctlp->cnt) {
166*0Sstevel@tonic-gate 			(void) hci1394_ixl_check_status(
167*0Sstevel@tonic-gate 			    &xferctlp->dma[ixldepth], ixlcur->ixl_opcode,
168*0Sstevel@tonic-gate 			    &timestamp, B_TRUE);
169*0Sstevel@tonic-gate 			ixldepth++;
170*0Sstevel@tonic-gate 		}
171*0Sstevel@tonic-gate 	}
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_ixl_reset_status_exit,
174*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
175*0Sstevel@tonic-gate }
176*0Sstevel@tonic-gate #endif
177*0Sstevel@tonic-gate /*
178*0Sstevel@tonic-gate  * hci1394_ixl_find_next_exec_xfer()
179*0Sstevel@tonic-gate  *    Follows execution path of ixl linked list until finds next xfer start IXL
180*0Sstevel@tonic-gate  *    command, including the current IXL command or finds end of IXL linked
181*0Sstevel@tonic-gate  *    list. Counts callback commands found along the way. (Previously, counted
182*0Sstevel@tonic-gate  *    store timestamp commands, as well.)
183*0Sstevel@tonic-gate  *
184*0Sstevel@tonic-gate  *    To detect an infinite loop of label<->jump without an intervening xfer,
185*0Sstevel@tonic-gate  *    a tolerance level of HCI1394_IXL_MAX_SEQ_JUMPS is used.  Once this
186*0Sstevel@tonic-gate  *    number of jumps is traversed, the IXL prog is assumed to have a loop.
187*0Sstevel@tonic-gate  *
188*0Sstevel@tonic-gate  *    Returns DDI_SUCCESS or DDI_FAILURE.  DDI_FAILURE, indicates an infinite
189*0Sstevel@tonic-gate  *    loop of labels & jumps was detected without any intervening xfers.
190*0Sstevel@tonic-gate  *    DDI_SUCCESS indicates the next_exec_ixlpp contains the next xfer ixlp
191*0Sstevel@tonic-gate  *    address, or NULL indicating the end of the list was reached.  Note that
192*0Sstevel@tonic-gate  *    DDI_FAILURE can only be returned during the IXL compilation phase, and
193*0Sstevel@tonic-gate  *    not during ixl_update processing.
194*0Sstevel@tonic-gate  */
195*0Sstevel@tonic-gate int
hci1394_ixl_find_next_exec_xfer(ixl1394_command_t * ixl_start,uint_t * callback_cnt,ixl1394_command_t ** next_exec_ixlpp)196*0Sstevel@tonic-gate hci1394_ixl_find_next_exec_xfer(ixl1394_command_t *ixl_start,
197*0Sstevel@tonic-gate     uint_t *callback_cnt, ixl1394_command_t **next_exec_ixlpp)
198*0Sstevel@tonic-gate {
199*0Sstevel@tonic-gate 	uint16_t ixlopcode;
200*0Sstevel@tonic-gate 	boolean_t xferfound;
201*0Sstevel@tonic-gate 	ixl1394_command_t *ixlp;
202*0Sstevel@tonic-gate 	int ii;
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_ixl_find_next_exec_xfer_enter,
205*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
206*0Sstevel@tonic-gate 
207*0Sstevel@tonic-gate 	ixlp = ixl_start;
208*0Sstevel@tonic-gate 	xferfound = B_FALSE;
209*0Sstevel@tonic-gate 	ii = HCI1394_IXL_MAX_SEQ_JUMPS;
210*0Sstevel@tonic-gate 	if (callback_cnt != NULL) {
211*0Sstevel@tonic-gate 		*callback_cnt = 0;
212*0Sstevel@tonic-gate 	}
213*0Sstevel@tonic-gate 
214*0Sstevel@tonic-gate 	/* continue until xfer start ixl cmd or end of ixl list found */
215*0Sstevel@tonic-gate 	while ((xferfound == B_FALSE) && (ixlp != NULL) && (ii > 0)) {
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate 		/* get current ixl cmd opcode without update flag */
218*0Sstevel@tonic-gate 		ixlopcode = ixlp->ixl_opcode & ~IXL1394_OPF_UPDATE;
219*0Sstevel@tonic-gate 
220*0Sstevel@tonic-gate 		/* if found an xfer start ixl command, are done */
221*0Sstevel@tonic-gate 		if (((ixlopcode & IXL1394_OPF_ISXFER) != 0) &&
222*0Sstevel@tonic-gate 		    ((ixlopcode & IXL1394_OPTY_MASK) != 0)) {
223*0Sstevel@tonic-gate 			xferfound = B_TRUE;
224*0Sstevel@tonic-gate 			continue;
225*0Sstevel@tonic-gate 		}
226*0Sstevel@tonic-gate 
227*0Sstevel@tonic-gate 		/* if found jump command, adjust to follow its path */
228*0Sstevel@tonic-gate 		if (ixlopcode == IXL1394_OP_JUMP) {
229*0Sstevel@tonic-gate 			ixlp = (ixl1394_command_t *)
230*0Sstevel@tonic-gate 			    ((ixl1394_jump_t *)ixlp)->label;
231*0Sstevel@tonic-gate 			ii--;
232*0Sstevel@tonic-gate 
233*0Sstevel@tonic-gate 			/* if exceeded tolerance, give up */
234*0Sstevel@tonic-gate 			if (ii == 0) {
235*0Sstevel@tonic-gate 				TNF_PROBE_1(
236*0Sstevel@tonic-gate 				    hci1394_ixl_find_next_exec_xfer_error,
237*0Sstevel@tonic-gate 				    HCI1394_TNF_HAL_ERROR_ISOCH, "", tnf_string,
238*0Sstevel@tonic-gate 				    errmsg, "Infinite loop w/no xfers");
239*0Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(
240*0Sstevel@tonic-gate 				    hci1394_ixl_find_next_exec_xfer_exit,
241*0Sstevel@tonic-gate 				    HCI1394_TNF_HAL_STACK_ISOCH, "");
242*0Sstevel@tonic-gate 				return (DDI_FAILURE);
243*0Sstevel@tonic-gate 			}
244*0Sstevel@tonic-gate 			continue;
245*0Sstevel@tonic-gate 		}
246*0Sstevel@tonic-gate 
247*0Sstevel@tonic-gate 		/* if current ixl command is a callback, count it */
248*0Sstevel@tonic-gate 		if ((ixlopcode == IXL1394_OP_CALLBACK) &&
249*0Sstevel@tonic-gate 		    (callback_cnt != NULL)) {
250*0Sstevel@tonic-gate 			(*callback_cnt)++;
251*0Sstevel@tonic-gate 		}
252*0Sstevel@tonic-gate 
253*0Sstevel@tonic-gate 		/* advance to next linked ixl command */
254*0Sstevel@tonic-gate 		ixlp = ixlp->next_ixlp;
255*0Sstevel@tonic-gate 	}
256*0Sstevel@tonic-gate 
257*0Sstevel@tonic-gate 	/* return ixl xfer start command found, if any */
258*0Sstevel@tonic-gate 	*next_exec_ixlpp = ixlp;
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_ixl_find_next_exec_xfer_exit,
261*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
262*0Sstevel@tonic-gate 	return (DDI_SUCCESS);
263*0Sstevel@tonic-gate }
264*0Sstevel@tonic-gate #ifdef _KERNEL
265*0Sstevel@tonic-gate /*
266*0Sstevel@tonic-gate  * hci1394_ixl_check_status()
267*0Sstevel@tonic-gate  *    Read the descriptor status and hdrs, clear as appropriate.
268*0Sstevel@tonic-gate  */
269*0Sstevel@tonic-gate int32_t
hci1394_ixl_check_status(hci1394_xfer_ctl_dma_t * dma,uint16_t ixlopcode,uint16_t * timestamp,boolean_t do_status_reset)270*0Sstevel@tonic-gate hci1394_ixl_check_status(hci1394_xfer_ctl_dma_t *dma, uint16_t ixlopcode,
271*0Sstevel@tonic-gate     uint16_t *timestamp, boolean_t do_status_reset)
272*0Sstevel@tonic-gate {
273*0Sstevel@tonic-gate 	uint16_t	bufsiz;
274*0Sstevel@tonic-gate 	uint16_t	hcicnt;
275*0Sstevel@tonic-gate 	uint16_t	hcirecvcnt;
276*0Sstevel@tonic-gate 	hci1394_desc_t	*hcidescp;
277*0Sstevel@tonic-gate 	off_t		hcidesc_off;
278*0Sstevel@tonic-gate 	ddi_acc_handle_t	acc_hdl;
279*0Sstevel@tonic-gate 	ddi_dma_handle_t	dma_hdl;
280*0Sstevel@tonic-gate 	uint32_t		desc_status;
281*0Sstevel@tonic-gate 	uint32_t		desc_hdr;
282*0Sstevel@tonic-gate 	int			err;
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_ixl_check_status_enter,
285*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate 	/* last dma descriptor in descriptor block from dma structure */
288*0Sstevel@tonic-gate 	hcidescp = (hci1394_desc_t *)(dma->dma_descp);
289*0Sstevel@tonic-gate 	hcidesc_off = (off_t)hcidescp - (off_t)dma->dma_buf->bi_kaddr;
290*0Sstevel@tonic-gate 	acc_hdl  = dma->dma_buf->bi_handle;
291*0Sstevel@tonic-gate 	dma_hdl  = dma->dma_buf->bi_dma_handle;
292*0Sstevel@tonic-gate 
293*0Sstevel@tonic-gate 	/* if current ixl command opcode is xmit */
294*0Sstevel@tonic-gate 	if ((ixlopcode & IXL1394_OPF_ONXMIT) != 0) {
295*0Sstevel@tonic-gate 
296*0Sstevel@tonic-gate 		/* Sync the descriptor before we get the status */
297*0Sstevel@tonic-gate 		err = ddi_dma_sync(dma_hdl, hcidesc_off,
298*0Sstevel@tonic-gate 		    sizeof (hci1394_desc_t), DDI_DMA_SYNC_FORCPU);
299*0Sstevel@tonic-gate 		if (err != DDI_SUCCESS) {
300*0Sstevel@tonic-gate 			TNF_PROBE_1(hci1394_ixl_check_status_error,
301*0Sstevel@tonic-gate 			    HCI1394_TNF_HAL_ERROR_ISOCH, "", tnf_string, errmsg,
302*0Sstevel@tonic-gate 			    "dma_sync() failed");
303*0Sstevel@tonic-gate 		}
304*0Sstevel@tonic-gate 		desc_status = ddi_get32(acc_hdl, &hcidescp->status);
305*0Sstevel@tonic-gate 
306*0Sstevel@tonic-gate 		/* check if status is set in last dma descriptor in block */
307*0Sstevel@tonic-gate 		if ((desc_status & DESC_XFER_ACTIVE_MASK) != 0) {
308*0Sstevel@tonic-gate 			/*
309*0Sstevel@tonic-gate 			 * dma descriptor status set - I/O done.
310*0Sstevel@tonic-gate 			 * if not to reset status, just return; else extract
311*0Sstevel@tonic-gate 			 * timestamp, reset desc status and return dma
312*0Sstevel@tonic-gate 			 * descriptor block status set
313*0Sstevel@tonic-gate 			 */
314*0Sstevel@tonic-gate 			if (do_status_reset == B_FALSE) {
315*0Sstevel@tonic-gate 				return (1);
316*0Sstevel@tonic-gate 			}
317*0Sstevel@tonic-gate 			*timestamp = (uint16_t)
318*0Sstevel@tonic-gate 			    ((desc_status & DESC_ST_TIMESTAMP_MASK) >>
319*0Sstevel@tonic-gate 			    DESC_ST_TIMESTAMP_SHIFT);
320*0Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->status, 0);
321*0Sstevel@tonic-gate 
322*0Sstevel@tonic-gate 			/* Sync descriptor for device (status was cleared) */
323*0Sstevel@tonic-gate 			err = ddi_dma_sync(dma_hdl, hcidesc_off,
324*0Sstevel@tonic-gate 			    sizeof (hci1394_desc_t), DDI_DMA_SYNC_FORDEV);
325*0Sstevel@tonic-gate 			if (err != DDI_SUCCESS) {
326*0Sstevel@tonic-gate 				TNF_PROBE_1(hci1394_ixl_check_status_error,
327*0Sstevel@tonic-gate 				    HCI1394_TNF_HAL_ERROR_ISOCH, "", tnf_string,
328*0Sstevel@tonic-gate 				    errmsg, "dma_sync() failed");
329*0Sstevel@tonic-gate 			}
330*0Sstevel@tonic-gate 
331*0Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(hci1394_ixl_check_status_exit,
332*0Sstevel@tonic-gate 			    HCI1394_TNF_HAL_STACK_ISOCH, "");
333*0Sstevel@tonic-gate 			return (1);
334*0Sstevel@tonic-gate 		}
335*0Sstevel@tonic-gate 		/* else, return dma descriptor block status not set */
336*0Sstevel@tonic-gate 		TNF_PROBE_0_DEBUG(hci1394_ixl_check_status_exit,
337*0Sstevel@tonic-gate 		    HCI1394_TNF_HAL_STACK_ISOCH, "");
338*0Sstevel@tonic-gate 		return (0);
339*0Sstevel@tonic-gate 	}
340*0Sstevel@tonic-gate 
341*0Sstevel@tonic-gate 	/* else current ixl opcode is recv */
342*0Sstevel@tonic-gate 	hcirecvcnt = 0;
343*0Sstevel@tonic-gate 
344*0Sstevel@tonic-gate 	/* get count of descriptors in current dma descriptor block */
345*0Sstevel@tonic-gate 	hcicnt = dma->dma_bound & DESC_Z_MASK;
346*0Sstevel@tonic-gate 	hcidescp -= (hcicnt - 1);
347*0Sstevel@tonic-gate 	hcidesc_off = (off_t)hcidescp - (off_t)dma->dma_buf->bi_kaddr;
348*0Sstevel@tonic-gate 
349*0Sstevel@tonic-gate 	/* iterate fwd through hci descriptors until end or find status set */
350*0Sstevel@tonic-gate 	while (hcicnt-- != 0) {
351*0Sstevel@tonic-gate 
352*0Sstevel@tonic-gate 		/* Sync the descriptor before we get the status */
353*0Sstevel@tonic-gate 		err = ddi_dma_sync(dma_hdl, hcidesc_off,
354*0Sstevel@tonic-gate 		    hcicnt * sizeof (hci1394_desc_t), DDI_DMA_SYNC_FORCPU);
355*0Sstevel@tonic-gate 		if (err != DDI_SUCCESS) {
356*0Sstevel@tonic-gate 			TNF_PROBE_1(hci1394_ixl_check_status_error,
357*0Sstevel@tonic-gate 			    HCI1394_TNF_HAL_ERROR_ISOCH, "", tnf_string, errmsg,
358*0Sstevel@tonic-gate 			    "dma_sync() failed");
359*0Sstevel@tonic-gate 		}
360*0Sstevel@tonic-gate 
361*0Sstevel@tonic-gate 		desc_hdr = ddi_get32(acc_hdl, &hcidescp->hdr);
362*0Sstevel@tonic-gate 
363*0Sstevel@tonic-gate 		/* get cur buffer size & accumulate potential buffr usage */
364*0Sstevel@tonic-gate 		bufsiz = (desc_hdr & DESC_HDR_REQCOUNT_MASK) >>
365*0Sstevel@tonic-gate 		    DESC_HDR_REQCOUNT_SHIFT;
366*0Sstevel@tonic-gate 		hcirecvcnt += bufsiz;
367*0Sstevel@tonic-gate 
368*0Sstevel@tonic-gate 		desc_status = ddi_get32(acc_hdl, &hcidescp->status);
369*0Sstevel@tonic-gate 
370*0Sstevel@tonic-gate 		/* check if status set on this descriptor block descriptor */
371*0Sstevel@tonic-gate 		if ((desc_status & DESC_XFER_ACTIVE_MASK) != 0) {
372*0Sstevel@tonic-gate 			/*
373*0Sstevel@tonic-gate 			 * dma descriptor status set - I/O done.
374*0Sstevel@tonic-gate 			 * if not to reset status, just return; else extract
375*0Sstevel@tonic-gate 			 * buffer space used, reset desc status and return dma
376*0Sstevel@tonic-gate 			 * descriptor block status set
377*0Sstevel@tonic-gate 			 */
378*0Sstevel@tonic-gate 			if (do_status_reset == B_FALSE) {
379*0Sstevel@tonic-gate 				TNF_PROBE_0_DEBUG(hci1394_ixl_check_status_exit,
380*0Sstevel@tonic-gate 				    HCI1394_TNF_HAL_STACK_ISOCH, "");
381*0Sstevel@tonic-gate 				return (1);
382*0Sstevel@tonic-gate 			}
383*0Sstevel@tonic-gate 
384*0Sstevel@tonic-gate 			hcirecvcnt -= (desc_status & DESC_ST_RESCOUNT_MASK) >>
385*0Sstevel@tonic-gate 			    DESC_ST_RESCOUNT_SHIFT;
386*0Sstevel@tonic-gate 			*timestamp = hcirecvcnt;
387*0Sstevel@tonic-gate 			desc_status = (bufsiz << DESC_ST_RESCOUNT_SHIFT) &
388*0Sstevel@tonic-gate 			    DESC_ST_RESCOUNT_MASK;
389*0Sstevel@tonic-gate 			ddi_put32(acc_hdl, &hcidescp->status, desc_status);
390*0Sstevel@tonic-gate 
391*0Sstevel@tonic-gate 			/* Sync descriptor for device (status was cleared) */
392*0Sstevel@tonic-gate 			err = ddi_dma_sync(dma_hdl, hcidesc_off,
393*0Sstevel@tonic-gate 			    sizeof (hci1394_desc_t), DDI_DMA_SYNC_FORDEV);
394*0Sstevel@tonic-gate 			if (err != DDI_SUCCESS) {
395*0Sstevel@tonic-gate 				TNF_PROBE_1(hci1394_ixl_check_status_error,
396*0Sstevel@tonic-gate 				    HCI1394_TNF_HAL_ERROR_ISOCH, "", tnf_string,
397*0Sstevel@tonic-gate 				    errmsg, "dma_sync() failed");
398*0Sstevel@tonic-gate 			}
399*0Sstevel@tonic-gate 
400*0Sstevel@tonic-gate 			TNF_PROBE_0_DEBUG(hci1394_ixl_check_status_exit,
401*0Sstevel@tonic-gate 			    HCI1394_TNF_HAL_STACK_ISOCH, "");
402*0Sstevel@tonic-gate 			return (1);
403*0Sstevel@tonic-gate 		} else {
404*0Sstevel@tonic-gate 			/* else, set to evaluate next descriptor. */
405*0Sstevel@tonic-gate 			hcidescp++;
406*0Sstevel@tonic-gate 			hcidesc_off = (off_t)hcidescp -
407*0Sstevel@tonic-gate 						(off_t)dma->dma_buf->bi_kaddr;
408*0Sstevel@tonic-gate 		}
409*0Sstevel@tonic-gate 	}
410*0Sstevel@tonic-gate 
411*0Sstevel@tonic-gate 	/* return input not complete status */
412*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_ixl_check_status_exit,
413*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
414*0Sstevel@tonic-gate 	return (0);
415*0Sstevel@tonic-gate }
416*0Sstevel@tonic-gate #endif
417*0Sstevel@tonic-gate /*
418*0Sstevel@tonic-gate  * hci1394_ixl_cleanup()
419*0Sstevel@tonic-gate  *    Delete all memory that has earlier been allocated for a context's IXL prog
420*0Sstevel@tonic-gate  */
421*0Sstevel@tonic-gate void
hci1394_ixl_cleanup(hci1394_state_t * soft_statep,hci1394_iso_ctxt_t * ctxtp)422*0Sstevel@tonic-gate hci1394_ixl_cleanup(hci1394_state_t *soft_statep, hci1394_iso_ctxt_t *ctxtp)
423*0Sstevel@tonic-gate {
424*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_ixl_cleanup_enter,
425*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
426*0Sstevel@tonic-gate 
427*0Sstevel@tonic-gate 	hci1394_delete_xfer_ctl((hci1394_xfer_ctl_t *)ctxtp->xcs_firstp);
428*0Sstevel@tonic-gate 	hci1394_delete_dma_desc_mem(soft_statep, ctxtp->dma_firstp);
429*0Sstevel@tonic-gate 
430*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_ixl_cleanup_exit,
431*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
432*0Sstevel@tonic-gate }
433*0Sstevel@tonic-gate 
434*0Sstevel@tonic-gate /*
435*0Sstevel@tonic-gate  * hci1394_delete_dma_desc_mem()
436*0Sstevel@tonic-gate  *    Iterate through linked list of dma memory descriptors, deleting
437*0Sstevel@tonic-gate  *    allocated dma memory blocks, then deleting the dma memory
438*0Sstevel@tonic-gate  *    descriptor after advancing to next one
439*0Sstevel@tonic-gate  */
440*0Sstevel@tonic-gate static void
441*0Sstevel@tonic-gate /* ARGSUSED */
hci1394_delete_dma_desc_mem(hci1394_state_t * soft_statep,hci1394_idma_desc_mem_t * dma_firstp)442*0Sstevel@tonic-gate hci1394_delete_dma_desc_mem(hci1394_state_t *soft_statep,
443*0Sstevel@tonic-gate     hci1394_idma_desc_mem_t *dma_firstp)
444*0Sstevel@tonic-gate {
445*0Sstevel@tonic-gate 	hci1394_idma_desc_mem_t *dma_next;
446*0Sstevel@tonic-gate 
447*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_delete_dma_desc_mem_enter,
448*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
449*0Sstevel@tonic-gate 
450*0Sstevel@tonic-gate 	while (dma_firstp != NULL) {
451*0Sstevel@tonic-gate 		dma_next = dma_firstp->dma_nextp;
452*0Sstevel@tonic-gate #ifdef _KERNEL
453*0Sstevel@tonic-gate 		/*
454*0Sstevel@tonic-gate 		 * if this dma descriptor memory block has the handles, then
455*0Sstevel@tonic-gate 		 * free the memory.  (Note that valid handles are kept only with
456*0Sstevel@tonic-gate 		 * the most recently acquired cookie, and that each cookie is in
457*0Sstevel@tonic-gate 		 * it's own idma_desc_mem_t struct.)
458*0Sstevel@tonic-gate 		 */
459*0Sstevel@tonic-gate 		if (dma_firstp->mem_handle != NULL) {
460*0Sstevel@tonic-gate 			hci1394_buf_free(&dma_firstp->mem_handle);
461*0Sstevel@tonic-gate 		}
462*0Sstevel@tonic-gate 
463*0Sstevel@tonic-gate 		/* free current dma memory descriptor */
464*0Sstevel@tonic-gate 		kmem_free(dma_firstp, sizeof (hci1394_idma_desc_mem_t));
465*0Sstevel@tonic-gate #else
466*0Sstevel@tonic-gate 		/* user mode free */
467*0Sstevel@tonic-gate 		/* free dma memory block and current dma mem descriptor */
468*0Sstevel@tonic-gate 		free(dma_firstp->mem.bi_kaddr);
469*0Sstevel@tonic-gate 		free(dma_firstp);
470*0Sstevel@tonic-gate #endif
471*0Sstevel@tonic-gate 		/* advance to next dma memory descriptor */
472*0Sstevel@tonic-gate 		dma_firstp = dma_next;
473*0Sstevel@tonic-gate 	}
474*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_delete_dma_desc_mem_exit,
475*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
476*0Sstevel@tonic-gate }
477*0Sstevel@tonic-gate 
478*0Sstevel@tonic-gate /*
479*0Sstevel@tonic-gate  * hci1394_delete_xfer_ctl()
480*0Sstevel@tonic-gate  *    Iterate thru linked list of xfer_ctl structs, deleting allocated memory.
481*0Sstevel@tonic-gate  */
482*0Sstevel@tonic-gate void
hci1394_delete_xfer_ctl(hci1394_xfer_ctl_t * xcsp)483*0Sstevel@tonic-gate hci1394_delete_xfer_ctl(hci1394_xfer_ctl_t *xcsp)
484*0Sstevel@tonic-gate {
485*0Sstevel@tonic-gate 	hci1394_xfer_ctl_t *delp;
486*0Sstevel@tonic-gate 
487*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_delete_xfer_ctl_enter,
488*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
489*0Sstevel@tonic-gate 
490*0Sstevel@tonic-gate 	while ((delp = xcsp) != NULL) {
491*0Sstevel@tonic-gate 		/* advance ptr to next xfer_ctl struct */
492*0Sstevel@tonic-gate 		xcsp = xcsp->ctl_nextp;
493*0Sstevel@tonic-gate 
494*0Sstevel@tonic-gate 		/*
495*0Sstevel@tonic-gate 		 * delete current xfer_ctl struct and included
496*0Sstevel@tonic-gate 		 * xfer_ctl_dma structs
497*0Sstevel@tonic-gate 		 */
498*0Sstevel@tonic-gate #ifdef _KERNEL
499*0Sstevel@tonic-gate 		kmem_free(delp,
500*0Sstevel@tonic-gate 		    sizeof (hci1394_xfer_ctl_t) +
501*0Sstevel@tonic-gate 		    sizeof (hci1394_xfer_ctl_dma_t) * (delp->cnt - 1));
502*0Sstevel@tonic-gate #else
503*0Sstevel@tonic-gate 		free(delp);
504*0Sstevel@tonic-gate #endif
505*0Sstevel@tonic-gate 	}
506*0Sstevel@tonic-gate 	TNF_PROBE_0_DEBUG(hci1394_delete_xfer_ctl_exit,
507*0Sstevel@tonic-gate 	    HCI1394_TNF_HAL_STACK_ISOCH, "");
508*0Sstevel@tonic-gate }
509