1*172Sbill /* tty_subr.c 3.3 10/14/12 */ 232Sbill 332Sbill #include "../h/param.h" 432Sbill #include "../h/tty.h" 532Sbill #include "../h/systm.h" 632Sbill #include "../h/conf.h" 732Sbill #include "../h/buf.h" 832Sbill 932Sbill struct cblock { 1032Sbill struct cblock *c_next; 1132Sbill char c_info[CBSIZE]; 1232Sbill }; 1332Sbill 1432Sbill struct cblock cfree[NCLIST]; 15*172Sbill int cbad; 1632Sbill struct cblock *cfreelist; 1732Sbill 1832Sbill /* 1932Sbill * Character list get/put 2032Sbill */ 2132Sbill getc(p) 2232Sbill register struct clist *p; 2332Sbill { 2432Sbill register struct cblock *bp; 2532Sbill register int c, s; 2632Sbill 2732Sbill s = spl6(); 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; 4132Sbill } else if (((int)p->c_cf & CROUND) == 0){ 4232Sbill bp = (struct cblock *)(p->c_cf); 4332Sbill bp--; 4432Sbill p->c_cf = bp->c_next->c_info; 4532Sbill bp->c_next = cfreelist; 4632Sbill cfreelist = bp; 4732Sbill } 4832Sbill } 4932Sbill splx(s); 5032Sbill return(c); 5132Sbill } 5232Sbill 5332Sbill /* 5432Sbill * copy clist to buffer. 5532Sbill * return number of bytes moved. 5632Sbill */ 5732Sbill q_to_b(q, cp, cc) 5832Sbill register struct clist *q; 5932Sbill register char *cp; 6032Sbill { 6132Sbill register struct cblock *bp; 6232Sbill register int s; 6332Sbill char *acp; 6432Sbill 6532Sbill if (cc <= 0) 6632Sbill return(0); 6732Sbill s = spl6(); 6832Sbill if (q->c_cc <= 0) { 6932Sbill q->c_cc = 0; 7032Sbill q->c_cf = q->c_cl = NULL; 7132Sbill return(0); 7232Sbill } 7332Sbill acp = cp; 7432Sbill cc++; 7532Sbill 7632Sbill while (--cc) { 7732Sbill *cp++ = *q->c_cf++; 7832Sbill if (--q->c_cc <= 0) { 7932Sbill bp = (struct cblock *)(q->c_cf-1); 8032Sbill bp = (struct cblock *)((int)bp & ~CROUND); 8132Sbill q->c_cf = q->c_cl = NULL; 8232Sbill bp->c_next = cfreelist; 8332Sbill cfreelist = bp; 8432Sbill break; 8532Sbill } 8632Sbill if (((int)q->c_cf & CROUND) == 0) { 8732Sbill bp = (struct cblock *)(q->c_cf); 8832Sbill bp--; 8932Sbill q->c_cf = bp->c_next->c_info; 9032Sbill bp->c_next = cfreelist; 9132Sbill cfreelist = bp; 9232Sbill } 9332Sbill } 9432Sbill splx(s); 9532Sbill return(cp-acp); 9632Sbill } 9732Sbill 9832Sbill /* 9932Sbill * Return count of contiguous characters 10032Sbill * in clist starting at q->c_cf. 10132Sbill * Stop counting if flag&character is non-null. 10232Sbill */ 10332Sbill ndqb(q, flag) 10432Sbill register struct clist *q; 10532Sbill { 10632Sbill register cc; 10732Sbill int s; 10832Sbill 10932Sbill s = spl6(); 11032Sbill if (q->c_cc <= 0) { 11132Sbill cc = -q->c_cc; 11232Sbill goto out; 11332Sbill } 11432Sbill cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 11532Sbill cc -= (int)q->c_cf; 11632Sbill if (q->c_cc < cc) 11732Sbill cc = q->c_cc; 11832Sbill if (flag) { 11932Sbill register char *p, *end; 12032Sbill 12132Sbill p = q->c_cf; 12232Sbill end = p; 12332Sbill end += cc; 12432Sbill while (p < end) { 12532Sbill if (*p & flag) { 12632Sbill cc = (int)p - (int)q->c_cf; 12732Sbill break; 12832Sbill } 12932Sbill p++; 13032Sbill } 13132Sbill } 13232Sbill out: 13332Sbill splx(s); 13432Sbill return(cc); 13532Sbill } 13632Sbill 13732Sbill /* 13832Sbill * Update clist to show that cc characters 13932Sbill * were removed. It is assumed that cc < CBSIZE. 14032Sbill */ 14132Sbill ndflush(q, cc) 14232Sbill register struct clist *q; 14332Sbill register cc; 14432Sbill { 14532Sbill register s; 14632Sbill 14732Sbill if (cc == 0) 14832Sbill return; 14932Sbill s = spl6(); 15032Sbill if (q->c_cc < 0) { 15132Sbill if (q->c_cf != NULL) { 15232Sbill q->c_cc += cc; 15332Sbill q->c_cf += cc; 15432Sbill goto out; 15532Sbill } 15632Sbill q->c_cc = 0; 15732Sbill goto out; 15832Sbill } 15932Sbill if (q->c_cc == 0) { 16032Sbill goto out; 16132Sbill } 162*172Sbill if (cc > CBSIZE || cc <= 0) { 163*172Sbill cbad++; 164*172Sbill goto out; 165*172Sbill } 16632Sbill q->c_cc -= cc; 16732Sbill q->c_cf += cc; 16832Sbill if (((int)q->c_cf & CROUND) == 0) { 16932Sbill register struct cblock *bp; 17032Sbill 17132Sbill bp = (struct cblock *)(q->c_cf) -1; 17232Sbill if (bp->c_next) { 17332Sbill q->c_cf = bp->c_next->c_info; 17432Sbill } else { 17532Sbill q->c_cf = q->c_cl = NULL; 17632Sbill } 17732Sbill bp->c_next = cfreelist; 17832Sbill cfreelist = bp; 17932Sbill } else 18032Sbill if (q->c_cc == 0) { 18132Sbill register struct cblock *bp; 18232Sbill q->c_cf = (char *)((int)q->c_cf & ~CROUND); 18332Sbill bp = (struct cblock *)(q->c_cf); 18432Sbill bp->c_next = cfreelist; 18532Sbill cfreelist = bp; 18632Sbill q->c_cf = q->c_cl = NULL; 18732Sbill } 18832Sbill out: 18932Sbill splx(s); 19032Sbill } 191*172Sbill 192*172Sbill /* 193*172Sbill * Put character c in queue p. 194*172Sbill */ 19532Sbill putc(c, p) 19632Sbill register struct clist *p; 19732Sbill { 19832Sbill register struct cblock *bp; 19932Sbill register char *cp; 20032Sbill register s; 20132Sbill 20232Sbill s = spl6(); 20332Sbill if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 20432Sbill if ((bp = cfreelist) == NULL) { 20532Sbill splx(s); 20632Sbill return(-1); 20732Sbill } 20832Sbill cfreelist = bp->c_next; 20932Sbill bp->c_next = NULL; 21032Sbill p->c_cf = cp = bp->c_info; 21132Sbill } else if (((int)cp & CROUND) == 0) { 21232Sbill bp = (struct cblock *)cp - 1; 21332Sbill if ((bp->c_next = cfreelist) == NULL) { 21432Sbill splx(s); 21532Sbill return(-1); 21632Sbill } 21732Sbill bp = bp->c_next; 21832Sbill cfreelist = bp->c_next; 21932Sbill bp->c_next = NULL; 22032Sbill cp = bp->c_info; 22132Sbill } 22232Sbill *cp++ = c; 22332Sbill p->c_cc++; 22432Sbill p->c_cl = cp; 22532Sbill splx(s); 22632Sbill return(0); 22732Sbill } 22832Sbill 22932Sbill /* 23032Sbill * copy buffer to clist. 23132Sbill * return number of bytes not transfered. 23232Sbill */ 23332Sbill b_to_q(cp, cc, q) 23432Sbill register char *cp; 23532Sbill struct clist *q; 23632Sbill register int cc; 23732Sbill { 23832Sbill register char *cq; 23932Sbill register struct cblock *bp; 24032Sbill register s, acc; 24132Sbill 24232Sbill if (cc <= 0) 24332Sbill return(0); 24432Sbill acc = cc; 24532Sbill s = spl6(); 24632Sbill if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 24732Sbill if ((bp = cfreelist) == NULL) 24832Sbill goto out; 24932Sbill cfreelist = bp->c_next; 25032Sbill bp->c_next = NULL; 25132Sbill q->c_cf = cq = bp->c_info; 25232Sbill } 25332Sbill 25432Sbill while (cc) { 25532Sbill if (((int)cq & CROUND) == 0) { 25632Sbill bp = (struct cblock *) cq - 1; 25732Sbill if ((bp->c_next = cfreelist) == NULL) 25832Sbill goto out; 25932Sbill bp = bp->c_next; 26032Sbill cfreelist = bp->c_next; 26132Sbill bp->c_next = NULL; 26232Sbill cq = bp->c_info; 26332Sbill } 26432Sbill *cq++ = *cp++; 26532Sbill cc--; 26632Sbill } 26732Sbill out: 26832Sbill q->c_cl = cq; 26932Sbill q->c_cc += acc-cc; 27032Sbill splx(s); 27132Sbill return(cc); 27232Sbill } 27332Sbill 27432Sbill /* 275*172Sbill * Given a non-NULL pointter into the list (like c_cf which 276*172Sbill * always points to a real character if non-NULL) return the pointer 277*172Sbill * to the next character in the list or return NULL if no more chars. 278*172Sbill * 279*172Sbill * Callers must not allow getc's to happen between nextc's so that the 280*172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 281*172Sbill */ 282*172Sbill char * 283*172Sbill nextc(p, cp) 284*172Sbill register struct clist *p; 285*172Sbill register char *cp; 286*172Sbill { 287*172Sbill 288*172Sbill if (p->c_cc && ++cp != p->c_cl) { 289*172Sbill if (((int)cp & CROUND) == 0) 290*172Sbill return (((struct cblock *)cp)[-1].c_next->c_info); 291*172Sbill return (cp); 292*172Sbill } 293*172Sbill return (0); 294*172Sbill } 295*172Sbill 296*172Sbill /* 297*172Sbill * Remove the last character in the list and return it. 298*172Sbill */ 299*172Sbill unputc(p) 300*172Sbill register struct clist *p; 301*172Sbill { 302*172Sbill register struct cblock *bp; 303*172Sbill register int c, s; 304*172Sbill struct cblock *obp; 305*172Sbill 306*172Sbill s = spl6(); 307*172Sbill if (p->c_cc <= 0) 308*172Sbill c = -1; 309*172Sbill else { 310*172Sbill c = *--p->c_cl; 311*172Sbill if (--p->c_cc <= 0) { 312*172Sbill bp = (struct cblock *)p->c_cl; 313*172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 314*172Sbill p->c_cl = p->c_cf = NULL; 315*172Sbill bp->c_next = cfreelist; 316*172Sbill cfreelist = bp; 317*172Sbill } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 318*172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 319*172Sbill bp = (struct cblock *)p->c_cf; 320*172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 321*172Sbill while (bp->c_next != (struct cblock *)p->c_cl) 322*172Sbill bp = bp->c_next; 323*172Sbill obp = bp; 324*172Sbill p->c_cl = (char *)(bp + 1); 325*172Sbill bp = bp->c_next; 326*172Sbill bp->c_next = cfreelist; 327*172Sbill cfreelist = bp; 328*172Sbill obp->c_next = NULL; 329*172Sbill } 330*172Sbill } 331*172Sbill splx(s); 332*172Sbill return (c); 333*172Sbill } 334*172Sbill 335*172Sbill /* 336*172Sbill * Put the chars in the from que 337*172Sbill * on the end of the to que. 338*172Sbill * 339*172Sbill * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. 340*172Sbill */ 341*172Sbill catq(from, to) 342*172Sbill struct clist *from, *to; 343*172Sbill { 344*172Sbill register c; 345*172Sbill 346*172Sbill while ((c = getc(from)) >= 0) 347*172Sbill (void) putc(c, to); 348*172Sbill } 349*172Sbill 350*172Sbill /* 35132Sbill * Initialize clist by freeing all character blocks, then count 35232Sbill * number of character devices. (Once-only routine) 35332Sbill */ 35432Sbill cinit() 35532Sbill { 35632Sbill register int ccp; 35732Sbill register struct cblock *cp; 35832Sbill register struct cdevsw *cdp; 35932Sbill 36032Sbill ccp = (int)cfree; 36132Sbill ccp = (ccp+CROUND) & ~CROUND; 36232Sbill for(cp=(struct cblock *)ccp; cp <= &cfree[NCLIST-1]; cp++) { 36332Sbill cp->c_next = cfreelist; 36432Sbill cfreelist = cp; 36532Sbill } 36632Sbill ccp = 0; 36732Sbill for(cdp = cdevsw; cdp->d_open; cdp++) 36832Sbill ccp++; 36932Sbill nchrdev = ccp; 37032Sbill } 37132Sbill 37232Sbill /* 37332Sbill * integer (2-byte) get/put 37432Sbill * using clists 37532Sbill */ 37632Sbill /* 37732Sbill getw(p) 37832Sbill register struct clist *p; 37932Sbill { 38032Sbill register int s; 38132Sbill 38232Sbill if (p->c_cc <= 1) 38332Sbill return(-1); 38432Sbill s = getc(p); 38532Sbill return(s | (getc(p)<<8)); 38632Sbill } 38732Sbill */ 38832Sbill 38932Sbill putw(c, p) 39032Sbill register struct clist *p; 39132Sbill { 39232Sbill register s; 39332Sbill 39432Sbill s = spl6(); 39532Sbill if (cfreelist==NULL) { 39632Sbill splx(s); 39732Sbill return(-1); 39832Sbill } 399130Sbill (void) putc(c, p); 400130Sbill (void) putc(c>>8, p); 40132Sbill splx(s); 40232Sbill return(0); 40332Sbill } 404