1*17368Ssam /* tty_subr.c 6.6 84/11/15 */ 21892Swnj 317097Sbloom #include "param.h" 417097Sbloom #include "systm.h" 517097Sbloom #include "conf.h" 617097Sbloom #include "buf.h" 717097Sbloom #include "tty.h" 817097Sbloom #include "clist.h" 932Sbill 101890Swnj char cwaiting; 111890Swnj 1232Sbill /* 1332Sbill * Character list get/put 1432Sbill */ 1532Sbill getc(p) 1612754Ssam register struct clist *p; 1732Sbill { 1832Sbill register struct cblock *bp; 1932Sbill register int c, s; 2032Sbill 213545Swnj s = spl5(); 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 5732Sbill /* 5832Sbill * copy clist to buffer. 5932Sbill * return number of bytes moved. 6032Sbill */ 6132Sbill q_to_b(q, cp, cc) 629761Ssam register struct clist *q; 639761Ssam register char *cp; 6432Sbill { 6532Sbill register struct cblock *bp; 6632Sbill register int s; 6732Sbill char *acp; 6832Sbill 6932Sbill if (cc <= 0) 7032Sbill return(0); 713545Swnj s = spl5(); 7232Sbill if (q->c_cc <= 0) { 7332Sbill q->c_cc = 0; 7432Sbill q->c_cf = q->c_cl = NULL; 751890Swnj splx(s); 7632Sbill return(0); 7732Sbill } 7832Sbill acp = cp; 7932Sbill cc++; 8032Sbill 8132Sbill while (--cc) { 8232Sbill *cp++ = *q->c_cf++; 8332Sbill if (--q->c_cc <= 0) { 8432Sbill bp = (struct cblock *)(q->c_cf-1); 8532Sbill bp = (struct cblock *)((int)bp & ~CROUND); 8632Sbill q->c_cf = q->c_cl = NULL; 8732Sbill bp->c_next = cfreelist; 8832Sbill cfreelist = bp; 891890Swnj cfreecount += CBSIZE; 901890Swnj if (cwaiting) { 911890Swnj wakeup(&cwaiting); 921890Swnj cwaiting = 0; 931890Swnj } 9432Sbill break; 9532Sbill } 9632Sbill if (((int)q->c_cf & CROUND) == 0) { 9732Sbill bp = (struct cblock *)(q->c_cf); 9832Sbill bp--; 9932Sbill q->c_cf = bp->c_next->c_info; 10032Sbill bp->c_next = cfreelist; 10132Sbill cfreelist = bp; 1021890Swnj cfreecount += CBSIZE; 1031890Swnj if (cwaiting) { 1041890Swnj wakeup(&cwaiting); 1051890Swnj cwaiting = 0; 1061890Swnj } 10732Sbill } 10832Sbill } 10932Sbill splx(s); 11032Sbill return(cp-acp); 11132Sbill } 11232Sbill 11332Sbill /* 11432Sbill * Return count of contiguous characters 11532Sbill * in clist starting at q->c_cf. 11632Sbill * Stop counting if flag&character is non-null. 11732Sbill */ 11832Sbill ndqb(q, flag) 1199761Ssam register struct clist *q; 12032Sbill { 1219761Ssam register cc; 1229761Ssam int s; 12332Sbill 1243545Swnj s = spl5(); 12532Sbill if (q->c_cc <= 0) { 12632Sbill cc = -q->c_cc; 12732Sbill goto out; 12832Sbill } 12932Sbill cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 13032Sbill cc -= (int)q->c_cf; 13132Sbill if (q->c_cc < cc) 13232Sbill cc = q->c_cc; 13332Sbill if (flag) { 13432Sbill register char *p, *end; 13532Sbill 13632Sbill p = q->c_cf; 13732Sbill end = p; 13832Sbill end += cc; 13932Sbill while (p < end) { 14032Sbill if (*p & flag) { 1411890Swnj cc = (int)p; 1421890Swnj cc -= (int)q->c_cf; 14332Sbill break; 14432Sbill } 14532Sbill p++; 14632Sbill } 14732Sbill } 14832Sbill out: 14932Sbill splx(s); 15032Sbill return(cc); 15132Sbill } 15232Sbill 1531890Swnj 1541890Swnj 15532Sbill /* 1561890Swnj * Flush cc bytes from q. 15732Sbill */ 15832Sbill ndflush(q, cc) 15912754Ssam register struct clist *q; 16012754Ssam register cc; 16132Sbill { 16212754Ssam register struct cblock *bp; 16312754Ssam char *end; 16412754Ssam int rem, s; 16532Sbill 1663545Swnj s = spl5(); 16710749Seric if (q->c_cc <= 0) { 16832Sbill goto out; 16932Sbill } 1701890Swnj while (cc>0 && q->c_cc) { 1711890Swnj bp = (struct cblock *)((int)q->c_cf & ~CROUND); 1721890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 1731890Swnj end = q->c_cl; 1741890Swnj } else { 1751890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 1761890Swnj } 1771890Swnj rem = end - q->c_cf; 1781890Swnj if (cc >= rem) { 1791890Swnj cc -= rem; 1801890Swnj q->c_cc -= rem; 18132Sbill q->c_cf = bp->c_next->c_info; 1821890Swnj bp->c_next = cfreelist; 1831890Swnj cfreelist = bp; 1841890Swnj cfreecount += CBSIZE; 1851890Swnj if (cwaiting) { 1861890Swnj wakeup(&cwaiting); 1871890Swnj cwaiting = 0; 1881890Swnj } 18932Sbill } else { 1901890Swnj q->c_cc -= cc; 1911890Swnj q->c_cf += cc; 1921890Swnj if (q->c_cc <= 0) { 1931890Swnj bp->c_next = cfreelist; 1941890Swnj cfreelist = bp; 1951890Swnj cfreecount += CBSIZE; 1961890Swnj if (cwaiting) { 1971890Swnj wakeup(&cwaiting); 1981890Swnj cwaiting = 0; 1991890Swnj } 2001890Swnj } 2011890Swnj break; 20232Sbill } 2031890Swnj } 2041890Swnj if (q->c_cc <= 0) { 20532Sbill q->c_cf = q->c_cl = NULL; 2061890Swnj q->c_cc = 0; 20732Sbill } 20832Sbill out: 20932Sbill splx(s); 21032Sbill } 211172Sbill 2121890Swnj 21332Sbill putc(c, p) 21412754Ssam register struct clist *p; 21532Sbill { 21632Sbill register struct cblock *bp; 21732Sbill register char *cp; 21832Sbill register s; 21932Sbill 2203545Swnj s = spl5(); 22132Sbill if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 22232Sbill if ((bp = cfreelist) == NULL) { 22332Sbill splx(s); 22432Sbill return(-1); 22532Sbill } 22632Sbill cfreelist = bp->c_next; 2271890Swnj cfreecount -= CBSIZE; 22832Sbill bp->c_next = NULL; 22932Sbill p->c_cf = cp = bp->c_info; 23032Sbill } else if (((int)cp & CROUND) == 0) { 23132Sbill bp = (struct cblock *)cp - 1; 23232Sbill if ((bp->c_next = cfreelist) == NULL) { 23332Sbill splx(s); 23432Sbill return(-1); 23532Sbill } 23632Sbill bp = bp->c_next; 23732Sbill cfreelist = bp->c_next; 2381890Swnj cfreecount -= CBSIZE; 23932Sbill bp->c_next = NULL; 24032Sbill cp = bp->c_info; 24132Sbill } 24232Sbill *cp++ = c; 24332Sbill p->c_cc++; 24432Sbill p->c_cl = cp; 24532Sbill splx(s); 24632Sbill return(0); 24732Sbill } 24832Sbill 2491890Swnj 2501890Swnj 25132Sbill /* 25232Sbill * copy buffer to clist. 25332Sbill * return number of bytes not transfered. 25432Sbill */ 25532Sbill b_to_q(cp, cc, q) 25612754Ssam register char *cp; 25712754Ssam struct clist *q; 25812754Ssam register int cc; 25932Sbill { 26032Sbill register char *cq; 26132Sbill register struct cblock *bp; 26232Sbill register s, acc; 26332Sbill 26432Sbill if (cc <= 0) 265*17368Ssam return (0); 26617366Stef while (cc > 0) { 26717366Stef s = spl6(); 26817366Stef if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 26917366Stef if ((bp = cfreelist) == NULL) { 27017366Stef splx(s); 27117366Stef break; 27217366Stef } 27317366Stef q->c_cf = cq = bp->c_info; 27417366Stef goto middle; 27517366Stef } 27632Sbill if (((int)cq & CROUND) == 0) { 277*17368Ssam bp = &((struct cblock *)cq)[-1]; 27817366Stef if ((bp->c_next = cfreelist) == NULL) { 27917366Stef splx(s); 28017366Stef break; 28117366Stef } 28232Sbill bp = bp->c_next; 28317366Stef cq = bp->c_info; 284*17368Ssam middle: 28532Sbill cfreelist = bp->c_next; 2861890Swnj cfreecount -= CBSIZE; 28732Sbill bp->c_next = NULL; 288*17368Ssam acc = MIN(cc, CBSIZE); 289*17368Ssam } else { 290*17368Ssam acc = (char *)((int)&cq[CBSIZE] &~ CROUND) - cq; 291*17368Ssam if (acc > cc) 292*17368Ssam acc = cc; 29332Sbill } 294*17368Ssam bcopy((caddr_t)cp, cq, acc); 29517366Stef q->c_cl = &cq[acc]; 29617366Stef q->c_cc += acc; 29717366Stef splx(s); 29817366Stef cp += acc; 29917366Stef cc -= acc; 30032Sbill } 301*17368Ssam return (cc); 30232Sbill } 30332Sbill 30432Sbill /* 305172Sbill * Given a non-NULL pointter into the list (like c_cf which 306172Sbill * always points to a real character if non-NULL) return the pointer 307172Sbill * to the next character in the list or return NULL if no more chars. 308172Sbill * 309172Sbill * Callers must not allow getc's to happen between nextc's so that the 310172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 311172Sbill */ 312172Sbill char * 313172Sbill nextc(p, cp) 31412754Ssam register struct clist *p; 31512754Ssam register char *cp; 316172Sbill { 317172Sbill 318172Sbill if (p->c_cc && ++cp != p->c_cl) { 319172Sbill if (((int)cp & CROUND) == 0) 320172Sbill return (((struct cblock *)cp)[-1].c_next->c_info); 321172Sbill return (cp); 322172Sbill } 323172Sbill return (0); 324172Sbill } 325172Sbill 326172Sbill /* 327172Sbill * Remove the last character in the list and return it. 328172Sbill */ 329172Sbill unputc(p) 33012754Ssam register struct clist *p; 331172Sbill { 332172Sbill register struct cblock *bp; 333172Sbill register int c, s; 334172Sbill struct cblock *obp; 335172Sbill 3363545Swnj s = spl5(); 337172Sbill if (p->c_cc <= 0) 338172Sbill c = -1; 339172Sbill else { 340172Sbill c = *--p->c_cl; 341172Sbill if (--p->c_cc <= 0) { 342172Sbill bp = (struct cblock *)p->c_cl; 343172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 344172Sbill p->c_cl = p->c_cf = NULL; 345172Sbill bp->c_next = cfreelist; 346172Sbill cfreelist = bp; 3471890Swnj cfreecount += CBSIZE; 348172Sbill } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 349172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 350172Sbill bp = (struct cblock *)p->c_cf; 351172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 352172Sbill while (bp->c_next != (struct cblock *)p->c_cl) 353172Sbill bp = bp->c_next; 354172Sbill obp = bp; 355172Sbill p->c_cl = (char *)(bp + 1); 356172Sbill bp = bp->c_next; 357172Sbill bp->c_next = cfreelist; 358172Sbill cfreelist = bp; 3591890Swnj cfreecount += CBSIZE; 360172Sbill obp->c_next = NULL; 361172Sbill } 362172Sbill } 363172Sbill splx(s); 364172Sbill return (c); 365172Sbill } 366172Sbill 367172Sbill /* 368172Sbill * Put the chars in the from que 369172Sbill * on the end of the to que. 370172Sbill * 371172Sbill * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. 372172Sbill */ 373172Sbill catq(from, to) 37412754Ssam struct clist *from, *to; 375172Sbill { 376172Sbill register c; 377172Sbill 378172Sbill while ((c = getc(from)) >= 0) 379172Sbill (void) putc(c, to); 380172Sbill } 381172Sbill 382172Sbill /* 3839761Ssam * Integer (short) get/put 38432Sbill * using clists 38532Sbill */ 3869761Ssam typedef short word_t; 3879761Ssam union chword { 3889761Ssam word_t word; 3899761Ssam struct { 3909761Ssam char Ch[sizeof (word_t)]; 3919761Ssam } Cha; 3929761Ssam #define ch Cha.Ch 3939761Ssam }; 3949761Ssam 39532Sbill getw(p) 3968955Sroot register struct clist *p; 39732Sbill { 3989761Ssam register int i; 3999761Ssam union chword x; 40032Sbill 4019761Ssam if (p->c_cc < sizeof (word_t)) 4029761Ssam return (-1); 4039761Ssam for (i = 0; i < sizeof (word_t); i++) 4049761Ssam x.ch[i] = getc(p); 4059761Ssam return (x.word); 40632Sbill } 40732Sbill 40832Sbill putw(c, p) 4098955Sroot register struct clist *p; 41032Sbill { 41132Sbill register s; 4129761Ssam register int i; 4139761Ssam union chword x; 41432Sbill 4153545Swnj s = spl5(); 41632Sbill if (cfreelist==NULL) { 41732Sbill splx(s); 41832Sbill return(-1); 41932Sbill } 4209761Ssam x.word = c; 4219761Ssam for (i = 0; i < sizeof (word_t); i++) 4229761Ssam (void) putc(x.ch[i], p); 42332Sbill splx(s); 4249761Ssam return (0); 42532Sbill } 426