#include "../h/local.h" #ifdef SCCS_ID static char SCCS_ID [] = "@(#)prim.c 3.3 01:53:18 - 81/12/10 "; #endif SCCS_ID #include "../h/param.h" #include "../h/tty.h" #include "../h/systm.h" #include "../h/conf.h" #include "../h/buf.h" #include "../h/clist.h" #define MIN(a,b) ((a) < (b) ? (a) : (b)) int cbad; /* * Character list get/put */ getc(p) register struct clist *p; { register struct cblock *bp; register int c, s; s = spl6(); if (p->c_cc <= 0) { c = -1; p->c_cc = 0; p->c_cf = p->c_cl = NULL; } else { c = *p->c_cf++ & 0377; if (--p->c_cc<=0) { bp = (struct cblock *)(p->c_cf-1); bp = (struct cblock *) ((int)bp & ~CROUND); p->c_cf = NULL; p->c_cl = NULL; bp->c_next = cfreelist; cfreelist = bp; } else if (((int)p->c_cf & CROUND) == 0){ bp = (struct cblock *)(p->c_cf); bp--; p->c_cf = bp->c_next->c_info; bp->c_next = cfreelist; cfreelist = bp; } } splx(s); return(c); } /* * copy clist to buffer. * return number of bytes moved. */ q_to_b(q, cp, cc) register struct clist *q; register char *cp; { register struct cblock *bp; register int s; char *acp; if (cc <= 0) return(0); s = spl6(); if (q->c_cc <= 0) { q->c_cc = 0; q->c_cf = q->c_cl = NULL; /* CGL BUG FIX...splx() was missing 17jun81 */ 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); q->c_cf = q->c_cl = NULL; bp->c_next = cfreelist; cfreelist = bp; break; } if (((int)q->c_cf & CROUND) == 0) { bp = (struct cblock *)(q->c_cf); bp--; q->c_cf = bp->c_next->c_info; bp->c_next = cfreelist; cfreelist = bp; } } splx(s); 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 cc; int s; s = spl6(); if (q->c_cc <= 0) { cc = -q->c_cc; goto out; } cc = ((int)q->c_cf + CBSIZE) & ~CROUND; cc -= (int)q->c_cf; if (q->c_cc < cc) cc = q->c_cc; if (flag) { register char *p, *end; p = q->c_cf; end = p; end += cc; while (p < end) { if (*p & flag) { cc = (int)p; cc -= (int)q->c_cf; break; } p++; } } out: splx(s); return(cc); } /* * Update clist to show that cc characters * were removed. It is assumed that cc < CBSIZE. */ ndflush(q, cc) register struct clist *q; register cc; { register s; 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) { goto out; } if (cc > CBSIZE || cc <= 0) { cbad++; 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) { q->c_cf = bp->c_next->c_info; } else { q->c_cf = q->c_cl = NULL; } 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; q->c_cf = q->c_cl = NULL; } out: splx(s); } putc(c, 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 ) { if ((bp = cfreelist) == NULL) { splx(s); return(-1); } cfreelist = bp->c_next; bp->c_next = NULL; p->c_cf = cp = bp->c_info; } else if (((int)cp & CROUND) == 0) { bp = (struct cblock *)cp - 1; if ((bp->c_next = cfreelist) == NULL) { splx(s); return(-1); } bp = bp->c_next; cfreelist = bp->c_next; bp->c_next = NULL; cp = bp->c_info; } *cp++ = c; p->c_cc++; p->c_cl = cp; splx(s); 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 int num; register char *cq; register struct cblock *bp; register int s; if (cc <= 0) return(0); while (cc > 0) { s = spl6(); if ((cq = q->c_cl) == NULL || q->c_cc < 0) { if ((bp = cfreelist) == NULL) { splx(s); break; } q->c_cf = cq = bp->c_info; goto middle; } if (((int)cq & CROUND) == 0) { bp = &((struct cblock *) cq)[-1]; if ((bp->c_next = cfreelist) == NULL) { splx(s); break; } bp = bp->c_next; cq = bp->c_info; middle: cfreelist = bp->c_next; bp->c_next = NULL; num = MIN (cc, CBSIZE); } else if ((num = (char *) ((int) &cq[CBSIZE] & ~CROUND) - cq) > cc) num = cc; bcopy ((caddr_t)cp, cq, num); q->c_cl = &cq[num]; q->c_cc += num; splx(s); cp += num; cc -= num; } return(cc); } /* * Initialize clist by freeing all character blocks, then count * number of character devices. (Once-only routine) * Align the table so that each clist block is on a ~CROUND boundary. */ cinit() { register int ccp; register struct cblock *cp; register struct cdevsw *cdp; ccp = (int)cfree; ccp = (ccp+CROUND) & ~CROUND; for(cp=(struct cblock *)ccp; cp <= &cfreeNCLIST[-1]; cp++) { cp->c_next = cfreelist; cfreelist = cp; } ccp = 0; for(cdp = cdevsw; cdp->d_open; cdp++) ccp++; nchrdev = ccp; } /* * integer (2-byte) get/put * using clists */ getw(p) register struct clist *p; { register int s; if (p->c_cc <= 1) return(-1); s = getc(p); #ifdef DEC return(s | (getc(p)<<8)); #else return((s<<8) | getc(p)); #endif } putw(c, p) register struct clist *p; { register s; s = spl6(); if (cfreelist==NULL) { splx(s); return(-1); } #ifdef DEC putc(c, p); putc(c>>8, p); #else putc(c>>8, p); putc(c, p); #endif splx(s); return(0); }