149589Sbostic /*- 2*63178Sbostic * Copyright (c) 1982, 1986, 1993 3*63178Sbostic * The Regents of the University of California. All rights reserved. 423391Smckusick * 549589Sbostic * %sccs.include.proprietary.c% 649589Sbostic * 7*63178Sbostic * @(#)tty_subr.c 8.1 (Berkeley) 06/10/93 823391Smckusick */ 91892Swnj 1056517Sbostic #include <sys/param.h> 1156517Sbostic #include <sys/systm.h> 1256517Sbostic #include <sys/buf.h> 1356517Sbostic #include <sys/ioctl.h> 1456517Sbostic #include <sys/proc.h> 1556517Sbostic #include <sys/tty.h> 1656517Sbostic #include <sys/clist.h> 1732Sbill 181890Swnj char cwaiting; 1961303Ssklower struct cblock *cfree, *cfreelist; 2061303Ssklower int cfreecount, nclist; 211890Swnj 2235811Smarc #define setquote(cp) \ 2335811Smarc setbit(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \ 2435811Smarc (int)(cp)&CROUND) 2535811Smarc #define isquote(cp) \ 2635811Smarc isset(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \ 2735811Smarc (int)(cp)&CROUND) 2835811Smarc #define cbptr(x) ((struct cblock *)(x)) 2935811Smarc 3032Sbill /* 3147545Skarels * Initialize clist by freeing all character blocks. 3247545Skarels */ 3347545Skarels cinit() 3447545Skarels { 3547545Skarels register int ccp; 3647545Skarels register struct cblock *cp; 3747545Skarels 3847545Skarels ccp = (int) cfree; 3947545Skarels ccp = (ccp + CROUND) & ~CROUND; 4047545Skarels for(cp = (struct cblock *) ccp; cp < &cfree[nclist - 1]; cp++) { 4147545Skarels cp->c_next = cfreelist; 4247545Skarels cfreelist = cp; 4347545Skarels cfreecount += CBSIZE; 4447545Skarels } 4547545Skarels } 4647545Skarels 4747545Skarels /* 4832Sbill * Character list get/put 4932Sbill */ 5032Sbill getc(p) 5112754Ssam register struct clist *p; 5232Sbill { 5332Sbill register struct cblock *bp; 5432Sbill register int c, s; 5532Sbill 5617542Skarels s = spltty(); 5732Sbill if (p->c_cc <= 0) { 5832Sbill c = -1; 5932Sbill p->c_cc = 0; 6032Sbill p->c_cf = p->c_cl = NULL; 6132Sbill } else { 6235811Smarc c = *p->c_cf & 0377; 6335811Smarc if (isquote(p->c_cf)) 6435811Smarc c |= TTY_QUOTE; 6535811Smarc p->c_cf++; 6632Sbill if (--p->c_cc<=0) { 6735811Smarc bp = cbptr(p->c_cf-1); 6835811Smarc bp = cbptr((int)bp & ~CROUND); 6932Sbill p->c_cf = NULL; 7032Sbill p->c_cl = NULL; 7132Sbill bp->c_next = cfreelist; 7232Sbill cfreelist = bp; 731890Swnj cfreecount += CBSIZE; 741890Swnj if (cwaiting) { 751890Swnj wakeup(&cwaiting); 761890Swnj cwaiting = 0; 771890Swnj } 7832Sbill } else if (((int)p->c_cf & CROUND) == 0){ 7935811Smarc bp = cbptr(p->c_cf); 8032Sbill bp--; 8132Sbill p->c_cf = bp->c_next->c_info; 8232Sbill bp->c_next = cfreelist; 8332Sbill cfreelist = bp; 841890Swnj cfreecount += CBSIZE; 851890Swnj if (cwaiting) { 861890Swnj wakeup(&cwaiting); 871890Swnj cwaiting = 0; 881890Swnj } 8932Sbill } 9032Sbill } 9132Sbill splx(s); 9226279Skarels return (c); 9332Sbill } 9432Sbill 9532Sbill /* 9632Sbill * copy clist to buffer. 9732Sbill * return number of bytes moved. 9832Sbill */ 9932Sbill q_to_b(q, cp, cc) 1009761Ssam register struct clist *q; 1019761Ssam register char *cp; 10252501Storek int cc; 10332Sbill { 10432Sbill register struct cblock *bp; 10552501Storek register int s, nc; 10632Sbill char *acp; 10732Sbill 10832Sbill if (cc <= 0) 10926279Skarels return (0); 11017542Skarels s = spltty(); 11132Sbill if (q->c_cc <= 0) { 11232Sbill q->c_cc = 0; 11332Sbill q->c_cf = q->c_cl = NULL; 1141890Swnj splx(s); 11526279Skarels return (0); 11632Sbill } 11732Sbill acp = cp; 11832Sbill 11917542Skarels while (cc) { 12026279Skarels nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND); 12155058Spendry nc = min(nc, cc); 12255058Spendry nc = min(nc, q->c_cc); 12317542Skarels (void) bcopy(q->c_cf, cp, (unsigned)nc); 12417542Skarels q->c_cf += nc; 12517542Skarels q->c_cc -= nc; 12617542Skarels cc -= nc; 12717542Skarels cp += nc; 12817542Skarels if (q->c_cc <= 0) { 12935811Smarc bp = cbptr(q->c_cf - 1); 13035811Smarc bp = cbptr((int)bp & ~CROUND); 13132Sbill q->c_cf = q->c_cl = NULL; 13232Sbill bp->c_next = cfreelist; 13332Sbill cfreelist = bp; 1341890Swnj cfreecount += CBSIZE; 1351890Swnj if (cwaiting) { 1361890Swnj wakeup(&cwaiting); 1371890Swnj cwaiting = 0; 1381890Swnj } 13932Sbill break; 14032Sbill } 14132Sbill if (((int)q->c_cf & CROUND) == 0) { 14235811Smarc bp = cbptr(q->c_cf); 14332Sbill bp--; 14432Sbill q->c_cf = bp->c_next->c_info; 14532Sbill bp->c_next = cfreelist; 14632Sbill cfreelist = bp; 1471890Swnj cfreecount += CBSIZE; 1481890Swnj if (cwaiting) { 1491890Swnj wakeup(&cwaiting); 1501890Swnj cwaiting = 0; 1511890Swnj } 15232Sbill } 15332Sbill } 15432Sbill splx(s); 15526279Skarels return (cp-acp); 15632Sbill } 15732Sbill 15832Sbill /* 15932Sbill * Return count of contiguous characters 16032Sbill * in clist starting at q->c_cf. 16132Sbill * Stop counting if flag&character is non-null. 16232Sbill */ 16332Sbill ndqb(q, flag) 1649761Ssam register struct clist *q; 16552501Storek int flag; 16632Sbill { 16752501Storek register int cc, s; 16832Sbill 16917542Skarels s = spltty(); 17032Sbill if (q->c_cc <= 0) { 17132Sbill cc = -q->c_cc; 17232Sbill goto out; 17332Sbill } 17432Sbill cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 17532Sbill cc -= (int)q->c_cf; 17632Sbill if (q->c_cc < cc) 17732Sbill cc = q->c_cc; 17832Sbill if (flag) { 17932Sbill register char *p, *end; 18032Sbill 18132Sbill p = q->c_cf; 18232Sbill end = p; 18332Sbill end += cc; 18432Sbill while (p < end) { 18532Sbill if (*p & flag) { 1861890Swnj cc = (int)p; 1871890Swnj cc -= (int)q->c_cf; 18832Sbill break; 18932Sbill } 19032Sbill p++; 19132Sbill } 19232Sbill } 19332Sbill out: 19432Sbill splx(s); 19526279Skarels return (cc); 19632Sbill } 19732Sbill 19832Sbill /* 1991890Swnj * Flush cc bytes from q. 20032Sbill */ 20132Sbill ndflush(q, cc) 20212754Ssam register struct clist *q; 20352501Storek register int cc; 20432Sbill { 20512754Ssam register struct cblock *bp; 20612754Ssam char *end; 20712754Ssam int rem, s; 20832Sbill 20917542Skarels s = spltty(); 21026279Skarels if (q->c_cc <= 0) 21132Sbill goto out; 2121890Swnj while (cc>0 && q->c_cc) { 21335811Smarc bp = cbptr((int)q->c_cf & ~CROUND); 2141890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 2151890Swnj end = q->c_cl; 2161890Swnj } else { 2171890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 2181890Swnj } 2191890Swnj rem = end - q->c_cf; 2201890Swnj if (cc >= rem) { 2211890Swnj cc -= rem; 2221890Swnj q->c_cc -= rem; 22332Sbill q->c_cf = bp->c_next->c_info; 2241890Swnj bp->c_next = cfreelist; 2251890Swnj cfreelist = bp; 2261890Swnj cfreecount += CBSIZE; 2271890Swnj if (cwaiting) { 2281890Swnj wakeup(&cwaiting); 2291890Swnj cwaiting = 0; 2301890Swnj } 23132Sbill } else { 2321890Swnj q->c_cc -= cc; 2331890Swnj q->c_cf += cc; 2341890Swnj if (q->c_cc <= 0) { 2351890Swnj bp->c_next = cfreelist; 2361890Swnj cfreelist = bp; 2371890Swnj cfreecount += CBSIZE; 2381890Swnj if (cwaiting) { 2391890Swnj wakeup(&cwaiting); 2401890Swnj cwaiting = 0; 2411890Swnj } 2421890Swnj } 2431890Swnj break; 24432Sbill } 2451890Swnj } 2461890Swnj if (q->c_cc <= 0) { 24732Sbill q->c_cf = q->c_cl = NULL; 2481890Swnj q->c_cc = 0; 24932Sbill } 25032Sbill out: 25132Sbill splx(s); 25232Sbill } 253172Sbill 2541890Swnj 25532Sbill putc(c, p) 25652501Storek int c; 25712754Ssam register struct clist *p; 25832Sbill { 25932Sbill register struct cblock *bp; 26032Sbill register char *cp; 26152501Storek register int s; 26232Sbill 26317542Skarels s = spltty(); 26435811Smarc if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { /* no cblocks yet */ 26532Sbill if ((bp = cfreelist) == NULL) { 26632Sbill splx(s); 26726279Skarels return (-1); 26832Sbill } 26932Sbill cfreelist = bp->c_next; 2701890Swnj cfreecount -= CBSIZE; 27132Sbill bp->c_next = NULL; 27235811Smarc bzero(bp->c_quote, CBQSIZE); 27332Sbill p->c_cf = cp = bp->c_info; 27432Sbill } else if (((int)cp & CROUND) == 0) { 27535811Smarc bp = cbptr(cp) - 1; /* pointer arith */ 27632Sbill if ((bp->c_next = cfreelist) == NULL) { 27732Sbill splx(s); 27826279Skarels return (-1); 27932Sbill } 28032Sbill bp = bp->c_next; 28132Sbill cfreelist = bp->c_next; 2821890Swnj cfreecount -= CBSIZE; 28332Sbill bp->c_next = NULL; 28432Sbill cp = bp->c_info; 28532Sbill } 28635811Smarc if (c&TTY_QUOTE) 28735811Smarc setquote(cp); 28832Sbill *cp++ = c; 28932Sbill p->c_cc++; 29032Sbill p->c_cl = cp; 29132Sbill splx(s); 29226279Skarels return (0); 29332Sbill } 29432Sbill 29532Sbill /* 29632Sbill * copy buffer to clist. 29732Sbill * return number of bytes not transfered. 29832Sbill */ 29932Sbill b_to_q(cp, cc, q) 30012754Ssam register char *cp; 30112754Ssam struct clist *q; 30212754Ssam register int cc; 30332Sbill { 30432Sbill register char *cq; 30532Sbill register struct cblock *bp; 30652501Storek register int s, nc; 30717542Skarels int acc; 30832Sbill 30932Sbill if (cc <= 0) 31026279Skarels return (0); 31117542Skarels acc = cc; 31217542Skarels s = spltty(); 31317542Skarels if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 31417542Skarels if ((bp = cfreelist) == NULL) 31517542Skarels goto out; 31617542Skarels cfreelist = bp->c_next; 31717542Skarels cfreecount -= CBSIZE; 31835811Smarc bzero(bp->c_quote, CBQSIZE); 31917542Skarels bp->c_next = NULL; 32017542Skarels q->c_cf = cq = bp->c_info; 32117542Skarels } 32217542Skarels 32317542Skarels while (cc) { 32432Sbill if (((int)cq & CROUND) == 0) { 32535811Smarc bp = cbptr(cq) - 1; 32617542Skarels if ((bp->c_next = cfreelist) == NULL) 32717542Skarels goto out; 32832Sbill bp = bp->c_next; 32932Sbill cfreelist = bp->c_next; 3301890Swnj cfreecount -= CBSIZE; 33135811Smarc bzero(bp->c_quote, CBQSIZE); 33232Sbill bp->c_next = NULL; 33317542Skarels cq = bp->c_info; 33432Sbill } 33555058Spendry nc = min(cc, sizeof (struct cblock) - ((int)cq & CROUND)); 33617542Skarels (void) bcopy(cp, cq, (unsigned)nc); 33717542Skarels cp += nc; 33817542Skarels cq += nc; 33917542Skarels cc -= nc; 34032Sbill } 34117542Skarels out: 34217542Skarels q->c_cl = cq; 34317542Skarels q->c_cc += acc - cc; 34417542Skarels splx(s); 34517368Ssam return (cc); 34632Sbill } 34732Sbill 34832Sbill /* 349172Sbill * Given a non-NULL pointter into the list (like c_cf which 350172Sbill * always points to a real character if non-NULL) return the pointer 351172Sbill * to the next character in the list or return NULL if no more chars. 352172Sbill * 353172Sbill * Callers must not allow getc's to happen between nextc's so that the 354172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 355172Sbill */ 356172Sbill char * 35735811Smarc nextc(p, cp, c) 35812754Ssam register struct clist *p; 35912754Ssam register char *cp; 36035811Smarc register int *c; 361172Sbill { 362172Sbill 363172Sbill if (p->c_cc && ++cp != p->c_cl) { 36435811Smarc if (((int)cp & CROUND) == 0) { 36535811Smarc cp = (cbptr(cp))[-1].c_next->c_info; 36635811Smarc } 36735811Smarc *c = *cp; 36835811Smarc if (isquote(cp)) 36935811Smarc *c |= TTY_QUOTE; 370172Sbill return (cp); 371172Sbill } 372172Sbill return (0); 373172Sbill } 374172Sbill 375172Sbill /* 376172Sbill * Remove the last character in the list and return it. 377172Sbill */ 378172Sbill unputc(p) 37912754Ssam register struct clist *p; 380172Sbill { 381172Sbill register struct cblock *bp; 382172Sbill register int c, s; 383172Sbill struct cblock *obp; 384172Sbill 38517542Skarels s = spltty(); 386172Sbill if (p->c_cc <= 0) 387172Sbill c = -1; 388172Sbill else { 389172Sbill c = *--p->c_cl; 39035811Smarc if (isquote(p->c_cl)) 39135811Smarc c |= TTY_QUOTE; 392172Sbill if (--p->c_cc <= 0) { 39335811Smarc bp = cbptr(p->c_cl); 39435811Smarc bp = cbptr((int)bp & ~CROUND); 395172Sbill p->c_cl = p->c_cf = NULL; 396172Sbill bp->c_next = cfreelist; 397172Sbill cfreelist = bp; 3981890Swnj cfreecount += CBSIZE; 39935811Smarc } else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) { 400172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 40135811Smarc 40235811Smarc bp = cbptr(p->c_cf); 40335811Smarc bp = cbptr((int)bp & ~CROUND); 40435811Smarc while (bp->c_next != cbptr(p->c_cl)) 405172Sbill bp = bp->c_next; 406172Sbill obp = bp; 407172Sbill p->c_cl = (char *)(bp + 1); 408172Sbill bp = bp->c_next; 409172Sbill bp->c_next = cfreelist; 410172Sbill cfreelist = bp; 4111890Swnj cfreecount += CBSIZE; 412172Sbill obp->c_next = NULL; 413172Sbill } 414172Sbill } 415172Sbill splx(s); 416172Sbill return (c); 417172Sbill } 418172Sbill 419172Sbill /* 420172Sbill * Put the chars in the from que 421172Sbill * on the end of the to que. 422172Sbill */ 423172Sbill catq(from, to) 42412754Ssam struct clist *from, *to; 425172Sbill { 42635811Smarc #ifdef notdef 42717542Skarels char bbuf[CBSIZE*4]; 42835811Smarc #endif 42952501Storek register int s, c; 430172Sbill 43117542Skarels s = spltty(); 43217542Skarels if (to->c_cc == 0) { 43317542Skarels *to = *from; 43417542Skarels from->c_cc = 0; 43517542Skarels from->c_cf = NULL; 43617542Skarels from->c_cl = NULL; 43717542Skarels splx(s); 43817542Skarels return; 43917542Skarels } 44017542Skarels splx(s); 44135811Smarc #ifdef notdef 44217542Skarels while (from->c_cc > 0) { 44317542Skarels c = q_to_b(from, bbuf, sizeof bbuf); 44417542Skarels (void) b_to_q(bbuf, c, to); 44517542Skarels } 44635811Smarc #endif 44735811Smarc /* XXX - FIX */ 44835811Smarc while ((c = getc(from)) >= 0) 44935811Smarc putc(c, to); 450172Sbill } 451172Sbill 45217542Skarels #ifdef unneeded 453172Sbill /* 45426279Skarels * Integer (short) get/put using clists. 45532Sbill */ 45617542Skarels typedef u_short word_t; 4579761Ssam 45832Sbill getw(p) 4598955Sroot register struct clist *p; 46032Sbill { 46117542Skarels register int s, c; 46217542Skarels register struct cblock *bp; 46332Sbill 46417542Skarels if (p->c_cc <= 1) 46517542Skarels return(-1); 46617542Skarels if (p->c_cc & 01) { 46717542Skarels c = getc(p); 46833398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 46926279Skarels return (c | (getc(p)<<8)); 47026279Skarels #else 47126279Skarels return (getc(p) | (c<<8)); 47226279Skarels #endif 47317542Skarels } 47417542Skarels s = spltty(); 47535811Smarc #if BYTE_ORDER == LITTLE_ENDIAN 47629947Skarels c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1]; 47726279Skarels #else 47826279Skarels c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0]; 47926279Skarels #endif 48026279Skarels p->c_cf += sizeof (word_t); 48126279Skarels p->c_cc -= sizeof (word_t); 48217542Skarels if (p->c_cc <= 0) { 48335811Smarc bp = cbptr(p->c_cf-1); 48435811Smarc bp = cbptr((int)bp & ~CROUND); 48517542Skarels p->c_cf = NULL; 48617542Skarels p->c_cl = NULL; 48717542Skarels bp->c_next = cfreelist; 48817542Skarels cfreelist = bp; 48917542Skarels cfreecount += CBSIZE; 49017542Skarels if (cwaiting) { 49117542Skarels wakeup(&cwaiting); 49217542Skarels cwaiting = 0; 49317542Skarels } 49417542Skarels } else if (((int)p->c_cf & CROUND) == 0) { 49535811Smarc bp = cbptr(p->c_cf); 49617542Skarels bp--; 49717542Skarels p->c_cf = bp->c_next->c_info; 49817542Skarels bp->c_next = cfreelist; 49917542Skarels cfreelist = bp; 50017542Skarels cfreecount += CBSIZE; 50117542Skarels if (cwaiting) { 50217542Skarels wakeup(&cwaiting); 50317542Skarels cwaiting = 0; 50417542Skarels } 50517542Skarels } 50617542Skarels splx(s); 50717542Skarels return (c); 50832Sbill } 50932Sbill 51032Sbill putw(c, p) 5118955Sroot register struct clist *p; 51217542Skarels word_t c; 51332Sbill { 51452501Storek register int s; 51517542Skarels register struct cblock *bp; 51617542Skarels register char *cp; 51732Sbill 51817542Skarels s = spltty(); 51932Sbill if (cfreelist==NULL) { 52032Sbill splx(s); 52132Sbill return(-1); 52232Sbill } 52317542Skarels if (p->c_cc & 01) { 52433398Smckusick #if BYTE_ORDER == LITTLE_ENDIAN 52517542Skarels (void) putc(c, p); 52617542Skarels (void) putc(c>>8, p); 52726279Skarels #else 52826279Skarels (void) putc(c>>8, p); 52926279Skarels (void) putc(c, p); 53026279Skarels #endif 53117542Skarels } else { 53217542Skarels if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 53317542Skarels if ((bp = cfreelist) == NULL) { 53417542Skarels splx(s); 53517542Skarels return (-1); 53617542Skarels } 53717542Skarels cfreelist = bp->c_next; 53817542Skarels cfreecount -= CBSIZE; 53917542Skarels bp->c_next = NULL; 54017542Skarels p->c_cf = cp = bp->c_info; 54117542Skarels } else if (((int)cp & CROUND) == 0) { 54235811Smarc bp = cbptr(cp) - 1; 54317542Skarels if ((bp->c_next = cfreelist) == NULL) { 54417542Skarels splx(s); 54517542Skarels return (-1); 54617542Skarels } 54717542Skarels bp = bp->c_next; 54817542Skarels cfreelist = bp->c_next; 54917542Skarels cfreecount -= CBSIZE; 55017542Skarels bp->c_next = NULL; 55117542Skarels cp = bp->c_info; 55217542Skarels } 55326279Skarels #if defined(vax) 55417542Skarels *(word_t *)cp = c; 55526279Skarels #else 55626279Skarels ((u_char *)cp)[0] = c>>8; 55726279Skarels ((u_char *)cp)[1] = c; 55826279Skarels #endif 55926279Skarels p->c_cl = cp + sizeof (word_t); 56026279Skarels p->c_cc += sizeof (word_t); 56117542Skarels } 56232Sbill splx(s); 5639761Ssam return (0); 56432Sbill } 56560348Storek #endif /* unneeded */ 566