|
|
1.1 ! root 1: /* ! 2: * Datakit URP protocol ! 3: * ! 4: * In the language we speak to the device driver, ! 5: * M_DATA blocks contain data envelopes ! 6: * M_CTL blocks contain a control envelope, ! 7: * followed by zero or more data envelopes ! 8: * ! 9: * Drivers are allowed to store up blocks for a while; ! 10: * the S_DELIM bit means that stored data must now be sent. ! 11: * The point is to work with some broken URP implementations ! 12: * that have found their way into Datakit controllers; ! 13: * a driver that speaks to one might have to save data up, ! 14: * then send it with no intervening control-nulls when S_DELIM comes. ! 15: */ ! 16: ! 17: #include "sys/param.h" ! 18: #include "sys/stream.h" ! 19: #include "sys/conf.h" ! 20: #include "sys/ttyio.h" ! 21: #include "sys/dkio.h" ! 22: #include "sys/dkstat.h" ! 23: #include "sys/dkp.h" ! 24: #include "sys/dkmod.h" ! 25: ! 26: #ifdef CAREFUL ! 27: #define TRC(c) *dkptrp++ = c; if (dkptrp>=&dkptrb[1024]) dkptrp=dkptrb ! 28: char dkptrb[1024]; char *dkptrp = dkptrb; ! 29: #else ! 30: #define TRC(c) ! 31: #endif ! 32: ! 33: extern struct dkstat dkstat; ! 34: ! 35: /* ! 36: * Protocol control bytes ! 37: */ ! 38: #define SEQ 0010 /* sequence number, ends trailers */ ! 39: #undef ECHO ! 40: #define ECHO 0020 /* echos, data given to next queue */ ! 41: #define REJ 0030 /* rejections, transmission error */ ! 42: #define ACK 0040 /* acknowledgments */ ! 43: #define BOT 0050 /* beginning of trailer */ ! 44: #define BOTM 0051 /* beginning of trailer, more data follows */ ! 45: #define BOTS 0052 /* seq update algorithm on this trailer */ ! 46: #define SOU 0053 /* start of unsequenced trailer */ ! 47: #define EOU 0054 /* end of unsequenced trailer */ ! 48: #define ENQ 0055 /* xmitter requests flow/error status */ ! 49: #define CHECK 0056 /* xmitter requests error status */ ! 50: #define INITREQ 0057 /* request initialization */ ! 51: #define INIT0 0060 /* disable trailer processing */ ! 52: #define INIT1 0061 /* enable trailer procesing */ ! 53: #define AINIT 0062 /* response to INIT0/INIT1 */ ! 54: #undef DELAY ! 55: #define DELAY 0100 /* real-time printing delay */ ! 56: #define BREAK 0110 /* Send/receive break (new style) */ ! 57: ! 58: #define OPEN 01 ! 59: #define LCLOSE 02 ! 60: #define RCLOSE 04 ! 61: #define XCHARMODE 010 ! 62: #define OPENING 020 ! 63: #define RJING 040 ! 64: #define STOPPED 0100 ! 65: #define RCHARMODE 0200 ! 66: ! 67: #define DKPPRI 28 ! 68: #define DKPTIME 2 ! 69: ! 70: extern struct dkp dkp[]; ! 71: extern int dkpcnt; ! 72: long dkpopen(), cdkpopen(); ! 73: int dkpiput(), dkpisrv(), dkpoput(), dkposrv(); ! 74: int dkpclose(); ! 75: static struct qinit cdkprinit = { dkpiput,dkpisrv,cdkpopen,dkpclose,512,64 }; ! 76: static struct qinit cdkpwinit = { dkpoput,dkposrv,cdkpopen,dkpclose,128,65 }; ! 77: static struct qinit dkprinit = { dkpiput,dkpisrv,dkpopen,dkpclose,1500,512 }; ! 78: static struct qinit dkpwinit = { dkpoput,dkposrv,dkpopen,dkpclose,1500,512 }; ! 79: struct streamtab dkpstream = { &dkprinit, &dkpwinit }; ! 80: struct streamtab cdkpstream = { &cdkprinit, &cdkpwinit }; ! 81: ! 82: #define MAXMSG 4096 /* max message size allowed */ ! 83: ! 84: long ! 85: dkpopen(q) ! 86: struct queue *q; ! 87: { ! 88: return(rdkpopen(q, !XCHARMODE)); ! 89: } ! 90: ! 91: long ! 92: cdkpopen(q) ! 93: struct queue *q; ! 94: { ! 95: return(rdkpopen(q, XCHARMODE)); ! 96: } ! 97: ! 98: rdkpopen(q, mode) ! 99: register struct queue *q; ! 100: { ! 101: register struct dkp *dkpp; ! 102: static timer = 0; ! 103: int dkptimer(); ! 104: ! 105: if (timer == 0) { ! 106: timer = 1; ! 107: timeout(dkptimer, (caddr_t)NULL, HZ); ! 108: } ! 109: if (q->ptr == NULL) { ! 110: for (dkpp = dkp; dkpp->state!=0; dkpp++) ! 111: if (dkpp >= &dkp[dkpcnt]) ! 112: return(0); ! 113: dkpp->rdq = q; ! 114: q->ptr = (caddr_t)dkpp; ! 115: WR(q)->ptr = (caddr_t)dkpp; ! 116: WR(q)->flag |= QNOENB; ! 117: putctl(q->next, M_FLUSH); ! 118: dkpp->timer = DKPTIME; ! 119: dkpp->trx = 0; ! 120: dkpp->iseq = 0; ! 121: dkpp->lastecho = ECHO+0; ! 122: dkpp->WS = 1; ! 123: dkpp->WACK = 1; ! 124: dkpp->WNX = 1; ! 125: dkpp->XW = 3; ! 126: dkpp->xsize = 64; ! 127: dkpp->lastctl = 0; ! 128: if (mode!=XCHARMODE) { ! 129: WR(q)->flag |= QDELIM; ! 130: dkpp->state = OPENING | RCHARMODE; ! 131: putctl1d(WR(q)->next, M_CTL, INIT1); ! 132: } else { ! 133: dkpp->XW = 1; ! 134: dkpp->state = RCHARMODE | XCHARMODE | OPEN; ! 135: putctl1d(WR(q)->next, M_CTL, INIT0); ! 136: } ! 137: } ! 138: return(1); ! 139: } ! 140: ! 141: /* ! 142: * Shut it down. ! 143: * The problem is to dispose of unacked stuff in the window. ! 144: * -- no real solution; the receiver might hang on for hours. ! 145: * Give it 15 seconds. ! 146: */ ! 147: dkpclose(q) ! 148: register struct queue *q; ! 149: { ! 150: register struct dkp *dkpp; ! 151: register s = spl5(); ! 152: register i; ! 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: bp->class |= S_DELIM; ! 185: (*WR(q)->next->qinfo->putp)(WR(q)->next, bp); ! 186: } else ! 187: freeb(bp); /* unknown control */ ! 188: continue; ! 189: } ! 190: if ((q->next->flag&QFULL)==0 || bp->type>=QPCTL ! 191: || dkpp->state&RCLOSE) { ! 192: TRC('G'); TRC(*bp->rptr); ! 193: (*q->next->qinfo->putp)(q->next, bp); ! 194: } else { ! 195: putbq(q, bp); ! 196: return; ! 197: } ! 198: } ! 199: } ! 200: ! 201: /* ! 202: * Packet arrives. ! 203: */ ! 204: dkpiput(q, bp) ! 205: struct queue *q; ! 206: register struct block *bp; ! 207: { ! 208: register struct dkp *dkpp; ! 209: register i; ! 210: register struct block *nbp; ! 211: ! 212: if ((dkpp = (struct dkp *)q->ptr)==NULL) { ! 213: freeb(bp); ! 214: return; ! 215: } ! 216: switch (bp->type) { ! 217: ! 218: moredata: ! 219: bp->rptr++; ! 220: bp->type = M_DATA; ! 221: case M_DATA: ! 222: bp->class &= ~S_DELIM; ! 223: if (bp->rptr >= bp->wptr||q->flag&QFULL||dkpp->state&LCLOSE) { ! 224: freeb(bp); ! 225: return; ! 226: } ! 227: if (dkpp->state & RCHARMODE) { ! 228: putq(q, bp); ! 229: return; ! 230: } ! 231: switch (dkpp->trx) { ! 232: ! 233: case 1: ! 234: case 2: ! 235: dkpp->trbuf[dkpp->trx++] = *bp->rptr; ! 236: goto moredata; ! 237: ! 238: default: ! 239: dkpp->trx = 0; ! 240: case 0: ! 241: break; ! 242: } ! 243: bp->next = NULL; ! 244: if (dkpp->indata > MAXMSG) { /* protect against garbage */ ! 245: freeb(bp); ! 246: return; ! 247: } ! 248: if (dkpp->inp) { ! 249: dkpp->inpe->next = bp; ! 250: dkpp->inpe = bp; ! 251: } else { ! 252: dkpp->inp = bp; ! 253: dkpp->inpe = bp; ! 254: } ! 255: dkpp->indata += bp->wptr - bp->rptr; ! 256: return; ! 257: ! 258: case M_CTL: ! 259: switch (*bp->rptr) { ! 260: ! 261: case ENQ: ! 262: putctl1(WR(q)->next, M_CTL, dkpp->lastecho); ! 263: case CHECK: ! 264: putctl1d(WR(q)->next, M_CTL, ACK+dkpp->iseq); ! 265: dkpinflush(dkpp); ! 266: goto moredata; ! 267: ! 268: case AINIT: ! 269: dkpp->state &= ~OPENING; ! 270: dkpp->state |= OPEN; ! 271: qenable(WR(q)); ! 272: dkpinflush(dkpp); ! 273: goto moredata; ! 274: ! 275: case INIT0: ! 276: case INIT1: ! 277: putctl1d(WR(q)->next, M_CTL, AINIT); ! 278: if (*bp->rptr==INIT0 && (dkpp->state&RCHARMODE)==0) { ! 279: dkpp->state |= RCHARMODE; ! 280: dkpp->XW = 1; /* why? */ ! 281: q->flag &= ~QDELIM; ! 282: } else if (*bp->rptr==INIT1 && (dkpp->state&RCHARMODE)) { ! 283: dkpp->state &= ~RCHARMODE; ! 284: dkpp->XW = 3; /* why? */ ! 285: q->flag |= QDELIM; ! 286: } ! 287: dkpinflush(dkpp); ! 288: dkpp->iseq = 0; ! 289: wakeup((caddr_t)dkpp); ! 290: goto moredata; ! 291: ! 292: case INITREQ: ! 293: if (dkpp->state&XCHARMODE) ! 294: putctl1d(WR(q)->next, M_CTL, INIT0); ! 295: else { ! 296: if (dkpp->WS < dkpp->WNX) ! 297: dkprack(dkpp, ECHO+((dkpp->WNX-1)&07)); ! 298: dkpp->WS = 1; ! 299: dkpp->WACK = 1; ! 300: dkpp->WNX = 1; ! 301: putctl1d(WR(q)->next, M_CTL, INIT1); ! 302: } ! 303: dkpinflush(dkpp); ! 304: goto moredata; ! 305: ! 306: case BREAK: ! 307: qpctl(q, M_BREAK); ! 308: dkpp->indata++; ! 309: goto moredata; ! 310: ! 311: case BOT: ! 312: case BOTS: ! 313: case BOTM: ! 314: dkpp->trx = 1; ! 315: dkpp->trbuf[0] = *bp->rptr; ! 316: goto moredata; ! 317: ! 318: case REJ+0: case REJ+1: case REJ+2: case REJ+3: ! 319: case REJ+4: case REJ+5: case REJ+6: case REJ+7: ! 320: if (dkpp->state&XCHARMODE) ! 321: goto moredata; ! 322: TRC('r'); ! 323: if (((*bp->rptr+1)&07) == (dkpp->WACK&07) ! 324: && (dkpp->state&RJING) == 0) { ! 325: dkstat.dkprxmit++; ! 326: for (i=dkpp->WACK; i<dkpp->WNX; i++) { ! 327: TRC('Z'); ! 328: TRC('0' + (i&07)); ! 329: dkpp->state |= RJING; ! 330: dkpxmit(WR(q), dkpp->xb[i&07], i); ! 331: } ! 332: } ! 333: goto moredata; ! 334: ! 335: case ACK+0: case ACK+1: case ACK+2: case ACK+3: ! 336: case ACK+4: case ACK+5: case ACK+6: case ACK+7: ! 337: case ECHO+0: case ECHO+1: case ECHO+2: case ECHO+3: ! 338: case ECHO+4: case ECHO+5: case ECHO+6: case ECHO+7: ! 339: dkprack(dkpp, *bp->rptr); ! 340: goto moredata; ! 341: ! 342: case SEQ+0: case SEQ+1: case SEQ+2: case SEQ+3: ! 343: case SEQ+4: case SEQ+5: case SEQ+6: case SEQ+7: ! 344: i = *bp->rptr & 07; ! 345: if (dkpp->state & RCHARMODE) { ! 346: TRC('e'); ! 347: qpctl1(q, M_CTL, ECHO+i); ! 348: goto moredata; ! 349: } ! 350: if (dkpp->trx !=3 ! 351: || dkpp->indata != dkpp->trbuf[1] + (dkpp->trbuf[2]<<8) ! 352: || i != ((dkpp->iseq+1)&07)) { /* reject? */ ! 353: if (dkpp->trx != 3) ! 354: dkstat.dkprjtrs++; ! 355: else if (i != ((dkpp->iseq+1)&07)) ! 356: dkstat.dkprjseq++; ! 357: else ! 358: dkstat.dkprjpks++; ! 359: dkpinflush(dkpp); ! 360: if (dkpp->trbuf[0]==BOTS) ! 361: dkpp->iseq = i; ! 362: TRC('R'); TRC('0'+dkpp->iseq); ! 363: TRC(dkpp->trx!=3?'t':(i!=(dkpp->iseq+1)&07?'s':'c')); ! 364: qpctl1(q, M_CTL, REJ+dkpp->iseq); ! 365: goto moredata; ! 366: } ! 367: /* accept */ ! 368: if (dkpp->inpe==NULL) ! 369: dkpp->inp = dkpp->inpe = allocb(0); ! 370: if (dkpp->trbuf[0] != BOTM && q->flag&QDELIM) ! 371: dkpp->inpe->class |= S_DELIM; ! 372: while (nbp = dkpp->inp) { ! 373: dkpp->inp = nbp->next; ! 374: putq(q, nbp); ! 375: } ! 376: TRC('A'); TRC('0'+i); ! 377: dkpp->inpe = NULL; ! 378: dkpp->trx = 0; ! 379: dkpp->indata = 0; ! 380: dkpp->iseq = i; ! 381: qpctl1(q, M_CTL, ECHO+i); ! 382: goto moredata; ! 383: ! 384: default: ! 385: if (*bp->rptr < 0200) /* non-supervisory */ ! 386: dkpp->indata++; ! 387: dkpp->lastctl = *bp->rptr; ! 388: qpctl1(q, M_CTL, *bp->rptr); ! 389: goto moredata; ! 390: } ! 391: ! 392: case M_HANGUP: ! 393: dkpp->state |= RCLOSE; ! 394: flushq(WR(q), 1); ! 395: dkprack(dkpp, ECHO+((dkpp->WNX-1) & 07)); ! 396: putq(q, bp); ! 397: return; ! 398: ! 399: case M_IOCACK: ! 400: case M_IOCNAK: ! 401: (*q->next->qinfo->putp)(q->next, bp); ! 402: return; ! 403: ! 404: case M_PRICTL: ! 405: if (*bp->rptr != DKMXINIT) { ! 406: (*q->next->qinfo->putp)(q->next, bp); ! 407: return; ! 408: } ! 409: bp->type = M_CTL; ! 410: bp->wptr = bp->rptr; ! 411: *bp->wptr++ = INITREQ; ! 412: dkpiput(q, bp); ! 413: putctl1d(WR(q)->next, M_CTL, INITREQ); ! 414: return; ! 415: ! 416: default: ! 417: freeb(bp); ! 418: return; ! 419: } ! 420: } ! 421: ! 422: /* ! 423: * --- Output processor ! 424: */ ! 425: ! 426: /* ! 427: * accept data from writer ! 428: * -- handle most non-data messages ! 429: */ ! 430: ! 431: int dkpwbig = 200; ! 432: ! 433: dkpoput(q, bp) ! 434: register struct queue *q; ! 435: register struct block *bp; ! 436: { ! 437: register struct dkp *dkpp = (struct dkp *)q->ptr; ! 438: register unsigned char *sp; ! 439: register x, s; ! 440: struct block *xbp; ! 441: ! 442: if (dkpp->state & RCLOSE) { ! 443: freeb(bp); ! 444: return; ! 445: } ! 446: switch (bp->type) { ! 447: ! 448: case M_STOP: ! 449: dkpp->state |= STOPPED; ! 450: freeb(bp); ! 451: return; ! 452: ! 453: case M_START: ! 454: dkpp->state &= ~STOPPED; ! 455: freeb(bp); ! 456: qenable(q); ! 457: return; ! 458: ! 459: case M_FLUSH: ! 460: /* annul data for blocks in transit */ ! 461: freeb(bp); ! 462: s = spl5(); /* in case an ECHO is about to arrive */ ! 463: for (x=0; x<8; x++) ! 464: if ((bp = dkpp->xb[x]) != NULL) ! 465: bp->wptr = bp->rptr; ! 466: splx(s); ! 467: flushq(q, 0); ! 468: return; ! 469: ! 470: case M_IOCTL: ! 471: sp = (unsigned char *)stiodata(bp); ! 472: switch (stiocom(bp)) { ! 473: ! 474: case TIOCSDEV: ! 475: x = ((struct ttydevb *)sp)->ispeed; ! 476: bp->wptr = bp->rptr; ! 477: bp->type = M_IOCACK; ! 478: qreply(q, bp); ! 479: if (x==0) ! 480: putctl(OTHERQ(q), M_HANGUP); ! 481: return; ! 482: ! 483: case TIOCGDEV: ! 484: ((struct ttydevb *)sp)->ispeed = ((struct ttydevb *)sp)->ospeed = B9600; ! 485: bp->wptr = bp->rptr + sizeof(struct ttydevb) + STIOCHDR; ! 486: if (bp->wptr >= bp->lim) ! 487: panic("dkioc"); ! 488: bp->type = M_IOCACK; ! 489: qreply(q, bp); ! 490: return; ! 491: ! 492: case DIOCSTREAM: ! 493: RD(q)->flag &= ~QDELIM; ! 494: bp->wptr = bp->rptr; ! 495: bp->type = M_IOCACK; ! 496: qreply(q, bp); ! 497: return; ! 498: ! 499: case DIOCRECORD: ! 500: if ((dkpp->state&RCHARMODE) == 0) { ! 501: RD(q)->flag |= QDELIM; ! 502: bp->type = M_IOCACK; ! 503: } else ! 504: bp->type = M_IOCNAK; ! 505: bp->wptr = bp->rptr; ! 506: qreply(q, bp); ! 507: return; ! 508: ! 509: case KIOCINIT: ! 510: if (dkpp->state&XCHARMODE) ! 511: putctl1d(q->next, M_CTL, INIT0); ! 512: else { ! 513: s = spl5(); ! 514: if (dkpp->WS < dkpp->WNX) ! 515: dkprack(dkpp, ECHO+((dkpp->WNX-1)&07)); ! 516: dkpp->WS = 1; ! 517: dkpp->WACK = 1; ! 518: dkpp->WNX = 1; ! 519: splx(s); ! 520: putctl1d(q->next, M_CTL, INIT1); ! 521: } ! 522: bp->wptr = bp->rptr; ! 523: bp->type = M_IOCACK; ! 524: qreply(q, bp); ! 525: return; ! 526: ! 527: case KIOCISURP: ! 528: bp->wptr = bp->rptr; ! 529: bp->type = M_IOCACK; ! 530: qreply(q, bp); ! 531: return; ! 532: ! 533: case DIOCSCTL: ! 534: bp->type = M_IOCACK; ! 535: bp->wptr = bp->rptr; ! 536: if (*sp == 0) { ! 537: qreply(q, bp); ! 538: return; ! 539: } ! 540: if ((xbp = allocb(1)) == NULL) ! 541: bp->type = M_IOCNAK; ! 542: else { ! 543: xbp->type = M_CTL; ! 544: xbp->class |= S_DELIM; ! 545: *xbp->wptr++ = *sp; ! 546: putq(q, xbp); ! 547: if (dkpp->WNX < dkpp->WS+dkpp->XW) ! 548: qenable(q); ! 549: } ! 550: qreply(q, bp); ! 551: return; ! 552: ! 553: case DIOCRCTL: ! 554: *sp = dkpp->lastctl; ! 555: dkpp->lastctl = 0; ! 556: bp->type = M_IOCACK; ! 557: bp->wptr = sp + 1; ! 558: qreply(q, bp); ! 559: return; ! 560: ! 561: case DIOCXWIN: ! 562: bp->type = M_IOCACK; ! 563: if (sp[4] >= 8 || sp[4] <= 0) ! 564: bp->type = M_IOCNAK; ! 565: else if ((x = sp[0] + (sp[1]<<8)) < 0 || x > MAXMSG) ! 566: bp->type = M_IOCNAK; ! 567: else { ! 568: dkpp->xsize = x; ! 569: dkpp->XW = sp[4]; ! 570: if (x > dkpwbig) ! 571: q->flag |= QBIGB; ! 572: else ! 573: q->flag &=~ QBIGB; ! 574: } ! 575: bp->wptr = bp->rptr; ! 576: qreply(q, bp); ! 577: return; ! 578: ! 579: default: ! 580: (*q->next->qinfo->putp)(q->next, bp); ! 581: return; ! 582: } ! 583: ! 584: case M_DELAY: ! 585: x = *bp->rptr; ! 586: *bp->rptr = DELAY; ! 587: bp->type = M_CTL; ! 588: while (x) { ! 589: (*bp->rptr)++; ! 590: x >>= 1; ! 591: } ! 592: goto putonq; ! 593: ! 594: case M_PRICTL: ! 595: (*q->next->qinfo->putp)(q->next, bp); ! 596: return; ! 597: ! 598: default: ! 599: freeb(bp); ! 600: return; ! 601: ! 602: case M_BREAK: ! 603: bp->type = M_CTL; ! 604: *bp->wptr++ = BREAK; ! 605: case M_DATA: ! 606: case M_CTL: ! 607: putonq: ! 608: putq(q, bp); ! 609: if (dkpp->WNX < dkpp->WS+dkpp->XW) ! 610: qenable(q); ! 611: return; ! 612: } ! 613: } ! 614: ! 615: /* ! 616: * Out server: ! 617: * if space in window, process queue ! 618: * This is the only place that WNX is incremented, ! 619: * and the only place xb[i] is set nonzero ! 620: * (remember these facts when thinking about races) ! 621: */ ! 622: dkposrv(q) ! 623: register struct queue *q; ! 624: { ! 625: register struct dkp *dkpp = (struct dkp *)q->ptr; ! 626: register struct block *bp, *xbp; ! 627: register int seqno; ! 628: register struct block **bpp; ! 629: register int s; ! 630: ! 631: if (dkpp->state & (STOPPED|OPENING)) ! 632: return; ! 633: while (dkpp->WNX < dkpp->WS+dkpp->XW) { ! 634: if ((bp = getq(q)) == NULL) ! 635: break; ! 636: /* ! 637: * Bite off one URP block; put back the rest. ! 638: * The initial blocks are passed by reference. ! 639: */ ! 640: if (bp->type==M_DATA && bp->wptr-bp->rptr > dkpp->xsize) { ! 641: xbp = dupb(bp); ! 642: bp->rptr += dkpp->xsize; ! 643: xbp->wptr = xbp->rptr+dkpp->xsize; ! 644: xbp->class &= ~S_DELIM; ! 645: putbq(q, bp); ! 646: bp = xbp; ! 647: } ! 648: if (dkpp->state & XCHARMODE) { ! 649: dkpp->outcnt += bp->wptr - bp->rptr; ! 650: (*q->next->qinfo->putp)(q->next, bp); ! 651: if (dkpp->outcnt >= dkpp->xsize) { ! 652: putctl1d(q->next, M_CTL, SEQ+(dkpp->WNX&07)); ! 653: dkpp->WNX++; ! 654: dkpp->WACK = dkpp->WNX; ! 655: dkpp->outcnt = 0; ! 656: } ! 657: continue; ! 658: } ! 659: TRC('x'); TRC('0'+dkpp->WS/10); TRC('0'+dkpp->WS%10); ! 660: TRC('.'); TRC('0'+dkpp->WNX/10); TRC('0'+dkpp->WNX%10); ! 661: bpp = &dkpp->xb[dkpp->WNX&07]; ! 662: if (*bpp) { ! 663: s = spl5(); /* in case of last-minute ECHO */ ! 664: if (*bpp) { ! 665: freeb(*bpp); ! 666: printf("dkp losing block %x\n", *bpp); ! 667: *bpp = 0; /* if ECHO comes later, don't free twice */ ! 668: } ! 669: splx(s); ! 670: } ! 671: *bpp = bp; ! 672: seqno = dkpp->WNX++; /* in case ECHO comes right away */ ! 673: dkpxmit(q, bp, seqno); ! 674: /* what if INIT[01] arrived between `bpp = ...' and here? */ ! 675: } ! 676: } ! 677: ! 678: /* ! 679: * Send out a message, with trailer. ! 680: */ ! 681: dkpxmit(q, bp, seqno) ! 682: register struct queue *q; ! 683: register struct block *bp; ! 684: { ! 685: register size; ! 686: register struct block *xbp; ! 687: register struct dkp *dkpp = (struct dkp *)q->ptr; ! 688: ! 689: if (bp==NULL) { ! 690: printf("null bp in dkpxmit\n"); ! 691: return; ! 692: } ! 693: size = bp->wptr - bp->rptr; ! 694: seqno &= 07; ! 695: /* send ptr to block, if non-empty */ ! 696: if (size) { ! 697: if ((xbp = dupb(bp)) == NULL) ! 698: return; ! 699: xbp->class &=~ S_DELIM; ! 700: TRC('X'); TRC('0'+seqno); ! 701: (*q->next->qinfo->putp)(q->next, xbp); ! 702: } ! 703: /* send trailer */ ! 704: if ((xbp = allocb(3)) == NULL) ! 705: return; ! 706: xbp->type = M_CTL; ! 707: *xbp->wptr++ = bp->class&S_DELIM? BOT: BOTM; ! 708: *xbp->wptr++ = size; ! 709: *xbp->wptr++ = size >> 8; ! 710: (*q->next->qinfo->putp)(q->next, xbp); ! 711: putctl1d(q->next, M_CTL, SEQ + seqno); ! 712: dkpp->timer = DKPTIME; ! 713: } ! 714: ! 715: /* ! 716: * Receive an ack of some sort for a transmitted message. ! 717: * Advance various windows. ! 718: * should be called at spl5 to avoid races ! 719: */ ! 720: dkprack(dkpp, msg) ! 721: register struct dkp *dkpp; ! 722: { ! 723: register struct block **bpp; ! 724: register seqno, i; ! 725: ! 726: seqno = msg & 07; ! 727: msg &= 0370; ! 728: /* invariants: 0 <= WS <= WACK <= WNX; seqno maximal < WNX; WS < 8 */ ! 729: if (seqno >= dkpp->WNX) ! 730: seqno -= 8; ! 731: else if (seqno+8 < dkpp->WNX) ! 732: seqno += 8; ! 733: dkpp->state &= ~RJING; ! 734: for (i=dkpp->WS; i<=seqno; i++) { ! 735: bpp = &dkpp->xb[i&07]; ! 736: if (*bpp) { ! 737: freeb(*bpp); ! 738: *bpp = NULL; ! 739: } ! 740: } ! 741: if ((int)dkpp->WACK <= seqno) ! 742: dkpp->WACK = seqno+1; ! 743: if (msg==ECHO) { ! 744: TRC('E'); TRC('0'+(seqno&07)); ! 745: if (dkpp->WS <= seqno) { ! 746: dkpp->timer = DKPTIME; /* push off timeout */ ! 747: dkpp->WS = seqno+1; ! 748: if (dkpp->WNX<dkpp->WS+dkpp->XW && WR(dkpp->rdq)->count) ! 749: qenable(WR(dkpp->rdq)); ! 750: } ! 751: } else { ! 752: for (i=dkpp->WACK; i<dkpp->WNX; i++) { ! 753: if (dkpp->xb[i&07]==0) ! 754: printf("WS %d WACK %d WNX %d i %d seqno %d\n", ! 755: dkpp->WS, dkpp->WACK, dkpp->WNX, i, seqno); ! 756: dkpxmit(WR(dkpp->rdq), dkpp->xb[i&07], i); ! 757: dkstat.dkprxmit++; ! 758: } ! 759: } ! 760: if (dkpp->WS >= 8) { ! 761: dkpp->WS -= 8; ! 762: dkpp->WACK -= 8; ! 763: dkpp->WNX -= 8; ! 764: } ! 765: } ! 766: ! 767: dkptimer() ! 768: { ! 769: register struct dkp *dkpp; ! 770: register struct queue *q; ! 771: register int i; ! 772: ! 773: for (dkpp = dkp, i = dkpcnt; i > 0; dkpp++, --i) { ! 774: if ((dkpp->state&(OPEN|OPENING)) == 0) ! 775: continue; ! 776: if (--dkpp->timer>0) ! 777: continue; ! 778: q = WR(dkpp->rdq)->next; ! 779: if (q->flag&QFULL) ! 780: continue; ! 781: if (dkpp->state & XCHARMODE) { ! 782: if (dkpp->WS < dkpp->WNX) ! 783: putctl1d(q, M_CTL, SEQ+((dkpp->WNX-1)&07)); ! 784: dkpp->timer = 10; ! 785: continue; ! 786: } ! 787: if (dkpp->state&OPENING) ! 788: putctl1d(q, M_CTL, INIT1); ! 789: if (dkpp->WS != dkpp->WNX) ! 790: putctl1d(q, M_CTL, ENQ); ! 791: dkpp->timer = DKPTIME; ! 792: } ! 793: timeout(dkptimer, (caddr_t)NULL, HZ); ! 794: } ! 795: ! 796: /* ! 797: * throw away data in front of the barrier, and clear the trailer buffer ! 798: */ ! 799: dkpinflush(dkpp) ! 800: register struct dkp *dkpp; ! 801: { ! 802: register struct block *bp; ! 803: ! 804: while (bp = dkpp->inp) { ! 805: dkpp->inp = bp->next; ! 806: freeb(bp); ! 807: } ! 808: dkpp->inpe = NULL; ! 809: dkpp->trx = 0; ! 810: dkpp->indata = 0; ! 811: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.