Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/port/stasync.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname port/stasync.c 1990/1009
## diff -e /dev/null /n/bootesdump/1990/1009/sys/src/9/mips/stasync.c
0a
#include	"u.h"
#include	"lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"errno.h"

#define DPRINT 	if(asyncdebug)kprint

/*
 *  configuration
 */
enum {
	MAXFRAME=	256,	/* also known to tsm8 code */
};

/* input states */
enum { Hunt=0, Framing, Framed, Data, Escape };

typedef struct Async {
	QLock;

	int	inuse;
	Queue	*wq;

	/* output state */

	QLock	xmit;		/* transmit lock */
	int	chan;		/* current urp channel */
	Block	*bp;		/* current output buffer */
	int	count;
	ushort	crc;

	/* input state */

	int	state;		/* input state */
	uchar	buf[MAXFRAME];	/* current input buffer */
	int	icount;
	ushort	icrc;

	/* statistics */

	ulong	chan0;
	ulong	toolong;
	ulong	tooshort;
	ulong	badcrc;
	ulong	badescape;
	ulong	in;		/* bytes in */
	ulong	out;		/* bytes out */
} Async;

Async *async;

/*
 *  async stream module definition
 */
static void asynciput(Queue*, Block*);
static void asyncoput(Queue*, Block*);
static void asyncopen(Queue*, Stream*);
static void asyncclose(Queue*);
static void asyncreset(void);
Qinfo asyncinfo = { asynciput, asyncoput, asyncopen, asyncclose, "async", asyncreset };

int asyncdebug = 0;
int asyncerror;

static ushort crc_table[256] = {
#include "crc_16.h"
};

#define	BOT	0050		/* begin trailer */
#define	BOTM	0051		/* begin trailer, more data follows */
#define	BOTS	0052		/* seq update alg. on this trailer */

#define	FRAME		0x7e
#define	STUF		0x9d

#define	CRCSTART	(crc_table[0xff])
#define	CRCFUNC(crc,x)	(crc_table[((crc)^(x))&0xff]^((crc)>>8))

/*
 *  create the async structures
 */
static void
asyncreset(void)
{
	async = (Async *)ialloc(conf.nasync*sizeof(Async), 0);
}

/*
 *  allocate an async structure
 */
static void
asyncopen(Queue *q, Stream *s)
{
	Async *ap;

	DPRINT("asyncopen %d\n", s->dev);

	for(ap = async; ap < &async[conf.nasync]; ap++){
		qlock(ap);
		if(ap->inuse == 0)
			break;
		qunlock(ap);
	}
	if(ap == &async[conf.nasync])
		error(0, Enoasync);
	q->ptr = q->other->ptr = ap;

	ap->inuse = 1;
	ap->bp = 0;
	ap->chan = -1;
	ap->count = 0;
	ap->toolong = 0;
	ap->tooshort = 0;
	ap->badcrc = 0;
	ap->badescape = 0;
	ap->chan0 = 0;
	ap->in = 0;
	ap->out = 0;
	ap->wq = WR(q);
	ap->state = Hunt;
	qunlock(ap);
}

static void
asyncclose(Queue * q)
{
	Async *ap = (Async *)q->ptr;

	DPRINT("asyncstclose %d\n", ap-async);
	qlock(ap);
	ap->inuse = 0;
	qunlock(ap);
}

/*
 *  free all blocks of a message in `q', `bp' is the first block
 *  of the message
 */
static void
freemsg(Queue *q, Block *bp)
{
	for(; bp; bp = getq(q)){
		if(bp->flags & S_DELIM){
			freeb(bp);
			return;
		}
		freeb(bp);
	}
}

static void
showframe(char *t, Async *ap, uchar *buf, int n)
{
	kprint("a%d %s [", ap-async, t);
	while (--n >= 0)
		kprint(" %2.2ux", *buf++);
	kprint(" ]\n");
}

void
aswrite(Async *ap)
{
	if(ap->bp->rptr == ap->bp->wptr)
		return;
	FLOWCTL(ap->wq);
	PUTNEXT(ap->wq, ap->bp);
	ap->bp = 0;
}

void
asputf(Async *ap, int frame)
{
	uchar *p;
	int c;

	p = ap->bp->wptr;
	if(ap->count > 0) {
		if(asyncerror)
			ap->crc^=1, asyncerror=0;
		*p++ = c = ap->crc&0xff;
		if(c == FRAME)
			*p++ = 0x00;
		*p++ = c = (ap->crc>>8)&0xff;
		if(c == FRAME)
			*p++ = 0x00;
		ap->count = 0;
	}
	if(frame) {
		*p++ = FRAME;
		*p++ = FRAME;
	}
	ap->bp->wptr = p;
	if(asyncdebug > 2)
		showframe("out", ap, ap->bp->rptr, BLEN(ap->bp));
	aswrite(ap);
}

