|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)pk0.c 5.1 (Berkeley) 7/2/83";
3: #endif
4:
5: extern char *malloc();
6:
7: #define USER 1
8: #include <stdio.h>
9: #ifdef SYSIII
10: #include <sys/types.h>
11: #endif
12: #include "pk.p"
13: #include <sys/param.h>
14: #include "pk.h"
15: #include <sys/buf.h>
16:
17:
18: /*
19: * packet driver
20: */
21:
22: char next[8] ={ 1,2,3,4,5,6,7,0}; /* packet sequence numbers */
23: char mask[8] ={ 1,2,4,010,020,040,0100,0200 };
24:
25: struct pack *pklines[NPLINES];
26:
27: /*
28: * Here are a couple of strange variables (rti!trt).
29: * pkactive is only incremented in pkopen.
30: * perhaps it should be decremented in pkclose?
31: * And pkdebug is set in gio.c but never used.
32: */
33: int pkactive;
34: int pkdebug;
35:
36: /*
37: * receive control messages
38: */
39: pkcntl(c, pk)
40: register struct pack *pk;
41: {
42: register cntl, val;
43:
44: val = c & MOD8;
45: cntl = (c>>3) & MOD8;
46:
47: if ( ! ISCNTL(c) ) {
48: fprintf(stderr, "not cntl\n");
49: return;
50: }
51:
52: if (pk->p_mode & 02)
53: fprintf(stderr, "%o ",c);
54: switch(cntl) {
55:
56: case INITB:
57: val++;
58: pk->p_xsize = pksizes[val];
59: pk->p_lpsize = val;
60: pk->p_bits = DTOM(pk->p_xsize);
61: if (pk->p_state & LIVE) {
62: pk->p_msg |= M_INITC;
63: break;
64: }
65: pk->p_state |= INITb;
66: if ((pk->p_state & INITa)==0) {
67: break;
68: }
69: pk->p_rmsg &= ~M_INITA;
70: pk->p_msg |= M_INITC;
71: break;
72:
73: case INITC:
74: if ((pk->p_state&INITab)==INITab) {
75: pk->p_state = LIVE;
76: WAKEUP(&pk->p_state);
77: pk->p_rmsg &= ~M_INITB;
78: } else
79: pk->p_msg |= M_INITB;
80: if (val)
81: pk->p_swindow = val;
82: break;
83: case INITA:
84: if (val==0 && pk->p_state&LIVE) {
85: fprintf(stderr, "alloc change not implemented\n");
86: break;
87: }
88: if (val) {
89: pk->p_state |= INITa;
90: pk->p_msg |= M_INITB;
91: pk->p_rmsg |= M_INITB;
92: pk->p_swindow = val;
93: }
94: break;
95: case RJ:
96: pk->p_state |= RXMIT;
97: pk->p_msg |= M_RR;
98: case RR:
99: pk->p_rpr = val;
100: if (pksack(pk)==0) {
101: WAKEUP(&pk->p_ps);
102: }
103: break;
104: case SRJ:
105: fprintf(stderr, "srj not implemented\n");
106: break;
107: case CLOSE:
108: pk->p_state = DOWN+RCLOSE;
109: SIGNAL;
110: WAKEUP(&pk->p_pr);
111: WAKEUP(&pk->p_ps);
112: WAKEUP(&pk->p_state);
113: return;
114: }
115: out:
116: if (pk->p_msg)
117: pkoutput(pk);
118: }
119:
120:
121:
122: pkaccept(pk)
123: register struct pack *pk;
124: {
125: register x,seq;
126: char m, cntl, *p, imask, **bp;
127: int bad,accept,skip,s,t,h,cc;
128: unsigned short sum;
129:
130:
131: bad = accept = skip = 0;
132: /*
133: * wait for input
134: */
135: LOCK;
136: x = next[pk->p_pr];
137: while ((imask=pk->p_imap) == 0 && pk->p_rcount==0) {
138: PKGETPKT(pk);
139: SLEEP(&pk->p_pr, PKIPRI);
140: }
141: pk->p_imap = 0;
142: UNLOCK;
143:
144:
145: /*
146: * determine input window in m.
147: */
148: t = (~(-1<<(int)(pk->p_rwindow))) <<x;
149: m = t;
150: m |= t>>8;
151:
152:
153: /*
154: * mark newly accepted input buffers
155: */
156: for(x=0; x<8; x++) {
157:
158: if ((imask & mask[x]) == 0)
159: continue;
160:
161: if (((cntl=pk->p_is[x])&0200)==0) {
162: bad++;
163: free:
164: bp = (char **)pk->p_ib[x];
165: LOCK;
166: *bp = (char *)pk->p_ipool;
167: pk->p_ipool = bp;
168: pk->p_is[x] = 0;
169: UNLOCK;
170: continue;
171: }
172:
173: pk->p_is[x] = ~(B_COPY+B_MARK);
174: sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)(cntl&0377);
175: sum += pk->p_isum[x];
176: if (sum == CHECK) {
177: seq = (cntl>>3) & MOD8;
178: if (m & mask[seq]) {
179: if (pk->p_is[seq] & (B_COPY | B_MARK)) {
180: dup:
181: pk->p_msg |= M_RR;
182: skip++;
183: goto free;
184: }
185: if (x != seq) {
186: LOCK;
187: p = pk->p_ib[x];
188: pk->p_ib[x] = pk->p_ib[seq];
189: pk->p_is[x] = pk->p_is[seq];
190: pk->p_ib[seq] = p;
191: UNLOCK;
192: }
193: pk->p_is[seq] = B_MARK;
194: accept++;
195: cc = 0;
196: if (cntl&B_SHORT) {
197: pk->p_is[seq] = B_MARK+B_SHORT;
198: p = pk->p_ib[seq];
199: cc = (unsigned)*p++ & 0377;
200: if (cc & 0200) {
201: cc &= 0177;
202: cc |= *p << 7;
203: }
204: }
205: pk->p_isum[seq] = pk->p_rsize - cc;
206: } else {
207: goto dup;
208: }
209: } else {
210: bad++;
211: goto free;
212: }
213: }
214:
215: /*
216: * scan window again turning marked buffers into
217: * COPY buffers and looking for missing sequence
218: * numbers.
219: */
220: accept = 0;
221: for(x=next[pk->p_pr],t=h= -1; m & mask[x]; x = next[x]) {
222: if (pk->p_is[x] & B_MARK)
223: pk->p_is[x] |= B_COPY;
224: /* hole code
225: if (pk->p_is[x] & B_COPY) {
226: if (h<0 && t>=0)
227: h = x;
228: } else {
229: if (t<0)
230: t = x;
231: }
232: */
233: if (pk->p_is[x] & B_COPY) {
234: if (t >= 0) {
235: bp = (char **)pk->p_ib[x];
236: LOCK;
237: *bp = (char *)pk->p_ipool;
238: pk->p_ipool = bp;
239: pk->p_is[x] = 0;
240: UNLOCK;
241: skip++;
242: } else
243: accept++;
244: } else {
245: if (t<0)
246: t = x;
247: }
248: }
249:
250: if (bad) {
251: pk->p_msg |= M_RJ;
252: }
253:
254: if (skip) {
255: pk->p_msg |= M_RR;
256: }
257:
258: pk->p_rcount = accept;
259: return(accept);
260: }
261:
262:
263: pkread(S)
264: SDEF;
265: {
266: register struct pack *pk;
267: register x,s;
268: int is,cc,xfr,count;
269: char *cp, **bp;
270:
271: pk = PADDR;
272: xfr = 0;
273: count = 0;
274: while (pkaccept(pk)==0);
275:
276:
277: while (UCOUNT) {
278:
279: x = next[pk->p_pr];
280: is = pk->p_is[x];
281:
282: if (is & B_COPY) {
283: cc = MIN(pk->p_isum[x], UCOUNT);
284: if (cc==0 && xfr) {
285: break;
286: }
287: if (is & B_RESID)
288: cp = pk->p_rptr;
289: else {
290: cp = pk->p_ib[x];
291: if (is & B_SHORT) {
292: if (*cp++ & 0200)
293: cp++;
294: }
295: }
296: IOMOVE(cp,cc,B_READ);
297: count += cc;
298: xfr++;
299: pk->p_isum[x] -= cc;
300: if (pk->p_isum[x] == 0) {
301: pk->p_pr = x;
302: bp = (char **)pk->p_ib[x];
303: LOCK;
304: *bp = (char *)pk->p_ipool;
305: pk->p_ipool = bp;
306: pk->p_is[x] = 0;
307: pk->p_rcount--;
308: UNLOCK;
309: pk->p_msg |= M_RR;
310: } else {
311: pk->p_rptr = cp+cc;
312: pk->p_is[x] |= B_RESID;
313: }
314: if (cc==0)
315: break;
316: } else
317: break;
318: }
319: pkoutput(pk);
320: return(count);
321: }
322:
323:
324:
325:
326: pkwrite(S)
327: SDEF;
328: {
329: register struct pack *pk;
330: register x;
331: int partial;
332: caddr_t cp;
333: int cc, s, fc, count;
334:
335: pk = PADDR;
336: if (pk->p_state&DOWN || !pk->p_state&LIVE) {
337: SETERROR;
338: return(-1);
339: }
340:
341: count = UCOUNT;
342: do {
343: LOCK;
344: while (pk->p_xcount>=pk->p_swindow) {
345: pkoutput(pk);
346: PKGETPKT(pk);
347: SLEEP(&pk->p_ps,PKOPRI);
348: }
349: x = next[pk->p_pscopy];
350: while (pk->p_os[x]!=B_NULL) {
351: PKGETPKT(pk);
352: SLEEP(&pk->p_ps,PKOPRI);
353: }
354: pk->p_os[x] = B_MARK;
355: pk->p_pscopy = x;
356: pk->p_xcount++;
357: UNLOCK;
358:
359: cp = pk->p_ob[x] = GETEPACK;
360: partial = 0;
361: if ((int)UCOUNT < pk->p_xsize) {
362: cc = UCOUNT;
363: fc = pk->p_xsize - cc;
364: *cp = fc&0177;
365: if (fc > 127) {
366: *cp++ |= 0200;
367: *cp++ = fc>>7;
368: } else
369: cp++;
370: partial = B_SHORT;
371: } else
372: cc = pk->p_xsize;
373: IOMOVE(cp,cc,B_WRITE);
374: pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize);
375: pk->p_os[x] = B_READY+partial;
376: pkoutput(pk);
377: } while (UCOUNT);
378:
379: return(count);
380: }
381:
382: pksack(pk)
383: register struct pack *pk;
384: {
385: register x, i;
386:
387: i = 0;
388: for(x=pk->p_ps; x!=pk->p_rpr; ) {
389: x = next[x];
390: if (pk->p_os[x]&B_SENT) {
391: i++;
392: pk->p_os[x] = B_NULL;
393: pk->p_state &= ~WAITO;
394: pk->p_xcount--;
395: FREEPACK(pk->p_ob[x], pk->p_bits);
396: pk->p_ps = x;
397: WAKEUP(&pk->p_ps);
398: }
399: }
400: return(i);
401: }
402:
403:
404:
405: pkoutput(pk)
406: register struct pack *pk;
407: {
408: register x,rx;
409: int s;
410: char bstate;
411: int i;
412: SDEF;
413: int flag;
414:
415: flag = 0;
416: ISYSTEM;
417: LOCK;
418: if (pk->p_obusy++ || OBUSY) {
419: pk->p_obusy--;
420: UNLOCK;
421: return;
422: }
423: UNLOCK;
424:
425:
426: /*
427: * find seq number and buffer state
428: * of next output packet
429: */
430: if (pk->p_state&RXMIT) {
431: pk->p_nxtps = next[pk->p_rpr];
432: flag++;
433: }
434: x = pk->p_nxtps;
435: bstate = pk->p_os[x];
436:
437:
438: /*
439: * Send control packet if indicated
440: */
441: if (pk->p_msg) {
442: if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) {
443: x = pk->p_msg;
444: for(i=0; i<8; i++)
445: if (x&1)
446: break; else
447: x >>= 1;
448: x = i;
449: x <<= 3;
450: switch(i) {
451: case CLOSE:
452: break;
453: case RJ:
454: case RR:
455: x += pk->p_pr;
456: break;
457: case SRJ:
458: break;
459: case INITB:
460: x += pksize(pk->p_rsize);
461: break;
462: case INITC:
463: x += pk->p_rwindow;
464: break;
465: case INITA:
466: x += pk->p_rwindow;
467: break;
468: }
469:
470: pk->p_msg &= ~mask[i];
471: pkxstart(pk, x, -1);
472: goto out;
473: }
474: }
475:
476:
477: /*
478: * Don't send data packets if line is marked dead.
479: */
480: if (pk->p_state&DOWN) {
481: WAKEUP(&pk->p_ps);
482: goto out;
483: }
484: /*
485: * Start transmission (or retransmission) of data packets.
486: */
487: if (bstate & (B_READY|B_SENT)) {
488: char seq;
489:
490: bstate |= B_SENT;
491: seq = x;
492: pk->p_nxtps = next[x];
493:
494: x = 0200+pk->p_pr+(seq<<3);
495: if (bstate & B_SHORT)
496: x |= 0100;
497: pkxstart(pk, x, seq);
498: pk->p_os[seq] = bstate;
499: pk->p_state &= ~RXMIT;
500: pk->p_nout++;
501: goto out;
502: }
503: /*
504: * enable timeout if there's nothing to send
505: * and transmission buffers are languishing
506: */
507: if (pk->p_xcount) {
508: pk->p_timer = 2;
509: pk->p_state |= WAITO;
510: } else
511: pk->p_state &= ~WAITO;
512: WAKEUP(&pk->p_ps);
513: out:
514: pk->p_obusy = 0;
515: }
516:
517:
518: /*
519: * shut down line by
520: * ignoring new input
521: * letting output drain
522: * releasing space and turning off line discipline
523: */
524: pkclose(S)
525: SDEF;
526: {
527: register struct pack *pk;
528: register i,s,rbits;
529: char **bp;
530: int rcheck;
531: char *p;
532:
533:
534: pk = PADDR;
535: pk->p_state |= DRAINO;
536:
537:
538: /*
539: * try to flush output
540: */
541: i = 0;
542: LOCK;
543: pk->p_timer = 2;
544: while (pk->p_xcount && pk->p_state&LIVE) {
545: if (pk->p_state&(RCLOSE+DOWN) || ++i > 2)
546: break;
547: pkoutput(pk);
548: SLEEP(&pk->p_ps,PKOPRI);
549: }
550: pk->p_timer = 0;
551: pk->p_state |= DOWN;
552: UNLOCK;
553:
554:
555: /*
556: * try to exchange CLOSE messages
557: */
558: i = 0;
559: while ((pk->p_state&RCLOSE)==0 && i<2) {
560: pk->p_msg = M_CLOSE;
561: pk->p_timer = 2;
562: pkoutput(pk);
563: SLEEP(&pk->p_ps, PKOPRI);
564: i++;
565: }
566:
567:
568: for(i=0;i<NPLINES;i++)
569: if (pklines[i]==pk) {
570: pklines[i] = NULL;
571: }
572: TURNOFF;
573:
574:
575: /*
576: * free space
577: */
578: rbits = DTOM(pk->p_rsize);
579: rcheck = 0;
580: for (i=0;i<8;i++) {
581: if (pk->p_os[i]!=B_NULL) {
582: FREEPACK(pk->p_ob[i],pk->p_bits);
583: pk->p_xcount--;
584: }
585: if (pk->p_is[i]!=B_NULL) {
586: FREEPACK(pk->p_ib[i],rbits);
587: rcheck++;
588: }
589: }
590: LOCK;
591: while (pk->p_ipool != NULL) {
592: bp = pk->p_ipool;
593: pk->p_ipool = (char **)*bp;
594: rcheck++;
595: FREEPACK(bp, rbits);
596: }
597: UNLOCK;
598: if (rcheck != pk->p_rwindow) {
599: fprintf(stderr, "r short %d want %d\n",rcheck,pk->p_rwindow);
600: fprintf(stderr, "rcount = %d\n",pk->p_rcount);
601: fprintf(stderr, "xcount = %d\n",pk->p_xcount);
602: }
603: FREEPACK((caddr_t)pk, npbits);
604: }
605:
606:
607:
608: pkreset(pk)
609: register struct pack *pk;
610: {
611:
612: pk->p_ps = pk->p_pr = pk->p_rpr = 0;
613: pk->p_nxtps = 1;
614: }
615:
616: chksum(s,n)
617: register char *s;
618: register n;
619: {
620: register unsigned sum, t;
621: register x;
622:
623: sum = -1;
624: x = 0;
625:
626: do {
627: if (sum&0x8000) {
628: sum <<= 1;
629: sum++;
630: } else
631: sum <<= 1;
632: t = sum;
633: sum += (unsigned)*s++ & 0377;
634: x += sum^n;
635: if ((sum&0xffff) <= (t&0xffff)) {
636: sum ^= x;
637: }
638: } while (--n > 0);
639:
640: return(sum & 0xffff);
641: }
642:
643: pkline(pk)
644: register struct pack *pk;
645: {
646: register i;
647: for(i=0;i<NPLINES;i++) {
648: if (pklines[i]==pk)
649: return(i);
650: }
651: return(-i);
652: }
653:
654: pkzero(s,n)
655: register char *s;
656: register n;
657: {
658: while (n--)
659: *s++ = 0;
660: }
661:
662: pksize(n)
663: register n;
664: {
665: register k;
666:
667: n >>= 5;
668: for(k=0; n >>= 1; k++);
669: return(k);
670: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.