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