1: /* 2: * Copyright (c) 1986 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: * 6: * @(#)tty_subr.c 1.1 (2.10BSD Berkeley) 12/1/86 7: */ 8: 9: #include "param.h" 10: #include "../machine/seg.h" 11: #include "clist.h" 12: #include "ioctl.h" 13: #include "tty.h" 14: 15: #ifdef UCB_CLIST 16: /* 17: * Modification to move clists out of kernel data space. 18: * Clist space is allocated by startup. 19: */ 20: memaddr clststrt; /* physical click address of clist */ 21: struct cblock *cfree = (struct cblock *)SEG5; 22: #endif 23: 24: char cwaiting; 25: 26: /* 27: * Character list get/put 28: */ 29: getc(p) 30: register struct clist *p; 31: { 32: register struct cblock *bp; 33: register int c, s; 34: #ifdef UCB_CLIST 35: segm sav5; 36: #endif 37: 38: s = spltty(); 39: #ifdef UCB_CLIST 40: saveseg5(sav5); 41: mapseg5(clststrt, clstdesc); 42: #endif 43: if (p->c_cc <= 0) { 44: c = -1; 45: p->c_cc = 0; 46: p->c_cf = p->c_cl = NULL; 47: } else { 48: c = *p->c_cf++ & 0377; 49: if (--p->c_cc<=0) { 50: bp = (struct cblock *)(p->c_cf-1); 51: bp = (struct cblock *)((int)bp & ~CROUND); 52: p->c_cf = NULL; 53: p->c_cl = NULL; 54: bp->c_next = cfreelist; 55: cfreelist = bp; 56: cfreecount += CBSIZE; 57: if (cwaiting) { 58: wakeup(&cwaiting); 59: cwaiting = 0; 60: } 61: } else if (((int)p->c_cf & CROUND) == 0){ 62: bp = (struct cblock *)(p->c_cf); 63: bp--; 64: p->c_cf = bp->c_next->c_info; 65: bp->c_next = cfreelist; 66: cfreelist = bp; 67: cfreecount += CBSIZE; 68: if (cwaiting) { 69: wakeup(&cwaiting); 70: cwaiting = 0; 71: } 72: } 73: } 74: #ifdef UCB_CLIST 75: restorseg5(sav5); 76: #endif 77: splx(s); 78: return (c); 79: } 80: 81: /* 82: * copy clist to buffer. 83: * return number of bytes moved. 84: */ 85: q_to_b(q, cp, cc) 86: register struct clist *q; 87: char *cp; 88: { 89: register struct cblock *bp; 90: register nc; 91: int s; 92: char *acp; 93: #ifdef UCB_CLIST 94: segm sav5; 95: #endif 96: 97: if (cc <= 0) 98: return (0); 99: s = spltty(); 100: #ifdef UCB_CLIST 101: saveseg5(sav5); 102: mapseg5(clststrt, clstdesc); 103: #endif 104: if (q->c_cc <= 0) { 105: q->c_cc = 0; 106: q->c_cf = q->c_cl = NULL; 107: #ifdef UCB_CLIST 108: restorseg5(sav5); 109: #endif 110: splx(s); 111: return (0); 112: } 113: acp = cp; 114: 115: while (cc) { 116: nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND); 117: nc = MIN(nc, cc); 118: nc = MIN(nc, q->c_cc); 119: (void) bcopy(q->c_cf, cp, (unsigned)nc); 120: q->c_cf += nc; 121: q->c_cc -= nc; 122: cc -= nc; 123: cp += nc; 124: if (q->c_cc <= 0) { 125: bp = (struct cblock *)(q->c_cf - 1); 126: bp = (struct cblock *)((int)bp & ~CROUND); 127: q->c_cf = q->c_cl = NULL; 128: bp->c_next = cfreelist; 129: cfreelist = bp; 130: cfreecount += CBSIZE; 131: if (cwaiting) { 132: wakeup(&cwaiting); 133: cwaiting = 0; 134: } 135: break; 136: } 137: if (((int)q->c_cf & CROUND) == 0) { 138: bp = (struct cblock *)(q->c_cf); 139: bp--; 140: q->c_cf = bp->c_next->c_info; 141: bp->c_next = cfreelist; 142: cfreelist = bp; 143: cfreecount += CBSIZE; 144: if (cwaiting) { 145: wakeup(&cwaiting); 146: cwaiting = 0; 147: } 148: } 149: } 150: #ifdef UCB_CLIST 151: restorseg5(sav5); 152: #endif 153: splx(s); 154: return (cp-acp); 155: } 156: 157: /* 158: * Return count of contiguous characters 159: * in clist starting at q->c_cf. 160: * Stop counting if flag&character is non-null. 161: */ 162: ndqb(q, flag) 163: register struct clist *q; 164: { 165: int cc; 166: int s; 167: #ifdef UCB_CLIST 168: segm sav5; 169: #endif 170: 171: s = spltty(); 172: if (q->c_cc <= 0) { 173: cc = -q->c_cc; 174: goto out; 175: } 176: cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 177: cc -= (int)q->c_cf; 178: if (q->c_cc < cc) 179: cc = q->c_cc; 180: if (flag) { 181: register char *p, *end; 182: 183: #ifdef UCB_CLIST 184: saveseg5(sav5); 185: mapseg5(clststrt, clstdesc); 186: #endif 187: p = q->c_cf; 188: end = p; 189: end += cc; 190: while (p < end) { 191: if (*p & flag) { 192: cc = (int)p; 193: cc -= (int)q->c_cf; 194: break; 195: } 196: p++; 197: } 198: #ifdef UCB_CLIST 199: restorseg5(sav5); 200: #endif 201: } 202: out: 203: splx(s); 204: return (cc); 205: } 206: 207: /* 208: * Flush cc bytes from q. 209: */ 210: ndflush(q, cc) 211: register struct clist *q; 212: register cc; 213: { 214: register struct cblock *bp; 215: char *end; 216: int rem, s; 217: #ifdef UCB_CLIST 218: segm sav5; 219: #endif 220: 221: s = spltty(); 222: if (q->c_cc <= 0) 223: goto out; 224: #ifdef UCB_CLIST 225: saveseg5(sav5); 226: mapseg5(clststrt, clstdesc); 227: #endif 228: while (cc>0 && q->c_cc) { 229: bp = (struct cblock *)((int)q->c_cf & ~CROUND); 230: if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 231: end = q->c_cl; 232: } else { 233: end = (char *)((int)bp + sizeof (struct cblock)); 234: } 235: rem = end - q->c_cf; 236: if (cc >= rem) { 237: cc -= rem; 238: q->c_cc -= rem; 239: q->c_cf = bp->c_next->c_info; 240: bp->c_next = cfreelist; 241: cfreelist = bp; 242: cfreecount += CBSIZE; 243: if (cwaiting) { 244: wakeup(&cwaiting); 245: cwaiting = 0; 246: } 247: } else { 248: q->c_cc -= cc; 249: q->c_cf += cc; 250: if (q->c_cc <= 0) { 251: bp->c_next = cfreelist; 252: cfreelist = bp; 253: cfreecount += CBSIZE; 254: if (cwaiting) { 255: wakeup(&cwaiting); 256: cwaiting = 0; 257: } 258: } 259: break; 260: } 261: } 262: #ifdef UCB_CLIST 263: restorseg5(sav5); 264: #endif 265: if (q->c_cc <= 0) { 266: q->c_cf = q->c_cl = NULL; 267: q->c_cc = 0; 268: } 269: out: 270: splx(s); 271: } 272: 273: putc(c, p) 274: register struct clist *p; 275: { 276: register struct cblock *bp; 277: register char *cp; 278: register s; 279: #ifdef UCB_CLIST 280: segm sav5; 281: #endif 282: 283: s = spltty(); 284: #ifdef UCB_CLIST 285: saveseg5(sav5); 286: mapseg5(clststrt, clstdesc); 287: #endif 288: if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 289: if ((bp = cfreelist) == NULL) { 290: splx(s); 291: #ifdef UCB_CLIST 292: restorseg5(sav5); 293: #endif 294: return (-1); 295: } 296: cfreelist = bp->c_next; 297: cfreecount -= CBSIZE; 298: bp->c_next = NULL; 299: p->c_cf = cp = bp->c_info; 300: } else if (((int)cp & CROUND) == 0) { 301: bp = (struct cblock *)cp - 1; 302: if ((bp->c_next = cfreelist) == NULL) { 303: splx(s); 304: #ifdef UCB_CLIST 305: restorseg5(sav5); 306: #endif 307: return (-1); 308: } 309: bp = bp->c_next; 310: cfreelist = bp->c_next; 311: cfreecount -= CBSIZE; 312: bp->c_next = NULL; 313: cp = bp->c_info; 314: } 315: *cp++ = c; 316: p->c_cc++; 317: p->c_cl = cp; 318: #ifdef UCB_CLIST 319: restorseg5(sav5); 320: #endif 321: splx(s); 322: return (0); 323: } 324: 325: /* 326: * copy buffer to clist. 327: * return number of bytes not transfered. 328: */ 329: b_to_q(cp, cc, q) 330: register char *cp; 331: struct clist *q; 332: register int cc; 333: { 334: register char *cq; 335: register struct cblock *bp; 336: register s, nc; 337: int acc; 338: #ifdef UCB_CLIST 339: segm sav5; 340: #endif 341: 342: if (cc <= 0) 343: return (0); 344: acc = cc; 345: s = spltty(); 346: #ifdef UCB_CLIST 347: saveseg5(sav5); 348: mapseg5(clststrt, clstdesc); 349: #endif 350: if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 351: if ((bp = cfreelist) == NULL) 352: goto out; 353: cfreelist = bp->c_next; 354: cfreecount -= CBSIZE; 355: bp->c_next = NULL; 356: q->c_cf = cq = bp->c_info; 357: } 358: 359: while (cc) { 360: if (((int)cq & CROUND) == 0) { 361: bp = (struct cblock *)cq - 1; 362: if ((bp->c_next = cfreelist) == NULL) 363: goto out; 364: bp = bp->c_next; 365: cfreelist = bp->c_next; 366: cfreecount -= CBSIZE; 367: bp->c_next = NULL; 368: cq = bp->c_info; 369: } 370: nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND)); 371: (void) bcopy(cp, cq, (unsigned)nc); 372: cp += nc; 373: cq += nc; 374: cc -= nc; 375: } 376: out: 377: q->c_cl = cq; 378: q->c_cc += acc - cc; 379: #ifdef UCB_CLIST 380: restorseg5(sav5); 381: #endif 382: splx(s); 383: return (cc); 384: } 385: 386: /* 387: * Given a non-NULL pointter into the list (like c_cf which 388: * always points to a real character if non-NULL) return the pointer 389: * to the next character in the list or return NULL if no more chars. 390: * 391: * Callers must not allow getc's to happen between nextc's so that the 392: * pointer becomes invalid. Note that interrupts are NOT masked. 393: */ 394: char * 395: #ifdef UCB_CLIST 396: nextc(p, cp, store) 397: register struct clist *p; 398: register char *cp; 399: char *store; 400: { 401: register char *rcp; 402: segm sav5; 403: 404: saveseg5(sav5); 405: mapseg5(clststrt, clstdesc); 406: #else 407: nextc(p, cp) 408: register struct clist *p; 409: register char *cp; 410: { 411: register char *rcp; 412: #endif 413: 414: if (p->c_cc && ++cp != p->c_cl) { 415: if (((int)cp & CROUND) == 0) 416: rcp = ((struct cblock *)cp)[-1].c_next->c_info; 417: else 418: rcp = cp; 419: #ifdef UCB_CLIST 420: *store = *rcp; 421: #endif 422: } 423: else 424: rcp = (char *)NULL; 425: #ifdef UCB_CLIST 426: restorseg5(sav5); 427: #endif 428: return (rcp); 429: } 430: 431: #ifdef UCB_CLIST 432: char 433: lookc(cp) 434: char *cp; 435: { 436: register char rc; 437: segm sav5; 438: 439: saveseg5(sav5); 440: mapseg5(clststrt, clstdesc); 441: rc = *cp; 442: restorseg5(sav5); 443: return(rc); 444: } 445: #endif 446: 447: /* 448: * Remove the last character in the list and return it. 449: */ 450: unputc(p) 451: register struct clist *p; 452: { 453: register struct cblock *bp; 454: register int c, s; 455: struct cblock *obp; 456: #ifdef UCB_CLIST 457: segm sav5; 458: #endif 459: 460: s = spltty(); 461: #ifdef UCB_CLIST 462: saveseg5(sav5); 463: mapseg5(clststrt, clstdesc); 464: #endif 465: if (p->c_cc <= 0) 466: c = -1; 467: else { 468: c = *--p->c_cl; 469: if (--p->c_cc <= 0) { 470: bp = (struct cblock *)p->c_cl; 471: bp = (struct cblock *)((int)bp & ~CROUND); 472: p->c_cl = p->c_cf = NULL; 473: bp->c_next = cfreelist; 474: cfreelist = bp; 475: cfreecount += CBSIZE; 476: } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 477: p->c_cl = (char *)((int)p->c_cl & ~CROUND); 478: bp = (struct cblock *)p->c_cf; 479: bp = (struct cblock *)((int)bp & ~CROUND); 480: while (bp->c_next != (struct cblock *)p->c_cl) 481: bp = bp->c_next; 482: obp = bp; 483: p->c_cl = (char *)(bp + 1); 484: bp = bp->c_next; 485: bp->c_next = cfreelist; 486: cfreelist = bp; 487: cfreecount += CBSIZE; 488: obp->c_next = NULL; 489: } 490: } 491: #ifdef UCB_CLIST 492: restorseg5(sav5); 493: #endif 494: splx(s); 495: return (c); 496: } 497: 498: /* 499: * Put the chars in the from que 500: * on the end of the to que. 501: */ 502: catq(from, to) 503: register struct clist *from, *to; 504: { 505: char bbuf[CBSIZE*4]; 506: register c; 507: int s; 508: 509: s = spltty(); 510: if (to->c_cc == 0) { 511: *to = *from; 512: from->c_cc = 0; 513: from->c_cf = NULL; 514: from->c_cl = NULL; 515: splx(s); 516: return; 517: } 518: splx(s); 519: while (from->c_cc > 0) { 520: c = q_to_b(from, bbuf, sizeof bbuf); 521: (void) b_to_q(bbuf, c, to); 522: } 523: } 524: 525: #ifdef unneeded 526: /* 527: * Integer (short) get/put using clists. 528: * Note dependency on byte order. 529: */ 530: typedef u_short word_t; 531: 532: getw(p) 533: register struct clist *p; 534: { 535: register int s, c; 536: register struct cblock *bp; 537: 538: if (p->c_cc <= 1) 539: return(-1); 540: if (p->c_cc & 01) { 541: c = getc(p); 542: #if defined(vax) 543: return (c | (getc(p)<<8)); 544: #else 545: return (getc(p) | (c<<8)); 546: #endif 547: } 548: s = spltty(); 549: #if defined(vax) 550: c = *((word_t *)p->c_cf); 551: #else 552: c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0]; 553: #endif 554: p->c_cf += sizeof (word_t); 555: p->c_cc -= sizeof (word_t); 556: if (p->c_cc <= 0) { 557: bp = (struct cblock *)(p->c_cf-1); 558: bp = (struct cblock *)((int)bp & ~CROUND); 559: p->c_cf = NULL; 560: p->c_cl = NULL; 561: bp->c_next = cfreelist; 562: cfreelist = bp; 563: cfreecount += CBSIZE; 564: if (cwaiting) { 565: wakeup(&cwaiting); 566: cwaiting = 0; 567: } 568: } else if (((int)p->c_cf & CROUND) == 0) { 569: bp = (struct cblock *)(p->c_cf); 570: bp--; 571: p->c_cf = bp->c_next->c_info; 572: bp->c_next = cfreelist; 573: cfreelist = bp; 574: cfreecount += CBSIZE; 575: if (cwaiting) { 576: wakeup(&cwaiting); 577: cwaiting = 0; 578: } 579: } 580: splx(s); 581: return (c); 582: } 583: 584: putw(c, p) 585: register struct clist *p; 586: word_t c; 587: { 588: register s; 589: register struct cblock *bp; 590: register char *cp; 591: 592: s = spltty(); 593: if (cfreelist==NULL) { 594: splx(s); 595: return(-1); 596: } 597: if (p->c_cc & 01) { 598: #if defined(vax) 599: (void) putc(c, p); 600: (void) putc(c>>8, p); 601: #else 602: (void) putc(c>>8, p); 603: (void) putc(c, p); 604: #endif 605: } else { 606: if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 607: if ((bp = cfreelist) == NULL) { 608: splx(s); 609: return (-1); 610: } 611: cfreelist = bp->c_next; 612: cfreecount -= CBSIZE; 613: bp->c_next = NULL; 614: p->c_cf = cp = bp->c_info; 615: } else if (((int)cp & CROUND) == 0) { 616: bp = (struct cblock *)cp - 1; 617: if ((bp->c_next = cfreelist) == NULL) { 618: splx(s); 619: return (-1); 620: } 621: bp = bp->c_next; 622: cfreelist = bp->c_next; 623: cfreecount -= CBSIZE; 624: bp->c_next = NULL; 625: cp = bp->c_info; 626: } 627: #if defined(vax) 628: *(word_t *)cp = c; 629: #else 630: ((u_char *)cp)[0] = c>>8; 631: ((u_char *)cp)[1] = c; 632: #endif 633: p->c_cl = cp + sizeof (word_t); 634: p->c_cc += sizeof (word_t); 635: } 636: splx(s); 637: return (0); 638: } 639: #endif unneeded