void
asputc(Async *ap, int c)
{
	int d;
	uchar *p;

	if(ap->bp == 0)
		ap->bp = allocb(MAXFRAME+4);
	p = ap->bp->wptr;
	if(ap->count <= 0) {
		*p++ = FRAME;
		*p++ = FRAME;
		*p++ = d = 0x80|((ap->chan>>5)&0x7e);
		ap->crc = CRCFUNC(CRCSTART, d);
		*p++ = d = 0x80|((ap->chan<<1)&0x7e);
		ap->crc = CRCFUNC(ap->crc, d);
	}
	*p++ = c;
	if(c == FRAME)
		*p++ = 0x00;
	ap->crc = CRCFUNC(ap->crc, c);
	ap->bp->wptr = p;
	if(++ap->count >= MAXFRAME-4)
		asputf(ap, 0);
	else if(ap->bp->lim - p < 8)
		aswrite(ap);
}

/*
 *  output a block
 *
 *  the first 2 bytes of every message are the channel number,
 *  low order byte first.  the third is a possible trailing control
 *  character.
 */
void
asyncoput(Queue *q, Block *bp)
{
	Async *ap = (Async *)q->ptr;
	int c, chan, ctl;

	if(bp->type != M_DATA){
		freeb(bp);
		return;
	}

	/*
	 *  get a whole message before handing bytes to the device
	 */
	if(!putq(q, bp))
		return;

	/*
	 *  one transmitter at a time
	 */
	qlock(&ap->xmit);

	/*
	 *  parse message
	 */
	bp = getq(q);
	if(bp->wptr - bp->rptr < 3){
		freemsg(q, bp);
		qunlock(&ap->xmit);
		return;
	}
	chan = bp->rptr[0] | (bp->rptr[1]<<8);
	ctl = bp->rptr[2];
	bp->rptr += 3;

	/*
	 *  new frame if the channel number has changed
	 */
	if(chan != ap->chan && ap->count > 0)
		asputf(ap, 0);
	ap->chan = chan;

	/*
	 *  send the 8 bit data
	 */
	for(;;){
		/*
		 *  put in next packet
		 */
		while (bp->rptr < bp->wptr) {
			asputc(ap, c = *bp->rptr++);
			if(c == STUF)
				asputc(ap, 0);
		}

		/*
		 *  get next block 
		 */
		if(bp->flags & S_DELIM){
			freeb(bp);
			break;
		}
		freeb(bp);
		bp = getq(q);
		if(bp==0)
			break;
	}

	/*
	 *  send the control byte if there is one
	 */
	if(ctl){
		asputc(ap, STUF);
		asputc(ap, ctl);
		switch (ctl) {
		case BOT:
		case BOTM:
		case BOTS:
			break;
		default:
			asputf(ap, 1);
		}
	}

	qunlock(&ap->xmit);
	return;
}

/*
 *  Read bytes from the raw input.
 */

void
asdeliver(Queue *q, Async *ap)
{
	int chan, c;
	Block *bp = 0;
	uchar *p = ap->buf;
	int n = ap->icount;

	chan = *p++ & 0x7e;
	chan = (chan<<5)|((*p++ & 0x7e)>>1);
	if(chan==0) {
		DPRINT("a%d deliver chan 0\n", ap-async);
		ap->chan0++;
		return;
	}
	for (n-=4; n>0; n--) {
		if(!bp) {
			bp = allocb(n+2);
			bp->flags |= S_DELIM;
			bp->wptr[0] = chan;
			bp->wptr[1] = chan>>8;
			bp->wptr[2] = 0;
			bp->wptr += 3;
		}
		if((c = *p++) == STUF) {
			--n;
			if((c = *p++) != 0) {
				bp->rptr[2] = c;
				if(asyncdebug > 1)
					kprint("a%d<-(%d)%3.3uo %d\n",
						ap-async, chan, bp->rptr[2],
						bp->wptr - bp->rptr - 3);
				PUTNEXT(q, bp);
				bp = 0;
				continue;
			} else
				c = STUF;
		}
		*bp->wptr++ = c;
	}
	if(bp) {
		if(asyncdebug > 1)
			kprint("a%d<-(%d)%3.3uo %d\n",
				ap-async, chan, bp->rptr[2],
				bp->wptr - bp->rptr - 3);
		PUTNEXT(q, bp);
	}
}

