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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Copyright (c) 2018, Joyent, Inc.
31 * routines common to isoch receive and isoch transmit
34 #include <sys/systm.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>
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
);
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
);
53 uint64_t av1394_ic_bitreverse(uint64_t);
54 boolean_t
av1394_ic_onebit(uint64_t);
56 #define AV1394_TNF_ENTER(func)
58 #define AV1394_TNF_EXIT(func)
61 extern int av1394_rate_n_dv_ntsc
;
62 extern int av1394_rate_d_dv_ntsc
;
63 extern int av1394_rate_n_dv_pal
;
64 extern int av1394_rate_d_dv_pal
;
68 av1394_ic_close(av1394_inst_t
*avp
, int flags
)
70 av1394_isoch_t
*ip
= &avp
->av_i
;
74 AV1394_TNF_ENTER(av1394_ic_close
);
76 /* cleanup channels in case application didn't */
77 for (i
= 0; i
< NELEM(ip
->i_ic
); i
++) {
80 (void) av1394_ic_stop(icp
);
85 AV1394_TNF_EXIT(av1394_ic_close
);
91 * Channel allocation and initialization.
94 av1394_ic_init(av1394_inst_t
*avp
, iec61883_isoch_init_t
*ii
,
97 av1394_isoch_t
*ip
= &avp
->av_i
;
98 av1394_ic_t
*icp
= NULL
;
100 av1394_isoch_pool_t
*pool
;
101 uint64_t mask
; /* channel mask */
103 ddi_iblock_cookie_t ibc
= avp
->av_attachinfo
.iblock_cookie
;
105 AV1394_TNF_ENTER(av1394_ic_init
);
107 ii
->ii_frame_rcnt
= 0;
111 if ((ret
= av1394_ic_validate_init_params(ii
)) != 0) {
112 AV1394_TNF_EXIT(av1394_ic_init
);
116 /* allocate channel structure */
117 icp
= kmem_zalloc(sizeof (av1394_ic_t
), KM_SLEEP
);
119 mutex_init(&icp
->ic_mutex
, NULL
, MUTEX_DRIVER
, ibc
);
120 cv_init(&icp
->ic_xfer_cv
, NULL
, CV_DRIVER
, NULL
);
122 av1394_ic_set_params(avp
, ii
, icp
, -1);
124 /* allocate isoch channel and bandwidth, except for broadcast */
125 if (ii
->ii_channel
== (1ULL << 63)) {
127 } else if (ii
->ii_flags
& IEC61883_PRIV_ISOCH_NOALLOC
) {
128 num
= lowbit(ii
->ii_channel
) - 1;
130 mask
= av1394_ic_bitreverse(ii
->ii_channel
);
131 ret
= av1394_ic_alloc_channel(icp
, mask
, &num
);
132 if (ret
!= DDI_SUCCESS
) {
133 ii
->ii_error
= IEC61883_ERR_NOCHANNEL
;
134 av1394_ic_cleanup(icp
, 1);
135 AV1394_TNF_EXIT(av1394_ic_init
);
139 ASSERT((num
>= 0) && (num
< 64));
141 mutex_enter(&icp
->ic_mutex
);
143 mutex_exit(&icp
->ic_mutex
);
145 mutex_enter(&ip
->i_mutex
);
146 if (ip
->i_ic
[num
] != NULL
) {
147 mutex_exit(&ip
->i_mutex
);
148 ii
->ii_error
= IEC61883_ERR_NOCHANNEL
;
149 av1394_ic_cleanup(icp
, 2);
150 AV1394_TNF_EXIT(av1394_ic_init
);
154 mutex_exit(&ip
->i_mutex
);
156 /* do direction specific initialization */
157 if (icp
->ic_dir
== AV1394_IR
) {
158 ret
= av1394_ir_init(icp
, &ii
->ii_error
);
159 pool
= &icp
->ic_ir
.ir_data_pool
;
161 ret
= av1394_it_init(icp
, &ii
->ii_error
);
162 pool
= &icp
->ic_it
.it_data_pool
;
166 av1394_ic_cleanup(icp
, 3);
167 AV1394_TNF_EXIT(av1394_ic_init
);
171 /* allocate mmap space */
172 mutex_enter(&ip
->i_mutex
);
173 mutex_enter(&icp
->ic_mutex
);
174 icp
->ic_mmap_sz
= pool
->ip_umem_size
;
175 icp
->ic_mmap_off
= av1394_as_alloc(&ip
->i_mmap_as
, icp
->ic_mmap_sz
);
177 icp
->ic_state
= AV1394_IC_IDLE
;
180 ii
->ii_handle
= icp
->ic_num
;
181 ii
->ii_frame_rcnt
= icp
->ic_nframes
;
182 ii
->ii_mmap_off
= icp
->ic_mmap_off
;
183 ii
->ii_rchannel
= icp
->ic_num
;
184 mutex_exit(&icp
->ic_mutex
);
185 mutex_exit(&ip
->i_mutex
);
187 AV1394_TNF_EXIT(av1394_ic_init
);
192 av1394_ic_fini(av1394_ic_t
*icp
)
194 AV1394_TNF_ENTER(av1394_ic_fini
);
196 av1394_ic_cleanup(icp
, AV1394_CLEANUP_LEVEL_MAX
);
198 AV1394_TNF_EXIT(av1394_ic_fini
);
203 * --- configuration routines
207 av1394_ic_cleanup(av1394_ic_t
*icp
, int level
)
209 av1394_inst_t
*avp
= icp
->ic_avp
;
210 av1394_isoch_t
*ip
= &avp
->av_i
;
212 ASSERT((level
> 0) && (level
<= AV1394_CLEANUP_LEVEL_MAX
));
216 if (icp
->ic_dir
== AV1394_IR
) {
223 mutex_enter(&ip
->i_mutex
);
224 av1394_as_free(&ip
->i_mmap_as
, icp
->ic_mmap_off
);
225 ip
->i_ic
[icp
->ic_num
] = NULL
;
226 mutex_exit(&ip
->i_mutex
);
229 av1394_ic_free_channel(icp
);
232 cv_destroy(&icp
->ic_xfer_cv
);
233 mutex_destroy(&icp
->ic_mutex
);
234 kmem_free(icp
, sizeof (av1394_ic_t
));
239 av1394_ic_validate_init_params(iec61883_isoch_init_t
*ii
)
244 if ((IEC61883_IMPL_VER_MAJOR(ii
->ii_version
) !=
245 IEC61883_IMPL_VER_MAJOR(AV1394_IEC61883_VER
)) ||
246 (IEC61883_IMPL_VER_MINOR(ii
->ii_version
) >
247 IEC61883_IMPL_VER_MINOR(AV1394_IEC61883_VER
))) {
248 ii
->ii_error
= IEC61883_ERR_VERSION
;
251 if ((ii
->ii_pkt_size
% 4) || (ii
->ii_pkt_size
> 512)) {
252 ii
->ii_error
= IEC61883_ERR_PKT_SIZE
;
255 framesz
= ii
->ii_frame_size
* ii
->ii_pkt_size
;
256 if (framesz
> AV1394_IC_FRAME_SIZE_MAX
) {
257 ii
->ii_error
= IEC61883_ERR_NOMEM
;
260 if ((ii
->ii_direction
!= IEC61883_DIR_RECV
) &&
261 (ii
->ii_direction
!= IEC61883_DIR_XMIT
)) {
262 ii
->ii_error
= IEC61883_ERR_INVAL
;
265 if (((ii
->ii_direction
== IEC61883_DIR_RECV
) &&
266 (ii
->ii_frame_cnt
< AV1394_IR_NFRAMES_MIN
)) ||
267 ((ii
->ii_direction
== IEC61883_DIR_XMIT
) &&
268 (ii
->ii_frame_cnt
< AV1394_IT_NFRAMES_MIN
))) {
269 ii
->ii_error
= IEC61883_ERR_INVAL
;
272 if ((ii
->ii_bus_speed
!= IEC61883_S100
) &&
273 (ii
->ii_bus_speed
!= IEC61883_S200
) &&
274 (ii
->ii_bus_speed
!= IEC61883_S400
)) {
275 ii
->ii_error
= IEC61883_ERR_INVAL
;
278 if (ii
->ii_channel
== 0) {
279 ii
->ii_error
= IEC61883_ERR_INVAL
;
282 if ((ii
->ii_flags
& IEC61883_PRIV_ISOCH_NOALLOC
) &&
283 !av1394_ic_onebit(ii
->ii_channel
)) {
284 ii
->ii_error
= IEC61883_ERR_INVAL
;
287 /* the rest are xmit only */
288 if (ii
->ii_direction
== IEC61883_DIR_RECV
) {
291 if (((ii
->ii_rate_d
!= 0) ||
292 (ii
->ii_rate_n
!= IEC61883_RATE_N_DV_NTSC
) &&
293 (ii
->ii_rate_n
!= IEC61883_RATE_N_DV_PAL
)) &&
294 ((ii
->ii_rate_d
<= 0) || (ii
->ii_rate_n
< 0) ||
295 ((ii
->ii_rate_n
!= 0) && (ii
->ii_rate_d
/ ii
->ii_rate_n
< 2)))) {
296 ii
->ii_error
= IEC61883_ERR_INVAL
;
299 if (AV1394_TS_MODE_GET_OFF(ii
->ii_ts_mode
) +
300 AV1394_TS_MODE_GET_SIZE(ii
->ii_ts_mode
) > ii
->ii_pkt_size
) {
301 ii
->ii_error
= IEC61883_ERR_INVAL
;
308 av1394_ic_set_params(av1394_inst_t
*avp
, iec61883_isoch_init_t
*ii
,
309 av1394_ic_t
*icp
, int num
)
311 av1394_ic_param_t
*cp
= &icp
->ic_param
;
313 mutex_enter(&icp
->ic_mutex
);
316 icp
->ic_dir
= (ii
->ii_direction
== IEC61883_DIR_RECV
) ?
317 AV1394_IR
: AV1394_IT
;
318 icp
->ic_pktsz
= ii
->ii_pkt_size
;
319 icp
->ic_npkts
= ii
->ii_frame_size
;
320 icp
->ic_framesz
= icp
->ic_pktsz
* icp
->ic_npkts
;
321 icp
->ic_nframes
= ii
->ii_frame_cnt
;
322 cp
->cp_bus_speed
= ii
->ii_bus_speed
;
323 cp
->cp_dbs
= ii
->ii_dbs
;
324 cp
->cp_fn
= ii
->ii_fn
;
325 if (icp
->ic_dir
== AV1394_IT
) {
326 if (ii
->ii_rate_d
== 0) {
327 switch (ii
->ii_rate_n
) {
328 case IEC61883_RATE_N_DV_NTSC
:
329 cp
->cp_n
= av1394_rate_n_dv_ntsc
;
330 cp
->cp_d
= av1394_rate_d_dv_ntsc
;
332 case IEC61883_RATE_N_DV_PAL
:
333 cp
->cp_n
= av1394_rate_n_dv_pal
;
334 cp
->cp_d
= av1394_rate_d_dv_pal
;
337 ASSERT(0); /* can't happen */
340 cp
->cp_n
= ii
->ii_rate_n
;
341 cp
->cp_d
= ii
->ii_rate_d
;
344 cp
->cp_ts_mode
= ii
->ii_ts_mode
;
345 mutex_exit(&icp
->ic_mutex
);
349 av1394_ic_alloc_channel(av1394_ic_t
*icp
, uint64_t mask
, int *num
)
351 av1394_inst_t
*avp
= icp
->ic_avp
;
353 t1394_isoch_singleinfo_t sii
;
354 t1394_isoch_single_out_t so
;
356 /* allocate isoch channel */
357 sii
.si_channel_mask
= mask
;
358 sii
.si_bandwidth
= icp
->ic_pktsz
;
359 sii
.rsrc_fail_target
= av1394_ic_rsrc_fail
;
360 sii
.single_evt_arg
= icp
;
361 sii
.si_speed
= icp
->ic_param
.cp_bus_speed
;
363 ret
= t1394_alloc_isoch_single(avp
->av_t1394_hdl
, &sii
, 0, &so
,
364 &icp
->ic_sii_hdl
, &result
);
365 if (ret
!= DDI_SUCCESS
) {
367 *num
= so
.channel_num
;
373 av1394_ic_free_channel(av1394_ic_t
*icp
)
375 av1394_inst_t
*avp
= icp
->ic_avp
;
377 if (icp
->ic_sii_hdl
!= NULL
) {
378 t1394_free_isoch_single(avp
->av_t1394_hdl
, &icp
->ic_sii_hdl
, 0);
384 * --- memory allocation and mapping routines
386 * av1394_ic_alloc_pool()
387 * Allocate isoch pool for at least 'mincnt' and at most 'cnt' frames
388 * 'framesz' bytes each. The strategy is to allocate segments of reasonably
389 * large size, to avoid fragmentation and use resources efficiently in case
390 * of a large number of very small frames.
392 * Another problem is that RECV/SEND_BUF IXL commands can address limited
393 * amount of buffer space (AV1394_IXL_BUFSZ_MAX), and if segment size and
394 * buffer size are not aligned, it can make much harder to build IXL chains.
395 * To simplify things, segments shall always contain full frames.
397 * Function returns number of frames the resulting pool can hold.
400 av1394_ic_alloc_pool(av1394_isoch_pool_t
*pool
, size_t framesz
, int cnt
,
403 av1394_isoch_seg_t
*seg
;
404 int fps
; /* frames per segment */
406 size_t totalsz
, segsz
;
410 AV1394_TNF_ENTER(av1394_ic_alloc_pool
);
412 totalsz
= framesz
* cnt
;
415 /* request should be reasonable */
416 if (btopr(totalsz
) > physmem
/ AV1394_MEM_MAX_PERCENT
) {
417 AV1394_TNF_EXIT(av1394_ic_alloc_pool
);
421 /* calculate segment size and number of segments */
424 if (framesz
< AV1394_IXL_BUFSZ_MAX
/ 2) {
425 fps
= AV1394_IXL_BUFSZ_MAX
/ framesz
;
426 segsz
= framesz
* fps
;
427 nsegs
= totalsz
/ segsz
;
428 if ((totalsz
% segsz
) != 0)
429 nsegs
++; /* remainder in non-full segment */
431 ASSERT(segsz
* nsegs
>= totalsz
);
433 /* allocate segment array */
434 pool
->ip_alloc_size
= nsegs
* sizeof (av1394_isoch_seg_t
);
435 pool
->ip_seg
= kmem_zalloc(pool
->ip_alloc_size
, KM_SLEEP
);
437 /* allocate page-aligned user-mappable memory for each segment */
440 pool
->ip_umem_size
= 0;
441 for (i
= 0; i
< nsegs
; i
++) {
442 seg
= &pool
->ip_seg
[i
];
444 seg
->is_umem_size
= ptob(btopr(segsz
));
445 seg
->is_kaddr
= ddi_umem_alloc(seg
->is_umem_size
,
446 DDI_UMEM_SLEEP
, &seg
->is_umem_cookie
);
447 if (seg
->is_kaddr
== NULL
) {
450 seg
->is_size
= segsz
;
452 pool
->ip_size
+= seg
->is_size
;
453 pool
->ip_umem_size
+= seg
->is_umem_size
;
457 /* number of frames the pool can hold */
458 ret
= pool
->ip_size
/ framesz
;
460 av1394_ic_free_pool(pool
);
464 AV1394_TNF_EXIT(av1394_ic_alloc_pool
);
469 av1394_ic_free_pool(av1394_isoch_pool_t
*pool
)
473 AV1394_TNF_ENTER(av1394_ic_free_pool
);
475 if (pool
->ip_seg
!= NULL
) {
476 for (i
= 0; i
< pool
->ip_nsegs
; i
++) {
477 ddi_umem_free(pool
->ip_seg
[i
].is_umem_cookie
);
479 kmem_free(pool
->ip_seg
, pool
->ip_alloc_size
);
483 AV1394_TNF_EXIT(av1394_ic_free_pool
);
487 av1394_ic_dma_setup(av1394_ic_t
*icp
, av1394_isoch_pool_t
*pool
)
489 av1394_inst_t
*avp
= icp
->ic_avp
;
490 av1394_isoch_seg_t
*isp
;
496 AV1394_TNF_ENTER(av1394_ic_dma_setup
);
498 dma_dir
= (icp
->ic_dir
== AV1394_IR
) ? DDI_DMA_READ
: DDI_DMA_WRITE
;
500 * Alloc and bind a DMA handle for each segment.
501 * Note that we need packet size alignment, but since ddi_umem_alloc'ed
502 * memory is page-aligned and our packets are less than page size (yet)
503 * we don't need to do anything special here.
505 for (i
= 0; i
< pool
->ip_nsegs
; i
++) {
506 isp
= &pool
->ip_seg
[i
];
508 ret
= ddi_dma_alloc_handle(avp
->av_dip
,
509 &avp
->av_attachinfo
.dma_attr
, DDI_DMA_DONTWAIT
, NULL
,
511 if (ret
!= DDI_SUCCESS
) {
512 av1394_ic_dma_cleanup(icp
, pool
);
513 AV1394_TNF_EXIT(av1394_ic_dma_setup
);
517 ret
= ddi_dma_addr_bind_handle(isp
->is_dma_hdl
, NULL
,
518 isp
->is_kaddr
, isp
->is_size
,
519 dma_dir
| DDI_DMA_CONSISTENT
, DDI_DMA_DONTWAIT
, NULL
,
520 &isp
->is_dma_cookie
[0], &isp
->is_dma_ncookies
);
522 if (ret
!= DDI_DMA_MAPPED
) {
523 av1394_ic_dma_cleanup(icp
, pool
);
524 AV1394_TNF_EXIT(av1394_ic_dma_setup
);
525 return (DDI_FAILURE
);
528 if (isp
->is_dma_ncookies
> COOKIES
) {
529 av1394_ic_dma_cleanup(icp
, pool
);
530 AV1394_TNF_EXIT(av1394_ic_dma_setup
);
531 return (DDI_FAILURE
);
534 for (j
= 1; j
< isp
->is_dma_ncookies
; ++j
)
535 ddi_dma_nextcookie(isp
->is_dma_hdl
,
536 &isp
->is_dma_cookie
[j
]);
539 AV1394_TNF_EXIT(av1394_ic_dma_setup
);
540 return (DDI_SUCCESS
);
545 av1394_ic_dma_cleanup(av1394_ic_t
*icp
, av1394_isoch_pool_t
*pool
)
547 av1394_isoch_seg_t
*seg
;
550 AV1394_TNF_ENTER(av1394_ic_dma_cleanup
);
552 for (i
= 0; i
< pool
->ip_nsegs
; i
++) {
553 seg
= &pool
->ip_seg
[i
];
554 if (seg
->is_dma_hdl
!= NULL
) {
555 if (seg
->is_dma_ncookies
> 0) {
556 (void) ddi_dma_unbind_handle(seg
->is_dma_hdl
);
558 ddi_dma_free_handle(&seg
->is_dma_hdl
);
562 AV1394_TNF_EXIT(av1394_ic_dma_cleanup
);
566 * sync frames for CPU access
569 av1394_ic_dma_sync_frames(av1394_ic_t
*icp
, int idx
, int cnt
,
570 av1394_isoch_pool_t
*pool
, uint_t type
)
572 int fps
; /* frames per segment */
573 int nsegs
; /* number of segments for indicated frames */
574 int seg
; /* index of segment to sync */
576 fps
= icp
->ic_nframes
/ pool
->ip_nsegs
;
578 nsegs
= (cnt
/ fps
) + 1;
583 (void) ddi_dma_sync(pool
->ip_seg
[seg
].is_dma_hdl
, 0,
584 icp
->ic_framesz
, type
);
591 if (seg
== pool
->ip_nsegs
)
592 seg
= 0; /* wrap segment index */
602 av1394_ic_start(av1394_ic_t
*icp
)
604 if (icp
->ic_dir
== AV1394_IR
) {
605 return (av1394_ir_start(icp
));
607 return (av1394_it_start(icp
));
612 av1394_ic_stop(av1394_ic_t
*icp
)
614 if (icp
->ic_dir
== AV1394_IR
) {
615 return (av1394_ir_stop(icp
));
617 return (av1394_it_stop(icp
));
628 av1394_ic_rsrc_fail(t1394_isoch_single_handle_t t1394_sii_hdl
, opaque_t arg
,
629 t1394_isoch_rsrc_error_t fail_args
)
631 AV1394_TNF_ENTER(av1394_ic_rsrc_fail
);
633 /* XXX this could be handled more gracefully */
634 cmn_err(CE_CONT
, "av1394: can't reallocate isochronous resources"
635 " after bus reset\n");
637 AV1394_TNF_EXIT(av1394_ic_rsrc_fail
);
645 * av1394_ic_ixl_seg_decomp()
646 * Calculate the best decomposition of a segment into buffers.
647 * Return number of buffers, buffer and tail buffer sizes.
649 * We are looking to divide a segment evenly into equally-sized or almost
650 * equally-sized buffers. Maximum buffer size is AV1394_IXL_BUFSZ_MAX.
652 * 1. If segment size divides evenly by maximum size, terminate.
653 * 2. n = number of maximum-size buffers than fits into the segment.
654 * 3. Divide the segment by n+1, calculate buffer size and tail
656 * 4. If the tail can be appended to the last buffer and the resulting
657 * buffer is still less than maximum size, terminate.
658 * 5. Repeat steps 3-5 for n+2, n+3, ... until division is too small.
660 * Since all sizes are packet-aligned, we scale them down (divide by
661 * packet size) in the beginning, do all calculations and scale them up
665 av1394_ic_ixl_seg_decomp(size_t segsz
, size_t pktsz
, size_t *bufszp
,
668 size_t nbufs
, bufsz
, tailsz
;
669 size_t maxsz
= AV1394_IXL_BUFSZ_MAX
;
671 ASSERT(segsz
>= maxsz
);
672 ASSERT(segsz
% pktsz
== 0);
674 if (segsz
% maxsz
== 0) {
675 *tailszp
= *bufszp
= maxsz
;
676 return (segsz
/ *bufszp
- 1);
682 nbufs
= segsz
/ maxsz
;
685 bufsz
= segsz
/ nbufs
;
686 tailsz
= bufsz
+ (segsz
- bufsz
* nbufs
);
687 } while ((tailsz
> maxsz
) && ((segsz
/ (nbufs
+ 1)) > 1));
690 *bufszp
= bufsz
* pktsz
;
691 *tailszp
= tailsz
* pktsz
;
696 av1394_ic_ixl_dump(ixl1394_command_t
*cmd
)
698 ixl1394_callback_t
*cb
;
700 ixl1394_xfer_buf_t
*buf
;
701 ixl1394_xfer_pkt_t
*pkt
;
704 switch (cmd
->ixl_opcode
) {
705 case IXL1394_OP_LABEL
:
706 cmn_err(CE_CONT
, "%p: LABEL\n", (void *)cmd
);
708 case IXL1394_OP_RECV_BUF
:
709 case IXL1394_OP_RECV_BUF_U
:
710 buf
= (ixl1394_xfer_buf_t
*)cmd
;
711 cmn_err(CE_CONT
, "%p: RECV_BUF addr=%p size=%d "
712 "pkt_size=%d\n", (void *)cmd
, (void *)buf
->mem_bufp
,
713 buf
->size
, buf
->pkt_size
);
715 case IXL1394_OP_SEND_BUF
:
716 case IXL1394_OP_SEND_BUF_U
:
717 buf
= (ixl1394_xfer_buf_t
*)cmd
;
718 cmn_err(CE_CONT
, "%p: SEND_BUF addr=%p size=%d "
719 "pkt_size=%d\n", (void *)cmd
, (void *)buf
->mem_bufp
,
720 buf
->size
, buf
->pkt_size
);
722 case IXL1394_OP_SEND_PKT_ST
:
723 pkt
= (ixl1394_xfer_pkt_t
*)cmd
;
724 cmn_err(CE_CONT
, "%p: SEND_PKT_ST addr=%p size=%d\n",
725 (void *)cmd
, (void *)pkt
->mem_bufp
, pkt
->size
);
727 case IXL1394_OP_CALLBACK
:
728 case IXL1394_OP_CALLBACK_U
:
729 cb
= (ixl1394_callback_t
*)cmd
;
730 cmn_err(CE_CONT
, "%p: CALLBACK %p\n", (void *)cmd
,
731 (void *)cb
->callback
);
733 case IXL1394_OP_JUMP
:
734 jmp
= (ixl1394_jump_t
*)cmd
;
735 cmn_err(CE_CONT
, "%p: JUMP %p\n", (void *)cmd
,
738 case IXL1394_OP_JUMP_U
:
739 jmp
= (ixl1394_jump_t
*)cmd
;
740 cmn_err(CE_CONT
, "%p: JUMP_U %p\n", (void *)cmd
,
743 case IXL1394_OP_STORE_TIMESTAMP
:
744 cmn_err(CE_CONT
, "%p: STORE_TIMESTAMP\n", (void *)cmd
);
747 cmn_err(CE_CONT
, "%p: other\n", (void *)cmd
);
749 cmd
= cmd
->next_ixlp
;
754 * trigger a soft interrupt, if not already, for a given channel and type
757 av1394_ic_trigger_softintr(av1394_ic_t
*icp
, int num
, int preq
)
759 av1394_isoch_t
*ip
= &icp
->ic_avp
->av_i
;
760 uint64_t chmask
= (1ULL << num
);
762 if (((ip
->i_softintr_ch
& chmask
) == 0) ||
763 ((icp
->ic_preq
& preq
) == 0)) {
764 ip
->i_softintr_ch
|= chmask
;
765 icp
->ic_preq
|= preq
;
766 ddi_trigger_softintr(ip
->i_softintr_id
);
771 * reverse bits in a 64-bit word
774 av1394_ic_bitreverse(uint64_t x
)
776 x
= (((x
>> 1) & 0x5555555555555555) | ((x
& 0x5555555555555555) << 1));
777 x
= (((x
>> 2) & 0x3333333333333333) | ((x
& 0x3333333333333333) << 2));
778 x
= (((x
>> 4) & 0x0f0f0f0f0f0f0f0f) | ((x
& 0x0f0f0f0f0f0f0f0f) << 4));
779 x
= (((x
>> 8) & 0x00ff00ff00ff00ff) | ((x
& 0x00ff00ff00ff00ff) << 8));
780 x
= (((x
>> 16) & 0x0000ffff0000ffff) |
781 ((x
& 0x0000ffff0000ffff) << 16));
783 return ((x
>> 32) | (x
<< 32));
787 * return B_TRUE if a 64-bit value has only one bit set to 1
790 av1394_ic_onebit(uint64_t i
)
792 return (((~i
+ 1) | ~i
) == 0xFFFFFFFFFFFFFFFF);