File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / sys / bsc / bscll.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:24:19 2019 UTC (6 years, 11 months ago) by root
Branches: bsd, MAIN
CVS tags: v12b, v121, HEAD
Power 6/32 Unix version 1.2b

#include "../bsc/local.h"
#include "../bsc/bscio.h"
#include "../bsc/bsc.h"

#ifdef BSC_DEBUG
#include "../bsc/bscdebug.h"
long bscdebug = 0;
long bscPC = 0;
#endif

/*	D.L.Buck and Associates, Inc. - %H%
 *
 *	COPYRIGHT NOTICE:
 *		Copyright c %H% - An unpublished work by 
 *		D.L.Buck and Associates, Inc.
 *
 *	PROPRIETARY RIGHTS NOTICE:
 *		All rights reserved. This document and program contains
 *		proprietary information of D.L.Buck and Associates,Inc.
 *		of San Jose, California, U.S.A., embodying confidential
 *		information,  ideas, and expressions,  no part of which
 *		may be reproduced, or transmitted in any form or by any
 *		means,  electronic,  mechanical,  or otherwise, without
 *		the written permission of D.L.Buck and Associates, Inc.
 */

/*
 * NAME
 *	bscll - CCI VIOCX' Communications Controller Interface
 *	and low-level hardware-dependent logic.
 * DESCRIPTION
 *	This file contains the CCI VIOCX' Communications Controller
 *	Interface routines prepared for the Computer Consoles, Inc.
 *	Power 5/20 ("Oneida") computer system.
 *	Included in this module are local initialization and termination
 *	routines (bsclopn, bsclcls: local open and close),
 *	local DSR checking logic (bsckdsr),
 *	local transmit start (bscxmit) and receiver reset (brxres) routines,
 *	and the interrupt handlers.
 *	Interrupts are actually fielded by other CCI-written routines, and
 *	routed to software here.
 *	These routines are meant to be hardware-dependent.
 */

#ifndef lint
char bscll_id[] = "%W% %Q% CCI";
#endif

#define t_dstat	t_col		/* Since 4.2 tty struct doesnot have dstat */
				/* we use t_col instead.		*/

/* External variables:							*/
extern struct bsc bsc[];	/* BSC Device structures: see bsc.c	*/
extern struct state states[];	/* BSC PSM State table: see bscpsm.c	*/
extern struct tty vx_tty[];
extern struct vcx vcx[];
char * strlchr();
struct vxcmd * vobtain();	/* Routine to obtain command buffer	*/
int bscxbsy;			/* Tx busy flags			*/

/*
 *	Bisync Low-Level Routines.
 *
 *	bsclopn - Local open routine
 *	bsclcls - Local close routine
 *	bscparam - Set up BSC device
 *	bscxmit	- Prepare xmit list and start BSC device
 *	bsctxd	- Transmission complete - awaken PSM
 *	bscrxc	- Receive single character
 */

/*
 * NAME
 *	bsclopn -- local line open routine
 * SYNOPSIS
 *	bsclopn (dev,bp)
 *	dev_t dev;
 *	struct bsc *bp;
 * DESCRIPTION
 *	Local open routine for CCI's VIOCX'.
 *	1. Find VIOCX and associated `vcx' structure.
 *	2. Initialize I/O port.
 * RETURNS
 *	0 for successful open,
 *	error number for failure (e.g., busy)
 */
/*VARARGS*/
bsclopn(dev, bp)
dev_t dev;
register struct bsc *bp;
{
	register struct vcx *xp;	/* Ptr to viocx control struct	*/
	struct tty *tp;			/* Ptr to associated tty	*/
	extern short vx_use;
	register int s;
	int port;

	dev = minor(dev);
	/* 1. Find VIOCX and associated `vcx' structure.		*/
	if ((xp = (struct vcx *) bp->b_devregs) == (struct vcx *)0)
		return ENXIO;
#ifdef BSC_DEBUG 
        bp->b_hlflgs |= BSC_DSR;	/* Force DSR on			*/
#endif

	/* 2. Initialize I/O Port.					*/
	port = dev;
/*	dev += (xp->v_nbr*16);   */
	dev  = (xp->v_nbr*16) + (dev%NBSC);   
	tp = &vx_tty[dev];		/* tp -> tty control struct	*/
	tp->t_dev &= 0xf;		/* Clear bscport no; upper nible*/
	tp->t_dev |= (port << 4);	/* Set bscport no 		*/
	tp->t_state = TS_ISOPEN;	/* Mark as open			*/
	tp->t_line = LDISP;		/* MARK LINE SWITCH #		*/
        tp->t_dstat = (char)port;       /* save bscport no. */
	bscparam(port);			/* Go program the device	*/
	/*brxres(port);*/		/* Done in bscparam().dn 2/2/85 */
	return 0;
}

