1*12754Ssam /* tty_subr.c 4.20 83/05/27 */ 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) 16*12754Ssam 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 57*12754Ssam #ifdef notdef 5832Sbill /* 5932Sbill * copy clist to buffer. 6032Sbill * return number of bytes moved. 6132Sbill */ 6232Sbill q_to_b(q, cp, cc) 639761Ssam register struct clist *q; 649761Ssam register char *cp; 6532Sbill { 6632Sbill register struct cblock *bp; 6732Sbill register int s; 6832Sbill char *acp; 6932Sbill 7032Sbill if (cc <= 0) 7132Sbill return(0); 723545Swnj s = spl5(); 7332Sbill if (q->c_cc <= 0) { 7432Sbill q->c_cc = 0; 7532Sbill q->c_cf = q->c_cl = NULL; 761890Swnj splx(s); 7732Sbill return(0); 7832Sbill } 7932Sbill acp = cp; 8032Sbill cc++; 8132Sbill 8232Sbill while (--cc) { 8332Sbill *cp++ = *q->c_cf++; 8432Sbill if (--q->c_cc <= 0) { 8532Sbill bp = (struct cblock *)(q->c_cf-1); 8632Sbill bp = (struct cblock *)((int)bp & ~CROUND); 8732Sbill q->c_cf = q->c_cl = NULL; 8832Sbill bp->c_next = cfreelist; 8932Sbill cfreelist = bp; 901890Swnj cfreecount += CBSIZE; 911890Swnj if (cwaiting) { 921890Swnj wakeup(&cwaiting); 931890Swnj cwaiting = 0; 941890Swnj } 9532Sbill break; 9632Sbill } 9732Sbill if (((int)q->c_cf & CROUND) == 0) { 9832Sbill bp = (struct cblock *)(q->c_cf); 9932Sbill bp--; 10032Sbill q->c_cf = bp->c_next->c_info; 10132Sbill bp->c_next = cfreelist; 10232Sbill cfreelist = bp; 1031890Swnj cfreecount += CBSIZE; 1041890Swnj if (cwaiting) { 1051890Swnj wakeup(&cwaiting); 1061890Swnj cwaiting = 0; 1071890Swnj } 10832Sbill } 10932Sbill } 11032Sbill splx(s); 11132Sbill return(cp-acp); 11232Sbill } 113*12754Ssam #endif 11432Sbill 11532Sbill /* 11632Sbill * Return count of contiguous characters 11732Sbill * in clist starting at q->c_cf. 11832Sbill * Stop counting if flag&character is non-null. 11932Sbill */ 12032Sbill ndqb(q, flag) 1219761Ssam register struct clist *q; 12232Sbill { 1239761Ssam register cc; 1249761Ssam int s; 12532Sbill 1263545Swnj s = spl5(); 12732Sbill if (q->c_cc <= 0) { 12832Sbill cc = -q->c_cc; 12932Sbill goto out; 13032Sbill } 13132Sbill cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 13232Sbill cc -= (int)q->c_cf; 13332Sbill if (q->c_cc < cc) 13432Sbill cc = q->c_cc; 13532Sbill if (flag) { 13632Sbill register char *p, *end; 13732Sbill 13832Sbill p = q->c_cf; 13932Sbill end = p; 14032Sbill end += cc; 14132Sbill while (p < end) { 14232Sbill if (*p & flag) { 1431890Swnj cc = (int)p; 1441890Swnj cc -= (int)q->c_cf; 14532Sbill break; 14632Sbill } 14732Sbill p++; 14832Sbill } 14932Sbill } 15032Sbill out: 15132Sbill splx(s); 15232Sbill return(cc); 15332Sbill } 15432Sbill 1551890Swnj 1561890Swnj 15732Sbill /* 1581890Swnj * Flush cc bytes from q. 15932Sbill */ 16032Sbill ndflush(q, cc) 161*12754Ssam register struct clist *q; 162*12754Ssam register cc; 16332Sbill { 164*12754Ssam register struct cblock *bp; 165*12754Ssam char *end; 166*12754Ssam int rem, s; 16732Sbill 1683545Swnj s = spl5(); 16910749Seric if (q->c_cc <= 0) { 17032Sbill goto out; 17132Sbill } 1721890Swnj while (cc>0 && q->c_cc) { 1731890Swnj bp = (struct cblock *)((int)q->c_cf & ~CROUND); 1741890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 1751890Swnj end = q->c_cl; 1761890Swnj } else { 1771890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 1781890Swnj } 1791890Swnj rem = end - q->c_cf; 1801890Swnj if (cc >= rem) { 1811890Swnj cc -= rem; 1821890Swnj q->c_cc -= rem; 18332Sbill q->c_cf = bp->c_next->c_info; 1841890Swnj bp->c_next = cfreelist; 1851890Swnj cfreelist = bp; 1861890Swnj cfreecount += CBSIZE; 1871890Swnj if (cwaiting) { 1881890Swnj wakeup(&cwaiting); 1891890Swnj cwaiting = 0; 1901890Swnj } 19132Sbill } else { 1921890Swnj q->c_cc -= cc; 1931890Swnj q->c_cf += cc; 1941890Swnj if (q->c_cc <= 0) { 1951890Swnj bp->c_next = cfreelist; 1961890Swnj cfreelist = bp; 1971890Swnj cfreecount += CBSIZE; 1981890Swnj if (cwaiting) { 1991890Swnj wakeup(&cwaiting); 2001890Swnj cwaiting = 0; 2011890Swnj } 2021890Swnj } 2031890Swnj break; 20432Sbill } 2051890Swnj } 2061890Swnj if (q->c_cc <= 0) { 20732Sbill q->c_cf = q->c_cl = NULL; 2081890Swnj q->c_cc = 0; 20932Sbill } 21032Sbill out: 21132Sbill splx(s); 21232Sbill } 213172Sbill 2141890Swnj 21532Sbill putc(c, p) 216*12754Ssam register struct clist *p; 21732Sbill { 21832Sbill register struct cblock *bp; 21932Sbill register char *cp; 22032Sbill register s; 22132Sbill 2223545Swnj s = spl5(); 22332Sbill if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 22432Sbill if ((bp = cfreelist) == NULL) { 22532Sbill splx(s); 22632Sbill return(-1); 22732Sbill } 22832Sbill cfreelist = bp->c_next; 2291890Swnj cfreecount -= CBSIZE; 23032Sbill bp->c_next = NULL; 23132Sbill p->c_cf = cp = bp->c_info; 23232Sbill } else if (((int)cp & CROUND) == 0) { 23332Sbill bp = (struct cblock *)cp - 1; 23432Sbill if ((bp->c_next = cfreelist) == NULL) { 23532Sbill splx(s); 23632Sbill return(-1); 23732Sbill } 23832Sbill bp = bp->c_next; 23932Sbill cfreelist = bp->c_next; 2401890Swnj cfreecount -= CBSIZE; 24132Sbill bp->c_next = NULL; 24232Sbill cp = bp->c_info; 24332Sbill } 24432Sbill *cp++ = c; 24532Sbill p->c_cc++; 24632Sbill p->c_cl = cp; 24732Sbill splx(s); 24832Sbill return(0); 24932Sbill } 25032Sbill 2511890Swnj 2521890Swnj 25332Sbill /* 25432Sbill * copy buffer to clist. 25532Sbill * return number of bytes not transfered. 25632Sbill */ 25732Sbill b_to_q(cp, cc, q) 258*12754Ssam register char *cp; 259*12754Ssam struct clist *q; 260*12754Ssam register int cc; 26132Sbill { 26232Sbill register char *cq; 26332Sbill register struct cblock *bp; 26432Sbill register s, acc; 26532Sbill 26632Sbill if (cc <= 0) 26732Sbill return(0); 26832Sbill acc = cc; 2691890Swnj 2701890Swnj 2713545Swnj s = spl5(); 27232Sbill if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 27332Sbill if ((bp = cfreelist) == NULL) 27432Sbill goto out; 27532Sbill cfreelist = bp->c_next; 2761890Swnj cfreecount -= CBSIZE; 27732Sbill bp->c_next = NULL; 27832Sbill q->c_cf = cq = bp->c_info; 27932Sbill } 28032Sbill 28132Sbill while (cc) { 28232Sbill if (((int)cq & CROUND) == 0) { 28332Sbill bp = (struct cblock *) cq - 1; 28432Sbill if ((bp->c_next = cfreelist) == NULL) 28532Sbill goto out; 28632Sbill bp = bp->c_next; 28732Sbill cfreelist = bp->c_next; 2881890Swnj cfreecount -= CBSIZE; 28932Sbill bp->c_next = NULL; 29032Sbill cq = bp->c_info; 29132Sbill } 29232Sbill *cq++ = *cp++; 29332Sbill cc--; 29432Sbill } 29532Sbill out: 29632Sbill q->c_cl = cq; 29732Sbill q->c_cc += acc-cc; 29832Sbill splx(s); 29932Sbill return(cc); 30032Sbill } 30132Sbill 30232Sbill /* 303172Sbill * Given a non-NULL pointter into the list (like c_cf which 304172Sbill * always points to a real character if non-NULL) return the pointer 305172Sbill * to the next character in the list or return NULL if no more chars. 306172Sbill * 307172Sbill * Callers must not allow getc's to happen between nextc's so that the 308172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 309172Sbill */ 310172Sbill char * 311172Sbill nextc(p, cp) 312*12754Ssam register struct clist *p; 313*12754Ssam register char *cp; 314172Sbill { 315172Sbill 316172Sbill if (p->c_cc && ++cp != p->c_cl) { 317172Sbill if (((int)cp & CROUND) == 0) 318172Sbill return (((struct cblock *)cp)[-1].c_next->c_info); 319172Sbill return (cp); 320172Sbill } 321172Sbill return (0); 322172Sbill } 323172Sbill 324172Sbill /* 325172Sbill * Remove the last character in the list and return it. 326172Sbill */ 327172Sbill unputc(p) 328*12754Ssam register struct clist *p; 329172Sbill { 330172Sbill register struct cblock *bp; 331172Sbill register int c, s; 332172Sbill struct cblock *obp; 333172Sbill 3343545Swnj s = spl5(); 335172Sbill if (p->c_cc <= 0) 336172Sbill c = -1; 337172Sbill else { 338172Sbill c = *--p->c_cl; 339172Sbill if (--p->c_cc <= 0) { 340172Sbill bp = (struct cblock *)p->c_cl; 341172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 342172Sbill p->c_cl = p->c_cf = NULL; 343172Sbill bp->c_next = cfreelist; 344172Sbill cfreelist = bp; 3451890Swnj cfreecount += CBSIZE; 346172Sbill } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 347172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 348172Sbill bp = (struct cblock *)p->c_cf; 349172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 350172Sbill while (bp->c_next != (struct cblock *)p->c_cl) 351172Sbill bp = bp->c_next; 352172Sbill obp = bp; 353172Sbill p->c_cl = (char *)(bp + 1); 354172Sbill bp = bp->c_next; 355172Sbill bp->c_next = cfreelist; 356172Sbill cfreelist = bp; 3571890Swnj cfreecount += CBSIZE; 358172Sbill obp->c_next = NULL; 359172Sbill } 360172Sbill } 361172Sbill splx(s); 362172Sbill return (c); 363172Sbill } 364172Sbill 365172Sbill /* 366172Sbill * Put the chars in the from que 367172Sbill * on the end of the to que. 368172Sbill * 369172Sbill * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. 370172Sbill */ 371172Sbill catq(from, to) 372*12754Ssam struct clist *from, *to; 373172Sbill { 374172Sbill register c; 375172Sbill 376172Sbill while ((c = getc(from)) >= 0) 377172Sbill (void) putc(c, to); 378172Sbill } 379172Sbill 380172Sbill /* 3819761Ssam * Integer (short) get/put 38232Sbill * using clists 38332Sbill */ 3849761Ssam typedef short word_t; 3859761Ssam union chword { 3869761Ssam word_t word; 3879761Ssam struct { 3889761Ssam char Ch[sizeof (word_t)]; 3899761Ssam } Cha; 3909761Ssam #define ch Cha.Ch 3919761Ssam }; 3929761Ssam 39332Sbill getw(p) 3948955Sroot register struct clist *p; 39532Sbill { 3969761Ssam register int i; 3979761Ssam union chword x; 39832Sbill 3999761Ssam if (p->c_cc < sizeof (word_t)) 4009761Ssam return (-1); 4019761Ssam for (i = 0; i < sizeof (word_t); i++) 4029761Ssam x.ch[i] = getc(p); 4039761Ssam return (x.word); 40432Sbill } 40532Sbill 40632Sbill putw(c, p) 4078955Sroot register struct clist *p; 40832Sbill { 40932Sbill register s; 4109761Ssam register int i; 4119761Ssam union chword x; 41232Sbill 4133545Swnj s = spl5(); 41432Sbill if (cfreelist==NULL) { 41532Sbill splx(s); 41632Sbill return(-1); 41732Sbill } 4189761Ssam x.word = c; 4199761Ssam for (i = 0; i < sizeof (word_t); i++) 4209761Ssam (void) putc(x.ch[i], p); 42132Sbill splx(s); 4229761Ssam return (0); 42332Sbill } 424