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