## 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
|