1*10749Seric /* tty_subr.c 4.19 83/02/06 */ 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" 82745Swnj #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 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) 15932Sbill register struct clist *q; 16032Sbill register cc; 16132Sbill { 1621890Swnj register struct cblock *bp; 1631890Swnj char *end; 1641890Swnj int rem; 16532Sbill register s; 16632Sbill 1673545Swnj s = spl5(); 168*10749Seric if (q->c_cc <= 0) { 16932Sbill goto out; 17032Sbill } 1711890Swnj while (cc>0 && q->c_cc) { 1721890Swnj bp = (struct cblock *)((int)q->c_cf & ~CROUND); 1731890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 1741890Swnj end = q->c_cl; 1751890Swnj } else { 1761890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 1771890Swnj } 1781890Swnj rem = end - q->c_cf; 1791890Swnj if (cc >= rem) { 1801890Swnj cc -= rem; 1811890Swnj q->c_cc -= rem; 18232Sbill q->c_cf = bp->c_next->c_info; 1831890Swnj bp->c_next = cfreelist; 1841890Swnj cfreelist = bp; 1851890Swnj cfreecount += CBSIZE; 1861890Swnj if (cwaiting) { 1871890Swnj wakeup(&cwaiting); 1881890Swnj cwaiting = 0; 1891890Swnj } 19032Sbill } else { 1911890Swnj q->c_cc -= cc; 1921890Swnj q->c_cf += cc; 1931890Swnj if (q->c_cc <= 0) { 1941890Swnj bp->c_next = cfreelist; 1951890Swnj cfreelist = bp; 1961890Swnj cfreecount += CBSIZE; 1971890Swnj if (cwaiting) { 1981890Swnj wakeup(&cwaiting); 1991890Swnj cwaiting = 0; 2001890Swnj } 2011890Swnj } 2021890Swnj break; 20332Sbill } 2041890Swnj } 2051890Swnj if (q->c_cc <= 0) { 20632Sbill q->c_cf = q->c_cl = NULL; 2071890Swnj q->c_cc = 0; 20832Sbill } 20932Sbill out: 21032Sbill splx(s); 21132Sbill } 212172Sbill 2131890Swnj 21432Sbill putc(c, p) 21532Sbill register struct clist *p; 21632Sbill { 21732Sbill register struct cblock *bp; 21832Sbill register char *cp; 21932Sbill register s; 22032Sbill 2213545Swnj s = spl5(); 22232Sbill if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 22332Sbill if ((bp = cfreelist) == NULL) { 22432Sbill splx(s); 22532Sbill return(-1); 22632Sbill } 22732Sbill cfreelist = bp->c_next; 2281890Swnj cfreecount -= CBSIZE; 22932Sbill bp->c_next = NULL; 23032Sbill p->c_cf = cp = bp->c_info; 23132Sbill } else if (((int)cp & CROUND) == 0) { 23232Sbill bp = (struct cblock *)cp - 1; 23332Sbill if ((bp->c_next = cfreelist) == NULL) { 23432Sbill splx(s); 23532Sbill return(-1); 23632Sbill } 23732Sbill bp = bp->c_next; 23832Sbill cfreelist = bp->c_next; 2391890Swnj cfreecount -= CBSIZE; 24032Sbill bp->c_next = NULL; 24132Sbill cp = bp->c_info; 24232Sbill } 24332Sbill *cp++ = c; 24432Sbill p->c_cc++; 24532Sbill p->c_cl = cp; 24632Sbill splx(s); 24732Sbill return(0); 24832Sbill } 24932Sbill 2501890Swnj 2511890Swnj 25232Sbill /* 25332Sbill * copy buffer to clist. 25432Sbill * return number of bytes not transfered. 25532Sbill */ 25632Sbill b_to_q(cp, cc, q) 25732Sbill register char *cp; 25832Sbill struct clist *q; 25932Sbill register int cc; 26032Sbill { 26132Sbill register char *cq; 26232Sbill register struct cblock *bp; 26332Sbill register s, acc; 26432Sbill 26532Sbill if (cc <= 0) 26632Sbill return(0); 26732Sbill acc = cc; 2681890Swnj 2691890Swnj 2703545Swnj s = spl5(); 27132Sbill if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 27232Sbill if ((bp = cfreelist) == NULL) 27332Sbill goto out; 27432Sbill cfreelist = bp->c_next; 2751890Swnj cfreecount -= CBSIZE; 27632Sbill bp->c_next = NULL; 27732Sbill q->c_cf = cq = bp->c_info; 27832Sbill } 27932Sbill 28032Sbill while (cc) { 28132Sbill if (((int)cq & CROUND) == 0) { 28232Sbill bp = (struct cblock *) cq - 1; 28332Sbill if ((bp->c_next = cfreelist) == NULL) 28432Sbill goto out; 28532Sbill bp = bp->c_next; 28632Sbill cfreelist = bp->c_next; 2871890Swnj cfreecount -= CBSIZE; 28832Sbill bp->c_next = NULL; 28932Sbill cq = bp->c_info; 29032Sbill } 29132Sbill *cq++ = *cp++; 29232Sbill cc--; 29332Sbill } 29432Sbill out: 29532Sbill q->c_cl = cq; 29632Sbill q->c_cc += acc-cc; 29732Sbill splx(s); 29832Sbill return(cc); 29932Sbill } 30032Sbill 30132Sbill /* 302172Sbill * Given a non-NULL pointter into the list (like c_cf which 303172Sbill * always points to a real character if non-NULL) return the pointer 304172Sbill * to the next character in the list or return NULL if no more chars. 305172Sbill * 306172Sbill * Callers must not allow getc's to happen between nextc's so that the 307172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 308172Sbill */ 309172Sbill char * 310172Sbill nextc(p, cp) 311172Sbill register struct clist *p; 312172Sbill register char *cp; 313172Sbill { 314172Sbill 315172Sbill if (p->c_cc && ++cp != p->c_cl) { 316172Sbill if (((int)cp & CROUND) == 0) 317172Sbill return (((struct cblock *)cp)[-1].c_next->c_info); 318172Sbill return (cp); 319172Sbill } 320172Sbill return (0); 321172Sbill } 322172Sbill 323172Sbill /* 324172Sbill * Remove the last character in the list and return it. 325172Sbill */ 326172Sbill unputc(p) 327172Sbill register struct clist *p; 328172Sbill { 329172Sbill register struct cblock *bp; 330172Sbill register int c, s; 331172Sbill struct cblock *obp; 332172Sbill 3333545Swnj s = spl5(); 334172Sbill if (p->c_cc <= 0) 335172Sbill c = -1; 336172Sbill else { 337172Sbill c = *--p->c_cl; 338172Sbill if (--p->c_cc <= 0) { 339172Sbill bp = (struct cblock *)p->c_cl; 340172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 341172Sbill p->c_cl = p->c_cf = NULL; 342172Sbill bp->c_next = cfreelist; 343172Sbill cfreelist = bp; 3441890Swnj cfreecount += CBSIZE; 345172Sbill } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 346172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 347172Sbill bp = (struct cblock *)p->c_cf; 348172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 349172Sbill while (bp->c_next != (struct cblock *)p->c_cl) 350172Sbill bp = bp->c_next; 351172Sbill obp = bp; 352172Sbill p->c_cl = (char *)(bp + 1); 353172Sbill bp = bp->c_next; 354172Sbill bp->c_next = cfreelist; 355172Sbill cfreelist = bp; 3561890Swnj cfreecount += CBSIZE; 357172Sbill obp->c_next = NULL; 358172Sbill } 359172Sbill } 360172Sbill splx(s); 361172Sbill return (c); 362172Sbill } 363172Sbill 364172Sbill /* 365172Sbill * Put the chars in the from que 366172Sbill * on the end of the to que. 367172Sbill * 368172Sbill * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. 369172Sbill */ 370172Sbill catq(from, to) 371172Sbill struct clist *from, *to; 372172Sbill { 373172Sbill register c; 374172Sbill 375172Sbill while ((c = getc(from)) >= 0) 376172Sbill (void) putc(c, to); 377172Sbill } 378172Sbill 379172Sbill /* 3809761Ssam * Integer (short) get/put 38132Sbill * using clists 38232Sbill */ 3839761Ssam typedef short word_t; 3849761Ssam union chword { 3859761Ssam word_t word; 3869761Ssam struct { 3879761Ssam char Ch[sizeof (word_t)]; 3889761Ssam } Cha; 3899761Ssam #define ch Cha.Ch 3909761Ssam }; 3919761Ssam 39232Sbill getw(p) 3938955Sroot register struct clist *p; 39432Sbill { 3959761Ssam register int i; 3969761Ssam union chword x; 39732Sbill 3989761Ssam if (p->c_cc < sizeof (word_t)) 3999761Ssam return (-1); 4009761Ssam for (i = 0; i < sizeof (word_t); i++) 4019761Ssam x.ch[i] = getc(p); 4029761Ssam return (x.word); 40332Sbill } 40432Sbill 40532Sbill putw(c, p) 4068955Sroot register struct clist *p; 40732Sbill { 40832Sbill register s; 4099761Ssam register int i; 4109761Ssam union chword x; 41132Sbill 4123545Swnj s = spl5(); 41332Sbill if (cfreelist==NULL) { 41432Sbill splx(s); 41532Sbill return(-1); 41632Sbill } 4179761Ssam x.word = c; 4189761Ssam for (i = 0; i < sizeof (word_t); i++) 4199761Ssam (void) putc(x.ch[i], p); 42032Sbill splx(s); 4219761Ssam return (0); 42232Sbill } 423