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 2004 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  * av1394 isochronous receive module
31  */
32 #include <sys/1394/targets/av1394/av1394_impl.h>
33 
34 /* configuration routines */
35 static void	av1394_ir_cleanup(av1394_ic_t *, int);
36 static int	av1394_ir_build_ixl(av1394_ic_t *);
37 static void	av1394_ir_ixl_label_init(av1394_ir_ixl_data_t *,
38 		ixl1394_command_t *);
39 static void	av1394_ir_ixl_buf_init(av1394_ic_t *, ixl1394_xfer_buf_t *,
40 		av1394_isoch_seg_t *, off_t, uint16_t, ixl1394_command_t *);
41 static void	av1394_ir_ixl_cb_init(av1394_ic_t *, av1394_ir_ixl_data_t *,
42 		int);
43 static void	av1394_ir_ixl_jump_init(av1394_ic_t *, av1394_ir_ixl_data_t *,
44 		int);
45 static void	av1394_ir_destroy_ixl(av1394_ic_t *);
46 static int	av1394_ir_alloc_isoch_dma(av1394_ic_t *);
47 static void	av1394_ir_free_isoch_dma(av1394_ic_t *);
48 static void	av1394_ir_dma_sync_frames(av1394_ic_t *, int, int);
49 
50 /* callbacks */
51 static void	av1394_ir_ixl_frame_cb(opaque_t, struct ixl1394_callback *);
52 static void	av1394_ir_overflow_resume(av1394_ic_t *icp);
53 static void	av1394_ir_dma_stopped_cb(t1394_isoch_dma_handle_t,
54 		opaque_t, id1394_isoch_dma_stopped_t);
55 
56 /* data transfer routines */
57 static int	av1394_ir_add_frames(av1394_ic_t *, int, int);
58 static int	av1394_ir_wait_frames(av1394_ic_t *, int *, int *);
59 static int	av1394_ir_copyout(av1394_ic_t *, struct uio *, int *);
60 static void	av1394_ir_zero_pkts(av1394_ic_t *, int, int);
61 
62 /* value complementary to hi & lo watermarks (modulo number of frames) */
63 int av1394_ir_hiwat_sub = 2;
64 int av1394_ir_lowat_sub = 3;
65 int av1394_ir_dump_ixl = 0;
66 
67 #define	AV1394_TNF_ENTER(func)	\
68 	TNF_PROBE_0_DEBUG(func##_enter, AV1394_TNF_ISOCH_STACK, "");
69 
70 #define	AV1394_TNF_EXIT(func)	\
71 	TNF_PROBE_0_DEBUG(func##_exit, AV1394_TNF_ISOCH_STACK, "");
72 
73 int
74 av1394_ir_init(av1394_ic_t *icp, int *error)
75 {
76 	av1394_ir_t	*irp = &icp->ic_ir;
77 	av1394_isoch_pool_t *pool = &irp->ir_data_pool;
78 	int		nframes;
79 
80 	AV1394_TNF_ENTER(av1394_ir_init);
81 
82 	nframes = av1394_ic_alloc_pool(pool, icp->ic_framesz, icp->ic_nframes,
83 					AV1394_IR_NFRAMES_MIN);
84 	if (nframes == 0) {
85 		*error = IEC61883_ERR_NOMEM;
86 		AV1394_TNF_EXIT(av1394_ir_init);
87 		return (EINVAL);
88 	}
89 	mutex_enter(&icp->ic_mutex);
90 	icp->ic_nframes = nframes;
91 	irp->ir_hiwat = nframes - av1394_ir_hiwat_sub;
92 	irp->ir_lowat = nframes - av1394_ir_lowat_sub;
93 
94 	if (av1394_ic_dma_setup(icp, pool) != DDI_SUCCESS) {
95 		mutex_exit(&icp->ic_mutex);
96 		*error = IEC61883_ERR_NOMEM;
97 		av1394_ir_cleanup(icp, 1);
98 		AV1394_TNF_EXIT(av1394_ir_init);
99 		return (EINVAL);
100 	}
101 
102 	if (av1394_ir_build_ixl(icp) != DDI_SUCCESS) {
103 		mutex_exit(&icp->ic_mutex);
104 		*error = IEC61883_ERR_NOMEM;
105 		av1394_ir_cleanup(icp, 2);
106 		AV1394_TNF_EXIT(av1394_ir_init);
107 		return (EINVAL);
108 	}
109 	mutex_exit(&icp->ic_mutex);
110 
111 	if (av1394_ir_alloc_isoch_dma(icp) != DDI_SUCCESS) {
112 		*error = IEC61883_ERR_NOMEM;
113 		av1394_ir_cleanup(icp, 3);
114 		AV1394_TNF_EXIT(av1394_ir_init);
115 		return (EINVAL);
116 	}
117 
118 	AV1394_TNF_EXIT(av1394_ir_init);
119 	return (0);
120 }
121 
122 void
123 av1394_ir_fini(av1394_ic_t *icp)
124 {
125 	AV1394_TNF_ENTER(av1394_ir_fini);
126 
127 	av1394_ir_cleanup(icp, AV1394_CLEANUP_LEVEL_MAX);
128 
129 	AV1394_TNF_ENTER(av1394_ir_fini);
130 }
131 
132 int
133 av1394_ir_start(av1394_ic_t *icp)
134 {
135 	av1394_inst_t	*avp = icp->ic_avp;
136 	av1394_ir_t	*irp = &icp->ic_ir;
137 	id1394_isoch_dma_ctrlinfo_t idma_ctrlinfo = { 0 };
138 	int		result;
139 	int		err;
140 	int		ret = 0;
141 
142 	AV1394_TNF_ENTER(av1394_ir_start);
143 
144 	mutex_enter(&icp->ic_mutex);
145 	if (icp->ic_state != AV1394_IC_IDLE) {
146 		mutex_exit(&icp->ic_mutex);
147 		return (0);
148 	}
149 
150 	irp->ir_first_full = 0;
151 	irp->ir_last_empty = icp->ic_nframes - 1;
152 	irp->ir_nfull = 0;
153 	irp->ir_nempty = icp->ic_nframes;
154 	irp->ir_read_cnt = 0;
155 	mutex_exit(&icp->ic_mutex);
156 
157 	err = t1394_start_isoch_dma(avp->av_t1394_hdl, icp->ic_isoch_hdl,
158 				&idma_ctrlinfo, 0, &result);
159 	if (err == DDI_SUCCESS) {
160 		mutex_enter(&icp->ic_mutex);
161 		icp->ic_state = AV1394_IC_DMA;
162 		mutex_exit(&icp->ic_mutex);
163 	} else {
164 		TNF_PROBE_1(av1394_ir_start_error, AV1394_TNF_ISOCH_ERROR, "",
165 		    tnf_int, result, result);
166 		ret = EIO;
167 	}
168 
169 	AV1394_TNF_EXIT(av1394_ir_start);
170 	return (ret);
171 }
172 
173 int
174 av1394_ir_stop(av1394_ic_t *icp)
175 {
176 	av1394_inst_t	*avp = icp->ic_avp;
177 
178 	AV1394_TNF_ENTER(av1394_ir_stop);
179 
180 	mutex_enter(&icp->ic_mutex);
181 	if (icp->ic_state != AV1394_IC_IDLE) {
182 		mutex_exit(&icp->ic_mutex);
183 		t1394_stop_isoch_dma(avp->av_t1394_hdl, icp->ic_isoch_hdl, 0);
184 		mutex_enter(&icp->ic_mutex);
185 		icp->ic_state = AV1394_IC_IDLE;
186 	}
187 	mutex_exit(&icp->ic_mutex);
188 
189 	AV1394_TNF_EXIT(av1394_ir_stop);
190 	return (0);
191 }
192 
193 int
194 av1394_ir_recv(av1394_ic_t *icp, iec61883_recv_t *recv)
195 {
196 	int		ret = 0;
197 	int		idx, cnt;
198 
199 	idx = recv->rx_xfer.xf_empty_idx;
200 	cnt = recv->rx_xfer.xf_empty_cnt;
201 
202 	/* check arguments */
203 	if ((idx < 0) || (idx >= icp->ic_nframes) ||
204 	    (cnt < 0) || (cnt > icp->ic_nframes)) {
205 		TNF_PROBE_2(av1394_ir_recv_error_args, AV1394_TNF_ISOCH_ERROR,
206 		    "", tnf_int, idx, idx, tnf_int, cnt, cnt);
207 		return (EINVAL);
208 	}
209 
210 	mutex_enter(&icp->ic_mutex);
211 	if (cnt > 0) {
212 		/* add empty frames to the pool */
213 		if ((ret = av1394_ir_add_frames(icp, idx, cnt)) != 0) {
214 			mutex_exit(&icp->ic_mutex);
215 			return (ret);
216 		}
217 	}
218 
219 	/* wait for new frames to arrive */
220 	ret = av1394_ir_wait_frames(icp,
221 		&recv->rx_xfer.xf_full_idx, &recv->rx_xfer.xf_full_cnt);
222 	mutex_exit(&icp->ic_mutex);
223 
224 	return (ret);
225 }
226 
227 int
228 av1394_ir_read(av1394_ic_t *icp, struct uio *uiop)
229 {
230 	av1394_ir_t	*irp = &icp->ic_ir;
231 	int		ret = 0;
232 	int		empty_cnt;
233 
234 	AV1394_TNF_ENTER(av1394_ir_read);
235 
236 	mutex_enter(&icp->ic_mutex);
237 	while (uiop->uio_resid) {
238 		/* wait for full frames, if necessary */
239 		if (irp->ir_read_cnt == 0) {
240 			irp->ir_read_off = 0;
241 			ret = av1394_ir_wait_frames(icp,
242 					&irp->ir_read_idx, &irp->ir_read_cnt);
243 			if (ret != 0) {
244 				mutex_exit(&icp->ic_mutex);
245 				AV1394_TNF_EXIT(av1394_ir_read);
246 				return (ret);
247 			}
248 		}
249 
250 		/* copyout the data */
251 		ret = av1394_ir_copyout(icp, uiop, &empty_cnt);
252 
253 		/* return freed frames to the pool */
254 		if (empty_cnt > 0) {
255 			av1394_ir_zero_pkts(icp, irp->ir_read_idx, empty_cnt);
256 			ret = av1394_ir_add_frames(icp, irp->ir_read_idx,
257 								empty_cnt);
258 			irp->ir_read_idx += empty_cnt;
259 			irp->ir_read_idx %= icp->ic_nframes;
260 			irp->ir_read_cnt -= empty_cnt;
261 		}
262 	}
263 	mutex_exit(&icp->ic_mutex);
264 
265 	AV1394_TNF_EXIT(av1394_ir_read);
266 	return (ret);
267 }
268 
269 /*
270  *
271  * --- configuration routines
272  *
273  */
274 static void
275 av1394_ir_cleanup(av1394_ic_t *icp, int level)
276 {
277 	av1394_isoch_pool_t *pool = &icp->ic_ir.ir_data_pool;
278 
279 	ASSERT((level > 0) && (level <= AV1394_CLEANUP_LEVEL_MAX));
280 
281 	switch (level) {
282 	default:
283 		av1394_ir_free_isoch_dma(icp);
284 		/* FALLTHRU */
285 	case 3:
286 		av1394_ir_destroy_ixl(icp);
287 		/* FALLTHRU */
288 	case 2:
289 		av1394_ic_dma_cleanup(icp, pool);
290 		/* FALLTHRU */
291 	case 1:
292 		av1394_ic_free_pool(pool);
293 		/* FALLTHRU */
294 	}
295 }
296 
297 /*
298  * av1394_ir_build_ixl()
299  *    Build an IXL chain to receive CIP data. The smallest instance of data
300  *    that can be received is a packet, typically 512 bytes. Frames consist
301  *    of a number of packets, typically 250-300. Packet size, frame size and
302  *    number of frames allocated are set by a user process. The received data
303  *    made available to the user process in full frames, hence there an IXL
304  *    callback at the end of each frame. A sequence of IXL commands that
305  *    receives one frame is further referred to as an IXL data block.
306  *
307  *    During normal operation, frames are in a circular list and IXL chain
308  *    does not change. When the user process does not keep up with the
309  *    data flow and there are too few empty frames left, the jump following
310  *    last empty frame is dynamically updated to point to NULL -- otherwise
311  *    the first full frame would be overwritten. When IXL execution reaches
312  *    the nulled jump, it just waits until the driver updates it again or
313  *    stops the transfer. Once a user process frees up enough frames, the
314  *    jump is restored and transfer continues. User process will be able to
315  *    detect dropped packets using continuity conters embedded in the data.
316  *
317  *    Because RECV_BUF buffer size is limited to AV1394_IXL_BUFSZ_MAX, and due
318  *    to isoch pool segmentaion, the number of RECV_BUF commands per IXL data
319  *    block depends on frame size. Also, to simplify calculations, we consider
320  *    a sequence of RECV_BUF commands to consist of two parts: zero or more
321  *    equal-sized RECV_BUF commands followed by one "tail" REC_BUF command,
322  *    whose size may not be equal to others.
323  *
324  *    Schematically the IXL chain looks like this:
325  *
326  *    ...
327  *    LABEL N;
328  *    RECV_BUF(buf)
329  *    ...
330  *    RECV_BUF(tail)
331  *    CALLBACK(frame done);
332  *    JUMP_U(LABEL (N+1)%nframes or NULL);
333  *    ...
334  */
335 static int
336 av1394_ir_build_ixl(av1394_ic_t *icp)
337 {
338 	av1394_ir_t		*irp = &icp->ic_ir;
339 	av1394_isoch_pool_t	*pool = &irp->ir_data_pool;
340 	size_t			segsz;
341 	av1394_ir_ixl_data_t	*dp;
342 	int			i;	/* frame index */
343 	int			j;	/* buffer index */
344 	int			k;
345 	int			spf;	/* segments per frame */
346 	int			bpf;	/* buffers per frame */
347 
348 	AV1394_TNF_ENTER(av1394_ir_build_ixl);
349 
350 	/* allocate space for IXL data blocks */
351 	irp->ir_ixl_data = kmem_zalloc(icp->ic_nframes *
352 				sizeof (av1394_ir_ixl_data_t), KM_SLEEP);
353 
354 	/*
355 	 * calculate and allocate space for buf commands
356 	 */
357 	segsz = pool->ip_seg[0].is_size;
358 	ASSERT(segsz * pool->ip_nsegs == pool->ip_size); /* equal-size segs */
359 	ASSERT(segsz % icp->ic_pktsz == 0);	/* packet-aligned */
360 	ASSERT(segsz >= icp->ic_framesz);	/* 1+ full frames per segment */
361 
362 	if (icp->ic_framesz <= AV1394_IXL_BUFSZ_MAX) {
363 		/* RECV_BUF == frame, one or more frames per segment */
364 		irp->ir_ixl_tailsz = irp->ir_ixl_bufsz = icp->ic_framesz;
365 		irp->ir_ixl_bpf = 0;
366 	} else {
367 		/* segment == frame, several RECV_BUF's per segment */
368 		ASSERT(segsz == icp->ic_framesz);
369 		/* calculate the best decomposition of a segment into buffers */
370 		irp->ir_ixl_bpf = av1394_ic_ixl_seg_decomp(segsz,
371 			icp->ic_pktsz, &irp->ir_ixl_bufsz, &irp->ir_ixl_tailsz);
372 	}
373 	spf = segsz / icp->ic_framesz;
374 	bpf = irp->ir_ixl_bpf + 1;
375 
376 	irp->ir_ixl_nbufs = bpf * icp->ic_nframes;
377 	irp->ir_ixl_buf = kmem_zalloc(irp->ir_ixl_nbufs *
378 				sizeof (ixl1394_xfer_buf_t), KM_SLEEP);
379 
380 	/* initialize data blocks and receive buffers */
381 	for (i = 0; i < icp->ic_nframes; i++) {
382 		dp = &irp->ir_ixl_data[i];
383 
384 		av1394_ir_ixl_label_init(dp,
385 				(ixl1394_command_t *)&irp->ir_ixl_buf[i * bpf]);
386 
387 		/* regular buffers, if any */
388 		for (j = 0; j < irp->ir_ixl_bpf; j++) {
389 			k = j + i * bpf;
390 			av1394_ir_ixl_buf_init(icp, &irp->ir_ixl_buf[k],
391 				&pool->ip_seg[i], j * irp->ir_ixl_bufsz,
392 				irp->ir_ixl_bufsz,
393 				(ixl1394_command_t *)&irp->ir_ixl_buf[k + 1]);
394 		}
395 
396 		/* tail buffer */
397 		if (icp->ic_framesz <= AV1394_IXL_BUFSZ_MAX) {
398 			av1394_ir_ixl_buf_init(icp, &irp->ir_ixl_buf[i],
399 				&pool->ip_seg[i / spf],
400 				i * irp->ir_ixl_tailsz,
401 				irp->ir_ixl_tailsz,
402 				(ixl1394_command_t *)&dp->rd_cb);
403 		} else {
404 			k = irp->ir_ixl_bpf + i * bpf;
405 			av1394_ir_ixl_buf_init(icp, &irp->ir_ixl_buf[k],
406 				&pool->ip_seg[i],
407 				irp->ir_ixl_bpf * irp->ir_ixl_bufsz,
408 				irp->ir_ixl_tailsz,
409 				(ixl1394_command_t *)&dp->rd_cb);
410 		}
411 
412 		av1394_ir_ixl_cb_init(icp, dp, i);
413 		av1394_ir_ixl_jump_init(icp, dp, i);
414 	}
415 
416 	irp->ir_ixlp = (ixl1394_command_t *)irp->ir_ixl_data;
417 
418 	if (av1394_ir_dump_ixl) {
419 		av1394_ic_ixl_dump(irp->ir_ixlp);
420 	}
421 
422 	AV1394_TNF_EXIT(av1394_ir_build_ixl);
423 	return (DDI_SUCCESS);
424 }
425 
426 static void
427 av1394_ir_ixl_label_init(av1394_ir_ixl_data_t *dp, ixl1394_command_t *nextp)
428 {
429 	dp->rd_label.ixl_opcode = IXL1394_OP_LABEL;
430 	dp->rd_label.next_ixlp	= nextp;
431 }
432 
433 static void
434 av1394_ir_ixl_buf_init(av1394_ic_t *icp, ixl1394_xfer_buf_t *buf,
435 	av1394_isoch_seg_t *isp, off_t offset, uint16_t size,
436 	ixl1394_command_t *nextp)
437 {
438 	buf->ixl_opcode = IXL1394_OP_RECV_BUF;
439 	buf->size = size;
440 	buf->pkt_size = icp->ic_pktsz;
441 	buf->ixl_buf._dmac_ll = isp->is_dma_cookie.dmac_laddress + offset;
442 	buf->mem_bufp = isp->is_kaddr + offset;
443 	buf->next_ixlp = nextp;
444 }
445 
446 /*ARGSUSED*/
447 static void
448 av1394_ir_ixl_cb_init(av1394_ic_t *icp, av1394_ir_ixl_data_t *dp, int i)
449 {
450 	dp->rd_cb.ixl_opcode = IXL1394_OP_CALLBACK;
451 	dp->rd_cb.callback = av1394_ir_ixl_frame_cb;
452 	dp->rd_cb.callback_arg = (void *)(intptr_t)i;
453 	dp->rd_cb.next_ixlp = (ixl1394_command_t *)&dp->rd_jump;
454 }
455 
456 static void
457 av1394_ir_ixl_jump_init(av1394_ic_t *icp, av1394_ir_ixl_data_t *dp, int i)
458 {
459 	av1394_ir_t	*irp = &icp->ic_ir;
460 	int		next_idx;
461 	ixl1394_command_t *jump_cmd;
462 
463 	next_idx = (i + 1) % icp->ic_nframes;
464 	jump_cmd = (ixl1394_command_t *)&irp->ir_ixl_data[next_idx];
465 
466 	dp->rd_jump.ixl_opcode	= IXL1394_OP_JUMP_U;
467 	dp->rd_jump.label = jump_cmd;
468 	dp->rd_jump.next_ixlp = (next_idx != 0) ? jump_cmd : NULL;
469 }
470 
471 static void
472 av1394_ir_destroy_ixl(av1394_ic_t *icp)
473 {
474 	av1394_ir_t		*irp = &icp->ic_ir;
475 
476 	AV1394_TNF_ENTER(av1394_ir_destroy_ixl);
477 
478 	mutex_enter(&icp->ic_mutex);
479 	kmem_free(irp->ir_ixl_buf,
480 			irp->ir_ixl_nbufs * sizeof (ixl1394_xfer_buf_t));
481 	kmem_free(irp->ir_ixl_data,
482 			icp->ic_nframes * sizeof (av1394_ir_ixl_data_t));
483 
484 	irp->ir_ixlp = NULL;
485 	irp->ir_ixl_buf = NULL;
486 	irp->ir_ixl_data = NULL;
487 	mutex_exit(&icp->ic_mutex);
488 
489 	AV1394_TNF_EXIT(av1394_ir_destroy_ixl);
490 }
491 
492 static int
493 av1394_ir_alloc_isoch_dma(av1394_ic_t *icp)
494 {
495 	av1394_inst_t		*avp = icp->ic_avp;
496 	av1394_ir_t		*irp = &icp->ic_ir;
497 	id1394_isoch_dmainfo_t	di;
498 	int			result;
499 	int			ret;
500 
501 	AV1394_TNF_ENTER(av1394_ir_alloc_isoch_dma);
502 
503 	di.ixlp = irp->ir_ixlp;
504 	di.channel_num = icp->ic_num;
505 	di.global_callback_arg = icp;
506 	di.idma_options = ID1394_LISTEN_PKT_MODE;
507 	di.isoch_dma_stopped = av1394_ir_dma_stopped_cb;
508 	di.idma_evt_arg = icp;
509 
510 	if ((ret = t1394_alloc_isoch_dma(avp->av_t1394_hdl, &di, 0,
511 	    &icp->ic_isoch_hdl, &result)) != DDI_SUCCESS) {
512 		TNF_PROBE_1(av1394_ir_alloc_isoch_dma_error,
513 		    AV1394_TNF_ISOCH_ERROR, "", tnf_int, result, result);
514 	}
515 
516 	AV1394_TNF_EXIT(av1394_ir_alloc_isoch_dma);
517 	return (ret);
518 }
519 
520 static void
521 av1394_ir_free_isoch_dma(av1394_ic_t *icp)
522 {
523 	av1394_inst_t		*avp = icp->ic_avp;
524 
525 	AV1394_TNF_ENTER(av1394_ir_free_isoch_rsrc);
526 
527 	t1394_free_isoch_dma(avp->av_t1394_hdl, 0, &icp->ic_isoch_hdl);
528 
529 	AV1394_TNF_EXIT(av1394_ir_free_isoch_rsrc);
530 }
531 
532 static void
533 av1394_ir_dma_sync_frames(av1394_ic_t *icp, int idx, int cnt)
534 {
535 	av1394_ic_dma_sync_frames(icp, idx, cnt,
536 			&icp->ic_ir.ir_data_pool, DDI_DMA_SYNC_FORCPU);
537 }
538 
539 /*
540  *
541  * --- callbacks
542  *
543  */
544 /*ARGSUSED*/
545 static void
546 av1394_ir_ixl_frame_cb(opaque_t arg, struct ixl1394_callback *cb)
547 {
548 	av1394_ic_t	*icp = arg;
549 	av1394_isoch_t	*ip = &icp->ic_avp->av_i;
550 	av1394_ir_t	*irp = &icp->ic_ir;
551 
552 	AV1394_TNF_ENTER(av1394_ir_ixl_frame_cb);
553 
554 	mutex_enter(&ip->i_mutex);
555 	mutex_enter(&icp->ic_mutex);
556 	if (irp->ir_nfull < icp->ic_nframes) {
557 		irp->ir_nfull++;
558 		irp->ir_nempty--;
559 		cv_broadcast(&icp->ic_xfer_cv);
560 
561 		/*
562 		 * signal the overflow condition early, so we get enough
563 		 * time to handle it before old data is overwritten
564 		 */
565 		if (irp->ir_nfull >= irp->ir_hiwat) {
566 			av1394_ic_trigger_softintr(icp, icp->ic_num,
567 					AV1394_PREQ_IR_OVERFLOW);
568 		}
569 	}
570 	mutex_exit(&icp->ic_mutex);
571 	mutex_exit(&ip->i_mutex);
572 
573 	AV1394_TNF_EXIT(av1394_ir_ixl_frame_cb);
574 }
575 
576 /*
577  * received data overflow
578  */
579 void
580 av1394_ir_overflow(av1394_ic_t *icp)
581 {
582 	av1394_inst_t	*avp = icp->ic_avp;
583 	av1394_ir_t	*irp = &icp->ic_ir;
584 	int		idx;
585 	ixl1394_jump_t	*old_jmp;
586 	ixl1394_jump_t	new_jmp;
587 	id1394_isoch_dma_updateinfo_t update_info;
588 	int		err;
589 	int		result;
590 
591 	AV1394_TNF_ENTER(av1394_ir_overflow);
592 
593 	/*
594 	 * in the circular IXL chain overflow means overwriting the least
595 	 * recent data. to avoid that, we suspend the transfer by NULL'ing
596 	 * the last IXL block until the user process frees up some frames.
597 	 */
598 	idx = irp->ir_last_empty;
599 
600 	old_jmp = &irp->ir_ixl_data[idx].rd_jump;
601 
602 	new_jmp.ixl_opcode = IXL1394_OP_JUMP_U;
603 	new_jmp.label = NULL;
604 	new_jmp.next_ixlp = NULL;
605 
606 	update_info.orig_ixlp = (ixl1394_command_t *)old_jmp;
607 	update_info.temp_ixlp = (ixl1394_command_t *)&new_jmp;
608 	update_info.ixl_count = 1;
609 
610 	mutex_exit(&icp->ic_mutex);
611 	err = t1394_update_isoch_dma(avp->av_t1394_hdl, icp->ic_isoch_hdl,
612 	    &update_info, 0, &result);
613 	mutex_enter(&icp->ic_mutex);
614 
615 	if (err == DDI_SUCCESS) {
616 		irp->ir_overflow_idx = idx;
617 		icp->ic_state = AV1394_IC_SUSPENDED;
618 	} else {
619 		TNF_PROBE_2(av1394_ir_overflow_error_update,
620 		    AV1394_TNF_ISOCH_ERROR, "", tnf_int, err, err,
621 		    tnf_int, result, result);
622 	}
623 
624 	AV1394_TNF_EXIT(av1394_ir_overflow);
625 }
626 
627 /*
628  * restore from overflow condition
629  */
630 static void
631 av1394_ir_overflow_resume(av1394_ic_t *icp)
632 {
633 	av1394_inst_t	*avp = icp->ic_avp;
634 	av1394_ir_t	*irp = &icp->ic_ir;
635 	int		idx, next_idx;
636 	ixl1394_jump_t	*old_jmp;
637 	ixl1394_jump_t	new_jmp;
638 	id1394_isoch_dma_updateinfo_t update_info;
639 	int		err;
640 	int		result;
641 
642 	AV1394_TNF_ENTER(av1394_ir_overflow_resume);
643 
644 	/*
645 	 * restore the jump command we NULL'ed in av1394_ir_overflow()
646 	 */
647 	idx = irp->ir_overflow_idx;
648 	next_idx = (idx + 1) % icp->ic_nframes;
649 
650 	old_jmp = &irp->ir_ixl_data[idx].rd_jump;
651 
652 	new_jmp.ixl_opcode = IXL1394_OP_JUMP_U;
653 	new_jmp.label = (ixl1394_command_t *)&irp->ir_ixl_data[next_idx];
654 	new_jmp.next_ixlp = NULL;
655 
656 	update_info.orig_ixlp = (ixl1394_command_t *)old_jmp;
657 	update_info.temp_ixlp = (ixl1394_command_t *)&new_jmp;
658 	update_info.ixl_count = 1;
659 
660 	mutex_exit(&icp->ic_mutex);
661 	err = t1394_update_isoch_dma(avp->av_t1394_hdl,
662 	    icp->ic_isoch_hdl, &update_info, 0, &result);
663 	mutex_enter(&icp->ic_mutex);
664 
665 	if (err == DDI_SUCCESS) {
666 		icp->ic_state = AV1394_IC_DMA;
667 	} else {
668 		TNF_PROBE_2(av1394_ir_overflow_resume_error_update,
669 		    AV1394_TNF_ISOCH_ERROR, "", tnf_int, err, err,
670 		    tnf_int, result, result);
671 	}
672 
673 	AV1394_TNF_EXIT(av1394_ir_overflow_resume);
674 }
675 
676 /*ARGSUSED*/
677 static void
678 av1394_ir_dma_stopped_cb(t1394_isoch_dma_handle_t t1394_idma_hdl,
679 	opaque_t idma_evt_arg, id1394_isoch_dma_stopped_t status)
680 {
681 	av1394_ic_t	*icp = idma_evt_arg;
682 
683 	AV1394_TNF_ENTER(av1394_ir_dma_stopped_cb);
684 
685 	mutex_enter(&icp->ic_mutex);
686 	icp->ic_state = AV1394_IC_IDLE;
687 	mutex_exit(&icp->ic_mutex);
688 
689 	AV1394_TNF_EXIT(av1394_ir_dma_stopped_cb);
690 }
691 
692 
693 /*
694  *
695  * --- data transfer routines
696  *
697  * av1394_ir_add_frames()
698  *    Add empty frames to the pool.
699  */
700 static int
701 av1394_ir_add_frames(av1394_ic_t *icp, int idx, int cnt)
702 {
703 	av1394_ir_t	*irp = &icp->ic_ir;
704 
705 	/* can only add to the tail */
706 	if (idx != ((irp->ir_last_empty + 1) % icp->ic_nframes)) {
707 		TNF_PROBE_1(av1394_ir_add_frames_error,
708 		    AV1394_TNF_ISOCH_ERROR, "", tnf_int, idx, idx);
709 		return (EINVAL);
710 	}
711 
712 	/* turn full frames into empty ones */
713 	irp->ir_nfull -= cnt;
714 	irp->ir_first_full = (irp->ir_first_full + cnt) % icp->ic_nframes;
715 	irp->ir_nempty += cnt;
716 	irp->ir_last_empty = (irp->ir_last_empty + cnt) % icp->ic_nframes;
717 	ASSERT((irp->ir_nfull >= 0) && (irp->ir_nempty <= icp->ic_nframes));
718 
719 	/* if suspended due to overflow, check if iwe can resume */
720 	if ((icp->ic_state == AV1394_IC_SUSPENDED) &&
721 	    (irp->ir_nempty >= irp->ir_lowat)) {
722 		av1394_ir_overflow_resume(icp);
723 	}
724 
725 	return (0);
726 }
727 
728 static int
729 av1394_ir_wait_frames(av1394_ic_t *icp, int *idx, int *cnt)
730 {
731 	av1394_ir_t	*irp = &icp->ic_ir;
732 	int		ret = 0;
733 
734 	while (irp->ir_nfull == 0) {
735 		if (cv_wait_sig(&icp->ic_xfer_cv, &icp->ic_mutex) <= 0) {
736 			ret = EINTR;
737 			break;
738 		}
739 	}
740 	if (irp->ir_nfull > 0) {
741 		*idx = irp->ir_first_full;
742 		*cnt = irp->ir_nfull;
743 		av1394_ir_dma_sync_frames(icp, *idx, *cnt);
744 		ret = 0;
745 	}
746 	return (ret);
747 }
748 
749 /*
750  * copyout the data, adjust to data format and remove empty CIPs if possible
751  */
752 static int
753 av1394_ir_copyout(av1394_ic_t *icp, struct uio *uiop, int *empty_cnt)
754 {
755 	av1394_ir_t	*irp = &icp->ic_ir;
756 	av1394_isoch_seg_t *seg = irp->ir_data_pool.ip_seg;
757 	int		idx = irp->ir_read_idx;
758 	int		cnt = irp->ir_read_cnt;
759 	int		pktsz = icp->ic_pktsz;
760 	int		bs;		/* data block size */
761 	caddr_t		kaddr_begin, kaddr;
762 	int		pkt_off;	/* offset into current packet */
763 	int		len;
764 	int		frame_resid;	/* bytes left in the current frame */
765 	int		ret = 0;
766 
767 	*empty_cnt = 0;
768 
769 	/* DBS -> block size */
770 	bs = *(uchar_t *)(seg[idx].is_kaddr + 1) * 4 + AV1394_CIPSZ;
771 	if ((bs > pktsz) || (bs < AV1394_CIPSZ + 8)) {
772 		bs = pktsz;
773 	}
774 
775 	while ((cnt > 0) && (uiop->uio_resid > 0) && (ret == 0)) {
776 		kaddr = kaddr_begin = seg[idx].is_kaddr + irp->ir_read_off;
777 		frame_resid = icp->ic_framesz - irp->ir_read_off;
778 
779 		mutex_exit(&icp->ic_mutex);
780 		/* copyout data blocks, skipping empty CIPs */
781 		while ((uiop->uio_resid > 0) && (frame_resid > 0)) {
782 			pkt_off = (uintptr_t)kaddr % pktsz;
783 			/*
784 			 * a quadlet following CIP header can't be zero
785 			 * unless in an empty packet
786 			 */
787 			if ((pkt_off == 0) &&
788 			    (*(uint32_t *)(kaddr + AV1394_CIPSZ) == 0)) {
789 				kaddr += pktsz;
790 				frame_resid -= pktsz;
791 				continue;
792 			}
793 
794 			len = bs - pkt_off;
795 			if (len > uiop->uio_resid) {
796 				len = uiop->uio_resid;
797 			}
798 			if (len > frame_resid) {
799 				len = frame_resid;
800 			}
801 			if ((ret = uiomove(kaddr, len, UIO_READ, uiop)) != 0) {
802 				break;
803 			}
804 
805 			if (pkt_off + len == bs) {
806 				kaddr += pktsz - pkt_off;
807 				frame_resid -= pktsz - pkt_off;
808 			} else {
809 				kaddr += len;
810 				frame_resid -= len;
811 			}
812 		}
813 		mutex_enter(&icp->ic_mutex);
814 
815 		if (frame_resid > 0) {
816 			irp->ir_read_off = kaddr - kaddr_begin;
817 		} else {
818 			irp->ir_read_off = 0;
819 			idx = (idx + 1) % icp->ic_nframes;
820 			cnt--;
821 			(*empty_cnt)++;
822 		}
823 	}
824 
825 	return (ret);
826 }
827 
828 /*
829  * zero a quadlet in each packet so we can recognize empty CIPs
830  */
831 static void
832 av1394_ir_zero_pkts(av1394_ic_t *icp, int idx, int cnt)
833 {
834 	av1394_ir_t	*irp = &icp->ic_ir;
835 	av1394_isoch_seg_t *seg = irp->ir_data_pool.ip_seg;
836 	caddr_t		kaddr, kaddr_end;
837 	int		pktsz = icp->ic_pktsz;
838 	int		i;
839 
840 	for (i = cnt; i > 0; i--) {
841 		kaddr = seg[idx].is_kaddr + AV1394_CIPSZ;
842 		kaddr_end = seg[idx].is_kaddr + icp->ic_framesz;
843 		do {
844 			*(uint32_t *)kaddr = 0;
845 			kaddr += pktsz;
846 		} while (kaddr < kaddr_end);
847 
848 		idx = (idx + 1) % icp->ic_nframes;
849 	}
850 }
851