xref: /illumos-gate/usr/src/uts/common/io/1394/targets/dcam1394/dcam_frame.c (revision a0955b86cd77e22e80846428a5065e871b6d8eb8)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * dcam_frame.c
31  *
32  * dcam1394 driver.  Support for video frame access.
33  */
34 
35 #include <sys/int_limits.h>
36 #include <sys/types.h>
37 #include <sys/kmem.h>
38 #include <sys/cmn_err.h>
39 #include <sys/1394/targets/dcam1394/dcam.h>
40 #include <sys/1394/targets/dcam1394/dcam_frame.h>
41 #include <sys/tnf_probe.h>
42 #include <sys/dcam/dcam1394_io.h>
43 
44 #include <sys/1394/targets/dcam1394/dcam_reg.h>
45 
46 static void dcam_free_resources(dcam_state_t *);
47 
48 typedef struct dcam_mode_info_s {
49 	int bytes_per_pkt;
50 	int pkts_per_frame;
51 } dcam_mode_info_t;
52 
53 /*
54  * packets per frame
55  *
56  * 30fps
57  *  mode_0 1/2h, 60q,  240b
58  *  mode_1 1h,  160q,  640
59  *  mode_2 2h,  480q, 1920
60  *  mode_3 2h,  640q, 2560
61  *  mode_4 2h,  960q, 3840
62  *  mode_5 2h,  320q, 1280
63  *
64  * 15fps
65  *  mode_0 1/4h, 30q,  120
66  *  mode_1 1/2h, 80q,  320
67  *  mode_2 1h,  240q,  960
68  *  mode_3 1h,  320q, 1280
69  *  mode_4 1h,  480q, 1920
70  *  mode_5 1h,  160q,  640
71  *
72  * 7.5fps
73  *  mode_0 1/8h,  15q,  60
74  *  mode_1 1/4h,  40q, 160
75  *  mode_2 1/2h, 120q, 480
76  *  mode_3 1/2h, 160q, 640
77  *  mode_4 1/2h, 240q, 960
78  *  mode_5 1/2h,  80q, 320
79  *
80  * 3.75fps
81  *  mode_0 x
82  *  mode_1 1/8h,  20q,  80
83  *  mode_2 1/4h,  60q, 240
84  *  mode_3 1/4h,  80q, 320
85  *  mode_4 1/4h, 120q, 480
86  *  mode_5 1/4h,  40q, 160
87  *
88  * 60fps
89  *  mode_5 4H, 640q, 2560
90  *
91  */
92 
93 /* indexed by vid mode, frame rate */
94 static int g_bytes_per_packet[6][5] = {
95 
96 	/* fps:			3.75	7.5	15	30	60 */
97 	/* vid mode 0 */	-1,	60,	120,	240,	-1,
98 	/* vid mode 1 */	80,	160,	320,	640,	-1,
99 	/* vid mode 2 */	240,	480,	960,	1920,	-1,
100 	/* vid mode 3 */	320,	640,	1280,	2560,	-1,
101 	/* vid mode 4 */	480,	960,	1920,	3840,	-1,
102 	/* vid mode 5 */	160,	320,	640,	1280,	2560
103 };
104 
105 /* indexed by vid mode */
106 static int g_bytes_per_frame[6] = {
107     57600,
108     153600,
109     460800,
110     614400,
111     921600,
112     307200
113 };
114 
115 
116 static
117 void dcam_rsrc_fail(t1394_isoch_single_handle_t	t1394_single_hdl,
118     opaque_t single_evt_arg, t1394_isoch_rsrc_error_t fail_args);
119 
120 /*
121  * dcam1394_ioctl_frame_rcv_start
122  */
123 int
124 dcam1394_ioctl_frame_rcv_start(dcam_state_t *softc_p)
125 {
126 	if (!(softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT)) {
127 
128 		if (dcam_frame_rcv_init(softc_p, softc_p->cur_vid_mode,
129 		    softc_p->cur_frame_rate, softc_p->cur_ring_buff_capacity)) {
130 
131 			dcam_free_resources(softc_p);
132 			return (1);
133 		}
134 
135 		softc_p->flags |= DCAM1394_FLAG_FRAME_RCV_INIT;
136 	}
137 
138 	if (dcam_frame_rcv_start(softc_p)) {
139 		return (1);
140 	}
141 
142 	return (0);
143 }
144 
145 
146 /*
147  * dcam_frame_rcv_init
148  */
149 int
150 dcam_frame_rcv_init(dcam_state_t *softc_p, int vid_mode, int frame_rate,
151     int ring_buff_capacity)
152 {
153 	int16_t			bytes_per_pkt;	/* # pkt bytes + overhead */
154 	int			bytes_per_frame;
155 	size_t			frame;
156 	int			cookie;
157 	int			failure;
158 	id1394_isoch_dmainfo_t	isoch_args;	/* for alloc isoch call */
159 	ixl1394_command_t	*last_ixlp;	/* last ixl in chain, */
160 						/* used for appending ixls */
161 	ixl1394_command_t	*new_ixl_cmdp;	/* new ixl command */
162 	ixl1394_set_syncwait_t	*new_ixl_sswp;	/* new ixl set syncwait */
163 	ixl1394_xfer_pkt_t	*new_ixl_xfpp;	/* new ixl xfer packet */
164 	ixl1394_xfer_buf_t	*new_ixl_xfbp;	/* new ixl xfer buffer */
165 	ixl1394_callback_t	*new_ixl_cbp;	/* new ixl callback */
166 	ixl1394_jump_t		*new_ixl_jmpp;	/* new ixl jump */
167 	int32_t			result;		/* errno from alloc_isoch_dma */
168 	buff_info_t		*buff_info_p;
169 	dcam1394_reg_io_t	reg_io;
170 	uint_t			data;
171 	size_t			num_bytes, num_bytes_left;
172 	size_t			num_xfer_cmds, xfer_cmd;
173 	size_t			max_ixl_buff_size;
174 	uint64_t		ixl_buff_kaddr;
175 	caddr_t			ixl_buff_vaddr;
176 
177 	bytes_per_pkt = g_bytes_per_packet[vid_mode][frame_rate];
178 	if (bytes_per_pkt == -1) {
179 		return (1);
180 	}
181 
182 	bytes_per_frame = g_bytes_per_frame[vid_mode];
183 
184 	if ((softc_p->ring_buff_p = ring_buff_create(softc_p,
185 	    (size_t)ring_buff_capacity, (size_t)bytes_per_frame)) == NULL) {
186 		return (1);
187 	}
188 
189 	softc_p->ring_buff_p->read_ptr_pos[0] = 0;
190 
191 	/* allocate isoch channel */
192 	softc_p->sii.si_channel_mask	= 0xFFFF000000000000;
193 	softc_p->sii.si_bandwidth	= bytes_per_pkt;
194 	softc_p->sii.rsrc_fail_target	= dcam_rsrc_fail;
195 	softc_p->sii.single_evt_arg	= softc_p;
196 	softc_p->sii.si_speed		= softc_p->targetinfo.current_max_speed;
197 
198 	if (t1394_alloc_isoch_single(softc_p->sl_handle,
199 	    &softc_p->sii, 0, &softc_p->sii_output_args, &softc_p->sii_hdl,
200 	    &failure) != DDI_SUCCESS) {
201 		return (1);
202 	}
203 
204 	/*
205 	 * At this point, all buffer memory has been allocated and
206 	 * mapped, and is tracked on a linear linked list.  Now need to
207 	 * build the IXL.  Done on a frame-by-frame basis.  Could
208 	 * theoretically have been done at the same time as the mem alloc
209 	 * above, but hey, no need to be so fancy here.
210 	 *
211 	 * ixl buff size is bound by SHRT_MAX and needs to
212 	 * be a multiple of packet size
213 	 */
214 	max_ixl_buff_size = (SHRT_MAX / bytes_per_pkt) * bytes_per_pkt;
215 
216 	/* for each frame build frame's ixl list */
217 	for (frame = 0; frame < softc_p->ring_buff_p->num_buffs; frame++) {
218 
219 		buff_info_p = &(softc_p->ring_buff_p->buff_info_array_p[frame]);
220 
221 		/*
222 		 * if this is the 1st frame, put a IXL label at the top so a
223 		 * loop can be created later
224 		 */
225 		if (frame == 0) {
226 			new_ixl_cmdp = kmem_zalloc(
227 					sizeof (ixl1394_label_t), KM_SLEEP);
228 			softc_p->ixlp = new_ixl_cmdp;
229 
230 			new_ixl_cmdp->ixl_opcode = IXL1394_OP_LABEL;
231 
232 			last_ixlp = softc_p->ixlp;
233 		}
234 
235 		/* add wait-for-sync IXL command */
236 		new_ixl_sswp = kmem_zalloc(
237 				sizeof (ixl1394_set_syncwait_t), KM_SLEEP);
238 
239 		new_ixl_sswp->ixl_opcode = IXL1394_OP_SET_SYNCWAIT;
240 
241 		last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_sswp;
242 		last_ixlp = (ixl1394_command_t *)new_ixl_sswp;
243 
244 		/* add in each dma cookie */
245 		for (cookie = 0; cookie < buff_info_p->dma_cookie_count;
246 		    cookie++) {
247 
248 			num_xfer_cmds = min(bytes_per_frame,
249 			    buff_info_p->dma_cookie.dmac_size) /
250 			    max_ixl_buff_size;
251 
252 			if (min(bytes_per_frame,
253 			    buff_info_p->dma_cookie.dmac_size) %
254 			    max_ixl_buff_size) {
255 				num_xfer_cmds++;
256 			}
257 
258 			num_bytes_left = min(bytes_per_frame,
259 			    buff_info_p->dma_cookie.dmac_size);
260 
261 			ixl_buff_kaddr =
262 			    buff_info_p->dma_cookie.dmac_laddress;
263 
264 			ixl_buff_vaddr = buff_info_p->kaddr_p;
265 
266 			for (xfer_cmd = 0; xfer_cmd < (num_xfer_cmds + 1);
267 			    xfer_cmd++) {
268 				num_bytes = min(num_bytes_left,
269 				    max_ixl_buff_size);
270 
271 				if (xfer_cmd == 0) {
272 					new_ixl_xfpp =
273 					    kmem_zalloc(
274 						sizeof (ixl1394_xfer_pkt_t),
275 						KM_SLEEP);
276 
277 					new_ixl_xfpp->ixl_opcode =
278 					    IXL1394_OP_RECV_PKT_ST;
279 
280 					new_ixl_xfpp->ixl_buf._dmac_ll =
281 					    ixl_buff_kaddr;
282 					new_ixl_xfpp->size =
283 					    (uint16_t)bytes_per_pkt;
284 					new_ixl_xfpp->mem_bufp =
285 					    ixl_buff_vaddr;
286 
287 					last_ixlp->next_ixlp =
288 					    (ixl1394_command_t *)new_ixl_xfpp;
289 					last_ixlp =
290 					    (ixl1394_command_t *)new_ixl_xfpp;
291 
292 					num_bytes_left -= bytes_per_pkt;
293 					ixl_buff_kaddr += bytes_per_pkt;
294 					ixl_buff_vaddr += bytes_per_pkt;
295 
296 					continue;
297 				}
298 
299 				/* allocate & init an IXL transfer command. */
300 				new_ixl_xfbp =
301 				    kmem_zalloc(sizeof (ixl1394_xfer_buf_t),
302 					    KM_SLEEP);
303 
304 				new_ixl_xfbp->ixl_opcode = IXL1394_OP_RECV_BUF;
305 
306 				new_ixl_xfbp->ixl_buf._dmac_ll =
307 				    ixl_buff_kaddr;
308 				new_ixl_xfbp->size = (uint16_t)num_bytes;
309 				new_ixl_xfbp->pkt_size = bytes_per_pkt;
310 				new_ixl_xfbp->mem_bufp = ixl_buff_vaddr;
311 
312 				last_ixlp->next_ixlp =
313 				    (ixl1394_command_t *)new_ixl_xfbp;
314 				last_ixlp =
315 				    (ixl1394_command_t *)new_ixl_xfbp;
316 
317 				num_bytes_left -= num_bytes;
318 				ixl_buff_kaddr += num_bytes;
319 				ixl_buff_vaddr += num_bytes;
320 			}
321 
322 			if (cookie > 0) {
323 				ddi_dma_nextcookie(buff_info_p->dma_handle,
324 				    &(buff_info_p->dma_cookie));
325 			}
326 
327 		}
328 
329 		/*
330 		 * at this point, have finished a frame.  put in a callback
331 		 */
332 		new_ixl_cbp = kmem_zalloc(
333 				sizeof (ixl1394_callback_t), KM_SLEEP);
334 
335 		new_ixl_cbp->ixl_opcode	= IXL1394_OP_CALLBACK;
336 
337 		new_ixl_cbp->callback = &dcam_frame_is_done;
338 		new_ixl_cbp->callback_arg = NULL;
339 
340 		last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_cbp;
341 		last_ixlp = (ixl1394_command_t *)new_ixl_cbp;
342 	}
343 
344 	/*
345 	 * for the final touch, put an IXL jump at the end to jump to the
346 	 * label at the top
347 	 */
348 	new_ixl_jmpp = kmem_zalloc(sizeof (ixl1394_jump_t), KM_SLEEP);
349 
350 	new_ixl_jmpp->ixl_opcode = IXL1394_OP_JUMP;
351 
352 	new_ixl_jmpp->label = softc_p->ixlp;
353 
354 	last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_jmpp;
355 
356 	/* don't need this, but it's neater */
357 	last_ixlp = (ixl1394_command_t *)new_ixl_jmpp;
358 
359 	/* call fwim routine to alloc an isoch resource */
360 	isoch_args.ixlp		= softc_p->ixlp;
361 	isoch_args.channel_num	= softc_p->sii_output_args.channel_num;
362 
363 	/* other misc args.  note speed doesn't matter for isoch receive */
364 	isoch_args.idma_options		= ID1394_LISTEN_PKT_MODE;
365 	isoch_args.default_tag		= 0;
366 	isoch_args.default_sync		= 1;
367 	isoch_args.global_callback_arg	= softc_p;
368 
369 	/* set the ISO channel number */
370 	data = (softc_p->sii_output_args.channel_num & 0xF) << 28;
371 
372 	/* set the ISO speed */
373 	data |= (softc_p->targetinfo.current_max_speed << 24);
374 
375 	reg_io.offs = DCAM1394_REG_OFFS_CUR_ISO_CHANNEL;
376 	reg_io.val  = data;
377 
378 	if (dcam_reg_write(softc_p, &reg_io)) {
379 		return (1);
380 	}
381 
382 	result = 1234;
383 
384 	if (t1394_alloc_isoch_dma(softc_p->sl_handle, &isoch_args, 0,
385 	    &softc_p->isoch_handle, &result) != DDI_SUCCESS) {
386 		return (1);
387 	}
388 
389 	return (0);
390 }
391 
392 
393 /*
394  * dcam_frame_rcv_fini
395  */
396 int
397 dcam_frame_rcv_fini(dcam_state_t *softc_p)
398 {
399 	t1394_free_isoch_dma(softc_p->sl_handle, 0, &softc_p->isoch_handle);
400 
401 	softc_p->isoch_handle = NULL;
402 
403 	t1394_free_isoch_single(softc_p->sl_handle, &softc_p->sii_hdl, 0);
404 
405 	return (0);
406 }
407 
408 
409 /*
410  * dcam_frame_rcv_start
411  */
412 int
413 dcam_frame_rcv_start(dcam_state_t *softc_p)
414 {
415 	id1394_isoch_dma_ctrlinfo_t	idma_ctrlinfo; /* currently not used */
416 	int32_t				result;
417 	dcam1394_reg_io_t		reg_io;
418 
419 	if ((t1394_start_isoch_dma(softc_p->sl_handle, softc_p->isoch_handle,
420 	    &idma_ctrlinfo, 0, &result)) != DDI_SUCCESS) {
421 		return (1);
422 	}
423 
424 	reg_io.offs = DCAM1394_REG_OFFS_ISO_EN;
425 	reg_io.val  = 0x80000000;
426 
427 	if (dcam_reg_write(softc_p, &reg_io)) {
428 		return (1);
429 	}
430 
431 	softc_p->flags |= DCAM1394_FLAG_FRAME_RCVING;
432 
433 	return (0);
434 }
435 
436 
437 /*
438  * dcam_frame_rcv_stop
439  */
440 int
441 dcam_frame_rcv_stop(dcam_state_t *softc_p)
442 {
443 	dcam1394_reg_io_t reg_io;
444 
445 	/* if resources have already been cleared, nothing to do */
446 	if (!(softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT)) {
447 		return (0);
448 	}
449 
450 	reg_io.offs = DCAM1394_REG_OFFS_ISO_EN;
451 	reg_io.val  = 0;
452 
453 	(void) dcam_reg_write(softc_p, &reg_io);
454 
455 	t1394_stop_isoch_dma(softc_p->sl_handle, softc_p->isoch_handle, 0);
456 	t1394_free_isoch_dma(softc_p->sl_handle, 0, &softc_p->isoch_handle);
457 	t1394_free_isoch_single(softc_p->sl_handle, &softc_p->sii_hdl, 0);
458 
459 	dcam_free_resources(softc_p);
460 
461 	return (0);
462 }
463 
464 
465 void
466 dcam_free_resources(dcam_state_t *softc_p)
467 {
468 	ixl1394_command_t *ptr;
469 	ixl1394_command_t *tmp;
470 
471 	/*
472 	 *  The following fixes a memory leak.  See bug #4423667.
473 	 *  The original code  only released memory for the first  frame.
474 	 */
475 
476 	/* free ixl opcode resources */
477 	ptr = softc_p->ixlp;
478 
479 	while (ptr != NULL) {
480 		tmp = ptr;
481 		ptr = ptr->next_ixlp;
482 
483 		switch (tmp->ixl_opcode) {
484 			case IXL1394_OP_LABEL:
485 				kmem_free(tmp, sizeof (ixl1394_label_t));
486 			break;
487 
488 			case IXL1394_OP_SET_SYNCWAIT:
489 				kmem_free(tmp, sizeof (ixl1394_set_syncwait_t));
490 			break;
491 
492 			case IXL1394_OP_RECV_PKT_ST:
493 				kmem_free(tmp, sizeof (ixl1394_xfer_pkt_t));
494 			break;
495 
496 			case IXL1394_OP_RECV_BUF:
497 				kmem_free(tmp, sizeof (ixl1394_xfer_buf_t));
498 			break;
499 
500 			case IXL1394_OP_CALLBACK:
501 				kmem_free(tmp, sizeof (ixl1394_callback_t));
502 			break;
503 
504 			case IXL1394_OP_JUMP:
505 				kmem_free(tmp, sizeof (ixl1394_jump_t));
506 			break;
507 		}
508 	}
509 
510 	/*
511 	 * free ring buff and indicate that the resources have been cleared
512 	 */
513 	ring_buff_free(softc_p, softc_p->ring_buff_p);
514 
515 	softc_p->flags &= ~DCAM1394_FLAG_FRAME_RCV_INIT;
516 	softc_p->ixlp = NULL;
517 }
518 
519 
520 /*
521  * dcam_frame_is_done
522  *
523  * This routine is called after DMA engine has stored a single received
524  * frame in ring buffer position pointed to by write pointer; this
525  * routine marks the frame's vid mode, timestamp, and sequence number
526  *
527  * Store received frame in ring buffer position pointed to by write pointer.
528  * Increment write pointer.  If write pointer is pointing to the same
529  * position as read pointer, increment read pointer.
530  *
531  * If device driver is processing a user process's read() request
532  * invalidate the read() request processing operation.
533  *
534  */
535 
536 /* ARGSUSED */
537 void
538 dcam_frame_is_done(void *ssp, ixl1394_callback_t *ixlp)
539 {
540 	dcam_state_t	*softc_p;
541 	int		 num_read_ptrs;
542 	int		 read_ptr_id;
543 	int		 vid_mode;
544 	size_t		 write_ptr_pos;
545 	ring_buff_t	*ring_buff_p;
546 	unsigned int	 seq_num;
547 
548 	/*
549 	 * Store received frame in ring buffer position pointed to by
550 	 * write pointer (this routine is called after DMA engine has
551 	 * stored a single received frame in ring buffer position pointed
552 	 * to by write pointer; this routine marks the frame's vid mode,
553 	 * timestamp, and sequence number)
554 	 */
555 
556 	if ((softc_p = (dcam_state_t *)ssp) == NULL) {
557 		return;
558 	}
559 
560 	if ((ring_buff_p = softc_p->ring_buff_p) == NULL) {
561 		return;
562 	}
563 
564 	mutex_enter(&softc_p->dcam_frame_is_done_mutex);
565 
566 	write_ptr_pos = ring_buff_write_ptr_pos_get(ring_buff_p);
567 
568 	/* mark vid mode */
569 	vid_mode =
570 	    softc_p->
571 		param_attr[DCAM1394_PARAM_VID_MODE][DCAM1394_SUBPARAM_NONE];
572 	ring_buff_p->buff_info_array_p[write_ptr_pos].vid_mode = vid_mode;
573 
574 
575 	/* update sequence counter overflow in param_status */
576 	if (softc_p->seq_count == 0xffffffff)
577 		softc_p->param_status |=
578 		    DCAM1394_STATUS_FRAME_SEQ_NUM_COUNT_OVERFLOW;
579 
580 
581 	/* mark frame's sequence number */
582 	ring_buff_p->buff_info_array_p[write_ptr_pos].seq_num =
583 	    softc_p->seq_count++;
584 
585 	seq_num = ring_buff_p->buff_info_array_p[write_ptr_pos].seq_num;
586 
587 
588 	/* mark frame's timestamp */
589 	ring_buff_p->buff_info_array_p[write_ptr_pos].timestamp = gethrtime();
590 
591 
592 	/* increment write pointer */
593 	ring_buff_write_ptr_incr(ring_buff_p);
594 
595 	num_read_ptrs = 1;
596 
597 	for (read_ptr_id = 0; read_ptr_id < num_read_ptrs; read_ptr_id++) {
598 
599 		/*
600 		 * if write pointer is pointing to the same position as
601 		 * read pointer
602 		 */
603 
604 		if ((ring_buff_write_ptr_pos_get(ring_buff_p) ==
605 		    ring_buff_read_ptr_pos_get(ring_buff_p, read_ptr_id)) &&
606 		    (seq_num != 0)) {
607 
608 			/* increment read pointer */
609 			ring_buff_read_ptr_incr(ring_buff_p, read_ptr_id);
610 
611 			/*
612 			 * if device driver is processing a user
613 			 * process's read() request
614 			 */
615 			if (softc_p->reader_flags[read_ptr_id] &
616 			    DCAM1394_FLAG_READ_REQ_PROC) {
617 
618 				/*
619 				 * invalidate the read() request processing
620 				 * operation
621 				 */
622 				softc_p->reader_flags[read_ptr_id] |=
623 				    DCAM1394_FLAG_READ_REQ_INVALID;
624 			}
625 
626 			/* inform user app that we have lost one frame */
627 			softc_p->param_status |=
628 			    DCAM1394_STATUS_RING_BUFF_LOST_FRAME;
629 		}
630 	}
631 
632 	/* inform user app that we have received one frame */
633 	softc_p->param_status |= DCAM1394_STATUS_FRAME_RCV_DONE;
634 
635 	mutex_exit(&softc_p->dcam_frame_is_done_mutex);
636 }
637 
638 
639 /* ARGSUSED */
640 static void
641 dcam_rsrc_fail(t1394_isoch_single_handle_t t1394_single_hdl,
642     opaque_t single_evt_arg, t1394_isoch_rsrc_error_t fail_args)
643 {
644 	cmn_err(CE_NOTE, "dcam_rsrc_fail(): unable to re-alloc resources\n");
645 }
646