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 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 130 av1394_it_fini(av1394_ic_t *icp) 131 { 132 av1394_it_cleanup(icp, AV1394_CLEANUP_LEVEL_MAX); 133 } 134 135 int 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 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 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 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 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 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 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 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 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 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 * 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 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 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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