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