1*17097Sbloom /* tty_subr.c 6.3 84/08/29 */ 21892Swnj 3*17097Sbloom #include "param.h" 4*17097Sbloom #include "systm.h" 5*17097Sbloom #include "conf.h" 6*17097Sbloom #include "buf.h" 7*17097Sbloom #include "tty.h" 8*17097Sbloom #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) 26532Sbill return(0); 26632Sbill acc = cc; 2671890Swnj 2681890Swnj 2693545Swnj s = spl5(); 27032Sbill if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 27132Sbill if ((bp = cfreelist) == NULL) 27232Sbill goto out; 27332Sbill cfreelist = bp->c_next; 2741890Swnj cfreecount -= CBSIZE; 27532Sbill bp->c_next = NULL; 27632Sbill q->c_cf = cq = bp->c_info; 27732Sbill } 27832Sbill 27932Sbill while (cc) { 28032Sbill if (((int)cq & CROUND) == 0) { 28132Sbill bp = (struct cblock *) cq - 1; 28232Sbill if ((bp->c_next = cfreelist) == NULL) 28332Sbill goto out; 28432Sbill bp = bp->c_next; 28532Sbill cfreelist = bp->c_next; 2861890Swnj cfreecount -= CBSIZE; 28732Sbill bp->c_next = NULL; 28832Sbill cq = bp->c_info; 28932Sbill } 29032Sbill *cq++ = *cp++; 29132Sbill cc--; 29232Sbill } 29332Sbill out: 29432Sbill q->c_cl = cq; 29532Sbill q->c_cc += acc-cc; 29632Sbill splx(s); 29732Sbill return(cc); 29832Sbill } 29932Sbill 30032Sbill /* 301172Sbill * Given a non-NULL pointter into the list (like c_cf which 302172Sbill * always points to a real character if non-NULL) return the pointer 303172Sbill * to the next character in the list or return NULL if no more chars. 304172Sbill * 305172Sbill * Callers must not allow getc's to happen between nextc's so that the 306172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 307172Sbill */ 308172Sbill char * 309172Sbill nextc(p, cp) 31012754Ssam register struct clist *p; 31112754Ssam register char *cp; 312172Sbill { 313172Sbill 314172Sbill if (p->c_cc && ++cp != p->c_cl) { 315172Sbill if (((int)cp & CROUND) == 0) 316172Sbill return (((struct cblock *)cp)[-1].c_next->c_info); 317172Sbill return (cp); 318172Sbill } 319172Sbill return (0); 320172Sbill } 321172Sbill 322172Sbill /* 323172Sbill * Remove the last character in the list and return it. 324172Sbill */ 325172Sbill unputc(p) 32612754Ssam register struct clist *p; 327172Sbill { 328172Sbill register struct cblock *bp; 329172Sbill register int c, s; 330172Sbill struct cblock *obp; 331172Sbill 3323545Swnj s = spl5(); 333172Sbill if (p->c_cc <= 0) 334172Sbill c = -1; 335172Sbill else { 336172Sbill c = *--p->c_cl; 337172Sbill if (--p->c_cc <= 0) { 338172Sbill bp = (struct cblock *)p->c_cl; 339172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 340172Sbill p->c_cl = p->c_cf = NULL; 341172Sbill bp->c_next = cfreelist; 342172Sbill cfreelist = bp; 3431890Swnj cfreecount += CBSIZE; 344172Sbill } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 345172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 346172Sbill bp = (struct cblock *)p->c_cf; 347172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 348172Sbill while (bp->c_next != (struct cblock *)p->c_cl) 349172Sbill bp = bp->c_next; 350172Sbill obp = bp; 351172Sbill p->c_cl = (char *)(bp + 1); 352172Sbill bp = bp->c_next; 353172Sbill bp->c_next = cfreelist; 354172Sbill cfreelist = bp; 3551890Swnj cfreecount += CBSIZE; 356172Sbill obp->c_next = NULL; 357172Sbill } 358172Sbill } 359172Sbill splx(s); 360172Sbill return (c); 361172Sbill } 362172Sbill 363172Sbill /* 364172Sbill * Put the chars in the from que 365172Sbill * on the end of the to que. 366172Sbill * 367172Sbill * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. 368172Sbill */ 369172Sbill catq(from, to) 37012754Ssam struct clist *from, *to; 371172Sbill { 372172Sbill register c; 373172Sbill 374172Sbill while ((c = getc(from)) >= 0) 375172Sbill (void) putc(c, to); 376172Sbill } 377172Sbill 378172Sbill /* 3799761Ssam * Integer (short) get/put 38032Sbill * using clists 38132Sbill */ 3829761Ssam typedef short word_t; 3839761Ssam union chword { 3849761Ssam word_t word; 3859761Ssam struct { 3869761Ssam char Ch[sizeof (word_t)]; 3879761Ssam } Cha; 3889761Ssam #define ch Cha.Ch 3899761Ssam }; 3909761Ssam 39132Sbill getw(p) 3928955Sroot register struct clist *p; 39332Sbill { 3949761Ssam register int i; 3959761Ssam union chword x; 39632Sbill 3979761Ssam if (p->c_cc < sizeof (word_t)) 3989761Ssam return (-1); 3999761Ssam for (i = 0; i < sizeof (word_t); i++) 4009761Ssam x.ch[i] = getc(p); 4019761Ssam return (x.word); 40232Sbill } 40332Sbill 40432Sbill putw(c, p) 4058955Sroot register struct clist *p; 40632Sbill { 40732Sbill register s; 4089761Ssam register int i; 4099761Ssam union chword x; 41032Sbill 4113545Swnj s = spl5(); 41232Sbill if (cfreelist==NULL) { 41332Sbill splx(s); 41432Sbill return(-1); 41532Sbill } 4169761Ssam x.word = c; 4179761Ssam for (i = 0; i < sizeof (word_t); i++) 4189761Ssam (void) putc(x.ch[i], p); 41932Sbill splx(s); 4209761Ssam return (0); 42132Sbill } 422