File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / sys / bsc / bsctr.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

/*	D.L.Buck and Associates, Inc. - 8/27/84
 *
 *	COPYRIGHT NOTICE:
 *		Copyright c 8/27/84 - 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
 *	bsctr - BISYNC TRACE Driver
 *
 * DESCRIPTION
 *	This trace module represents a pseudo-device to Unix. It has
 *	the usual open, close, read, and ioctl routines for a read-only
 *	device. As well, it has a trace event logging routine which is
 *	called from the other portions of the bisync driver to log state
 *	changes, received information, transmitted information, and errors.
 *	Trace events are stored in a trace buffer until read by a user-level
 *	routine.
 */

#ifndef lint
static char bsctr_c[] = "@(#)bsctr.c	1.7 REL";
#endif

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

#if defined BSD42
#define ERRRET(x)	return x
#define	UCOUNT	uio->uio_resid
#else
#define	ERRRET(x)	u.u_error = x; return
#define	UCOUNT	u.u_count
#endif

#define SIZEMASK 0x03ff

extern struct bsc bsc[];	/* device information */
char bsctbuf[TBUFSIZE]; 	/* circular trace buffer */
char *bsctbin, *bsctbout;	/* ptrs to next write, read locations */
char *lastpkt;			/* pts to len field of last pkt if 'y' */
char bscbw;			/* someone's waiting on the trace buffer */
unsigned char bsclost;		/* number of lost trace events */
int bsctlock = -1;		/* Trace lock */
#if defined BSD42
extern struct timeval time;
#define TRTIME time.tv_sec
#else
extern long time;
#define TRTIME time
#endif

#define INSERT(x)	{*bsctbin = (x);\
			if (++bsctbin == &bsctbuf[TBUFSIZE]) bsctbin = bsctbuf;}
#define ZERO    0	/* dummy insert value for odd byte receive packets */

/*
 * NAME
 *	bsctr - trace an event for Bisync Drivers
 * SYNOPSIS
 *	bsctr (dev, state, type [, len, dptr])
 *	dev_t dev;	Device number
 *	unsigned state;	State number (bscpsm) or other info (bscll)
 *	char type;	Trace Packet type
 *	short len;	(Optional) Length of data section of packet
 *	char *dptr;	(Optional) Pointer to data section (kernel space)
 * ALGORITHM
 *	1. Check for trace buffer overflow
 *	2. If we can't insert next trace packet, count
 *	   trace buffer overruns. Otherwise, insert
 *	   packet into trace buffer.
 *	3. If the last packet was of type 'y' and this packet is the
 *	   same, combine the packets by merging the data from the
 *	   second into the first.
 *	4. If the last packet was type 'y' and the data length was
 *	   odd, make it even by adding a dummy data byte.
 *	5. Add the new data packet by inserting the time (a long),
 *	   state, type, and if type 'x' or 'y', the length and
 *	   data.
 * MACHINE DEPENDENCIES
 *	This algorithm assumes a 'normal' byte ordering within a short.
 *	If the length needs to be increased ((3) above), the low-order
 *	byte address is computed and incremented, and any carry
 *	added to the computed high-order address.
 *	On Intel and PDP-11's, for example, this algorithm will need
 *	to be modified.
 */	

bsctr(dev,state,type,len,dptr)
dev_t dev;		/* bsc device minor number */
unsigned state; 	/* current state number, or other info */
char type;		/* current state's type */
register short int len;	/* length of data in dptr */
register char *dptr;	/* data to be logged */
{
	register int avail;	/* number of trace buffer bytes available */
	short int givenlen;

	/* 1. check for trace buffer overflow */
	avail = (bsctbin >= bsctbout) ? TBUFSIZE - (bsctbin - bsctbout):
				      bsctbout - bsctbin;
	--avail;	/* don't allow in to catch out */

	/* 2. if we can't insert next trace packet, count
	 *	trace buffer overruns. Otherwise, insert
	 *	packet into trace buffer.
	 */
	givenlen = (type < 'x') ? 0 : (len & SIZEMASK);

	if (avail < givenlen+8) {	/* we will lose data */
		++bsclost;
		return;
	}

/*
 *   3.	If it is a 'y' type (receive) then the characters will be
 *	sent here one at a time.  In order to store them similarly to
 *	'x' types (transmit), each character is added to the end of the
 *	list of received characters and the length is incremented by one
 *	instead of storing each of the characters as an individual packet.
 *	The first receive character is stored just as a transmit packet
 *	with a length of one.  The next packet, if a 'y', is stored as 
 *	noted above.
 */

	if (type == 'y' && lastpkt) {
		INSERT(*dptr);
		lastpkt[0]++;		/* Incr. length */
		if (*lastpkt == 0) {	/* Overflow? */
			if (lastpkt == bsctbuf)
				bsctbuf[TBUFSIZE-1]++;
			else	lastpkt[-1]++;
		}
	} else	{
		/*
		 * Check to see if the last character stored was a receive type
		 * and whether the length was odd.  If it was, a 
		 * dummy character must be added to force an even boundary
		 * as with transmit characters
		 */
		if (lastpkt && (*lastpkt & 1))
				INSERT(ZERO);
		lastpkt = (char *)0;
		
		INSERT(TRTIME>>24);
		INSERT(TRTIME>>16);
		INSERT(TRTIME>>8);
		INSERT(TRTIME);
		INSERT(state);
		INSERT(type);
		if (type >= 'x') {	/* we will log data */
			INSERT(givenlen>>8);
			if (type == 'y')
				lastpkt = bsctbin;
			INSERT(givenlen);
			if (type == 'x' && (givenlen & 1)) ++givenlen;
			while (--givenlen >= 0)
				INSERT(*dptr++);
		}
	}
	if (bscbw) {		/* someone waiting */
		bscbw = 0;
		wakeup (bsctbuf);
	}
}