/*
 * NAME
 *	bsclcls -- local bsc close
 * SYNOPSIS
 *	bsclcls (dev,bp)
 *	dev_t dev;
 *	struct bsc *bp;
 * DESCRIPTION
 *	Local close routine for CCI's VIOCX.
 */
/*ARGSUSED*/
bsclcls (dev,bp)
dev_t dev;
register struct bsc *bp;
{
	register struct vcx *xp;
	register struct vxcmd *cp;
	register struct tty *tp;
	int s;

	xp = (struct vcx *) bp->b_devregs;
/*	s = spl8();     */           
	cp = vobtain (xp);		/* Obtain command buffer	*/
	cp->cmd = MDMCTL;		/* Modem control operation	*/
	cp->par[0] = 0;			/* Turn DTR off			*/
	cp->par[1] = (dev%NBSC) + xp->v_loport;	/* Specify the device	*/
/*	cp->par[1] = dev + xp->v_loport;  */	/* Specify the device	*/
	vcmd (xp->v_nbr, &cp->cmd);	/* Send the command		*/
	sleep ((caddr_t)cp, BSCPRI);	/* Wait for completion		*/
	/*vrelease (xp, cp);*/		/* Done in compl. intr. handler */
	bscxbsy &= ~(1<<dev);		/* Ensure transmit not busy	*/
/*	splx(s);    */

/*	tp = &vx_tty[dev+xp->v_nbr*16];*//* Close tty			*/
	tp = &vx_tty[(dev%NBSC)+xp->v_nbr*16];/* Close tty		*/
	tp->t_state = 0;		/* Initial state		*/
	tp->t_line = 0;			/* Reset line switch		*/
}

/*
 *	bscparam -- set up user-controlled BSC device parameters
 *		if ASCII, set up length=7, odd parity, ASCII SYN
 *		if EBCDIC,       length=8, no parity, EBCDIC SYN
 */
bscparam(dev)			/* set up user-controlled BSC device params */
dev_t dev;
{
	extern char ebccls[], asccls[];/* character class ptr, tbls	*/
	register struct bsc *bp = &bsc[dev];
	register struct vxcmd *cp;
	register struct vcx *xp;
	register struct tty *tp;
	int s;

	xp = (struct vcx *) bp->b_devregs;
	s = spl8();
	cp = vobtain(xp);		/* Obtain command buffer	*/
	cp->cmd = LPARAX;		/* Load Port Parameters		*/
	cp->par[0] = (bp->b_hlflgs & BSCFDX) ? 1 : 0;
	cp->par[1] = (dev%NBSC) + xp->v_loport;	/* Port #		*/
	cp->par[2] = 0;			/* Not used			*/
	cp->par[3] = 10;		/* XMITDTA TimeOut (seconds)	*/
	if (bp->b_hlflgs & BSCASCII)	/* ASCII code in use		*/
	{
		cp->par[4] = 0x40;	/* 7 bits			*/
		cp->par[5] = ASCSYN;	/* ASCII SYN char		*/
		cp->par[6] = 0;		/* Not used			*/
		cp->par[7] = 1;		/* Odd Parity			*/
		bp->b_rxcls = asccls;	/* Use ascii char class tbl	*/
	} else {		/* EBCDIC code in use			*/
		cp->par[4] = 0xc0;	/* 8 bits			*/
		cp->par[5] = EBCSYN;	/* EBCDIC SYN char		*/
		cp->par[6] = 0;		/* Not used			*/
		cp->par[7] = 0;		/* No Parity			*/
		bp->b_rxcls = ebccls;	/* Use ebcdic char class tbl	*/
	}
	vcmd(xp->v_nbr, &cp->cmd);	/* Do LPARAX command		*/
	sleep ((caddr_t)cp, BSCPRI);	/* Wait on Completion		*/

	cp = vobtain(xp);		/* Obtain command buffer	*/
	cp->cmd = MDMCTL;		/* Set Modem Control		*/
	cp->par[1] = (dev%NBSC) + xp->v_loport;	/* Port #		*/
	cp->par[0] = MDM_DTR;		/* Turn on DTR			*/
	vcmd(xp->v_nbr, &cp->cmd);	/* Do MDMCTL command		*/
	sleep ((caddr_t)cp, BSCPRI);	/* Wait on Completion		*/

	/*vrelease (xp, cp);*/		/* Done in compl. intr. handler */
	splx(s);
	brxres(dev);			/* Reset receiver		*/
}

/*
 * NAME/SYNOPSIS
 *	bsckdsr(dev,bp)
 *	dev_t dev; struct bsc *bp;
 * DESCRIPTION
 *	Check DSR status, post result to b_hlflgs
 * ALGORITHM
 *	Currently ineffective; CCI fixing firmware problem.
 */
/*ARGSUSED*/
bsckdsr(dev,bp)		/* Check for current DSR status			*/
register dev_t dev;
register struct bsc *bp;
{	}	/* Completely ineffective */

