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

1990/0911/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 | prev | next)
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    
} 


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