Annotation of sys/kern/tty_subr.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: tty_subr.c,v 1.18 2005/12/21 12:43:49 jsg Exp $ */
2: /* $NetBSD: tty_subr.c,v 1.13 1996/02/09 19:00:43 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1993, 1994 Theo de Raadt
6: * All rights reserved.
7: *
8: * Per Lindqvist <pgd@compuram.bbt.se> supplied an almost fully working
9: * set of true clist functions that this is very loosely based on.
10: *
11: * Redistribution and use in source and binary forms, with or without
12: * modification, are permitted provided that the following conditions
13: * are met:
14: * 1. Redistributions of source code must retain the above copyright
15: * notice, this list of conditions and the following disclaimer.
16: * 2. Redistributions in binary form must reproduce the above copyright
17: * notice, this list of conditions and the following disclaimer in the
18: * documentation and/or other materials provided with the distribution.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30: */
31:
32: #include <sys/param.h>
33: #include <sys/systm.h>
34: #include <sys/buf.h>
35: #include <sys/ioctl.h>
36: #include <sys/tty.h>
37: #include <sys/malloc.h>
38:
39: /*
40: * If TTY_QUOTE functionality isn't required by a line discipline,
41: * it can free c_cq and set it to NULL. This speeds things up,
42: * and also does not use any extra memory. This is useful for (say)
43: * a SLIP line discipline that wants a 32K ring buffer for data
44: * but doesn't need quoting.
45: */
46: #define QMEM(n) ((((n)-1)/NBBY)+1)
47:
48: void cinit(void);
49: void clrbits(u_char *, int, int);
50:
51: /*
52: * Initialize clists.
53: */
54: void
55: cinit(void)
56: {
57: }
58:
59: /*
60: * Initialize a particular clist. Ok, they are really ring buffers,
61: * of the specified length, with/without quoting support.
62: */
63: int
64: clalloc(struct clist *clp, int size, int quot)
65: {
66:
67: clp->c_cs = malloc(size, M_TTYS, M_WAITOK);
68: bzero(clp->c_cs, size);
69:
70: if (quot) {
71: clp->c_cq = malloc(QMEM(size), M_TTYS, M_WAITOK);
72: bzero(clp->c_cq, QMEM(size));
73: } else
74: clp->c_cq = (u_char *)0;
75:
76: clp->c_cf = clp->c_cl = (u_char *)0;
77: clp->c_ce = clp->c_cs + size;
78: clp->c_cn = size;
79: clp->c_cc = 0;
80: return (0);
81: }
82:
83: void
84: clfree(struct clist *clp)
85: {
86: if (clp->c_cs) {
87: bzero(clp->c_cs, clp->c_cn);
88: free(clp->c_cs, M_TTYS);
89: }
90: if (clp->c_cq) {
91: bzero(clp->c_cq, QMEM(clp->c_cn));
92: free(clp->c_cq, M_TTYS);
93: }
94: clp->c_cs = clp->c_cq = (u_char *)0;
95: }
96:
97:
98: /*
99: * Get a character from a clist.
100: */
101: int
102: getc(struct clist *clp)
103: {
104: int c = -1;
105: int s;
106:
107: s = spltty();
108: if (clp->c_cc == 0)
109: goto out;
110:
111: c = *clp->c_cf & 0xff;
112: if (clp->c_cq) {
113: if (isset(clp->c_cq, clp->c_cf - clp->c_cs) )
114: c |= TTY_QUOTE;
115: }
116: if (++clp->c_cf == clp->c_ce)
117: clp->c_cf = clp->c_cs;
118: if (--clp->c_cc == 0)
119: clp->c_cf = clp->c_cl = (u_char *)0;
120: out:
121: splx(s);
122: return c;
123: }
124:
125: /*
126: * Copy clist to buffer.
127: * Return number of bytes moved.
128: */
129: int
130: q_to_b(struct clist *clp, u_char *cp, int count)
131: {
132: int cc;
133: u_char *p = cp;
134: int s;
135:
136: s = spltty();
137: /* optimize this while loop */
138: while (count > 0 && clp->c_cc > 0) {
139: cc = clp->c_cl - clp->c_cf;
140: if (clp->c_cf >= clp->c_cl)
141: cc = clp->c_ce - clp->c_cf;
142: if (cc > count)
143: cc = count;
144: bcopy(clp->c_cf, p, cc);
145: count -= cc;
146: p += cc;
147: clp->c_cc -= cc;
148: clp->c_cf += cc;
149: if (clp->c_cf == clp->c_ce)
150: clp->c_cf = clp->c_cs;
151: }
152: if (clp->c_cc == 0)
153: clp->c_cf = clp->c_cl = (u_char *)0;
154: splx(s);
155: return p - cp;
156: }
157:
158: /*
159: * Return count of contiguous characters in clist.
160: * Stop counting if flag&character is non-null.
161: */
162: int
163: ndqb(struct clist *clp, int flag)
164: {
165: int count = 0;
166: int i;
167: int cc;
168: int s;
169:
170: s = spltty();
171: if ((cc = clp->c_cc) == 0)
172: goto out;
173:
174: if (flag == 0) {
175: count = clp->c_cl - clp->c_cf;
176: if (count <= 0)
177: count = clp->c_ce - clp->c_cf;
178: goto out;
179: }
180:
181: i = clp->c_cf - clp->c_cs;
182: if (flag & TTY_QUOTE) {
183: while (cc-- > 0 && !(clp->c_cs[i++] & (flag & ~TTY_QUOTE) ||
184: isset(clp->c_cq, i))) {
185: count++;
186: if (i == clp->c_cn)
187: break;
188: }
189: } else {
190: while (cc-- > 0 && !(clp->c_cs[i++] & flag)) {
191: count++;
192: if (i == clp->c_cn)
193: break;
194: }
195: }
196: out:
197: splx(s);
198: return count;
199: }
200:
201: /*
202: * Flush count bytes from clist.
203: */
204: void
205: ndflush(struct clist *clp, int count)
206: {
207: int cc;
208: int s;
209:
210: s = spltty();
211: if (count == clp->c_cc) {
212: clp->c_cc = 0;
213: clp->c_cf = clp->c_cl = (u_char *)0;
214: goto out;
215: }
216: /* optimize this while loop */
217: while (count > 0 && clp->c_cc > 0) {
218: cc = clp->c_cl - clp->c_cf;
219: if (clp->c_cf >= clp->c_cl)
220: cc = clp->c_ce - clp->c_cf;
221: if (cc > count)
222: cc = count;
223: count -= cc;
224: clp->c_cc -= cc;
225: clp->c_cf += cc;
226: if (clp->c_cf == clp->c_ce)
227: clp->c_cf = clp->c_cs;
228: }
229: if (clp->c_cc == 0)
230: clp->c_cf = clp->c_cl = (u_char *)0;
231: out:
232: splx(s);
233: }
234:
235: /*
236: * Put a character into the output queue.
237: */
238: int
239: putc(int c, struct clist *clp)
240: {
241: int i;
242: int s;
243:
244: s = spltty();
245: if (clp->c_cc == clp->c_cn)
246: goto out;
247:
248: if (clp->c_cc == 0) {
249: if (!clp->c_cs) {
250: #if defined(DIAGNOSTIC) || 1
251: printf("putc: required clalloc\n");
252: #endif
253: if (clalloc(clp, 1024, 1)) {
254: out:
255: splx(s);
256: return -1;
257: }
258: }
259: clp->c_cf = clp->c_cl = clp->c_cs;
260: }
261:
262: *clp->c_cl = c & 0xff;
263: i = clp->c_cl - clp->c_cs;
264: if (clp->c_cq) {
265: if (c & TTY_QUOTE)
266: setbit(clp->c_cq, i);
267: else
268: clrbit(clp->c_cq, i);
269: }
270: clp->c_cc++;
271: clp->c_cl++;
272: if (clp->c_cl == clp->c_ce)
273: clp->c_cl = clp->c_cs;
274: splx(s);
275: return 0;
276: }
277:
278: /*
279: * optimized version of
280: *
281: * for (i = 0; i < len; i++)
282: * clrbit(cp, off + len);
283: */
284: void
285: clrbits(u_char *cp, int off, int len)
286: {
287: int sby, sbi, eby, ebi;
288: int i;
289: u_char mask;
290:
291: if (len==1) {
292: clrbit(cp, off);
293: return;
294: }
295:
296: sby = off / NBBY;
297: sbi = off % NBBY;
298: eby = (off+len) / NBBY;
299: ebi = (off+len) % NBBY;
300: if (sby == eby) {
301: mask = ((1 << (ebi - sbi)) - 1) << sbi;
302: cp[sby] &= ~mask;
303: } else {
304: mask = (1<<sbi) - 1;
305: cp[sby++] &= mask;
306:
307: mask = (1<<ebi) - 1;
308: cp[eby] &= ~mask;
309:
310: for (i = sby; i < eby; i++)
311: cp[i] = 0x00;
312: }
313: }
314:
315: /*
316: * Copy buffer to clist.
317: * Return number of bytes not transferred.
318: */
319: int
320: b_to_q(u_char *cp, int count, struct clist *clp)
321: {
322: int cc;
323: u_char *p = cp;
324: int s;
325:
326: if (count <= 0)
327: return 0;
328:
329: s = spltty();
330: if (clp->c_cc == clp->c_cn)
331: goto out;
332:
333: if (clp->c_cc == 0) {
334: if (!clp->c_cs) {
335: #if defined(DIAGNOSTIC) || 1
336: printf("b_to_q: required clalloc\n");
337: #endif
338: if (clalloc(clp, 1024, 1))
339: goto out;
340: }
341: clp->c_cf = clp->c_cl = clp->c_cs;
342: }
343:
344: /* optimize this while loop */
345: while (count > 0 && clp->c_cc < clp->c_cn) {
346: cc = clp->c_ce - clp->c_cl;
347: if (clp->c_cf > clp->c_cl)
348: cc = clp->c_cf - clp->c_cl;
349: if (cc > count)
350: cc = count;
351: bcopy(p, clp->c_cl, cc);
352: if (clp->c_cq) {
353: clrbits(clp->c_cq, clp->c_cl - clp->c_cs, cc);
354: }
355: p += cc;
356: count -= cc;
357: clp->c_cc += cc;
358: clp->c_cl += cc;
359: if (clp->c_cl == clp->c_ce)
360: clp->c_cl = clp->c_cs;
361: }
362: out:
363: splx(s);
364: return count;
365: }
366:
367: static int cc;
368:
369: /*
370: * Given a non-NULL pointer into the clist return the pointer
371: * to the next character in the list or return NULL if no more chars.
372: *
373: * Callers must not allow getc's to happen between firstc's and getc's
374: * so that the pointer becomes invalid. Note that interrupts are NOT
375: * masked.
376: */
377: u_char *
378: nextc(struct clist *clp, u_char *cp, int *c)
379: {
380:
381: if (clp->c_cf == cp) {
382: /*
383: * First time initialization.
384: */
385: cc = clp->c_cc;
386: }
387: if (cc == 0 || cp == NULL)
388: return NULL;
389: if (--cc == 0)
390: return NULL;
391: if (++cp == clp->c_ce)
392: cp = clp->c_cs;
393: *c = *cp & 0xff;
394: if (clp->c_cq) {
395: if (isset(clp->c_cq, cp - clp->c_cs))
396: *c |= TTY_QUOTE;
397: }
398: return cp;
399: }
400:
401: /*
402: * Given a non-NULL pointer into the clist return the pointer
403: * to the first character in the list or return NULL if no more chars.
404: *
405: * Callers must not allow getc's to happen between firstc's and getc's
406: * so that the pointer becomes invalid. Note that interrupts are NOT
407: * masked.
408: *
409: * *c is set to the NEXT character
410: */
411: u_char *
412: firstc(struct clist *clp, int *c)
413: {
414: u_char *cp;
415:
416: cc = clp->c_cc;
417: if (cc == 0)
418: return NULL;
419: cp = clp->c_cf;
420: *c = *cp & 0xff;
421: if (clp->c_cq) {
422: if (isset(clp->c_cq, cp - clp->c_cs))
423: *c |= TTY_QUOTE;
424: }
425: return clp->c_cf;
426: }
427:
428: /*
429: * Remove the last character in the clist and return it.
430: */
431: int
432: unputc(struct clist *clp)
433: {
434: unsigned int c = -1;
435: int s;
436:
437: s = spltty();
438: if (clp->c_cc == 0)
439: goto out;
440:
441: if (clp->c_cl == clp->c_cs)
442: clp->c_cl = clp->c_ce - 1;
443: else
444: --clp->c_cl;
445: clp->c_cc--;
446:
447: c = *clp->c_cl & 0xff;
448: if (clp->c_cq) {
449: if (isset(clp->c_cq, clp->c_cl - clp->c_cs))
450: c |= TTY_QUOTE;
451: }
452: if (clp->c_cc == 0)
453: clp->c_cf = clp->c_cl = (u_char *)0;
454: out:
455: splx(s);
456: return c;
457: }
458:
459: /*
460: * Put the chars in the from queue on the end of the to queue.
461: */
462: void
463: catq(struct clist *from, struct clist *to)
464: {
465: int c;
466: int s;
467:
468: s = spltty();
469: if (from->c_cc == 0) { /* nothing to move */
470: splx(s);
471: return;
472: }
473:
474: /*
475: * if `to' queue is empty and the queues are the same max size,
476: * it is more efficient to just swap the clist structures.
477: */
478: if (to->c_cc == 0 && from->c_cn == to->c_cn) {
479: struct clist tmp;
480:
481: tmp = *from;
482: *from = *to;
483: *to = tmp;
484: splx(s);
485: return;
486: }
487: splx(s);
488:
489: while ((c = getc(from)) != -1)
490: putc(c, to);
491: }
CVSweb