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
av1394_initq(av1394_queue_t * q,ddi_iblock_cookie_t ibc,int max)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
av1394_destroyq(av1394_queue_t * q)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
av1394_setmaxq(av1394_queue_t * q,int max)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
av1394_getmaxq(av1394_queue_t * q)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
av1394_flushq(av1394_queue_t * q)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
av1394_putq(av1394_queue_t * q,mblk_t * bp)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
av1394_putbq(av1394_queue_t * q,mblk_t * bp)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 *
av1394_getq(av1394_queue_t * q)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 *
av1394_peekq(av1394_queue_t * q)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 *
av1394_peekq_locked(av1394_queue_t * q)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
av1394_qwait_sig(av1394_queue_t * q)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
av1394_put_common(av1394_queue_t * q,mblk_t * bp,putfunc_t put)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 *
av1394_getq_locked(av1394_queue_t * q)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