xref: /illumos-gate/usr/src/cmd/bnu/pk0.c (revision 2a8bcb4e)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23462be471Sceastha  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
287c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include "uucp.h"
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate #include "pk.h"
337c478bd9Sstevel@tonic-gate #include <sys/buf.h>
347c478bd9Sstevel@tonic-gate 
35462be471Sceastha extern void xlatecntl();
367c478bd9Sstevel@tonic-gate extern void pkcntl(), pkoutput(), pkclose(), pkreset(), pkzero(),
377c478bd9Sstevel@tonic-gate 	pkgetpack(), pkxstart();
387c478bd9Sstevel@tonic-gate extern int pkread(), pkwrite(), pksack();
397c478bd9Sstevel@tonic-gate static int pksize(), chksum(), pkaccept();
407c478bd9Sstevel@tonic-gate 
417c478bd9Sstevel@tonic-gate extern int Connodata;		/* Continuous No Valid Data Count */
427c478bd9Sstevel@tonic-gate extern int xpacksize;
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate /*
457c478bd9Sstevel@tonic-gate  * receive control messages
467c478bd9Sstevel@tonic-gate  *	c	-> message type fields
477c478bd9Sstevel@tonic-gate  *	pk	-> line control unit
487c478bd9Sstevel@tonic-gate  */
497c478bd9Sstevel@tonic-gate void
pkcntl(c,pk)507c478bd9Sstevel@tonic-gate pkcntl(c, pk)
51462be471Sceastha int c;
52462be471Sceastha struct pack *pk;
537c478bd9Sstevel@tonic-gate {
54462be471Sceastha 	int cntl, val;
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate 	val = c & MOD8;
577c478bd9Sstevel@tonic-gate 	cntl = (c>>3) & MOD8;
587c478bd9Sstevel@tonic-gate 
597c478bd9Sstevel@tonic-gate 	if ( ! ISCNTL(c) ) {
607c478bd9Sstevel@tonic-gate 		logent("PK0", "not cntl");
617c478bd9Sstevel@tonic-gate 		return;
627c478bd9Sstevel@tonic-gate 	}
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	if (Debug >= 9)
657c478bd9Sstevel@tonic-gate 		xlatecntl(0, c);
667c478bd9Sstevel@tonic-gate 	switch(cntl) {
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	case INITB:
697c478bd9Sstevel@tonic-gate 		val++;
707c478bd9Sstevel@tonic-gate 		pk->p_xsize = xpacksize = pksizes[val];
717c478bd9Sstevel@tonic-gate 		pk->p_lpsize = val;
727c478bd9Sstevel@tonic-gate 		pk->p_bits = 1;
737c478bd9Sstevel@tonic-gate 		if (pk->p_state & LIVE) {
747c478bd9Sstevel@tonic-gate 			pk->p_msg |= M_INITC;
757c478bd9Sstevel@tonic-gate 			break;
767c478bd9Sstevel@tonic-gate 		}
777c478bd9Sstevel@tonic-gate 		pk->p_state |= INITb;
787c478bd9Sstevel@tonic-gate 		if ((pk->p_state & INITa)==0) {
797c478bd9Sstevel@tonic-gate 			break;
807c478bd9Sstevel@tonic-gate 		}
817c478bd9Sstevel@tonic-gate 		pk->p_rmsg &= ~M_INITA;
827c478bd9Sstevel@tonic-gate 		pk->p_msg |= M_INITC;
837c478bd9Sstevel@tonic-gate 		break;
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate 	case INITC:
867c478bd9Sstevel@tonic-gate 		if ((pk->p_state&INITab)==INITab) {
877c478bd9Sstevel@tonic-gate 			pk->p_state = LIVE;
887c478bd9Sstevel@tonic-gate 			pk->p_rmsg &= ~M_INITB;
897c478bd9Sstevel@tonic-gate 		} else
907c478bd9Sstevel@tonic-gate 			pk->p_msg |= M_INITB;
917c478bd9Sstevel@tonic-gate 		if (val)
927c478bd9Sstevel@tonic-gate 			pk->p_swindow = val;
937c478bd9Sstevel@tonic-gate 		break;
947c478bd9Sstevel@tonic-gate 	case INITA:
957c478bd9Sstevel@tonic-gate 		if (val==0 && pk->p_state&LIVE) {
967c478bd9Sstevel@tonic-gate 			logent("PK0", "alloc change not implemented");
977c478bd9Sstevel@tonic-gate 			break;
987c478bd9Sstevel@tonic-gate 		}
997c478bd9Sstevel@tonic-gate 		if (val) {
1007c478bd9Sstevel@tonic-gate 			pk->p_state |= INITa;
1017c478bd9Sstevel@tonic-gate 			pk->p_msg |= M_INITB;
1027c478bd9Sstevel@tonic-gate 			pk->p_rmsg |= M_INITB;
1037c478bd9Sstevel@tonic-gate 			pk->p_swindow = val;
1047c478bd9Sstevel@tonic-gate 		}
1057c478bd9Sstevel@tonic-gate 		break;
1067c478bd9Sstevel@tonic-gate 	case RJ:
1077c478bd9Sstevel@tonic-gate 		pk->p_state |= RXMIT;
1087c478bd9Sstevel@tonic-gate 		pk->p_msg |= M_RR;
1097c478bd9Sstevel@tonic-gate 		DEBUG(9, "pkcntl: RJ: Connodata=%d\n", Connodata);
1107c478bd9Sstevel@tonic-gate 		/* FALLTHRU */
1117c478bd9Sstevel@tonic-gate 	case RR:
1127c478bd9Sstevel@tonic-gate 		pk->p_rpr = val;
1137c478bd9Sstevel@tonic-gate 		(void) pksack(pk);
1147c478bd9Sstevel@tonic-gate 		break;
1157c478bd9Sstevel@tonic-gate 	case CLOSE:
1167c478bd9Sstevel@tonic-gate 		pk->p_state = DOWN+RCLOSE;
1177c478bd9Sstevel@tonic-gate 		return;
1187c478bd9Sstevel@tonic-gate 	}
1197c478bd9Sstevel@tonic-gate 	if (pk->p_msg)
1207c478bd9Sstevel@tonic-gate 		pkoutput(pk);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate static int
pkaccept()1247c478bd9Sstevel@tonic-gate pkaccept()
1257c478bd9Sstevel@tonic-gate {
126462be471Sceastha 	struct pack *pk;
127462be471Sceastha 	int x,seq;
1287c478bd9Sstevel@tonic-gate 	char m, cntl, *p, imask, **bp;
1297c478bd9Sstevel@tonic-gate 	int bad,accept,skip,t,cc;
1307c478bd9Sstevel@tonic-gate 	unsigned short sum;
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	pk = Pk;
1337c478bd9Sstevel@tonic-gate 	bad = accept = skip = 0;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	/*
1367c478bd9Sstevel@tonic-gate 	 * wait for input
1377c478bd9Sstevel@tonic-gate 	 */
1387c478bd9Sstevel@tonic-gate 	x = next[pk->p_pr];
1397c478bd9Sstevel@tonic-gate 	while ((imask=pk->p_imap) == 0 && pk->p_rcount==0) {
1407c478bd9Sstevel@tonic-gate 		pkgetpack(pk);
1417c478bd9Sstevel@tonic-gate 	}
1427c478bd9Sstevel@tonic-gate 	pk->p_imap = 0;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 	/*
1467c478bd9Sstevel@tonic-gate 	 * determine input window in m.
1477c478bd9Sstevel@tonic-gate 	 */
1487c478bd9Sstevel@tonic-gate 	t = (~(-1<<pk->p_rwindow)) <<x;
1497c478bd9Sstevel@tonic-gate 	m = t;
1507c478bd9Sstevel@tonic-gate 	m |= t>>8;
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	/*
1547c478bd9Sstevel@tonic-gate 	 * mark newly accepted input buffers
1557c478bd9Sstevel@tonic-gate 	 */
1567c478bd9Sstevel@tonic-gate 	for(x=0; x<8; x++) {
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 		if ((imask & mask[x]) == 0)
1597c478bd9Sstevel@tonic-gate 			continue;
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate 		if (((cntl=pk->p_is[x])&0200)==0) {
1627c478bd9Sstevel@tonic-gate 			bad++;
1637c478bd9Sstevel@tonic-gate free:
1647c478bd9Sstevel@tonic-gate 			bp = (char **)pk->p_ib[x];
1657c478bd9Sstevel@tonic-gate 			*bp = (char *)pk->p_ipool;
1667c478bd9Sstevel@tonic-gate 			pk->p_ipool = bp;
1677c478bd9Sstevel@tonic-gate 			pk->p_is[x] = 0;
1687c478bd9Sstevel@tonic-gate 			continue;
1697c478bd9Sstevel@tonic-gate 		}
1707c478bd9Sstevel@tonic-gate 
1717c478bd9Sstevel@tonic-gate 		pk->p_is[x] = (char) ~(B_COPY+B_MARK);
1727c478bd9Sstevel@tonic-gate 		sum = (unsigned)chksum(pk->p_ib[x], pk->p_rsize) ^ (unsigned)(cntl&0377);
1737c478bd9Sstevel@tonic-gate 		sum += pk->p_isum[x];
1747c478bd9Sstevel@tonic-gate 		if (sum == CHECK) {
1757c478bd9Sstevel@tonic-gate 			seq = (cntl>>3) & MOD8;
1767c478bd9Sstevel@tonic-gate 			if (m & mask[seq]) {
1777c478bd9Sstevel@tonic-gate 				if (pk->p_is[seq] & (B_COPY | B_MARK)) {
1787c478bd9Sstevel@tonic-gate 				dup:
1797c478bd9Sstevel@tonic-gate 					pk->p_msg |= M_RR;
1807c478bd9Sstevel@tonic-gate 					skip++;
1817c478bd9Sstevel@tonic-gate 					goto free;
1827c478bd9Sstevel@tonic-gate 				}
1837c478bd9Sstevel@tonic-gate 				if (x != seq) {
1847c478bd9Sstevel@tonic-gate 					p = pk->p_ib[x];
1857c478bd9Sstevel@tonic-gate 					pk->p_ib[x] = pk->p_ib[seq];
1867c478bd9Sstevel@tonic-gate 					pk->p_is[x] = pk->p_is[seq];
1877c478bd9Sstevel@tonic-gate 					pk->p_ib[seq] = p;
1887c478bd9Sstevel@tonic-gate 				}
1897c478bd9Sstevel@tonic-gate 				pk->p_is[seq] = B_MARK;
1907c478bd9Sstevel@tonic-gate 				accept++;
1917c478bd9Sstevel@tonic-gate 				cc = 0;
1927c478bd9Sstevel@tonic-gate 				if (cntl&B_SHORT) {
1937c478bd9Sstevel@tonic-gate 					pk->p_is[seq] = B_MARK+B_SHORT;
1947c478bd9Sstevel@tonic-gate 					p = pk->p_ib[seq];
1957c478bd9Sstevel@tonic-gate 					cc = (unsigned)*p++ & 0377;
1967c478bd9Sstevel@tonic-gate 					if (cc & 0200) {
1977c478bd9Sstevel@tonic-gate 						cc &= 0177;
1987c478bd9Sstevel@tonic-gate 						cc |= *p << 7;
1997c478bd9Sstevel@tonic-gate 					}
2007c478bd9Sstevel@tonic-gate 				}
2017c478bd9Sstevel@tonic-gate 				pk->p_isum[seq] = pk->p_rsize - cc;
2027c478bd9Sstevel@tonic-gate 			} else {
2037c478bd9Sstevel@tonic-gate 				goto dup;
2047c478bd9Sstevel@tonic-gate 			}
2057c478bd9Sstevel@tonic-gate 		} else {
2067c478bd9Sstevel@tonic-gate 			bad++;
2077c478bd9Sstevel@tonic-gate 			goto free;
2087c478bd9Sstevel@tonic-gate 		}
2097c478bd9Sstevel@tonic-gate 	}
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 	/*
2127c478bd9Sstevel@tonic-gate 	 * scan window again turning marked buffers into
2137c478bd9Sstevel@tonic-gate 	 * COPY buffers and looking for missing sequence
2147c478bd9Sstevel@tonic-gate 	 * numbers.
2157c478bd9Sstevel@tonic-gate 	 */
2167c478bd9Sstevel@tonic-gate 	accept = 0;
2177c478bd9Sstevel@tonic-gate 	for(x=next[pk->p_pr],t= -1; m & mask[x]; x = next[x]) {
2187c478bd9Sstevel@tonic-gate 		if (pk->p_is[x] & B_MARK)
2197c478bd9Sstevel@tonic-gate 			pk->p_is[x] |= B_COPY;
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 		if (pk->p_is[x] & B_COPY) {
2227c478bd9Sstevel@tonic-gate 			if (t >= 0) {
2237c478bd9Sstevel@tonic-gate 				bp = (char **)pk->p_ib[x];
2247c478bd9Sstevel@tonic-gate 				*bp = (char *)pk->p_ipool;
2257c478bd9Sstevel@tonic-gate 				pk->p_ipool = bp;
2267c478bd9Sstevel@tonic-gate 				pk->p_is[x] = 0;
2277c478bd9Sstevel@tonic-gate 				skip++;
228*2a8bcb4eSToomas Soome 			} else
2297c478bd9Sstevel@tonic-gate 				accept++;
2307c478bd9Sstevel@tonic-gate 		} else if (t<0)
2317c478bd9Sstevel@tonic-gate 			t = x;
2327c478bd9Sstevel@tonic-gate 	}
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	if (bad) {
2357c478bd9Sstevel@tonic-gate 		pk->p_msg |= M_RJ;
2367c478bd9Sstevel@tonic-gate 	}
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 	if (skip) {
2397c478bd9Sstevel@tonic-gate 		pk->p_msg |= M_RR;
2407c478bd9Sstevel@tonic-gate 	}
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	pk->p_rcount = accept;
2437c478bd9Sstevel@tonic-gate 	return(accept);
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate 
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate int
pkread(ibuf,icount)2487c478bd9Sstevel@tonic-gate pkread(ibuf, icount)
2497c478bd9Sstevel@tonic-gate char *ibuf;
2507c478bd9Sstevel@tonic-gate int icount;
2517c478bd9Sstevel@tonic-gate {
252462be471Sceastha 	struct pack *pk;
253462be471Sceastha 	int x;
2547c478bd9Sstevel@tonic-gate 	int is,cc,xfr,count;
2557c478bd9Sstevel@tonic-gate 	char *cp, **bp;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	pk = Pk;
2587c478bd9Sstevel@tonic-gate 	xfr = 0;
2597c478bd9Sstevel@tonic-gate 	count = 0;
2607c478bd9Sstevel@tonic-gate 	while (pkaccept()==0)
2617c478bd9Sstevel@tonic-gate 		;
2627c478bd9Sstevel@tonic-gate 	Connodata = 0;		/* accecpted a packet -- good data */
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 
2657c478bd9Sstevel@tonic-gate 	while (icount) {
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate 		x = next[pk->p_pr];
2687c478bd9Sstevel@tonic-gate 		is = pk->p_is[x];
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 		if (is & B_COPY) {
2717c478bd9Sstevel@tonic-gate 			cc = MIN(pk->p_isum[x], icount);
2727c478bd9Sstevel@tonic-gate 			if (cc==0 && xfr) {
2737c478bd9Sstevel@tonic-gate 				break;
2747c478bd9Sstevel@tonic-gate 			}
2757c478bd9Sstevel@tonic-gate 			if (is & B_RESID)
2767c478bd9Sstevel@tonic-gate 				cp = pk->p_rptr;
2777c478bd9Sstevel@tonic-gate 			else {
2787c478bd9Sstevel@tonic-gate 				cp = pk->p_ib[x];
2797c478bd9Sstevel@tonic-gate 				if (is & B_SHORT) {
2807c478bd9Sstevel@tonic-gate 					if (*cp++ & 0200)
2817c478bd9Sstevel@tonic-gate 						cp++;
2827c478bd9Sstevel@tonic-gate 				}
2837c478bd9Sstevel@tonic-gate 			}
2847c478bd9Sstevel@tonic-gate 			if (cc)
2857c478bd9Sstevel@tonic-gate 				memcpy(ibuf, cp, cc);
2867c478bd9Sstevel@tonic-gate 			ibuf += cc;
2877c478bd9Sstevel@tonic-gate 			icount -= cc;
2887c478bd9Sstevel@tonic-gate 			count += cc;
2897c478bd9Sstevel@tonic-gate 			xfr++;
2907c478bd9Sstevel@tonic-gate 			pk->p_isum[x] -= cc;
2917c478bd9Sstevel@tonic-gate 			if (pk->p_isum[x] == 0) {
2927c478bd9Sstevel@tonic-gate 				pk->p_pr = x;
2937c478bd9Sstevel@tonic-gate 				bp = (char **)pk->p_ib[x];
2947c478bd9Sstevel@tonic-gate 				*bp = (char *)pk->p_ipool;
2957c478bd9Sstevel@tonic-gate 				pk->p_ipool = bp;
2967c478bd9Sstevel@tonic-gate 				pk->p_is[x] = 0;
2977c478bd9Sstevel@tonic-gate 				pk->p_rcount--;
2987c478bd9Sstevel@tonic-gate 				pk->p_msg |= M_RR;
2997c478bd9Sstevel@tonic-gate 			} else {
3007c478bd9Sstevel@tonic-gate 				pk->p_rptr = cp+cc;
3017c478bd9Sstevel@tonic-gate 				pk->p_is[x] |= B_RESID;
3027c478bd9Sstevel@tonic-gate 			}
3037c478bd9Sstevel@tonic-gate 			if (cc==0)
3047c478bd9Sstevel@tonic-gate 				break;
3057c478bd9Sstevel@tonic-gate 		} else
3067c478bd9Sstevel@tonic-gate 			break;
3077c478bd9Sstevel@tonic-gate 	}
3087c478bd9Sstevel@tonic-gate 	pkoutput(pk);
3097c478bd9Sstevel@tonic-gate 	return(count);
3107c478bd9Sstevel@tonic-gate }
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate /* return number of bytes writtten */
3137c478bd9Sstevel@tonic-gate int
pkwrite(ibuf,icount)3147c478bd9Sstevel@tonic-gate pkwrite(ibuf, icount)
3157c478bd9Sstevel@tonic-gate char *ibuf;
3167c478bd9Sstevel@tonic-gate int icount;
3177c478bd9Sstevel@tonic-gate {
318462be471Sceastha 	struct pack *pk;
319462be471Sceastha 	int x;
3207c478bd9Sstevel@tonic-gate 	caddr_t cp;
3217c478bd9Sstevel@tonic-gate 	int partial;
3227c478bd9Sstevel@tonic-gate 	int cc, fc, count;
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	pk = Pk;
3257c478bd9Sstevel@tonic-gate 	if (pk->p_state&DOWN || !pk->p_state&LIVE) {
3267c478bd9Sstevel@tonic-gate 		return(-1);
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	count = icount;
3307c478bd9Sstevel@tonic-gate 	do {
3317c478bd9Sstevel@tonic-gate 		while (pk->p_xcount>=pk->p_swindow)  {
3327c478bd9Sstevel@tonic-gate 			pkoutput(pk);
3337c478bd9Sstevel@tonic-gate 			pkgetpack(pk);
3347c478bd9Sstevel@tonic-gate 		}
3357c478bd9Sstevel@tonic-gate 		x = next[pk->p_pscopy];
3367c478bd9Sstevel@tonic-gate 		while (pk->p_os[x]!=B_NULL)  {
3377c478bd9Sstevel@tonic-gate 			pkgetpack(pk);
3387c478bd9Sstevel@tonic-gate 		}
3397c478bd9Sstevel@tonic-gate 		pk->p_os[x] = B_MARK;
3407c478bd9Sstevel@tonic-gate 		pk->p_pscopy = x;
3417c478bd9Sstevel@tonic-gate 		pk->p_xcount++;
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 		cp = pk->p_ob[x] = (caddr_t) malloc((unsigned) pk->p_xsize);
3447c478bd9Sstevel@tonic-gate 		partial = 0;
3457c478bd9Sstevel@tonic-gate 		if ((int)icount < pk->p_xsize) {
3467c478bd9Sstevel@tonic-gate 			cc = icount;
3477c478bd9Sstevel@tonic-gate 			fc = pk->p_xsize - cc;
3487c478bd9Sstevel@tonic-gate 			*cp = fc&0177;
3497c478bd9Sstevel@tonic-gate 			if (fc > 127) {
3507c478bd9Sstevel@tonic-gate 				*cp++ |= 0200;
3517c478bd9Sstevel@tonic-gate 				*cp++ = fc>>7;
3527c478bd9Sstevel@tonic-gate 			} else
3537c478bd9Sstevel@tonic-gate 				cp++;
3547c478bd9Sstevel@tonic-gate 			partial = B_SHORT;
3557c478bd9Sstevel@tonic-gate 		} else
3567c478bd9Sstevel@tonic-gate 			cc = pk->p_xsize;
3577c478bd9Sstevel@tonic-gate 		memcpy(cp, ibuf, cc);
3587c478bd9Sstevel@tonic-gate 		ibuf += cc;
3597c478bd9Sstevel@tonic-gate 		icount -= cc;
3607c478bd9Sstevel@tonic-gate 		pk->p_osum[x] = chksum(pk->p_ob[x], pk->p_xsize);
3617c478bd9Sstevel@tonic-gate 		pk->p_os[x] = B_READY+partial;
3627c478bd9Sstevel@tonic-gate 		pkoutput(pk);
3637c478bd9Sstevel@tonic-gate 	} while (icount);
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	return(count);
3667c478bd9Sstevel@tonic-gate }
3677c478bd9Sstevel@tonic-gate 
3687c478bd9Sstevel@tonic-gate int
pksack(pk)3697c478bd9Sstevel@tonic-gate pksack(pk)
370462be471Sceastha struct pack *pk;
3717c478bd9Sstevel@tonic-gate {
372462be471Sceastha 	int x, i;
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	i = 0;
3757c478bd9Sstevel@tonic-gate 	for(x=pk->p_ps; x!=pk->p_rpr; ) {
3767c478bd9Sstevel@tonic-gate 		x = next[x];
3777c478bd9Sstevel@tonic-gate 		if (pk->p_os[x]&B_SENT) {
3787c478bd9Sstevel@tonic-gate 			i++;
3797c478bd9Sstevel@tonic-gate 			Connodata = 0;
3807c478bd9Sstevel@tonic-gate 			pk->p_os[x] = B_NULL;
3817c478bd9Sstevel@tonic-gate 			pk->p_state &= ~WAITO;
3827c478bd9Sstevel@tonic-gate 			pk->p_xcount--;
3837c478bd9Sstevel@tonic-gate 			free((char *) pk->p_ob[x]);
3847c478bd9Sstevel@tonic-gate 			pk->p_ps = x;
3857c478bd9Sstevel@tonic-gate 		}
3867c478bd9Sstevel@tonic-gate 	}
3877c478bd9Sstevel@tonic-gate 	return(i);
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 
3917c478bd9Sstevel@tonic-gate void
pkoutput(pk)3927c478bd9Sstevel@tonic-gate pkoutput(pk)
393462be471Sceastha struct pack *pk;
3947c478bd9Sstevel@tonic-gate {
395462be471Sceastha int x;
3967c478bd9Sstevel@tonic-gate char bstate;
3977c478bd9Sstevel@tonic-gate int i;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	if (pk->p_obusy++) {
4007c478bd9Sstevel@tonic-gate 		pk->p_obusy--;
4017c478bd9Sstevel@tonic-gate 		return;
4027c478bd9Sstevel@tonic-gate 	}
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	/*
4067c478bd9Sstevel@tonic-gate 	 * find seq number and buffer state
4077c478bd9Sstevel@tonic-gate 	 * of next output packet
4087c478bd9Sstevel@tonic-gate 	 */
4097c478bd9Sstevel@tonic-gate 	if (pk->p_state&RXMIT)
4107c478bd9Sstevel@tonic-gate 		pk->p_nxtps = next[pk->p_rpr];
4117c478bd9Sstevel@tonic-gate 	x = pk->p_nxtps;
4127c478bd9Sstevel@tonic-gate 	bstate = pk->p_os[x];
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 	/*
4167c478bd9Sstevel@tonic-gate 	 * Send control packet if indicated
4177c478bd9Sstevel@tonic-gate 	 */
4187c478bd9Sstevel@tonic-gate 	if (pk->p_msg) {
4197c478bd9Sstevel@tonic-gate 		if (pk->p_msg & ~M_RR || !(bstate&B_READY) ) {
4207c478bd9Sstevel@tonic-gate 			x = pk->p_msg;
421*2a8bcb4eSToomas Soome 			for(i=0; i<8; i++)
4227c478bd9Sstevel@tonic-gate 				if (x&1)
423*2a8bcb4eSToomas Soome 					break;
4247c478bd9Sstevel@tonic-gate else
4257c478bd9Sstevel@tonic-gate 				x >>= 1;
4267c478bd9Sstevel@tonic-gate 			x = i;
4277c478bd9Sstevel@tonic-gate 			x <<= 3;
4287c478bd9Sstevel@tonic-gate 			switch(i) {
4297c478bd9Sstevel@tonic-gate 			case CLOSE:
4307c478bd9Sstevel@tonic-gate 				break;
4317c478bd9Sstevel@tonic-gate 			case RJ:
4327c478bd9Sstevel@tonic-gate 			case RR:
4337c478bd9Sstevel@tonic-gate 				x += pk->p_pr;
4347c478bd9Sstevel@tonic-gate 				break;
4357c478bd9Sstevel@tonic-gate 			case INITB:
4367c478bd9Sstevel@tonic-gate 				x += pksize(pk->p_rsize);
4377c478bd9Sstevel@tonic-gate 				break;
4387c478bd9Sstevel@tonic-gate 			case INITC:
4397c478bd9Sstevel@tonic-gate 				x += pk->p_rwindow;
4407c478bd9Sstevel@tonic-gate 				break;
4417c478bd9Sstevel@tonic-gate 			case INITA:
4427c478bd9Sstevel@tonic-gate 				x += pk->p_rwindow;
4437c478bd9Sstevel@tonic-gate 				break;
4447c478bd9Sstevel@tonic-gate 			}
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 			pk->p_msg &= ~mask[i];
4477c478bd9Sstevel@tonic-gate 			pkxstart(pk, x, -1);
4487c478bd9Sstevel@tonic-gate 			goto out;
4497c478bd9Sstevel@tonic-gate 		}
4507c478bd9Sstevel@tonic-gate 	}
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 
4537c478bd9Sstevel@tonic-gate 	/*
4547c478bd9Sstevel@tonic-gate 	 * Don't send data packets if line is marked dead.
4557c478bd9Sstevel@tonic-gate 	 */
4567c478bd9Sstevel@tonic-gate 	if (pk->p_state&DOWN) {
4577c478bd9Sstevel@tonic-gate 		goto out;
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	/*
4617c478bd9Sstevel@tonic-gate 	 * Start transmission (or retransmission) of data packets.
4627c478bd9Sstevel@tonic-gate 	 */
4637c478bd9Sstevel@tonic-gate 	if (bstate & (B_READY|B_SENT)) {
4647c478bd9Sstevel@tonic-gate 		char seq;
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 		bstate |= B_SENT;
4677c478bd9Sstevel@tonic-gate 		seq = x;
4687c478bd9Sstevel@tonic-gate 		pk->p_nxtps = next[x];
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 		x = 0200+pk->p_pr+(seq<<3);
4717c478bd9Sstevel@tonic-gate 		if (bstate & B_SHORT)
4727c478bd9Sstevel@tonic-gate 			x |= 0100;
4737c478bd9Sstevel@tonic-gate 		pkxstart(pk, x, seq);
4747c478bd9Sstevel@tonic-gate 		pk->p_os[seq] = bstate;
4757c478bd9Sstevel@tonic-gate 		pk->p_state &= ~RXMIT;
4767c478bd9Sstevel@tonic-gate 		pk->p_nout++;
4777c478bd9Sstevel@tonic-gate 		goto out;
4787c478bd9Sstevel@tonic-gate 	}
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	/*
4817c478bd9Sstevel@tonic-gate 	 * enable timeout if there's nothing to send
4827c478bd9Sstevel@tonic-gate 	 * and transmission buffers are languishing
4837c478bd9Sstevel@tonic-gate 	 */
4847c478bd9Sstevel@tonic-gate 	if (pk->p_xcount) {
4857c478bd9Sstevel@tonic-gate 		pk->p_timer = 2;
4867c478bd9Sstevel@tonic-gate 		pk->p_state |= WAITO;
4877c478bd9Sstevel@tonic-gate 	} else
4887c478bd9Sstevel@tonic-gate 		pk->p_state &= ~WAITO;
4897c478bd9Sstevel@tonic-gate out:
4907c478bd9Sstevel@tonic-gate 	pk->p_obusy = 0;
4917c478bd9Sstevel@tonic-gate }
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate /*
4947c478bd9Sstevel@tonic-gate  * shut down line by ignoring new input
4957c478bd9Sstevel@tonic-gate  * letting output drain
4967c478bd9Sstevel@tonic-gate  * releasing space
4977c478bd9Sstevel@tonic-gate  */
4987c478bd9Sstevel@tonic-gate void
pkclose()4997c478bd9Sstevel@tonic-gate pkclose()
5007c478bd9Sstevel@tonic-gate {
501462be471Sceastha 	struct pack *pk;
502462be471Sceastha 	int i;
5037c478bd9Sstevel@tonic-gate 	int rcheck;
5047c478bd9Sstevel@tonic-gate 	char **bp;
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	pk = Pk;
5077c478bd9Sstevel@tonic-gate 	pk->p_state |= DRAINO;
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	/*
5107c478bd9Sstevel@tonic-gate 	 * try to flush output
5117c478bd9Sstevel@tonic-gate 	 */
5127c478bd9Sstevel@tonic-gate 	i = 0;
5137c478bd9Sstevel@tonic-gate 	pk->p_timer = 2;
5147c478bd9Sstevel@tonic-gate 	while (pk->p_xcount && pk->p_state&LIVE) {
5157c478bd9Sstevel@tonic-gate 		if (pk->p_state&(RCLOSE+DOWN) || ++i > 2)
5167c478bd9Sstevel@tonic-gate 			break;
5177c478bd9Sstevel@tonic-gate 		pkoutput(pk);
5187c478bd9Sstevel@tonic-gate 	}
5197c478bd9Sstevel@tonic-gate 	pk->p_timer = 0;
5207c478bd9Sstevel@tonic-gate 	pk->p_state |= DOWN;
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	/*
5237c478bd9Sstevel@tonic-gate 	 * try to exchange CLOSE messages
5247c478bd9Sstevel@tonic-gate 	 */
5257c478bd9Sstevel@tonic-gate 	i = 0;
5267c478bd9Sstevel@tonic-gate 	while ((pk->p_state&RCLOSE)==0 && i<2) {
5277c478bd9Sstevel@tonic-gate 		pk->p_msg = M_CLOSE;
5287c478bd9Sstevel@tonic-gate 		pk->p_timer = 2;
5297c478bd9Sstevel@tonic-gate 		pkoutput(pk);
5307c478bd9Sstevel@tonic-gate 		i++;
5317c478bd9Sstevel@tonic-gate 	}
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	/*
5347c478bd9Sstevel@tonic-gate 	 * free space
5357c478bd9Sstevel@tonic-gate 	 */
5367c478bd9Sstevel@tonic-gate 	rcheck = 0;
5377c478bd9Sstevel@tonic-gate 	for (i=0;i<8;i++) {
5387c478bd9Sstevel@tonic-gate 		if (pk->p_os[i]!=B_NULL) {
5397c478bd9Sstevel@tonic-gate 			free((char *) pk->p_ob[i]);
5407c478bd9Sstevel@tonic-gate 			pk->p_xcount--;
5417c478bd9Sstevel@tonic-gate 		}
5427c478bd9Sstevel@tonic-gate 		if (pk->p_is[i]!=B_NULL)  {
5437c478bd9Sstevel@tonic-gate 			free((char *) pk->p_ib[i]);
5447c478bd9Sstevel@tonic-gate 			rcheck++;
5457c478bd9Sstevel@tonic-gate 		}
5467c478bd9Sstevel@tonic-gate 	}
5477c478bd9Sstevel@tonic-gate 	while (pk->p_ipool != NULL) {
5487c478bd9Sstevel@tonic-gate 		bp = pk->p_ipool;
5497c478bd9Sstevel@tonic-gate 		pk->p_ipool = (char **)*bp;
5507c478bd9Sstevel@tonic-gate 		rcheck++;
5517c478bd9Sstevel@tonic-gate 		free((char *) bp);
5527c478bd9Sstevel@tonic-gate 	}
5537c478bd9Sstevel@tonic-gate 	if (rcheck  != pk->p_rwindow) {
5547c478bd9Sstevel@tonic-gate 		logent("PK0", "pkclose rcheck != p_rwindow");
5557c478bd9Sstevel@tonic-gate 	}
5567c478bd9Sstevel@tonic-gate 	free((char *) pk);
5577c478bd9Sstevel@tonic-gate }
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate void
pkreset(pk)5617c478bd9Sstevel@tonic-gate pkreset(pk)
562462be471Sceastha struct pack *pk;
5637c478bd9Sstevel@tonic-gate {
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 	pk->p_ps = pk->p_pr =  pk->p_rpr = 0;
5667c478bd9Sstevel@tonic-gate 	pk->p_nxtps = 1;
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate static int
chksum(s,n)5707c478bd9Sstevel@tonic-gate chksum(s,n)
571462be471Sceastha char *s;
572462be471Sceastha int n;
5737c478bd9Sstevel@tonic-gate {
574462be471Sceastha 	short sum;
575462be471Sceastha 	unsigned short t;
576462be471Sceastha 	short x;
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate 	sum = -1;
5797c478bd9Sstevel@tonic-gate 	x = 0;
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 	do {
5827c478bd9Sstevel@tonic-gate 		if (sum<0) {
5837c478bd9Sstevel@tonic-gate 			sum <<= 1;
5847c478bd9Sstevel@tonic-gate 			sum++;
5857c478bd9Sstevel@tonic-gate 		} else
5867c478bd9Sstevel@tonic-gate 			sum <<= 1;
5877c478bd9Sstevel@tonic-gate 		t = sum;
5887c478bd9Sstevel@tonic-gate 		sum += (unsigned)*s++ & 0377;
5897c478bd9Sstevel@tonic-gate 		x += sum^n;
5907c478bd9Sstevel@tonic-gate 		if ((unsigned short)sum <= t) {
5917c478bd9Sstevel@tonic-gate 			sum ^= x;
5927c478bd9Sstevel@tonic-gate 		}
5937c478bd9Sstevel@tonic-gate 	} while (--n > 0);
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	return(sum);
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate static int
pksize(n)5997c478bd9Sstevel@tonic-gate pksize(n)
600462be471Sceastha int n;
6017c478bd9Sstevel@tonic-gate {
602462be471Sceastha 	int k;
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	n >>= 5;
6057c478bd9Sstevel@tonic-gate 	for(k=0; n >>= 1; k++);
6067c478bd9Sstevel@tonic-gate 	return(k);
6077c478bd9Sstevel@tonic-gate }
608