|
|
1.1 root 1: #include "u.h"
2: #include "../port/lib.h"
3: #include "mem.h"
4: #include "dat.h"
5: #include "fns.h"
6: #include "../port/error.h"
7:
8: #define DPRINT if(asyncdebug)kprint
9:
10: /*
11: * configuration
12: */
13: enum {
14: MAXFRAME= 256, /* also known to tsm8 code */
15: };
16:
17: /* input states */
18: enum
19: {
20: Hunt,
21: Framing,
22: Framed,
23: Data,
24: Escape
25: };
26:
27: typedef struct Async Async;
28: struct Async
29: {
30: QLock;
31: Async *list;
32: int id;
33:
34: int inuse;
35: Queue *wq;
36:
37: /* output state */
38: QLock xmit; /* transmit lock */
39: int chan; /* current urp channel */
40: Block *bp; /* current output buffer */
41: int count;
42: ushort crc;
43:
44: /* input state */
45: int state; /* input state */
46: uchar buf[MAXFRAME]; /* current input buffer */
47: int icount;
48: ushort icrc;
49:
50: /* statistics */
51: ulong chan0;
52: ulong toolong;
53: ulong tooshort;
54: ulong badcrc;
55: ulong badescape;
56: ulong in; /* bytes in */
57: ulong out; /* bytes out */
58: };
59:
60: int nasync;
61:
62: /* list of allocated async structures (never freed) */
63: struct
64: {
65: Lock;
66: Async *async;
67: } asyncalloc;
68:
69: /*
70: * async stream module definition
71: */
72: static void asynciput(Queue*, Block*);
73: static void asyncoput(Queue*, Block*);
74: static void asyncopen(Queue*, Stream*);
75: static void asyncclose(Queue*);
76: static void asyncreset(void);
77: Qinfo asyncinfo =
78: {
79: asynciput,
80: asyncoput,
81: asyncopen,
82: asyncclose,
83: "async",
84: asyncreset
85: };
86:
87: static int debugcount = 6;
88: int asyncdebug;
89: int asyncerror;
90:
91: static ushort crc_table[256] = {
92: #include "../port/crc_16.h"
93: };
94:
95: #define BOT 0050 /* begin trailer */
96: #define BOTM 0051 /* begin trailer, more data follows */
97: #define BOTS 0052 /* seq update alg. on this trailer */
98:
99: #define FRAME 0x7e
100: #define STUF 0x9d
101:
102: #define CRCSTART (crc_table[0xff])
103: #define CRCFUNC(crc,x) (crc_table[((crc)^(x))&0xff]^((crc)>>8))
104:
105: void
106: stasynclink(void)
107: {
108: newqinfo(&asyncinfo);
109: }
110:
111: /*
112: * create the async structures
113: */
114: static void
115: asyncreset(void)
116: {
117: }
118:
119: /*
120: * allocate an async structure
121: */
122: static void
123: asyncopen(Queue *q, Stream *s)
124: {
125: Async *ap;
126:
127: DPRINT("asyncopen %d\n", s->dev);
128:
129: for(ap = asyncalloc.async; ap; ap = ap->list){
130: qlock(ap);
131: if(ap->inuse == 0)
132: break;
133: qunlock(ap);
134: }
135: if(ap == 0){
136: ap = smalloc(sizeof(Async));
137: qlock(ap);
138: lock(&asyncalloc);
139: ap->list = asyncalloc.async;
140: asyncalloc.async = ap;
141: ap->id = nasync++;
142: unlock(&asyncalloc);
143: }
144: q->ptr = q->other->ptr = ap;
145:
146: ap->inuse = 1;
147: ap->bp = 0;
148: ap->chan = -1;
149: ap->count = 0;
150: ap->toolong = 0;
151: ap->tooshort = 0;
152: ap->badcrc = 0;
153: ap->badescape = 0;
154: ap->chan0 = 0;
155: ap->in = 0;
156: ap->out = 0;
157: ap->wq = WR(q);
158: ap->state = Hunt;
159: qunlock(ap);
160: }
161:
162: static void
163: asyncclose(Queue * q)
164: {
165: Async *ap = (Async *)q->ptr;
166:
167: DPRINT("asyncstclose %d\n", ap->id);
168: qlock(ap);
169: ap->inuse = 0;
170: qunlock(ap);
171: }
172:
173: /*
174: * free all blocks of a message in `q', `bp' is the first block
175: * of the message
176: */
177: static void
178: freemsg(Queue *q, Block *bp)
179: {
180: for(; bp; bp = getq(q)){
181: if(bp->flags & S_DELIM){
182: freeb(bp);
183: return;
184: }
185: freeb(bp);
186: }
187: }
188:
189: static void
190: showframe(char *t, Async *ap, uchar *buf, int n)
191: {
192: kprint("a%d %s [", ap->id, t);
193: while (--n >= 0)
194: kprint(" %2.2ux", *buf++);
195: kprint(" ]\n");
196: }
197:
198: void
199: aswrite(Async *ap)
200: {
201: if(ap->bp->rptr == ap->bp->wptr)
202: return;
203: if(asyncdebug > 2)
204: showframe("out", ap, ap->bp->rptr, BLEN(ap->bp));
205: FLOWCTL(ap->wq, ap->bp);
206: ap->bp = 0;
207: ap->count = 0;
208: }
209:
210: void
211: asputf(Async *ap)
212: {
213: uchar *p;
214: int c;
215:
216: p = ap->bp->wptr;
217: if(ap->count > 0) {
218: if(asyncerror)
219: ap->crc^=1, asyncerror=0;
220: *p++ = c = ap->crc&0xff;
221: if(c == FRAME)
222: *p++ = 0x00;
223: *p++ = c = (ap->crc>>8)&0xff;
224: if(c == FRAME)
225: *p++ = 0x00;
226: ap->count = 0;
227: }
228: *p++ = FRAME;
229: *p++ = FRAME;
230: ap->bp->wptr = p;
231: aswrite(ap);
232: }
233:
234: void
235: asputc(Async *ap, int c)
236: {
237: int d;
238: uchar *p;
239:
240: if(ap->bp == 0)
241: ap->bp = allocb(2*MAXFRAME+8); /* worst-case expansion */
242: p = ap->bp->wptr;
243: if(ap->count <= 0) {
244: *p++ = d = 0x80|((ap->chan>>5)&0x7e);
245: ap->crc = CRCFUNC(CRCSTART, d);
246: *p++ = d = 0x80|((ap->chan<<1)&0x7e);
247: ap->crc = CRCFUNC(ap->crc, d);
248: }
249: *p++ = c;
250: if(c == FRAME)
251: *p++ = 0x00;
252: ap->crc = CRCFUNC(ap->crc, c);
253: ap->bp->wptr = p;
254: if(++ap->count >= MAXFRAME-4)
255: asputf(ap);
256: }
257:
258: /*
259: * output a block
260: *
261: * the first 2 bytes of every message are the channel number,
262: * low order byte first. the third is a possible trailing control
263: * character.
264: */
265: void
266: asyncoput(Queue *q, Block *bp)
267: {
268: Async *ap = (Async *)q->ptr;
269: int c, chan, ctl;
270: Block *msg;
271:
272: if(bp->type != M_DATA){
273: if(streamparse("debug", bp)){
274: asyncdebug = 3;
275: freeb(bp);
276: } else {
277: PUTNEXT(q, bp);
278: }
279: return;
280: }
281:
282: /*
283: * each datakit message has a 2 byte channel number followed by
284: * one control byte
285: */
286: msg = pullup(bp, 3);
287: if(msg == 0){
288: print("asyncoput msglen < 3\n");
289: return;
290: }
291: chan = msg->rptr[0] | (msg->rptr[1]<<8);
292: ctl = msg->rptr[2];
293: msg->rptr += 3;
294:
295: qlock(&ap->xmit);
296: if(waserror()){
297: qunlock(&ap->xmit);
298: freeb(msg);
299: nexterror();
300: }
301:
302: /*
303: * new frame if the channel number has changed
304: */
305: if(chan != ap->chan && ap->count > 0)
306: asputf(ap);
307: ap->chan = chan;
308:
309: if(asyncdebug > 1)
310: kprint("a%d->(%d)%3.3uo %d\n",
311: ap->id, chan, ctl, bp->wptr-bp->rptr);
312:
313: /*
314: * send the 8 bit data
315: */
316: for(bp = msg; bp; bp = bp->next){
317: while (bp->rptr < bp->wptr) {
318: asputc(ap, c = *bp->rptr++);
319: if(c == STUF)
320: asputc(ap, 0);
321: }
322: }
323:
324: /*
325: * send the control byte if there is one
326: */
327: if(ctl){
328: asputc(ap, STUF);
329: asputc(ap, ctl);
330: switch (ctl) {
331: case BOT:
332: case BOTM:
333: case BOTS:
334: break;
335: default:
336: asputf(ap);
337: }
338: }
339: if(debugcount > 0 && --debugcount == 0)
340: asyncdebug = 1;
341:
342: freeb(msg);
343: qunlock(&ap->xmit);
344: poperror();
345: return;
346: }
347:
348: /*
349: * Read bytes from the raw input.
350: */
351:
352: void
353: asdeliver(Queue *q, Async *ap)
354: {
355: int chan, c;
356: Block *bp = 0;
357: uchar *p = ap->buf;
358: int n = ap->icount;
359:
360: chan = *p++ & 0x7e;
361: chan = (chan<<5)|((*p++ & 0x7e)>>1);
362: if(chan==0) {
363: DPRINT("a%d deliver chan 0\n", ap->id);
364: ap->chan0++;
365: return;
366: }
367: for (n-=4; n>0; n--) {
368: if(!bp) {
369: bp = allocb(n+2);
370: bp->flags |= S_DELIM;
371: bp->wptr[0] = chan;
372: bp->wptr[1] = chan>>8;
373: bp->wptr[2] = 0;
374: bp->wptr += 3;
375: }
376: if((c = *p++) == STUF) {
377: --n;
378: if((c = *p++) != 0) {
379: bp->rptr[2] = c;
380: if(asyncdebug > 1)
381: kprint("a%d<-(%d)%3.3uo %d\n",
382: ap->id, chan, bp->rptr[2],
383: bp->wptr - bp->rptr - 3);
384: PUTNEXT(q, bp);
385: bp = 0;
386: continue;
387: } else
388: c = STUF;
389: }
390: *bp->wptr++ = c;
391: }
392: if(bp) {
393: if(asyncdebug > 1)
394: kprint("a%d<-(%d)%3.3uo %d\n",
395: ap->id, chan, bp->rptr[2],
396: bp->wptr - bp->rptr - 3);
397: PUTNEXT(q, bp);
398: }
399: }
400:
401: static void
402: asynciput(Queue *q, Block *bp)
403: {
404: int c;
405: Async *ap = q->ptr;
406: int state = ap->state;
407:
408: while(bp->wptr > bp->rptr){
409: c = *bp->rptr++;
410: switch(state) {
411: case Hunt: /* wait for framing byte */
412: if(c == FRAME)
413: state = Framing;
414: break;
415:
416: case Framing: /* saw 1 framing byte after Hunt */
417: if(c == FRAME)
418: state = Framed;
419: else
420: state = Hunt;
421: break;
422:
423: case Framed: /* saw 2 or more framing bytes */
424: if(c == FRAME)
425: break;
426: state = Data;
427: ap->icrc = CRCSTART;
428: ap->icount = 0;
429: goto Datachar;
430:
431: case Data: /* mid-frame */
432: if(c == FRAME) {
433: state = Escape;
434: break;
435: }
436: Datachar:
437: if(ap->icount >= MAXFRAME) {
438: DPRINT("a%d pkt too long\n", ap->id);
439: ap->toolong++;
440: state = Hunt;
441: break;
442: }
443: ap->icrc = CRCFUNC(ap->icrc, c);
444: ap->buf[ap->icount++] = c;
445: break;
446:
447: case Escape: /* saw framing byte in Data */
448: switch (c) {
449: case FRAME:
450: if(asyncdebug > 2)
451: showframe("in", ap, ap->buf, ap->icount);
452: if(ap->icount < 5) {
453: DPRINT("a%d pkt too short\n", ap->id);
454: if(asyncdebug && asyncdebug<=2)
455: showframe("shortin", ap, ap->buf, ap->icount);
456: ap->tooshort++;
457: } else if(ap->icrc != 0) {
458: DPRINT("a%d bad crc\n", ap->id);
459: if(asyncdebug && asyncdebug<=2)
460: showframe("badin", ap, ap->buf, ap->icount);
461: ap->badcrc++;
462: } else {
463: asdeliver(q, ap);
464: }
465: state = Framed;
466: break;
467: case 0:
468: c = FRAME;
469: state = Data;
470: goto Datachar;
471: default:
472: DPRINT("a%d bad escape\n", ap->id);
473: ap->badescape++;
474: state = Hunt;
475: break;
476: }
477: break;
478: }
479: }
480: ap->state = state;
481: freeb(bp);
482: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.