plan 9 kernel history: overview | file list | diff list

gnot/stasync.c (diff list | history)

1990/0905/sys/src/9/gnot/stasync.c:7,241990/0911/sys/src/9/gnot/stasync.c:7,47 (short | long)
1990/0905    
 
#define DPRINT 	if(asyncdebug)kprint 
 
1990/0911    
/* 
 *  configuration 
 */ 
enum { 
	MAXFRAME=	246, 
	Nasync=		1, 
}; 
 
/* input states */ 
enum { Hunt=0, Framing, Framed, Data, Escape }; 
 
1990/0905    
typedef struct Async { 
	QLock; 
 
	int	inuse; 
1990/0911    
	Queue	*wq; 
 
	/* output state */ 
 
1990/0905    
	QLock	xmit;		/* transmit lock */ 
	int	chan;		/* current urp channel */ 
	Block	*bp;		/* current buffer */ 
1990/0911    
	Block	*bp;		/* current output buffer */ 
1990/0905    
	int	count; 
	ushort	crc; 
 
1990/0911    
	/* input state */ 
 
	int	state;		/* input state */ 
	uchar	buf[MAXFRAME];	/* current input buffer */ 
	int	icount; 
	ushort	icrc; 
 
1990/0905    
	/* statistics */ 
 
1990/0911    
	ulong	chan0; 
1990/0905    
	ulong	toolong; 
	ulong	tooshort; 
	ulong	badcrc; 
1990/0905/sys/src/9/gnot/stasync.c:27,331990/0911/sys/src/9/gnot/stasync.c:50,56
1990/0905    
	ulong	out;		/* bytes out */ 
} Async; 
 
Async async[Nasync]; 
1990/0911    
Async *async; 
1990/0905    
 
/* 
 *  async stream module definition 
1990/0905/sys/src/9/gnot/stasync.c:36,421990/0911/sys/src/9/gnot/stasync.c:59,66
1990/0905    
static void asyncoput(Queue*, Block*); 
static void asyncopen(Queue*, Stream*); 
static void asyncclose(Queue*); 
Qinfo asyncinfo = { asynciput, asyncoput, asyncopen, asyncclose, "async" }; 
1990/0911    
static void asyncreset(void); 
Qinfo asyncinfo = { asynciput, asyncoput, asyncopen, asyncclose, "async", asyncreset }; 
1990/0905    
 
int asyncdebug = 1; 
int asyncerror; 
1990/0905/sys/src/9/gnot/stasync.c:49,551990/0911/sys/src/9/gnot/stasync.c:73,78
1990/0905    
#define	BOTM	0051		/* begin trailer, more data follows */ 
#define	BOTS	0052		/* seq update alg. on this trailer */ 
 
#define	MAXFRAME	256 
#define	FRAME		0x7e 
#define	STUF		0x9d 
 
1990/0905/sys/src/9/gnot/stasync.c:57,691990/0911/sys/src/9/gnot/stasync.c:80,103
1990/0905    
#define	CRCFUNC(crc,x)	(crc_table[((crc)^(x))&0xff]^((crc)>>8)) 
 
/* 
 *  create the kernel process for input 
1990/0911    
 *  create the async structures 
1990/0905    
 */ 
static void 
1990/0911    
asyncreset(void) 
{ 
	async = (Async *)ialloc(conf.nasync*sizeof(Async), 0); 
} 
 
/* 
 *  allocate an async structure 
 */ 
