xref: /titanic_50/usr/src/cmd/bnu/pk0.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1988 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28*7c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
29*7c478bd9Sstevel@tonic-gate 
30*7c478bd9Sstevel@tonic-gate 
31*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
32*7c478bd9Sstevel@tonic-gate 
33*7c478bd9Sstevel@tonic-gate #include "uucp.h"
34*7c478bd9Sstevel@tonic-gate 
35*7c478bd9Sstevel@tonic-gate #include "pk.h"
36*7c478bd9Sstevel@tonic-gate #include <sys/buf.h>
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate extern void pkcntl(), pkoutput(), pkclose(), pkreset(), pkzero(),
39*7c478bd9Sstevel@tonic-gate 	pkgetpack(), pkxstart();
40*7c478bd9Sstevel@tonic-gate extern int pkread(), pkwrite(), pksack();
41*7c478bd9Sstevel@tonic-gate static int pksize(), chksum(), pkaccept();
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate extern int Connodata;		/* Continuous No Valid Data Count */
44*7c478bd9Sstevel@tonic-gate extern int xpacksize;
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate /*
47*7c478bd9Sstevel@tonic-gate  * receive control messages
48*7c478bd9Sstevel@tonic-gate  *	c	-> message type fields
49*7c478bd9Sstevel@tonic-gate  *	pk	-> line control unit
50*7c478bd9Sstevel@tonic-gate  */
51*7c478bd9Sstevel@tonic-gate void
52*7c478bd9Sstevel@tonic-gate pkcntl(c, pk)
53*7c478bd9Sstevel@tonic-gate register struct pack *pk;
54*7c478bd9Sstevel@tonic-gate {
55*7c478bd9Sstevel@tonic-gate 	register cntl, val;
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate 	val = c & MOD8;
58*7c478bd9Sstevel@tonic-gate 	cntl = (c>>3) & MOD8;
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate 	if ( ! ISCNTL(c) ) {
61*7c478bd9Sstevel@tonic-gate 		logent("PK0", "not cntl");
62*7c478bd9Sstevel@tonic-gate 		return;
63*7c478bd9Sstevel@tonic-gate 	}
64*7c478bd9Sstevel@tonic-gate 
65*7c478bd9Sstevel@tonic-gate 	if (Debug >= 9)
66*7c478bd9Sstevel@tonic-gate 		xlatecntl(0, c);
67*7c478bd9Sstevel@tonic-gate 	switch(cntl) {
68*7c478bd9Sstevel@tonic-gate 
69*7c478bd9Sstevel@tonic-gate 	case INITB:
70*7c478bd9Sstevel@tonic-gate 		val++;
71*7c478bd9Sstevel@tonic-gate 		pk->p_xsize = xpacksize = pksizes[val];
72*7c478bd9Sstevel@tonic-gate 		pk->p_lpsize = val;
73*7c478bd9Sstevel@tonic-gate 		pk->p_bits = 1;
74*7c478bd9Sstevel@tonic-gate 		if (pk->p_state & LIVE) {
75*7c478bd9Sstevel@tonic-gate 			pk->p_msg |= M_INITC;
76*7c478bd9Sstevel@tonic-gate 			break;
77*7c478bd9Sstevel@tonic-gate 		}
78*7c478bd9Sstevel@tonic-gate 		pk->p_state |= INITb;
79*7c478bd9Sstevel@tonic-gate 		if ((pk->p_state & INITa)==0) {
80*7c478bd9Sstevel@tonic-gate 			break;
81*7c478bd9Sstevel@tonic-gate 		}
82*7c478bd9Sstevel@tonic-gate 		pk->p_rmsg &= ~M_INITA;
83*7c478bd9Sstevel@tonic-gate 		pk->p_msg |= M_INITC;
84*7c478bd9Sstevel@tonic-gate 		break;
85*7c478bd9Sstevel@tonic-gate 
86*7c478bd9Sstevel@tonic-gate 	case INITC:
87*7c478bd9Sstevel@tonic-gate 		if ((pk->p_state&INITab)==INITab) {
88*7c478bd9Sstevel@tonic-gate 			pk->p_state = LIVE;
89*7c478bd9Sstevel@tonic-gate 			pk->p_rmsg &= ~M_INITB;
90*7c478bd9Sstevel@tonic-gate 		} else
91*7c478bd9Sstevel@tonic-gate 			pk->p_msg |= M_INITB;
92*7c478bd9Sstevel@tonic-gate 		if (val)
93*7c478bd9Sstevel@tonic-gate 			pk->p_swindow = val;
94*7c478bd9Sstevel@tonic-gate 		break;
95*7c478bd9Sstevel@tonic-gate 	case INITA:
96*7c478bd9Sstevel@tonic-gate 		if (val==0 && pk->p_state&LIVE) {
97*7c478bd9Sstevel@tonic-gate 			logent("PK0", "alloc change not implemented");
98*7c478bd9Sstevel@tonic-gate 			break;
99*7c478bd9Sstevel@tonic-gate 		}
100*7c478bd9Sstevel@tonic-gate 		if (val) {
101*7c478bd9Sstevel@tonic-gate 			pk->p_state |= INITa;
102*7c478bd9Sstevel@tonic-gate 			pk->p_msg |= M_INITB;
103*7c478bd9Sstevel@tonic-gate 			pk->p_rmsg |= M_INITB;
104*7c478bd9Sstevel@tonic-gate 			pk->p_swindow = val;
105*7c478bd9Sstevel@tonic-gate 		}
106*7c478bd9Sstevel@tonic-gate 		break;
107*7c478bd9Sstevel@tonic-gate 	case RJ:
108*7c478bd9Sstevel@tonic-gate 		pk->p_state |= RXMIT;
109*7c478bd9Sstevel@tonic-gate 		pk->p_msg |= M_RR;
110*7c478bd9Sstevel@tonic-gate 		DEBUG(9, "pkcntl: RJ: Connodata=%d\n", Connodata);
111*7c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
112*7c478bd9Sstevel@tonic-gate 	case RR:
113*7c478bd9Sstevel@tonic-gate 		pk->p_rpr = val;
114*7c478bd9Sstevel@tonic-gate 		(void) pksack(pk);
115*7c478bd9Sstevel@tonic-gate 		break;
116*7c478bd9Sstevel@tonic-gate 	case CLOSE:
117*7c478bd9Sstevel@tonic-gate 		pk->p_state = DOWN+RCLOSE;
118*7c478bd9Sstevel@tonic-gate 		return;
119*7c478bd9Sstevel@tonic-gate 	}
120*7c478bd9Sstevel@tonic-gate 	if (pk->p_msg)
121*7c478bd9Sstevel@tonic-gate 		pkoutput(pk);
122*7c478bd9Sstevel@tonic-gate }
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate static int
125*7c478bd9Sstevel@tonic-gate pkaccept()
126*7c478bd9Sstevel@tonic-gate {
127*7c478bd9Sstevel@tonic-gate 	register struct pack *pk;
128*7c478bd9Sstevel@tonic-gate 	register x,seq;
129*7c478bd9Sstevel@tonic-gate 	char m, cntl, *p, imask, **bp;
130*7c478bd9Sstevel@tonic-gate 	int bad,accept,skip,t,cc;
131*7c478bd9Sstevel@tonic-gate 	unsigned short sum;
132*7c478bd9Sstevel@tonic-gate 
133*7c478bd9Sstevel@tonic-gate 	pk = Pk;
134*7c478bd9Sstevel@tonic-gate 	bad = accept = skip = 0;
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	/*
137*7c478bd9Sstevel@tonic-gate 	 * wait for input
138*7c478bd9Sstevel@tonic-gate 	 */
139*7c478bd9Sstevel@tonic-gate 	x = next[pk->p_pr];
140*7c478bd9Sstevel@tonic-gate 	while ((imask=pk->p_imap) == 0 && pk->p_rcount==0) {
141*7c478bd9Sstevel@tonic-gate 		pkgetpack(pk);
142*7c478bd9Sstevel@tonic-gate 	}
143*7c478bd9Sstevel@tonic-gate 	pk->p_imap = 0;
144*7c478bd9Sstevel@tonic-gate 
145*7c478bd9Sstevel@tonic-gate 
146*7c478bd9Sstevel@tonic-gate 	/*
147*7c478bd9Sstevel@tonic-gate 	 * determine input window in m.
148*7c478bd9Sstevel@tonic-gate 	 */
149*7c478bd9Sstevel@tonic-gate 	t = (~(-1<<pk->p_rwindow)) <<x;
150*7c478bd9Sstevel@tonic-gate 	m = t;
151*7c478bd9Sstevel@tonic-gate 	m |= t>>8;
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	/*
155*7c478bd9Sstevel@tonic-gate 	 * mark newly accepted input buffers
156*7c478bd9Sstevel@tonic-gate 	 */
157*7c478bd9Sstevel@tonic-gate 	for(x=0; x<8; x++) {
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 		if ((imask & mask[x]) == 0)
160*7c478bd9Sstevel@tonic-gate 			continue;
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate 		if (((cntl=pk->p_is[x])&0200)==0) {
163*7c478bd9Sstevel@tonic-gate 			bad++;
164*7c478bd9Sstevel@tonic-gate free:
165*7c478bd9Sstevel@tonic-gate 			bp = (char **)pk->p_ib[x];
166*7c478bd9Sstevel@tonic-gate 			*bp = (char *)pk->p_ipool;
167*7c478bd9Sstevel@tonic-gate 			pk->p_ipool = bp;
168*7c478bd9Sstevel@tonic-gate 			pk->p_is[x] = 0;
169*7c478bd9Sstevel@tonic-gate 			continue;
170*7c478bd9Sstevel@tonic-gate 		}
171*7c478bd9Sstevel@tonic-gate 
172*7c478bd9Sstevel@tonic-gate 		pk->p_is[x] = (char) ~(B_COPY+B_MARK);
173*7c478bd9Sstevel@tonic-gate 		sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)(cntl&0377);
174*7c478bd9Sstevel@tonic-gate 		sum += pk->p_isum[x];
175*7c478bd9Sstevel@tonic-gate 		if (sum == CHECK) {
176*7c478bd9Sstevel@tonic-gate 			seq = (cntl>>3) & MOD8;
177*7c478bd9Sstevel@tonic-gate 			if (m & mask[seq]) {
178*7c478bd9Sstevel@tonic-gate 				if (pk->p_is[seq] & (B_COPY | B_MARK)) {
179*7c478bd9Sstevel@tonic-gate 				dup:
180*7c478bd9Sstevel@tonic-gate 					pk->p_msg |= M_RR;
181*7c478bd9Sstevel@tonic-gate 					skip++;
182*7c478bd9Sstevel@tonic-gate 					goto free;
183*7c478bd9Sstevel@tonic-gate 				}
184*7c478bd9Sstevel@tonic-gate 				if (x != seq) {
185*7c478bd9Sstevel@tonic-gate 					p = pk->p_ib[x];
186*7c478bd9Sstevel@tonic-gate 					pk->p_ib[x] = pk->p_ib[seq];
187*7c478bd9Sstevel@tonic-gate 					pk->p_is[x] = pk->p_is[seq];
188*7c478bd9Sstevel@tonic-gate 					pk->p_ib[seq] = p;
189*7c478bd9Sstevel@tonic-gate 				}
190*7c478bd9Sstevel@tonic-gate 				pk->p_is[seq] = B_MARK;
191*7c478bd9Sstevel@tonic-gate 				accept++;
192*7c478bd9Sstevel@tonic-gate 				cc = 0;
193*7c478bd9Sstevel@tonic-gate 				if (cntl&B_SHORT) {
194*7c478bd9Sstevel@tonic-gate 					pk->p_is[seq] = B_MARK+B_SHORT;
195*7c478bd9Sstevel@tonic-gate 					p = pk->p_ib[seq];
196*7c478bd9Sstevel@tonic-gate 					cc = (unsigned)*p++ & 0377;
197*7c478bd9Sstevel@tonic-gate 					if (cc & 0200) {
198*7c478bd9Sstevel@tonic-gate 						cc &= 0177;
199*7c478bd9Sstevel@tonic-gate 						cc |= *p << 7;
200*7c478bd9Sstevel@tonic-gate 					}
201*7c478bd9Sstevel@tonic-gate 				}
202*7c478bd9Sstevel@tonic-gate 				pk->p_isum[seq] = pk->p_rsize - cc;
203*7c478bd9Sstevel@tonic-gate 			} else {
204*7c478bd9Sstevel@tonic-gate 				goto dup;
205*7c478bd9Sstevel@tonic-gate 			}
206*7c478bd9Sstevel@tonic-gate 		} else {
207*7c478bd9Sstevel@tonic-gate 			bad++;
208*7c478bd9Sstevel@tonic-gate 			goto free;
209*7c478bd9Sstevel@tonic-gate 		}
210*7c478bd9Sstevel@tonic-gate 	}
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 	/*
213*7c478bd9Sstevel@tonic-gate 	 * scan window again turning marked buffers into
214*7c478bd9Sstevel@tonic-gate 	 * COPY buffers and looking for missing sequence
215*7c478bd9Sstevel@tonic-gate 	 * numbers.
216*7c478bd9Sstevel@tonic-gate 	 */
217*7c478bd9Sstevel@tonic-gate 	accept = 0;
218*7c478bd9Sstevel@tonic-gate 	for(x=next[pk->p_pr],t= -1; m & mask[x]; x = next[x]) {
219*7c478bd9Sstevel@tonic-gate 		if (pk->p_is[x] & B_MARK)
220*7c478bd9Sstevel@tonic-gate 			pk->p_is[x] |= B_COPY;
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate 		if (pk->p_is[x] & B_COPY) {
223*7c478bd9Sstevel@tonic-gate 			if (t >= 0) {
224*7c478bd9Sstevel@tonic-gate 				bp = (char **)pk->p_ib[x];
225*7c478bd9Sstevel@tonic-gate 				*bp = (char *)pk->p_ipool;
226*7c478bd9Sstevel@tonic-gate 				pk->p_ipool = bp;
227*7c478bd9Sstevel@tonic-gate 				pk->p_is[x] = 0;
228*7c478bd9Sstevel@tonic-gate 				skip++;
229*7c478bd9Sstevel@tonic-gate 			} else
230*7c478bd9Sstevel@tonic-gate 				accept++;
231*7c478bd9Sstevel@tonic-gate 		} else if (t<0)
232*7c478bd9Sstevel@tonic-gate 			t = x;
233*7c478bd9Sstevel@tonic-gate 	}
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	if (bad) {
236*7c478bd9Sstevel@tonic-gate 		pk->p_msg |= M_RJ;
237*7c478bd9Sstevel@tonic-gate 	}
238*7c478bd9Sstevel@tonic-gate 
239*7c478bd9Sstevel@tonic-gate 	if (skip) {
240*7c478bd9Sstevel@tonic-gate 		pk->p_msg |= M_RR;
241*7c478bd9Sstevel@tonic-gate 	}
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	pk->p_rcount = accept;
244*7c478bd9Sstevel@tonic-gate 	return(accept);
245*7c478bd9Sstevel@tonic-gate }
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate 
248*7c478bd9Sstevel@tonic-gate int
249*7c478bd9Sstevel@tonic-gate pkread(ibuf, icount)
250*7c478bd9Sstevel@tonic-gate char *ibuf;
251*7c478bd9Sstevel@tonic-gate int icount;
252*7c478bd9Sstevel@tonic-gate {
253*7c478bd9Sstevel@tonic-gate 	register struct pack *pk;
254*7c478bd9Sstevel@tonic-gate 	register x;
255*7c478bd9Sstevel@tonic-gate 	int is,cc,xfr,count;
256*7c478bd9Sstevel@tonic-gate 	char *cp, **bp;
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 	pk = Pk;
259*7c478bd9Sstevel@tonic-gate 	xfr = 0;
260*7c478bd9Sstevel@tonic-gate 	count = 0;
261*7c478bd9Sstevel@tonic-gate 	while (pkaccept()==0)
262*7c478bd9Sstevel@tonic-gate 		;
263*7c478bd9Sstevel@tonic-gate 	Connodata = 0;		/* accecpted a packet -- good data */
264*7c478bd9Sstevel@tonic-gate 
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	while (icount) {
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate 		x = next[pk->p_pr];
269*7c478bd9Sstevel@tonic-gate 		is = pk->p_is[x];
270*7c478bd9Sstevel@tonic-gate 
271*7c478bd9Sstevel@tonic-gate 		if (is & B_COPY) {
272*7c478bd9Sstevel@tonic-gate 			cc = MIN(pk->p_isum[x], icount);
273*7c478bd9Sstevel@tonic-gate 			if (cc==0 && xfr) {
274*7c478bd9Sstevel@tonic-gate 				break;
275*7c478bd9Sstevel@tonic-gate 			}
276*7c478bd9Sstevel@tonic-gate 			if (is & B_RESID)
277*7c478bd9Sstevel@tonic-gate 				cp = pk->p_rptr;
278*7c478bd9Sstevel@tonic-gate 			else {
279*7c478bd9Sstevel@tonic-gate 				cp = pk->p_ib[x];
280*7c478bd9Sstevel@tonic-gate 				if (is & B_SHORT) {
281*7c478bd9Sstevel@tonic-gate 					if (*cp++ & 0200)
282*7c478bd9Sstevel@tonic-gate 						cp++;
283*7c478bd9Sstevel@tonic-gate 				}
284*7c478bd9Sstevel@tonic-gate 			}
285*7c478bd9Sstevel@tonic-gate 			if (cc)
286*7c478bd9Sstevel@tonic-gate 				memcpy(ibuf, cp, cc);
287*7c478bd9Sstevel@tonic-gate 			ibuf += cc;
288*7c478bd9Sstevel@tonic-gate 			icount -= cc;
289*7c478bd9Sstevel@tonic-gate 			count += cc;
290*7c478bd9Sstevel@tonic-gate 			xfr++;
291*7c478bd9Sstevel@tonic-gate 			pk->p_isum[x] -= cc;
292*7c478bd9Sstevel@tonic-gate 			if (pk->p_isum[x] == 0) {
293*7c478bd9Sstevel@tonic-gate 				pk->p_pr = x;
294*7c478bd9Sstevel@tonic-gate 				bp = (char **)pk->p_ib[x];
295*7c478bd9Sstevel@tonic-gate 				*bp = (char *)pk->p_ipool;
296*7c478bd9Sstevel@tonic-gate 				pk->p_ipool = bp;
297*7c478bd9Sstevel@tonic-gate 				pk->p_is[x] = 0;
298*7c478bd9Sstevel@tonic-gate 				pk->p_rcount--;
299*7c478bd9Sstevel@tonic-gate 				pk->p_msg |= M_RR;
300*7c478bd9Sstevel@tonic-gate 			} else {
301*7c478bd9Sstevel@tonic-gate 				pk->p_rptr = cp+cc;
302*7c478bd9Sstevel@tonic-gate 				pk->p_is[x] |= B_RESID;
303*7c478bd9Sstevel@tonic-gate 			}
304*7c478bd9Sstevel@tonic-gate 			if (cc==0)
305*7c478bd9Sstevel@tonic-gate 				break;
306*7c478bd9Sstevel@tonic-gate 		} else
307*7c478bd9Sstevel@tonic-gate 			break;
308*7c478bd9Sstevel@tonic-gate 	}
309*7c478bd9Sstevel@tonic-gate 	pkoutput(pk);
310*7c478bd9Sstevel@tonic-gate 	return(count);
311*7c478bd9Sstevel@tonic-gate }
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate /* return number of bytes writtten */
314*7c478bd9Sstevel@tonic-gate int
315*7c478bd9Sstevel@tonic-gate pkwrite(ibuf, icount)
316*7c478bd9Sstevel@tonic-gate char *ibuf;
317*7c478bd9Sstevel@tonic-gate int icount;
318*7c478bd9Sstevel@tonic-gate {
319*7c478bd9Sstevel@tonic-gate 	register struct pack *pk;
320*7c478bd9Sstevel@tonic-gate 	register x;
321*7c478bd9Sstevel@tonic-gate 	caddr_t cp;
322*7c478bd9Sstevel@tonic-gate 	int partial;
323*7c478bd9Sstevel@tonic-gate 	int cc, fc, count;
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 	pk = Pk;
326*7c478bd9Sstevel@tonic-gate 	if (pk->p_state&DOWN || !pk->p_state&LIVE) {
327*7c478bd9Sstevel@tonic-gate 		return(-1);
328*7c478bd9Sstevel@tonic-gate 	}
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	count = icount;
331*7c478bd9Sstevel@tonic-gate 	do {
332*7c478bd9Sstevel@tonic-gate 		while (pk->p_xcount>=pk->p_swindow)  {
333*7c478bd9Sstevel@tonic-gate 			pkoutput(pk);
334*7c478bd9Sstevel@tonic-gate 			pkgetpack(pk);
335*7c478bd9Sstevel@tonic-gate 		}
336*7c478bd9Sstevel@tonic-gate 		x = next[pk->p_pscopy];
337*7c478bd9Sstevel@tonic-gate 		while (pk->p_os[x]!=B_NULL)  {
338*7c478bd9Sstevel@tonic-gate 			pkgetpack(pk);
339*7c478bd9Sstevel@tonic-gate 		}
340*7c478bd9Sstevel@tonic-gate 		pk->p_os[x] = B_MARK;
341*7c478bd9Sstevel@tonic-gate 		pk->p_pscopy = x;
342*7c478bd9Sstevel@tonic-gate 		pk->p_xcount++;
343*7c478bd9Sstevel@tonic-gate 
344*7c478bd9Sstevel@tonic-gate 		cp = pk->p_ob[x] = (caddr_t) malloc((unsigned) pk->p_xsize);
345*7c478bd9Sstevel@tonic-gate 		partial = 0;
346*7c478bd9Sstevel@tonic-gate 		if ((int)icount < pk->p_xsize) {
347*7c478bd9Sstevel@tonic-gate 			cc = icount;
348*7c478bd9Sstevel@tonic-gate 			fc = pk->p_xsize - cc;
349*7c478bd9Sstevel@tonic-gate 			*cp = fc&0177;
350*7c478bd9Sstevel@tonic-gate 			if (fc > 127) {
351*7c478bd9Sstevel@tonic-gate 				*cp++ |= 0200;
352*7c478bd9Sstevel@tonic-gate 				*cp++ = fc>>7;
353*7c478bd9Sstevel@tonic-gate 			} else
354*7c478bd9Sstevel@tonic-gate 				cp++;
355*7c478bd9Sstevel@tonic-gate 			partial = B_SHORT;
356*7c478bd9Sstevel@tonic-gate 		} else
357*7c478bd9Sstevel@tonic-gate 			cc = pk->p_xsize;
358*7c478bd9Sstevel@tonic-gate 		memcpy(cp, ibuf, cc);
359*7c478bd9Sstevel@tonic-gate 		ibuf += cc;
360*7c478bd9Sstevel@tonic-gate 		icount -= cc;
361*7c478bd9Sstevel@tonic-gate 		pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize);
362*7c478bd9Sstevel@tonic-gate 		pk->p_os[x] = B_READY+partial;
363*7c478bd9Sstevel@tonic-gate 		pkoutput(pk);
364*7c478bd9Sstevel@tonic-gate 	} while (icount);
365*7c478bd9Sstevel@tonic-gate 
366*7c478bd9Sstevel@tonic-gate 	return(count);
367*7c478bd9Sstevel@tonic-gate }
368*7c478bd9Sstevel@tonic-gate 
369*7c478bd9Sstevel@tonic-gate int
370*7c478bd9Sstevel@tonic-gate pksack(pk)
371*7c478bd9Sstevel@tonic-gate register struct pack *pk;
372*7c478bd9Sstevel@tonic-gate {
373*7c478bd9Sstevel@tonic-gate 	register x, i;
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 	i = 0;
376*7c478bd9Sstevel@tonic-gate 	for(x=pk->p_ps; x!=pk->p_rpr; ) {
377*7c478bd9Sstevel@tonic-gate 		x = next[x];
378*7c478bd9Sstevel@tonic-gate 		if (pk->p_os[x]&B_SENT) {
379*7c478bd9Sstevel@tonic-gate 			i++;
380*7c478bd9Sstevel@tonic-gate 			Connodata = 0;
381*7c478bd9Sstevel@tonic-gate 			pk->p_os[x] = B_NULL;
382*7c478bd9Sstevel@tonic-gate 			pk->p_state &= ~WAITO;
383*7c478bd9Sstevel@tonic-gate 			pk->p_xcount--;
384*7c478bd9Sstevel@tonic-gate 			free((char *) pk->p_ob[x]);
385*7c478bd9Sstevel@tonic-gate 			pk->p_ps = x;
386*7c478bd9Sstevel@tonic-gate 		}
387*7c478bd9Sstevel@tonic-gate 	}
388*7c478bd9Sstevel@tonic-gate 	return(i);
389*7c478bd9Sstevel@tonic-gate }
390*7c478bd9Sstevel@tonic-gate 
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate void
393*7c478bd9Sstevel@tonic-gate pkoutput(pk)
394*7c478bd9Sstevel@tonic-gate register struct pack *pk;
395*7c478bd9Sstevel@tonic-gate {
396*7c478bd9Sstevel@tonic-gate register x;
397*7c478bd9Sstevel@tonic-gate char bstate;
398*7c478bd9Sstevel@tonic-gate int i;
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 	if (pk->p_obusy++) {
401*7c478bd9Sstevel@tonic-gate 		pk->p_obusy--;
402*7c478bd9Sstevel@tonic-gate 		return;
403*7c478bd9Sstevel@tonic-gate 	}
404*7c478bd9Sstevel@tonic-gate 
405*7c478bd9Sstevel@tonic-gate 
406*7c478bd9Sstevel@tonic-gate 	/*
407*7c478bd9Sstevel@tonic-gate 	 * find seq number and buffer state
408*7c478bd9Sstevel@tonic-gate 	 * of next output packet
409*7c478bd9Sstevel@tonic-gate 	 */
410*7c478bd9Sstevel@tonic-gate 	if (pk->p_state&RXMIT)
411*7c478bd9Sstevel@tonic-gate 		pk->p_nxtps = next[pk->p_rpr];
412*7c478bd9Sstevel@tonic-gate 	x = pk->p_nxtps;
413*7c478bd9Sstevel@tonic-gate 	bstate = pk->p_os[x];
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 
416*7c478bd9Sstevel@tonic-gate 	/*
417*7c478bd9Sstevel@tonic-gate 	 * Send control packet if indicated
418*7c478bd9Sstevel@tonic-gate 	 */
419*7c478bd9Sstevel@tonic-gate 	if (pk->p_msg) {
420*7c478bd9Sstevel@tonic-gate 		if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) {
421*7c478bd9Sstevel@tonic-gate 			x = pk->p_msg;
422*7c478bd9Sstevel@tonic-gate 			for(i=0; i<8; i++)
423*7c478bd9Sstevel@tonic-gate 				if (x&1)
424*7c478bd9Sstevel@tonic-gate 					break;
425*7c478bd9Sstevel@tonic-gate else
426*7c478bd9Sstevel@tonic-gate 				x >>= 1;
427*7c478bd9Sstevel@tonic-gate 			x = i;
428*7c478bd9Sstevel@tonic-gate 			x <<= 3;
429*7c478bd9Sstevel@tonic-gate 			switch(i) {
430*7c478bd9Sstevel@tonic-gate 			case CLOSE:
431*7c478bd9Sstevel@tonic-gate 				break;
432*7c478bd9Sstevel@tonic-gate 			case RJ:
433*7c478bd9Sstevel@tonic-gate 			case RR:
434*7c478bd9Sstevel@tonic-gate 				x += pk->p_pr;
435*7c478bd9Sstevel@tonic-gate 				break;
436*7c478bd9Sstevel@tonic-gate 			case INITB:
437*7c478bd9Sstevel@tonic-gate 				x += pksize(pk->p_rsize);
438*7c478bd9Sstevel@tonic-gate 				break;
439*7c478bd9Sstevel@tonic-gate 			case INITC:
440*7c478bd9Sstevel@tonic-gate 				x += pk->p_rwindow;
441*7c478bd9Sstevel@tonic-gate 				break;
442*7c478bd9Sstevel@tonic-gate 			case INITA:
443*7c478bd9Sstevel@tonic-gate 				x += pk->p_rwindow;
444*7c478bd9Sstevel@tonic-gate 				break;
445*7c478bd9Sstevel@tonic-gate 			}
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 			pk->p_msg &= ~mask[i];
448*7c478bd9Sstevel@tonic-gate 			pkxstart(pk, x, -1);
449*7c478bd9Sstevel@tonic-gate 			goto out;
450*7c478bd9Sstevel@tonic-gate 		}
451*7c478bd9Sstevel@tonic-gate 	}
452*7c478bd9Sstevel@tonic-gate 
453*7c478bd9Sstevel@tonic-gate 
454*7c478bd9Sstevel@tonic-gate 	/*
455*7c478bd9Sstevel@tonic-gate 	 * Don't send data packets if line is marked dead.
456*7c478bd9Sstevel@tonic-gate 	 */
457*7c478bd9Sstevel@tonic-gate 	if (pk->p_state&DOWN) {
458*7c478bd9Sstevel@tonic-gate 		goto out;
459*7c478bd9Sstevel@tonic-gate 	}
460*7c478bd9Sstevel@tonic-gate 
461*7c478bd9Sstevel@tonic-gate 	/*
462*7c478bd9Sstevel@tonic-gate 	 * Start transmission (or retransmission) of data packets.
463*7c478bd9Sstevel@tonic-gate 	 */
464*7c478bd9Sstevel@tonic-gate 	if (bstate & (B_READY|B_SENT)) {
465*7c478bd9Sstevel@tonic-gate 		char seq;
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate 		bstate |= B_SENT;
468*7c478bd9Sstevel@tonic-gate 		seq = x;
469*7c478bd9Sstevel@tonic-gate 		pk->p_nxtps = next[x];
470*7c478bd9Sstevel@tonic-gate 
471*7c478bd9Sstevel@tonic-gate 		x = 0200+pk->p_pr+(seq<<3);
472*7c478bd9Sstevel@tonic-gate 		if (bstate & B_SHORT)
473*7c478bd9Sstevel@tonic-gate 			x |= 0100;
474*7c478bd9Sstevel@tonic-gate 		pkxstart(pk, x, seq);
475*7c478bd9Sstevel@tonic-gate 		pk->p_os[seq] = bstate;
476*7c478bd9Sstevel@tonic-gate 		pk->p_state &= ~RXMIT;
477*7c478bd9Sstevel@tonic-gate 		pk->p_nout++;
478*7c478bd9Sstevel@tonic-gate 		goto out;
479*7c478bd9Sstevel@tonic-gate 	}
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 	/*
482*7c478bd9Sstevel@tonic-gate 	 * enable timeout if there's nothing to send
483*7c478bd9Sstevel@tonic-gate 	 * and transmission buffers are languishing
484*7c478bd9Sstevel@tonic-gate 	 */
485*7c478bd9Sstevel@tonic-gate 	if (pk->p_xcount) {
486*7c478bd9Sstevel@tonic-gate 		pk->p_timer = 2;
487*7c478bd9Sstevel@tonic-gate 		pk->p_state |= WAITO;
488*7c478bd9Sstevel@tonic-gate 	} else
489*7c478bd9Sstevel@tonic-gate 		pk->p_state &= ~WAITO;
490*7c478bd9Sstevel@tonic-gate out:
491*7c478bd9Sstevel@tonic-gate 	pk->p_obusy = 0;
492*7c478bd9Sstevel@tonic-gate }
493*7c478bd9Sstevel@tonic-gate 
494*7c478bd9Sstevel@tonic-gate /*
495*7c478bd9Sstevel@tonic-gate  * shut down line by ignoring new input
496*7c478bd9Sstevel@tonic-gate  * letting output drain
497*7c478bd9Sstevel@tonic-gate  * releasing space
498*7c478bd9Sstevel@tonic-gate  */
499*7c478bd9Sstevel@tonic-gate void
500*7c478bd9Sstevel@tonic-gate pkclose()
501*7c478bd9Sstevel@tonic-gate {
502*7c478bd9Sstevel@tonic-gate 	register struct pack *pk;
503*7c478bd9Sstevel@tonic-gate 	register i;
504*7c478bd9Sstevel@tonic-gate 	int rcheck;
505*7c478bd9Sstevel@tonic-gate 	char **bp;
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 	pk = Pk;
508*7c478bd9Sstevel@tonic-gate 	pk->p_state |= DRAINO;
509*7c478bd9Sstevel@tonic-gate 
510*7c478bd9Sstevel@tonic-gate 	/*
511*7c478bd9Sstevel@tonic-gate 	 * try to flush output
512*7c478bd9Sstevel@tonic-gate 	 */
513*7c478bd9Sstevel@tonic-gate 	i = 0;
514*7c478bd9Sstevel@tonic-gate 	pk->p_timer = 2;
515*7c478bd9Sstevel@tonic-gate 	while (pk->p_xcount && pk->p_state&LIVE) {
516*7c478bd9Sstevel@tonic-gate 		if (pk->p_state&(RCLOSE+DOWN) || ++i > 2)
517*7c478bd9Sstevel@tonic-gate 			break;
518*7c478bd9Sstevel@tonic-gate 		pkoutput(pk);
519*7c478bd9Sstevel@tonic-gate 	}
520*7c478bd9Sstevel@tonic-gate 	pk->p_timer = 0;
521*7c478bd9Sstevel@tonic-gate 	pk->p_state |= DOWN;
522*7c478bd9Sstevel@tonic-gate 
523*7c478bd9Sstevel@tonic-gate 	/*
524*7c478bd9Sstevel@tonic-gate 	 * try to exchange CLOSE messages
525*7c478bd9Sstevel@tonic-gate 	 */
526*7c478bd9Sstevel@tonic-gate 	i = 0;
527*7c478bd9Sstevel@tonic-gate 	while ((pk->p_state&RCLOSE)==0 && i<2) {
528*7c478bd9Sstevel@tonic-gate 		pk->p_msg = M_CLOSE;
529*7c478bd9Sstevel@tonic-gate 		pk->p_timer = 2;
530*7c478bd9Sstevel@tonic-gate 		pkoutput(pk);
531*7c478bd9Sstevel@tonic-gate 		i++;
532*7c478bd9Sstevel@tonic-gate 	}
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 	/*
535*7c478bd9Sstevel@tonic-gate 	 * free space
536*7c478bd9Sstevel@tonic-gate 	 */
537*7c478bd9Sstevel@tonic-gate 	rcheck = 0;
538*7c478bd9Sstevel@tonic-gate 	for (i=0;i<8;i++) {
539*7c478bd9Sstevel@tonic-gate 		if (pk->p_os[i]!=B_NULL) {
540*7c478bd9Sstevel@tonic-gate 			free((char *) pk->p_ob[i]);
541*7c478bd9Sstevel@tonic-gate 			pk->p_xcount--;
542*7c478bd9Sstevel@tonic-gate 		}
543*7c478bd9Sstevel@tonic-gate 		if (pk->p_is[i]!=B_NULL)  {
544*7c478bd9Sstevel@tonic-gate 			free((char *) pk->p_ib[i]);
545*7c478bd9Sstevel@tonic-gate 			rcheck++;
546*7c478bd9Sstevel@tonic-gate 		}
547*7c478bd9Sstevel@tonic-gate 	}
548*7c478bd9Sstevel@tonic-gate 	while (pk->p_ipool != NULL) {
549*7c478bd9Sstevel@tonic-gate 		bp = pk->p_ipool;
550*7c478bd9Sstevel@tonic-gate 		pk->p_ipool = (char **)*bp;
551*7c478bd9Sstevel@tonic-gate 		rcheck++;
552*7c478bd9Sstevel@tonic-gate 		free((char *) bp);
553*7c478bd9Sstevel@tonic-gate 	}
554*7c478bd9Sstevel@tonic-gate 	if (rcheck  != pk->p_rwindow) {
555*7c478bd9Sstevel@tonic-gate 		logent("PK0", "pkclose rcheck != p_rwindow");
556*7c478bd9Sstevel@tonic-gate 	}
557*7c478bd9Sstevel@tonic-gate 	free((char *) pk);
558*7c478bd9Sstevel@tonic-gate }
559*7c478bd9Sstevel@tonic-gate 
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate void
562*7c478bd9Sstevel@tonic-gate pkreset(pk)
563*7c478bd9Sstevel@tonic-gate register struct pack *pk;
564*7c478bd9Sstevel@tonic-gate {
565*7c478bd9Sstevel@tonic-gate 
566*7c478bd9Sstevel@tonic-gate 	pk->p_ps = pk->p_pr =  pk->p_rpr = 0;
567*7c478bd9Sstevel@tonic-gate 	pk->p_nxtps = 1;
568*7c478bd9Sstevel@tonic-gate }
569*7c478bd9Sstevel@tonic-gate 
570*7c478bd9Sstevel@tonic-gate static int
571*7c478bd9Sstevel@tonic-gate chksum(s,n)
572*7c478bd9Sstevel@tonic-gate register char *s;
573*7c478bd9Sstevel@tonic-gate register n;
574*7c478bd9Sstevel@tonic-gate {
575*7c478bd9Sstevel@tonic-gate 	register short sum;
576*7c478bd9Sstevel@tonic-gate 	register unsigned short t;
577*7c478bd9Sstevel@tonic-gate 	register short x;
578*7c478bd9Sstevel@tonic-gate 
579*7c478bd9Sstevel@tonic-gate 	sum = -1;
580*7c478bd9Sstevel@tonic-gate 	x = 0;
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 	do {
583*7c478bd9Sstevel@tonic-gate 		if (sum<0) {
584*7c478bd9Sstevel@tonic-gate 			sum <<= 1;
585*7c478bd9Sstevel@tonic-gate 			sum++;
586*7c478bd9Sstevel@tonic-gate 		} else
587*7c478bd9Sstevel@tonic-gate 			sum <<= 1;
588*7c478bd9Sstevel@tonic-gate 		t = sum;
589*7c478bd9Sstevel@tonic-gate 		sum += (unsigned)*s++ & 0377;
590*7c478bd9Sstevel@tonic-gate 		x += sum^n;
591*7c478bd9Sstevel@tonic-gate 		if ((unsigned short)sum <= t) {
592*7c478bd9Sstevel@tonic-gate 			sum ^= x;
593*7c478bd9Sstevel@tonic-gate 		}
594*7c478bd9Sstevel@tonic-gate 	} while (--n > 0);
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate 	return(sum);
597*7c478bd9Sstevel@tonic-gate }
598*7c478bd9Sstevel@tonic-gate 
599*7c478bd9Sstevel@tonic-gate static int
600*7c478bd9Sstevel@tonic-gate pksize(n)
601*7c478bd9Sstevel@tonic-gate register n;
602*7c478bd9Sstevel@tonic-gate {
603*7c478bd9Sstevel@tonic-gate 	register k;
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate 	n >>= 5;
606*7c478bd9Sstevel@tonic-gate 	for(k=0; n >>= 1; k++);
607*7c478bd9Sstevel@tonic-gate 	return(k);
608*7c478bd9Sstevel@tonic-gate }
609