#define	SIZEMASK 0x03ff	/* Lower portion of word is transmit length	*/
#define X_HUNT	0x0200	/* Hunting for synch				*/
#define	X_CNT	0x0003	/* Mask for g/p counter				*/

/*	NAME
 *		bscxmit - Start transmission on given device
 *	SYNOPSIS
 *		bscxmit (dev, newstate)
 *		dev_t dev;
 *		int newstate;
 *	ALGORITHM
 *		1. Save 'newstate' as psm state to follow completion of
 *		   transmission.  Initialize b_cntl control flags.
 *		2. Prepare for transmission.  Build VIOCX XMITDTA command
 *		   block, giving pointers and counts for each transmit data
 *		   element.  CRC must be calculated before transmission as
 *		   VIOCX' controller emulates simple DMA operation.
 *		3. Start transmission by giving XMITDTA command to VIOCX'.
 *	VALUE RETURNED
 *		None.
 *	ERRORS
 *		None.
 */
bscxmit (dev, newstate)
dev_t dev;
int newstate;
{
	register struct bsc *bp = &bsc[dev];
	int s, i, j;
	struct vxcmd *vobtain();
	register struct vcx *xp;
	register struct vxcmd *cp;
	register char *mp;
	char * addr, *phaddr, *p;
	caddr_t vtoph();

	/* Make sure we don't try to double transmit			*/
	xp = (struct vcx *)bp->b_devregs;
	s = spl8();
	if (bscxbsy & (1<<dev))	{	/* Tx already busy		*/
		splx(s);
		return;
	}
	bscxbsy |= 1<<dev;		/* Mark tx busy			*/
	/* 1. Save 'newstate' as psm state to follow completion of
	 *    transmission.  Initialize b_cntl control flags.
	 */
	bp->b_nstate = newstate;	/* Next state for PSM when tx done */

	/* 2. Prepare for transmission.  Build VIOCX XMITDTA command
	 *    block, giving pointers and counts for each transmit data
	 *    element.  CRC must be calculated before transmission as
	 *    VIOCX' controller emulates simple DMA operation.
	 */
	cp = vobtain(xp);		/* Obtain XMITDTA Cmd. Buffer	*/
/*	splx(s);   */		/* Should be done after vcmd().dn 2/2/85 */
	cp->cmd = XMITDTA-1;		/* Initially, zero items in tx list */
	mp = cp->par;	/* First xmit subcommand area	*/
	bp->b_crc[0] = bp->b_crc[1] = 0;/* Reset lrc (we compute)	*/

	for (bp->b_txlptr = &bp->b_txlst[1];/* For each xmit list element,*/
	     bp->b_txlptr->xptr;	/* until end of list,		*/
	     ++bp->b_txlptr) {		/* stepping one list element,	*/
		/*			   Compute the CRC		*/
		i = bp->b_txlptr->xnum & SIZEMASK;	/* Length	*/
		if (!i)
			continue;	/* zero-length element		*/
		addr = bp->b_txlptr->xptr;		/* Address	*/
		addr[i] = '\0';
		if (bp->b_txlptr->xnum & X_CRC)	/* Needs crc accumulation */
		{	
			register char *next;
			if(!(bp->b_hlflgs & BSC_XTRN)){
			/* Append CRC after each IUS			*/
			    while (next = strlchr(addr,0x1f,
			       (int)(&bp->b_txlptr->xptr[i]-addr))) {
				   ++next;
				   crccalc((int)(next-addr),addr,bp);
				   if (!(bp->b_hlflgs & BSCASCII))
					*next++ = bp->b_crc[0];
				   *next++ = bp->b_crc[1];
				   bp->b_crc[0] = bp->b_crc[1] = 0;
				   addr = next;
			   }
			} else {
			/* Transparent: skip DLE in DLE-xxx sequence	*/
			    while(next = strlchr(addr,0x10,
				(int)(&bp->b_txlptr->xptr[i]-addr))) {
				    ++next;
				    crccalc((int)(next-addr),addr,bp);
				    addr = ++next;
			    }
			}
			/* Compute CRC for last segment			*/
			crccalc((int)(&bp->b_txlptr->xptr[i] - addr), addr, bp);
		}
		addr = bp->b_txlptr->xptr;
		if (i > 254) {	/* Max of 254 bytes per VIOC list element */
			/* Divide into two transmit segments for DMA	*/
			mp[1] = 254-1;	/* Set count		*/
			mp[0] = (dev%NBSC)+xp->v_loport;/* Set device	*/
			phaddr = vtoph(0, addr);
			p = (char *)&phaddr;
			for (j=0; j < sizeof phaddr; j++)
				mp[j+2] = *p++;
			i -= 254;
			addr += 254;
			mp += 6;
			++cp->cmd;			/* Count # elements*/
		}
		mp[1] = i-1;				/* Set count	*/
		mp[0] = (dev%NBSC)+xp->v_loport;	/* Set device	*/
#if BSC_DEBUG
		if (bscdebug & BSCLLX) {
			register long ic;
			register char *d_addr = addr;

			printf("bscxmit: ");
			for (ic=0;ic<i;ic++) {
				printf("(%lx)",d_addr[ic] & 0xff);
				if (!(ic % 15)) printf("\n");
			}
		}
#endif
		phaddr = vtoph(0, addr);
		p = (char *)&phaddr;
		for (j=0; j < sizeof phaddr; j++)
			mp[j+2] = *p++;
		mp += 6;		/* Advance cmd list element ptr	*/
		++cp->cmd;		/* Keep count on # elements	*/
	}

	/* 3. Start transmission by giving XMITDTA command to VIOCX'.	*/
	vcmd (xp->v_nbr, &cp->cmd);	/* Give XMITDTA cmd. to VIOCX'	*/
        splx(s);
}

