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 2002 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 queue
31  *    Based on av1394 list, plus locking, works only with mblk's,
32  *    counts and limits amount of data on the queue.
33  */
34 #include <sys/stream.h>
35 #include <sys/strsun.h>
36 #include <sys/1394/targets/av1394/av1394_impl.h>
37 
38 typedef void (*putfunc_t)(av1394_list_t *, void *);
39 
40 static mblk_t	*av1394_getq_locked(av1394_queue_t *);
41 static int	av1394_put_common(av1394_queue_t *, mblk_t *, putfunc_t);
42 
43 void
44 av1394_initq(av1394_queue_t *q, ddi_iblock_cookie_t ibc, int max)
45 {
46 	bzero(q, sizeof (av1394_queue_t));
47 
48 	mutex_init(&q->q_mutex, NULL, MUTEX_DRIVER, ibc);
49 	cv_init(&q->q_cv, NULL, CV_DRIVER, NULL);
50 
51 	AV1394_ENTERQ(q);
52 	av1394_list_init(&q->q_list);
53 	q->q_max = max;
54 	AV1394_LEAVEQ(q);
55 }
56 
57 void
58 av1394_destroyq(av1394_queue_t *q)
59 {
60 	av1394_flushq(q);
61 	mutex_destroy(&q->q_mutex);
62 	cv_destroy(&q->q_cv);
63 }
64 
65 void
66 av1394_setmaxq(av1394_queue_t *q, int max)
67 {
68 	AV1394_ENTERQ(q);
69 	q->q_max = max;
70 	AV1394_LEAVEQ(q);
71 }
72 
73 int
74 av1394_getmaxq(av1394_queue_t *q)
75 {
76 	int	max;
77 
78 	AV1394_ENTERQ(q);
79 	max = q->q_max;
80 	AV1394_LEAVEQ(q);
81 	return (max);
82 }
83 
84 void
85 av1394_flushq(av1394_queue_t *q)
86 {
87 	mblk_t	*bp;
88 
89 	AV1394_ENTERQ(q);
90 	while ((bp = av1394_getq_locked(q)) != NULL) {
91 		freemsg(bp);
92 	}
93 	ASSERT(q->q_size == 0);
94 	AV1394_LEAVEQ(q);
95 }
96 
97 int
98 av1394_putq(av1394_queue_t *q, mblk_t *bp)
99 {
100 	return (av1394_put_common(q, bp, av1394_list_put_tail));
101 }
102 
103 int
104 av1394_putbq(av1394_queue_t *q, mblk_t *bp)
105 {
106 	return (av1394_put_common(q, bp, av1394_list_put_head));
107 }
108 
109 mblk_t *
110 av1394_getq(av1394_queue_t *q)
111 {
112 	mblk_t	*bp;
113 
114 	AV1394_ENTERQ(q);
115 	bp = av1394_getq_locked(q);
116 	AV1394_LEAVEQ(q);
117 
118 	return (bp);
119 }
120 
121 mblk_t *
122 av1394_peekq(av1394_queue_t *q)
123 {
124 	mblk_t	*mp;
125 
126 	AV1394_ENTERQ(q);
127 	mp = av1394_peekq_locked(q);
128 	AV1394_LEAVEQ(q);
129 	return (mp);
130 }
131 
132 mblk_t *
133 av1394_peekq_locked(av1394_queue_t *q)
134 {
135 	ASSERT(mutex_owned(&q->q_mutex));
136 	return (av1394_list_head(&q->q_list));
137 }
138 
139 /*
140  * wait until queue is not empty or a signal arrives
141  */
142 int
143 av1394_qwait_sig(av1394_queue_t *q)
144 {
145 	int	ret = 1;
146 
147 	AV1394_ENTERQ(q);
148 	while (av1394_peekq_locked(q) == NULL) {
149 		if ((ret = cv_wait_sig(&q->q_cv, &q->q_mutex)) <= 0) {
150 			break;
151 		}
152 	}
153 	AV1394_LEAVEQ(q);
154 
155 	return (ret);
156 }
157 
158 static int
159 av1394_put_common(av1394_queue_t *q, mblk_t *bp, putfunc_t put)
160 {
161 	int	ret;
162 	int	len = MBLKL(bp);
163 
164 	AV1394_ENTERQ(q);
165 	if (q->q_size + len > q->q_max) {
166 		ret = 0;
167 	} else {
168 		put(&q->q_list, bp);
169 		q->q_size += len;
170 		cv_broadcast(&q->q_cv);
171 		ret = 1;
172 	}
173 	AV1394_LEAVEQ(q);
174 
175 	return (ret);
176 }
177 
178 static mblk_t *
179 av1394_getq_locked(av1394_queue_t *q)
180 {
181 	mblk_t	*bp;
182 
183 	if ((bp = av1394_list_get_head(&q->q_list)) != NULL) {
184 		q->q_size -= MBLKL(bp);
185 		ASSERT(q->q_size >= 0);
186 	}
187 	return (bp);
188 }
189