X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/11bd398ce9a985e5abb6a4ab86596517b0cce0de..7bf304e65beb1e282cd098ed53ab9f4999b78280:/usr/src/sys/kern/tty_subr.c diff --git a/usr/src/sys/kern/tty_subr.c b/usr/src/sys/kern/tty_subr.c index f193895c65..c6e3e07a91 100644 --- a/usr/src/sys/kern/tty_subr.c +++ b/usr/src/sys/kern/tty_subr.c @@ -1,52 +1,74 @@ -/* tty_subr.c 3.1 %H% */ +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + * + * @(#)tty_subr.c 7.4 (Berkeley) %G% + */ -#include "../h/param.h" -#include "../h/tty.h" -#include "../h/systm.h" -#include "../h/conf.h" -#include "../h/buf.h" +#include "param.h" +#include "systm.h" +#include "buf.h" +#include "ioctl.h" +#include "tty.h" +#include "clist.h" -struct cblock { - struct cblock *c_next; - char c_info[CBSIZE]; -}; +char cwaiting; -struct cblock cfree[NCLIST]; -struct cblock *cfreelist; +#define setquote(cp) \ + setbit(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \ + (int)(cp)&CROUND) +#define isquote(cp) \ + isset(((char *)((int)(cp)&~CROUND)+sizeof(struct cblock *)), \ + (int)(cp)&CROUND) +#define cbptr(x) ((struct cblock *)(x)) /* * Character list get/put */ getc(p) -register struct clist *p; + register struct clist *p; { register struct cblock *bp; register int c, s; - s = spl6(); + s = spltty(); if (p->c_cc <= 0) { c = -1; p->c_cc = 0; p->c_cf = p->c_cl = NULL; } else { - c = *p->c_cf++ & 0377; + c = *p->c_cf & 0377; + if (isquote(p->c_cf)) + c |= TTY_QUOTE; + p->c_cf++; if (--p->c_cc<=0) { - bp = (struct cblock *)(p->c_cf-1); - bp = (struct cblock *) ((int)bp & ~CROUND); + bp = cbptr(p->c_cf-1); + bp = cbptr((int)bp & ~CROUND); p->c_cf = NULL; p->c_cl = NULL; bp->c_next = cfreelist; cfreelist = bp; + cfreecount += CBSIZE; + if (cwaiting) { + wakeup(&cwaiting); + cwaiting = 0; + } } else if (((int)p->c_cf & CROUND) == 0){ - bp = (struct cblock *)(p->c_cf); + bp = cbptr(p->c_cf); bp--; p->c_cf = bp->c_next->c_info; bp->c_next = cfreelist; cfreelist = bp; + cfreecount += CBSIZE; + if (cwaiting) { + wakeup(&cwaiting); + cwaiting = 0; + } } } splx(s); - return(c); + return (c); } /* @@ -54,59 +76,76 @@ register struct clist *p; * return number of bytes moved. */ q_to_b(q, cp, cc) -register struct clist *q; -register char *cp; + register struct clist *q; + register char *cp; { register struct cblock *bp; register int s; + register nc; char *acp; if (cc <= 0) - return(0); - s = spl6(); + return (0); + s = spltty(); if (q->c_cc <= 0) { q->c_cc = 0; q->c_cf = q->c_cl = NULL; - return(0); + splx(s); + return (0); } acp = cp; - cc++; - while (--cc) { - *cp++ = *q->c_cf++; - if (--q->c_cc <= 0) { - bp = (struct cblock *)(q->c_cf-1); - bp = (struct cblock *)((int)bp & ~CROUND); + while (cc) { + nc = sizeof (struct cblock) - ((int)q->c_cf & CROUND); + nc = MIN(nc, cc); + nc = MIN(nc, q->c_cc); + (void) bcopy(q->c_cf, cp, (unsigned)nc); + q->c_cf += nc; + q->c_cc -= nc; + cc -= nc; + cp += nc; + if (q->c_cc <= 0) { + bp = cbptr(q->c_cf - 1); + bp = cbptr((int)bp & ~CROUND); q->c_cf = q->c_cl = NULL; bp->c_next = cfreelist; cfreelist = bp; + cfreecount += CBSIZE; + if (cwaiting) { + wakeup(&cwaiting); + cwaiting = 0; + } break; } if (((int)q->c_cf & CROUND) == 0) { - bp = (struct cblock *)(q->c_cf); + bp = cbptr(q->c_cf); bp--; q->c_cf = bp->c_next->c_info; bp->c_next = cfreelist; cfreelist = bp; + cfreecount += CBSIZE; + if (cwaiting) { + wakeup(&cwaiting); + cwaiting = 0; + } } } splx(s); - return(cp-acp); + return (cp-acp); } - /* * Return count of contiguous characters * in clist starting at q->c_cf. * Stop counting if flag&character is non-null. */ ndqb(q, flag) -register struct clist *q; + register struct clist *q; { -register cc; -int s; + register cc; + int s; - s = spl6(); + s = spltty(); if (q->c_cc <= 0) { cc = -q->c_cc; goto out; @@ -123,7 +162,8 @@ int s; end += cc; while (p < end) { if (*p & flag) { - cc = (int)p - (int)q->c_cf; + cc = (int)p; + cc -= (int)q->c_cf; break; } p++; @@ -131,193 +171,374 @@ int s; } out: splx(s); - return(cc); + return (cc); } - - /* - * Update clist to show that cc characters - * were removed. It is assumed that cc < CBSIZE. + * Flush cc bytes from q. */ ndflush(q, cc) -register struct clist *q; -register cc; + register struct clist *q; + register cc; { -register s; + register struct cblock *bp; + char *end; + int rem, s; - if (cc == 0) - return; - s = spl6(); - if (q->c_cc < 0) { - if (q->c_cf != NULL) { - q->c_cc += cc; - q->c_cf += cc; - goto out; - } - q->c_cc = 0; - goto out; - } - if (q->c_cc == 0) { + s = spltty(); + if (q->c_cc <= 0) goto out; - } - q->c_cc -= cc; - q->c_cf += cc; - if (((int)q->c_cf & CROUND) == 0) { - register struct cblock *bp; - - bp = (struct cblock *)(q->c_cf) -1; - if (bp->c_next) { + while (cc>0 && q->c_cc) { + bp = cbptr((int)q->c_cf & ~CROUND); + if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { + end = q->c_cl; + } else { + end = (char *)((int)bp + sizeof (struct cblock)); + } + rem = end - q->c_cf; + if (cc >= rem) { + cc -= rem; + q->c_cc -= rem; q->c_cf = bp->c_next->c_info; + bp->c_next = cfreelist; + cfreelist = bp; + cfreecount += CBSIZE; + if (cwaiting) { + wakeup(&cwaiting); + cwaiting = 0; + } } else { - q->c_cf = q->c_cl = NULL; + q->c_cc -= cc; + q->c_cf += cc; + if (q->c_cc <= 0) { + bp->c_next = cfreelist; + cfreelist = bp; + cfreecount += CBSIZE; + if (cwaiting) { + wakeup(&cwaiting); + cwaiting = 0; + } + } + break; } - bp->c_next = cfreelist; - cfreelist = bp; - } else - if (q->c_cc == 0) { - register struct cblock *bp; - q->c_cf = (char *)((int)q->c_cf & ~CROUND); - bp = (struct cblock *)(q->c_cf); - bp->c_next = cfreelist; - cfreelist = bp; + } + if (q->c_cc <= 0) { q->c_cf = q->c_cl = NULL; + q->c_cc = 0; } out: splx(s); } + + putc(c, p) -register struct clist *p; + register struct clist *p; { register struct cblock *bp; register char *cp; register s; - s = spl6(); - if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { + s = spltty(); + if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { /* no cblocks yet */ if ((bp = cfreelist) == NULL) { splx(s); - return(-1); + return (-1); } cfreelist = bp->c_next; + cfreecount -= CBSIZE; bp->c_next = NULL; + bzero(bp->c_quote, CBQSIZE); p->c_cf = cp = bp->c_info; } else if (((int)cp & CROUND) == 0) { - bp = (struct cblock *)cp - 1; + bp = cbptr(cp) - 1; /* pointer arith */ if ((bp->c_next = cfreelist) == NULL) { splx(s); - return(-1); + return (-1); } bp = bp->c_next; cfreelist = bp->c_next; + cfreecount -= CBSIZE; bp->c_next = NULL; cp = bp->c_info; } + if (c&TTY_QUOTE) + setquote(cp); *cp++ = c; p->c_cc++; p->c_cl = cp; splx(s); - return(0); + return (0); } - - /* * copy buffer to clist. * return number of bytes not transfered. */ b_to_q(cp, cc, q) -register char *cp; -struct clist *q; -register int cc; + register char *cp; + struct clist *q; + register int cc; { register char *cq; register struct cblock *bp; - register s, acc; + register s, nc; + int acc; if (cc <= 0) - return(0); + return (0); acc = cc; - s = spl6(); + s = spltty(); if ((cq = q->c_cl) == NULL || q->c_cc < 0) { if ((bp = cfreelist) == NULL) goto out; cfreelist = bp->c_next; + cfreecount -= CBSIZE; + bzero(bp->c_quote, CBQSIZE); bp->c_next = NULL; q->c_cf = cq = bp->c_info; } while (cc) { if (((int)cq & CROUND) == 0) { - bp = (struct cblock *) cq - 1; + bp = cbptr(cq) - 1; if ((bp->c_next = cfreelist) == NULL) goto out; bp = bp->c_next; cfreelist = bp->c_next; + cfreecount -= CBSIZE; + bzero(bp->c_quote, CBQSIZE); bp->c_next = NULL; cq = bp->c_info; } - *cq++ = *cp++; - cc--; + nc = MIN(cc, sizeof (struct cblock) - ((int)cq & CROUND)); + (void) bcopy(cp, cq, (unsigned)nc); + cp += nc; + cq += nc; + cc -= nc; } out: q->c_cl = cq; - q->c_cc += acc-cc; + q->c_cc += acc - cc; splx(s); - return(cc); + return (cc); +} + +/* + * Given a non-NULL pointter into the list (like c_cf which + * always points to a real character if non-NULL) return the pointer + * to the next character in the list or return NULL if no more chars. + * + * Callers must not allow getc's to happen between nextc's so that the + * pointer becomes invalid. Note that interrupts are NOT masked. + */ +char * +nextc(p, cp, c) + register struct clist *p; + register char *cp; + register int *c; +{ + + if (p->c_cc && ++cp != p->c_cl) { + if (((int)cp & CROUND) == 0) { + cp = (cbptr(cp))[-1].c_next->c_info; + } + *c = *cp; + if (isquote(cp)) + *c |= TTY_QUOTE; + return (cp); + } + return (0); } /* - * Initialize clist by freeing all character blocks, then count - * number of character devices. (Once-only routine) + * Remove the last character in the list and return it. */ -cinit() +unputc(p) + register struct clist *p; { - register int ccp; - register struct cblock *cp; - register struct cdevsw *cdp; + register struct cblock *bp; + register int c, s; + struct cblock *obp; + register int first = 1; - ccp = (int)cfree; - ccp = (ccp+CROUND) & ~CROUND; - for(cp=(struct cblock *)ccp; cp <= &cfree[NCLIST-1]; cp++) { - cp->c_next = cfreelist; - cfreelist = cp; + s = spltty(); + if (p->c_cc <= 0) + c = -1; + else { + c = *--p->c_cl; + if (isquote(p->c_cl)) + c |= TTY_QUOTE; + if (--p->c_cc <= 0) { + bp = cbptr(p->c_cl); + bp = cbptr((int)bp & ~CROUND); + p->c_cl = p->c_cf = NULL; + bp->c_next = cfreelist; + cfreelist = bp; + cfreecount += CBSIZE; + } else if (p->c_cl == (cbptr((int)p->c_cl & ~CROUND))->c_info) { + p->c_cl = (char *)((int)p->c_cl & ~CROUND); + + bp = cbptr(p->c_cf); + bp = cbptr((int)bp & ~CROUND); + while (bp->c_next != cbptr(p->c_cl)) + bp = bp->c_next; + obp = bp; + p->c_cl = (char *)(bp + 1); + bp = bp->c_next; + bp->c_next = cfreelist; + cfreelist = bp; + cfreecount += CBSIZE; + obp->c_next = NULL; + } } - ccp = 0; - for(cdp = cdevsw; cdp->d_open; cdp++) - ccp++; - nchrdev = ccp; + splx(s); + return (c); } /* - * integer (2-byte) get/put - * using clists + * Put the chars in the from que + * on the end of the to que. */ +catq(from, to) + struct clist *from, *to; +{ +#ifdef notdef + char bbuf[CBSIZE*4]; +#endif + register s, c; + + s = spltty(); + if (to->c_cc == 0) { + *to = *from; + from->c_cc = 0; + from->c_cf = NULL; + from->c_cl = NULL; + splx(s); + return; + } + splx(s); +#ifdef notdef + while (from->c_cc > 0) { + c = q_to_b(from, bbuf, sizeof bbuf); + (void) b_to_q(bbuf, c, to); + } +#endif + /* XXX - FIX */ + while ((c = getc(from)) >= 0) + putc(c, to); +} + +#ifdef unneeded /* + * Integer (short) get/put using clists. + */ +typedef u_short word_t; + getw(p) -register struct clist *p; + register struct clist *p; { - register int s; + register int s, c; + register struct cblock *bp; if (p->c_cc <= 1) return(-1); - s = getc(p); - return(s | (getc(p)<<8)); + if (p->c_cc & 01) { + c = getc(p); +#if BYTE_ORDER == LITTLE_ENDIAN + return (c | (getc(p)<<8)); +#else + return (getc(p) | (c<<8)); +#endif + } + s = spltty(); +#if BYTE_ORDER == LITTLE_ENDIAN + c = (((u_char *)p->c_cf)[0] << 8) | ((u_char *)p->c_cf)[1]; +#else + c = (((u_char *)p->c_cf)[1] << 8) | ((u_char *)p->c_cf)[0]; +#endif + p->c_cf += sizeof (word_t); + p->c_cc -= sizeof (word_t); + if (p->c_cc <= 0) { + bp = cbptr(p->c_cf-1); + bp = cbptr((int)bp & ~CROUND); + p->c_cf = NULL; + p->c_cl = NULL; + bp->c_next = cfreelist; + cfreelist = bp; + cfreecount += CBSIZE; + if (cwaiting) { + wakeup(&cwaiting); + cwaiting = 0; + } + } else if (((int)p->c_cf & CROUND) == 0) { + bp = cbptr(p->c_cf); + bp--; + p->c_cf = bp->c_next->c_info; + bp->c_next = cfreelist; + cfreelist = bp; + cfreecount += CBSIZE; + if (cwaiting) { + wakeup(&cwaiting); + cwaiting = 0; + } + } + splx(s); + return (c); } -*/ putw(c, p) -register struct clist *p; + register struct clist *p; + word_t c; { register s; + register struct cblock *bp; + register char *cp; - s = spl6(); + s = spltty(); if (cfreelist==NULL) { splx(s); return(-1); } - VOID putc(c, p); - VOID putc(c>>8, p); + if (p->c_cc & 01) { +#if BYTE_ORDER == LITTLE_ENDIAN + (void) putc(c, p); + (void) putc(c>>8, p); +#else + (void) putc(c>>8, p); + (void) putc(c, p); +#endif + } else { + if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { + if ((bp = cfreelist) == NULL) { + splx(s); + return (-1); + } + cfreelist = bp->c_next; + cfreecount -= CBSIZE; + bp->c_next = NULL; + p->c_cf = cp = bp->c_info; + } else if (((int)cp & CROUND) == 0) { + bp = cbptr(cp) - 1; + if ((bp->c_next = cfreelist) == NULL) { + splx(s); + return (-1); + } + bp = bp->c_next; + cfreelist = bp->c_next; + cfreecount -= CBSIZE; + bp->c_next = NULL; + cp = bp->c_info; + } +#if defined(vax) + *(word_t *)cp = c; +#else + ((u_char *)cp)[0] = c>>8; + ((u_char *)cp)[1] = c; +#endif + p->c_cl = cp + sizeof (word_t); + p->c_cc += sizeof (word_t); + } splx(s); - return(0); + return (0); } +#endif unneeded