|
|
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 date 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; ! 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: for (x=0; x<8; x++) ! 462: if (dkpp->xb[x]) ! 463: dkpp->xb[x]->wptr = dkpp->xb[x]->rptr; ! 464: flushq(q, 0); ! 465: freeb(bp); ! 466: return; ! 467: ! 468: case M_IOCTL: ! 469: sp = (unsigned char *)stiodata(bp); ! 470: switch (stiocom(bp)) { ! 471: ! 472: case TIOCSDEV: ! 473: x = ((struct ttydevb *)sp)->ispeed; ! 474: bp->wptr = bp->rptr; ! 475: bp->type = M_IOCACK; ! 476: qreply(q, bp); ! 477: if (x==0) ! 478: putctl(OTHERQ(q), M_HANGUP); ! 479: return; ! 480: ! 481: case TIOCGDEV: ! 482: ((struct ttydevb *)sp)->ispeed = ((struct ttydevb *)sp)->ospeed = B9600; ! 483: bp->wptr = bp->rptr + sizeof(struct ttydevb) + STIOCHDR; ! 484: if (bp->wptr >= bp->lim) ! 485: panic("dkioc"); ! 486: bp->type = M_IOCACK; ! 487: qreply(q, bp); ! 488: return; ! 489: ! 490: case DIOCSTREAM: ! 491: RD(q)->flag &= ~QDELIM; ! 492: bp->wptr = bp->rptr; ! 493: bp->type = M_IOCACK; ! 494: qreply(q, bp); ! 495: return; ! 496: ! 497: case DIOCRECORD: ! 498: if ((dkpp->state&RCHARMODE) == 0) { ! 499: RD(q)->flag |= QDELIM; ! 500: bp->type = M_IOCACK; ! 501: } else ! 502: bp->type = M_IOCNAK; ! 503: bp->wptr = bp->rptr; ! 504: qreply(q, bp); ! 505: return; ! 506: ! 507: case KIOCINIT: ! 508: if (dkpp->state&XCHARMODE) ! 509: putctl1d(q->next, M_CTL, INIT0); ! 510: else { ! 511: if (dkpp->WS < dkpp->WNX) ! 512: dkprack(dkpp, ECHO+((dkpp->WNX-1)&07)); ! 513: dkpp->WS = 1; ! 514: dkpp->WACK = 1; ! 515: dkpp->WNX = 1; ! 516: putctl1d(q->next, M_CTL, INIT1); ! 517: } ! 518: bp->wptr = bp->rptr; ! 519: bp->type = M_IOCACK; ! 520: qreply(q, bp); ! 521: return; ! 522: ! 523: case KIOCISURP: ! 524: bp->wptr = bp->rptr; ! 525: bp->type = M_IOCACK; ! 526: qreply(q, bp); ! 527: return; ! 528: ! 529: case DIOCSCTL: ! 530: bp->type = M_IOCACK; ! 531: bp->wptr = bp->rptr; ! 532: if (*sp == 0) { ! 533: qreply(q, bp); ! 534: return; ! 535: } ! 536: if ((xbp = allocb(1)) == NULL) ! 537: bp->type = M_IOCNAK; ! 538: else { ! 539: xbp->type = M_CTL; ! 540: xbp->class |= S_DELIM; ! 541: *xbp->wptr++ = *sp; ! 542: putq(q, xbp); ! 543: if (dkpp->WNX < dkpp->WS+dkpp->XW) ! 544: qenable(q); ! 545: } ! 546: qreply(q, bp); ! 547: return; ! 548: ! 549: case DIOCRCTL: ! 550: *sp = dkpp->lastctl; ! 551: dkpp->lastctl = 0; ! 552: bp->type = M_IOCACK; ! 553: bp->wptr = sp + 1; ! 554: qreply(q, bp); ! 555: return; ! 556: ! 557: case DIOCXWIN: ! 558: bp->type = M_IOCACK; ! 559: if (sp[4] >= 8 || sp[4] <= 0) ! 560: bp->type = M_IOCNAK; ! 561: else if ((x = sp[0] + (sp[1]<<8)) < 0 || x > MAXMSG) ! 562: bp->type = M_IOCNAK; ! 563: else { ! 564: dkpp->xsize = x; ! 565: dkpp->XW = sp[4]; ! 566: if (x > dkpwbig) ! 567: q->flag |= QBIGB; ! 568: else ! 569: q->flag &=~ QBIGB; ! 570: } ! 571: bp->wptr = bp->rptr; ! 572: qreply(q, bp); ! 573: return; ! 574: ! 575: default: ! 576: (*q->next->qinfo->putp)(q->next, bp); ! 577: return; ! 578: } ! 579: ! 580: case M_DELAY: ! 581: x = *bp->rptr; ! 582: *bp->rptr = DELAY; ! 583: bp->type = M_CTL; ! 584: while (x) { ! 585: (*bp->rptr)++; ! 586: x >>= 1; ! 587: } ! 588: goto putonq; ! 589: ! 590: case M_PRICTL: ! 591: (*q->next->qinfo->putp)(q->next, bp); ! 592: return; ! 593: ! 594: default: ! 595: freeb(bp); ! 596: return; ! 597: ! 598: case M_BREAK: ! 599: bp->type = M_CTL; ! 600: *bp->wptr++ = BREAK; ! 601: case M_DATA: ! 602: case M_CTL: ! 603: putonq: ! 604: putq(q, bp); ! 605: if (dkpp->WNX < dkpp->WS+dkpp->XW) ! 606: qenable(q); ! 607: return; ! 608: } ! 609: } ! 610: ! 611: /* ! 612: * Out server: ! 613: * if space in window, process queue ! 614: */ ! 615: dkposrv(q) ! 616: register struct queue *q; ! 617: { ! 618: register struct dkp *dkpp = (struct dkp *)q->ptr; ! 619: register struct block *bp, *xbp; ! 620: register int seqno; ! 621: ! 622: if (dkpp->state & (STOPPED|OPENING)) ! 623: return; ! 624: while (dkpp->WNX < dkpp->WS+dkpp->XW) { ! 625: if ((bp = getq(q)) == NULL) ! 626: break; ! 627: /* ! 628: * Bite off one URP block; put back the rest. ! 629: * The initial blocks are passed by reference. ! 630: */ ! 631: if (bp->type==M_DATA && bp->wptr-bp->rptr > dkpp->xsize) { ! 632: xbp = dupb(bp); ! 633: bp->rptr += dkpp->xsize; ! 634: xbp->wptr = xbp->rptr+dkpp->xsize; ! 635: xbp->class &= ~S_DELIM; ! 636: putbq(q, bp); ! 637: bp = xbp; ! 638: } ! 639: if (dkpp->state & XCHARMODE) { ! 640: dkpp->outcnt += bp->wptr - bp->rptr; ! 641: (*q->next->qinfo->putp)(q->next, bp); ! 642: if (dkpp->outcnt >= dkpp->xsize) { ! 643: putctl1d(q->next, M_CTL, SEQ+(dkpp->WNX&07)); ! 644: dkpp->WNX++; ! 645: dkpp->WACK = dkpp->WNX; ! 646: dkpp->outcnt = 0; ! 647: } ! 648: continue; ! 649: } ! 650: TRC('x'); TRC('0'+dkpp->WS/10); TRC('0'+dkpp->WS%10); ! 651: TRC('.'); TRC('0'+dkpp->WNX/10); TRC('0'+dkpp->WNX%10); ! 652: if (dkpp->xb[dkpp->WNX&07]) { ! 653: freeb(dkpp->xb[dkpp->WNX&07]); ! 654: printf("dkp losing block\n"); ! 655: } ! 656: dkpp->xb[dkpp->WNX & 07] = bp; ! 657: seqno = dkpp->WNX++; /* in case ECHO comes right away */ ! 658: dkpxmit(q, bp, seqno); ! 659: } ! 660: } ! 661: ! 662: /* ! 663: * Send out a message, with trailer. ! 664: */ ! 665: dkpxmit(q, bp, seqno) ! 666: register struct queue *q; ! 667: register struct block *bp; ! 668: { ! 669: register size; ! 670: register struct block *xbp; ! 671: register struct dkp *dkpp = (struct dkp *)q->ptr; ! 672: ! 673: if (bp==NULL) { ! 674: printf("null bp in dkpxmit\n"); ! 675: return; ! 676: } ! 677: size = bp->wptr - bp->rptr; ! 678: seqno &= 07; ! 679: /* send ptr to block, if non-empty */ ! 680: if (size) { ! 681: if ((xbp = dupb(bp)) == NULL) ! 682: return; ! 683: xbp->class &=~ S_DELIM; ! 684: TRC('X'); TRC('0'+seqno); ! 685: (*q->next->qinfo->putp)(q->next, xbp); ! 686: } ! 687: /* send trailer */ ! 688: if ((xbp = allocb(3)) == NULL) ! 689: return; ! 690: xbp->type = M_CTL; ! 691: *xbp->wptr++ = bp->class&S_DELIM? BOT: BOTM; ! 692: *xbp->wptr++ = size; ! 693: *xbp->wptr++ = size >> 8; ! 694: (*q->next->qinfo->putp)(q->next, xbp); ! 695: putctl1d(q->next, M_CTL, SEQ + seqno); ! 696: dkpp->timer = DKPTIME; ! 697: } ! 698: ! 699: /* ! 700: * Receive an ack of some sort for a transmitted message. ! 701: * Advance various windows. ! 702: */ ! 703: dkprack(dkpp, msg) ! 704: register struct dkp *dkpp; ! 705: { ! 706: register struct block **bpp; ! 707: register seqno, i; ! 708: ! 709: seqno = msg & 07; ! 710: msg &= 0370; ! 711: /* invariants: 0 <= WS <= WACK <= WNX; seqno maximal < WNX; WS < 8 */ ! 712: if (seqno >= dkpp->WNX) ! 713: seqno -= 8; ! 714: else if (seqno+8 < dkpp->WNX) ! 715: seqno += 8; ! 716: dkpp->state &= ~RJING; ! 717: for (i=dkpp->WS; i<=seqno; i++) { ! 718: bpp = &dkpp->xb[i&07]; ! 719: if (*bpp) { ! 720: freeb(*bpp); ! 721: *bpp = NULL; ! 722: } ! 723: } ! 724: if ((int)dkpp->WACK <= seqno) ! 725: dkpp->WACK = seqno+1; ! 726: if (msg==ECHO) { ! 727: TRC('E'); TRC('0'+(seqno&07)); ! 728: if (dkpp->WS <= seqno) { ! 729: dkpp->timer = DKPTIME; /* push off timeout */ ! 730: dkpp->WS = seqno+1; ! 731: if (dkpp->WNX<dkpp->WS+dkpp->XW && WR(dkpp->rdq)->count) ! 732: qenable(WR(dkpp->rdq)); ! 733: } ! 734: } else { ! 735: for (i=dkpp->WACK; i<dkpp->WNX; i++) { ! 736: if (dkpp->xb[i&07]==0) ! 737: printf("WS %d WACK %d WNX %d i %d seqno %d\n", ! 738: dkpp->WS, dkpp->WACK, dkpp->WNX, i, seqno); ! 739: dkpxmit(WR(dkpp->rdq), dkpp->xb[i&07], i); ! 740: dkstat.dkprxmit++; ! 741: } ! 742: } ! 743: if (dkpp->WS >= 8) { ! 744: dkpp->WS -= 8; ! 745: dkpp->WACK -= 8; ! 746: dkpp->WNX -= 8; ! 747: } ! 748: } ! 749: ! 750: dkptimer() ! 751: { ! 752: register struct dkp *dkpp; ! 753: register struct queue *q; ! 754: register int i; ! 755: ! 756: for (dkpp = dkp, i = dkpcnt; i > 0; dkpp++, --i) { ! 757: if ((dkpp->state&(OPEN|OPENING)) == 0) ! 758: continue; ! 759: if (--dkpp->timer>0) ! 760: continue; ! 761: q = WR(dkpp->rdq)->next; ! 762: if (q->flag&QFULL) ! 763: continue; ! 764: if (dkpp->state & XCHARMODE) { ! 765: if (dkpp->WS < dkpp->WNX) ! 766: putctl1d(q, M_CTL, SEQ+((dkpp->WNX-1)&07)); ! 767: dkpp->timer = 10; ! 768: continue; ! 769: } ! 770: if (dkpp->state&OPENING) ! 771: putctl1d(q, M_CTL, INIT1); ! 772: if (dkpp->WS != dkpp->WNX) ! 773: putctl1d(q, M_CTL, ENQ); ! 774: dkpp->timer = DKPTIME; ! 775: } ! 776: timeout(dkptimer, (caddr_t)NULL, HZ); ! 777: } ! 778: ! 779: /* ! 780: * throw away data in front of the barrier, and clear the trailer buffer ! 781: */ ! 782: dkpinflush(dkpp) ! 783: register struct dkp *dkpp; ! 784: { ! 785: register struct block *bp; ! 786: ! 787: while (bp = dkpp->inp) { ! 788: dkpp->inp = bp->next; ! 789: freeb(bp); ! 790: } ! 791: dkpp->inpe = NULL; ! 792: dkpp->trx = 0; ! 793: dkpp->indata = 0; ! 794: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.