static void
asynciput(Queue *q, Block *bp)
{
	int c;
	Async *ap = q->ptr;
	int state = ap->state;

	while(bp->wptr > bp->rptr){
		c = *bp->rptr++;
		switch(state) {
		case Hunt:	/* wait for framing byte */
			if(c == FRAME)
				state = Framing;
			break;
	
		case Framing:	/* saw 1 framing byte after Hunt */
			if(c == FRAME)
				state = Framed;
			else
				state = Hunt;
			break;
	
		case Framed:	/* saw 2 or more framing bytes */
			if(c == FRAME)
				break;
			state = Data;
			ap->icrc = CRCSTART;
			ap->icount = 0;
			goto Datachar;
	
		case Data:	/* mid-frame */
			if(c == FRAME) {
				state = Escape;
				break;
			}
		Datachar:
			if(ap->icount >= MAXFRAME) {
				DPRINT("a%d pkt too long\n", ap-async);
				ap->toolong++;
				state = Hunt;
				break;
			}
			ap->icrc = CRCFUNC(ap->icrc, c);
			ap->buf[ap->icount++] = c;
			break;
	
		case Escape:	/* saw framing byte in Data */
			switch (c) {
			case FRAME:
				if(asyncdebug > 2)
					showframe("in", ap, ap->buf, ap->icount);
				if(ap->icount < 5) {
					DPRINT("a%d pkt too short\n", ap-async);
					ap->tooshort++;
				} else if(ap->icrc != 0) {
					DPRINT("a%d bad crc\n", ap-async);
					ap->badcrc++;
				} else {
					asdeliver(q, ap);
				}
				state = Framed;
				break;
			case 0:
				c = FRAME;
				state = Data;
				goto Datachar;
			default:
				DPRINT("a%d bad escape\n", ap-async);
				ap->badescape++;
				state = Hunt;
				break;
			}
			break;
		}
	}
	ap->state = state;
	freeb(bp);
}
.
## diffname port/stasync.c 1990/11151
## diff -e /n/bootesdump/1990/1009/sys/src/9/mips/stasync.c /n/bootesdump/1990/11151/sys/src/9/mips/stasync.c
62c
Qinfo asyncinfo =
{
	asynciput,
	asyncoput,
	asyncopen,
	asyncclose,
	"async",
	asyncreset
};
.
## diffname port/stasync.c 1990/11211
## diff -e /n/bootesdump/1990/11151/sys/src/9/mips/stasync.c /n/bootesdump/1990/11211/sys/src/9/mips/stasync.c
115c
		error(Enoasync);
.
## diffname port/stasync.c 1991/0217
## diff -e /n/bootesdump/1990/1210/sys/src/9/mips/stasync.c /n/bootesdump/1991/0217/sys/src/9/port/stasync.c
249a
		if(streamparse("debug", bp))
			asyncdebug = 3;
.
72c
int asyncdebug = 3;
.
## diffname port/stasync.c 1991/0223
## diff -e /n/bootesdump/1991/0217/sys/src/9/port/stasync.c /n/bootesdump/1991/0223/sys/src/9/port/stasync.c
325c
			asputf(ap);
.
284c
		asputf(ap);
.
231c
		asputf(ap);
.
218,219d
198,201c
	*p++ = FRAME;
	*p++ = FRAME;
.
181c
asputf(Async *ap)
.
## diffname port/stasync.c 1991/0423
## diff -e /n/bootesdump/1991/0223/sys/src/9/port/stasync.c /n/bootesdump/1991/0423/sys/src/9/port/stasync.c
437a
					if(asyncdebug && asyncdebug<=2)
						showframe("badin", ap, ap->buf, ap->icount);
.
434a
					if(asyncdebug && asyncdebug<=2)
						showframe("shortin", ap, ap->buf, ap->icount);
.
323a
	if(debugcount > 0 && --debugcount == 0)
		asyncdebug = 1;
.
282a
	if(asyncdebug > 1)
		kprint("a%d->(%d)%3.3uo %d\n",
			ap-async, chan, ctl, bp->wptr-bp->rptr);

.
71a
static int	debugcount = 6;
.
## diffname port/stasync.c 1991/0428
## diff -e /n/bootesdump/1991/0423/sys/src/9/port/stasync.c /n/bootesdump/1991/0428/sys/src/9/port/stasync.c
77c
#include "../port/crc_16.h"
.
## diffname port/stasync.c 1991/0926
## diff -e /n/bootesdump/1991/0428/sys/src/9/port/stasync.c /n/bootesdump/1991/0926/sys/src/9/port/stasync.c
332a
	poperror();
.
331a
	freeb(msg);