/*
 * NAME/SYNOPSIS
 *	bsctxd(dev)
 *	int dev
 * DESCRIPTION
 *	Called from CCI's interrupt fielder for VIOCX command completion.
 *	(vxxint, in vcx.c)
 *	If the command was for a device having tp->t_line == LDISP
 *	(marked as BSC device in vxreset),
 *	this routine is called with the port number.
 * ALGORITHM
 *	Turn off Tx Busy flag, set PSM state to previously given newstate
 *	(see bscxmit), and call PSM.
 */
bsctxd(dev)			/* Transmission Done */
int dev;
{
	register struct bsc *bp = &bsc[dev];

	bscxbsy &= ~(1<<dev);		/* Tx done - turn off busy flag	*/
	if (states[bp->b_state].s_type != 's')
		return;
	bp->b_state = bp->b_nstate;	/* New state			*/
	bscpsm((dev_t)dev);		/* Restart PSM			*/
}

/*
 * Receive Processing Data and Tables
 */
char adlelst[] = { '0', '1', ';', '<', 0x04 };
char edlelst[] = { 0x70, 0x61, 0x6b, 0x7c, 0x37 };
char dlexxx[] =  {C_AK0, C_AK1, C_WAK, C_RVI, C_EOT };

/* Level 0 data classes: */
#define	C0_DATA	0	/* Data character				*/
#define	C0_SOH	1	/* Start of Heading				*/
#define	C0_STX	2	/* Start of Text				*/
#define	C0_ETX	3	/* End of Text and Last Block			*/
#define	C0_ETB	4	/* End of Text, not Last Block			*/
#define	C0_IUS	5	/* Unit Separator (2780 only)			*/
#define	C0_SYN	6	/* Synchronous Idle char.			*/
#define	C0_NAK	7	/* Negative Acknowledgement			*/
#define	C0_DLE	8	/* Data Link Escape				*/
#define	C0_ENQ	9	/* Enquiry					*/
#define	C0_EOT	10	/* End of Transmission (Session)		*/

/* state 0 = initialization
 * state 1 = collect heading following SOH
 * state 2 = collect data following STX
 * state 3 = interpret character after DLE
 * state 4 = collect transparent data
 * state 5 = interpret character after DLE in transparent mode
 *
 *
 * Date structure of table entries is:
 * 	high order nibble = next state
 *	low order nibble  = action to take
 *
 */

	/* state:0     1     2     3     4     5 */
char clstbl[] = {
		0x02, 0x12, 0x24, 0x0b, 0x44, 0x44,	/* 0: data	*/
		0x11, 0x12, 0x24, 0x02, 0x44, 0x44,	/* 1: soh	*/
		0x21, 0x20, 0x24, 0x47, 0x44, 0x44,	/* 2: stx	*/
		0x02, 0x06, 0x06, 0x02, 0x44, 0x06,	/* 3: etx	*/
		0x02, 0x06, 0x06, 0x02, 0x44, 0x06,	/* 4: etb	*/
		0x02, 0x12, 0x25, 0x02, 0x44, 0x25,	/* 5: ius	*/
		0x0c, 0x1c, 0x2c, 0x0c, 0x44, 0x4c,	/* 6: syn	*/
		0x08, 0x12, 0x24, 0x02, 0x44, 0x44,	/* 7: nak	*/
		0x30, 0x30, 0x30, 0x02, 0x5c, 0x44,	/* 8: dle	*/
		0x09, 0x03, 0x03, 0x02, 0x44, 0x03,	/* 9: enq	*/
		0x0a, 0x12, 0x24, 0x0a, 0x44, 0x44};	/*10: eot	*/

	/*	   SOH, STX, ETX, ETB, IUS, SYN, NAK, DLE, ENQ, EOT */
char ebccls[] = { 0x01,0x02,0x03,0x26,0x1f,0x32,0x3d,0x10,0x2d,0x37 };
char asccls[] = { 0x01,0x02,0x03,0x17,0x1f,0x16,0x15,0x10,0x05,0x04 };

