Annotation of sys/kern/tty_subr.c, Revision 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