132Sbill #include "../h/param.h" 232Sbill #include "../h/systm.h" 332Sbill #include "../h/conf.h" 432Sbill #include "../h/buf.h" 5*1890Swnj #include "../h/tty.h" 632Sbill 732Sbill struct cblock { 8*1890Swnj struct cblock *c_next; 932Sbill char c_info[CBSIZE]; 1032Sbill }; 1132Sbill 12*1890Swnj struct cblock cfree[NCLIST]; 13*1890Swnj struct cblock *cfreelist; 1432Sbill 15*1890Swnj int cfreecount; 16*1890Swnj char cwaiting; 17*1890Swnj 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; 41*1890Swnj cfreecount += CBSIZE; 42*1890Swnj if (cwaiting) { 43*1890Swnj wakeup(&cwaiting); 44*1890Swnj cwaiting = 0; 45*1890Swnj } 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; 52*1890Swnj cfreecount += CBSIZE; 53*1890Swnj if (cwaiting) { 54*1890Swnj wakeup(&cwaiting); 55*1890Swnj cwaiting = 0; 56*1890Swnj } 5732Sbill } 5832Sbill } 5932Sbill splx(s); 6032Sbill return(c); 6132Sbill } 6232Sbill 63*1890Swnj #if HAVTR > 0 64*1890Swnj trgetc(p) 65*1890Swnj register struct clist *p; 66*1890Swnj { 67*1890Swnj register struct cblock *bp; 68*1890Swnj register int c, s; 69*1890Swnj 70*1890Swnj if (p->c_cc <= 0) { 71*1890Swnj c = -1; 72*1890Swnj p->c_cc = 0; 73*1890Swnj p->c_cf = NULL; 74*1890Swnj } else { 75*1890Swnj c = *p->c_cf++ & 0377; 76*1890Swnj if (--p->c_cc<=0) { 77*1890Swnj p->c_cf = NULL; 78*1890Swnj } else if (((int)p->c_cf & CROUND) == 0) { 79*1890Swnj bp = (struct cblock *)(p->c_cf); 80*1890Swnj bp--; 81*1890Swnj p->c_cf = bp->c_next->c_info; 82*1890Swnj } 83*1890Swnj } 84*1890Swnj return(c); 85*1890Swnj } 86*1890Swnj #endif 87*1890Swnj 8832Sbill /* 8932Sbill * copy clist to buffer. 9032Sbill * return number of bytes moved. 9132Sbill */ 9232Sbill q_to_b(q, cp, cc) 9332Sbill register struct clist *q; 9432Sbill register char *cp; 9532Sbill { 9632Sbill register struct cblock *bp; 9732Sbill register int s; 9832Sbill char *acp; 9932Sbill 10032Sbill if (cc <= 0) 10132Sbill return(0); 10232Sbill s = spl6(); 10332Sbill if (q->c_cc <= 0) { 10432Sbill q->c_cc = 0; 10532Sbill q->c_cf = q->c_cl = NULL; 106*1890Swnj splx(s); 10732Sbill return(0); 10832Sbill } 10932Sbill acp = cp; 11032Sbill cc++; 11132Sbill 11232Sbill while (--cc) { 11332Sbill *cp++ = *q->c_cf++; 11432Sbill if (--q->c_cc <= 0) { 11532Sbill bp = (struct cblock *)(q->c_cf-1); 11632Sbill bp = (struct cblock *)((int)bp & ~CROUND); 11732Sbill q->c_cf = q->c_cl = NULL; 11832Sbill bp->c_next = cfreelist; 11932Sbill cfreelist = bp; 120*1890Swnj cfreecount += CBSIZE; 121*1890Swnj if (cwaiting) { 122*1890Swnj wakeup(&cwaiting); 123*1890Swnj cwaiting = 0; 124*1890Swnj } 12532Sbill break; 12632Sbill } 12732Sbill if (((int)q->c_cf & CROUND) == 0) { 12832Sbill bp = (struct cblock *)(q->c_cf); 12932Sbill bp--; 13032Sbill q->c_cf = bp->c_next->c_info; 13132Sbill bp->c_next = cfreelist; 13232Sbill cfreelist = bp; 133*1890Swnj cfreecount += CBSIZE; 134*1890Swnj if (cwaiting) { 135*1890Swnj wakeup(&cwaiting); 136*1890Swnj cwaiting = 0; 137*1890Swnj } 13832Sbill } 13932Sbill } 14032Sbill splx(s); 14132Sbill return(cp-acp); 14232Sbill } 14332Sbill 144*1890Swnj #if HAVTR > 0 14532Sbill /* 146*1890Swnj * Traverse a clist copying its contents to a buffer. 147*1890Swnj * q->cc and q->cf are updated with the current position 148*1890Swnj * in the list, but bytes are not released to the freelist. 149*1890Swnj */ 150*1890Swnj trq_to_b(q, cp, cc) 151*1890Swnj register struct clist *q; 152*1890Swnj register char *cp; 153*1890Swnj register cc; 154*1890Swnj { 155*1890Swnj register struct cblock *bp; 156*1890Swnj char *acp; 157*1890Swnj 158*1890Swnj if (cc <= 0) 159*1890Swnj return(0); 160*1890Swnj if (q->c_cc <= 0) 161*1890Swnj return(0); 162*1890Swnj 163*1890Swnj acp = cp; 164*1890Swnj cc++; 165*1890Swnj while (--cc) { 166*1890Swnj *cp++ = *q->c_cf++; 167*1890Swnj if (((int)q->c_cf & CROUND) == 0) { 168*1890Swnj bp = (struct cblock *)(q->c_cf); 169*1890Swnj bp--; 170*1890Swnj q->c_cf = bp->c_next->c_info; 171*1890Swnj } 172*1890Swnj if (--q->c_cc <= 0) 173*1890Swnj break; 174*1890Swnj } 175*1890Swnj return(cp-acp); 176*1890Swnj } 177*1890Swnj #endif 178*1890Swnj 179*1890Swnj 180*1890Swnj /* 18132Sbill * Return count of contiguous characters 18232Sbill * in clist starting at q->c_cf. 18332Sbill * Stop counting if flag&character is non-null. 18432Sbill */ 18532Sbill ndqb(q, flag) 18632Sbill register struct clist *q; 18732Sbill { 18832Sbill register cc; 18932Sbill int s; 19032Sbill 19132Sbill s = spl6(); 19232Sbill if (q->c_cc <= 0) { 19332Sbill cc = -q->c_cc; 19432Sbill goto out; 19532Sbill } 19632Sbill cc = ((int)q->c_cf + CBSIZE) & ~CROUND; 19732Sbill cc -= (int)q->c_cf; 19832Sbill if (q->c_cc < cc) 19932Sbill cc = q->c_cc; 20032Sbill if (flag) { 20132Sbill register char *p, *end; 20232Sbill 20332Sbill p = q->c_cf; 20432Sbill end = p; 20532Sbill end += cc; 20632Sbill while (p < end) { 20732Sbill if (*p & flag) { 208*1890Swnj cc = (int)p; 209*1890Swnj cc -= (int)q->c_cf; 21032Sbill break; 21132Sbill } 21232Sbill p++; 21332Sbill } 21432Sbill } 21532Sbill out: 21632Sbill splx(s); 21732Sbill return(cc); 21832Sbill } 21932Sbill 220*1890Swnj 221*1890Swnj 22232Sbill /* 223*1890Swnj * Flush cc bytes from q. 22432Sbill */ 22532Sbill ndflush(q, cc) 22632Sbill register struct clist *q; 22732Sbill register cc; 22832Sbill { 229*1890Swnj register struct cblock *bp; 230*1890Swnj char *end; 231*1890Swnj int rem; 23232Sbill register s; 23332Sbill 23432Sbill s = spl6(); 23532Sbill if (q->c_cc < 0) { 236*1890Swnj printf("neg q flush\n"); 23732Sbill goto out; 23832Sbill } 23932Sbill if (q->c_cc == 0) { 24032Sbill goto out; 24132Sbill } 242*1890Swnj while (cc>0 && q->c_cc) { 243*1890Swnj bp = (struct cblock *)((int)q->c_cf & ~CROUND); 244*1890Swnj if ((int)bp == (((int)q->c_cl-1) & ~CROUND)) { 245*1890Swnj end = q->c_cl; 246*1890Swnj } else { 247*1890Swnj end = (char *)((int)bp + sizeof (struct cblock)); 248*1890Swnj } 249*1890Swnj rem = end - q->c_cf; 250*1890Swnj if (cc >= rem) { 251*1890Swnj cc -= rem; 252*1890Swnj q->c_cc -= rem; 25332Sbill q->c_cf = bp->c_next->c_info; 254*1890Swnj bp->c_next = cfreelist; 255*1890Swnj cfreelist = bp; 256*1890Swnj cfreecount += CBSIZE; 257*1890Swnj if (cwaiting) { 258*1890Swnj wakeup(&cwaiting); 259*1890Swnj cwaiting = 0; 260*1890Swnj } 26132Sbill } else { 262*1890Swnj q->c_cc -= cc; 263*1890Swnj q->c_cf += cc; 264*1890Swnj if (q->c_cc <= 0) { 265*1890Swnj bp->c_next = cfreelist; 266*1890Swnj cfreelist = bp; 267*1890Swnj cfreecount += CBSIZE; 268*1890Swnj if (cwaiting) { 269*1890Swnj wakeup(&cwaiting); 270*1890Swnj cwaiting = 0; 271*1890Swnj } 272*1890Swnj } 273*1890Swnj break; 27432Sbill } 275*1890Swnj } 276*1890Swnj if (q->c_cc <= 0) { 27732Sbill q->c_cf = q->c_cl = NULL; 278*1890Swnj q->c_cc = 0; 27932Sbill } 28032Sbill out: 28132Sbill splx(s); 28232Sbill } 283172Sbill 284*1890Swnj 28532Sbill putc(c, p) 28632Sbill register struct clist *p; 28732Sbill { 28832Sbill register struct cblock *bp; 28932Sbill register char *cp; 29032Sbill register s; 29132Sbill 29232Sbill s = spl6(); 29332Sbill if ((cp = p->c_cl) == NULL || p->c_cc < 0 ) { 29432Sbill if ((bp = cfreelist) == NULL) { 29532Sbill splx(s); 29632Sbill return(-1); 29732Sbill } 29832Sbill cfreelist = bp->c_next; 299*1890Swnj cfreecount -= CBSIZE; 30032Sbill bp->c_next = NULL; 30132Sbill p->c_cf = cp = bp->c_info; 30232Sbill } else if (((int)cp & CROUND) == 0) { 30332Sbill bp = (struct cblock *)cp - 1; 30432Sbill if ((bp->c_next = cfreelist) == NULL) { 30532Sbill splx(s); 30632Sbill return(-1); 30732Sbill } 30832Sbill bp = bp->c_next; 30932Sbill cfreelist = bp->c_next; 310*1890Swnj cfreecount -= CBSIZE; 31132Sbill bp->c_next = NULL; 31232Sbill cp = bp->c_info; 31332Sbill } 31432Sbill *cp++ = c; 31532Sbill p->c_cc++; 31632Sbill p->c_cl = cp; 31732Sbill splx(s); 31832Sbill return(0); 31932Sbill } 32032Sbill 321*1890Swnj 322*1890Swnj 32332Sbill /* 32432Sbill * copy buffer to clist. 32532Sbill * return number of bytes not transfered. 32632Sbill */ 32732Sbill b_to_q(cp, cc, q) 32832Sbill register char *cp; 32932Sbill struct clist *q; 33032Sbill register int cc; 33132Sbill { 33232Sbill register char *cq; 33332Sbill register struct cblock *bp; 33432Sbill register s, acc; 33532Sbill 33632Sbill if (cc <= 0) 33732Sbill return(0); 33832Sbill acc = cc; 339*1890Swnj 340*1890Swnj 34132Sbill s = spl6(); 34232Sbill if ((cq = q->c_cl) == NULL || q->c_cc < 0) { 34332Sbill if ((bp = cfreelist) == NULL) 34432Sbill goto out; 34532Sbill cfreelist = bp->c_next; 346*1890Swnj cfreecount -= CBSIZE; 34732Sbill bp->c_next = NULL; 34832Sbill q->c_cf = cq = bp->c_info; 34932Sbill } 35032Sbill 35132Sbill while (cc) { 35232Sbill if (((int)cq & CROUND) == 0) { 35332Sbill bp = (struct cblock *) cq - 1; 35432Sbill if ((bp->c_next = cfreelist) == NULL) 35532Sbill goto out; 35632Sbill bp = bp->c_next; 35732Sbill cfreelist = bp->c_next; 358*1890Swnj cfreecount -= CBSIZE; 35932Sbill bp->c_next = NULL; 36032Sbill cq = bp->c_info; 36132Sbill } 36232Sbill *cq++ = *cp++; 36332Sbill cc--; 36432Sbill } 36532Sbill out: 36632Sbill q->c_cl = cq; 36732Sbill q->c_cc += acc-cc; 36832Sbill splx(s); 36932Sbill return(cc); 37032Sbill } 37132Sbill 372*1890Swnj char * 373*1890Swnj wb_to_q(cp, cc, q) 374*1890Swnj register char *cp; 375*1890Swnj register struct clist *q; 376*1890Swnj register cc; 377*1890Swnj { 378*1890Swnj char *f; 379*1890Swnj register s; 380*1890Swnj 381*1890Swnj s = spl6(); 382*1890Swnj while (cc > cfreecount) { 383*1890Swnj cwaiting = 1; 384*1890Swnj sleep(&cwaiting, TTOPRI); 385*1890Swnj } 386*1890Swnj if (q->c_cc==0) { 387*1890Swnj b_to_q(cp, cc, q); 388*1890Swnj f = q->c_cf; 389*1890Swnj } else { 390*1890Swnj (void) putc(*cp++, q); 391*1890Swnj f = q->c_cl; 392*1890Swnj f--; 393*1890Swnj b_to_q(cp, --cc, q); 394*1890Swnj } 395*1890Swnj splx(s); 396*1890Swnj return(f); 397*1890Swnj } 398*1890Swnj 399*1890Swnj #ifdef notdef 400*1890Swnj char * 401*1890Swnj nb_to_q(cp, cc, q) 402*1890Swnj register char *cp; 403*1890Swnj register struct clist *q; 404*1890Swnj register cc; 405*1890Swnj { 406*1890Swnj char *f; 407*1890Swnj register s; 408*1890Swnj 409*1890Swnj s = spl6(); 410*1890Swnj if (cc > cfreecount) { 411*1890Swnj f = NULL; 412*1890Swnj goto out; 413*1890Swnj } 414*1890Swnj if (q->c_cc==0) { 415*1890Swnj b_to_q(cp, cc, q); 416*1890Swnj f = q->c_cf; 417*1890Swnj } else { 418*1890Swnj (void) putc(*cp++, q); 419*1890Swnj f = q->c_cl; 420*1890Swnj f--; 421*1890Swnj b_to_q(cp, --cc, q); 422*1890Swnj } 423*1890Swnj out: 424*1890Swnj splx(s); 425*1890Swnj return(f); 426*1890Swnj } 427*1890Swnj #endif 428*1890Swnj 42932Sbill /* 430172Sbill * Given a non-NULL pointter into the list (like c_cf which 431172Sbill * always points to a real character if non-NULL) return the pointer 432172Sbill * to the next character in the list or return NULL if no more chars. 433172Sbill * 434172Sbill * Callers must not allow getc's to happen between nextc's so that the 435172Sbill * pointer becomes invalid. Note that interrupts are NOT masked. 436172Sbill */ 437172Sbill char * 438172Sbill nextc(p, cp) 439172Sbill register struct clist *p; 440172Sbill register char *cp; 441172Sbill { 442172Sbill 443172Sbill if (p->c_cc && ++cp != p->c_cl) { 444172Sbill if (((int)cp & CROUND) == 0) 445172Sbill return (((struct cblock *)cp)[-1].c_next->c_info); 446172Sbill return (cp); 447172Sbill } 448172Sbill return (0); 449172Sbill } 450172Sbill 451172Sbill /* 452172Sbill * Remove the last character in the list and return it. 453172Sbill */ 454172Sbill unputc(p) 455172Sbill register struct clist *p; 456172Sbill { 457172Sbill register struct cblock *bp; 458172Sbill register int c, s; 459172Sbill struct cblock *obp; 460172Sbill 461172Sbill s = spl6(); 462172Sbill if (p->c_cc <= 0) 463172Sbill c = -1; 464172Sbill else { 465172Sbill c = *--p->c_cl; 466172Sbill if (--p->c_cc <= 0) { 467172Sbill bp = (struct cblock *)p->c_cl; 468172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 469172Sbill p->c_cl = p->c_cf = NULL; 470172Sbill bp->c_next = cfreelist; 471172Sbill cfreelist = bp; 472*1890Swnj cfreecount += CBSIZE; 473172Sbill } else if (((int)p->c_cl & CROUND) == sizeof(bp->c_next)) { 474172Sbill p->c_cl = (char *)((int)p->c_cl & ~CROUND); 475172Sbill bp = (struct cblock *)p->c_cf; 476172Sbill bp = (struct cblock *)((int)bp & ~CROUND); 477172Sbill while (bp->c_next != (struct cblock *)p->c_cl) 478172Sbill bp = bp->c_next; 479172Sbill obp = bp; 480172Sbill p->c_cl = (char *)(bp + 1); 481172Sbill bp = bp->c_next; 482172Sbill bp->c_next = cfreelist; 483172Sbill cfreelist = bp; 484*1890Swnj cfreecount += CBSIZE; 485172Sbill obp->c_next = NULL; 486172Sbill } 487172Sbill } 488172Sbill splx(s); 489172Sbill return (c); 490172Sbill } 491172Sbill 492172Sbill /* 493172Sbill * Put the chars in the from que 494172Sbill * on the end of the to que. 495172Sbill * 496172Sbill * SHOULD JUST USE q_to_b AND THEN b_to_q HERE. 497172Sbill */ 498172Sbill catq(from, to) 499172Sbill struct clist *from, *to; 500172Sbill { 501172Sbill register c; 502172Sbill 503172Sbill while ((c = getc(from)) >= 0) 504172Sbill (void) putc(c, to); 505172Sbill } 506172Sbill 507172Sbill /* 50832Sbill * Initialize clist by freeing all character blocks, then count 50932Sbill * number of character devices. (Once-only routine) 51032Sbill */ 51132Sbill cinit() 51232Sbill { 51332Sbill register int ccp; 51432Sbill register struct cblock *cp; 51532Sbill register struct cdevsw *cdp; 51632Sbill 51732Sbill ccp = (int)cfree; 51832Sbill ccp = (ccp+CROUND) & ~CROUND; 519*1890Swnj for(cp=(struct cblock *)ccp; cp < &cfree[NCLIST-1]; cp++) { 52032Sbill cp->c_next = cfreelist; 52132Sbill cfreelist = cp; 522*1890Swnj cfreecount += CBSIZE; 52332Sbill } 52432Sbill ccp = 0; 52532Sbill for(cdp = cdevsw; cdp->d_open; cdp++) 52632Sbill ccp++; 52732Sbill nchrdev = ccp; 52832Sbill } 52932Sbill 530*1890Swnj 53132Sbill /* 53232Sbill * integer (2-byte) get/put 53332Sbill * using clists 53432Sbill */ 53532Sbill getw(p) 53632Sbill register struct clist *p; 53732Sbill { 53832Sbill register int s; 53932Sbill 54032Sbill if (p->c_cc <= 1) 54132Sbill return(-1); 54232Sbill s = getc(p); 54332Sbill return(s | (getc(p)<<8)); 54432Sbill } 54532Sbill 546*1890Swnj #if HAVTR > 0 547*1890Swnj trgetw(p) 548*1890Swnj register struct clist *p; 549*1890Swnj { 550*1890Swnj register int w; 551*1890Swnj 552*1890Swnj if (p->c_cc <=1) 553*1890Swnj return(-1); 554*1890Swnj w = trgetc(p); 555*1890Swnj return(w | (trgetc(p)<<8)); 556*1890Swnj } 557*1890Swnj #endif 558*1890Swnj 55932Sbill putw(c, p) 56032Sbill register struct clist *p; 56132Sbill { 56232Sbill register s; 56332Sbill 56432Sbill s = spl6(); 56532Sbill if (cfreelist==NULL) { 56632Sbill splx(s); 56732Sbill return(-1); 56832Sbill } 569130Sbill (void) putc(c, p); 570130Sbill (void) putc(c>>8, p); 57132Sbill splx(s); 57232Sbill return(0); 57332Sbill } 574