#if defined BSD42
bstread(dev,uio)	/* user request to read trace buffer */
register dev_t dev;
struct uio *uio;
#else
bstread(dev)	/* user request to read trace buffer */
register dev_t dev;
#endif
{
	register int x, diff;
	int errcode = 0;

	dev = minor(dev);
	x = spl8();
	while (bsctbin == bsctbout) {	/* buffer empty */
		if (bsc[dev].b_mode == BSC_CLOSED){
			splx(x);
#if defined BSD42
			return 0;
#else
			return;
#endif
		}
		++bscbw;		/* indicate we'll sleep for trace buf*/
		sleep(bsctbuf, BSCPRI);/* sleep for it */
	}
	if (lastpkt && (*lastpkt & 1))
		INSERT(ZERO);
	lastpkt = (char *)0;
	diff = (bsctbin > bsctbout) ? bsctbin - bsctbout :
			TBUFSIZE - (bsctbout - bsctbin);
	splx(x);
	if (diff > UCOUNT) diff = UCOUNT;
	if (&bsctbout[diff] >= &bsctbuf[TBUFSIZE])  {
		x = &bsctbuf[TBUFSIZE] - bsctbout;
#if defined BSD42
		errcode = uiomove(bsctbout, x, UIO_READ, uio);
		if (!errcode)
			errcode = uiomove (bsctbuf, diff - x, UIO_READ, uio);
#else
		if (iomove (bsctbout, x, B_READ) ||
		    iomove (bsctbuf, diff - x, B_READ))
			errcode = EFAULT;
#endif
		bsctbout = &bsctbuf[diff - x];
	} else {
#if defined BSD42
		errcode = uiomove(bsctbout, diff, UIO_READ, uio);
#else
		if (iomove(bsctbout, diff, B_READ))
			errcode = EFAULT;
#endif
		bsctbout += diff;
	}
	/* ?. If trace events were lost, add loss event to next buffer */
	if (bsclost) {	/* # trace events lost */
		x = spl8();
		bsctr(dev, bsclost, 'o');	/* overrun event */
		bsclost = 0;
		splx(x);
	}
#ifdef BSD42
	return errcode;
#else
	if (errcode)
		u.u_error = errcode;
#endif
}

bstopen(dev, flag)
dev_t dev;
{
	if (bsctlock != -1) {
		ERRRET(EBUSY);
	}
	bsctlock = dev = minor(dev);
	bsc[dev].b_trace = 1;		/* indicate tracing activated */
	bsctbin = bsctbout = bsctbuf;	/* initialize in, out pointers */
	lastpkt = (char *)0;
	while (bsc[dev].b_mode == BSC_CLOSED) /* wait till open */
		sleep (&bsc[dev].b_trace, BSCPRI);
#ifdef BSD42
	return 0;
#endif
}

bstclose(dev)
dev_t dev;
{
	wakeup(bsctbuf);
	bsc[minor(dev)].b_trace = 0;
	bsctlock = -1;
#if defined BSD42
	return 0;
#endif
}

bstioctl(dev,cmd,arg)		/* ioctl entry */
dev_t dev;
{
	bsc[minor(dev)].b_trace = (cmd&0xf) + 1;
#if defined BSD42
	return 0;
#endif
}

unix.superglobalmegacorp.com

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