Annotation of researchv10no/sys/io/dkp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Datakit URP protocol
                      3:  *
                      4:  * In the language we speak to the device driver,
                      5:  * M_DATA blocks contain data envelopes
                      6:  * M_CTL blocks contain a control envelope,
                      7:  * followed by zero or more data envelopes
                      8:  *
                      9:  * Drivers are allowed to store up blocks for a while;
                     10:  * the S_DELIM bit means that stored data must now be sent.
                     11:  * The point is to work with some broken URP implementations
                     12:  * that have found their way into Datakit controllers;
                     13:  * a driver that speaks to one might have to save data up,
                     14:  * then send it with no intervening control-nulls when S_DELIM comes.
                     15:  */
                     16: 
                     17: #include "sys/param.h"
                     18: #include "sys/stream.h"
                     19: #include "sys/conf.h"
                     20: #include "sys/ttyio.h"
                     21: #include "sys/dkio.h"
                     22: #include "sys/dkstat.h"
                     23: #include "sys/dkp.h"
                     24: #include "sys/dkmod.h"
                     25: 
                     26: #ifdef CAREFUL
                     27: #define        TRC(c)  *dkptrp++ = c; if (dkptrp>=&dkptrb[1024]) dkptrp=dkptrb
                     28: char   dkptrb[1024]; char *dkptrp = dkptrb;
                     29: #else
                     30: #define        TRC(c)
                     31: #endif
                     32: 
                     33: extern struct  dkstat dkstat;
                     34: 
                     35: /*
                     36:  *  Protocol control bytes
                     37:  */
                     38: #define        SEQ     0010            /* sequence number, ends trailers */
                     39: #undef ECHO
                     40: #define        ECHO    0020            /* echos, data given to next queue */
                     41: #define        REJ     0030            /* rejections, transmission error */
                     42: #define        ACK     0040            /* acknowledgments */
                     43: #define        BOT     0050            /* beginning of trailer */
                     44: #define        BOTM    0051            /* beginning of trailer, more data follows */
                     45: #define        BOTS    0052            /* seq update algorithm on this trailer */
                     46: #define        SOU     0053            /* start of unsequenced trailer */
                     47: #define        EOU     0054            /* end of unsequenced trailer */
                     48: #define        ENQ     0055            /* xmitter requests flow/error status */
                     49: #define        CHECK   0056            /* xmitter requests error status */
                     50: #define        INITREQ 0057            /* request initialization */
                     51: #define        INIT0   0060            /* disable trailer processing */
                     52: #define        INIT1   0061            /* enable trailer procesing */
                     53: #define        AINIT   0062            /* response to INIT0/INIT1 */
                     54: #undef DELAY
                     55: #define        DELAY   0100            /* real-time printing delay */
                     56: #define        BREAK   0110            /* Send/receive break (new style) */
                     57: 
                     58: #define        OPEN    01
                     59: #define        LCLOSE  02
                     60: #define        RCLOSE  04
                     61: #define        XCHARMODE 010
                     62: #define        OPENING 020
                     63: #define        RJING   040
                     64: #define        STOPPED 0100
                     65: #define        RCHARMODE 0200
                     66: 
                     67: #define        DKPPRI  28
                     68: #define        DKPTIME 2
                     69: 
                     70: extern struct dkp dkp[];
                     71: extern int     dkpcnt;
                     72: long   dkpopen(), cdkpopen();
                     73: int    dkpiput(), dkpisrv(), dkpoput(), dkposrv();
                     74: int    dkpclose();
                     75: static struct qinit cdkprinit = { dkpiput,dkpisrv,cdkpopen,dkpclose,512,64 };
                     76: static struct qinit cdkpwinit = { dkpoput,dkposrv,cdkpopen,dkpclose,128,65 };
                     77: static struct qinit dkprinit = { dkpiput,dkpisrv,dkpopen,dkpclose,1500,512 };
                     78: static struct qinit dkpwinit = { dkpoput,dkposrv,dkpopen,dkpclose,1500,512 };
                     79: struct streamtab dkpstream = { &dkprinit, &dkpwinit };
                     80: struct streamtab cdkpstream = { &cdkprinit, &cdkpwinit };
                     81: 
                     82: #define        MAXMSG  4096            /* max message size allowed */
                     83: 
                     84: long
                     85: dkpopen(q)
                     86: struct queue *q;
                     87: {
                     88:        return(rdkpopen(q, !XCHARMODE));
                     89: }
                     90: 
                     91: long
                     92: cdkpopen(q)
                     93: struct queue *q;
                     94: {
                     95:        return(rdkpopen(q, XCHARMODE));
                     96: }
                     97: 
                     98: rdkpopen(q, mode)
                     99: register struct queue *q;
                    100: {
                    101:        register struct dkp *dkpp;
                    102:        static timer = 0;
                    103:        int dkptimer();
                    104: 
                    105:        if (timer == 0) {
                    106:                timer = 1;
                    107:                timeout(dkptimer, (caddr_t)NULL, HZ);
                    108:        }
                    109:        if (q->ptr == NULL) {
                    110:                for (dkpp = dkp; dkpp->state!=0; dkpp++)
                    111:                        if (dkpp >= &dkp[dkpcnt])
                    112:                                return(0);
                    113:                dkpp->rdq = q;
                    114:                q->ptr = (caddr_t)dkpp;
                    115:                WR(q)->ptr = (caddr_t)dkpp;
                    116:                WR(q)->flag |= QNOENB;
                    117:                putctl(q->next, M_FLUSH);
                    118:                dkpp->timer = DKPTIME;
                    119:                dkpp->trx = 0;
                    120:                dkpp->iseq = 0;
                    121:                dkpp->lastecho = ECHO+0;
                    122:                dkpp->WS = 1;
                    123:                dkpp->WACK = 1;
                    124:                dkpp->WNX = 1;
                    125:                dkpp->XW = 3;
                    126:                dkpp->xsize = 64;
                    127:                dkpp->lastctl = 0;
                    128:                if (mode!=XCHARMODE) {
                    129:                        WR(q)->flag |= QDELIM;
                    130:                        dkpp->state = OPENING | RCHARMODE;
                    131:                        putctl1d(WR(q)->next, M_CTL, INIT1);
                    132:                } else {
                    133:                        dkpp->XW = 1;
                    134:                        dkpp->state = RCHARMODE | XCHARMODE | OPEN;
                    135:                        putctl1d(WR(q)->next, M_CTL, INIT0);
                    136:                }
                    137:        }
                    138:        return(1);
                    139: }
                    140: 
                    141: /*
                    142:  * Shut it down.
                    143:  *  The problem is to dispose of unacked stuff in the window.
                    144:  *   -- no real solution; the receiver might hang on for hours.
                    145:  *   Give it 15 seconds.
                    146:  */
                    147: dkpclose(q)
                    148: register struct queue *q;
                    149: {
                    150:        register struct dkp *dkpp;
                    151:        register s = spl5();
                    152:        register i;
                    153: 
                    154:        dkpp = (struct dkp *)q->ptr;
                    155:        dkpp->state |= LCLOSE;
                    156:        flushq(q, 1);
                    157:        for (i=0; dkpp->WACK < dkpp->WNX && i<15; i++)
                    158:                tsleep((caddr_t)dkpp, DKPPRI, 1);
                    159:        if (dkpp->WACK < dkpp->WNX)
                    160:                dkprack(dkpp, ACK+((dkpp->WNX-1) & 07));
                    161:        dkpinflush(dkpp);
                    162:        splx(s);
                    163:        dkpp->state = 0;
                    164:        flushq(WR(q), 1);
                    165: }
                    166: 
                    167: 
                    168: /*
                    169:  * Process a bunch of input
                    170:  *   -- for now, ignore strange control bytes
                    171:  */
                    172: dkpisrv(q)
                    173: register struct queue *q;
                    174: {
                    175:        register struct dkp *dkpp = (struct dkp *)q->ptr;
                    176:        register struct block *bp;
                    177:        register c;
                    178: 
                    179:        while (bp = getq(q)) {
                    180:                if (bp->type == M_CTL) {
                    181:                        c = *bp->rptr & 0370;
                    182:                        if (c==REJ || c==ECHO) {
                    183:                                dkpp->lastecho = *bp->rptr;
                    184:                                bp->class |= S_DELIM;
                    185:                                (*WR(q)->next->qinfo->putp)(WR(q)->next, bp);
                    186:                        } else
                    187:                                freeb(bp);      /* unknown control */
                    188:                        continue;
                    189:                }
                    190:                if ((q->next->flag&QFULL)==0 || bp->type>=QPCTL
                    191:                 || dkpp->state&RCLOSE) {
                    192:                        TRC('G'); TRC(*bp->rptr);
                    193:                        (*q->next->qinfo->putp)(q->next, bp);
                    194:                } else {
                    195:                        putbq(q, bp);
                    196:                        return;
                    197:                }
                    198:        }
                    199: }
                    200: 
                    201: /*
                    202:  * Packet arrives.
                    203:  */
                    204: dkpiput(q, bp)
                    205: struct queue *q;
                    206: register struct block *bp;
                    207: {
                    208:        register struct dkp *dkpp;
                    209:        register i;
                    210:        register struct block *nbp;
                    211: 
                    212:        if ((dkpp = (struct dkp *)q->ptr)==NULL) {
                    213:                freeb(bp);
                    214:                return;
                    215:        }
                    216:        switch (bp->type) {
                    217: 
                    218:        moredata:
                    219:                bp->rptr++;
                    220:                bp->type = M_DATA;
                    221:        case M_DATA:
                    222:                bp->class &= ~S_DELIM;
                    223:                if (bp->rptr >= bp->wptr||q->flag&QFULL||dkpp->state&LCLOSE) {
                    224:                        freeb(bp);
                    225:                        return;
                    226:                }
                    227:                if (dkpp->state & RCHARMODE) {
                    228:                        putq(q, bp);
                    229:                        return;
                    230:                }
                    231:                switch (dkpp->trx) {
                    232: 
                    233:                        case 1:
                    234:                        case 2:
                    235:                                dkpp->trbuf[dkpp->trx++] = *bp->rptr;
                    236:                                goto moredata;
                    237:                        
                    238:                        default:
                    239:                                dkpp->trx = 0;
                    240:                        case 0:
                    241:                                break;
                    242:                }
                    243:                bp->next = NULL;
                    244:                if (dkpp->indata > MAXMSG) {    /* protect against garbage */
                    245:                        freeb(bp);
                    246:                        return;
                    247:                }
                    248:                if (dkpp->inp) {
                    249:                        dkpp->inpe->next = bp;
                    250:                        dkpp->inpe = bp;
                    251:                } else {
                    252:                        dkpp->inp = bp;
                    253:                        dkpp->inpe = bp;
                    254:                }
                    255:                dkpp->indata += bp->wptr - bp->rptr;
                    256:                return;
                    257: 
                    258:        case M_CTL:
                    259:                switch (*bp->rptr) {
                    260: 
                    261:                case ENQ:
                    262:                        putctl1(WR(q)->next, M_CTL, dkpp->lastecho);
                    263:                case CHECK:
                    264:                        putctl1d(WR(q)->next, M_CTL, ACK+dkpp->iseq);
                    265:                        dkpinflush(dkpp);
                    266:                        goto moredata;
                    267: 
                    268:                case AINIT:
                    269:                        dkpp->state &= ~OPENING;
                    270:                        dkpp->state |= OPEN;
                    271:                        qenable(WR(q));
                    272:                        dkpinflush(dkpp);
                    273:                        goto moredata;
                    274: 
                    275:                case INIT0:
                    276:                case INIT1:
                    277:                        putctl1d(WR(q)->next, M_CTL, AINIT);
                    278:                        if (*bp->rptr==INIT0 && (dkpp->state&RCHARMODE)==0) {
                    279:                                dkpp->state |= RCHARMODE;
                    280:                                dkpp->XW = 1;   /* why? */
                    281:                                q->flag &= ~QDELIM;
                    282:                        } else if (*bp->rptr==INIT1 && (dkpp->state&RCHARMODE)) {
                    283:                                dkpp->state &= ~RCHARMODE;
                    284:                                dkpp->XW = 3;   /* why? */
                    285:                                q->flag |= QDELIM;
                    286:                        }
                    287:                        dkpinflush(dkpp);
                    288:                        dkpp->iseq = 0;
                    289:                        wakeup((caddr_t)dkpp);
                    290:                        goto moredata;
                    291: 
                    292:                case INITREQ:
                    293:                        if (dkpp->state&XCHARMODE)
                    294:                                putctl1d(WR(q)->next, M_CTL, INIT0);
                    295:                        else {
                    296:                                if (dkpp->WS < dkpp->WNX)
                    297:                                        dkprack(dkpp, ECHO+((dkpp->WNX-1)&07));
                    298:                                dkpp->WS = 1;
                    299:                                dkpp->WACK = 1;
                    300:                                dkpp->WNX = 1;
                    301:                                putctl1d(WR(q)->next, M_CTL, INIT1);
                    302:                        }
                    303:                        dkpinflush(dkpp);
                    304:                        goto moredata;
                    305: 
                    306:                case BREAK:
                    307:                        qpctl(q, M_BREAK);
                    308:                        dkpp->indata++;
                    309:                        goto moredata;
                    310: 
                    311:                case BOT:
                    312:                case BOTS:
                    313:                case BOTM:
                    314:                        dkpp->trx = 1;
                    315:                        dkpp->trbuf[0] = *bp->rptr;
                    316:                        goto moredata;
                    317: 
                    318:                case REJ+0: case REJ+1: case REJ+2: case REJ+3:
                    319:                case REJ+4: case REJ+5: case REJ+6: case REJ+7:
                    320:                        if (dkpp->state&XCHARMODE)
                    321:                                goto moredata;
                    322:                        TRC('r');
                    323:                        if (((*bp->rptr+1)&07) == (dkpp->WACK&07)
                    324:                         && (dkpp->state&RJING) == 0) {
                    325:                                dkstat.dkprxmit++;
                    326:                                for (i=dkpp->WACK; i<dkpp->WNX; i++) {
                    327:                                        TRC('Z');
                    328:                                        TRC('0' + (i&07));
                    329:                                        dkpp->state |= RJING;
                    330:                                        dkpxmit(WR(q), dkpp->xb[i&07], i);
                    331:                                }
                    332:                        }
                    333:                        goto moredata;
                    334:                
                    335:                case ACK+0: case ACK+1: case ACK+2: case ACK+3:
                    336:                case ACK+4: case ACK+5: case ACK+6: case ACK+7:
                    337:                case ECHO+0: case ECHO+1: case ECHO+2: case ECHO+3:
                    338:                case ECHO+4: case ECHO+5: case ECHO+6: case ECHO+7:
                    339:                        dkprack(dkpp, *bp->rptr);
                    340:                        goto moredata;
                    341: 
                    342:                case SEQ+0: case SEQ+1: case SEQ+2: case SEQ+3:
                    343:                case SEQ+4: case SEQ+5: case SEQ+6: case SEQ+7:
                    344:                        i = *bp->rptr & 07;
                    345:                        if (dkpp->state & RCHARMODE) {
                    346:                                TRC('e');
                    347:                                qpctl1(q, M_CTL, ECHO+i);
                    348:                                goto moredata;
                    349:                        }
                    350:                        if (dkpp->trx !=3
                    351:                         || dkpp->indata != dkpp->trbuf[1] + (dkpp->trbuf[2]<<8)
                    352:                         || i != ((dkpp->iseq+1)&07)) { /* reject? */
                    353:                                if (dkpp->trx != 3)
                    354:                                        dkstat.dkprjtrs++;
                    355:                                else if (i != ((dkpp->iseq+1)&07))
                    356:                                        dkstat.dkprjseq++;
                    357:                                else
                    358:                                        dkstat.dkprjpks++;
                    359:                                dkpinflush(dkpp);
                    360:                                if (dkpp->trbuf[0]==BOTS)
                    361:                                        dkpp->iseq = i;
                    362:                                TRC('R'); TRC('0'+dkpp->iseq);
                    363:                                TRC(dkpp->trx!=3?'t':(i!=(dkpp->iseq+1)&07?'s':'c'));
                    364:                                qpctl1(q, M_CTL, REJ+dkpp->iseq);
                    365:                                goto moredata;
                    366:                        }
                    367:                        /* accept */
                    368:                        if (dkpp->inpe==NULL)
                    369:                                dkpp->inp = dkpp->inpe = allocb(0);
                    370:                        if (dkpp->trbuf[0] != BOTM && q->flag&QDELIM)
                    371:                                dkpp->inpe->class |= S_DELIM;
                    372:                        while (nbp = dkpp->inp) {
                    373:                                dkpp->inp = nbp->next;
                    374:                                putq(q, nbp);
                    375:                        }
                    376:                        TRC('A'); TRC('0'+i);
                    377:                        dkpp->inpe = NULL;
                    378:                        dkpp->trx = 0;
                    379:                        dkpp->indata = 0;
                    380:                        dkpp->iseq = i;
                    381:                        qpctl1(q, M_CTL, ECHO+i);
                    382:                        goto moredata;
                    383: 
                    384:                default:
                    385:                        if (*bp->rptr < 0200)   /* non-supervisory */
                    386:                                dkpp->indata++;
                    387:                        dkpp->lastctl = *bp->rptr;
                    388:                        qpctl1(q, M_CTL, *bp->rptr);
                    389:                        goto moredata;
                    390:                }
                    391: 
                    392:        case M_HANGUP:
                    393:                dkpp->state |= RCLOSE;
                    394:                flushq(WR(q), 1);
                    395:                dkprack(dkpp, ECHO+((dkpp->WNX-1) & 07));
                    396:                putq(q, bp);
                    397:                return;
                    398: 
                    399:        case M_IOCACK:
                    400:        case M_IOCNAK:
                    401:                (*q->next->qinfo->putp)(q->next, bp);
                    402:                return;
                    403: 
                    404:        case M_PRICTL:
                    405:                if (*bp->rptr != DKMXINIT) {
                    406:                        (*q->next->qinfo->putp)(q->next, bp);
                    407:                        return;
                    408:                }
                    409:                bp->type = M_CTL;
                    410:                bp->wptr = bp->rptr;
                    411:                *bp->wptr++ = INITREQ;
                    412:                dkpiput(q, bp);
                    413:                putctl1d(WR(q)->next, M_CTL, INITREQ);
                    414:                return;
                    415: 
                    416:        default:
                    417:                freeb(bp);
                    418:                return;
                    419:        }
                    420: }
                    421: 
                    422: /*
                    423:  * --- Output processor
                    424:  */
                    425: 
                    426: /*
                    427:  * accept data from writer
                    428:  *  -- handle most non-data messages
                    429:  */
                    430: 
                    431: int dkpwbig = 200;
                    432: 
                    433: dkpoput(q, bp)
                    434: register struct queue *q;
                    435: register struct block *bp;
                    436: {
                    437:        register struct dkp *dkpp = (struct dkp *)q->ptr;
                    438:        register unsigned char *sp;
                    439:        register x, s;
                    440:        struct block *xbp;
                    441: 
                    442:        if (dkpp->state & RCLOSE) {
                    443:                freeb(bp);
                    444:                return;
                    445:        }
                    446:        switch (bp->type) {
                    447: 
                    448:        case M_STOP:
                    449:                dkpp->state |= STOPPED;
                    450:                freeb(bp);
                    451:                return;
                    452: 
                    453:        case M_START:
                    454:                dkpp->state &= ~STOPPED;
                    455:                freeb(bp);
                    456:                qenable(q);
                    457:                return;
                    458: 
                    459:        case M_FLUSH:
                    460:                /* annul data for blocks in transit */
                    461:                freeb(bp);
                    462:                s = spl5();     /* in case an ECHO is about to arrive */
                    463:                for (x=0; x<8; x++)
                    464:                        if ((bp = dkpp->xb[x]) != NULL)
                    465:                                bp->wptr = bp->rptr;
                    466:                splx(s);
                    467:                flushq(q, 0);
                    468:                return;
                    469: 
                    470:        case M_IOCTL:
                    471:                sp = (unsigned char *)stiodata(bp);
                    472:                switch (stiocom(bp)) {
                    473: 
                    474:                case TIOCSDEV:
                    475:                        x = ((struct ttydevb *)sp)->ispeed;
                    476:                        bp->wptr = bp->rptr;
                    477:                        bp->type = M_IOCACK;
                    478:                        qreply(q, bp);
                    479:                        if (x==0)
                    480:                                putctl(OTHERQ(q), M_HANGUP);
                    481:                        return;
                    482: 
                    483:                case TIOCGDEV:
                    484:                        ((struct ttydevb *)sp)->ispeed = ((struct ttydevb *)sp)->ospeed = B9600;
                    485:                        bp->wptr = bp->rptr + sizeof(struct ttydevb) + STIOCHDR;
                    486:                        if (bp->wptr >= bp->lim)
                    487:                                panic("dkioc");
                    488:                        bp->type = M_IOCACK;
                    489:                        qreply(q, bp);
                    490:                        return;
                    491: 
                    492:                case DIOCSTREAM:
                    493:                        RD(q)->flag &= ~QDELIM;
                    494:                        bp->wptr = bp->rptr;
                    495:                        bp->type = M_IOCACK;
                    496:                        qreply(q, bp);
                    497:                        return;
                    498:                
                    499:                case DIOCRECORD:
                    500:                        if ((dkpp->state&RCHARMODE) == 0) {
                    501:                                RD(q)->flag |= QDELIM;
                    502:                                bp->type = M_IOCACK;
                    503:                        } else
                    504:                                bp->type = M_IOCNAK;
                    505:                        bp->wptr = bp->rptr;
                    506:                        qreply(q, bp);
                    507:                        return;
                    508: 
                    509:                case KIOCINIT:
                    510:                        if (dkpp->state&XCHARMODE)
                    511:                                putctl1d(q->next, M_CTL, INIT0);
                    512:                        else {
                    513:                                s = spl5();
                    514:                                if (dkpp->WS < dkpp->WNX)
                    515:                                        dkprack(dkpp, ECHO+((dkpp->WNX-1)&07));
                    516:                                dkpp->WS = 1;
                    517:                                dkpp->WACK = 1;
                    518:                                dkpp->WNX = 1;
                    519:                                splx(s);
                    520:                                putctl1d(q->next, M_CTL, INIT1);
                    521:                        }
                    522:                        bp->wptr = bp->rptr;
                    523:                        bp->type = M_IOCACK;
                    524:                        qreply(q, bp);
                    525:                        return;
                    526: 
                    527:                case KIOCISURP:
                    528:                        bp->wptr = bp->rptr;
                    529:                        bp->type = M_IOCACK;
                    530:                        qreply(q, bp);
                    531:                        return;
                    532: 
                    533:                case DIOCSCTL:
                    534:                        bp->type = M_IOCACK;
                    535:                        bp->wptr = bp->rptr;
                    536:                        if (*sp == 0) {
                    537:                                qreply(q, bp);
                    538:                                return;
                    539:                        }
                    540:                        if ((xbp = allocb(1)) == NULL)
                    541:                                bp->type = M_IOCNAK;
                    542:                        else {
                    543:                                xbp->type = M_CTL;
                    544:                                xbp->class |= S_DELIM;
                    545:                                *xbp->wptr++ = *sp;
                    546:                                putq(q, xbp);
                    547:                                if (dkpp->WNX < dkpp->WS+dkpp->XW)
                    548:                                        qenable(q);
                    549:                        }
                    550:                        qreply(q, bp);
                    551:                        return;
                    552: 
                    553:                case DIOCRCTL:
                    554:                        *sp = dkpp->lastctl;
                    555:                        dkpp->lastctl = 0;
                    556:                        bp->type = M_IOCACK;
                    557:                        bp->wptr = sp + 1;
                    558:                        qreply(q, bp);
                    559:                        return;
                    560: 
                    561:                case DIOCXWIN:
                    562:                        bp->type = M_IOCACK;
                    563:                        if (sp[4] >= 8 || sp[4] <= 0)
                    564:                                bp->type = M_IOCNAK;
                    565:                        else if ((x = sp[0] + (sp[1]<<8)) < 0 || x > MAXMSG)
                    566:                                bp->type = M_IOCNAK;
                    567:                        else {
                    568:                                dkpp->xsize = x;
                    569:                                dkpp->XW = sp[4];
                    570:                                if (x > dkpwbig)
                    571:                                        q->flag |= QBIGB;
                    572:                                else
                    573:                                        q->flag &=~ QBIGB;
                    574:                        }
                    575:                        bp->wptr = bp->rptr;
                    576:                        qreply(q, bp);
                    577:                        return;
                    578: 
                    579:                default:
                    580:                        (*q->next->qinfo->putp)(q->next, bp);
                    581:                        return;
                    582:                }
                    583: 
                    584:        case M_DELAY:
                    585:                x = *bp->rptr;
                    586:                *bp->rptr = DELAY;
                    587:                bp->type = M_CTL;
                    588:                while (x) {
                    589:                        (*bp->rptr)++;
                    590:                        x >>= 1;
                    591:                }
                    592:                goto putonq;
                    593: 
                    594:        case M_PRICTL:
                    595:                (*q->next->qinfo->putp)(q->next, bp);
                    596:                return;
                    597: 
                    598:        default:
                    599:                freeb(bp);
                    600:                return;
                    601: 
                    602:        case M_BREAK:
                    603:                bp->type = M_CTL;
                    604:                *bp->wptr++ = BREAK;
                    605:        case M_DATA:
                    606:        case M_CTL:
                    607:        putonq:
                    608:                putq(q, bp);
                    609:                if (dkpp->WNX < dkpp->WS+dkpp->XW)
                    610:                        qenable(q);
                    611:                return;
                    612:        }
                    613: }
                    614: 
                    615: /*
                    616:  * Out server:
                    617:  *  if space in window, process queue
                    618:  * This is the only place that WNX is incremented,
                    619:  * and the only place xb[i] is set nonzero
                    620:  * (remember these facts when thinking about races)
                    621:  */
                    622: dkposrv(q)
                    623: register struct queue *q;
                    624: {
                    625:        register struct dkp *dkpp = (struct dkp *)q->ptr;
                    626:        register struct block *bp, *xbp;
                    627:        register int seqno;
                    628:        register struct block **bpp;
                    629:        register int s;
                    630: 
                    631:        if (dkpp->state & (STOPPED|OPENING))
                    632:                return;
                    633:        while (dkpp->WNX < dkpp->WS+dkpp->XW) {
                    634:                if ((bp = getq(q)) == NULL)
                    635:                        break;
                    636:                /*
                    637:                 * Bite off one URP block; put back the rest.
                    638:                 * The initial blocks are passed by reference.
                    639:                 */
                    640:                if (bp->type==M_DATA && bp->wptr-bp->rptr > dkpp->xsize) {
                    641:                        xbp = dupb(bp);
                    642:                        bp->rptr += dkpp->xsize;
                    643:                        xbp->wptr = xbp->rptr+dkpp->xsize;
                    644:                        xbp->class &= ~S_DELIM;
                    645:                        putbq(q, bp);
                    646:                        bp = xbp;
                    647:                }
                    648:                if (dkpp->state & XCHARMODE) {
                    649:                        dkpp->outcnt += bp->wptr - bp->rptr;
                    650:                        (*q->next->qinfo->putp)(q->next, bp);
                    651:                        if (dkpp->outcnt >= dkpp->xsize) {
                    652:                                putctl1d(q->next, M_CTL, SEQ+(dkpp->WNX&07));
                    653:                                dkpp->WNX++;
                    654:                                dkpp->WACK = dkpp->WNX;
                    655:                                dkpp->outcnt = 0;
                    656:                        }
                    657:                        continue;
                    658:                }
                    659:                TRC('x'); TRC('0'+dkpp->WS/10); TRC('0'+dkpp->WS%10);
                    660:                TRC('.'); TRC('0'+dkpp->WNX/10); TRC('0'+dkpp->WNX%10);
                    661:                bpp = &dkpp->xb[dkpp->WNX&07];
                    662:                if (*bpp) {
                    663:                        s = spl5();     /* in case of last-minute ECHO */
                    664:                        if (*bpp) {
                    665:                                freeb(*bpp);
                    666:                                printf("dkp losing block %x\n", *bpp);
                    667:                                *bpp = 0;       /* if ECHO comes later, don't free twice */
                    668:                        }
                    669:                        splx(s);
                    670:                }
                    671:                *bpp = bp;
                    672:                seqno = dkpp->WNX++;            /* in case ECHO comes right away */
                    673:                dkpxmit(q, bp, seqno);
                    674:                /* what if INIT[01] arrived between `bpp = ...' and here? */
                    675:        }
                    676: }
                    677: 
                    678: /*
                    679:  *  Send out a message, with trailer.
                    680:  */
                    681: dkpxmit(q, bp, seqno)
                    682: register struct queue *q;
                    683: register struct block *bp;
                    684: {
                    685:        register size;
                    686:        register struct block *xbp;
                    687:        register struct dkp *dkpp = (struct dkp *)q->ptr;
                    688: 
                    689:        if (bp==NULL) {
                    690:                printf("null bp in dkpxmit\n");
                    691:                return;
                    692:        }
                    693:        size = bp->wptr - bp->rptr;
                    694:        seqno &= 07;
                    695:        /* send ptr to block, if non-empty */
                    696:        if (size) {
                    697:                if ((xbp = dupb(bp)) == NULL)
                    698:                        return;
                    699:                xbp->class &=~ S_DELIM;
                    700:                TRC('X'); TRC('0'+seqno);
                    701:                (*q->next->qinfo->putp)(q->next, xbp);
                    702:        }
                    703:        /* send trailer */
                    704:        if ((xbp = allocb(3)) == NULL)
                    705:                return;
                    706:        xbp->type = M_CTL;
                    707:        *xbp->wptr++ = bp->class&S_DELIM? BOT: BOTM;
                    708:        *xbp->wptr++ = size;
                    709:        *xbp->wptr++ = size >> 8;
                    710:        (*q->next->qinfo->putp)(q->next, xbp);
                    711:        putctl1d(q->next, M_CTL, SEQ + seqno);
                    712:        dkpp->timer = DKPTIME;
                    713: }
                    714: 
                    715: /*
                    716:  * Receive an ack of some sort for a transmitted message.
                    717:  *  Advance various windows.
                    718:  * should be called at spl5 to avoid races
                    719:  */
                    720: dkprack(dkpp, msg)
                    721: register struct dkp *dkpp;
                    722: {
                    723:        register struct block **bpp;
                    724:        register seqno, i;
                    725: 
                    726:        seqno = msg & 07;
                    727:        msg &= 0370;
                    728:        /* invariants: 0 <= WS <= WACK <= WNX; seqno maximal < WNX; WS < 8 */
                    729:        if (seqno >= dkpp->WNX)
                    730:                seqno -= 8;
                    731:        else if (seqno+8 < dkpp->WNX)
                    732:                seqno += 8;
                    733:        dkpp->state &= ~RJING;
                    734:        for (i=dkpp->WS; i<=seqno; i++) {
                    735:                bpp = &dkpp->xb[i&07];
                    736:                if (*bpp) {
                    737:                        freeb(*bpp);
                    738:                        *bpp = NULL;
                    739:                }
                    740:        }
                    741:        if ((int)dkpp->WACK <= seqno)
                    742:                dkpp->WACK = seqno+1;
                    743:        if (msg==ECHO) {
                    744:                TRC('E'); TRC('0'+(seqno&07));
                    745:                if (dkpp->WS <= seqno) {
                    746:                        dkpp->timer = DKPTIME;  /* push off timeout */
                    747:                        dkpp->WS = seqno+1;
                    748:                        if (dkpp->WNX<dkpp->WS+dkpp->XW && WR(dkpp->rdq)->count)
                    749:                                qenable(WR(dkpp->rdq));
                    750:                }
                    751:        } else {
                    752:                for (i=dkpp->WACK; i<dkpp->WNX; i++) {
                    753:                        if (dkpp->xb[i&07]==0)
                    754:                         printf("WS %d WACK %d WNX %d i %d seqno %d\n",
                    755:                           dkpp->WS, dkpp->WACK, dkpp->WNX, i, seqno);
                    756:                        dkpxmit(WR(dkpp->rdq), dkpp->xb[i&07], i);
                    757:                        dkstat.dkprxmit++;
                    758:                }
                    759:        }
                    760:        if (dkpp->WS >= 8) {
                    761:                dkpp->WS -= 8;
                    762:                dkpp->WACK -= 8;
                    763:                dkpp->WNX -= 8;
                    764:        }
                    765: }
                    766: 
                    767: dkptimer()
                    768: {
                    769:        register struct dkp *dkpp;
                    770:        register struct queue *q;
                    771:        register int i;
                    772: 
                    773:        for (dkpp = dkp, i = dkpcnt; i > 0; dkpp++, --i) {
                    774:                if ((dkpp->state&(OPEN|OPENING)) == 0)
                    775:                        continue;
                    776:                if (--dkpp->timer>0)
                    777:                        continue;
                    778:                q = WR(dkpp->rdq)->next;
                    779:                if (q->flag&QFULL)
                    780:                        continue;
                    781:                if (dkpp->state & XCHARMODE) {
                    782:                        if (dkpp->WS < dkpp->WNX)
                    783:                                putctl1d(q, M_CTL, SEQ+((dkpp->WNX-1)&07));
                    784:                        dkpp->timer = 10;
                    785:                        continue;
                    786:                }
                    787:                if (dkpp->state&OPENING)
                    788:                        putctl1d(q, M_CTL, INIT1);
                    789:                if (dkpp->WS != dkpp->WNX)
                    790:                        putctl1d(q, M_CTL, ENQ);
                    791:                dkpp->timer = DKPTIME;
                    792:        }
                    793:        timeout(dkptimer, (caddr_t)NULL, HZ);
                    794: }
                    795: 
                    796: /*
                    797:  * throw away data in front of the barrier, and clear the trailer buffer
                    798:  */
                    799: dkpinflush(dkpp)
                    800: register struct dkp *dkpp;
                    801: {
                    802:        register struct block *bp;
                    803: 
                    804:        while (bp = dkpp->inp) {
                    805:                dkpp->inp = bp->next;
                    806:                freeb(bp);
                    807:        }
                    808:        dkpp->inpe = NULL;
                    809:        dkpp->trx = 0;
                    810:        dkpp->indata = 0;
                    811: }

unix.superglobalmegacorp.com

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