static int tval = 5;
static dev_t sdev;

bel_psm(bp)
register struct bsc *bp;
{
	if ((!bp->b_rclptr) || (states[bp->b_state].s_type != 'r'))
		printf("\nthrowing away messages");
	else {
		bp->b_state = bp->b_rclptr[bp->b_class1];
		bp->b_alenb = 0;
		bp->b_rclptr = (char *)0;
		bscpsm(bp-&bsc[0]);
	}
}

bscrxc(c,tp)			/* Receive Single Character */
struct tty *tp;
short c;
{
	register struct bsc *bp;
	register char *p;
	register dev_t dev;
	int class, stact;
	short cc;			/* Character in 'c'		*/
	char tc;			/* Same char for trace call	*/

/***	dev = tp - vx_tty;
	dev -= (((struct vcx *)(bsc[0].b_devregs))->v_nbr * 16);
***/
        dev = (dev_t)tp->t_dstat;	/* set in bsclopb() */
	bp = &bsc[dev];
	cc = c;				/* Obtain character		*/
	cc &= 0xff;			/* Keep lower 8 bits of char	*/
	tc = (char)cc;
	if (bp->b_rxcnt) {		/* Do minimal processing - crc/lrc */
		crccalc (1, &tc, bp);	/* do crc inclusion */
		if (--bp->b_rxcnt) 	/* not end of crc sequence */
			goto brxrti;
		if (bp->b_class1 == C_IUS)	/* IUS - continue */
			goto brxrti;
		if (bp->b_crc[0] || bp->b_crc[1])	/* if crc error */
			bp->b_hlflgs |= BSC_CRCERR;
brx_term:	/* Termination of level-0 message */
		if ((bp->b_hlflgs & BSC_POLLWT) && 
			(bp->b_class1 == C_EOT)) {
			bp->b_hlflgs &= ~BSC_POLLWT;
			goto brxrti;
		}
		if (bp->b_class1 == C_EOT) {
			bp->b_crc[0] = bp->b_crc[1] = 0;
			bp->b_rxhptr = bp->b_iocout.b_hostid;
			bp->b_rxhcnt = 0;
			bp->b_rxst0 = 0;
		}
		else brxres(dev);
		if ((!bp->b_rclptr) || (states[bp->b_state].s_type != 'r')) {
		/*	sdev = dev;  	*/
printf("\nbscrxc: timeout,(r%lx)(s%lx)(t%lx)",
	bp->b_rclptr,bp->b_state,states[bp->b_state].s_type&0xff);
			timeout(bel_psm,bp,tval);
			goto brxrti;
		}
		bp->b_state = bp->b_rclptr[bp->b_class1];
		bp->b_alenb = 0;
		bp->b_rclptr = (char *) 0;
		if (bp->b_trace)
			bsctr (dev, bp->b_class1, 'c');
		bscpsm(dev);
		goto brxrti;
	}

	/* Check for HUNT mode */
	if (bp->b_cntl & X_HUNT) {
		if (cc != 0)	/* We get a null when hunt done */
			goto brxrti;
	/*	c = spl8(); 	*/

		/* Release command buffer */
		/*vrelease (bp->b_devregs, bp->b_cmdbuf);*/
                /*	splx(c);	*/
		bp->b_cntl &= ~X_HUNT;
		goto brxrti;
	}

	if (bp->b_rclptr == (char *)0)	/* Is PSM waiting on us? */
		goto brxrti;		/* no - ignore this character */

	/* Classify current data character, get new state, do action */
	p = strlchr(bp->b_rxcls, cc, sizeof asccls);
	if (p == (char *) 0)
		class = 0;
	else	class = (p - bp->b_rxcls) + 1;


	stact = (clstbl[class*6 + bp->b_rxst0]) & 0xff;

#ifdef BSC_DEBUG
	if (bscdebug & LRCVCHAR)
		printf("\nbscrcx: (%lx)",cc & 0xff);
	if (bscdebug & LSTATE)
		printf("\nbscrcx: (lstate=%d)(event=%d)(nstate=%d)(act=%d)",
			bp->b_rxst0, class, stact >> 4, stact & 15);
#endif

	bp->b_rxst0 = stact >> 4;	/* new state 0 */
	switch (stact & 15) {		/* take action */
	case 0:
		break;

	case 1:	/* Prepare to receive data */
		bp->b_hlflgs &= ~BSC_XTRN;	/* reset transp indicator */
act1a:		bp->b_hlflgs &= ~BSC_CRCERR;	/* reset CRC error flag */
		bp->b_rxdptr = bp->b_buffer;		/* receive data ptr */
		bp->b_bsize = 0;		/* data count <- 0 */
		if (class == C0_SOH) {		/* if header, reset hptr */
			bp->b_rxhptr = bp->b_iocout.b_hostid;
			bp->b_rxhcnt = 0;
		}
		bp->b_crc[0] = bp->b_crc[1] = 0;	/* clear crc/lrc */
		bp->b_cntl |= X_ACMCRC;	/* set accum flag */
		break;

	case 2:	/* Save current character as heading info */
		/* Must be 'printable' character in code set in use */
		if (bp->b_rxhcnt < sizeof bp->b_iocout.b_hostid &&
		    (((bp->b_hlflgs & BSCASCII) && cc >= 0x20 && cc < 0x7e) ||
		    (!(bp->b_hlflgs& BSCASCII) && cc >= 0x40 && cc < 0xf9))) {
			*bp->b_rxhptr++ = (char)cc;
			++bp->b_rxhcnt;
		} else
			brxres(dev);
		if (bp->b_cntl & X_ACMCRC)
			crccalc (1, &tc, bp);
		break;

	case 3:	/* Terminate, class = TTD */
		bp->b_class1 = C_TTD;
		goto brx_term;

	case 5:	/* crc/lrc for IUS follows - skip processing it */
		bp->b_class1 = C_IUS;
		bp->b_rxcnt = (bp->b_hlflgs & BSCASCII) ? 1 : 2;
		/* Fall through to case 4, saving IUS as data */

	case 4:	/* Save current character as data */
		crccalc (1, &tc, bp);
		if (++bp->b_bsize <= BSCMBLK)
			*bp->b_rxdptr++ = (char)cc;
		if (bp->b_trace > 1) {	/* data trace? */
			tc = (char)cc;
			bsctr(dev,bp->b_class1,'y',(short)1,&tc);
		}
		break;

	case 6:	/* crc/lrc for ETB/ETX follows - skip processing it */
		crccalc (1, &tc, bp);
		bp->b_class1 = class - C0_ETX + C_ETX;
		if (bp->b_hlflgs & BSCASCII)
			bp->b_rxcnt = 1;	/* Lrc for Ascii	*/
		else
			bp->b_rxcnt = 2;	/* 2 for crc		*/
		break;

	case 7:	/* Set crc accum and transparency flag */
		bp->b_hlflgs |= BSC_XTRN;
		goto act1a;

	case 8:	/* Terminate; NAK */
		bp->b_class1 = C_NAK;
		goto brx_term;

	case 9:	/* Terminate; ENQ */
		bp->b_class1 = C_ENQ;
		goto brx_term;

	case 10:/* Terminate; EOT */
		bp->b_class1 = C_EOT;
		goto brx_term;

	case 11:/* Check for DLE-xxx sequence; terminate with L1 code */
		/* if applicable, else ignore */
		if (bp->b_hlflgs & BSCASCII) {
			p = strlchr(adlelst,cc,sizeof adlelst);
			if (p == (char *)0)
				break;
			bp->b_class1 = dlexxx[p - adlelst];
		} else {
			p = strlchr(edlelst,cc,sizeof edlelst);
			if (p == (char *)0)
				break;
			bp->b_class1 = dlexxx[p - edlelst];
		}
		goto brx_term;

	case 12:/* Don't accum crc/lrc on this. */
		bp->b_alarm = 2*PSMTPS;	/* Set 2 sec. timeout		*/
		break;
	}
brxrti:;
}

