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