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