xref: /csrg-svn/usr.bin/uucp/uucico/pk0.c (revision 18620)
113663Ssam #ifndef lint
2*18620Sralph static char sccsid[] = "@(#)pk0.c	5.3 (Berkeley) 04/10/85";
313663Ssam #endif
413663Ssam 
5*18620Sralph #include "uucp.h"
613663Ssam #include "pk.h"
713663Ssam 
813663Ssam /*
913663Ssam  * packet driver
1013663Ssam  */
1113663Ssam 
1217836Sralph char next[8] = { 1, 2, 3, 4, 5, 6, 7, 0};	/* packet sequence numbers */
1317836Sralph char mask[8] = { 1, 2, 4, 010, 020, 040, 0100, 0200 };
1413663Ssam 
1513663Ssam struct pack *pklines[NPLINES];
1613663Ssam int	pkactive;
1717836Sralph long chksum();
1813663Ssam 
1913663Ssam /*
2013663Ssam  * receive control messages
2113663Ssam  */
2213663Ssam pkcntl(c, pk)
2313663Ssam register struct pack *pk;
2413663Ssam {
2517836Sralph 	register cntl, val;
2613663Ssam 
2713663Ssam 	val = c & MOD8;
2813663Ssam 	cntl = (c>>3) & MOD8;
2913663Ssam 
3017836Sralph 	if (!ISCNTL(c)) {
3117836Sralph 		logent("PK0", "not cntl");
3213663Ssam 		return;
3313663Ssam 	}
3413663Ssam 
3513663Ssam 	switch(cntl) {
3613663Ssam 	case INITB:
3713663Ssam 		val++;
3813663Ssam 		pk->p_xsize = pksizes[val];
3913663Ssam 		pk->p_lpsize = val;
4017836Sralph 		pk->p_bits = 1;
4113663Ssam 		if (pk->p_state & LIVE) {
4213663Ssam 			pk->p_msg |= M_INITC;
4313663Ssam 			break;
4413663Ssam 		}
4513663Ssam 		pk->p_state |= INITb;
4613663Ssam 		if ((pk->p_state & INITa)==0) {
4713663Ssam 			break;
4813663Ssam 		}
4913663Ssam 		pk->p_rmsg &= ~M_INITA;
5013663Ssam 		pk->p_msg |= M_INITC;
5113663Ssam 		break;
5213663Ssam 
5313663Ssam 	case INITC:
5413663Ssam 		if ((pk->p_state&INITab)==INITab) {
5513663Ssam 			pk->p_state = LIVE;
5613663Ssam 			pk->p_rmsg &= ~M_INITB;
5713663Ssam 		} else
5813663Ssam 			pk->p_msg |= M_INITB;
5913663Ssam 		if (val)
6013663Ssam 			pk->p_swindow = val;
6113663Ssam 		break;
6213663Ssam 	case INITA:
6317836Sralph 		if (val == 0 && pk->p_state&LIVE) {
6417836Sralph 			logent("PK0", "alloc change not implemented");
6513663Ssam 			break;
6613663Ssam 		}
6713663Ssam 		if (val) {
6813663Ssam 			pk->p_state |= INITa;
6913663Ssam 			pk->p_msg |= M_INITB;
7013663Ssam 			pk->p_rmsg |= M_INITB;
7113663Ssam 			pk->p_swindow = val;
7213663Ssam 		}
7313663Ssam 		break;
7413663Ssam 	case RJ:
7513663Ssam 		pk->p_state |= RXMIT;
7613663Ssam 		pk->p_msg |= M_RR;
7713663Ssam 	case RR:
7813663Ssam 		pk->p_rpr = val;
7917836Sralph 		(void) pksack(pk);
8013663Ssam 		break;
8113663Ssam 	case SRJ:
8217836Sralph 		logent("PK0", "srj not implemented");
8313663Ssam 		break;
8413663Ssam 	case CLOSE:
8513663Ssam 		pk->p_state = DOWN+RCLOSE;
8613663Ssam 		return;
8713663Ssam 	}
8813663Ssam 	if (pk->p_msg)
8913663Ssam 		pkoutput(pk);
9013663Ssam }
9113663Ssam 
9213663Ssam pkaccept(pk)
9313663Ssam register struct pack *pk;
9413663Ssam {
9517836Sralph 	register x, seq;
9617836Sralph 	char m, cntl, *p, imask, **bp;
9717836Sralph 	int bad, accept, skip, t,  cc;
9817836Sralph 	unsigned short sum;
9913663Ssam 
10013663Ssam 	bad = accept = skip = 0;
10113663Ssam 	/*
10213663Ssam 	 * wait for input
10313663Ssam 	 */
10413663Ssam 	x = next[pk->p_pr];
10517836Sralph 	while ((imask=pk->p_imap) == 0 && pk->p_rcount == 0) {
10617836Sralph 		pkgetpack(pk);
10713663Ssam 	}
10813663Ssam 	pk->p_imap = 0;
10913663Ssam 
11013663Ssam 	/*
11113663Ssam 	 * determine input window in m.
11213663Ssam 	 */
11313663Ssam 	t = (~(-1<<(int)(pk->p_rwindow))) <<x;
11413663Ssam 	m = t;
11513663Ssam 	m |= t>>8;
11613663Ssam 
11713663Ssam 	/*
11813663Ssam 	 * mark newly accepted input buffers
11913663Ssam 	 */
12013663Ssam 	for(x=0; x<8; x++) {
12113663Ssam 		if ((imask & mask[x]) == 0)
12213663Ssam 			continue;
12313663Ssam 
12417836Sralph 		if (((cntl=pk->p_is[x])&0200) == 0) {
12513663Ssam 			bad++;
12613663Ssam free:
12713663Ssam 			bp = (char **)pk->p_ib[x];
12813663Ssam 			*bp = (char *)pk->p_ipool;
12913663Ssam 			pk->p_ipool = bp;
13013663Ssam 			pk->p_is[x] = 0;
13113663Ssam 			continue;
13213663Ssam 		}
13313663Ssam 
13413663Ssam 		pk->p_is[x] = ~(B_COPY+B_MARK);
13513663Ssam 		sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)(cntl&0377);
13613663Ssam 		sum += pk->p_isum[x];
13713663Ssam 		if (sum == CHECK) {
13813663Ssam 			seq = (cntl>>3) & MOD8;
13913663Ssam 			if (m & mask[seq]) {
14013663Ssam 				if (pk->p_is[seq] & (B_COPY | B_MARK)) {
14113663Ssam 				dup:
14213663Ssam 					pk->p_msg |= M_RR;
14313663Ssam 					skip++;
14413663Ssam 					goto free;
14513663Ssam 				}
14613663Ssam 				if (x != seq) {
14713663Ssam 					p = pk->p_ib[x];
14813663Ssam 					pk->p_ib[x] = pk->p_ib[seq];
14913663Ssam 					pk->p_is[x] = pk->p_is[seq];
15013663Ssam 					pk->p_ib[seq] = p;
15113663Ssam 				}
15213663Ssam 				pk->p_is[seq] = B_MARK;
15313663Ssam 				accept++;
15413663Ssam 				cc = 0;
15513663Ssam 				if (cntl&B_SHORT) {
15613663Ssam 					pk->p_is[seq] = B_MARK+B_SHORT;
15713663Ssam 					p = pk->p_ib[seq];
15813663Ssam 					cc = (unsigned)*p++ & 0377;
15913663Ssam 					if (cc & 0200) {
16013663Ssam 						cc &= 0177;
16113663Ssam 						cc |= *p << 7;
16213663Ssam 					}
16313663Ssam 				}
16413663Ssam 				pk->p_isum[seq] = pk->p_rsize - cc;
16513663Ssam 			} else {
16613663Ssam 				goto dup;
16713663Ssam 			}
16813663Ssam 		} else {
16913663Ssam 			bad++;
17013663Ssam 			goto free;
17113663Ssam 		}
17213663Ssam 	}
17313663Ssam 
17413663Ssam 	/*
17513663Ssam 	 * scan window again turning marked buffers into
17613663Ssam 	 * COPY buffers and looking for missing sequence
17713663Ssam 	 * numbers.
17813663Ssam 	 */
17913663Ssam 	accept = 0;
18017836Sralph 	t = -1;
18117836Sralph 	for(x=next[pk->p_pr]; m & mask[x]; x = next[x]) {
18213663Ssam 		if (pk->p_is[x] & B_MARK)
18313663Ssam 			pk->p_is[x] |= B_COPY;
18417836Sralph 
18513663Ssam 		if (pk->p_is[x] & B_COPY) {
18613663Ssam 			if (t >= 0) {
18713663Ssam 				bp = (char **)pk->p_ib[x];
18813663Ssam 				*bp = (char *)pk->p_ipool;
18913663Ssam 				pk->p_ipool = bp;
19013663Ssam 				pk->p_is[x] = 0;
19113663Ssam 				skip++;
19217836Sralph 			} else
19313663Ssam 				accept++;
19413663Ssam 		} else {
19513663Ssam 			if (t<0)
19613663Ssam 				t = x;
19713663Ssam 		}
19813663Ssam 	}
19913663Ssam 
20013663Ssam 	if (bad) {
20113663Ssam 		pk->p_msg |= M_RJ;
20213663Ssam 	}
20313663Ssam 
20413663Ssam 	if (skip) {
20513663Ssam 		pk->p_msg |= M_RR;
20613663Ssam 	}
20713663Ssam 
20813663Ssam 	pk->p_rcount = accept;
20917836Sralph 	return accept;
21013663Ssam }
21113663Ssam 
21217836Sralph /*ARGSUSED*/
21317836Sralph pkread(ipk, ibuf, icount)
21417836Sralph int icount;
21517836Sralph char *ibuf;
21617836Sralph struct pack *ipk;
21713663Ssam {
21817836Sralph 	register struct pack *pk;
21917836Sralph 	register x;
22017836Sralph 	int is, cc, xfr, count;
22117836Sralph 	char *cp, **bp;
22213663Ssam 
22317836Sralph 	pk = ipk;
22413663Ssam 	xfr = 0;
22513663Ssam 	count = 0;
22617836Sralph 	while (pkaccept(pk) == 0)
22717836Sralph 		;
22813663Ssam 
22917836Sralph 	while (icount) {
23013663Ssam 		x = next[pk->p_pr];
23113663Ssam 		is = pk->p_is[x];
23213663Ssam 
23313663Ssam 		if (is & B_COPY) {
23417836Sralph 			cc = MIN(pk->p_isum[x], icount);
23513663Ssam 			if (cc==0 && xfr) {
23613663Ssam 				break;
23713663Ssam 			}
23813663Ssam 			if (is & B_RESID)
23913663Ssam 				cp = pk->p_rptr;
24013663Ssam 			else {
24113663Ssam 				cp = pk->p_ib[x];
24213663Ssam 				if (is & B_SHORT) {
24313663Ssam 					if (*cp++ & 0200)
24413663Ssam 						cp++;
24513663Ssam 				}
24613663Ssam 			}
24717836Sralph 			pkmove(cp, ibuf, cc, B_READ);
24817836Sralph 			ibuf += cc;
24917836Sralph 			icount -= cc;
25013663Ssam 			count += cc;
25113663Ssam 			xfr++;
25213663Ssam 			pk->p_isum[x] -= cc;
25313663Ssam 			if (pk->p_isum[x] == 0) {
25413663Ssam 				pk->p_pr = x;
25513663Ssam 				bp = (char **)pk->p_ib[x];
25613663Ssam 				*bp = (char *)pk->p_ipool;
25713663Ssam 				pk->p_ipool = bp;
25813663Ssam 				pk->p_is[x] = 0;
25913663Ssam 				pk->p_rcount--;
26013663Ssam 				pk->p_msg |= M_RR;
26113663Ssam 			} else {
26213663Ssam 				pk->p_rptr = cp+cc;
26313663Ssam 				pk->p_is[x] |= B_RESID;
26413663Ssam 			}
26513663Ssam 			if (cc==0)
26613663Ssam 				break;
26713663Ssam 		} else
26813663Ssam 			break;
26913663Ssam 	}
27013663Ssam 	pkoutput(pk);
27117836Sralph 	return count;
27213663Ssam }
27313663Ssam 
27417836Sralph /*ARGSUSED*/
27517836Sralph pkwrite(ipk, ibuf, icount)
27617836Sralph struct pack *ipk;
27717836Sralph char *ibuf;
27817836Sralph int icount;
27913663Ssam {
28017836Sralph 	register struct pack *pk;
28117836Sralph 	register x;
28217836Sralph 	int partial;
28317836Sralph 	caddr_t cp;
28417836Sralph 	int cc, fc, count;
28513663Ssam 
28617836Sralph 	pk = ipk;
28713663Ssam 	if (pk->p_state&DOWN || !pk->p_state&LIVE) {
28817836Sralph 		return -1;
28913663Ssam 	}
29013663Ssam 
29117836Sralph 	count = icount;
29213663Ssam 	do {
29313663Ssam 		while (pk->p_xcount>=pk->p_swindow)  {
29413663Ssam 			pkoutput(pk);
29517836Sralph 			pkgetpack(pk);
29613663Ssam 		}
29713663Ssam 		x = next[pk->p_pscopy];
29813663Ssam 		while (pk->p_os[x]!=B_NULL)  {
29917836Sralph 			pkgetpack(pk);
30013663Ssam 		}
30113663Ssam 		pk->p_os[x] = B_MARK;
30213663Ssam 		pk->p_pscopy = x;
30313663Ssam 		pk->p_xcount++;
30413663Ssam 
30517836Sralph 		cp = pk->p_ob[x] = malloc((unsigned)pk->p_xsize);
30613663Ssam 		partial = 0;
30717836Sralph 		if ((int)icount < pk->p_xsize) {
30817836Sralph 			cc = icount;
30913663Ssam 			fc = pk->p_xsize - cc;
31013663Ssam 			*cp = fc&0177;
31113663Ssam 			if (fc > 127) {
31213663Ssam 				*cp++ |= 0200;
31313663Ssam 				*cp++ = fc>>7;
31413663Ssam 			} else
31513663Ssam 				cp++;
31613663Ssam 			partial = B_SHORT;
31713663Ssam 		} else
31813663Ssam 			cc = pk->p_xsize;
31917836Sralph 		pkmove(cp, ibuf, cc, B_WRITE);
32017836Sralph 		ibuf += cc;
32117836Sralph 		icount -= cc;
32213663Ssam 		pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize);
32313663Ssam 		pk->p_os[x] = B_READY+partial;
32413663Ssam 		pkoutput(pk);
32517836Sralph 	} while (icount);
32613663Ssam 
32717836Sralph 	return count;
32813663Ssam }
32913663Ssam 
33013663Ssam pksack(pk)
33113663Ssam register struct pack *pk;
33213663Ssam {
33317836Sralph 	register x, i;
33413663Ssam 
33513663Ssam 	i = 0;
33613663Ssam 	for(x=pk->p_ps; x!=pk->p_rpr; ) {
33713663Ssam 		x = next[x];
33813663Ssam 		if (pk->p_os[x]&B_SENT) {
33913663Ssam 			i++;
34013663Ssam 			pk->p_os[x] = B_NULL;
34113663Ssam 			pk->p_state &= ~WAITO;
34213663Ssam 			pk->p_xcount--;
34317836Sralph 			free((char *)pk->p_ob[x]);
34413663Ssam 			pk->p_ps = x;
34513663Ssam 		}
34613663Ssam 	}
34717836Sralph 	return i;
34813663Ssam }
34913663Ssam 
35013663Ssam 
35113663Ssam 
35213663Ssam pkoutput(pk)
35313663Ssam register struct pack *pk;
35413663Ssam {
35517836Sralph 	register x;
35617836Sralph 	int i;
35717836Sralph 	char bstate;
35813663Ssam 
35917836Sralph 	if (pk->p_obusy++) {
36013663Ssam 		pk->p_obusy--;
36113663Ssam 		return;
36213663Ssam 	}
36313663Ssam 
36413663Ssam 	/*
36513663Ssam 	 * find seq number and buffer state
36613663Ssam 	 * of next output packet
36713663Ssam 	 */
36813663Ssam 	if (pk->p_state&RXMIT)  {
36913663Ssam 		pk->p_nxtps = next[pk->p_rpr];
37013663Ssam 	}
37113663Ssam 	x = pk->p_nxtps;
37213663Ssam 	bstate = pk->p_os[x];
37313663Ssam 
37413663Ssam 	/*
37513663Ssam 	 * Send control packet if indicated
37613663Ssam 	 */
37713663Ssam 	if (pk->p_msg) {
37813663Ssam 		if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) {
37913663Ssam 			x = pk->p_msg;
38017836Sralph 			for(i=0; i<8; i++)
38113663Ssam 				if (x&1)
38217836Sralph 					break;
38317836Sralph 				else
38417836Sralph 					x >>= 1;
38513663Ssam 			x = i;
38613663Ssam 			x <<= 3;
38713663Ssam 			switch(i) {
38813663Ssam 			case CLOSE:
38913663Ssam 				break;
39013663Ssam 			case RJ:
39113663Ssam 			case RR:
39213663Ssam 				x += pk->p_pr;
39313663Ssam 				break;
39413663Ssam 			case SRJ:
39513663Ssam 				break;
39613663Ssam 			case INITB:
39713663Ssam 				x += pksize(pk->p_rsize);
39813663Ssam 				break;
39913663Ssam 			case INITC:
40013663Ssam 				x += pk->p_rwindow;
40113663Ssam 				break;
40213663Ssam 			case INITA:
40313663Ssam 				x += pk->p_rwindow;
40413663Ssam 				break;
40513663Ssam 			}
40613663Ssam 
40713663Ssam 			pk->p_msg &= ~mask[i];
40813663Ssam 			pkxstart(pk, x, -1);
40913663Ssam 			goto out;
41013663Ssam 		}
41113663Ssam 	}
41213663Ssam 
41313663Ssam 
41413663Ssam 	/*
41513663Ssam 	 * Don't send data packets if line is marked dead.
41613663Ssam 	 */
41713663Ssam 	if (pk->p_state&DOWN) {
41813663Ssam 		goto out;
41913663Ssam 	}
42013663Ssam 	/*
42113663Ssam 	 * Start transmission (or retransmission) of data packets.
42213663Ssam 	 */
42313663Ssam 	if (bstate & (B_READY|B_SENT)) {
42413663Ssam 		char seq;
42513663Ssam 
42613663Ssam 		bstate |= B_SENT;
42713663Ssam 		seq = x;
42813663Ssam 		pk->p_nxtps = next[x];
42913663Ssam 
43013663Ssam 		x = 0200+pk->p_pr+(seq<<3);
43113663Ssam 		if (bstate & B_SHORT)
43213663Ssam 			x |= 0100;
43313663Ssam 		pkxstart(pk, x, seq);
43413663Ssam 		pk->p_os[seq] = bstate;
43513663Ssam 		pk->p_state &= ~RXMIT;
43613663Ssam 		pk->p_nout++;
43713663Ssam 		goto out;
43813663Ssam 	}
43913663Ssam 	/*
44013663Ssam 	 * enable timeout if there's nothing to send
44113663Ssam 	 * and transmission buffers are languishing
44213663Ssam 	 */
44313663Ssam 	if (pk->p_xcount) {
44413663Ssam 		pk->p_timer = 2;
44513663Ssam 		pk->p_state |= WAITO;
44613663Ssam 	} else
44713663Ssam 		pk->p_state &= ~WAITO;
44813663Ssam out:
44913663Ssam 	pk->p_obusy = 0;
45013663Ssam }
45113663Ssam 
45213663Ssam /*
45313663Ssam  * shut down line by
45413663Ssam  *	ignoring new input
45513663Ssam  *	letting output drain
45613663Ssam  *	releasing space and turning off line discipline
45713663Ssam  */
45817836Sralph /*ARGSUSED*/
45917836Sralph pkclose(ipk, ibuf, icount)
46017836Sralph struct pack *ipk;
46117836Sralph char *ibuf;
46217836Sralph int icount;
46313663Ssam {
46417836Sralph 	register struct pack *pk;
465*18620Sralph 	register i;
46617836Sralph 	char **bp;
467*18620Sralph 	int rcheck = 0;
46813663Ssam 
46917836Sralph 	pk = ipk;
47013663Ssam 	pk->p_state |= DRAINO;
47113663Ssam 
47213663Ssam 	/*
47313663Ssam 	 * try to flush output
47413663Ssam 	 */
47513663Ssam 	i = 0;
47613663Ssam 	pk->p_timer = 2;
47713663Ssam 	while (pk->p_xcount && pk->p_state&LIVE) {
47813663Ssam 		if (pk->p_state&(RCLOSE+DOWN) || ++i > 2)
47913663Ssam 			break;
48013663Ssam 		pkoutput(pk);
48113663Ssam 	}
48213663Ssam 	pk->p_timer = 0;
48313663Ssam 	pk->p_state |= DOWN;
48413663Ssam 
48513663Ssam 	/*
48613663Ssam 	 * try to exchange CLOSE messages
48713663Ssam 	 */
48813663Ssam 	i = 0;
48913663Ssam 	while ((pk->p_state&RCLOSE)==0 && i<2) {
49013663Ssam 		pk->p_msg = M_CLOSE;
49113663Ssam 		pk->p_timer = 2;
49213663Ssam 		pkoutput(pk);
49313663Ssam 		i++;
49413663Ssam 	}
49513663Ssam 
49613663Ssam 	for(i=0;i<NPLINES;i++)
49713663Ssam 		if (pklines[i]==pk)  {
49813663Ssam 			pklines[i] = NULL;
49913663Ssam 		}
50013663Ssam 
50113663Ssam 	/*
50213663Ssam 	 * free space
50313663Ssam 	 */
50413663Ssam 	rcheck = 0;
50513663Ssam 	for (i=0;i<8;i++) {
50617836Sralph 		if (pk->p_os[i] != B_NULL) {
50717836Sralph 			free((char *)pk->p_ob[i]);
50813663Ssam 			pk->p_xcount--;
50913663Ssam 		}
51017836Sralph 		if (pk->p_is[i] != B_NULL)  {
51117836Sralph 			free((char *)pk->p_ib[i]);
51213663Ssam 			rcheck++;
51313663Ssam 		}
51413663Ssam 	}
51513663Ssam 	while (pk->p_ipool != NULL) {
51613663Ssam 		bp = pk->p_ipool;
51713663Ssam 		pk->p_ipool = (char **)*bp;
51813663Ssam 		rcheck++;
51917836Sralph 		free((char *)bp);
52013663Ssam 	}
52117836Sralph 	if (rcheck != pk->p_rwindow) {
52217836Sralph 		logent("PK0", "pkclose rcheck != p_rwindow");
52313663Ssam 	}
52417836Sralph 	free((char *)pk);
52513663Ssam }
52613663Ssam 
52713663Ssam pkreset(pk)
52813663Ssam register struct pack *pk;
52913663Ssam {
53013663Ssam 
53113663Ssam 	pk->p_ps = pk->p_pr =  pk->p_rpr = 0;
53213663Ssam 	pk->p_nxtps = 1;
53313663Ssam }
53413663Ssam 
53513663Ssam pkline(pk)
53613663Ssam register struct pack *pk;
53713663Ssam {
53817836Sralph 	register i;
53917836Sralph 
54013663Ssam 	for(i=0;i<NPLINES;i++) {
54113663Ssam 		if (pklines[i]==pk)
54217836Sralph 			return i;
54313663Ssam 	}
54417836Sralph 	return -i;
54513663Ssam }
54613663Ssam 
54717836Sralph #ifndef BSD4_2
54817836Sralph bzero(s,n)
54913663Ssam register char *s;
55013663Ssam register n;
55113663Ssam {
55213663Ssam 	while (n--)
55313663Ssam 		*s++ = 0;
55413663Ssam }
55517836Sralph #endif !BSD4_2
55613663Ssam 
55713663Ssam pksize(n)
55813663Ssam register n;
55913663Ssam {
56017836Sralph 	register k;
56113663Ssam 
56213663Ssam 	n >>= 5;
56317836Sralph 	for(k=0; n >>= 1; k++)
56417836Sralph 		;
56517836Sralph 	return k;
56613663Ssam }
567