1*2745Swnj /* tty_subr.c 4.7 02/26/81 */ 21892Swnj 332Sbill #include "../h/param.h" 432Sbill #include "../h/systm.h" 532Sbill #include "../h/conf.h" 632Sbill #include "../h/buf.h" 71890Swnj #include "../h/tty.h" 8*2745Swnj #include "../h/clist.h" 932Sbill 101890Swnj char cwaiting; 111890Swnj 1232Sbill /* 1332Sbill * Character list get/put 1432Sbill */ 1532Sbill getc(p) 1632Sbill register struct clist *p; 1732Sbill { 1832Sbill register struct cblock *bp; 1932Sbill register int c, s; 2032Sbill 2132Sbill s = spl6(); 2232Sbill if (p->c_cc <= 0) { 2332Sbill c = -1; 2432Sbill p->c_cc = 0; 2532Sbill p->c_cf = p->c_cl = NULL; 2632Sbill } else { 2732Sbill c = *p->c_cf++ & 0377; 2832Sbill if (--p->c_cc<=0) { 2932Sbill bp = (struct cblock *)(p->c_cf-1); 3032Sbill bp = (struct cblock *) ((int)bp & ~CROUND); 3132Sbill p->c_cf = NULL; 3232Sbill p->c_cl = NULL; 3332Sbill bp->c_next = cfreelist; 3432Sbill cfreelist = bp; 351890Swnj cfreecount += CBSIZE; 361890Swnj if (cwaiting) { 371890Swnj wakeup(&cwaiting); 381890Swnj cwaiting = 0; 391890Swnj } 4032Sbill } else if (((int)p->c_cf & CROUND) == 0){ 4132Sbill bp = (struct cblock *)(p->c_cf); 4232Sbill bp--; 4332Sbill p->c_cf = bp->c_next->c_info; 4432Sbill bp->c_next = cfreelist; 4532Sbill cfreelist = bp; 461890Swnj cfreecount += CBSIZE; 471890Swnj if (cwaiting) { 481890Swnj wakeup(&cwaiting); 491890Swnj cwaiting = 0; 501890Swnj } 5132Sbill } 5232Sbill } 5332Sbill splx(s); 5432Sbill return(c); 5532Sbill } 5632Sbill 571890Swnj #if HAVTR > 0 581890Swnj trgetc(p) 591890Swnj register struct clist *p; 601890Swnj { 611890Swnj register struct cblock *bp; 621890Swnj register int c, s; 631890Swnj 641890Swnj if (p->c_cc <= 0) { 651890Swnj c = -1; 661890Swnj p->c_cc = 0; 671890Swnj p->c_cf = NULL; 681890Swnj } else { 691890Swnj c = *p->c_cf++ & 0377; 701890Swnj if (--p->c_cc<=0) { 711890Swnj p->c_cf = NULL; 721890Swnj } else if (((int)p->c_cf & CROUND) == 0) { 731890Swnj bp = (struct cblock *)(p->c_cf); 741890Swnj bp--; 751890Swnj p->c_cf = bp->c_next->c_info; 761890Swnj } 771890Swnj } 781890Swnj return(c); 791890Swnj } 801890Swnj #endif 811890Swnj 8232Sbill /* 8332Sbill * copy clist to buffer. 8432Sbill * return number of bytes moved. 8532Sbill */ 8632Sbill q_to_b(q, cp, cc) 8732Sbill register struct clist *q; 8832Sbill register char *cp; 8932Sbill { 9032Sbill register struct cblock *bp; 9132Sbill register int s; 9232Sbill char *acp; 9332Sbill 9432Sbill if (cc <= 0) 9532Sbill return(0); 9632Sbill s = spl6(); 9732Sbill if (q->c_cc <= 0) { 9832Sbill q->c_cc = 0; 9932Sbill q->c_cf = q->c_cl = NULL; 1001890Swnj splx(s); 10132Sbill return(0); 10232Sbill } 10332Sbill acp = cp; 10432Sbill cc++; 10532Sbill 10632Sbill while (--cc) { 10732Sbill *cp++ = *q->c_cf++; 10832Sbill if (--q->c_cc <= 0) { 10932Sbill bp = (struct cblock *)(q->c_cf-1); 11032Sbill bp = (struct cblock *)((int)bp & ~CROUND); 11132Sbill q->c_cf = q->c_cl = NULL; 11232Sbill bp->c_next = cfreelist; 11332Sbill cfreelist = bp; 1141890Swnj cfreecount += CBSIZE; 1151890Swnj if (cwaiting) { 1161890Swnj wakeup(&cwaiting); 1171890Swnj cwaiting = 0; 1181890Swnj } 11932Sbill break; 12032Sbill } 12132Sbill if (((int)q->c_cf & CROUND) == 0) { 12232Sbill bp = (struct cblock *)(q->c_cf); 12332Sbill bp--; 12432Sbill q->c_cf = bp->c_next->c_info; 12532Sbill bp->c_next = cfreelist; 12632Sbill cfreelist = bp; 1271890Swnj cfreecount += CBSIZE; 1281890Swnj if (cwaiting) { 1291890Swnj wakeup(&cwaiting); 1301890Swnj cwaiting = 0; 1311890Swnj } 13232Sbill } 13332Sbill } 13432Sbill splx(s); 13532Sbill return(cp-acp); 13632Sbill } 13732Sbill 1381890Swnj #if HAVTR > 0 13932Sbill /* 1401890Swnj * Traverse a clist copying its contents to a buffer. 1411890Swnj * q->cc and q->cf are updated with the current position 1421890Swnj * in the list, but bytes are not released to the freelist. 1431890Swnj */ 1441890Swnj trq_to_b(q, cp, cc) 1451890Swnj register struct clist *q; 1461890Swnj register char *cp; 1471890Swnj register cc; 1481890Swnj { 1491890Swnj register struct cblock *bp; 1501890Swnj char *acp; 1511890Swnj 1521890Swnj if (cc <= 0) 1531890Swnj return(0); 1541890Swnj if (q->c_cc <= 0) 1551890Swnj return(0); 1561890Swnj 1571890Swnj acp = cp; 1581890Swnj cc++; 1591890Swnj while (--cc) { 1601890Swnj *cp++ = *q->c_cf++; 1611890Swnj if (((int)q->c_cf & CROUND) == 0) { 1621890Swnj bp = (struct cblock *)(q->c_cf); 1631890Swnj bp--; 1641890Swnj q->c_cf = bp->c_next->c_info; 1651890Swnj } 1661890Swnj if (--q->c_cc <= 0) 1671890Swnj break; 1681890Swnj } 1691890Swnj return(cp-acp); 1701890Swnj } 1711890Swnj #endif 1721890Swnj 1731890Swnj 1741890Swnj /* 17532Sbill * Return count of contiguous characters 17632Sbill * in clist starting at q->c_cf. 17732Sbill * Stop counting if flag&character is non-null. 17832Sbill */ 17932Sbill ndqb(q, flag) 18032Sbill register struct clist *q; 18132Sbill { 18232Sbill register cc; 18332Sbill int s; 18432Sbill 18532Sbill s = spl6(); 18632Sbill if (q->c_cc <= 0) { 18732Sbill cc = -q->c_cc; 18832Sbill goto out; 18932Sbill } 19032Sbill cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 19132Sbill cc -= (int)q->c_cf; 19232Sbill if (q->c_cc < cc) 19332Sbill cc = q->c_cc; 19432Sbill if (flag) { 19532Sbill register char *p, *end; 19632Sbill 19732Sbill p = q->c_cf; 19832Sbill end = p; 19932Sbill end += cc; 20032Sbill while (p < end) { 20132Sbill if (*p & flag) { 2021890Swnj cc = (int)p; 2031890Swnj cc -= (int)q->c_cf; 20432Sbill break; 20532Sbill } 20632Sbill p++; 20732Sbill } 20832Sbill } 20932Sbill out: 21032Sbill splx(s); 21132Sbill return(cc); 21232Sbill } 21332Sbill 2141890Swnj 2151890Swnj 21632Sbill /* 2171890Swnj * Flush cc bytes from q. 21832Sbill */ 21932Sbill ndflush(q, cc) 22032Sbill register struct clist *q; 22132Sbill register cc; 22232Sbill { 2231890Swnj register struct cblock *bp; 2241890Swnj char *end; 2251890Swnj int rem; 22632Sbill register s; 22732Sbill 22832Sbill s = spl6(); 22932Sbill if (q->c_cc < 0) { 2301890Swnj printf("neg q flush\n"); 23132Sbill goto out; 23232Sbill } 23332Sbill if (q->c_cc == 0) { 23432Sbill goto out; 23532Sbill } 2361890Swnj while (cc>0 && q->c_cc) { 2371890Swnj bp = (struct cblock *)((int)q->c_cf & ~CROUND); 2381890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 2391890Swnj end = q->c_cl; 2401890Swnj } else { 2411890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 2421890Swnj } 2431890Swnj rem = end - q->c_cf; 2441890Swnj if (cc >= rem) { 2451890Swnj cc -= rem; 2461890Swnj q->c_cc -= rem; 24732Sbill q->c_cf = bp->c_next->c_info; 2481890Swnj bp->c_next = cfreelist; 2491890Swnj cfreelist = bp; 2501890Swnj cfreecount += CBSIZE; 2511890Swnj if (cwaiting) { 2521890Swnj wakeup(&cwaiting); 2531890Swnj cwaiting = 0; 2541890Swnj } 25532Sbill } else { 2561890Swnj q->c_cc -= cc; 2571890Swnj q->c_cf += cc; 2581890Swnj if (q->c_cc <= 0) { 2591890Swnj bp->c_next = cfreelist; 2601890Swnj cfreelist = bp; 2611890Swnj cfreecount += CBSIZE; 2621890Swnj if (cwaiting) { 2631890Swnj wakeup(&cwaiting); 2641890Swnj cwaiting = 0; 2651890Swnj } 2661890Swnj } 2671890Swnj break; 26832Sbill } 2691890Swnj } 2701890Swnj if (q->c_cc <= 0) { 27132Sbill q->c_cf = q->c_cl = NULL; 2721890Swnj q->c_cc = 0; 27332Sbill } 27432Sbill out: 27532Sbill splx(s); 27632Sbill } 277172Sbill 2781890Swnj 27932Sbill putc(c, p) 28032Sbill register struct clist *p; 28132Sbill { 28232Sbill register struct cblock *bp; 28332Sbill register char *cp; 28432Sbill register s; 28532Sbill 28632Sbill s = spl6(); 28732Sbill if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 28832Sbill if ((bp = cfreelist) == NULL) { 28932Sbill splx(s); 29032Sbill return(-1); 29132Sbill } 29232Sbill cfreelist = bp->c_next; 2931890Swnj cfreecount -= CBSIZE; 29432Sbill bp->c_next = NULL; 29532Sbill p->c_cf = cp = bp->c_info; 29632Sbill } else if (((int)cp & CROUND) == 0) { 29732Sbill bp = (struct cblock *)cp - 1; 29832Sbill if ((bp->c_next = cfreelist) == NULL) { 29932Sbill splx(s); 30032Sbill return(-1); 30132Sbill } 30232Sbill bp = bp->c_next; 30332Sbill cfreelist = bp->c_next; 3041890Swnj cfreecount -= CBSIZE; 30532Sbill bp->c_next = NULL; 30632Sbill cp = bp->c_info; 30732Sbill } 30832Sbill *cp++ = c; 30932Sbill p->c_cc++; 31032Sbill p->c_cl = cp; 31132Sbill splx(s); 31232Sbill return(0); 31332Sbill } 31432Sbill 3151890Swnj 3161890Swnj 31732Sbill /* 31832Sbill * copy buffer to clist. 31932Sbill * return number of bytes not transfered. 32032Sbill */ 32132Sbill b_to_q(cp, cc, q) 32232Sbill register char *cp; 32332Sbill struct clist *q; 32432Sbill register int cc; 32532Sbill { 32632Sbill register char *cq; 32732Sbill register struct cblock *bp; 32832Sbill register s, acc; 32932Sbill 33032Sbill if (cc <= 0) 33132Sbill return(0); 33232Sbill acc = cc; 3331890Swnj 3341890Swnj 33532Sbill s = spl6(); 33632Sbill if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 33732Sbill if ((bp = cfreelist) == NULL) 33832Sbill goto out; 33932Sbill cfreelist = bp->c_next; 3401890Swnj cfreecount -= CBSIZE; 34132Sbill bp->c_next = NULL; 34232Sbill q->c_cf = cq = bp->c_info; 34332Sbill } 34432Sbill 34532Sbill while (cc) { 34632Sbill if (((int)cq & CROUND) == 0) { 34732Sbill bp = (struct cblock *) cq - 1; 34832Sbill if ((bp->c_next = cfreelist) == NULL) 34932Sbill goto out; 35032Sbill bp = bp->c_next; 35132Sbill cfreelist = bp->c_next; 3521890Swnj cfreecount -= CBSIZE; 35332Sbill bp->c_next = NULL; 35432Sbill cq = bp->c_info; 35532Sbill } 35632Sbill *cq++ = *cp++; 35732Sbill cc--; 35832Sbill } 35932Sbill out: 36032Sbill q->c_cl = cq; 36132Sbill q->c_cc += acc-cc; 36232Sbill splx(s); 36332Sbill return(cc); 36432Sbill } 36532Sbill 3661890Swnj char * 3671890Swnj wb_to_q(cp, cc, q) 3681890Swnj register char *cp; 3691890Swnj register struct clist *q; 3701890Swnj register cc; 3711890Swnj { 3721890Swnj char *f; 3731890Swnj register s; 3741890Swnj 3751890Swnj s = spl6(); 3761890Swnj while (cc > cfreecount) { 3771890Swnj cwaiting = 1; 3781890Swnj sleep(&cwaiting, TTOPRI); 3791890Swnj } 3801890Swnj if (q->c_cc==0) { 3811890Swnj b_to_q(cp, cc, q); 3821890Swnj f = q->c_cf; 3831890Swnj } else { 3841890Swnj (void) putc(*cp++, q); 3851890Swnj f = q->c_cl; 3861890Swnj f--; 3871890Swnj b_to_q(cp, --cc, q); 3881890Swnj } 3891890Swnj splx(s); 3901890Swnj return(f); 3911890Swnj } 3921890Swnj 3932329Swnj #ifdef UCBIPC 3941890Swnj char * 3951890Swnj nb_to_q(cp, cc, q) 3961890Swnj register char *cp; 3971890Swnj register struct clist *q; 3981890Swnj register cc; 3991890Swnj { 4001890Swnj char *f; 4011890Swnj register s; 4021890Swnj 4031890Swnj s = spl6(); 4041890Swnj if (cc > cfreecount) { 4051890Swnj f = NULL; 4061890Swnj goto out; 4071890Swnj } 4081890Swnj if (q->c_cc==0) { 4091890Swnj b_to_q(cp, cc, q); 4101890Swnj f = q->c_cf; 4111890Swnj } else { 4121890Swnj (void) putc(*cp++, q); 4131890Swnj f = q->c_cl; 4141890Swnj f--; 4151890Swnj b_to_q(cp, --cc, q); 4161890Swnj } 4171890Swnj out: 4181890Swnj splx(s); 4191890Swnj return(f); 4201890Swnj } 4211890Swnj #endif 4221890Swnj 42332Sbill /* 424172Sbill * Given a non-NULL pointter into the list (like c_cf which 425172Sbill * always points to a real character if non-NULL) return the pointer 426172Sbill * to the next character in the list or return NULL if no more chars. 427172Sbill * 428172Sbill * Callers must not allow getc's to happen between nextc's so that the 429172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 430172Sbill */ 431172Sbill char * 432172Sbill nextc(p, cp) 433172Sbill register struct clist *p; 434172Sbill register char *cp; 435172Sbill { 436172Sbill 437172Sbill if (p->c_cc && ++cp != p->c_cl) { 438172Sbill if (((int)cp & CROUND) == 0) 439172Sbill return (((struct cblock *)cp)[-1].c_next->c_info); 440172Sbill return (cp); 441172Sbill } 442172Sbill return (0); 443172Sbill } 444172Sbill 445172Sbill /* 446172Sbill * Remove the last character in the list and return it. 447172Sbill */ 448172Sbill unputc(p) 449172Sbill register struct clist *p; 450172Sbill { 451172Sbill register struct cblock *bp; 452172Sbill register int c, s; 453172Sbill struct cblock *obp; 454172Sbill 455172Sbill s = spl6(); 456172Sbill if (p->c_cc <= 0) 457172Sbill c = -1; 458172Sbill else { 459172Sbill c = *--p->c_cl; 460172Sbill if (--p->c_cc <= 0) { 461172Sbill bp = (struct cblock *)p->c_cl; 462172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 463172Sbill p->c_cl = p->c_cf = NULL; 464172Sbill bp->c_next = cfreelist; 465172Sbill cfreelist = bp; 4661890Swnj cfreecount += CBSIZE; 467172Sbill } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 468172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 469172Sbill bp = (struct cblock *)p->c_cf; 470172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 471172Sbill while (bp->c_next != (struct cblock *)p->c_cl) 472172Sbill bp = bp->c_next; 473172Sbill obp = bp; 474172Sbill p->c_cl = (char *)(bp + 1); 475172Sbill bp = bp->c_next; 476172Sbill bp->c_next = cfreelist; 477172Sbill cfreelist = bp; 4781890Swnj cfreecount += CBSIZE; 479172Sbill obp->c_next = NULL; 480172Sbill } 481172Sbill } 482172Sbill splx(s); 483172Sbill return (c); 484172Sbill } 485172Sbill 486172Sbill /* 487172Sbill * Put the chars in the from que 488172Sbill * on the end of the to que. 489172Sbill * 490172Sbill * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. 491172Sbill */ 492172Sbill catq(from, to) 493172Sbill struct clist *from, *to; 494172Sbill { 495172Sbill register c; 496172Sbill 497172Sbill while ((c = getc(from)) >= 0) 498172Sbill (void) putc(c, to); 499172Sbill } 500172Sbill 501172Sbill /* 50232Sbill * integer (2-byte) get/put 50332Sbill * using clists 50432Sbill */ 50532Sbill getw(p) 50632Sbill register struct clist *p; 50732Sbill { 50832Sbill register int s; 50932Sbill 51032Sbill if (p->c_cc <= 1) 51132Sbill return(-1); 51232Sbill s = getc(p); 51332Sbill return(s | (getc(p)<<8)); 51432Sbill } 51532Sbill 5161890Swnj #if HAVTR > 0 5171890Swnj trgetw(p) 5181890Swnj register struct clist *p; 5191890Swnj { 5201890Swnj register int w; 5211890Swnj 5221890Swnj if (p->c_cc <=1) 5231890Swnj return(-1); 5241890Swnj w = trgetc(p); 5251890Swnj return(w | (trgetc(p)<<8)); 5261890Swnj } 5271890Swnj #endif 5281890Swnj 52932Sbill putw(c, p) 53032Sbill register struct clist *p; 53132Sbill { 53232Sbill register s; 53332Sbill 53432Sbill s = spl6(); 53532Sbill if (cfreelist==NULL) { 53632Sbill splx(s); 53732Sbill return(-1); 53832Sbill } 539130Sbill (void) putc(c, p); 540130Sbill (void) putc(c>>8, p); 54132Sbill splx(s); 54232Sbill return(0); 54332Sbill } 544