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