|
|
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.