|
|
1.1 ! root 1: /* ! 2: * New Datakit protocol ! 3: */ ! 4: ! 5: #include "../h/param.h" ! 6: #include "../h/stream.h" ! 7: #include "../h/conf.h" ! 8: #include "../h/ioctl.h" ! 9: #include "../h/dkstat.h" ! 10: #include "../h/ttyld.h" ! 11: #include "dkp.h" ! 12: ! 13: #if NDKP>0 ! 14: #ifdef CAREFUL ! 15: #define TRC(c) *dkptrp++ = c; if (dkptrp>=&dkptrb[1024]) dkptrp=dkptrb ! 16: char dkptrb[1024]; char *dkptrp = dkptrb; ! 17: #else ! 18: #define TRC(c) ! 19: #endif ! 20: ! 21: struct dkp { ! 22: struct queue *rdq; /* associated read queue */ ! 23: struct block *inp; /* msg being collected */ ! 24: struct block *inpe; /* end of msg */ ! 25: short state; /* flags */ ! 26: short trx; /* # bytes in trailer being collected */ ! 27: short indata; /* # bytes in message being collected */ ! 28: u_char iseq; /* last good input sequence number */ ! 29: u_char lastecho; /* last echo/rej sent */ ! 30: char WS; /* first non-consumed message */ ! 31: char WACK; /* first non-acknowledged message */ ! 32: char WNX; /* next message to be sent */ ! 33: u_char XW; /* size of xmit window */ ! 34: u_char timer; /* timeout for xmit */ ! 35: u_char outcnt; /* count output chars for char mode */ ! 36: u_char trbuf[3]; /* trailer being collected */ ! 37: struct block *xb[8]; /* the xmit window buffer */ ! 38: }; ! 39: ! 40: extern struct dkstat dkstat; ! 41: ! 42: /* ! 43: * Protocol control bytes ! 44: */ ! 45: #define SEQ 0010 /* sequence number, ends trailers */ ! 46: #undef ECHO ! 47: #define ECHO 0020 /* echos, data given to next queue */ ! 48: #define REJ 0030 /* rejections, transmission error */ ! 49: #define ACK 0040 /* acknowledgments */ ! 50: #define BOT 0050 /* beginning of trailer */ ! 51: #define BOTM 0051 /* beginning of trailer, more data follows */ ! 52: #define BOTS 0052 /* seq update algorithm on this trailer */ ! 53: #define SOU 0053 /* start of unsequenced trailer */ ! 54: #define EOU 0054 /* end of unsequenced trailer */ ! 55: #define ENQ 0055 /* xmitter requests flow/error status */ ! 56: #define CHECK 0056 /* xmitter requests error status */ ! 57: #define INITREQ 0057 /* request initialization */ ! 58: #define INIT0 0060 /* disable trailer processing */ ! 59: #define INIT1 0061 /* enable trailer procesing */ ! 60: #define AINIT 0062 /* response to INIT0/INIT1 */ ! 61: #undef DELAY ! 62: #define DELAY 0100 /* real-time printing delay */ ! 63: #define BREAK 0110 /* Send/receive break (new style) */ ! 64: ! 65: #define OPEN 01 ! 66: #define LCLOSE 02 ! 67: #define RCLOSE 04 ! 68: #define XCHARMODE 010 ! 69: #define OPENING 020 ! 70: #define RJING 040 ! 71: #define STOPPED 0100 ! 72: #define RCHARMODE 0200 ! 73: ! 74: #define DKPPRI 28 ! 75: #define DKPTIME 2 ! 76: ! 77: struct dkp dkp[NDKP]; ! 78: ! 79: int dkpiput(), dkpisrv(), dkpoput(), dkposrv(), dkpopen(), cdkpopen(); ! 80: int dkpclose(); ! 81: static struct qinit cdkprinit = { dkpiput,dkpisrv,cdkpopen,dkpclose,512,64 }; ! 82: static struct qinit dkprinit = { dkpiput,dkpisrv,dkpopen,dkpclose,512,64 }; ! 83: static struct qinit dkpwinit = { dkpoput,dkposrv,dkpopen,dkpclose,128,65 }; ! 84: struct streamtab dkpinfo = { &dkprinit, &dkpwinit }; ! 85: struct streamtab cdkpinfo = { &cdkprinit, &dkpwinit }; ! 86: ! 87: dkpopen(q) ! 88: { ! 89: return(rdkpopen(q, !XCHARMODE)); ! 90: } ! 91: ! 92: cdkpopen(q) ! 93: { ! 94: return(rdkpopen(q, XCHARMODE)); ! 95: } ! 96: ! 97: rdkpopen(q, mode) ! 98: register struct queue *q; ! 99: { ! 100: register struct dkp *dkpp; ! 101: static timer = 0; ! 102: int dkptimer(); ! 103: ! 104: if (timer == 0) { ! 105: timer = 1; ! 106: timeout(dkptimer, (caddr_t)NULL, 60); ! 107: } ! 108: if (q->ptr) ! 109: dkpp = (struct dkp *)q->ptr; ! 110: else { ! 111: for (dkpp = dkp; dkpp->state!=0; dkpp++) ! 112: if (dkpp >= &dkp[NDKP]) ! 113: return(0); ! 114: dkpp->rdq = q; ! 115: q->ptr = (caddr_t)dkpp; ! 116: WR(q)->ptr = (caddr_t)dkpp; ! 117: WR(q)->flag |= QNOENB; ! 118: putctl(q->next, M_FLUSH); ! 119: dkpp->timer = DKPTIME; ! 120: dkpp->trx = 0; ! 121: dkpp->iseq = 0; ! 122: dkpp->lastecho = ECHO+0; ! 123: dkpp->WS = 1; ! 124: dkpp->WACK = 1; ! 125: dkpp->WNX = 1; ! 126: dkpp->XW = 3; ! 127: if (mode!=XCHARMODE) { ! 128: WR(q)->flag |= QDELIM; ! 129: dkpp->state = OPENING | RCHARMODE; ! 130: putctl1(WR(q)->next, M_CTL, INIT1); ! 131: } else { ! 132: dkpp->XW = 1; ! 133: dkpp->state = RCHARMODE | XCHARMODE | OPEN; ! 134: putctl1(WR(q)->next, M_CTL, INIT0); ! 135: } ! 136: } ! 137: return(1); ! 138: } ! 139: ! 140: /* ! 141: * Shut it down. ! 142: * The problem is to dispose of unacked stuff in the window. ! 143: * -- no real solution; the receiver might hang on for hours. ! 144: * Give it 15 seconds. ! 145: */ ! 146: dkpclose(q) ! 147: register struct queue *q; ! 148: { ! 149: register struct dkp *dkpp; ! 150: register s = spl5(); ! 151: register i; ! 152: register struct block *bp; ! 153: ! 154: dkpp = (struct dkp *)q->ptr; ! 155: dkpp->state |= LCLOSE; ! 156: flushq(q, 1); ! 157: for (i=0; dkpp->WACK < dkpp->WNX && i<15; i++) ! 158: tsleep((caddr_t)dkpp, DKPPRI, 1); ! 159: if (dkpp->WACK < dkpp->WNX) ! 160: dkprack(dkpp, ACK+((dkpp->WNX-1) & 07)); ! 161: dkpinflush(dkpp); ! 162: splx(s); ! 163: dkpp->state = 0; ! 164: flushq(WR(q), 1); ! 165: } ! 166: ! 167: ! 168: /* ! 169: * Process a bunch of input ! 170: * -- for now, ignore strange control bytes ! 171: */ ! 172: dkpisrv(q) ! 173: register struct queue *q; ! 174: { ! 175: register struct dkp *dkpp = (struct dkp *)q->ptr; ! 176: register struct block *bp; ! 177: register c; ! 178: ! 179: while (bp = getq(q)) { ! 180: if (bp->type == M_CTL) { ! 181: c = *bp->rptr & 0370; ! 182: if (c==REJ || c==ECHO) { ! 183: dkpp->lastecho = *bp->rptr; ! 184: (*WR(q)->next->qinfo->putp)(WR(q)->next, bp); ! 185: } else ! 186: freeb(bp); ! 187: continue; ! 188: } ! 189: if ((q->next->flag&QFULL)==0 || bp->type>=QPCTL ! 190: || dkpp->state&RCLOSE) { ! 191: TRC('G'); TRC(*bp->rptr); ! 192: (*q->next->qinfo->putp)(q->next, bp); ! 193: } else { ! 194: putbq(q, bp); ! 195: return; ! 196: } ! 197: } ! 198: } ! 199: ! 200: /* ! 201: * Packet arrives. ! 202: */ ! 203: dkpiput(q, bp) ! 204: struct queue *q; ! 205: register struct block *bp; ! 206: { ! 207: register struct dkp *dkpp; ! 208: register i; ! 209: register struct block *nbp; ! 210: ! 211: if ((dkpp = (struct dkp *)q->ptr)==NULL) { ! 212: freeb(bp); ! 213: return; ! 214: } ! 215: switch (bp->type) { ! 216: ! 217: moredata: ! 218: bp->rptr++; ! 219: bp->type = M_DATA; ! 220: case M_DATA: ! 221: if (bp->rptr >= bp->wptr||q->flag&QFULL||dkpp->state&LCLOSE) { ! 222: freeb(bp); ! 223: return; ! 224: } ! 225: if (dkpp->state & RCHARMODE) { ! 226: putq(q, bp); ! 227: return; ! 228: } ! 229: switch (dkpp->trx) { ! 230: ! 231: case 1: ! 232: case 2: ! 233: dkpp->trbuf[dkpp->trx++] = *bp->rptr; ! 234: goto moredata; ! 235: ! 236: default: ! 237: dkpp->trx = 0; ! 238: case 0: ! 239: break; ! 240: } ! 241: bp->next = NULL; ! 242: if (dkpp->indata > 256) { /* protect against garbage */ ! 243: freeb(bp); ! 244: return; ! 245: } ! 246: if (dkpp->inp) { ! 247: dkpp->inpe->next = bp; ! 248: dkpp->inpe = bp; ! 249: } else { ! 250: dkpp->inp = bp; ! 251: dkpp->inpe = bp; ! 252: } ! 253: dkpp->indata += bp->wptr - bp->rptr; ! 254: return; ! 255: ! 256: case M_CTL: ! 257: switch (*bp->rptr) { ! 258: ! 259: case ENQ: ! 260: putctl1(WR(q)->next, M_CTL, dkpp->lastecho); ! 261: case CHECK: ! 262: putctl1(WR(q)->next, M_CTL, ACK+dkpp->iseq); ! 263: dkpinflush(dkpp); ! 264: goto moredata; ! 265: ! 266: case AINIT: ! 267: dkpp->state &= ~OPENING; ! 268: dkpp->state |= OPEN; ! 269: qenable(WR(q)); ! 270: dkpinflush(dkpp); ! 271: goto moredata; ! 272: ! 273: case INIT0: ! 274: case INIT1: ! 275: putctl1(WR(q)->next, M_CTL, AINIT); ! 276: if (*bp->rptr==INIT0 && (dkpp->state&RCHARMODE)==0) { ! 277: dkpp->state |= RCHARMODE; ! 278: dkpp->XW = 1; ! 279: q->flag &= ~QDELIM; ! 280: } else if (*bp->rptr==INIT1 && (dkpp->state&RCHARMODE)){ ! 281: dkpp->state &= ~RCHARMODE; ! 282: dkpp->XW = 3; ! 283: q->flag |= QDELIM; ! 284: } ! 285: dkpinflush(dkpp); ! 286: dkpp->iseq = 0; ! 287: wakeup(dkpp); ! 288: goto moredata; ! 289: ! 290: case INITREQ: ! 291: if (dkpp->state&XCHARMODE) ! 292: putctl1(WR(q)->next, M_CTL, INIT0); ! 293: else { ! 294: if (dkpp->WS < dkpp->WNX) ! 295: dkprack(dkpp, ECHO+((dkpp->WNX-1)&07)); ! 296: dkpp->WS = 1; ! 297: dkpp->WACK = 1; ! 298: dkpp->WNX = 1; ! 299: putctl1(WR(q)->next, M_CTL, INIT1); ! 300: } ! 301: dkpinflush(dkpp); ! 302: goto moredata; ! 303: ! 304: case BREAK: ! 305: qpctl(q, M_BREAK); ! 306: dkpp->indata++; ! 307: goto moredata; ! 308: ! 309: case BOT: ! 310: case BOTS: ! 311: case BOTM: ! 312: dkpp->trx = 1; ! 313: dkpp->trbuf[0] = *bp->rptr; ! 314: goto moredata; ! 315: ! 316: case REJ+0: case REJ+1: case REJ+2: case REJ+3: ! 317: case REJ+4: case REJ+5: case REJ+6: case REJ+7: ! 318: if (dkpp->state&RCHARMODE) ! 319: goto moredata; ! 320: TRC('r'); ! 321: if (((*bp->rptr+1)&07) == (dkpp->WACK&07) ! 322: && (dkpp->state&RJING) == 0) { ! 323: dkstat.dkprxmit++; ! 324: for (i=dkpp->WACK; i<dkpp->WNX; i++) { ! 325: TRC('Z'); ! 326: TRC('0' + (i&07)); ! 327: dkpp->state |= RJING; ! 328: dkpxmit(WR(q), dkpp->xb[i&07], i); ! 329: } ! 330: } ! 331: goto moredata; ! 332: ! 333: case ACK+0: case ACK+1: case ACK+2: case ACK+3: ! 334: case ACK+4: case ACK+5: case ACK+6: case ACK+7: ! 335: case ECHO+0: case ECHO+1: case ECHO+2: case ECHO+3: ! 336: case ECHO+4: case ECHO+5: case ECHO+6: case ECHO+7: ! 337: dkprack(dkpp, *bp->rptr); ! 338: goto moredata; ! 339: ! 340: case SEQ+0: case SEQ+1: case SEQ+2: case SEQ+3: ! 341: case SEQ+4: case SEQ+5: case SEQ+6: case SEQ+7: ! 342: i = *bp->rptr & 07; ! 343: if (dkpp->state & RCHARMODE) { ! 344: TRC('e'); ! 345: qpctl1(q, M_CTL, ECHO+i); ! 346: goto moredata; ! 347: } ! 348: if (dkpp->trx !=3 ! 349: || dkpp->indata != dkpp->trbuf[1] + (dkpp->trbuf[2]<<8) ! 350: || i != ((dkpp->iseq+1)&07)) { /* reject? */ ! 351: if (dkpp->trx != 3) ! 352: dkstat.dkprjtrs++; ! 353: else if (i != ((dkpp->iseq+1)&07)) ! 354: dkstat.dkprjseq++; ! 355: else ! 356: dkstat.dkprjpks++; ! 357: dkpinflush(dkpp); ! 358: if (dkpp->trbuf[0]==BOTS) ! 359: dkpp->iseq = i; ! 360: TRC('R'); TRC('0'+dkpp->iseq); ! 361: TRC(dkpp->trx!=3?'t':(i!=(dkpp->iseq+1)&07?'s':'c')); ! 362: qpctl1(q, M_CTL, REJ+dkpp->iseq); ! 363: goto moredata; ! 364: } ! 365: /* accept */ ! 366: while (nbp = dkpp->inp) { ! 367: dkpp->inp = nbp->next; ! 368: putq(q, nbp); ! 369: } ! 370: TRC('A'); TRC('0'+i); ! 371: dkpp->inpe = NULL; ! 372: dkpp->trx = 0; ! 373: dkpp->indata = 0; ! 374: dkpp->iseq = i; ! 375: qpctl1(q, M_CTL, ECHO+i); ! 376: if (dkpp->trbuf[0] != BOTM) ! 377: qpctl(q, M_DELIM); ! 378: goto moredata; ! 379: ! 380: default: ! 381: if (*bp->rptr < 0200) /* non-supervisory */ ! 382: dkpp->indata++; ! 383: qpctl1(q, M_CTL, *bp->rptr); ! 384: goto moredata; ! 385: } ! 386: ! 387: case M_HANGUP: ! 388: dkpp->state |= RCLOSE; ! 389: flushq(WR(q), 1); ! 390: dkprack(dkpp, ECHO+((dkpp->WNX-1) & 07)); ! 391: putq(q, bp); ! 392: return; ! 393: ! 394: case M_IOCACK: ! 395: case M_IOCNAK: ! 396: case M_CLOSE: ! 397: (*q->next->qinfo->putp)(q->next, bp); ! 398: return; ! 399: ! 400: default: ! 401: freeb(bp); ! 402: return; ! 403: } ! 404: } ! 405: ! 406: /* ! 407: * --- Output processor ! 408: */ ! 409: ! 410: /* ! 411: * accept data from writer ! 412: * -- handle most non-data messages ! 413: */ ! 414: dkpoput(q, bp) ! 415: register struct queue *q; ! 416: register struct block *bp; ! 417: { ! 418: register struct dkp *dkpp = (struct dkp *)q->ptr; ! 419: register union stmsg *sp; ! 420: register x; ! 421: ! 422: if (dkpp->state & RCLOSE) { ! 423: freeb(bp); ! 424: return; ! 425: } ! 426: switch (bp->type) { ! 427: ! 428: case M_STOP: ! 429: dkpp->state |= STOPPED; ! 430: freeb(bp); ! 431: return; ! 432: ! 433: case M_START: ! 434: dkpp->state &= ~STOPPED; ! 435: freeb(bp); ! 436: qenable(q); ! 437: return; ! 438: ! 439: case M_FLUSH: ! 440: flushq(q, 0); ! 441: freeb(bp); ! 442: return; ! 443: ! 444: case M_IOCTL: ! 445: sp = (union stmsg *)bp->rptr; ! 446: switch (sp->ioc0.com) { ! 447: ! 448: case TIOCSETP: ! 449: case TIOCSETN: ! 450: x = sp->ioc1.sb.sg_ispeed; ! 451: bp->wptr = bp->rptr; ! 452: bp->type = M_IOCACK; ! 453: qreply(q, bp); ! 454: if (x==0) ! 455: putctl(OTHERQ(q), M_HANGUP); ! 456: return; ! 457: ! 458: case TIOCGETP: ! 459: sp->ioc1.sb.sg_ispeed = ! 460: sp->ioc1.sb.sg_ospeed = B9600; ! 461: bp->type = M_IOCACK; ! 462: qreply(q, bp); ! 463: return; ! 464: ! 465: case DIOCSTREAM: ! 466: RD(q)->flag &= ~QDELIM; ! 467: bp->wptr = bp->rptr; ! 468: bp->type = M_IOCACK; ! 469: qreply(q, bp); ! 470: return; ! 471: ! 472: case DIOCRECORD: ! 473: if ((dkpp->state&RCHARMODE) == 0) { ! 474: RD(q)->flag | = QDELIM; ! 475: bp->wptr = bp->rptr; ! 476: bp->type = M_IOCACK; ! 477: } else ! 478: bp->type = M_IOCNAK; ! 479: qreply(q, bp); ! 480: return; ! 481: ! 482: case KIOCINIT: ! 483: if (dkpp->state&XCHARMODE) ! 484: putctl1(q->next, M_CTL, INIT0); ! 485: else { ! 486: if (dkpp->WS < dkpp->WNX) ! 487: dkprack(dkpp, ECHO+((dkpp->WNX-1)&07)); ! 488: dkpp->WS = 1; ! 489: dkpp->WACK = 1; ! 490: dkpp->WNX = 1; ! 491: putctl1(q->next, M_CTL, INIT1); ! 492: } ! 493: bp->wptr = bp->rptr; ! 494: bp->type = M_IOCACK; ! 495: qreply(q, bp); ! 496: return; ! 497: ! 498: case KIOCISURP: ! 499: bp->wptr = bp->rptr; ! 500: bp->type = M_IOCACK; ! 501: qreply(q, bp); ! 502: return; ! 503: ! 504: default: ! 505: (*q->next->qinfo->putp)(q->next, bp); ! 506: return; ! 507: } ! 508: ! 509: case M_DELAY: ! 510: x = *bp->rptr; ! 511: *bp->rptr = DELAY; ! 512: bp->type = M_CTL; ! 513: while (x) { ! 514: (*bp->rptr)++; ! 515: x >>= 1; ! 516: } ! 517: goto putonq; ! 518: ! 519: case M_CLOSE: ! 520: (*q->next->qinfo->putp)(q->next, bp); ! 521: return; ! 522: ! 523: default: ! 524: freeb(bp); ! 525: return; ! 526: ! 527: case M_BREAK: ! 528: bp->type = M_CTL; ! 529: *bp->wptr++ = BREAK; ! 530: case M_DELIM: ! 531: case M_DATA: ! 532: putonq: ! 533: putq(q, bp); ! 534: if (dkpp->WNX < dkpp->WS+dkpp->XW) ! 535: qenable(q); ! 536: return; ! 537: } ! 538: } ! 539: ! 540: /* ! 541: * Out server: ! 542: * if space in window, process queue ! 543: */ ! 544: dkposrv(q) ! 545: register struct queue *q; ! 546: { ! 547: register struct dkp *dkpp = (struct dkp *)q->ptr; ! 548: register struct block *bp, *xbp; ! 549: int c; ! 550: ! 551: if (dkpp->state & (STOPPED|OPENING)) ! 552: return; ! 553: while (dkpp->WNX < dkpp->WS+dkpp->XW) { ! 554: if ((bp = getq(q)) == NULL) ! 555: break; ! 556: if (dkpp->state & XCHARMODE) { ! 557: switch (bp->type) { ! 558: ! 559: case M_DELIM: ! 560: freeb(bp); ! 561: continue; ! 562: ! 563: default: ! 564: dkpp->outcnt += bp->wptr - bp->rptr; ! 565: (*q->next->qinfo->putp)(q->next, bp); ! 566: if (dkpp->outcnt >= 64) { ! 567: putctl1(q->next, M_CTL, ! 568: SEQ+(dkpp->WNX&07)); ! 569: dkpp->WNX++; ! 570: dkpp->WACK = dkpp->WNX; ! 571: dkpp->outcnt = 0; ! 572: } ! 573: continue; ! 574: } ! 575: } ! 576: /* ! 577: * look ahead for delimiters. ! 578: * Don't transmit a single data block, ! 579: * to avoid 0-len block next time ! 580: */ ! 581: if (bp->type==M_DATA && (xbp = q->first) && xbp->type==M_DELIM){ ! 582: xbp = getq(q); ! 583: if (xbp) ! 584: freeb(xbp); /* toss delimiter */ ! 585: bp->type = M_DELIM; ! 586: } ! 587: if (bp->type==M_DATA && q->first==NULL) { ! 588: putbq(q, bp); ! 589: return; ! 590: } ! 591: TRC('x'); TRC('0'+dkpp->WS/10); TRC('0'+dkpp->WS%10); ! 592: TRC('.'); TRC('0'+dkpp->WNX/10); TRC('0'+dkpp->WNX%10); ! 593: if (dkpp->xb[dkpp->WNX&07]) { ! 594: freeb(dkpp->xb[dkpp->WNX&07]); ! 595: printf("dkp losing block"); ! 596: } ! 597: dkpp->xb[dkpp->WNX & 07] = bp; ! 598: dkpxmit(q, bp, dkpp->WNX); ! 599: dkpp->WNX++; ! 600: } ! 601: } ! 602: ! 603: /* ! 604: * Send out a message, with trailer. ! 605: */ ! 606: dkpxmit(q, bp, seqno) ! 607: struct queue *q; ! 608: register struct block *bp; ! 609: { ! 610: register struct dkp *dkpp = (struct dkp *)q->ptr; ! 611: register type; ! 612: register size; ! 613: register struct block *xbp; ! 614: ! 615: if (bp==NULL) { ! 616: printf("null bp in dkpxmit\n"); ! 617: return; ! 618: } ! 619: type = bp->type; ! 620: size = bp->wptr - bp->rptr; ! 621: seqno &= 07; ! 622: /* send ptr to block, if non-empty */ ! 623: if (size) { ! 624: if ((xbp = allocb(0)) == NULL) ! 625: return; ! 626: TRC('X'); TRC('0'+seqno); ! 627: xbp->rptr = bp->rptr; ! 628: xbp->wptr = bp->wptr; ! 629: if (type!=M_DELIM) ! 630: xbp->type = type; ! 631: (*q->next->qinfo->putp)(q->next, xbp); ! 632: } ! 633: /* send trailer */ ! 634: if ((xbp = allocb(3)) == NULL) ! 635: return; ! 636: xbp->type = M_CTL; ! 637: *xbp->wptr++ = type==M_DATA? BOTM: BOT; ! 638: *xbp->wptr++ = size; ! 639: *xbp->wptr++ = size >> 8; ! 640: (*q->next->qinfo->putp)(q->next, xbp); ! 641: putctl1(q->next, M_CTL, SEQ + seqno); ! 642: dkpp->timer = DKPTIME; ! 643: } ! 644: ! 645: /* ! 646: * Receive an ack of some sort for a transmitted message. ! 647: * Advance various windows. ! 648: */ ! 649: dkprack(dkpp, msg) ! 650: register struct dkp *dkpp; ! 651: { ! 652: register struct block **bpp; ! 653: register seqno, i; ! 654: ! 655: seqno = msg & 07; ! 656: msg &= 0370; ! 657: /* invariants: 0 <= WS <= WACK <= WNX; seqno maximal < WNX; WS < 8 */ ! 658: if (seqno >= dkpp->WNX) ! 659: seqno -= 8; ! 660: else if (seqno+8 < dkpp->WNX) ! 661: seqno += 8; ! 662: dkpp->state &= ~RJING; ! 663: for (i=dkpp->WS; i<=seqno; i++) { ! 664: bpp = &dkpp->xb[i&07]; ! 665: if (*bpp) { ! 666: freeb(*bpp); ! 667: *bpp = NULL; ! 668: } ! 669: } ! 670: if ((int)dkpp->WACK <= seqno) ! 671: dkpp->WACK = seqno+1; ! 672: if (msg==ECHO) { ! 673: TRC('E'); TRC('0'+(seqno&07)); ! 674: if (dkpp->WS <= seqno) { ! 675: dkpp->timer = DKPTIME; /* push off timeout */ ! 676: dkpp->WS = seqno+1; ! 677: if (dkpp->WNX<dkpp->WS+dkpp->XW && WR(dkpp->rdq)->count) ! 678: qenable(WR(dkpp->rdq)); ! 679: } ! 680: } else { ! 681: for (i=dkpp->WACK; i<dkpp->WNX; i++) { ! 682: if (dkpp->xb[i&07]==0) ! 683: printf("WS %d WACK %d WNX %d i %d seqno %d\n", ! 684: dkpp->WS, dkpp->WACK, dkpp->WNX, i, seqno); ! 685: dkpxmit(WR(dkpp->rdq), dkpp->xb[i&07], i); ! 686: dkstat.dkprxmit++; ! 687: } ! 688: } ! 689: if (dkpp->WS >= 8) { ! 690: dkpp->WS -= 8; ! 691: dkpp->WACK -= 8; ! 692: dkpp->WNX -= 8; ! 693: } ! 694: } ! 695: ! 696: dkptimer() ! 697: { ! 698: register struct dkp *dkpp; ! 699: register struct queue *q; ! 700: ! 701: for (dkpp = dkp; dkpp < &dkp[NDKP]; dkpp++) { ! 702: if ((dkpp->state&(OPEN|OPENING)) == 0) ! 703: continue; ! 704: if (--dkpp->timer>0) ! 705: continue; ! 706: q = WR(dkpp->rdq)->next; ! 707: if (q->flag&QFULL) ! 708: continue; ! 709: if (dkpp->state & XCHARMODE) { ! 710: if (dkpp->WS < dkpp->WNX) ! 711: putctl1(q, M_CTL, SEQ+((dkpp->WNX-1)&07)); ! 712: dkpp->timer = 10; ! 713: continue; ! 714: } ! 715: if (dkpp->state&OPENING) ! 716: putctl1(q, M_CTL, INIT1); ! 717: if (dkpp->WS != dkpp->WNX) ! 718: putctl1(q, M_CTL, ENQ); ! 719: dkpp->timer = DKPTIME; ! 720: } ! 721: timeout(dkptimer, (caddr_t)NULL, 60); ! 722: } ! 723: ! 724: /* ! 725: * throw away data in front of the barrier, and clear the trailer buffer ! 726: */ ! 727: dkpinflush(dkpp) ! 728: register struct dkp *dkpp; ! 729: { ! 730: register struct block *bp; ! 731: ! 732: while (bp = dkpp->inp) { ! 733: dkpp->inp = bp->next; ! 734: freeb(bp); ! 735: } ! 736: dkpp->inpe = NULL; ! 737: dkpp->trx = 0; ! 738: dkpp->indata = 0; ! 739: } ! 740: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.