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