1*23391Smckusick /* 2*23391Smckusick * Copyright (c) 1982 Regents of the University of California. 3*23391Smckusick * All rights reserved. The Berkeley software License Agreement 4*23391Smckusick * specifies the terms and conditions for redistribution. 5*23391Smckusick * 6*23391Smckusick * @(#)tty_subr.c 6.10 (Berkeley) 06/08/85 7*23391Smckusick */ 81892Swnj 917097Sbloom #include "param.h" 1017097Sbloom #include "systm.h" 1117097Sbloom #include "buf.h" 1217576Sbloom #include "ioctl.h" 1317097Sbloom #include "tty.h" 1417097Sbloom #include "clist.h" 1532Sbill 161890Swnj char cwaiting; 171890Swnj 1832Sbill /* 1932Sbill * Character list get/put 2032Sbill */ 2132Sbill getc(p) 2212754Ssam register struct clist *p; 2332Sbill { 2432Sbill register struct cblock *bp; 2532Sbill register int c, s; 2632Sbill 2717542Skarels s = spltty(); 2832Sbill if (p->c_cc <= 0) { 2932Sbill c = -1; 3032Sbill p->c_cc = 0; 3132Sbill p->c_cf = p->c_cl = NULL; 3232Sbill } else { 3332Sbill c = *p->c_cf++ & 0377; 3432Sbill if (--p->c_cc<=0) { 3532Sbill bp = (struct cblock *)(p->c_cf-1); 3632Sbill bp = (struct cblock *) ((int)bp & ~CROUND); 3732Sbill p->c_cf = NULL; 3832Sbill p->c_cl = NULL; 3932Sbill bp->c_next = cfreelist; 4032Sbill cfreelist = bp; 411890Swnj cfreecount += CBSIZE; 421890Swnj if (cwaiting) { 431890Swnj wakeup(&cwaiting); 441890Swnj cwaiting = 0; 451890Swnj } 4632Sbill } else if (((int)p->c_cf & CROUND) == 0){ 4732Sbill bp = (struct cblock *)(p->c_cf); 4832Sbill bp--; 4932Sbill p->c_cf = bp->c_next->c_info; 5032Sbill bp->c_next = cfreelist; 5132Sbill cfreelist = bp; 521890Swnj cfreecount += CBSIZE; 531890Swnj if (cwaiting) { 541890Swnj wakeup(&cwaiting); 551890Swnj cwaiting = 0; 561890Swnj } 5732Sbill } 5832Sbill } 5932Sbill splx(s); 6032Sbill return(c); 6132Sbill } 6232Sbill 6332Sbill /* 6432Sbill * copy clist to buffer. 6532Sbill * return number of bytes moved. 6632Sbill */ 6732Sbill q_to_b(q, cp, cc) 689761Ssam register struct clist *q; 699761Ssam register char *cp; 7032Sbill { 7132Sbill register struct cblock *bp; 7232Sbill register int s; 7317542Skarels register nc; 7432Sbill char *acp; 7532Sbill 7632Sbill if (cc <= 0) 7732Sbill return(0); 7817542Skarels s = spltty(); 7932Sbill if (q->c_cc <= 0) { 8032Sbill q->c_cc = 0; 8132Sbill q->c_cf = q->c_cl = NULL; 821890Swnj splx(s); 8332Sbill return(0); 8432Sbill } 8532Sbill acp = cp; 8632Sbill 8717542Skarels while (cc) { 8817542Skarels nc = sizeof(struct cblock) - ((int)q->c_cf & CROUND); 8917542Skarels nc = MIN(nc, cc); 9017542Skarels nc = MIN(nc, q->c_cc); 9117542Skarels (void) bcopy(q->c_cf, cp, (unsigned)nc); 9217542Skarels q->c_cf += nc; 9317542Skarels q->c_cc -= nc; 9417542Skarels cc -= nc; 9517542Skarels cp += nc; 9617542Skarels if (q->c_cc <= 0) { 9717542Skarels bp = (struct cblock *)(q->c_cf - 1); 9832Sbill bp = (struct cblock *)((int)bp & ~CROUND); 9932Sbill q->c_cf = q->c_cl = NULL; 10032Sbill bp->c_next = cfreelist; 10132Sbill cfreelist = bp; 1021890Swnj cfreecount += CBSIZE; 1031890Swnj if (cwaiting) { 1041890Swnj wakeup(&cwaiting); 1051890Swnj cwaiting = 0; 1061890Swnj } 10732Sbill break; 10832Sbill } 10932Sbill if (((int)q->c_cf & CROUND) == 0) { 11032Sbill bp = (struct cblock *)(q->c_cf); 11132Sbill bp--; 11232Sbill q->c_cf = bp->c_next->c_info; 11332Sbill bp->c_next = cfreelist; 11432Sbill cfreelist = bp; 1151890Swnj cfreecount += CBSIZE; 1161890Swnj if (cwaiting) { 1171890Swnj wakeup(&cwaiting); 1181890Swnj cwaiting = 0; 1191890Swnj } 12032Sbill } 12132Sbill } 12232Sbill splx(s); 12332Sbill return(cp-acp); 12432Sbill } 12532Sbill 12632Sbill /* 12732Sbill * Return count of contiguous characters 12832Sbill * in clist starting at q->c_cf. 12932Sbill * Stop counting if flag&character is non-null. 13032Sbill */ 13132Sbill ndqb(q, flag) 1329761Ssam register struct clist *q; 13332Sbill { 1349761Ssam register cc; 1359761Ssam int s; 13632Sbill 13717542Skarels s = spltty(); 13832Sbill if (q->c_cc <= 0) { 13932Sbill cc = -q->c_cc; 14032Sbill goto out; 14132Sbill } 14232Sbill cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 14332Sbill cc -= (int)q->c_cf; 14432Sbill if (q->c_cc < cc) 14532Sbill cc = q->c_cc; 14632Sbill if (flag) { 14732Sbill register char *p, *end; 14832Sbill 14932Sbill p = q->c_cf; 15032Sbill end = p; 15132Sbill end += cc; 15232Sbill while (p < end) { 15332Sbill if (*p & flag) { 1541890Swnj cc = (int)p; 1551890Swnj cc -= (int)q->c_cf; 15632Sbill break; 15732Sbill } 15832Sbill p++; 15932Sbill } 16032Sbill } 16132Sbill out: 16232Sbill splx(s); 16332Sbill return(cc); 16432Sbill } 16532Sbill 1661890Swnj 1671890Swnj 16832Sbill /* 1691890Swnj * Flush cc bytes from q. 17032Sbill */ 17132Sbill ndflush(q, cc) 17212754Ssam register struct clist *q; 17312754Ssam register cc; 17432Sbill { 17512754Ssam register struct cblock *bp; 17612754Ssam char *end; 17712754Ssam int rem, s; 17832Sbill 17917542Skarels s = spltty(); 18010749Seric if (q->c_cc <= 0) { 18132Sbill goto out; 18232Sbill } 1831890Swnj while (cc>0 && q->c_cc) { 1841890Swnj bp = (struct cblock *)((int)q->c_cf & ~CROUND); 1851890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 1861890Swnj end = q->c_cl; 1871890Swnj } else { 1881890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 1891890Swnj } 1901890Swnj rem = end - q->c_cf; 1911890Swnj if (cc >= rem) { 1921890Swnj cc -= rem; 1931890Swnj q->c_cc -= rem; 19432Sbill q->c_cf = bp->c_next->c_info; 1951890Swnj bp->c_next = cfreelist; 1961890Swnj cfreelist = bp; 1971890Swnj cfreecount += CBSIZE; 1981890Swnj if (cwaiting) { 1991890Swnj wakeup(&cwaiting); 2001890Swnj cwaiting = 0; 2011890Swnj } 20232Sbill } else { 2031890Swnj q->c_cc -= cc; 2041890Swnj q->c_cf += cc; 2051890Swnj if (q->c_cc <= 0) { 2061890Swnj bp->c_next = cfreelist; 2071890Swnj cfreelist = bp; 2081890Swnj cfreecount += CBSIZE; 2091890Swnj if (cwaiting) { 2101890Swnj wakeup(&cwaiting); 2111890Swnj cwaiting = 0; 2121890Swnj } 2131890Swnj } 2141890Swnj break; 21532Sbill } 2161890Swnj } 2171890Swnj if (q->c_cc <= 0) { 21832Sbill q->c_cf = q->c_cl = NULL; 2191890Swnj q->c_cc = 0; 22032Sbill } 22132Sbill out: 22232Sbill splx(s); 22332Sbill } 224172Sbill 2251890Swnj 22632Sbill putc(c, p) 22712754Ssam register struct clist *p; 22832Sbill { 22932Sbill register struct cblock *bp; 23032Sbill register char *cp; 23132Sbill register s; 23232Sbill 23317542Skarels s = spltty(); 23432Sbill if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 23532Sbill if ((bp = cfreelist) == NULL) { 23632Sbill splx(s); 23732Sbill return(-1); 23832Sbill } 23932Sbill cfreelist = bp->c_next; 2401890Swnj cfreecount -= CBSIZE; 24132Sbill bp->c_next = NULL; 24232Sbill p->c_cf = cp = bp->c_info; 24332Sbill } else if (((int)cp & CROUND) == 0) { 24432Sbill bp = (struct cblock *)cp - 1; 24532Sbill if ((bp->c_next = cfreelist) == NULL) { 24632Sbill splx(s); 24732Sbill return(-1); 24832Sbill } 24932Sbill bp = bp->c_next; 25032Sbill cfreelist = bp->c_next; 2511890Swnj cfreecount -= CBSIZE; 25232Sbill bp->c_next = NULL; 25332Sbill cp = bp->c_info; 25432Sbill } 25532Sbill *cp++ = c; 25632Sbill p->c_cc++; 25732Sbill p->c_cl = cp; 25832Sbill splx(s); 25932Sbill return(0); 26032Sbill } 26132Sbill 2621890Swnj 2631890Swnj 26432Sbill /* 26532Sbill * copy buffer to clist. 26632Sbill * return number of bytes not transfered. 26732Sbill */ 26832Sbill b_to_q(cp, cc, q) 26912754Ssam register char *cp; 27012754Ssam struct clist *q; 27112754Ssam register int cc; 27232Sbill { 27332Sbill register char *cq; 27432Sbill register struct cblock *bp; 27517542Skarels register s, nc; 27617542Skarels int acc; 27732Sbill 27832Sbill if (cc <= 0) 27917542Skarels return(0); 28017542Skarels acc = cc; 28117542Skarels s = spltty(); 28217542Skarels if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 28317542Skarels if ((bp = cfreelist) == NULL) 28417542Skarels goto out; 28517542Skarels cfreelist = bp->c_next; 28617542Skarels cfreecount -= CBSIZE; 28717542Skarels bp->c_next = NULL; 28817542Skarels q->c_cf = cq = bp->c_info; 28917542Skarels } 29017542Skarels 29117542Skarels while (cc) { 29232Sbill if (((int)cq & CROUND) == 0) { 29317542Skarels bp = (struct cblock *) cq - 1; 29417542Skarels if ((bp->c_next = cfreelist) == NULL) 29517542Skarels goto out; 29632Sbill bp = bp->c_next; 29732Sbill cfreelist = bp->c_next; 2981890Swnj cfreecount -= CBSIZE; 29932Sbill bp->c_next = NULL; 30017542Skarels cq = bp->c_info; 30132Sbill } 30217542Skarels nc = MIN(cc, sizeof(struct cblock) - ((int)cq & CROUND)); 30317542Skarels (void) bcopy(cp, cq, (unsigned)nc); 30417542Skarels cp += nc; 30517542Skarels cq += nc; 30617542Skarels cc -= nc; 30732Sbill } 30817542Skarels out: 30917542Skarels q->c_cl = cq; 31017542Skarels q->c_cc += acc - cc; 31117542Skarels splx(s); 31217368Ssam return (cc); 31332Sbill } 31432Sbill 31532Sbill /* 316172Sbill * Given a non-NULL pointter into the list (like c_cf which 317172Sbill * always points to a real character if non-NULL) return the pointer 318172Sbill * to the next character in the list or return NULL if no more chars. 319172Sbill * 320172Sbill * Callers must not allow getc's to happen between nextc's so that the 321172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 322172Sbill */ 323172Sbill char * 324172Sbill nextc(p, cp) 32512754Ssam register struct clist *p; 32612754Ssam register char *cp; 327172Sbill { 328172Sbill 329172Sbill if (p->c_cc && ++cp != p->c_cl) { 330172Sbill if (((int)cp & CROUND) == 0) 331172Sbill return (((struct cblock *)cp)[-1].c_next->c_info); 332172Sbill return (cp); 333172Sbill } 334172Sbill return (0); 335172Sbill } 336172Sbill 337172Sbill /* 338172Sbill * Remove the last character in the list and return it. 339172Sbill */ 340172Sbill unputc(p) 34112754Ssam register struct clist *p; 342172Sbill { 343172Sbill register struct cblock *bp; 344172Sbill register int c, s; 345172Sbill struct cblock *obp; 346172Sbill 34717542Skarels s = spltty(); 348172Sbill if (p->c_cc <= 0) 349172Sbill c = -1; 350172Sbill else { 351172Sbill c = *--p->c_cl; 352172Sbill if (--p->c_cc <= 0) { 353172Sbill bp = (struct cblock *)p->c_cl; 354172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 355172Sbill p->c_cl = p->c_cf = NULL; 356172Sbill bp->c_next = cfreelist; 357172Sbill cfreelist = bp; 3581890Swnj cfreecount += CBSIZE; 359172Sbill } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 360172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 361172Sbill bp = (struct cblock *)p->c_cf; 362172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 363172Sbill while (bp->c_next != (struct cblock *)p->c_cl) 364172Sbill bp = bp->c_next; 365172Sbill obp = bp; 366172Sbill p->c_cl = (char *)(bp + 1); 367172Sbill bp = bp->c_next; 368172Sbill bp->c_next = cfreelist; 369172Sbill cfreelist = bp; 3701890Swnj cfreecount += CBSIZE; 371172Sbill obp->c_next = NULL; 372172Sbill } 373172Sbill } 374172Sbill splx(s); 375172Sbill return (c); 376172Sbill } 377172Sbill 378172Sbill /* 379172Sbill * Put the chars in the from que 380172Sbill * on the end of the to que. 381172Sbill */ 382172Sbill catq(from, to) 38312754Ssam struct clist *from, *to; 384172Sbill { 38517542Skarels char bbuf[CBSIZE*4]; 38617542Skarels register s, c; 387172Sbill 38817542Skarels s = spltty(); 38917542Skarels if (to->c_cc == 0) { 39017542Skarels *to = *from; 39117542Skarels from->c_cc = 0; 39217542Skarels from->c_cf = NULL; 39317542Skarels from->c_cl = NULL; 39417542Skarels splx(s); 39517542Skarels return; 39617542Skarels } 39717542Skarels splx(s); 39817542Skarels while (from->c_cc > 0) { 39917542Skarels c = q_to_b(from, bbuf, sizeof bbuf); 40017542Skarels (void) b_to_q(bbuf, c, to); 40117542Skarels } 402172Sbill } 403172Sbill 40417542Skarels #ifdef unneeded 405172Sbill /* 4069761Ssam * Integer (short) get/put 40732Sbill * using clists 40832Sbill */ 40917542Skarels typedef u_short word_t; 4109761Ssam 41132Sbill getw(p) 4128955Sroot register struct clist *p; 41332Sbill { 41417542Skarels register int s, c; 41517542Skarels register struct cblock *bp; 41632Sbill 41717542Skarels if (p->c_cc <= 1) 41817542Skarels return(-1); 41917542Skarels if (p->c_cc & 01) { 42017542Skarels c = getc(p); 42117542Skarels return(c | (getc(p)<<8)); 42217542Skarels } 42317542Skarels s = spltty(); 42417542Skarels c = *((word_t *)p->c_cf); 42517542Skarels p->c_cf += sizeof(word_t); 42617542Skarels p->c_cc -= sizeof(word_t); 42717542Skarels if (p->c_cc <= 0) { 42817542Skarels bp = (struct cblock *)(p->c_cf-1); 42917542Skarels bp = (struct cblock *) ((int)bp & ~CROUND); 43017542Skarels p->c_cf = NULL; 43117542Skarels p->c_cl = NULL; 43217542Skarels bp->c_next = cfreelist; 43317542Skarels cfreelist = bp; 43417542Skarels cfreecount += CBSIZE; 43517542Skarels if (cwaiting) { 43617542Skarels wakeup(&cwaiting); 43717542Skarels cwaiting = 0; 43817542Skarels } 43917542Skarels } else if (((int)p->c_cf & CROUND) == 0) { 44017542Skarels bp = (struct cblock *)(p->c_cf); 44117542Skarels bp--; 44217542Skarels p->c_cf = bp->c_next->c_info; 44317542Skarels bp->c_next = cfreelist; 44417542Skarels cfreelist = bp; 44517542Skarels cfreecount += CBSIZE; 44617542Skarels if (cwaiting) { 44717542Skarels wakeup(&cwaiting); 44817542Skarels cwaiting = 0; 44917542Skarels } 45017542Skarels } 45117542Skarels splx(s); 45217542Skarels return (c); 45332Sbill } 45432Sbill 45532Sbill putw(c, p) 4568955Sroot register struct clist *p; 45717542Skarels word_t c; 45832Sbill { 45932Sbill register s; 46017542Skarels register struct cblock *bp; 46117542Skarels register char *cp; 46232Sbill 46317542Skarels s = spltty(); 46432Sbill if (cfreelist==NULL) { 46532Sbill splx(s); 46632Sbill return(-1); 46732Sbill } 46817542Skarels if (p->c_cc & 01) { 46917542Skarels (void) putc(c, p); 47017542Skarels (void) putc(c>>8, p); 47117542Skarels } else { 47217542Skarels if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 47317542Skarels if ((bp = cfreelist) == NULL) { 47417542Skarels splx(s); 47517542Skarels return (-1); 47617542Skarels } 47717542Skarels cfreelist = bp->c_next; 47817542Skarels cfreecount -= CBSIZE; 47917542Skarels bp->c_next = NULL; 48017542Skarels p->c_cf = cp = bp->c_info; 48117542Skarels } else if (((int)cp & CROUND) == 0) { 48217542Skarels bp = (struct cblock *)cp - 1; 48317542Skarels if ((bp->c_next = cfreelist) == NULL) { 48417542Skarels splx(s); 48517542Skarels return (-1); 48617542Skarels } 48717542Skarels bp = bp->c_next; 48817542Skarels cfreelist = bp->c_next; 48917542Skarels cfreecount -= CBSIZE; 49017542Skarels bp->c_next = NULL; 49117542Skarels cp = bp->c_info; 49217542Skarels } 49317542Skarels *(word_t *)cp = c; 49417542Skarels p->c_cl = cp + sizeof(word_t); 49517542Skarels p->c_cc += sizeof(word_t); 49617542Skarels } 49732Sbill splx(s); 4989761Ssam return (0); 49932Sbill } 50017542Skarels #endif unneeded 501