xref: /illumos-gate/usr/src/uts/common/io/1394/targets/dcam1394/dcam_frame.c (revision 78b6ed601aa3a251030edda42ce9770e9c21567a)
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 	caddr_t			ixl_buff_kaddr, ixl_buff_vaddr;
175 
176 	bytes_per_pkt = g_bytes_per_packet[vid_mode][frame_rate];
177 	if (bytes_per_pkt == -1) {
178 		return (1);
179 	}
180 
181 	bytes_per_frame = g_bytes_per_frame[vid_mode];
182 
183 	if ((softc_p->ring_buff_p = ring_buff_create(softc_p,
184 	    (size_t)ring_buff_capacity, (size_t)bytes_per_frame)) == NULL) {
185 		return (1);
186 	}
187 
188 	softc_p->ring_buff_p->read_ptr_pos[0] = 0;
189 
190 	/* allocate isoch channel */
191 	softc_p->sii.si_channel_mask	= 0xFFFF000000000000;
192 	softc_p->sii.si_bandwidth	= bytes_per_pkt;
193 	softc_p->sii.rsrc_fail_target	= dcam_rsrc_fail;
194 	softc_p->sii.single_evt_arg	= softc_p;
195 	softc_p->sii.si_speed		= softc_p->targetinfo.current_max_speed;
196 
197 	if (t1394_alloc_isoch_single(softc_p->sl_handle,
198 	    &softc_p->sii, 0, &softc_p->sii_output_args, &softc_p->sii_hdl,
199 	    &failure) != DDI_SUCCESS) {
200 		return (1);
201 	}
202 
203 	/*
204 	 * At this point, all buffer memory has been allocated and
205 	 * mapped, and is tracked on a linear linked list.  Now need to
206 	 * build the IXL.  Done on a frame-by-frame basis.  Could
207 	 * theoretically have been done at the same time as the mem alloc
208 	 * above, but hey, no need to be so fancy here.
209 	 *
210 	 * ixl buff size is bound by SHRT_MAX and needs to
211 	 * be a multiple of packet size
212 	 */
213 	max_ixl_buff_size = (SHRT_MAX / bytes_per_pkt) * bytes_per_pkt;
214 
215 	/* for each frame build frame's ixl list */
216 	for (frame = 0; frame < softc_p->ring_buff_p->num_buffs; frame++) {
217 
218 		buff_info_p = &(softc_p->ring_buff_p->buff_info_array_p[frame]);
219 
220 		/*
221 		 * if this is the 1st frame, put a IXL label at the top so a
222 		 * loop can be created later
223 		 */
224 		if (frame == 0) {
225 			new_ixl_cmdp = kmem_zalloc(
226 					sizeof (ixl1394_label_t), KM_SLEEP);
227 			softc_p->ixlp = new_ixl_cmdp;
228 
229 			new_ixl_cmdp->ixl_opcode = IXL1394_OP_LABEL;
230 
231 			last_ixlp = softc_p->ixlp;
232 		}
233 
234 		/* add wait-for-sync IXL command */
235 		new_ixl_sswp = kmem_zalloc(
236 				sizeof (ixl1394_set_syncwait_t), KM_SLEEP);
237 
238 		new_ixl_sswp->ixl_opcode = IXL1394_OP_SET_SYNCWAIT;
239 
240 		last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_sswp;
241 		last_ixlp = (ixl1394_command_t *)new_ixl_sswp;
242 
243 		/* add in each dma cookie */
244 		for (cookie = 0; cookie < buff_info_p->dma_cookie_count;
245 		    cookie++) {
246 
247 			num_xfer_cmds = min(bytes_per_frame,
248 			    buff_info_p->dma_cookie.dmac_size) /
249 			    max_ixl_buff_size;
250 
251 			if (min(bytes_per_frame,
252 			    buff_info_p->dma_cookie.dmac_size) %
253 			    max_ixl_buff_size) {
254 				num_xfer_cmds++;
255 			}
256 
257 			num_bytes_left = min(bytes_per_frame,
258 			    buff_info_p->dma_cookie.dmac_size);
259 
260 			ixl_buff_kaddr = (caddr_t)
261 			    buff_info_p->dma_cookie.dmac_laddress;
262 
263 			ixl_buff_vaddr = buff_info_p->kaddr_p;
264 
265 			for (xfer_cmd = 0; xfer_cmd < (num_xfer_cmds + 1);
266 			    xfer_cmd++) {
267 				num_bytes = min(num_bytes_left,
268 				    max_ixl_buff_size);
269 
270 				if (xfer_cmd == 0) {
271 					new_ixl_xfpp =
272 					    kmem_zalloc(
273 						sizeof (ixl1394_xfer_pkt_t),
274 						KM_SLEEP);
275 
276 					new_ixl_xfpp->ixl_opcode =
277 					    IXL1394_OP_RECV_PKT_ST;
278 
279 					new_ixl_xfpp->ixl_buf._dmac_ll =
280 					    (uint64_t)ixl_buff_kaddr;
281 					new_ixl_xfpp->size =
282 					    (uint16_t)bytes_per_pkt;
283 					new_ixl_xfpp->mem_bufp =
284 					    ixl_buff_vaddr;
285 
286 					last_ixlp->next_ixlp =
287 					    (ixl1394_command_t *)new_ixl_xfpp;
288 					last_ixlp =
289 					    (ixl1394_command_t *)new_ixl_xfpp;
290 
291 					num_bytes_left -= bytes_per_pkt;
292 					ixl_buff_kaddr += bytes_per_pkt;
293 					ixl_buff_vaddr += bytes_per_pkt;
294 
295 					continue;
296 				}
297 
298 				/* allocate & init an IXL transfer command. */
299 				new_ixl_xfbp =
300 				    kmem_zalloc(sizeof (ixl1394_xfer_buf_t),
301 					    KM_SLEEP);
302 
303 				new_ixl_xfbp->ixl_opcode = IXL1394_OP_RECV_BUF;
304 
305 				new_ixl_xfbp->ixl_buf._dmac_ll =
306 				    (uint64_t)ixl_buff_kaddr;
307 				new_ixl_xfbp->size = (uint16_t)num_bytes;
308 				new_ixl_xfbp->pkt_size = bytes_per_pkt;
309 				new_ixl_xfbp->mem_bufp = ixl_buff_vaddr;
310 
311 				last_ixlp->next_ixlp =
312 				    (ixl1394_command_t *)new_ixl_xfbp;
313 				last_ixlp =
314 				    (ixl1394_command_t *)new_ixl_xfbp;
315 
316 				num_bytes_left -= num_bytes;
317 				ixl_buff_kaddr += num_bytes;
318 				ixl_buff_vaddr += num_bytes;
319 			}
320 
321 			if (cookie > 0) {
322 				ddi_dma_nextcookie(buff_info_p->dma_handle,
323 				    &(buff_info_p->dma_cookie));
324 			}
325 
326 		}
327 
328 		/*
329 		 * at this point, have finished a frame.  put in a callback
330 		 */
331 		new_ixl_cbp = kmem_zalloc(
332 				sizeof (ixl1394_callback_t), KM_SLEEP);
333 
334 		new_ixl_cbp->ixl_opcode	= IXL1394_OP_CALLBACK;
335 
336 		new_ixl_cbp->callback = &dcam_frame_is_done;
337 		new_ixl_cbp->callback_arg = NULL;
338 
339 		last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_cbp;
340 		last_ixlp = (ixl1394_command_t *)new_ixl_cbp;
341 	}
342 
343 	/*
344 	 * for the final touch, put an IXL jump at the end to jump to the
345 	 * label at the top
346 	 */
347 	new_ixl_jmpp = kmem_zalloc(sizeof (ixl1394_jump_t), KM_SLEEP);
348 
349 	new_ixl_jmpp->ixl_opcode = IXL1394_OP_JUMP;
350 
351 	new_ixl_jmpp->label = softc_p->ixlp;
352 
353 	last_ixlp->next_ixlp = (ixl1394_command_t *)new_ixl_jmpp;
354 
355 	/* don't need this, but it's neater */
356 	last_ixlp = (ixl1394_command_t *)new_ixl_jmpp;
357 
358 	/* call fwim routine to alloc an isoch resource */
359 	isoch_args.ixlp		= softc_p->ixlp;
360 	isoch_args.channel_num	= softc_p->sii_output_args.channel_num;
361 
362 	/* other misc args.  note speed doesn't matter for isoch receive */
363 	isoch_args.idma_options		= ID1394_LISTEN_PKT_MODE;
364 	isoch_args.default_tag		= 0;
365 	isoch_args.default_sync		= 1;
366 	isoch_args.global_callback_arg	= softc_p;
367 
368 	/* set the ISO channel number */
369 	data = (softc_p->sii_output_args.channel_num & 0xF) << 28;
370 
371 	/* set the ISO speed */
372 	data |= (softc_p->targetinfo.current_max_speed << 24);
373 
374 	reg_io.offs = DCAM1394_REG_OFFS_CUR_ISO_CHANNEL;
375 	reg_io.val  = data;
376 
377 	if (dcam_reg_write(softc_p, &reg_io)) {
378 		return (1);
379 	}
380 
381 	result = 1234;
382 
383 	if (t1394_alloc_isoch_dma(softc_p->sl_handle, &isoch_args, 0,
384 	    &softc_p->isoch_handle, &result) != DDI_SUCCESS) {
385 		return (1);
386 	}
387 
388 	return (0);
389 }
390 
391 
392 /*
393  * dcam_frame_rcv_fini
394  */
395 int
396 dcam_frame_rcv_fini(dcam_state_t *softc_p)
397 {
398 	t1394_free_isoch_dma(softc_p->sl_handle, 0, &softc_p->isoch_handle);
399 
400 	softc_p->isoch_handle = NULL;
401 
402 	t1394_free_isoch_single(softc_p->sl_handle, &softc_p->sii_hdl, 0);
403 
404 	return (0);
405 }
406 
407 
408 /*
409  * dcam_frame_rcv_start
410  */
411 int
412 dcam_frame_rcv_start(dcam_state_t *softc_p)
413 {
414 	id1394_isoch_dma_ctrlinfo_t	idma_ctrlinfo; /* currently not used */
415 	int32_t				result;
416 	dcam1394_reg_io_t		reg_io;
417 
418 	if ((t1394_start_isoch_dma(softc_p->sl_handle, softc_p->isoch_handle,
419 	    &idma_ctrlinfo, 0, &result)) != DDI_SUCCESS) {
420 		return (1);
421 	}
422 
423 	reg_io.offs = DCAM1394_REG_OFFS_ISO_EN;
424 	reg_io.val  = 0x80000000;
425 
426 	if (dcam_reg_write(softc_p, &reg_io)) {
427 		return (1);
428 	}
429 
430 	softc_p->flags |= DCAM1394_FLAG_FRAME_RCVING;
431 
432 	return (0);
433 }
434 
435 
436 /*
437  * dcam_frame_rcv_stop
438  */
439 int
440 dcam_frame_rcv_stop(dcam_state_t *softc_p)
441 {
442 	dcam1394_reg_io_t reg_io;
443 
444 	/* if resources have already been cleared, nothing to do */
445 	if (!(softc_p->flags & DCAM1394_FLAG_FRAME_RCV_INIT)) {
446 		return (0);
447 	}
448 
449 	reg_io.offs = DCAM1394_REG_OFFS_ISO_EN;
450 	reg_io.val  = 0;
451 
452 	(void) dcam_reg_write(softc_p, &reg_io);
453 
454 	t1394_stop_isoch_dma(softc_p->sl_handle, softc_p->isoch_handle, 0);
455 	t1394_free_isoch_dma(softc_p->sl_handle, 0, &softc_p->isoch_handle);
456 	t1394_free_isoch_single(softc_p->sl_handle, &softc_p->sii_hdl, 0);
457 
458 	dcam_free_resources(softc_p);
459 
460 	return (0);
461 }
462 
463 
464 void
465 dcam_free_resources(dcam_state_t *softc_p)
466 {
467 	ixl1394_command_t *ptr;
468 	ixl1394_command_t *tmp;
469 
470 	/*
471 	 *  The following fixes a memory leak.  See bug #4423667.
472 	 *  The original code  only released memory for the first  frame.
473 	 */
474 
475 	/* free ixl opcode resources */
476 	ptr = softc_p->ixlp;
477 
478 	while (ptr != NULL) {
479 		tmp = ptr;
480 		ptr = ptr->next_ixlp;
481 
482 		switch (tmp->ixl_opcode) {
483 			case IXL1394_OP_LABEL:
484 				kmem_free(tmp, sizeof (ixl1394_label_t));
485 			break;
486 
487 			case IXL1394_OP_SET_SYNCWAIT:
488 				kmem_free(tmp, sizeof (ixl1394_set_syncwait_t));
489 			break;
490 
491 			case IXL1394_OP_RECV_PKT_ST:
492 				kmem_free(tmp, sizeof (ixl1394_xfer_pkt_t));
493 			break;
494 
495 			case IXL1394_OP_RECV_BUF:
496 				kmem_free(tmp, sizeof (ixl1394_xfer_buf_t));
497 			break;
498 
499 			case IXL1394_OP_CALLBACK:
500 				kmem_free(tmp, sizeof (ixl1394_callback_t));
501 			break;
502 
503 			case IXL1394_OP_JUMP:
504 				kmem_free(tmp, sizeof (ixl1394_jump_t));
505 			break;
506 		}
507 	}
508 
509 	/*
510 	 * free ring buff and indicate that the resources have been cleared
511 	 */
512 	ring_buff_free(softc_p, softc_p->ring_buff_p);
513 
514 	softc_p->flags &= ~DCAM1394_FLAG_FRAME_RCV_INIT;
515 	softc_p->ixlp = NULL;
516 }
517 
518 
519 /*
520  * dcam_frame_is_done
521  *
522  * This routine is called after DMA engine has stored a single received
523  * frame in ring buffer position pointed to by write pointer; this
524  * routine marks the frame's vid mode, timestamp, and sequence number
525  *
526  * Store received frame in ring buffer position pointed to by write pointer.
527  * Increment write pointer.  If write pointer is pointing to the same
528  * position as read pointer, increment read pointer.
529  *
530  * If device driver is processing a user process's read() request
531  * invalidate the read() request processing operation.
532  *
533  */
534 
535 /* ARGSUSED */
536 void
537 dcam_frame_is_done(void *ssp, ixl1394_callback_t *ixlp)
538 {
539 	dcam_state_t	*softc_p;
540 	int		 num_read_ptrs;
541 	int		 read_ptr_id;
542 	int		 vid_mode;
543 	size_t		 write_ptr_pos;
544 	ring_buff_t	*ring_buff_p;
545 	unsigned int	 seq_num;
546 
547 	/*
548 	 * Store received frame in ring buffer position pointed to by
549 	 * write pointer (this routine is called after DMA engine has
550 	 * stored a single received frame in ring buffer position pointed
551 	 * to by write pointer; this routine marks the frame's vid mode,
552 	 * timestamp, and sequence number)
553 	 */
554 
555 	if ((softc_p = (dcam_state_t *)ssp) == NULL) {
556 		return;
557 	}
558 
559 	if ((ring_buff_p = softc_p->ring_buff_p) == NULL) {
560 		return;
561 	}
562 
563 	mutex_enter(&softc_p->dcam_frame_is_done_mutex);
564 
565 	write_ptr_pos = ring_buff_write_ptr_pos_get(ring_buff_p);
566 
567 	/* mark vid mode */
568 	vid_mode =
569 	    softc_p->
570 		param_attr[DCAM1394_PARAM_VID_MODE][DCAM1394_SUBPARAM_NONE];
571 	ring_buff_p->buff_info_array_p[write_ptr_pos].vid_mode = vid_mode;
572 
573 
574 	/* update sequence counter overflow in param_status */
575 	if (softc_p->seq_count == 0xffffffff)
576 		softc_p->param_status |=
577 		    DCAM1394_STATUS_FRAME_SEQ_NUM_COUNT_OVERFLOW;
578 
579 
580 	/* mark frame's sequence number */
581 	ring_buff_p->buff_info_array_p[write_ptr_pos].seq_num =
582 	    softc_p->seq_count++;
583 
584 	seq_num = ring_buff_p->buff_info_array_p[write_ptr_pos].seq_num;
585 
586 
587 	/* mark frame's timestamp */
588 	ring_buff_p->buff_info_array_p[write_ptr_pos].timestamp = gethrtime();
589 
590 
591 	/* increment write pointer */
592 	ring_buff_write_ptr_incr(ring_buff_p);
593 
594 	num_read_ptrs = 1;
595 
596 	for (read_ptr_id = 0; read_ptr_id < num_read_ptrs; read_ptr_id++) {
597 
598 		/*
599 		 * if write pointer is pointing to the same position as
600 		 * read pointer
601 		 */
602 
603 		if ((ring_buff_write_ptr_pos_get(ring_buff_p) ==
604 		    ring_buff_read_ptr_pos_get(ring_buff_p, read_ptr_id)) &&
605 		    (seq_num != 0)) {
606 
607 			/* increment read pointer */
608 			ring_buff_read_ptr_incr(ring_buff_p, read_ptr_id);
609 
610 			/*
611 			 * if device driver is processing a user
612 			 * process's read() request
613 			 */
614 			if (softc_p->reader_flags[read_ptr_id] &
615 			    DCAM1394_FLAG_READ_REQ_PROC) {
616 
617 				/*
618 				 * invalidate the read() request processing
619 				 * operation
620 				 */
621 				softc_p->reader_flags[read_ptr_id] |=
622 				    DCAM1394_FLAG_READ_REQ_INVALID;
623 			}
624 
625 			/* inform user app that we have lost one frame */
626 			softc_p->param_status |=
627 			    DCAM1394_STATUS_RING_BUFF_LOST_FRAME;
628 		}
629 	}
630 
631 	/* inform user app that we have received one frame */
632 	softc_p->param_status |= DCAM1394_STATUS_FRAME_RCV_DONE;
633 
634 	mutex_exit(&softc_p->dcam_frame_is_done_mutex);
635 }
636 
637 
638 /* ARGSUSED */
639 static void
640 dcam_rsrc_fail(t1394_isoch_single_handle_t t1394_single_hdl,
641     opaque_t single_evt_arg, t1394_isoch_rsrc_error_t fail_args)
642 {
643 	cmn_err(CE_NOTE, "dcam_rsrc_fail(): unable to re-alloc resources\n");
644 }
645