xref: /titanic_51/usr/src/uts/common/io/1394/targets/av1394/av1394_isoch_xmit.c (revision 47cd5876b2168926dea28a62f1857b167da29d6c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * av1394 isochronous transmit module
28  */
29 #include <sys/1394/targets/av1394/av1394_impl.h>
30 
31 static int	av1394_it_start_common(av1394_ic_t *);
32 
33 /* configuration routines */
34 static void	av1394_it_cleanup(av1394_ic_t *, int);
35 static int	av1394_it_bld_ixl(av1394_ic_t *);
36 static void	av1394_it_destroy_ixl(av1394_ic_t *);
37 static int	av1394_it_ixl_bld_data(av1394_ic_t *);
38 static void	av1394_it_ixl_destroy_data(av1394_ic_t *);
39 static av1394_it_ixl_buf_t *av1394_it_ixl_bld_buf(av1394_ic_t *, int, int,
40 		off_t, int, int);
41 static void	av1394_it_ixl_complete_buf(av1394_it_ixl_buf_t *,
42 		av1394_it_ixl_empty_cip_t *);
43 static void	av1394_it_ixl_complete_buf2(av1394_it_ixl_buf_t *,
44 		av1394_it_ixl_buf_t *);
45 static av1394_it_ixl_empty_cip_t *av1394_it_ixl_bld_empty_cip(av1394_ic_t *,
46 		int);
47 static void	av1394_it_ixl_complete_empty_cip(av1394_it_ixl_empty_cip_t *,
48 		av1394_it_ixl_buf_t *);
49 static void	av1394_it_ixl_bld_begin(av1394_ic_t *);
50 static void	av1394_it_ixl_begin_update_pkts(av1394_ic_t *,
51 		av1394_it_ixl_buf_t *);
52 static int	av1394_it_alloc_isoch_dma(av1394_ic_t *);
53 static void	av1394_it_free_isoch_dma(av1394_ic_t *);
54 static void	av1394_it_dma_sync_frames(av1394_ic_t *, int, int);
55 
56 /* callbacks */
57 static void	av1394_it_ixl_begin_cb(opaque_t, struct ixl1394_callback *);
58 static void	av1394_it_ixl_buf_cb(opaque_t, struct ixl1394_callback *);
59 static void	av1394_it_ixl_eof_cb(av1394_it_ixl_buf_t *bp);
60 static int	av1394_it_underrun_resume(av1394_ic_t *);
61 static void	av1394_it_dma_stopped_cb(t1394_isoch_dma_handle_t,
62 		opaque_t, id1394_isoch_dma_stopped_t);
63 
64 /* data transfer routines */
65 static int	av1394_it_add_frames(av1394_ic_t *, int, int);
66 static int	av1394_it_wait_frames(av1394_ic_t *, int *, int *, int *);
67 
68 static void	av1394_it_update_frame_syt(av1394_ic_t *, int, int, uint16_t);
69 static uint16_t	av1394_it_ts_cyc2syt(uint16_t);
70 static uint16_t	av1394_it_ts_syt_inc(uint16_t, uint16_t);
71 
72 static void	av1394_it_kcopyin(av1394_ic_t *, void *, size_t);
73 static int	av1394_it_copyin(av1394_ic_t *, struct uio *, int *, int);
74 static boolean_t av1394_it_is_dv_frame_start(caddr_t);
75 static void	av1394_it_reset_frame_syt(av1394_ic_t *, int);
76 
77 /* tunables */
78 int av1394_it_hiwat_sub = 2;
79 int av1394_it_lowat = 3;
80 int av1394_it_start_thre = 3;	/* xmit start threshold */
81 int av1394_it_syt_off = 3;	/* SYT offset in cycles */
82 int av1394_it_dump_ixl = 0;
83 
84 #define	AV1394_TNF_ENTER(func)	\
85 	TNF_PROBE_0_DEBUG(func##_enter, AV1394_TNF_ISOCH_STACK, "");
86 
87 #define	AV1394_TNF_EXIT(func)	\
88 	TNF_PROBE_0_DEBUG(func##_exit, AV1394_TNF_ISOCH_STACK, "");
89 
90 int
91 av1394_it_init(av1394_ic_t *icp, int *error)
92 {
93 	av1394_it_t	*itp = &icp->ic_it;
94 	av1394_isoch_pool_t *pool = &itp->it_data_pool;
95 	int		nframes;
96 
97 	AV1394_TNF_ENTER(av1394_it_init);
98 
99 	nframes = av1394_ic_alloc_pool(pool, icp->ic_framesz, icp->ic_nframes,
100 	    AV1394_IT_NFRAMES_MIN);
101 	if (nframes == 0) {
102 		*error = IEC61883_ERR_NOMEM;
103 		AV1394_TNF_EXIT(av1394_it_init);
104 		return (EINVAL);
105 	}
106 	mutex_enter(&icp->ic_mutex);
107 	icp->ic_nframes = nframes;
108 	itp->it_hiwat = nframes - av1394_it_hiwat_sub;
109 	itp->it_lowat = av1394_it_lowat;
110 	itp->it_start_thre = av1394_it_start_thre;
111 	itp->it_nempty = icp->ic_nframes;
112 	itp->it_last_full = icp->ic_nframes - 1;
113 
114 	if (av1394_ic_dma_setup(icp, pool) != DDI_SUCCESS) {
115 		mutex_exit(&icp->ic_mutex);
116 		*error = IEC61883_ERR_NOMEM;
117 		av1394_it_cleanup(icp, 1);
118 		AV1394_TNF_EXIT(av1394_it_init);
119 		return (EINVAL);
120 	}
121 
122 	if (av1394_it_bld_ixl(icp) != DDI_SUCCESS) {
123 		mutex_exit(&icp->ic_mutex);
124 		*error = IEC61883_ERR_NOMEM;
125 		av1394_it_cleanup(icp, 2);
126 		AV1394_TNF_EXIT(av1394_it_init);
127 		return (EINVAL);
128 	}
129 	mutex_exit(&icp->ic_mutex);
130 
131 	if (av1394_it_alloc_isoch_dma(icp) != DDI_SUCCESS) {
132 		*error = IEC61883_ERR_NOMEM;
133 		av1394_it_cleanup(icp, 3);
134 		AV1394_TNF_EXIT(av1394_it_init);
135 		return (EINVAL);
136 	}
137 
138 	AV1394_TNF_EXIT(av1394_it_init);
139 	return (0);
140 }
141 
142 void
143 av1394_it_fini(av1394_ic_t *icp)
144 {
145 	AV1394_TNF_ENTER(av1394_it_fini);
146 
147 	av1394_it_cleanup(icp, AV1394_CLEANUP_LEVEL_MAX);
148 
149 	AV1394_TNF_ENTER(av1394_it_fini);
150 }
151 
152 int
153 av1394_it_start(av1394_ic_t *icp)
154 {
155 	av1394_it_t	*itp = &icp->ic_it;
156 	int		ret = 0;
157 
158 	AV1394_TNF_ENTER(av1394_it_start);
159 
160 	mutex_enter(&icp->ic_mutex);
161 	ASSERT(icp->ic_state == AV1394_IC_IDLE);
162 
163 	/* should be enough full frames to be able to start */
164 	if (itp->it_nfull >= itp->it_start_thre) {
165 		ret = av1394_it_start_common(icp);
166 	}
167 	mutex_exit(&icp->ic_mutex);
168 
169 	AV1394_TNF_EXIT(av1394_it_start);
170 	return (ret);
171 }
172 
173 static int
174 av1394_it_start_common(av1394_ic_t *icp)
175 {
176 	av1394_inst_t	*avp = icp->ic_avp;
177 	id1394_isoch_dma_ctrlinfo_t idma_ctrlinfo = { 0 };
178 	int		result;
179 	int		err;
180 	int		ret = 0;
181 
182 	ASSERT(icp->ic_state == AV1394_IC_IDLE);
183 
184 	err = t1394_start_isoch_dma(avp->av_t1394_hdl, icp->ic_isoch_hdl,
185 	    &idma_ctrlinfo, 0, &result);
186 	if (err == DDI_SUCCESS) {
187 		icp->ic_state = AV1394_IC_DMA;
188 	} else {
189 		TNF_PROBE_1(av1394_it_start_common_error,
190 		    AV1394_TNF_ISOCH_ERROR, "", tnf_int, result, result);
191 		ret = EIO;
192 	}
193 
194 	return (ret);
195 }
196 
197 
198 int
199 av1394_it_stop(av1394_ic_t *icp)
200 {
201 	av1394_inst_t	*avp = icp->ic_avp;
202 	av1394_it_t	*itp = &icp->ic_it;
203 
204 	AV1394_TNF_ENTER(av1394_it_stop);
205 
206 	mutex_enter(&icp->ic_mutex);
207 	if (icp->ic_state != AV1394_IC_IDLE) {
208 		mutex_exit(&icp->ic_mutex);
209 		t1394_stop_isoch_dma(avp->av_t1394_hdl, icp->ic_isoch_hdl, 0);
210 		mutex_enter(&icp->ic_mutex);
211 
212 		icp->ic_state = AV1394_IC_IDLE;
213 		itp->it_nempty = icp->ic_nframes;
214 		itp->it_first_empty = 0;
215 		itp->it_last_full = icp->ic_nframes - 1;
216 		itp->it_nfull = 0;
217 	}
218 	mutex_exit(&icp->ic_mutex);
219 
220 	AV1394_TNF_EXIT(av1394_it_stop);
221 	return (0);
222 }
223 
224 int
225 av1394_it_xmit(av1394_ic_t *icp, iec61883_xmit_t *xmit)
226 {
227 	av1394_it_t	*itp = &icp->ic_it;
228 	int		ret = 0;
229 	int		idx, cnt;
230 
231 	idx = xmit->tx_xfer.xf_full_idx;
232 	cnt = xmit->tx_xfer.xf_full_cnt;
233 
234 	mutex_enter(&icp->ic_mutex);
235 	/* check arguments */
236 	if ((idx < 0) || (cnt < 0) || (cnt > itp->it_nempty)) {
237 		mutex_exit(&icp->ic_mutex);
238 		TNF_PROBE_2(av1394_it_xmit_error_args, AV1394_TNF_ISOCH_ERROR,
239 		    "", tnf_int, idx, idx, tnf_int, cnt, cnt);
240 		return (EINVAL);
241 	}
242 
243 	/* add full frames to the pool */
244 	if (cnt > 0) {
245 		if ((ret = av1394_it_add_frames(icp, idx, cnt)) != 0) {
246 			mutex_exit(&icp->ic_mutex);
247 			return (ret);
248 		}
249 	}
250 
251 	if ((icp->ic_state == AV1394_IC_IDLE) &&
252 	    (itp->it_nfull >= itp->it_start_thre)) {
253 		if ((ret = av1394_it_start_common(icp)) != 0) {
254 			mutex_exit(&icp->ic_mutex);
255 			return (ret);
256 		}
257 	}
258 
259 	/* wait for new empty frames */
260 	ret = av1394_it_wait_frames(icp, &xmit->tx_xfer.xf_empty_idx,
261 	    &xmit->tx_xfer.xf_empty_cnt, &xmit->tx_miss_cnt);
262 	mutex_exit(&icp->ic_mutex);
263 
264 	return (ret);
265 }
266 
267 int
268 av1394_it_write(av1394_ic_t *icp, struct uio *uiop)
269 {
270 	av1394_inst_t	*avp = icp->ic_avp;
271 	av1394_it_t	*itp = &icp->ic_it;
272 	av1394_isoch_autoxmit_t *axp = &avp->av_i.i_autoxmit;
273 	int		dv;
274 	int		ret = 0;
275 	int		full_cnt;
276 	int		miss_cnt;
277 
278 	AV1394_TNF_ENTER(av1394_it_write);
279 
280 	mutex_enter(&icp->ic_mutex);
281 	dv = (axp->ax_fmt & AV1394_ISOCH_AUTOXMIT_DV);
282 
283 	while (uiop->uio_resid > 0) {
284 		/* must have at least one empty frame */
285 		if (itp->it_write_cnt == 0) {
286 			ret = av1394_it_wait_frames(icp, &itp->it_write_idx,
287 			    &itp->it_write_cnt, &miss_cnt);
288 			if (ret != 0) {
289 				break;
290 			}
291 		}
292 
293 		/* copyin as much data as we can */
294 		if (axp->ax_copy_ciph) {
295 			ASSERT(itp->it_write_off == 0);
296 			av1394_it_kcopyin(icp, axp->ax_ciph, AV1394_CIPSZ);
297 			axp->ax_copy_ciph = B_FALSE;
298 		}
299 		if ((ret = av1394_it_copyin(icp, uiop, &full_cnt, dv)) != 0) {
300 			break;
301 		}
302 
303 		/* add full frames to the pool */
304 		if (full_cnt > 0) {
305 			ret = av1394_it_add_frames(icp,
306 			    itp->it_write_idx, full_cnt);
307 			if (ret != 0) {
308 				break;
309 			}
310 			itp->it_write_idx += full_cnt;
311 			itp->it_write_idx %= icp->ic_nframes;
312 		}
313 
314 		/* start xfer if not already */
315 		if ((icp->ic_state == AV1394_IC_IDLE) &&
316 		    (itp->it_nfull >= itp->it_start_thre)) {
317 			if ((ret = av1394_it_start_common(icp)) != 0) {
318 				mutex_exit(&icp->ic_mutex);
319 				AV1394_TNF_EXIT(av1394_it_write);
320 				return (ret);
321 			}
322 		}
323 	}
324 	mutex_exit(&icp->ic_mutex);
325 
326 	AV1394_TNF_EXIT(av1394_it_write);
327 	return (ret);
328 }
329 
330 /*
331  *
332  * --- configuration routines
333  *
334  */
335 static void
336 av1394_it_cleanup(av1394_ic_t *icp, int level)
337 {
338 	av1394_isoch_pool_t *pool = &icp->ic_it.it_data_pool;
339 
340 	ASSERT((level > 0) && (level <= AV1394_CLEANUP_LEVEL_MAX));
341 
342 	switch (level) {
343 	default:
344 		av1394_it_free_isoch_dma(icp);
345 		/* FALLTHRU */
346 	case 3:
347 		av1394_it_destroy_ixl(icp);
348 		/* FALLTHRU */
349 	case 2:
350 		av1394_ic_dma_cleanup(icp, pool);
351 		/* FALLTHRU */
352 	case 1:
353 		av1394_ic_free_pool(pool);
354 		/* FALLTHRU */
355 	}
356 }
357 
358 /*
359  * av1394_it_bld_ixl()
360  *    Build an IXL chain out of several blocks.
361  */
362 static int
363 av1394_it_bld_ixl(av1394_ic_t *icp)
364 {
365 	av1394_it_t	*itp = &icp->ic_it;
366 	int		ret;
367 
368 	AV1394_TNF_ENTER(av1394_it_bld_ixl);
369 
370 	/* data block */
371 	if ((ret = av1394_it_ixl_bld_data(icp)) != DDI_SUCCESS) {
372 		AV1394_TNF_EXIT(av1394_it_bld_ixl);
373 		return (ret);
374 	}
375 
376 	/* begin block */
377 	if (icp->ic_param.cp_ts_mode != IEC61883_TS_NONE) {
378 		av1394_it_ixl_bld_begin(icp);
379 
380 		itp->it_ixlp = (ixl1394_command_t *)&itp->it_ixl_begin;
381 	} else {
382 		itp->it_ixlp = (ixl1394_command_t *)
383 		    &((av1394_it_ixl_buf_t *)itp->it_ixl_data)->tb_label;
384 	}
385 
386 	if (av1394_it_dump_ixl) {
387 		av1394_ic_ixl_dump(itp->it_ixlp);
388 	}
389 
390 	AV1394_TNF_EXIT(av1394_it_bld_ixl);
391 	return (ret);
392 }
393 
394 static void
395 av1394_it_destroy_ixl(av1394_ic_t *icp)
396 {
397 	av1394_it_t	*itp = &icp->ic_it;
398 
399 	av1394_it_ixl_destroy_data(icp);
400 	itp->it_ixlp = NULL;
401 }
402 
403 /*
404  * build data transmit part of the IXL chain
405  */
406 static int
407 av1394_it_ixl_bld_data(av1394_ic_t *icp)
408 {
409 	av1394_it_t		*itp = &icp->ic_it;
410 	av1394_isoch_pool_t	*pool = &itp->it_data_pool;
411 	int			total = 0;	/* # of pkts in the chain */
412 	int			nfull = 0;	/* # of full CIPs in a series */
413 	int			framenum = -1;	/* frame number */
414 	int			bufsz_max;	/* max buffer size in pkts */
415 	int			segnum = 0;	/* current segment number */
416 	int			segsz;		/* segment size in pkts */
417 	off_t			segoff = 0;	/* segment offset in pkts */
418 	av1394_it_ixl_empty_cip_t *ep = NULL;	/* last empty CIP */
419 	av1394_it_ixl_buf_t	*bp = NULL;	/* last data buffer */
420 	av1394_it_ixl_buf_t	*prevbp = NULL;
421 	int			a, n, d;	/* N/D algorithm variables */
422 	int			type, ptype;	/* current and prev CIP type */
423 	int			tb_flags;
424 
425 	itp->it_frame_info = kmem_zalloc(icp->ic_nframes *
426 	    sizeof (av1394_it_frame_info_t), KM_SLEEP);
427 
428 	bufsz_max = AV1394_IXL_BUFSZ_MAX / icp->ic_pktsz;
429 	n = icp->ic_param.cp_n;
430 	d = icp->ic_param.cp_d;
431 	/*
432 	 * following assert guarantees no more than one empty CIP in a row,
433 	 * i.e. empty CIPs account for <=50% of all packets.
434 	 * this should be ensured by ioctl argument validation.
435 	 */
436 	ASSERT((n == 0) || (d / n > 1));
437 	/*
438 	 * build the chain. it is hard to precalculate amount of memory
439 	 * needed for the entire chain, so we simply allocate as we go.
440 	 */
441 	ptype = AV1394_CIP_EMPTY;
442 	segsz = pool->ip_seg[0].is_size / icp->ic_pktsz;
443 	a = n;
444 	while (total < icp->ic_nframes * icp->ic_npkts) {
445 		/* insert empty CIPs using N/D algorithm */
446 		a += n;
447 		if (a > d) {
448 			a -= d;
449 			type = AV1394_CIP_EMPTY;
450 		} else {
451 			type = AV1394_CIP_FULL;
452 			nfull++;
453 		}
454 
455 		/*
456 		 * merge series of full packets into single SEND_BUF commands.
457 		 * a series can be terminated by:
458 		 *  - an empty CIP;
459 		 *  - series buffer size reached maximum;
460 		 *  - end of isoch segment;
461 		 *  - end of frame (which is always at the end of segment);
462 		 */
463 		if (((type == AV1394_CIP_EMPTY) || (segoff + nfull == segsz) ||
464 		    (nfull == bufsz_max)) && (nfull > 0)) {
465 
466 			/* build buffer block */
467 			prevbp = bp;
468 			tb_flags = 0;
469 			if (type == AV1394_CIP_EMPTY) {
470 				tb_flags |= AV1394_IT_IXL_BUF_NEXT_EMPTY;
471 			}
472 			if (total % icp->ic_npkts == 0) {
473 				tb_flags |= AV1394_IT_IXL_BUF_SOF;
474 				framenum++;
475 			}
476 			if ((total + nfull) % icp->ic_npkts == 0) {
477 				tb_flags |= AV1394_IT_IXL_BUF_EOF;
478 			}
479 			bp = av1394_it_ixl_bld_buf(icp, nfull, segnum, segoff,
480 			    tb_flags, framenum);
481 
482 			if (itp->it_ixl_data == NULL) {
483 				itp->it_ixl_data = &bp->tb_common;
484 			}
485 
486 			/* complete previous empty CIP or a buffer */
487 			if (ep) {
488 				av1394_it_ixl_complete_empty_cip(ep, bp);
489 				ep = NULL;
490 			} else if (prevbp) {
491 				av1394_it_ixl_complete_buf2(prevbp, bp);
492 			}
493 
494 			/* if current segment is used up, pick next one */
495 			segoff += nfull;
496 			if (segoff == segsz) {
497 				if (++segnum < pool->ip_nsegs) {
498 					segsz = pool->ip_seg[segnum].is_size /
499 					    icp->ic_pktsz;
500 				}
501 				segoff = 0;
502 			}
503 
504 			total += nfull;
505 			nfull = 0;
506 		}
507 		/* insert an empty packet if needed */
508 		if (type == AV1394_CIP_EMPTY) {
509 			ep = av1394_it_ixl_bld_empty_cip(icp, framenum);
510 			av1394_it_ixl_complete_buf(bp, ep);
511 		}
512 		ptype = type;
513 	}
514 	ASSERT(nfull == 0);
515 
516 	/* last packet must be an empty CIP, except when n == 0 */
517 	if (n != 0) {
518 		if (ptype != AV1394_CIP_EMPTY) {
519 			ep = av1394_it_ixl_bld_empty_cip(icp, framenum);
520 			av1394_it_ixl_complete_buf(bp, ep);
521 		}
522 		av1394_it_ixl_complete_empty_cip(ep,
523 		    (av1394_it_ixl_buf_t *)itp->it_ixl_data);
524 		ep->te_jump.next_ixlp = NULL;
525 		ep->te_common.tc_next = NULL;
526 	} else {
527 		bp->tb_jump.label = (ixl1394_command_t *)
528 		    &(((av1394_it_ixl_buf_t *)itp->it_ixl_data)->tb_label);
529 	}
530 
531 	return (DDI_SUCCESS);
532 }
533 
534 static void
535 av1394_it_ixl_destroy_data(av1394_ic_t *icp)
536 {
537 	av1394_it_t		*itp = &icp->ic_it;
538 	av1394_it_ixl_common_t	*cmd, *cmd_next;
539 
540 	for (cmd = itp->it_ixl_data; cmd != NULL; cmd = cmd_next) {
541 		cmd_next = cmd->tc_next;
542 		kmem_free(cmd, cmd->tc_size);
543 	}
544 	itp->it_ixl_data = NULL;
545 
546 	kmem_free(itp->it_frame_info,
547 	    icp->ic_nframes * sizeof (av1394_it_frame_info_t));
548 }
549 
550 static av1394_it_ixl_buf_t *
551 av1394_it_ixl_bld_buf(av1394_ic_t *icp, int cnt, int segnum, off_t off,
552 		int flags, int framenum)
553 {
554 	av1394_it_t		*itp = &icp->ic_it;
555 	av1394_isoch_seg_t	*isp = &itp->it_data_pool.ip_seg[segnum];
556 	av1394_it_ixl_buf_t	*bp;
557 	int			pktsz = icp->ic_pktsz;
558 
559 	bp = kmem_zalloc(sizeof (av1394_it_ixl_buf_t), KM_SLEEP);
560 	bp->tb_common.tc_size = sizeof (av1394_it_ixl_buf_t);
561 	/* tc_next later */
562 	bp->tb_flags = flags;
563 	bp->tb_framenum = framenum;
564 	bp->tb_icp = icp;
565 
566 	bp->tb_label.ixl_opcode = IXL1394_OP_LABEL;
567 	bp->tb_label.next_ixlp = (ixl1394_command_t *)&bp->tb_buf;
568 
569 	bp->tb_buf.ixl_opcode = IXL1394_OP_SEND_BUF;
570 	bp->tb_buf.pkt_size = pktsz;
571 	bp->tb_buf.size = cnt * pktsz;
572 	bp->tb_buf.ixl_buf._dmac_ll =
573 	    isp->is_dma_cookie[0].dmac_laddress + off * pktsz;
574 	bp->tb_buf.mem_bufp = isp->is_kaddr + off * pktsz;
575 
576 	if (flags & AV1394_IT_IXL_BUF_EOF) {
577 		bp->tb_buf.next_ixlp = (ixl1394_command_t *)&bp->tb_store_ts;
578 
579 		bp->tb_store_ts.ixl_opcode = IXL1394_OP_STORE_TIMESTAMP;
580 		bp->tb_store_ts.next_ixlp = (ixl1394_command_t *)&bp->tb_cb;
581 
582 		bp->tb_cb.ixl_opcode = IXL1394_OP_CALLBACK;
583 		bp->tb_cb.callback = av1394_it_ixl_buf_cb;
584 		bp->tb_cb.callback_arg = bp;
585 		bp->tb_cb.next_ixlp = (ixl1394_command_t *)&bp->tb_jump;
586 
587 		bp->tb_jump.ixl_opcode = IXL1394_OP_JUMP_U;
588 	} else {
589 		bp->tb_buf.next_ixlp = (ixl1394_command_t *)&bp->tb_jump;
590 
591 		bp->tb_jump.ixl_opcode = IXL1394_OP_JUMP;
592 	}
593 	/*
594 	 * jump label and next_ixlp later.
595 	 * unset fields will be set in av1394_it_ixl_complete_buf()
596 	 *
597 	 * save additional frame info
598 	 */
599 	if (flags & AV1394_IT_IXL_BUF_SOF) {
600 		itp->it_frame_info[framenum].fi_first_buf = bp;
601 		itp->it_frame_info[framenum].fi_ts_off = bp->tb_buf.mem_bufp +
602 		    AV1394_TS_MODE_GET_OFF(icp->ic_param.cp_ts_mode);
603 	} else if (flags & AV1394_IT_IXL_BUF_EOF) {
604 		itp->it_frame_info[framenum].fi_last_buf = bp;
605 	}
606 	itp->it_frame_info[framenum].fi_ncycs += cnt;
607 
608 	return (bp);
609 }
610 
611 static void
612 av1394_it_ixl_complete_buf(av1394_it_ixl_buf_t *bp,
613 	av1394_it_ixl_empty_cip_t *ep)
614 {
615 	bp->tb_common.tc_next = &ep->te_common;
616 	bp->tb_jump.label = bp->tb_jump.next_ixlp =
617 	    (ixl1394_command_t *)&ep->te_label;
618 }
619 
620 static void
621 av1394_it_ixl_complete_buf2(av1394_it_ixl_buf_t *bp,
622 	av1394_it_ixl_buf_t *nextbp)
623 {
624 	bp->tb_common.tc_next = &nextbp->tb_common;
625 	bp->tb_jump.label = bp->tb_jump.next_ixlp =
626 	    (ixl1394_command_t *)&nextbp->tb_label;
627 }
628 
629 static av1394_it_ixl_empty_cip_t *
630 av1394_it_ixl_bld_empty_cip(av1394_ic_t *icp, int framenum)
631 {
632 	av1394_it_t	*itp = &icp->ic_it;
633 	av1394_it_ixl_empty_cip_t *ep;
634 
635 	ep = kmem_zalloc(sizeof (av1394_it_ixl_empty_cip_t), KM_SLEEP);
636 	ep->te_common.tc_size = sizeof (av1394_it_ixl_empty_cip_t);
637 	/* tc_next later */
638 
639 	ep->te_label.ixl_opcode = IXL1394_OP_LABEL;
640 	ep->te_label.next_ixlp = (ixl1394_command_t *)&ep->te_pkt;
641 
642 	ep->te_pkt.ixl_opcode = IXL1394_OP_SEND_PKT_ST;
643 	ep->te_pkt.size = AV1394_CIPSZ;
644 	/* ixl_buf and mem_bufp later */
645 	ep->te_pkt.next_ixlp = (ixl1394_command_t *)&ep->te_jump;
646 
647 	ep->te_jump.ixl_opcode = IXL1394_OP_JUMP;
648 	/*
649 	 * label and next_ixlp later.
650 	 * unset fields will be set in av1394_it_ixl_complete_empty_cip()
651 	 */
652 
653 	itp->it_frame_info[framenum].fi_ncycs++;
654 
655 	return (ep);
656 }
657 
658 /*
659  * empty CIP packet contains CIP header of the next packet,
660  * so we just point to the same address as the next packet's header
661  */
662 static void
663 av1394_it_ixl_complete_empty_cip(av1394_it_ixl_empty_cip_t *ep,
664 	av1394_it_ixl_buf_t *bp)
665 {
666 	ep->te_common.tc_next = &bp->tb_common;
667 
668 	ep->te_pkt.ixl_buf._dmac_ll = bp->tb_buf.ixl_buf._dmac_ll;
669 	ep->te_pkt.mem_bufp = bp->tb_buf.mem_bufp;
670 
671 	ep->te_jump.label = ep->te_jump.next_ixlp =
672 	    (ixl1394_command_t *)&bp->tb_label;
673 }
674 
675 static void
676 av1394_it_ixl_bld_begin(av1394_ic_t *icp)
677 {
678 	av1394_it_t		*itp = &icp->ic_it;
679 	av1394_it_ixl_buf_t	*bp = (av1394_it_ixl_buf_t *)itp->it_ixl_data;
680 	av1394_it_ixl_begin_t	*bep = &itp->it_ixl_begin;
681 	int			i;
682 
683 	bep->be_label.ixl_opcode = IXL1394_OP_LABEL;
684 	bep->be_label.next_ixlp = (ixl1394_command_t *)&bep->be_empty_pre;
685 
686 	bep->be_empty_pre.ixl_opcode = IXL1394_OP_SEND_PKT_ST;
687 	bep->be_empty_pre.size = AV1394_CIPSZ;
688 	bep->be_empty_pre.ixl_buf._dmac_ll = bp->tb_buf.ixl_buf._dmac_ll;
689 	bep->be_empty_pre.mem_bufp = bp->tb_buf.mem_bufp;
690 	bep->be_empty_pre.next_ixlp = (ixl1394_command_t *)&bep->be_store_ts;
691 
692 	bep->be_store_ts.ixl_opcode = IXL1394_OP_STORE_TIMESTAMP;
693 	bep->be_store_ts.next_ixlp = (ixl1394_command_t *)&bep->be_cb;
694 
695 	bep->be_cb.ixl_opcode = IXL1394_OP_CALLBACK;
696 	bep->be_cb.callback = av1394_it_ixl_begin_cb;
697 	bep->be_cb.callback_arg = &bep->be_store_ts.timestamp;
698 	bep->be_cb.next_ixlp = (ixl1394_command_t *)&bep->be_empty_post[0];
699 
700 	for (i = 0; i < AV1394_IT_IXL_BEGIN_NPOST; i++) {
701 		bep->be_empty_post[i].ixl_opcode = IXL1394_OP_SEND_PKT_ST;
702 		bep->be_empty_post[i].size = AV1394_CIPSZ;
703 		bep->be_empty_post[i].ixl_buf._dmac_ll =
704 		    bp->tb_buf.ixl_buf._dmac_ll;
705 		bep->be_empty_post[i].mem_bufp = bp->tb_buf.mem_bufp;
706 		bep->be_empty_post[i].next_ixlp =
707 		    (ixl1394_command_t *)&bep->be_empty_post[i + 1];
708 	}
709 	bep->be_empty_post[AV1394_IT_IXL_BEGIN_NPOST - 1].next_ixlp =
710 	    (ixl1394_command_t *)&bep->be_jump;
711 
712 	bep->be_jump.ixl_opcode = IXL1394_OP_JUMP_U;
713 	bep->be_jump.label = (ixl1394_command_t *)&bp->tb_label;
714 	bep->be_jump.next_ixlp = (ixl1394_command_t *)&bp->tb_label;
715 }
716 
717 static void
718 av1394_it_ixl_begin_update_pkts(av1394_ic_t *icp, av1394_it_ixl_buf_t *bp)
719 {
720 	av1394_it_t		*itp = &icp->ic_it;
721 	av1394_it_ixl_begin_t	*bep = &itp->it_ixl_begin;
722 	int			i;
723 
724 	for (i = 0; i < AV1394_IT_IXL_BEGIN_NPOST; i++) {
725 		bep->be_empty_post[i].ixl_buf._dmac_ll =
726 		    bp->tb_buf.ixl_buf._dmac_ll;
727 		bep->be_empty_post[i].mem_bufp = bp->tb_buf.mem_bufp;
728 	}
729 }
730 
731 static int
732 av1394_it_alloc_isoch_dma(av1394_ic_t *icp)
733 {
734 	av1394_inst_t		*avp = icp->ic_avp;
735 	av1394_it_t		*itp = &icp->ic_it;
736 	id1394_isoch_dmainfo_t	di;
737 	int			result;
738 	int			ret;
739 
740 	AV1394_TNF_ENTER(av1394_it_alloc_isoch_dma);
741 
742 	di.ixlp = itp->it_ixlp;
743 	di.channel_num = icp->ic_num;
744 	di.idma_options = ID1394_TALK;
745 	di.it_speed = icp->ic_param.cp_bus_speed;
746 	/*
747 	 * XXX this should really be IXL1394_SKIP_TO_NEXT,
748 	 * but it can't be used yet due to the Framework bug
749 	 */
750 	di.it_default_skip = IXL1394_SKIP_TO_SELF;
751 	di.default_tag = 1;
752 	di.default_sync = 0;
753 	di.global_callback_arg = icp;
754 	di.isoch_dma_stopped = av1394_it_dma_stopped_cb;
755 	di.idma_evt_arg = icp;
756 
757 	if ((ret = t1394_alloc_isoch_dma(avp->av_t1394_hdl, &di, 0,
758 	    &icp->ic_isoch_hdl, &result)) != DDI_SUCCESS) {
759 		TNF_PROBE_1(av1394_it_alloc_isoch_dma_error,
760 		    AV1394_TNF_ISOCH_ERROR, "", tnf_int, result, result);
761 	}
762 
763 	AV1394_TNF_EXIT(av1394_it_alloc_isoch_dma);
764 	return (ret);
765 }
766 
767 static void
768 av1394_it_free_isoch_dma(av1394_ic_t *icp)
769 {
770 	av1394_inst_t		*avp = icp->ic_avp;
771 
772 	AV1394_TNF_ENTER(av1394_it_free_isoch_rsrc);
773 
774 	t1394_free_isoch_dma(avp->av_t1394_hdl, 0, &icp->ic_isoch_hdl);
775 
776 	AV1394_TNF_EXIT(av1394_it_free_isoch_rsrc);
777 }
778 
779 static void
780 av1394_it_dma_sync_frames(av1394_ic_t *icp, int idx, int cnt)
781 {
782 	av1394_ic_dma_sync_frames(icp, idx, cnt,
783 	    &icp->ic_it.it_data_pool, DDI_DMA_SYNC_FORDEV);
784 }
785 
786 /*
787  *
788  * --- callbacks
789  *
790  */
791 static void
792 av1394_it_ixl_begin_cb(opaque_t arg, struct ixl1394_callback *cb)
793 {
794 	av1394_ic_t	*icp = arg;
795 	av1394_it_t	*itp = &icp->ic_it;
796 	uint16_t	*cycp = cb->callback_arg; /* cycle timestamp pointer */
797 	uint16_t	syt;
798 	int		first;
799 
800 	AV1394_TNF_ENTER(av1394_it_ixl_begin_cb);
801 
802 	mutex_enter(&icp->ic_mutex);
803 	/* save initial timestamp value */
804 	itp->it_ts_init.ts_syt = av1394_it_ts_cyc2syt(*cycp);
805 
806 	/*
807 	 * update frame timestamps if needed
808 	 */
809 	if ((itp->it_nfull <= 0) ||
810 	    (AV1394_TS_MODE_GET_SIZE(icp->ic_param.cp_ts_mode) == 0)) {
811 		mutex_exit(&icp->ic_mutex);
812 		AV1394_TNF_EXIT(av1394_it_ixl_begin_cb);
813 		return;
814 	}
815 	ASSERT(itp->it_nfull <= icp->ic_nframes);
816 
817 	syt = av1394_it_ts_syt_inc(itp->it_ts_init.ts_syt,
818 	    AV1394_IT_IXL_BEGIN_NPOST + av1394_it_syt_off);
819 	first = (itp->it_last_full + icp->ic_nframes - itp->it_nfull + 1) %
820 	    icp->ic_nframes;
821 	av1394_it_update_frame_syt(icp, first, itp->it_nfull, syt);
822 	mutex_exit(&icp->ic_mutex);
823 
824 	AV1394_TNF_EXIT(av1394_it_ixl_begin_cb);
825 }
826 
827 /*ARGSUSED*/
828 static void
829 av1394_it_ixl_buf_cb(opaque_t arg, struct ixl1394_callback *cb)
830 {
831 	av1394_it_ixl_buf_t	*bp = cb->callback_arg;
832 
833 	AV1394_TNF_ENTER(av1394_it_ixl_buf_cb);
834 	if (bp->tb_flags & AV1394_IT_IXL_BUF_EOF) {
835 		av1394_it_ixl_eof_cb(bp);
836 	}
837 	AV1394_TNF_EXIT(av1394_it_ixl_buf_cb);
838 }
839 
840 static void
841 av1394_it_ixl_eof_cb(av1394_it_ixl_buf_t *bp)
842 {
843 	av1394_ic_t	*icp = bp->tb_icp;
844 	av1394_isoch_t	*ip = &icp->ic_avp->av_i;
845 	av1394_it_t	*itp = &icp->ic_it;
846 
847 	AV1394_TNF_ENTER(av1394_it_ixl_eof_cb);
848 
849 	mutex_enter(&ip->i_mutex);
850 	mutex_enter(&icp->ic_mutex);
851 	if (itp->it_nempty < icp->ic_nframes) {
852 		itp->it_nempty++;
853 		itp->it_nfull--;
854 		cv_signal(&icp->ic_xfer_cv);
855 	}
856 
857 	if ((itp->it_nempty >= itp->it_hiwat) &&
858 	    (icp->ic_state == AV1394_IC_DMA)) {
859 		av1394_ic_trigger_softintr(icp, icp->ic_num,
860 		    AV1394_PREQ_IT_UNDERRUN);
861 	}
862 	mutex_exit(&icp->ic_mutex);
863 	mutex_exit(&ip->i_mutex);
864 
865 	AV1394_TNF_EXIT(av1394_it_ixl_eof_cb);
866 }
867 
868 void
869 av1394_it_underrun(av1394_ic_t *icp)
870 {
871 	av1394_it_t		*itp = &icp->ic_it;
872 	av1394_inst_t		*avp = icp->ic_avp;
873 	int			idx;
874 	ixl1394_jump_t		*old_jmp;
875 	ixl1394_jump_t		new_jmp;
876 	id1394_isoch_dma_updateinfo_t update_info;
877 	int			err;
878 	int			result;
879 
880 	AV1394_TNF_ENTER(av1394_it_underrun);
881 
882 	/*
883 	 * update the last full frame's jump to NULL
884 	 */
885 	idx = (itp->it_first_empty + icp->ic_nframes - 1) % icp->ic_nframes;
886 
887 	old_jmp = &itp->it_frame_info[idx].fi_last_buf->tb_jump;
888 	itp->it_saved_label = old_jmp->label;
889 
890 	new_jmp.ixl_opcode = IXL1394_OP_JUMP_U;
891 	new_jmp.label = NULL;
892 	new_jmp.next_ixlp = NULL;
893 
894 	update_info.orig_ixlp = (ixl1394_command_t *)old_jmp;
895 	update_info.temp_ixlp = (ixl1394_command_t *)&new_jmp;
896 	update_info.ixl_count = 1;
897 
898 	mutex_exit(&icp->ic_mutex);
899 	err = t1394_update_isoch_dma(avp->av_t1394_hdl,
900 	    icp->ic_isoch_hdl, &update_info, 0, &result);
901 	mutex_enter(&icp->ic_mutex);
902 
903 	if (err == DDI_SUCCESS) {
904 		itp->it_underrun_idx = idx;
905 		icp->ic_state = AV1394_IC_SUSPENDED;
906 		cv_signal(&icp->ic_xfer_cv);
907 	} else {
908 		TNF_PROBE_2(av1394_it_underrun_error_update,
909 		    AV1394_TNF_ISOCH_ERROR, "", tnf_int, err, err,
910 		    tnf_int, result, result);
911 	}
912 
913 	AV1394_TNF_EXIT(av1394_it_underrun);
914 }
915 
916 /*
917  * resume from the underrun condition
918  */
919 static int
920 av1394_it_underrun_resume(av1394_ic_t *icp)
921 {
922 	av1394_it_t		*itp = &icp->ic_it;
923 	av1394_inst_t		*avp = icp->ic_avp;
924 	av1394_it_ixl_buf_t	*bp;
925 	int			idx;
926 	ixl1394_jump_t		*old_jmp;
927 	ixl1394_jump_t		new_jmp;
928 	id1394_isoch_dma_updateinfo_t update_info;
929 	int			err;
930 	int			result;
931 
932 	AV1394_TNF_ENTER(av1394_it_underrun_resume);
933 
934 	/*
935 	 * resuming the transfer it a lot like starting the transfer:
936 	 * first the IXL begin block needs to be executed, then the rest
937 	 * of the IXL chain. The following dynamic updates are needed:
938 	 *
939 	 *  1. update the begin block to jump to the first empty frame;
940 	 *  2. restore the original jump label which we previously
941 	 *    changed to jump to the underrun block;
942 	 *
943 	 * update #1
944 	 *   start by updating the begin block with a new buffer address
945 	 */
946 	idx = (itp->it_underrun_idx + 1) % icp->ic_nframes;
947 	bp = itp->it_frame_info[idx].fi_first_buf;
948 	av1394_it_ixl_begin_update_pkts(icp, bp);
949 
950 	old_jmp = &itp->it_ixl_begin.be_jump;
951 
952 	new_jmp.ixl_opcode = IXL1394_OP_JUMP_U;
953 	new_jmp.label = (ixl1394_command_t *)&bp->tb_label;
954 	new_jmp.next_ixlp = NULL;
955 
956 	update_info.orig_ixlp = (ixl1394_command_t *)old_jmp;
957 	update_info.temp_ixlp = (ixl1394_command_t *)&new_jmp;
958 	update_info.ixl_count = 1;
959 
960 	mutex_exit(&icp->ic_mutex);
961 	err = t1394_update_isoch_dma(avp->av_t1394_hdl,
962 	    icp->ic_isoch_hdl, &update_info, 0, &result);
963 	mutex_enter(&icp->ic_mutex);
964 
965 	if (err != DDI_SUCCESS) {
966 		TNF_PROBE_2(av1394_it_underrun_resume_error_update1,
967 		    AV1394_TNF_ISOCH_ERROR, "", tnf_int, err, err,
968 		    tnf_int, result, result);
969 		AV1394_TNF_EXIT(av1394_it_underrun_resume);
970 		return (EIO);
971 	}
972 
973 	/*
974 	 * update #2
975 	 */
976 	bp = itp->it_frame_info[itp->it_underrun_idx].fi_last_buf;
977 	old_jmp = &bp->tb_jump;
978 
979 	new_jmp.ixl_opcode = IXL1394_OP_JUMP_U;
980 	new_jmp.label = itp->it_saved_label;
981 	new_jmp.next_ixlp = NULL;
982 
983 	update_info.orig_ixlp = (ixl1394_command_t *)old_jmp;
984 	update_info.temp_ixlp = (ixl1394_command_t *)&new_jmp;
985 	update_info.ixl_count = 1;
986 
987 	mutex_exit(&icp->ic_mutex);
988 	err = t1394_update_isoch_dma(avp->av_t1394_hdl,
989 	    icp->ic_isoch_hdl, &update_info, 0, &result);
990 	mutex_enter(&icp->ic_mutex);
991 
992 	if (err != DDI_SUCCESS) {
993 		TNF_PROBE_2(av1394_it_underrun_resume_error_update2,
994 		    AV1394_TNF_ISOCH_ERROR, "", tnf_int, err, err,
995 		    tnf_int, result, result);
996 		AV1394_TNF_EXIT(av1394_it_underrun_resume);
997 		return (EIO);
998 	}
999 
1000 	icp->ic_state = AV1394_IC_DMA;
1001 
1002 	AV1394_TNF_EXIT(av1394_it_underrun_resume);
1003 	return (0);
1004 }
1005 
1006 /*ARGSUSED*/
1007 static void
1008 av1394_it_dma_stopped_cb(t1394_isoch_dma_handle_t t1394_idma_hdl,
1009 	opaque_t idma_evt_arg, id1394_isoch_dma_stopped_t status)
1010 {
1011 	av1394_ic_t	*icp = idma_evt_arg;
1012 
1013 	AV1394_TNF_ENTER(av1394_it_dma_stopped_cb);
1014 
1015 	mutex_enter(&icp->ic_mutex);
1016 	icp->ic_state = AV1394_IC_IDLE;
1017 	mutex_exit(&icp->ic_mutex);
1018 
1019 	AV1394_TNF_EXIT(av1394_it_dma_stopped_cb);
1020 }
1021 
1022 
1023 /*
1024  *
1025  * --- data transfer routines
1026  *
1027  * av1394_it_add_frames()
1028  *    Add full frames to the pool.
1029  */
1030 static int
1031 av1394_it_add_frames(av1394_ic_t *icp, int idx, int cnt)
1032 {
1033 	av1394_it_t	*itp = &icp->ic_it;
1034 	av1394_it_frame_info_t *fip;
1035 	int		prev_full = itp->it_last_full;
1036 	uint16_t	syt;
1037 	int		ret = 0;
1038 
1039 	/* can only add to tail */
1040 	if (idx != ((itp->it_last_full + 1) % icp->ic_nframes)) {
1041 		TNF_PROBE_1(av1394_it_add_frames_error,
1042 		    AV1394_TNF_ISOCH_ERROR, "", tnf_int, idx, idx);
1043 		return (EINVAL);
1044 	}
1045 
1046 	/* turn empty frames into full ones */
1047 	itp->it_nempty -= cnt;
1048 	itp->it_first_empty = (itp->it_first_empty + cnt) % icp->ic_nframes;
1049 	itp->it_nfull += cnt;
1050 	itp->it_last_full = (itp->it_last_full + cnt) % icp->ic_nframes;
1051 	ASSERT((itp->it_nempty >= 0) && (itp->it_nfull <= icp->ic_nframes));
1052 
1053 	/*
1054 	 * update frame timestamps if needed
1055 	 */
1056 	if (AV1394_TS_MODE_GET_SIZE(icp->ic_param.cp_ts_mode) > 0) {
1057 		ASSERT(prev_full >= 0);
1058 		fip = &itp->it_frame_info[prev_full];
1059 		syt = *(uint16_t *)fip->fi_ts_off;
1060 		syt = av1394_it_ts_syt_inc(syt, fip->fi_ncycs);
1061 		av1394_it_update_frame_syt(icp, idx, cnt, syt);
1062 	}
1063 
1064 	av1394_it_dma_sync_frames(icp, idx, cnt);
1065 
1066 	/* if suspended due to overrun, check if we can resume */
1067 	if ((icp->ic_state == AV1394_IC_SUSPENDED) &&
1068 	    (itp->it_nempty >= itp->it_lowat)) {
1069 		ret = av1394_it_underrun_resume(icp);
1070 	}
1071 
1072 	return (ret);
1073 }
1074 
1075 /*
1076  * wait for empty frames
1077  */
1078 static int
1079 av1394_it_wait_frames(av1394_ic_t *icp, int *idx, int *cnt, int *nlost)
1080 {
1081 	av1394_it_t	*itp = &icp->ic_it;
1082 	int		ret = 0;
1083 
1084 	while ((itp->it_nempty == 0) && (icp->ic_state == AV1394_IC_DMA)) {
1085 		if (cv_wait_sig(&icp->ic_xfer_cv, &icp->ic_mutex) <= 0) {
1086 			ret = EINTR;
1087 			break;
1088 		}
1089 	}
1090 
1091 	if (itp->it_nempty > 0) {
1092 		*idx = itp->it_first_empty;
1093 		*cnt = itp->it_nempty;
1094 		*nlost = 0;
1095 		ret = 0;
1096 	}
1097 	return (ret);
1098 }
1099 
1100 /*
1101  * update frame timestamps for a range of frames
1102  */
1103 static void
1104 av1394_it_update_frame_syt(av1394_ic_t *icp, int first, int cnt, uint16_t syt)
1105 {
1106 	av1394_it_t	*itp = &icp->ic_it;
1107 	int		i;
1108 	int		j = first;	/* frame number */
1109 
1110 	for (i = cnt; i > 0; i--) {
1111 		*(uint16_t *)itp->it_frame_info[j].fi_ts_off = syt;
1112 		syt = av1394_it_ts_syt_inc(syt, itp->it_frame_info[j].fi_ncycs);
1113 		j = (j + 1) % icp->ic_nframes;
1114 	}
1115 }
1116 
1117 /*
1118  * convert cycle timestamp into SYT timestamp:
1119  *
1120  * Cycle timer:          cycleSeconds         cycleCount     cycleOffset
1121  *                   31_30_29_28_27_26_25  24___15_14_13_12  11________0
1122  * Cycle timestamp:              |------------------------|
1123  * SYT timestamp:                               |----------------------|
1124  */
1125 static uint16_t
1126 av1394_it_ts_cyc2syt(uint16_t cyc)
1127 {
1128 	return (((cyc & 0xF) << 12) + 0x800);
1129 }
1130 
1131 /*
1132  * increment SYT by a number of cycles
1133  */
1134 static uint16_t
1135 av1394_it_ts_syt_inc(uint16_t syt, uint16_t ncycs)
1136 {
1137 	return (syt + (ncycs << 12));
1138 }
1139 
1140 /*
1141  * copyin from the kernel buffer
1142  */
1143 static void
1144 av1394_it_kcopyin(av1394_ic_t *icp, void *buf, size_t len)
1145 {
1146 	av1394_it_t	*itp = &icp->ic_it;
1147 	av1394_isoch_seg_t *seg = itp->it_data_pool.ip_seg;
1148 
1149 	ASSERT(itp->it_write_off + len < icp->ic_framesz);
1150 
1151 	bcopy(buf, seg[itp->it_write_idx].is_kaddr + itp->it_write_off, len);
1152 	itp->it_write_off += len;
1153 }
1154 
1155 /*
1156  * copyin from the user buffer
1157  */
1158 static int
1159 av1394_it_copyin(av1394_ic_t *icp, struct uio *uiop, int *full_cnt, int dv)
1160 {
1161 	av1394_it_t	*itp = &icp->ic_it;
1162 	av1394_isoch_seg_t *seg = itp->it_data_pool.ip_seg;
1163 	int		idx = itp->it_write_idx;
1164 	int		framesz = icp->ic_framesz;
1165 	size_t		len, frame_resid, start_resid;
1166 	caddr_t		kaddr, kaddr_end;
1167 	int		ret = 0;
1168 
1169 	*full_cnt = 0;
1170 
1171 	while ((uiop->uio_resid > 0) && (itp->it_write_cnt > 0)) {
1172 		kaddr = seg[idx].is_kaddr + itp->it_write_off;
1173 		frame_resid = framesz - itp->it_write_off;
1174 		len = min(uiop->uio_resid, frame_resid);
1175 
1176 		mutex_exit(&icp->ic_mutex);
1177 		ret = uiomove(kaddr, len, UIO_WRITE, uiop);
1178 		mutex_enter(&icp->ic_mutex);
1179 		if (ret != 0) {
1180 			break;
1181 		}
1182 
1183 		itp->it_write_off += len;
1184 		if ((itp->it_write_off == framesz) && dv) {
1185 			/*
1186 			 * for DV formats, make sure we got a frame start.
1187 			 * this is to ensure correct timestamping
1188 			 */
1189 			kaddr = seg[idx].is_kaddr;
1190 			kaddr_end = kaddr + framesz;
1191 			while (!av1394_it_is_dv_frame_start(kaddr)) {
1192 				kaddr += icp->ic_pktsz;
1193 				if (kaddr == kaddr_end) {
1194 					break;
1195 				}
1196 			}
1197 			start_resid = kaddr_end - kaddr;
1198 			if (start_resid != framesz) {
1199 				bcopy(kaddr, seg[idx].is_kaddr, start_resid);
1200 				itp->it_write_off = start_resid;
1201 			}
1202 		}
1203 		if (itp->it_write_off == framesz) {
1204 			/* for DV formats, reset frame's SYT fields */
1205 			if (dv) {
1206 				av1394_it_reset_frame_syt(icp, idx);
1207 			}
1208 			itp->it_write_off = 0;
1209 			itp->it_write_cnt--;
1210 			idx = (idx + 1) % icp->ic_nframes;
1211 			(*full_cnt)++;
1212 		}
1213 	}
1214 
1215 	return (ret);
1216 }
1217 
1218 /*
1219  * check if a packet starts a new DV frame
1220  */
1221 static boolean_t
1222 av1394_it_is_dv_frame_start(caddr_t kaddr)
1223 {
1224 	uint8_t *p = (uint8_t *)kaddr + 8;
1225 	/*
1226 	 * in the DIF block ID data, which immediately follows CIP header,
1227 	 * SCT, Dseq and DBN fields should be zero (Ref: IEC 61834-2, Fig. 66)
1228 	 */
1229 	return (((p[0] & 0xE0) == 0) && ((p[1] & 0xF0) == 0) && (p[2] == 0));
1230 }
1231 
1232 /*
1233  * reset all frame's SYT fields
1234  */
1235 static void
1236 av1394_it_reset_frame_syt(av1394_ic_t *icp, int idx)
1237 {
1238 	caddr_t		kaddr = icp->ic_it.it_data_pool.ip_seg[idx].is_kaddr;
1239 	caddr_t		kaddr_end = kaddr + icp->ic_framesz;
1240 
1241 	kaddr += 6;
1242 	while (kaddr < kaddr_end) {
1243 		*(uint16_t *)kaddr = 0xFFFF;
1244 		kaddr += icp->ic_pktsz;
1245 	}
1246 }
1247