static void 
1990/0905    
asyncopen(Queue *q, Stream *s) 
{ 
	DPRINT("asyncstopen %d\n", s->dev); 
1990/0911    
	Async *ap; 
1990/0905    
 
1990/0911    
	DPRINT("asyncopen %d\n", s->dev); 
 
1990/0905    
	for(ap = async; ap < &async[Nasync]; ap++){ 
		qlock(ap); 
		if(ap->inuse == 0) 
1990/0905/sys/src/9/gnot/stasync.c:74,801990/0911/sys/src/9/gnot/stasync.c:108,114
1990/0905    
		error(0, Enoasync); 
	q->ptr = q->other->ptr = ap; 
 
	ap->bp = allocb(256); 
1990/0911    
	ap->bp = 0; 
1990/0905    
	ap->chan = -1; 
	ap->count = 0; 
	ap->toolong = 0; 
1990/0905/sys/src/9/gnot/stasync.c:84,891990/0911/sys/src/9/gnot/stasync.c:118,125
1990/0905    
	ap->chan0 = 0; 
	ap->in = 0; 
	ap->out = 0; 
1990/0911    
	ap->wq = WR(q); 
	ap->state = Hunt; 
1990/0905    
} 
 
static void 
1990/0905/sys/src/9/gnot/stasync.c:125,1611990/0911/sys/src/9/gnot/stasync.c:161,196
1990/0905    
void 
aswrite(Async *ap) 
{ 
	int n = ap->bp - ap->buf; 
	if (n <= 0) 
1990/0911    
	if(ap->bp->rptr == ap->bp->wptr) 
1990/0905    
		return; 
	if (asyncdebug > 2) 
		showframe("out", ap, ap->buf, n); 
	(*devtab[ap->c->type].write)(ap->c, ap->buf, n); 
	ap->out += n; 
	ap->bp = ap->buf; 
1990/0911    
	FLOWCTL(ap->wq); 
	PUTNEXT(ap->wq, ap->bp); 
	ap->bp = 0; 
1990/0905    
} 
 
void 
asputf(Async *ap, int frame) 
{ 
	uchar *p = ap->bp; 
1990/0911    
	uchar *p; 
1990/0905    
	int c; 
	if (ap->count > 0) { 
		if (asyncerror) 
1990/0911    
 
	p = ap->bp->wptr; 
	if(ap->count > 0) { 
		if(asyncerror) 
1990/0905    
			ap->crc^=1, asyncerror=0; 
		*p++ = c = ap->crc&0xff; 
		if (c == FRAME) 
1990/0911    
		if(c == FRAME) 
1990/0905    
			*p++ = 0x00; 
		*p++ = c = (ap->crc>>8)&0xff; 
		if (c == FRAME) 
1990/0911    
		if(c == FRAME) 
1990/0905    
			*p++ = 0x00; 
		ap->count = 0; 
	} 
	if (frame) { 
1990/0911    
	if(frame) { 
1990/0905    
		*p++ = FRAME; 
		*p++ = FRAME; 
	} 
	ap->bp = p; 
1990/0911    
	ap->bp->wptr = p; 
1990/0905    
	aswrite(ap); 
} 
 
1990/0905/sys/src/9/gnot/stasync.c:163,1701990/0911/sys/src/9/gnot/stasync.c:198,209
1990/0905    
asputc(Async *ap, int c) 
{ 
	int d; 
	uchar *p = ap->bp; 
	if (ap->count <= 0) { 
1990/0911    
	uchar *p; 
 
	if(ap->bp == 0) 
		ap->bp = allocb(MAXFRAME+4); 
	p = ap->bp->wptr; 
	if(ap->count <= 0) { 
1990/0905    
		*p++ = FRAME; 
		*p++ = FRAME; 
		*p++ = d = 0x80|((ap->chan>>5)&0x7e); 
1990/0905/sys/src/9/gnot/stasync.c:173,1851990/0911/sys/src/9/gnot/stasync.c:212,224
1990/0905    
		ap->crc = CRCFUNC(ap->crc, d); 
	} 
	*p++ = c; 
	if (c == FRAME) 
1990/0911    
	if(c == FRAME) 
1990/0905    
		*p++ = 0x00; 
	ap->crc = CRCFUNC(ap->crc, c); 
	ap->bp = p; 
	if (++ap->count >= MAXFRAME-4) 
1990/0911    
	ap->bp->wptr = p; 
	if(++ap->count >= MAXFRAME-4) 
1990/0905    
		asputf(ap, 0); 
	else if (p-ap->buf >= sizeof(ap->buf)-8) 
1990/0911    
	else if(ap->bp->lim - p < 8) 
1990/0905    
		aswrite(ap); 
} 
 
1990/0905/sys/src/9/gnot/stasync.c:228,2381990/0911/sys/src/9/gnot/stasync.c:267,277
1990/0905    
	/* 
	 *  new frame if the channel number has changed 
	 */ 
	if (chan != ap->chan && ap->count > 0) 
1990/0911    
	if(chan != ap->chan && ap->count > 0) 
1990/0905    
		asputf(ap, 0); 
	ap->chan = chan; 
 
	if (asyncdebug > 1) 
1990/0911    
	if(asyncdebug > 1) 
1990/0905    
		kprint("a%d->(%d)%3.3uo %d\n", 
			ap-async, chan, ctl, bp->wptr - bp->rptr); 
 
1990/0905/sys/src/9/gnot/stasync.c:245,2511990/0911/sys/src/9/gnot/stasync.c:284,290
1990/0905    
		 */ 
		while (bp->rptr < bp->wptr) { 
			asputc(ap, c = *bp->rptr++); 
			if (c == STUF) 
1990/0911    
			if(c == STUF) 
1990/0905    
				asputc(ap, 0); 
		} 
 
1990/0905/sys/src/9/gnot/stasync.c:287,3091990/0911/sys/src/9/gnot/stasync.c:326,347
1990/0905    
 */ 
 
void 
asdeliver(Async *ap, uchar *p, int n) 
1990/0911    
asdeliver(Queue *q, Async *ap) 
1990/0905    
{ 
	Block *bp = 0; 
	int chan, c; 
1990/0911    
	Block *bp; 
	uchar *p = ap->buf; 
	int n = ap->icount; 
1990/0905    
 
	if (!ap->rq) 
		return; 
                 
	chan = *p++ & 0x7e; 
	chan = (chan<<5)|((*p++ & 0x7e)>>1); 
	if (chan==0) { 
1990/0911    
	chan = p[1] & 0x7e; 
	chan = (chan<<5)|((p[2] & 0x7e)>>1); 
	if(chan==0) { 
1990/0905    
		DPRINT("a%d deliver chan 0\n", ap-async); 
		ap->chan0++; 
		return; 
	} 
	for (n-=4; n>0; n--) { 
		if (!bp) { 
1990/0911    
		if(!bp) { 
1990/0905    
			bp = allocb(n+2); 
			bp->flags |= S_DELIM; 
			bp->wptr[0] = chan; 
1990/0905/sys/src/9/gnot/stasync.c:311,3251990/0911/sys/src/9/gnot/stasync.c:349,363
1990/0905    
			bp->wptr[2] = 0; 
			bp->wptr += 3; 
		} 
		if ((c = *p++) == STUF) { 
1990/0911    
		if((c = *p++) == STUF) { 
1990/0905    
			--n; 
			if ((c = *p++) != 0) { 
1990/0911    
			if((c = *p++) != 0) { 
1990/0905    
				bp->rptr[2] = c; 
				if (asyncdebug > 1) 
1990/0911    
				if(asyncdebug > 1) 
1990/0905    
					kprint("a%d<-(%d)%3.3uo %d\n", 
						ap-async, chan, bp->rptr[2], 
						bp->wptr - bp->rptr - 3); 
				PUTNEXT(ap->rq, bp); 
1990/0911    
				PUTNEXT(q, bp); 
1990/0905    
				bp = 0; 
				continue; 
			} else 
1990/0905/sys/src/9/gnot/stasync.c:327,4321990/0911/sys/src/9/gnot/stasync.c:365,454
1990/0905    
		} 
		*bp->wptr++ = c; 
	} 
	if (bp) { 
		if (asyncdebug > 1) 
1990/0911    
	if(bp) { 
		if(asyncdebug > 1) 
1990/0905    
			kprint("a%d<-(%d)%3.3uo %d\n", 
				ap-async, chan, bp->rptr[2], 
				bp->wptr - bp->rptr - 3); 
		PUTNEXT(ap->rq, bp); 
1990/0911    
		PUTNEXT(q, bp); 
1990/0905    
	} 
} 
 
enum { Hunt=0, Framing, Framed, Data, Escape }; 
                 
static void 
asynckproc(void *arg) 
1990/0911    
asynciput(Queue *q, Block *bp) 
1990/0905    
{ 
	Async *ap = (Async *)arg; 
	int c, state, count; unsigned short crc; 
	uchar buf[MAXFRAME], ibuf[MAXFRAME], *p; 
	int nibuf; 
1990/0911    
	int c; 
	Async *ap = q->ptr; 
	int state = ap->state; 
1990/0905    
 
	DPRINT("asynckproc %d\n", ap-async); 
	nibuf = 0; 
	state = Hunt; 
Loop: 
	if (--nibuf < 0) { 
		if (ap->rq) 
			nibuf = (*devtab[ap->c->type].read)(ap->c, 
					ibuf, sizeof ibuf); 
		if (nibuf <= 0) { 
			unlock(&ap->kstart); 
			wakeup(&ap->r); 
			return; 
		} 
		ap->in += nibuf--; 
		p = ibuf; 
	} 
	c = *p++; 
	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) 
1990/0911    
	while(bp->wptr > bp->rptr){ 
		c = *bp->rptr++; 
		switch(state) { 
		case Hunt:	/* wait for framing byte */ 
			if(c == FRAME) 
				state = Framing; 
1990/0905    
			break; 
		state = Data; 
		crc = CRCSTART; 
		count = 0; 
		goto Datachar; 
                 
	case Data:	/* mid-frame */ 
		if (c == FRAME) { 
			state = Escape; 
1990/0911    
	 
		case Framing:	/* saw 1 framing byte after Hunt */ 
			if(c == FRAME) 
				state = Framed; 
			else 
				state = Hunt; 
1990/0905    
			break; 
		} 
	Datachar: 
		if (count >= MAXFRAME) { 
			DPRINT("a%d pkt too long\n", ap-async); 
			ap->toolong++; 
			state = Hunt; 
			break; 
		} 
		crc = CRCFUNC(crc, c); 
		buf[count++] = c; 
		break; 
                 
	case Escape:	/* saw framing byte in Data */ 
		switch (c) { 
		case FRAME: 
			if (asyncdebug > 2) 
				showframe("in", ap, buf, count); 
			if (count < 5) { 
				DPRINT("a%d pkt too short\n", ap-async); 
				ap->tooshort++; 
			} else if (crc != 0) { 
				DPRINT("a%d bad crc\n", ap-async); 
				ap->badcrc++; 
			} else { 
				asdeliver(ap, buf, count); 
			} 
			state = Framed; 
			break; 
		case 0: 
			c = FRAME; 
1990/0911    
	 
		case Framed:	/* saw 2 or more framing bytes */ 
			if(c == FRAME) 
				break; 
1990/0905    
			state = Data; 
1990/0911    
			ap->icrc = CRCSTART; 
			ap->icount = 0; 
1990/0905    
			goto Datachar; 
		default: 
			DPRINT("a%d bad escape\n", ap-async); 
			ap->badescape++; 
			state = Hunt; 
1990/0911    
	 
		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; 
1990/0905    
			break; 
1990/0911    
	 
		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; 
1990/0905    
		} 
		break; 
	} 
	goto Loop; 
1990/0911    
	ap->state = state; 
	freeb(bp); 
1990/0905    
} 
1990/0911/sys/src/9/gnot/stasync.c:11,181990/0914/sys/src/9/gnot/stasync.c:11,17 (short | long)
1990/0911    
 *  configuration 
 */ 
enum { 
	MAXFRAME=	246, 
	Nasync=		1, 
1990/0914    
	MAXFRAME=	256,	/* also known to tsm8 code */ 
1990/0911    
}; 
 
/* input states */ 
1990/0911/sys/src/9/gnot/stasync.c:98,1131990/0914/sys/src/9/gnot/stasync.c:97,113
1990/0905    
 
1990/0911    
	DPRINT("asyncopen %d\n", s->dev); 
 
1990/0905    
	for(ap = async; ap < &async[Nasync]; ap++){ 
1990/0914    
	for(ap = async; ap < &async[conf.nasync]; ap++){ 
1990/0905    
		qlock(ap); 
		if(ap->inuse == 0) 
			break; 
		qunlock(ap); 
	} 
	if(ap == &async[Nasync]) 
1990/0914    
	if(ap == &async[conf.nasync]) 
1990/0905    
		error(0, Enoasync); 
	q->ptr = q->other->ptr = ap; 
 
1990/0914    
	ap->inuse = 1; 
1990/0911    
	ap->bp = 0; 
1990/0905    
	ap->chan = -1; 
	ap->count = 0; 
1990/0911/sys/src/9/gnot/stasync.c:120,1251990/0914/sys/src/9/gnot/stasync.c:120,126
1990/0905    
	ap->out = 0; 
1990/0911    
	ap->wq = WR(q); 
	ap->state = Hunt; 
1990/0914    
	qunlock(ap); 
1990/0905    
} 
 
static void 
1990/0911/sys/src/9/gnot/stasync.c:329,3401990/0914/sys/src/9/gnot/stasync.c:330,341
1990/0911    
asdeliver(Queue *q, Async *ap) 
1990/0905    
{ 
	int chan, c; 
1990/0911    
	Block *bp; 
1990/0914    
	Block *bp = 0; 
1990/0911    
	uchar *p = ap->buf; 
	int n = ap->icount; 
1990/0905    
 
1990/0911    
	chan = p[1] & 0x7e; 
	chan = (chan<<5)|((p[2] & 0x7e)>>1); 
1990/0914    
	chan = *p++ & 0x7e; 
	chan = (chan<<5)|((*p++ & 0x7e)>>1); 
1990/0911    
	if(chan==0) { 
1990/0905    
		DPRINT("a%d deliver chan 0\n", ap-async); 
		ap->chan0++; 
1990/0914/sys/src/9/gnot/stasync.c:61,671990/09141/sys/src/9/gnot/stasync.c:61,67 (short | long)
1990/0911    
static void asyncreset(void); 
Qinfo asyncinfo = { asynciput, asyncoput, asyncopen, asyncclose, "async", asyncreset }; 
1990/0905    
 
int asyncdebug = 1; 
1990/09141    
int asyncdebug = 10; 
1990/0905    
int asyncerror; 
 
static ushort crc_table[256] = { 
1990/09141/sys/src/9/gnot/stasync.c:192,1971990/0920/sys/src/9/gnot/stasync.c:192,199 (short | long)
1990/0905    
		*p++ = FRAME; 
	} 
1990/0911    
	ap->bp->wptr = p; 
1990/0920    
	if(asyncdebug > 2) 
		showframe("out", ap, ap->bp->rptr, BLEN(ap->bp)); 
1990/0905    
	aswrite(ap); 
} 
 
1990/09141/sys/src/9/gnot/stasync.c:271,2801990/0920/sys/src/9/gnot/stasync.c:273,278
1990/0911    
	if(chan != ap->chan && ap->count > 0) 
1990/0905    
		asputf(ap, 0); 
	ap->chan = chan; 
                 
1990/0911    
	if(asyncdebug > 1) 
1990/0905    
		kprint("a%d->(%d)%3.3uo %d\n", 
			ap-async, chan, ctl, bp->wptr - bp->rptr); 
 
	/* 
	 *  send the 8 bit data 
1990/0920/sys/src/9/gnot/stasync.c:61,671990/1009/sys/src/9/gnot/stasync.c:61,67 (short | long)
1990/0911    
static void asyncreset(void); 
Qinfo asyncinfo = { asynciput, asyncoput, asyncopen, asyncclose, "async", asyncreset }; 
1990/0905    
 
1990/09141    
int asyncdebug = 10; 
1990/1009    
int asyncdebug = 0; 
1990/0905    
int asyncerror; 
 
static ushort crc_table[256] = { 
1990/1009/sys/src/9/gnot/stasync.c:59,651990/11151/sys/src/9/gnot/stasync.c:59,73 (short | long)
1990/0905    
static void asyncopen(Queue*, Stream*); 
static void asyncclose(Queue*); 
1990/0911    
static void asyncreset(void); 
Qinfo asyncinfo = { asynciput, asyncoput, asyncopen, asyncclose, "async", asyncreset }; 
1990/11151    
Qinfo asyncinfo = 
{ 
	asynciput, 
	asyncoput, 
	asyncopen, 
	asyncclose, 
	"async", 
	asyncreset 
}; 
1990/0905    
 
1990/1009    
int asyncdebug = 0; 
1990/0905    
int asyncerror; 
1990/11151/sys/src/9/gnot/stasync.c:112,1181990/11211/sys/src/9/gnot/stasync.c:112,118 (short | long)
1990/0905    
		qunlock(ap); 
	} 
1990/0914    
	if(ap == &async[conf.nasync]) 
1990/0905    
		error(0, Enoasync); 
1990/11211    
		error(Enoasync); 
1990/0905    
	q->ptr = q->other->ptr = ap; 
 
1990/0914    
	ap->inuse = 1; 
1990/11211/sys/src/9/gnot/stasync.c:1,4611990/1210/sys/src/9/gnot/stasync.c:0 (short | long)
Deleted.
rsc Mon Mar 7 10:21:54 2005
1990/0905    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"errno.h" 
                 
#define DPRINT 	if(asyncdebug)kprint 
                 
1990/0911    
/* 
 *  configuration 
 */ 
enum { 
1990/0914    
	MAXFRAME=	256,	/* also known to tsm8 code */ 
1990/0911    
}; 
                 
/* input states */ 
enum { Hunt=0, Framing, Framed, Data, Escape }; 
                 
1990/0905    
typedef struct Async { 
	QLock; 
                 
	int	inuse; 
1990/0911    
	Queue	*wq; 
                 
	/* output state */ 
                 
1990/0905    
	QLock	xmit;		/* transmit lock */ 
	int	chan;		/* current urp channel */ 
1990/0911    
	Block	*bp;		/* current output buffer */ 
1990/0905    
	int	count; 
	ushort	crc; 
                 
1990/0911    
	/* input state */ 
                 
	int	state;		/* input state */ 
	uchar	buf[MAXFRAME];	/* current input buffer */ 
	int	icount; 
	ushort	icrc; 
                 
1990/0905    
	/* statistics */ 
                 
1990/0911    
	ulong	chan0; 
1990/0905    
	ulong	toolong; 
	ulong	tooshort; 
	ulong	badcrc; 
	ulong	badescape; 
	ulong	in;		/* bytes in */ 
	ulong	out;		/* bytes out */ 
} Async; 
                 
1990/0911    
Async *async; 
1990/0905    
                 
/* 
 *  async stream module definition 
 */ 
static void asynciput(Queue*, Block*); 
static void asyncoput(Queue*, Block*); 
static void asyncopen(Queue*, Stream*); 
static void asyncclose(Queue*); 
1990/0911    
static void asyncreset(void); 
1990/11151    
Qinfo asyncinfo = 
{ 
	asynciput, 
	asyncoput, 
	asyncopen, 
	asyncclose, 
	"async", 
	asyncreset 
}; 
1990/0905    
                 
1990/1009    
int asyncdebug = 0; 
1990/0905    
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)) 
                 
/* 
1990/0911    
 *  create the async structures 
1990/0905    
 */ 
static void 
1990/0911    
asyncreset(void) 
{ 
	async = (Async *)ialloc(conf.nasync*sizeof(Async), 0); 
} 
                 
/* 
 *  allocate an async structure 
 */ 
static void 
1990/0905    
asyncopen(Queue *q, Stream *s) 
{ 
1990/0911    
	Async *ap; 
1990/0905    
                 
1990/0911    
	DPRINT("asyncopen %d\n", s->dev); 
                 
1990/0914    
	for(ap = async; ap < &async[conf.nasync]; ap++){ 
1990/0905    
		qlock(ap); 
		if(ap->inuse == 0) 
			break; 
		qunlock(ap); 
	} 
1990/0914    
	if(ap == &async[conf.nasync]) 
1990/11211    
		error(Enoasync); 
1990/0905    
	q->ptr = q->other->ptr = ap; 
                 
1990/0914    
	ap->inuse = 1; 
1990/0911    
	ap->bp = 0; 
1990/0905    
	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; 
1990/0911    
	ap->wq = WR(q); 
	ap->state = Hunt; 
1990/0914    
	qunlock(ap); 
1990/0905    
} 
                 
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) 
{ 
1990/0911    
	if(ap->bp->rptr == ap->bp->wptr) 
1990/0905    
		return; 
1990/0911    
	FLOWCTL(ap->wq); 
	PUTNEXT(ap->wq, ap->bp); 
	ap->bp = 0; 
1990/0905    
} 
                 
void 
asputf(Async *ap, int frame) 
{ 
1990/0911    
	uchar *p; 
1990/0905    
	int c; 
1990/0911    
                 
	p = ap->bp->wptr; 
	if(ap->count > 0) { 
		if(asyncerror) 
1990/0905    
			ap->crc^=1, asyncerror=0; 
		*p++ = c = ap->crc&0xff; 
1990/0911    
		if(c == FRAME) 
1990/0905    
			*p++ = 0x00; 
		*p++ = c = (ap->crc>>8)&0xff; 
1990/0911    
		if(c == FRAME) 
1990/0905    
			*p++ = 0x00; 
		ap->count = 0; 
	} 
1990/0911    
	if(frame) { 
1990/0905    
		*p++ = FRAME; 
		*p++ = FRAME; 
	} 
1990/0911    
	ap->bp->wptr = p; 
1990/0920    
	if(asyncdebug > 2) 
		showframe("out", ap, ap->bp->rptr, BLEN(ap->bp)); 
1990/0905    
	aswrite(ap); 
} 
                 
void 
asputc(Async *ap, int c) 
{ 
	int d; 
1990/0911    
	uchar *p; 
                 
	if(ap->bp == 0) 
		ap->bp = allocb(MAXFRAME+4); 
	p = ap->bp->wptr; 
	if(ap->count <= 0) { 
1990/0905    
		*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; 
1990/0911    
	if(c == FRAME) 
1990/0905    
		*p++ = 0x00; 
	ap->crc = CRCFUNC(ap->crc, c); 
1990/0911    
	ap->bp->wptr = p; 
	if(++ap->count >= MAXFRAME-4) 
1990/0905    
		asputf(ap, 0); 
1990/0911    
	else if(ap->bp->lim - p < 8) 
1990/0905    
		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 
	 */ 
1990/0911    
	if(chan != ap->chan && ap->count > 0) 
1990/0905    
		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++); 
1990/0911    
			if(c == STUF) 
1990/0905    
				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 
1990/0911    
asdeliver(Queue *q, Async *ap) 
1990/0905    
{ 
	int chan, c; 
1990/0914    
	Block *bp = 0; 
1990/0911    
	uchar *p = ap->buf; 
	int n = ap->icount; 
1990/0905    
                 
1990/0914    
	chan = *p++ & 0x7e; 
	chan = (chan<<5)|((*p++ & 0x7e)>>1); 
1990/0911    
	if(chan==0) { 
1990/0905    
		DPRINT("a%d deliver chan 0\n", ap-async); 
		ap->chan0++; 
		return; 
	} 
	for (n-=4; n>0; n--) { 
1990/0911    
		if(!bp) { 
1990/0905    
			bp = allocb(n+2); 
			bp->flags |= S_DELIM; 
			bp->wptr[0] = chan; 
			bp->wptr[1] = chan>>8; 
			bp->wptr[2] = 0; 
			bp->wptr += 3; 
		} 
1990/0911    
		if((c = *p++) == STUF) { 
1990/0905    
			--n; 
1990/0911    
			if((c = *p++) != 0) { 
1990/0905    
				bp->rptr[2] = c; 
1990/0911    
				if(asyncdebug > 1) 
1990/0905    
					kprint("a%d<-(%d)%3.3uo %d\n", 
						ap-async, chan, bp->rptr[2], 
						bp->wptr - bp->rptr - 3); 
1990/0911    
				PUTNEXT(q, bp); 
1990/0905    
				bp = 0; 
				continue; 
			} else 
				c = STUF; 
		} 
		*bp->wptr++ = c; 
	} 
1990/0911    
	if(bp) { 
		if(asyncdebug > 1) 
1990/0905    
			kprint("a%d<-(%d)%3.3uo %d\n", 
				ap-async, chan, bp->rptr[2], 
				bp->wptr - bp->rptr - 3); 
1990/0911    
		PUTNEXT(q, bp); 
1990/0905    
	} 
} 
                 
static void 
1990/0911    
asynciput(Queue *q, Block *bp) 
1990/0905    
{ 
1990/0911    
	int c; 
	Async *ap = q->ptr; 
	int state = ap->state; 
1990/0905    
                 
1990/0911    
	while(bp->wptr > bp->rptr){ 
		c = *bp->rptr++; 
		switch(state) { 
		case Hunt:	/* wait for framing byte */ 
			if(c == FRAME) 
				state = Framing; 
1990/0905    
			break; 
1990/0911    
	                 
		case Framing:	/* saw 1 framing byte after Hunt */ 
			if(c == FRAME) 
				state = Framed; 
			else 
				state = Hunt; 
1990/0905    
			break; 
1990/0911    
	                 
		case Framed:	/* saw 2 or more framing bytes */ 
			if(c == FRAME) 
				break; 
1990/0905    
			state = Data; 
1990/0911    
			ap->icrc = CRCSTART; 
			ap->icount = 0; 
1990/0905    
			goto Datachar; 
1990/0911    
	                 
		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; 
1990/0905    
			break; 
1990/0911    
	                 
		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; 
1990/0905    
		} 
	} 
1990/0911    
	ap->state = state; 
	freeb(bp); 
1990/0905    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)