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