Annotation of lucent/sys/src/9/port/stasync.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.