FreeBSD/Linux Kernel Cross Reference
sys/device/cirbuf.c
1 /*
2 * Mach Operating System
3 * Copyright (c) 1992,1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26 /*
27 * HISTORY
28 * $Log: cirbuf.c,v $
29 * Revision 2.10 93/05/17 10:31:09 rvb
30 * Fixed nasty bug in getc(): it was returning -1 when
31 * the character was 0xff. This makes SLIP work on DS boxes.
32 * [93/05/13 20:28:59 af]
33 *
34 *
35 * Revision 2.9 93/01/14 17:26:33 danner
36 * Added function prototypes. Added cb_clear.
37 * [92/11/17 dbg]
38 * Added function prototypes. Added cb_clear.
39 * [92/11/17 dbg]
40 *
41 * Revision 2.8 92/08/03 17:32:56 jfriedl
42 * removed silly prototypes
43 * [92/08/02 jfriedl]
44 *
45 * Revision 2.7 92/05/21 17:08:44 jfriedl
46 * tried prototypes.
47 * [92/05/20 jfriedl]
48 *
49 * Revision 2.6 92/05/05 10:46:15 danner
50 * Initialize c_hog.
51 * [92/05/04 af]
52 *
53 * Revision 2.5 91/07/31 17:32:09 dbg
54 * Put CB_CHECK under debugging switch.
55 * [91/07/30 16:45:34 dbg]
56 *
57 * Revision 2.4 91/05/14 15:39:25 mrt
58 * Correcting copyright
59 *
60 * Revision 2.3 91/02/05 17:08:01 mrt
61 * Changed to new Mach copyright
62 * [91/01/31 17:26:33 mrt]
63 *
64 * Revision 2.2 90/08/27 21:54:30 dbg
65 * q_to_b was always emptying the circular buffer; fix it.
66 * [90/08/06 dbg]
67 * Created.
68 * [90/07/09 dbg]
69 *
70 */
71 /*
72 * Author: David B. Golub, Carnegie Mellon University
73 * Date: 7/90
74 *
75 * Circular buffers for TTY
76 */
77
78 #include <device/cirbuf.h>
79 #include <kern/kalloc.h>
80
81
82
83 /* read at c_cf, write at c_cl */
84 /* if c_cf == c_cl, buffer is empty */
85 /* if c_cl == c_cf - 1, buffer is full */
86
87 #if DEBUG
88 int cb_check_enable = 0;
89 #define CB_CHECK(cb) if (cb_check_enable) cb_check(cb)
90
91 void
92 cb_check(register struct cirbuf *cb)
93 {
94 if (!(cb->c_cf >= cb->c_start && cb->c_cf < cb->c_end))
95 panic("cf %x out of range [%x..%x)",
96 cb->c_cf, cb->c_start, cb->c_end);
97 if (!(cb->c_cl >= cb->c_start && cb->c_cl < cb->c_end))
98 panic("cl %x out of range [%x..%x)",
99 cb->c_cl, cb->c_start, cb->c_end);
100 if (cb->c_cf <= cb->c_cl) {
101 if (!(cb->c_cc == cb->c_cl - cb->c_cf))
102 panic("cc %x should be %x",
103 cb->c_cc,
104 cb->c_cl - cb->c_cf);
105 }
106 else {
107 if (!(cb->c_cc == cb->c_end - cb->c_cf
108 + cb->c_cl - cb->c_start))
109 panic("cc %x should be %x",
110 cb->c_cc,
111 cb->c_end - cb->c_cf +
112 cb->c_cl - cb->c_start);
113 }
114 }
115 #else /* DEBUG */
116 #define CB_CHECK(cb)
117 #endif /* DEBUG */
118
119 /*
120 * Put one character in circular buffer.
121 */
122 int putc(
123 int c,
124 register struct cirbuf *cb)
125 {
126 register char *ow, *nw;
127
128 ow = cb->c_cl;
129 nw = ow+1;
130 if (nw == cb->c_end)
131 nw = cb->c_start;
132 if (nw == cb->c_cf)
133 return 1; /* not entered */
134 *ow = c;
135 cb->c_cl = nw;
136
137 cb->c_cc++;
138
139 CB_CHECK(cb);
140
141 return 0;
142 }
143
144 /*
145 * Get one character from circular buffer.
146 */
147 int getc(register struct cirbuf *cb)
148 {
149 register unsigned char *nr;
150 register int c;
151
152 nr = (unsigned char *)cb->c_cf;
153 if (nr == (unsigned char *)cb->c_cl) {
154 CB_CHECK(cb);
155 return -1; /* empty */
156 }
157 c = *nr;
158 nr++;
159 if (nr == (unsigned char *)cb->c_end)
160 nr = (unsigned char *)cb->c_start;
161 cb->c_cf = (char *)nr;
162
163 cb->c_cc--;
164
165 CB_CHECK(cb);
166
167 return c;
168 }
169
170 /*
171 * Get lots of characters.
172 * Return number moved.
173 */
174 int
175 q_to_b( register struct cirbuf *cb,
176 register char *cp,
177 register int count)
178 {
179 char * ocp = cp;
180 register int i;
181
182 while (count != 0) {
183 if (cb->c_cl == cb->c_cf)
184 break; /* empty */
185 if (cb->c_cl < cb->c_cf)
186 i = cb->c_end - cb->c_cf;
187 else
188 i = cb->c_cl - cb->c_cf;
189 if (i > count)
190 i = count;
191 bcopy(cb->c_cf, cp, i);
192 cp += i;
193 count -= i;
194 cb->c_cf += i;
195 cb->c_cc -= i;
196 if (cb->c_cf == cb->c_end)
197 cb->c_cf = cb->c_start;
198
199 CB_CHECK(cb);
200 }
201 CB_CHECK(cb);
202
203 return cp - ocp;
204 }
205
206 /*
207 * Add character array to buffer and return number of characters
208 * NOT entered.
209 */
210 int
211 b_to_q( register char * cp,
212 int count,
213 register struct cirbuf *cb)
214 {
215 register int i;
216 register char *lim;
217
218 while (count != 0) {
219 lim = cb->c_cf - 1;
220 if (lim < cb->c_start)
221 lim = cb->c_end - 1;
222
223 if (cb->c_cl == lim)
224 break;
225 if (cb->c_cl < lim)
226 i = lim - cb->c_cl;
227 else
228 i = cb->c_end - cb->c_cl;
229
230 if (i > count)
231 i = count;
232 bcopy(cp, cb->c_cl, i);
233 cp += i;
234 count -= i;
235 cb->c_cc += i;
236 cb->c_cl += i;
237 if (cb->c_cl == cb->c_end)
238 cb->c_cl = cb->c_start;
239
240 CB_CHECK(cb);
241 }
242 CB_CHECK(cb);
243 return count;
244 }
245
246 /*
247 * Return number of contiguous characters up to a character
248 * that matches the mask.
249 */
250 int
251 ndqb( register struct cirbuf *cb,
252 register int mask)
253 {
254 register char *cp, *lim;
255
256 if (cb->c_cl < cb->c_cf)
257 lim = cb->c_end;
258 else
259 lim = cb->c_cl;
260 if (mask == 0)
261 return (lim - cb->c_cf);
262 cp = cb->c_cf;
263 while (cp < lim) {
264 if (*cp & mask)
265 break;
266 cp++;
267 }
268 return (cp - cb->c_cf);
269 }
270
271 /*
272 * Flush characters from circular buffer.
273 */
274 void
275 ndflush(register struct cirbuf *cb,
276 register int count)
277 {
278 register int i;
279
280 while (count != 0) {
281 if (cb->c_cl == cb->c_cf)
282 break; /* empty */
283 if (cb->c_cl < cb->c_cf)
284 i = cb->c_end - cb->c_cf;
285 else
286 i = cb->c_cl - cb->c_cf;
287 if (i > count)
288 i = count;
289 count -= i;
290 cb->c_cf += i;
291 cb->c_cc -= i;
292 if (cb->c_cf == cb->c_end)
293 cb->c_cf = cb->c_start;
294 CB_CHECK(cb);
295 }
296
297 CB_CHECK(cb);
298 }
299
300 /*
301 * Empty a circular buffer.
302 */
303 void cb_clear(struct cirbuf *cb)
304 {
305 cb->c_cf = cb->c_start;
306 cb->c_cl = cb->c_start;
307 cb->c_cc = 0;
308 }
309
310 /*
311 * Allocate character space for a circular buffer.
312 */
313 void
314 cb_alloc(
315 register struct cirbuf *cb,
316 int buf_size)
317 {
318 register char *buf;
319
320 buf = (char *)kalloc(buf_size);
321
322 cb->c_start = buf;
323 cb->c_end = buf + buf_size;
324 cb->c_cf = buf;
325 cb->c_cl = buf;
326 cb->c_cc = 0;
327 cb->c_hog = buf_size - 1;
328
329 CB_CHECK(cb);
330 }
331
332 /*
333 * Free character space for a circular buffer.
334 */
335 void
336 cb_free(register struct cirbuf *cb)
337 {
338 int size;
339
340 size = cb->c_end - cb->c_start;
341 kfree((vm_offset_t)cb->c_start, size);
342 }
343
Cache object: 2349482ee7a823f1a1193fcca067bd86
|