brxres(dev)	/* Reset Receiver (Hunt Mode) */
dev_t dev;
{
	register struct bsc *bp = &bsc[dev];
	register struct vxcmd *cp;
	register struct vcx *xp;
	struct vxcmd * vobtain();
	int x = spl8();

	xp = (struct vcx *) bp->b_devregs;
	cp = vobtain(xp);	/* Get command buffer for Hunt Command	*/
	/* splx(x); */  	/* Should be after vcmd(); dn 2/27/85   */
	cp->cmd = HUNTMD;	/* Synch. Hunt Mode Command		*/
	cp->par[0] = 0;		/* Not used				*/
	cp->par[1] = (dev%NBSC)+xp->v_loport;	/* Port Number		*/
	vcmd(xp->v_nbr, &cp->cmd);	/* Execute Command		*/
	splx(x);
	bp->b_cntl |= X_HUNT;
	bp->b_crc[0] = bp->b_crc[1] = 0;	/* Reset lrc		*/
	bp->b_rxhptr = bp->b_iocout.b_hostid;	/* reset ptr for header	*/
	bp->b_rxhcnt = 0;		/* Reset current header count	*/
	bp->b_rxst0 = 0;		/* Reset lvl 0 state		*/
}

char * strlchr(s,c,l)	/* locate character in string */
register char *s, c;
register int l;
{	while (--l >= 0) {
		if (*s == c)
			return (s);
		++s;
	}
	return (char *) 0;
}

