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