1*3545Swnj /* tty_subr.c 4.11 81/04/17 */ 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 21*3545Swnj 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) 6232Sbill register struct clist *q; 6332Sbill register char *cp; 6432Sbill { 6532Sbill register struct cblock *bp; 6632Sbill register int s; 6732Sbill char *acp; 6832Sbill 6932Sbill if (cc <= 0) 7032Sbill return(0); 71*3545Swnj 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) 11932Sbill register struct clist *q; 12032Sbill { 12132Sbill register cc; 12232Sbill int s; 12332Sbill 124*3545Swnj 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 167*3545Swnj s = spl5(); 16832Sbill if (q->c_cc < 0) { 1691890Swnj printf("neg q flush\n"); 17032Sbill goto out; 17132Sbill } 17232Sbill if (q->c_cc == 0) { 17332Sbill goto out; 17432Sbill } 1751890Swnj while (cc>0 && q->c_cc) { 1761890Swnj bp = (struct cblock *)((int)q->c_cf & ~CROUND); 1771890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 1781890Swnj end = q->c_cl; 1791890Swnj } else { 1801890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 1811890Swnj } 1821890Swnj rem = end - q->c_cf; 1831890Swnj if (cc >= rem) { 1841890Swnj cc -= rem; 1851890Swnj q->c_cc -= rem; 18632Sbill q->c_cf = bp->c_next->c_info; 1871890Swnj bp->c_next = cfreelist; 1881890Swnj cfreelist = bp; 1891890Swnj cfreecount += CBSIZE; 1901890Swnj if (cwaiting) { 1911890Swnj wakeup(&cwaiting); 1921890Swnj cwaiting = 0; 1931890Swnj } 19432Sbill } else { 1951890Swnj q->c_cc -= cc; 1961890Swnj q->c_cf += cc; 1971890Swnj if (q->c_cc <= 0) { 1981890Swnj bp->c_next = cfreelist; 1991890Swnj cfreelist = bp; 2001890Swnj cfreecount += CBSIZE; 2011890Swnj if (cwaiting) { 2021890Swnj wakeup(&cwaiting); 2031890Swnj cwaiting = 0; 2041890Swnj } 2051890Swnj } 2061890Swnj break; 20732Sbill } 2081890Swnj } 2091890Swnj if (q->c_cc <= 0) { 21032Sbill q->c_cf = q->c_cl = NULL; 2111890Swnj q->c_cc = 0; 21232Sbill } 21332Sbill out: 21432Sbill splx(s); 21532Sbill } 216172Sbill 2171890Swnj 21832Sbill putc(c, p) 21932Sbill register struct clist *p; 22032Sbill { 22132Sbill register struct cblock *bp; 22232Sbill register char *cp; 22332Sbill register s; 22432Sbill 225*3545Swnj s = spl5(); 22632Sbill if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 22732Sbill if ((bp = cfreelist) == NULL) { 22832Sbill splx(s); 22932Sbill return(-1); 23032Sbill } 23132Sbill cfreelist = bp->c_next; 2321890Swnj cfreecount -= CBSIZE; 23332Sbill bp->c_next = NULL; 23432Sbill p->c_cf = cp = bp->c_info; 23532Sbill } else if (((int)cp & CROUND) == 0) { 23632Sbill bp = (struct cblock *)cp - 1; 23732Sbill if ((bp->c_next = cfreelist) == NULL) { 23832Sbill splx(s); 23932Sbill return(-1); 24032Sbill } 24132Sbill bp = bp->c_next; 24232Sbill cfreelist = bp->c_next; 2431890Swnj cfreecount -= CBSIZE; 24432Sbill bp->c_next = NULL; 24532Sbill cp = bp->c_info; 24632Sbill } 24732Sbill *cp++ = c; 24832Sbill p->c_cc++; 24932Sbill p->c_cl = cp; 25032Sbill splx(s); 25132Sbill return(0); 25232Sbill } 25332Sbill 2541890Swnj 2551890Swnj 25632Sbill /* 25732Sbill * copy buffer to clist. 25832Sbill * return number of bytes not transfered. 25932Sbill */ 26032Sbill b_to_q(cp, cc, q) 26132Sbill register char *cp; 26232Sbill struct clist *q; 26332Sbill register int cc; 26432Sbill { 26532Sbill register char *cq; 26632Sbill register struct cblock *bp; 26732Sbill register s, acc; 26832Sbill 26932Sbill if (cc <= 0) 27032Sbill return(0); 27132Sbill acc = cc; 2721890Swnj 2731890Swnj 274*3545Swnj s = spl5(); 27532Sbill if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 27632Sbill if ((bp = cfreelist) == NULL) 27732Sbill goto out; 27832Sbill cfreelist = bp->c_next; 2791890Swnj cfreecount -= CBSIZE; 28032Sbill bp->c_next = NULL; 28132Sbill q->c_cf = cq = bp->c_info; 28232Sbill } 28332Sbill 28432Sbill while (cc) { 28532Sbill if (((int)cq & CROUND) == 0) { 28632Sbill bp = (struct cblock *) cq - 1; 28732Sbill if ((bp->c_next = cfreelist) == NULL) 28832Sbill goto out; 28932Sbill bp = bp->c_next; 29032Sbill cfreelist = bp->c_next; 2911890Swnj cfreecount -= CBSIZE; 29232Sbill bp->c_next = NULL; 29332Sbill cq = bp->c_info; 29432Sbill } 29532Sbill *cq++ = *cp++; 29632Sbill cc--; 29732Sbill } 29832Sbill out: 29932Sbill q->c_cl = cq; 30032Sbill q->c_cc += acc-cc; 30132Sbill splx(s); 30232Sbill return(cc); 30332Sbill } 30432Sbill 30532Sbill /* 306172Sbill * Given a non-NULL pointter into the list (like c_cf which 307172Sbill * always points to a real character if non-NULL) return the pointer 308172Sbill * to the next character in the list or return NULL if no more chars. 309172Sbill * 310172Sbill * Callers must not allow getc's to happen between nextc's so that the 311172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 312172Sbill */ 313172Sbill char * 314172Sbill nextc(p, cp) 315172Sbill register struct clist *p; 316172Sbill register char *cp; 317172Sbill { 318172Sbill 319172Sbill if (p->c_cc && ++cp != p->c_cl) { 320172Sbill if (((int)cp & CROUND) == 0) 321172Sbill return (((struct cblock *)cp)[-1].c_next->c_info); 322172Sbill return (cp); 323172Sbill } 324172Sbill return (0); 325172Sbill } 326172Sbill 327172Sbill /* 328172Sbill * Remove the last character in the list and return it. 329172Sbill */ 330172Sbill unputc(p) 331172Sbill register struct clist *p; 332172Sbill { 333172Sbill register struct cblock *bp; 334172Sbill register int c, s; 335172Sbill struct cblock *obp; 336172Sbill 337*3545Swnj s = spl5(); 338172Sbill if (p->c_cc <= 0) 339172Sbill c = -1; 340172Sbill else { 341172Sbill c = *--p->c_cl; 342172Sbill if (--p->c_cc <= 0) { 343172Sbill bp = (struct cblock *)p->c_cl; 344172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 345172Sbill p->c_cl = p->c_cf = NULL; 346172Sbill bp->c_next = cfreelist; 347172Sbill cfreelist = bp; 3481890Swnj cfreecount += CBSIZE; 349172Sbill } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 350172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 351172Sbill bp = (struct cblock *)p->c_cf; 352172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 353172Sbill while (bp->c_next != (struct cblock *)p->c_cl) 354172Sbill bp = bp->c_next; 355172Sbill obp = bp; 356172Sbill p->c_cl = (char *)(bp + 1); 357172Sbill bp = bp->c_next; 358172Sbill bp->c_next = cfreelist; 359172Sbill cfreelist = bp; 3601890Swnj cfreecount += CBSIZE; 361172Sbill obp->c_next = NULL; 362172Sbill } 363172Sbill } 364172Sbill splx(s); 365172Sbill return (c); 366172Sbill } 367172Sbill 368172Sbill /* 369172Sbill * Put the chars in the from que 370172Sbill * on the end of the to que. 371172Sbill * 372172Sbill * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. 373172Sbill */ 374172Sbill catq(from, to) 375172Sbill struct clist *from, *to; 376172Sbill { 377172Sbill register c; 378172Sbill 379172Sbill while ((c = getc(from)) >= 0) 380172Sbill (void) putc(c, to); 381172Sbill } 382172Sbill 383172Sbill /* 38432Sbill * integer (2-byte) get/put 38532Sbill * using clists 38632Sbill */ 3873101Swnj #ifdef unneeded 38832Sbill getw(p) 38932Sbill register struct clist *p; 39032Sbill { 39132Sbill register int s; 39232Sbill 39332Sbill if (p->c_cc <= 1) 39432Sbill return(-1); 39532Sbill s = getc(p); 39632Sbill return(s | (getc(p)<<8)); 39732Sbill } 3983101Swnj #endif 39932Sbill 40032Sbill putw(c, p) 40132Sbill register struct clist *p; 40232Sbill { 40332Sbill register s; 40432Sbill 405*3545Swnj s = spl5(); 40632Sbill if (cfreelist==NULL) { 40732Sbill splx(s); 40832Sbill return(-1); 40932Sbill } 410130Sbill (void) putc(c, p); 411130Sbill (void) putc(c>>8, p); 41232Sbill splx(s); 41332Sbill return(0); 41432Sbill } 415