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