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
av1394_it_init(av1394_ic_t * icp,int * error)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
av1394_it_fini(av1394_ic_t * icp)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
av1394_it_start(av1394_ic_t * icp)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
av1394_it_start_common(av1394_ic_t * icp)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
av1394_it_stop(av1394_ic_t * icp)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
av1394_it_xmit(av1394_ic_t * icp,iec61883_xmit_t * xmit)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
av1394_it_write(av1394_ic_t * icp,struct uio * uiop)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
av1394_it_cleanup(av1394_ic_t * icp,int level)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
av1394_it_bld_ixl(av1394_ic_t * icp)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
av1394_it_destroy_ixl(av1394_ic_t * icp)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
av1394_it_ixl_bld_data(av1394_ic_t * icp)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
av1394_it_ixl_destroy_data(av1394_ic_t * icp)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 *
av1394_it_ixl_bld_buf(av1394_ic_t * icp,int cnt,int segnum,off_t off,int flags,int framenum)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
av1394_it_ixl_complete_buf(av1394_it_ixl_buf_t * bp,av1394_it_ixl_empty_cip_t * ep)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
av1394_it_ixl_complete_buf2(av1394_it_ixl_buf_t * bp,av1394_it_ixl_buf_t * nextbp)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 *
av1394_it_ixl_bld_empty_cip(av1394_ic_t * icp,int framenum)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
av1394_it_ixl_complete_empty_cip(av1394_it_ixl_empty_cip_t * ep,av1394_it_ixl_buf_t * bp)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
av1394_it_ixl_bld_begin(av1394_ic_t * icp)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
av1394_it_ixl_begin_update_pkts(av1394_ic_t * icp,av1394_it_ixl_buf_t * bp)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
av1394_it_alloc_isoch_dma(av1394_ic_t * icp)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
av1394_it_free_isoch_dma(av1394_ic_t * icp)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
av1394_it_dma_sync_frames(av1394_ic_t * icp,int idx,int cnt)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
av1394_it_ixl_begin_cb(opaque_t arg,struct ixl1394_callback * cb)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
av1394_it_ixl_buf_cb(opaque_t arg,struct ixl1394_callback * cb)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
av1394_it_ixl_eof_cb(av1394_it_ixl_buf_t * bp)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
av1394_it_underrun(av1394_ic_t * icp)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
av1394_it_underrun_resume(av1394_ic_t * icp)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
av1394_it_dma_stopped_cb(t1394_isoch_dma_handle_t t1394_idma_hdl,opaque_t idma_evt_arg,id1394_isoch_dma_stopped_t status)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
av1394_it_add_frames(av1394_ic_t * icp,int idx,int cnt)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
av1394_it_wait_frames(av1394_ic_t * icp,int * idx,int * cnt,int * nlost)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
av1394_it_update_frame_syt(av1394_ic_t * icp,int first,int cnt,uint16_t syt)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
av1394_it_ts_cyc2syt(uint16_t cyc)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
av1394_it_ts_syt_inc(uint16_t syt,uint16_t ncycs)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
av1394_it_kcopyin(av1394_ic_t * icp,void * buf,size_t len)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
av1394_it_copyin(av1394_ic_t * icp,struct uio * uiop,int * full_cnt,int dv)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
av1394_it_is_dv_frame_start(caddr_t kaddr)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
av1394_it_reset_frame_syt(av1394_ic_t * icp,int idx)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