.
300,311d
291,294c
	for(bp = msg; bp; bp = bp->next){
.
273,275d
271c
		freeb(msg);
		nexterror();
.
263,269c
	if(waserror()){
.
259,261d
257a
	}
	chan = msg->rptr[0] | (msg->rptr[1]<<8);
	ctl = msg->rptr[2];
	msg->rptr += 3;
.
256c
	msg = pullup(bp, 3);
	if(BLEN(msg) < 3){
		print("asyncoput msglen < 3\n");
		freeb(bp);
.
254c
	 *  each datakit message has a 2 byte channel number followed by
	 *  one control byte
.
244a
	Block *msg;
.
## diffname port/stasync.c 1992/0111
## diff -e /n/bootesdump/1991/0926/sys/src/9/port/stasync.c /n/bootesdump/1992/0111/sys/src/9/port/stasync.c
6c
#include	"../port/error.h"
.
## diffname port/stasync.c 1992/0114
## diff -e /n/bootesdump/1992/0111/sys/src/9/port/stasync.c /n/bootesdump/1992/0114/sys/src/9/port/stasync.c
116c
		exhausted("async stream modules");
.
## diffname port/stasync.c 1992/0305
## diff -e /n/bootesdump/1992/0114/sys/src/9/port/stasync.c /n/bootesdump/1992/0305/sys/src/9/port/stasync.c
176,177c
	FLOWCTL(ap->wq, ap->bp);
.
## diffname port/stasync.c 1992/0321
## diff -e /n/bootesdump/1992/0305/sys/src/9/port/stasync.c /n/bootesdump/1992/0321/sys/src/9/port/stasync.c
2c
#include	"../port/lib.h"
.
## diffname port/stasync.c 1992/0622
## diff -e /n/bootesdump/1992/0321/sys/src/9/port/stasync.c /n/bootesdump/1992/0622/sys/src/9/port/stasync.c
96c
	async = (Async *)xalloc(conf.nasync*sizeof(Async));
.
42d
35d
27d
18c
enum
{
	Hunt,
	Framing,
	Framed,
	Data,
	Escape
};
.
## diffname port/stasync.c 1992/0623
## diff -e /n/bootesdump/1992/0622/sys/src/9/port/stasync.c /n/bootesdump/1992/0623/sys/src/9/port/stasync.c
448c
				DPRINT("a%d bad escape\n", ap->id);
.
434c
					DPRINT("a%d bad crc\n", ap->id);
.
429c
					DPRINT("a%d pkt too short\n", ap->id);
.
414c
				DPRINT("a%d pkt too long\n", ap->id);
.
371c
				ap->id, chan, bp->rptr[2],
.
358c
						ap->id, chan, bp->rptr[2],
.
339c
		DPRINT("a%d deliver chan 0\n", ap->id);
.
287c
			ap->id, chan, ctl, bp->wptr-bp->rptr);
.
169c
	kprint("a%d %s [", ap->id, t);
.
144c
	DPRINT("asyncstclose %d\n", ap->id);
.
119,120c
	if(ap == 0){
		ap = smalloc(sizeof(Async));
		qlock(ap);
		lock(&asyncalloc);
		ap->list = asyncalloc.async;
		asyncalloc.async = ap;
		ap->id = nasync++;
		unlock(&asyncalloc);
	}
.
113c
	for(ap = asyncalloc.async; ap; ap = ap->list){
.
100d
57a
/* list of allocated async structures (never freed) */
struct
{
	Lock;
	Async *async;
} asyncalloc;

.
56c
int nasync;
.
54c
};
.
28a
	Async	*list;
	int	id;
.
27c
typedef struct Async Async;
struct Async
{
.
## diffname port/stasync.c 1992/0725
## diff -e /n/bootesdump/1992/0623/sys/src/9/port/stasync.c /n/bootesdump/1992/0725/sys/src/9/port/stasync.c
88c
int asyncdebug;
.
## diffname port/stasync.c 1992/0917
## diff -e /n/bootesdump/1992/0725/sys/src/9/port/stasync.c /n/bootesdump/1992/0917/sys/src/9/port/stasync.c
270c
			freeb(bp);
		} else {
			PUTNEXT(q, bp);
		}
.
268c
		if(streamparse("debug", bp)){
.
## diffname port/stasync.c 1992/1219
## diff -e /n/bootesdump/1992/0917/sys/src/9/port/stasync.c /n/bootesdump/1992/1219/sys/src/9/port/stasync.c
284d
282c
	if(msg == 0){
.
## diffname port/stasync.c 1993/0418
## diff -e /n/bootesdump/1992/1219/sys/src/9/port/stasync.c /n/bootesdump/1993/0418/sys/src/9/port/stasync.c
198a
	ap->count = 0;
.
## diffname port/stasync.c 1993/0501
## diff -e /n/bootesdump/1993/0418/sys/src/9/port/stasync.c /n/fornaxdump/1993/0501/sys/src/brazil/port/stasync.c
199d
## diffname port/stasync.c 1993/0804 # deleted
## diff -e /n/fornaxdump/1993/0501/sys/src/brazil/port/stasync.c /n/fornaxdump/1993/0804/sys/src/brazil/port/stasync.c
1,477d

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.