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