/*	CRC table - crc-16	*/
short crctab[] = {
	0x0000,	/* 00 */
	0xc0c1,	/* 01 */
	0xc181,	/* 02 */
	0x0140,	/* 03 */
	0xc301,	/* 04 */
	0x03c0,	/* 05 */
	0x0280,	/* 06 */
	0xc241,	/* 07 */
	0xc601,	/* 08 */
	0x06c0,	/* 09 */
	0x0780,	/* 0a */
	0xc741,	/* 0b */
	0x0500,	/* 0c */
	0xc5c1,	/* 0d */
	0xc481,	/* 0e */
	0x0440,	/* 0f */
	0xcc01,	/* 10 */
	0x0cc0,	/* 11 */
	0x0d80,	/* 12 */
	0xcd41,	/* 13 */
	0x0f00,	/* 14 */
	0xcfc1,	/* 15 */
	0xce81,	/* 16 */
	0x0e40,	/* 17 */
	0x0a00,	/* 18 */
	0xcac1,	/* 19 */
	0xcb81,	/* 1a */
	0x0b40,	/* 1b */
	0xc901,	/* 1c */
	0x09c0,	/* 1d */
	0x0880,	/* 1e */
	0xc841,	/* 1f */
	0xd801,	/* 20 */
	0x18c0,	/* 21 */
	0x1980,	/* 22 */
	0xd941,	/* 23 */
	0x1b00,	/* 24 */
	0xdbc1,	/* 25 */
	0xda81,	/* 26 */
	0x1a40,	/* 27 */
	0x1e00,	/* 28 */
	0xdec1,	/* 29 */
	0xdf81,	/* 2a */
	0x1f40,	/* 2b */
	0xdd01,	/* 2c */
	0x1dc0,	/* 2d */
	0x1c80,	/* 2e */
	0xdc41,	/* 2f */
	0x1400,	/* 30 */
	0xd4c1,	/* 31 */
	0xd581,	/* 32 */
	0x1540,	/* 33 */
	0xd701,	/* 34 */
	0x17c0,	/* 35 */
	0x1680,	/* 36 */
	0xd641,	/* 37 */
	0xd201,	/* 38 */
	0x12c0,	/* 39 */
	0x1380,	/* 3a */
	0xd341,	/* 3b */
	0x1100,	/* 3c */
	0xd1c1,	/* 3d */
	0xd081,	/* 3e */
	0x1040,	/* 3f */
	0xf001,	/* 40 */
	0x30c0,	/* 41 */
	0x3180,	/* 42 */
	0xf141,	/* 43 */
	0x3300,	/* 44 */
	0xf3c1,	/* 45 */
	0xf281,	/* 46 */
	0x3240,	/* 47 */
	0x3600,	/* 48 */
	0xf6c1,	/* 49 */
	0xf781,	/* 4a */
	0x3740,	/* 4b */
	0xf501,	/* 4c */
	0x35c0,	/* 4d */
	0x3480,	/* 4e */
	0xf441,	/* 4f */
	0x3c00,	/* 50 */
	0xfcc1,	/* 51 */
	0xfd81,	/* 52 */
	0x3d40,	/* 53 */
	0xff01,	/* 54 */
	0x3fc0,	/* 55 */
	0x3e80,	/* 56 */
	0xfe41,	/* 57 */
	0xfa01,	/* 58 */
	0x3ac0,	/* 59 */
	0x3b80,	/* 5a */
	0xfb41,	/* 5b */
	0x3900,	/* 5c */
	0xf9c1,	/* 5d */
	0xf881,	/* 5e */
	0x3840,	/* 5f */
	0x2800,	/* 60 */
	0xe8c1,	/* 61 */
	0xe981,	/* 62 */
	0x2940,	/* 63 */
	0xeb01,	/* 64 */
	0x2bc0,	/* 65 */
	0x2a80,	/* 66 */
	0xea41,	/* 67 */
	0xee01,	/* 68 */
	0x2ec0,	/* 69 */
	0x2f80,	/* 6a */
	0xef41,	/* 6b */
	0x2d00,	/* 6c */
	0xedc1,	/* 6d */
	0xec81,	/* 6e */
	0x2c40,	/* 6f */
	0xe401,	/* 70 */
	0x24c0,	/* 71 */
	0x2580,	/* 72 */
	0xe541,	/* 73 */
	0x2700,	/* 74 */
	0xe7c1,	/* 75 */
	0xe681,	/* 76 */
	0x2640,	/* 77 */
	0x2200,	/* 78 */
	0xe2c1,	/* 79 */
	0xe381,	/* 7a */
	0x2340,	/* 7b */
	0xe101,	/* 7c */
	0x21c0,	/* 7d */
	0x2080,	/* 7e */
	0xe041,	/* 7f */
	0xa001,	/* 80 */
	0x60c0,	/* 81 */
	0x6180,	/* 82 */
	0xa141,	/* 83 */
	0x6300,	/* 84 */
	0xa3c1,	/* 85 */
	0xa281,	/* 86 */
	0x6240,	/* 87 */
	0x6600,	/* 88 */
	0xa6c1,	/* 89 */
	0xa781,	/* 8a */
	0x6740,	/* 8b */
	0xa501,	/* 8c */
	0x65c0,	/* 8d */
	0x6480,	/* 8e */
	0xa441,	/* 8f */
	0x6c00,	/* 90 */
	0xacc1,	/* 91 */
	0xad81,	/* 92 */
	0x6d40,	/* 93 */
	0xaf01,	/* 94 */
	0x6fc0,	/* 95 */
	0x6e80,	/* 96 */
	0xae41,	/* 97 */
	0xaa01,	/* 98 */
	0x6ac0,	/* 99 */
	0x6b80,	/* 9a */
	0xab41,	/* 9b */
	0x6900,	/* 9c */
	0xa9c1,	/* 9d */
	0xa881,	/* 9e */
	0x6840,	/* 9f */
	0x7800,	/* a0 */
	0xb8c1,	/* a1 */
	0xb981,	/* a2 */
	0x7940,	/* a3 */
	0xbb01,	/* a4 */
	0x7bc0,	/* a5 */
	0x7a80,	/* a6 */
	0xba41,	/* a7 */
	0xbe01,	/* a8 */
	0x7ec0,	/* a9 */
	0x7f80,	/* aa */
	0xbf41,	/* ab */
	0x7d00,	/* ac */
	0xbdc1,	/* ad */
	0xbc81,	/* ae */
	0x7c40,	/* af */
	0xb401,	/* b0 */
	0x74c0,	/* b1 */
	0x7580,	/* b2 */
	0xb541,	/* b3 */
	0x7700,	/* b4 */
	0xb7c1,	/* b5 */
	0xb681,	/* b6 */
	0x7640,	/* b7 */
	0x7200,	/* b8 */
	0xb2c1,	/* b9 */
	0xb381,	/* ba */
	0x7340,	/* bb */
	0xb101,	/* bc */
	0x71c0,	/* bd */
	0x7080,	/* be */
	0xb041,	/* bf */
	0x5000,	/* c0 */
	0x90c1,	/* c1 */
	0x9181,	/* c2 */
	0x5140,	/* c3 */
	0x9301,	/* c4 */
	0x53c0,	/* c5 */
	0x5280,	/* c6 */
	0x9241,	/* c7 */
	0x9601,	/* c8 */
	0x56c0,	/* c9 */
	0x5780,	/* ca */
	0x9741,	/* cb */
	0x5500,	/* cc */
	0x95c1,	/* cd */
	0x9481,	/* ce */
	0x5440,	/* cf */
	0x9c01,	/* d0 */
	0x5cc0,	/* d1 */
	0x5d80,	/* d2 */
	0x9d41,	/* d3 */
	0x5f00,	/* d4 */
	0x9fc1,	/* d5 */
	0x9e81,	/* d6 */
	0x5e40,	/* d7 */
	0x5a00,	/* d8 */
	0x9ac1,	/* d9 */
	0x9b81,	/* da */
	0x5b40,	/* db */
	0x9901,	/* dc */
	0x59c0,	/* dd */
	0x5880,	/* de */
	0x9841,	/* df */
	0x8801,	/* e0 */
	0x48c0,	/* e1 */
	0x4980,	/* e2 */
	0x8941,	/* e3 */
	0x4b00,	/* e4 */
	0x8bc1,	/* e5 */
	0x8a81,	/* e6 */
	0x4a40,	/* e7 */
	0x4e00,	/* e8 */
	0x8ec1,	/* e9 */
	0x8f81,	/* ea */
	0x4f40,	/* eb */
	0x8d01,	/* ec */
	0x4dc0,	/* ed */
	0x4c80,	/* ee */
	0x8c41,	/* ef */
	0x4400,	/* f0 */
	0x84c1,	/* f1 */
	0x8581,	/* f2 */
	0x4540,	/* f3 */
	0x8701,	/* f4 */
	0x47c0,	/* f5 */
	0x4680,	/* f6 */
	0x8641,	/* f7 */
	0x8201,	/* f8 */
	0x42c0,	/* f9 */
	0x4380,	/* fa */
	0x8341,	/* fb */
	0x4100,	/* fc */
	0x81c1,	/* fd */
	0x8081,	/* fe */
	0x4040,	/* ff */
	};

crccalc(count, buffer, bp)
register int count;
register char *buffer;
struct bsc *bp;
{
	register unsigned int work, crc;

	crc = ((bp->b_crc[1] & 0xff)<<8) | (bp->b_crc[0] & 0xff);
	if (bp->b_hlflgs & BSCASCII)
		while (--count >= 0)	{
			work = (*buffer++) & 0xff;
			crc ^= work | (work << 8);
		}
	else
		while (--count >= 0)	{
			work = crctab[0xff & (crc ^ *buffer++)];
			crc = (work & 0xff00) |
			      (0xff & ((crc >> 8) ^ work));
		}
	bp->b_crc[0] = crc;
	bp->b_crc[1] = crc >> 8;
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.