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