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 * Copyright (c) 2018, Joyent, Inc. 28 */ 29 30 /* 31 * routines common to isoch receive and isoch transmit 32 */ 33 #include <sys/stat.h> 34 #include <sys/systm.h> 35 #include <sys/ddi.h> 36 #include <sys/sunddi.h> 37 #include <sys/bitmap.h> 38 #include <sys/av/iec61883.h> 39 #include <sys/1394/targets/av1394/av1394_impl.h> 40 41 /* configuration routines */ 42 static void av1394_ic_cleanup(av1394_ic_t *icp, int level); 43 static int av1394_ic_validate_init_params(iec61883_isoch_init_t *ii); 44 static void av1394_ic_set_params(av1394_inst_t *avp, 45 iec61883_isoch_init_t *ii, av1394_ic_t *icp, int num); 46 static int av1394_ic_alloc_channel(av1394_ic_t *icp, uint64_t mask, int *); 47 static void av1394_ic_free_channel(av1394_ic_t *icp); 48 49 /* callbacks */ 50 static void av1394_ic_rsrc_fail(t1394_isoch_single_handle_t t1394_sii_hdl, 51 opaque_t arg, t1394_isoch_rsrc_error_t fail_args); 52 53 uint64_t av1394_ic_bitreverse(uint64_t); 54 boolean_t av1394_ic_onebit(uint64_t); 55 56 /* tunables */ 57 extern int av1394_rate_n_dv_ntsc; 58 extern int av1394_rate_d_dv_ntsc; 59 extern int av1394_rate_n_dv_pal; 60 extern int av1394_rate_d_dv_pal; 61 62 /*ARGSUSED*/ 63 int 64 av1394_ic_close(av1394_inst_t *avp, int flags) 65 { 66 av1394_isoch_t *ip = &avp->av_i; 67 av1394_ic_t *icp; 68 int i; 69 70 /* cleanup channels in case application didn't */ 71 for (i = 0; i < NELEM(ip->i_ic); i++) { 72 icp = ip->i_ic[i]; 73 if (icp != NULL) { 74 (void) av1394_ic_stop(icp); 75 av1394_ic_fini(icp); 76 } 77 } 78 79 return (0); 80 } 81 82 /* 83 * av1394_ic_init() 84 * Channel allocation and initialization. 85 */ 86 int 87 av1394_ic_init(av1394_inst_t *avp, iec61883_isoch_init_t *ii, 88 av1394_ic_t **icpp) 89 { 90 av1394_isoch_t *ip = &avp->av_i; 91 av1394_ic_t *icp = NULL; 92 int num; 93 av1394_isoch_pool_t *pool; 94 uint64_t mask; /* channel mask */ 95 int ret; 96 ddi_iblock_cookie_t ibc = avp->av_attachinfo.iblock_cookie; 97 98 ii->ii_frame_rcnt = 0; 99 ii->ii_rchannel = 0; 100 ii->ii_error = 0; 101 102 if ((ret = av1394_ic_validate_init_params(ii)) != 0) { 103 return (ret); 104 } 105 106 /* allocate channel structure */ 107 icp = kmem_zalloc(sizeof (av1394_ic_t), KM_SLEEP); 108 109 mutex_init(&icp->ic_mutex, NULL, MUTEX_DRIVER, ibc); 110 cv_init(&icp->ic_xfer_cv, NULL, CV_DRIVER, NULL); 111 112 av1394_ic_set_params(avp, ii, icp, -1); 113 114 /* allocate isoch channel and bandwidth, except for broadcast */ 115 if (ii->ii_channel == (1ULL << 63)) { 116 num = 63; 117 } else if (ii->ii_flags & IEC61883_PRIV_ISOCH_NOALLOC) { 118 num = lowbit(ii->ii_channel) - 1; 119 } else { 120 mask = av1394_ic_bitreverse(ii->ii_channel); 121 ret = av1394_ic_alloc_channel(icp, mask, &num); 122 if (ret != DDI_SUCCESS) { 123 ii->ii_error = IEC61883_ERR_NOCHANNEL; 124 av1394_ic_cleanup(icp, 1); 125 return (EINVAL); 126 } 127 } 128 ASSERT((num >= 0) && (num < 64)); 129 130 mutex_enter(&icp->ic_mutex); 131 icp->ic_num = num; 132 mutex_exit(&icp->ic_mutex); 133 134 mutex_enter(&ip->i_mutex); 135 if (ip->i_ic[num] != NULL) { 136 mutex_exit(&ip->i_mutex); 137 ii->ii_error = IEC61883_ERR_NOCHANNEL; 138 av1394_ic_cleanup(icp, 2); 139 return (EINVAL); 140 } 141 ip->i_ic[num] = icp; 142 mutex_exit(&ip->i_mutex); 143 144 /* do direction specific initialization */ 145 if (icp->ic_dir == AV1394_IR) { 146 ret = av1394_ir_init(icp, &ii->ii_error); 147 pool = &icp->ic_ir.ir_data_pool; 148 } else { 149 ret = av1394_it_init(icp, &ii->ii_error); 150 pool = &icp->ic_it.it_data_pool; 151 } 152 153 if (ret != 0) { 154 av1394_ic_cleanup(icp, 3); 155 return (ret); 156 } 157 158 /* allocate mmap space */ 159 mutex_enter(&ip->i_mutex); 160 mutex_enter(&icp->ic_mutex); 161 icp->ic_mmap_sz = pool->ip_umem_size; 162 icp->ic_mmap_off = av1394_as_alloc(&ip->i_mmap_as, icp->ic_mmap_sz); 163 164 icp->ic_state = AV1394_IC_IDLE; 165 166 *icpp = icp; 167 ii->ii_handle = icp->ic_num; 168 ii->ii_frame_rcnt = icp->ic_nframes; 169 ii->ii_mmap_off = icp->ic_mmap_off; 170 ii->ii_rchannel = icp->ic_num; 171 mutex_exit(&icp->ic_mutex); 172 mutex_exit(&ip->i_mutex); 173 174 return (0); 175 } 176 177 void 178 av1394_ic_fini(av1394_ic_t *icp) 179 { 180 av1394_ic_cleanup(icp, AV1394_CLEANUP_LEVEL_MAX); 181 } 182 183 /* 184 * 185 * --- configuration routines 186 * 187 */ 188 static void 189 av1394_ic_cleanup(av1394_ic_t *icp, int level) 190 { 191 av1394_inst_t *avp = icp->ic_avp; 192 av1394_isoch_t *ip = &avp->av_i; 193 194 ASSERT((level > 0) && (level <= AV1394_CLEANUP_LEVEL_MAX)); 195 196 switch (level) { 197 default: 198 if (icp->ic_dir == AV1394_IR) { 199 av1394_ir_fini(icp); 200 } else { 201 av1394_it_fini(icp); 202 } 203 /* FALLTHRU */ 204 case 3: 205 mutex_enter(&ip->i_mutex); 206 av1394_as_free(&ip->i_mmap_as, icp->ic_mmap_off); 207 ip->i_ic[icp->ic_num] = NULL; 208 mutex_exit(&ip->i_mutex); 209 /* FALLTHRU */ 210 case 2: 211 av1394_ic_free_channel(icp); 212 /* FALLTHRU */ 213 case 1: 214 cv_destroy(&icp->ic_xfer_cv); 215 mutex_destroy(&icp->ic_mutex); 216 kmem_free(icp, sizeof (av1394_ic_t)); 217 } 218 } 219 220 static int 221 av1394_ic_validate_init_params(iec61883_isoch_init_t *ii) 222 { 223 int framesz; 224 225 ii->ii_error = 0; 226 if ((IEC61883_IMPL_VER_MAJOR(ii->ii_version) != 227 IEC61883_IMPL_VER_MAJOR(AV1394_IEC61883_VER)) || 228 (IEC61883_IMPL_VER_MINOR(ii->ii_version) > 229 IEC61883_IMPL_VER_MINOR(AV1394_IEC61883_VER))) { 230 ii->ii_error = IEC61883_ERR_VERSION; 231 return (EINVAL); 232 } 233 if ((ii->ii_pkt_size % 4) || (ii->ii_pkt_size > 512)) { 234 ii->ii_error = IEC61883_ERR_PKT_SIZE; 235 return (EINVAL); 236 } 237 framesz = ii->ii_frame_size * ii->ii_pkt_size; 238 if (framesz > AV1394_IC_FRAME_SIZE_MAX) { 239 ii->ii_error = IEC61883_ERR_NOMEM; 240 return (EINVAL); 241 } 242 if ((ii->ii_direction != IEC61883_DIR_RECV) && 243 (ii->ii_direction != IEC61883_DIR_XMIT)) { 244 ii->ii_error = IEC61883_ERR_INVAL; 245 return (EINVAL); 246 } 247 if (((ii->ii_direction == IEC61883_DIR_RECV) && 248 (ii->ii_frame_cnt < AV1394_IR_NFRAMES_MIN)) || 249 ((ii->ii_direction == IEC61883_DIR_XMIT) && 250 (ii->ii_frame_cnt < AV1394_IT_NFRAMES_MIN))) { 251 ii->ii_error = IEC61883_ERR_INVAL; 252 return (EINVAL); 253 } 254 if ((ii->ii_bus_speed != IEC61883_S100) && 255 (ii->ii_bus_speed != IEC61883_S200) && 256 (ii->ii_bus_speed != IEC61883_S400)) { 257 ii->ii_error = IEC61883_ERR_INVAL; 258 return (EINVAL); 259 } 260 if (ii->ii_channel == 0) { 261 ii->ii_error = IEC61883_ERR_INVAL; 262 return (EINVAL); 263 } 264 if ((ii->ii_flags & IEC61883_PRIV_ISOCH_NOALLOC) && 265 !av1394_ic_onebit(ii->ii_channel)) { 266 ii->ii_error = IEC61883_ERR_INVAL; 267 return (EINVAL); 268 } 269 /* the rest are xmit only */ 270 if (ii->ii_direction == IEC61883_DIR_RECV) { 271 return (0); 272 } 273 if (((ii->ii_rate_d != 0) || 274 (ii->ii_rate_n != IEC61883_RATE_N_DV_NTSC) && 275 (ii->ii_rate_n != IEC61883_RATE_N_DV_PAL)) && 276 ((ii->ii_rate_d <= 0) || (ii->ii_rate_n < 0) || 277 ((ii->ii_rate_n != 0) && (ii->ii_rate_d / ii->ii_rate_n < 2)))) { 278 ii->ii_error = IEC61883_ERR_INVAL; 279 return (EINVAL); 280 } 281 if (AV1394_TS_MODE_GET_OFF(ii->ii_ts_mode) + 282 AV1394_TS_MODE_GET_SIZE(ii->ii_ts_mode) > ii->ii_pkt_size) { 283 ii->ii_error = IEC61883_ERR_INVAL; 284 return (EINVAL); 285 } 286 return (0); 287 } 288 289 static void 290 av1394_ic_set_params(av1394_inst_t *avp, iec61883_isoch_init_t *ii, 291 av1394_ic_t *icp, int num) 292 { 293 av1394_ic_param_t *cp = &icp->ic_param; 294 295 mutex_enter(&icp->ic_mutex); 296 icp->ic_avp = avp; 297 icp->ic_num = num; 298 icp->ic_dir = (ii->ii_direction == IEC61883_DIR_RECV) ? 299 AV1394_IR : AV1394_IT; 300 icp->ic_pktsz = ii->ii_pkt_size; 301 icp->ic_npkts = ii->ii_frame_size; 302 icp->ic_framesz = icp->ic_pktsz * icp->ic_npkts; 303 icp->ic_nframes = ii->ii_frame_cnt; 304 cp->cp_bus_speed = ii->ii_bus_speed; 305 cp->cp_dbs = ii->ii_dbs; 306 cp->cp_fn = ii->ii_fn; 307 if (icp->ic_dir == AV1394_IT) { 308 if (ii->ii_rate_d == 0) { 309 switch (ii->ii_rate_n) { 310 case IEC61883_RATE_N_DV_NTSC: 311 cp->cp_n = av1394_rate_n_dv_ntsc; 312 cp->cp_d = av1394_rate_d_dv_ntsc; 313 break; 314 case IEC61883_RATE_N_DV_PAL: 315 cp->cp_n = av1394_rate_n_dv_pal; 316 cp->cp_d = av1394_rate_d_dv_pal; 317 break; 318 default: 319 ASSERT(0); /* can't happen */ 320 } 321 } else { 322 cp->cp_n = ii->ii_rate_n; 323 cp->cp_d = ii->ii_rate_d; 324 } 325 } 326 cp->cp_ts_mode = ii->ii_ts_mode; 327 mutex_exit(&icp->ic_mutex); 328 } 329 330 static int 331 av1394_ic_alloc_channel(av1394_ic_t *icp, uint64_t mask, int *num) 332 { 333 av1394_inst_t *avp = icp->ic_avp; 334 int ret, result; 335 t1394_isoch_singleinfo_t sii; 336 t1394_isoch_single_out_t so; 337 338 /* allocate isoch channel */ 339 sii.si_channel_mask = mask; 340 sii.si_bandwidth = icp->ic_pktsz; 341 sii.rsrc_fail_target = av1394_ic_rsrc_fail; 342 sii.single_evt_arg = icp; 343 sii.si_speed = icp->ic_param.cp_bus_speed; 344 345 ret = t1394_alloc_isoch_single(avp->av_t1394_hdl, &sii, 0, &so, 346 &icp->ic_sii_hdl, &result); 347 if (ret == DDI_SUCCESS) { 348 *num = so.channel_num; 349 } 350 return (ret); 351 } 352 353 static void 354 av1394_ic_free_channel(av1394_ic_t *icp) 355 { 356 av1394_inst_t *avp = icp->ic_avp; 357 358 if (icp->ic_sii_hdl != NULL) { 359 t1394_free_isoch_single(avp->av_t1394_hdl, &icp->ic_sii_hdl, 0); 360 } 361 } 362 363 /* 364 * 365 * --- memory allocation and mapping routines 366 * 367 * av1394_ic_alloc_pool() 368 * Allocate isoch pool for at least 'mincnt' and at most 'cnt' frames 369 * 'framesz' bytes each. The strategy is to allocate segments of reasonably 370 * large size, to avoid fragmentation and use resources efficiently in case 371 * of a large number of very small frames. 372 * 373 * Another problem is that RECV/SEND_BUF IXL commands can address limited 374 * amount of buffer space (AV1394_IXL_BUFSZ_MAX), and if segment size and 375 * buffer size are not aligned, it can make much harder to build IXL chains. 376 * To simplify things, segments shall always contain full frames. 377 * 378 * Function returns number of frames the resulting pool can hold. 379 */ 380 int 381 av1394_ic_alloc_pool(av1394_isoch_pool_t *pool, size_t framesz, int cnt, 382 int mincnt) 383 { 384 av1394_isoch_seg_t *seg; 385 int fps; /* frames per segment */ 386 int nsegs; 387 size_t totalsz, segsz; 388 int i; 389 int ret; 390 391 totalsz = framesz * cnt; 392 ASSERT(totalsz > 0); 393 394 /* request should be reasonable */ 395 if (btopr(totalsz) > physmem / AV1394_MEM_MAX_PERCENT) { 396 return (0); 397 } 398 399 /* calculate segment size and number of segments */ 400 segsz = framesz; 401 nsegs = cnt; 402 if (framesz < AV1394_IXL_BUFSZ_MAX / 2) { 403 fps = AV1394_IXL_BUFSZ_MAX / framesz; 404 segsz = framesz * fps; 405 nsegs = totalsz / segsz; 406 if ((totalsz % segsz) != 0) 407 nsegs++; /* remainder in non-full segment */ 408 } 409 ASSERT(segsz * nsegs >= totalsz); 410 411 /* allocate segment array */ 412 pool->ip_alloc_size = nsegs * sizeof (av1394_isoch_seg_t); 413 pool->ip_seg = kmem_zalloc(pool->ip_alloc_size, KM_SLEEP); 414 415 /* allocate page-aligned user-mappable memory for each segment */ 416 pool->ip_nsegs = 0; 417 pool->ip_size = 0; 418 pool->ip_umem_size = 0; 419 for (i = 0; i < nsegs; i++) { 420 seg = &pool->ip_seg[i]; 421 422 seg->is_umem_size = ptob(btopr(segsz)); 423 seg->is_kaddr = ddi_umem_alloc(seg->is_umem_size, 424 DDI_UMEM_SLEEP, &seg->is_umem_cookie); 425 if (seg->is_kaddr == NULL) { 426 break; 427 } 428 seg->is_size = segsz; 429 430 pool->ip_size += seg->is_size; 431 pool->ip_umem_size += seg->is_umem_size; 432 pool->ip_nsegs++; 433 } 434 435 /* number of frames the pool can hold */ 436 ret = pool->ip_size / framesz; 437 if (ret < mincnt) { 438 av1394_ic_free_pool(pool); 439 ret = 0; 440 } 441 442 return (ret); 443 } 444 445 void 446 av1394_ic_free_pool(av1394_isoch_pool_t *pool) 447 { 448 int i; 449 450 if (pool->ip_seg != NULL) { 451 for (i = 0; i < pool->ip_nsegs; i++) { 452 ddi_umem_free(pool->ip_seg[i].is_umem_cookie); 453 } 454 kmem_free(pool->ip_seg, pool->ip_alloc_size); 455 pool->ip_seg = NULL; 456 } 457 } 458 459 int 460 av1394_ic_dma_setup(av1394_ic_t *icp, av1394_isoch_pool_t *pool) 461 { 462 av1394_inst_t *avp = icp->ic_avp; 463 av1394_isoch_seg_t *isp; 464 uint_t dma_dir; 465 int ret; 466 int i; 467 int j; 468 469 dma_dir = (icp->ic_dir == AV1394_IR) ? DDI_DMA_READ : DDI_DMA_WRITE; 470 /* 471 * Alloc and bind a DMA handle for each segment. 472 * Note that we need packet size alignment, but since ddi_umem_alloc'ed 473 * memory is page-aligned and our packets are less than page size (yet) 474 * we don't need to do anything special here. 475 */ 476 for (i = 0; i < pool->ip_nsegs; i++) { 477 isp = &pool->ip_seg[i]; 478 479 ret = ddi_dma_alloc_handle(avp->av_dip, 480 &avp->av_attachinfo.dma_attr, DDI_DMA_DONTWAIT, NULL, 481 &isp->is_dma_hdl); 482 if (ret != DDI_SUCCESS) { 483 av1394_ic_dma_cleanup(icp, pool); 484 return (ret); 485 } 486 487 ret = ddi_dma_addr_bind_handle(isp->is_dma_hdl, NULL, 488 isp->is_kaddr, isp->is_size, 489 dma_dir | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, NULL, 490 &isp->is_dma_cookie[0], &isp->is_dma_ncookies); 491 492 if (ret != DDI_DMA_MAPPED) { 493 av1394_ic_dma_cleanup(icp, pool); 494 return (DDI_FAILURE); 495 } 496 497 if (isp->is_dma_ncookies > COOKIES) { 498 av1394_ic_dma_cleanup(icp, pool); 499 return (DDI_FAILURE); 500 } 501 502 for (j = 1; j < isp->is_dma_ncookies; ++j) 503 ddi_dma_nextcookie(isp->is_dma_hdl, 504 &isp->is_dma_cookie[j]); 505 } 506 507 return (DDI_SUCCESS); 508 } 509 510 /*ARGSUSED*/ 511 void 512 av1394_ic_dma_cleanup(av1394_ic_t *icp, av1394_isoch_pool_t *pool) 513 { 514 av1394_isoch_seg_t *seg; 515 int i; 516 517 for (i = 0; i < pool->ip_nsegs; i++) { 518 seg = &pool->ip_seg[i]; 519 if (seg->is_dma_hdl != NULL) { 520 if (seg->is_dma_ncookies > 0) { 521 (void) ddi_dma_unbind_handle(seg->is_dma_hdl); 522 } 523 ddi_dma_free_handle(&seg->is_dma_hdl); 524 } 525 } 526 } 527 528 /* 529 * sync frames for CPU access 530 */ 531 void 532 av1394_ic_dma_sync_frames(av1394_ic_t *icp, int idx, int cnt, 533 av1394_isoch_pool_t *pool, uint_t type) 534 { 535 int fps; /* frames per segment */ 536 int nsegs; /* number of segments for indicated frames */ 537 int seg; /* index of segment to sync */ 538 539 fps = icp->ic_nframes / pool->ip_nsegs; 540 541 nsegs = (cnt / fps) + 1; 542 543 seg = idx / fps; 544 545 for (;;) { 546 (void) ddi_dma_sync(pool->ip_seg[seg].is_dma_hdl, 0, 547 icp->ic_framesz, type); 548 549 --nsegs; 550 if (nsegs == 0) 551 break; 552 553 ++seg; 554 if (seg == pool->ip_nsegs) 555 seg = 0; /* wrap segment index */ 556 } 557 } 558 559 /* 560 * 561 * --- transfer 562 * 563 */ 564 int 565 av1394_ic_start(av1394_ic_t *icp) 566 { 567 if (icp->ic_dir == AV1394_IR) { 568 return (av1394_ir_start(icp)); 569 } else { 570 return (av1394_it_start(icp)); 571 } 572 } 573 574 int 575 av1394_ic_stop(av1394_ic_t *icp) 576 { 577 if (icp->ic_dir == AV1394_IR) { 578 return (av1394_ir_stop(icp)); 579 } else { 580 return (av1394_it_stop(icp)); 581 } 582 } 583 584 /* 585 * 586 * --- callbacks 587 * 588 */ 589 /*ARGSUSED*/ 590 static void 591 av1394_ic_rsrc_fail(t1394_isoch_single_handle_t t1394_sii_hdl, opaque_t arg, 592 t1394_isoch_rsrc_error_t fail_args) 593 { 594 /* XXX this could be handled more gracefully */ 595 cmn_err(CE_CONT, "av1394: can't reallocate isochronous resources" 596 " after bus reset\n"); 597 } 598 599 /* 600 * 601 * --- misc 602 * 603 * 604 * av1394_ic_ixl_seg_decomp() 605 * Calculate the best decomposition of a segment into buffers. 606 * Return number of buffers, buffer and tail buffer sizes. 607 * 608 * We are looking to divide a segment evenly into equally-sized or almost 609 * equally-sized buffers. Maximum buffer size is AV1394_IXL_BUFSZ_MAX. 610 * Algorithm: 611 * 1. If segment size divides evenly by maximum size, terminate. 612 * 2. n = number of maximum-size buffers than fits into the segment. 613 * 3. Divide the segment by n+1, calculate buffer size and tail 614 * (remainder) size. 615 * 4. If the tail can be appended to the last buffer and the resulting 616 * buffer is still less than maximum size, terminate. 617 * 5. Repeat steps 3-5 for n+2, n+3, ... until division is too small. 618 * 619 * Since all sizes are packet-aligned, we scale them down (divide by 620 * packet size) in the beginning, do all calculations and scale them up 621 * in the end. 622 */ 623 int 624 av1394_ic_ixl_seg_decomp(size_t segsz, size_t pktsz, size_t *bufszp, 625 size_t *tailszp) 626 { 627 size_t nbufs, bufsz, tailsz; 628 size_t maxsz = AV1394_IXL_BUFSZ_MAX; 629 630 ASSERT(segsz >= maxsz); 631 ASSERT(segsz % pktsz == 0); 632 633 if (segsz % maxsz == 0) { 634 *tailszp = *bufszp = maxsz; 635 return (segsz / *bufszp - 1); 636 } 637 638 maxsz /= pktsz; 639 segsz /= pktsz; 640 641 nbufs = segsz / maxsz; 642 do { 643 nbufs++; 644 bufsz = segsz / nbufs; 645 tailsz = bufsz + (segsz - bufsz * nbufs); 646 } while ((tailsz > maxsz) && ((segsz / (nbufs + 1)) > 1)); 647 nbufs--; 648 649 *bufszp = bufsz * pktsz; 650 *tailszp = tailsz * pktsz; 651 return (nbufs); 652 } 653 654 void 655 av1394_ic_ixl_dump(ixl1394_command_t *cmd) 656 { 657 ixl1394_callback_t *cb; 658 ixl1394_jump_t *jmp; 659 ixl1394_xfer_buf_t *buf; 660 ixl1394_xfer_pkt_t *pkt; 661 662 while (cmd) { 663 switch (cmd->ixl_opcode) { 664 case IXL1394_OP_LABEL: 665 cmn_err(CE_CONT, "%p: LABEL\n", (void *)cmd); 666 break; 667 case IXL1394_OP_RECV_BUF: 668 case IXL1394_OP_RECV_BUF_U: 669 buf = (ixl1394_xfer_buf_t *)cmd; 670 cmn_err(CE_CONT, "%p: RECV_BUF addr=%p size=%d " 671 "pkt_size=%d\n", (void *)cmd, (void *)buf->mem_bufp, 672 buf->size, buf->pkt_size); 673 break; 674 case IXL1394_OP_SEND_BUF: 675 case IXL1394_OP_SEND_BUF_U: 676 buf = (ixl1394_xfer_buf_t *)cmd; 677 cmn_err(CE_CONT, "%p: SEND_BUF addr=%p size=%d " 678 "pkt_size=%d\n", (void *)cmd, (void *)buf->mem_bufp, 679 buf->size, buf->pkt_size); 680 break; 681 case IXL1394_OP_SEND_PKT_ST: 682 pkt = (ixl1394_xfer_pkt_t *)cmd; 683 cmn_err(CE_CONT, "%p: SEND_PKT_ST addr=%p size=%d\n", 684 (void *)cmd, (void *)pkt->mem_bufp, pkt->size); 685 break; 686 case IXL1394_OP_CALLBACK: 687 case IXL1394_OP_CALLBACK_U: 688 cb = (ixl1394_callback_t *)cmd; 689 cmn_err(CE_CONT, "%p: CALLBACK %p\n", (void *)cmd, 690 (void *)cb->callback); 691 break; 692 case IXL1394_OP_JUMP: 693 jmp = (ixl1394_jump_t *)cmd; 694 cmn_err(CE_CONT, "%p: JUMP %p\n", (void *)cmd, 695 (void *)jmp->label); 696 break; 697 case IXL1394_OP_JUMP_U: 698 jmp = (ixl1394_jump_t *)cmd; 699 cmn_err(CE_CONT, "%p: JUMP_U %p\n", (void *)cmd, 700 (void *)jmp->label); 701 break; 702 case IXL1394_OP_STORE_TIMESTAMP: 703 cmn_err(CE_CONT, "%p: STORE_TIMESTAMP\n", (void *)cmd); 704 break; 705 default: 706 cmn_err(CE_CONT, "%p: other\n", (void *)cmd); 707 } 708 cmd = cmd->next_ixlp; 709 } 710 } 711 712 /* 713 * trigger a soft interrupt, if not already, for a given channel and type 714 */ 715 void 716 av1394_ic_trigger_softintr(av1394_ic_t *icp, int num, int preq) 717 { 718 av1394_isoch_t *ip = &icp->ic_avp->av_i; 719 uint64_t chmask = (1ULL << num); 720 721 if (((ip->i_softintr_ch & chmask) == 0) || 722 ((icp->ic_preq & preq) == 0)) { 723 ip->i_softintr_ch |= chmask; 724 icp->ic_preq |= preq; 725 ddi_trigger_softintr(ip->i_softintr_id); 726 } 727 } 728 729 /* 730 * reverse bits in a 64-bit word 731 */ 732 uint64_t 733 av1394_ic_bitreverse(uint64_t x) 734 { 735 x = (((x >> 1) & 0x5555555555555555) | ((x & 0x5555555555555555) << 1)); 736 x = (((x >> 2) & 0x3333333333333333) | ((x & 0x3333333333333333) << 2)); 737 x = (((x >> 4) & 0x0f0f0f0f0f0f0f0f) | ((x & 0x0f0f0f0f0f0f0f0f) << 4)); 738 x = (((x >> 8) & 0x00ff00ff00ff00ff) | ((x & 0x00ff00ff00ff00ff) << 8)); 739 x = (((x >> 16) & 0x0000ffff0000ffff) | 740 ((x & 0x0000ffff0000ffff) << 16)); 741 742 return ((x >> 32) | (x << 32)); 743 } 744 745 /* 746 * return B_TRUE if a 64-bit value has only one bit set to 1 747 */ 748 boolean_t 749 av1394_ic_onebit(uint64_t i) 750 { 751 return (((~i + 1) | ~i) == 0xFFFFFFFFFFFFFFFF); 752 } 753