1*8955Sroot /* tty_subr.c 4.16 82/10/31 */ 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 576180Sroot #if notdef 5832Sbill /* 5932Sbill * copy clist to buffer. 6032Sbill * return number of bytes moved. 6132Sbill */ 6232Sbill q_to_b(q, cp, cc) 6332Sbill register struct clist *q; 6432Sbill 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 } 1134970Swnj #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) 12132Sbill register struct clist *q; 12232Sbill { 12332Sbill register cc; 12432Sbill 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) 16132Sbill register struct clist *q; 16232Sbill register cc; 16332Sbill { 1641890Swnj register struct cblock *bp; 1651890Swnj char *end; 1661890Swnj int rem; 16732Sbill register s; 16832Sbill 1693545Swnj s = spl5(); 17032Sbill if (q->c_cc < 0) { 1711890Swnj printf("neg q flush\n"); 17232Sbill goto out; 17332Sbill } 17432Sbill if (q->c_cc == 0) { 17532Sbill goto out; 17632Sbill } 1771890Swnj while (cc>0 && q->c_cc) { 1781890Swnj bp = (struct cblock *)((int)q->c_cf & ~CROUND); 1791890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 1801890Swnj end = q->c_cl; 1811890Swnj } else { 1821890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 1831890Swnj } 1841890Swnj rem = end - q->c_cf; 1851890Swnj if (cc >= rem) { 1861890Swnj cc -= rem; 1871890Swnj q->c_cc -= rem; 18832Sbill q->c_cf = bp->c_next->c_info; 1891890Swnj bp->c_next = cfreelist; 1901890Swnj cfreelist = bp; 1911890Swnj cfreecount += CBSIZE; 1921890Swnj if (cwaiting) { 1931890Swnj wakeup(&cwaiting); 1941890Swnj cwaiting = 0; 1951890Swnj } 19632Sbill } else { 1971890Swnj q->c_cc -= cc; 1981890Swnj q->c_cf += cc; 1991890Swnj if (q->c_cc <= 0) { 2001890Swnj bp->c_next = cfreelist; 2011890Swnj cfreelist = bp; 2021890Swnj cfreecount += CBSIZE; 2031890Swnj if (cwaiting) { 2041890Swnj wakeup(&cwaiting); 2051890Swnj cwaiting = 0; 2061890Swnj } 2071890Swnj } 2081890Swnj break; 20932Sbill } 2101890Swnj } 2111890Swnj if (q->c_cc <= 0) { 21232Sbill q->c_cf = q->c_cl = NULL; 2131890Swnj q->c_cc = 0; 21432Sbill } 21532Sbill out: 21632Sbill splx(s); 21732Sbill } 218172Sbill 2191890Swnj 22032Sbill putc(c, p) 22132Sbill register struct clist *p; 22232Sbill { 22332Sbill register struct cblock *bp; 22432Sbill register char *cp; 22532Sbill register s; 22632Sbill 2273545Swnj s = spl5(); 22832Sbill if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 22932Sbill if ((bp = cfreelist) == NULL) { 23032Sbill splx(s); 23132Sbill return(-1); 23232Sbill } 23332Sbill cfreelist = bp->c_next; 2341890Swnj cfreecount -= CBSIZE; 23532Sbill bp->c_next = NULL; 23632Sbill p->c_cf = cp = bp->c_info; 23732Sbill } else if (((int)cp & CROUND) == 0) { 23832Sbill bp = (struct cblock *)cp - 1; 23932Sbill if ((bp->c_next = cfreelist) == NULL) { 24032Sbill splx(s); 24132Sbill return(-1); 24232Sbill } 24332Sbill bp = bp->c_next; 24432Sbill cfreelist = bp->c_next; 2451890Swnj cfreecount -= CBSIZE; 24632Sbill bp->c_next = NULL; 24732Sbill cp = bp->c_info; 24832Sbill } 24932Sbill *cp++ = c; 25032Sbill p->c_cc++; 25132Sbill p->c_cl = cp; 25232Sbill splx(s); 25332Sbill return(0); 25432Sbill } 25532Sbill 2561890Swnj 2571890Swnj 25832Sbill /* 25932Sbill * copy buffer to clist. 26032Sbill * return number of bytes not transfered. 26132Sbill */ 26232Sbill b_to_q(cp, cc, q) 26332Sbill register char *cp; 26432Sbill struct clist *q; 26532Sbill register int cc; 26632Sbill { 26732Sbill register char *cq; 26832Sbill register struct cblock *bp; 26932Sbill register s, acc; 27032Sbill 27132Sbill if (cc <= 0) 27232Sbill return(0); 27332Sbill acc = cc; 2741890Swnj 2751890Swnj 2763545Swnj s = spl5(); 27732Sbill if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 27832Sbill if ((bp = cfreelist) == NULL) 27932Sbill goto out; 28032Sbill cfreelist = bp->c_next; 2811890Swnj cfreecount -= CBSIZE; 28232Sbill bp->c_next = NULL; 28332Sbill q->c_cf = cq = bp->c_info; 28432Sbill } 28532Sbill 28632Sbill while (cc) { 28732Sbill if (((int)cq & CROUND) == 0) { 28832Sbill bp = (struct cblock *) cq - 1; 28932Sbill if ((bp->c_next = cfreelist) == NULL) 29032Sbill goto out; 29132Sbill bp = bp->c_next; 29232Sbill cfreelist = bp->c_next; 2931890Swnj cfreecount -= CBSIZE; 29432Sbill bp->c_next = NULL; 29532Sbill cq = bp->c_info; 29632Sbill } 29732Sbill *cq++ = *cp++; 29832Sbill cc--; 29932Sbill } 30032Sbill out: 30132Sbill q->c_cl = cq; 30232Sbill q->c_cc += acc-cc; 30332Sbill splx(s); 30432Sbill return(cc); 30532Sbill } 30632Sbill 30732Sbill /* 308172Sbill * Given a non-NULL pointter into the list (like c_cf which 309172Sbill * always points to a real character if non-NULL) return the pointer 310172Sbill * to the next character in the list or return NULL if no more chars. 311172Sbill * 312172Sbill * Callers must not allow getc's to happen between nextc's so that the 313172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 314172Sbill */ 315172Sbill char * 316172Sbill nextc(p, cp) 317172Sbill register struct clist *p; 318172Sbill register char *cp; 319172Sbill { 320172Sbill 321172Sbill if (p->c_cc && ++cp != p->c_cl) { 322172Sbill if (((int)cp & CROUND) == 0) 323172Sbill return (((struct cblock *)cp)[-1].c_next->c_info); 324172Sbill return (cp); 325172Sbill } 326172Sbill return (0); 327172Sbill } 328172Sbill 329172Sbill /* 330172Sbill * Remove the last character in the list and return it. 331172Sbill */ 332172Sbill unputc(p) 333172Sbill register struct clist *p; 334172Sbill { 335172Sbill register struct cblock *bp; 336172Sbill register int c, s; 337172Sbill struct cblock *obp; 338172Sbill 3393545Swnj s = spl5(); 340172Sbill if (p->c_cc <= 0) 341172Sbill c = -1; 342172Sbill else { 343172Sbill c = *--p->c_cl; 344172Sbill if (--p->c_cc <= 0) { 345172Sbill bp = (struct cblock *)p->c_cl; 346172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 347172Sbill p->c_cl = p->c_cf = NULL; 348172Sbill bp->c_next = cfreelist; 349172Sbill cfreelist = bp; 3501890Swnj cfreecount += CBSIZE; 351172Sbill } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 352172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 353172Sbill bp = (struct cblock *)p->c_cf; 354172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 355172Sbill while (bp->c_next != (struct cblock *)p->c_cl) 356172Sbill bp = bp->c_next; 357172Sbill obp = bp; 358172Sbill p->c_cl = (char *)(bp + 1); 359172Sbill bp = bp->c_next; 360172Sbill bp->c_next = cfreelist; 361172Sbill cfreelist = bp; 3621890Swnj cfreecount += CBSIZE; 363172Sbill obp->c_next = NULL; 364172Sbill } 365172Sbill } 366172Sbill splx(s); 367172Sbill return (c); 368172Sbill } 369172Sbill 370172Sbill /* 371172Sbill * Put the chars in the from que 372172Sbill * on the end of the to que. 373172Sbill * 374172Sbill * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. 375172Sbill */ 376172Sbill catq(from, to) 377172Sbill struct clist *from, *to; 378172Sbill { 379172Sbill register c; 380172Sbill 381172Sbill while ((c = getc(from)) >= 0) 382172Sbill (void) putc(c, to); 383172Sbill } 384172Sbill 385172Sbill /* 38632Sbill * integer (2-byte) get/put 38732Sbill * using clists 38832Sbill */ 38932Sbill getw(p) 390*8955Sroot register struct clist *p; 39132Sbill { 39232Sbill register int s; 39332Sbill 39432Sbill if (p->c_cc <= 1) 39532Sbill return(-1); 39632Sbill s = getc(p); 39732Sbill return(s | (getc(p)<<8)); 39832Sbill } 39932Sbill 40032Sbill putw(c, p) 401*8955Sroot register struct clist *p; 40232Sbill { 40332Sbill register s; 40432Sbill 4053545Swnj 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