Annotation of researchv10no/sys/io/archosld.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *  Raw line discipline and listener stuff for talking to controller
        !             3:  */
        !             4: #include "sys/param.h"
        !             5: #include "sys/stream.h"
        !             6: #include "sys/dkio.h"
        !             7: #include "sys/conf.h"
        !             8: #include "sys/dkstat.h"
        !             9: #include "sys/dkmod.h"
        !            10: 
        !            11: /*
        !            12:  * CMC/Listener message structure
        !            13:  */
        !            14: struct dialin {
        !            15:        char    type;
        !            16:        char    srv;
        !            17:        short   param0;
        !            18:        short   param1;
        !            19:        short   param2;
        !            20:        short   param3;
        !            21:        short   param4;
        !            22:        short   param5;
        !            23: };
        !            24: 
        !            25: struct dialout {
        !            26:        short   chan;
        !            27:        struct  dialin d;
        !            28: };
        !            29: 
        !            30: /*
        !            31:  * Message codes
        !            32:  */
        !            33: #define T_CALL '0'
        !            34: #define        T_LSTNR 4
        !            35: #define        T_CHG   3
        !            36: #define        T_REPLY 10
        !            37: #define        D_CLOSE 1
        !            38: #define        D_ISCLOSED 2
        !            39: #define        D_ENQ   3
        !            40: #define        D_ENQANS 4
        !            41: 
        !            42: /*
        !            43:  * Raw-mode line discipline for DK (only)
        !            44:  */
        !            45: long   adkopen();
        !            46: int    adkclose(), adkiput(), adkoput(), adkosrv(), adkisrv();
        !            47: static struct qinit adkrinit = { adkiput, adkisrv, adkopen, adkclose, 72, 36};
        !            48: static struct qinit adkwinit = { adkoput, adkosrv, adkopen, nulldev, 72, 36};
        !            49: struct streamtab adkstream = { &adkrinit, &adkwinit };
        !            50: 
        !            51: extern struct  dkstat dkstat;
        !            52: extern struct  dkmodule dkmod[];
        !            53: extern int dkmodcnt;
        !            54: 
        !            55: #define        NDKRAW  32
        !            56: struct adk {
        !            57:        struct  queue *q;
        !            58:        struct  dkmodule *module;
        !            59:        short   chan;
        !            60: } adk[NDKRAW];
        !            61: 
        !            62: long
        !            63: adkopen(q, dev)
        !            64: register struct queue *q;
        !            65: {
        !            66:        static timer_on = 0;
        !            67:        register struct adk *dkp, *edkp;
        !            68:        register struct dkmodule *dkm;
        !            69: 
        !            70:        if ((dkm = getdkmod(dev)) == NULL)
        !            71:                return (0);
        !            72:        edkp = NULL;
        !            73:        for (dkp=adk; dkp < &adk[NDKRAW]; dkp++) {
        !            74:                if (dkp->q == q) {
        !            75:                        if (dkp->chan != minor(dev) - dkm->lo || WR(q)->ptr==NULL) {
        !            76:                                printf("q %x dkp %x\n", q, dkp);
        !            77:                                panic("adkopen");
        !            78:                        }
        !            79:                        return(1);
        !            80:                }
        !            81:                if (dkp->q == NULL && edkp==NULL)
        !            82:                        edkp = dkp;
        !            83:        }
        !            84:        if (edkp==NULL)
        !            85:                return(0);
        !            86:        edkp->q = q;
        !            87:        edkp->module = dkm;
        !            88:        edkp->chan = minor(dev) - dkm->lo;
        !            89:        q->flag |= QDELIM;
        !            90:        q->ptr = 0;
        !            91:        WR(q)->ptr = (caddr_t)edkp;
        !            92:        if (timer_on==0) {
        !            93:                adktimer();
        !            94:                timer_on = 1;
        !            95:        }
        !            96:        return(1);
        !            97: }
        !            98: 
        !            99: adkclose(q)
        !           100: register struct queue *q;
        !           101: {
        !           102:        register struct block *bp;
        !           103:        register struct adk *dkp = (struct adk *)WR(q)->ptr;
        !           104: 
        !           105:        if (WR(q)==dkp->module->listnrq) {
        !           106:                dkp->module->listnrq = NULL;
        !           107:                dkp->module->type = 0;
        !           108:        }
        !           109:        while (bp = getq(q))
        !           110:                (*q->next->qinfo->putp)(q->next, bp);
        !           111:        dkp->q = NULL;
        !           112:        dkp->module = NULL;
        !           113: }
        !           114: 
        !           115: /*
        !           116:  * output put procedure.
        !           117:  */
        !           118: adkoput(q, bp)
        !           119: register struct queue *q;
        !           120: register struct block *bp;
        !           121: {
        !           122:        register struct adk *dkp = (struct adk *)q->ptr;
        !           123:        register struct dkmodule *modp = dkp->module;
        !           124:        register i;
        !           125: 
        !           126:        switch (bp->type) {
        !           127: 
        !           128:        case M_IOCTL:
        !           129:                switch (stiocom(bp)) {
        !           130: 
        !           131:                /* hang everybody up */
        !           132:                case DIOCHUP:
        !           133:                        /* must be on listener chan */
        !           134:                        if (q == modp->listnrq) {
        !           135:                                adkmesg(modp, T_LSTNR, 0, 0, 0, 1);
        !           136:                                bp->type = M_IOCACK;
        !           137:                                bp->rptr = bp->wptr;
        !           138:                                qreply(q, bp);
        !           139:                                return;
        !           140:                        }
        !           141:                        break;
        !           142: 
        !           143:                /* announce listener channel */
        !           144:                case DIOCLHN:
        !           145:                        if (modp->listnrq == NULL) {
        !           146:                                modp->listnrq = q;
        !           147:                                RD(q)->flag |= QNOENB;
        !           148:                                modp->type = CMCLD;
        !           149:                                adkmesg(modp, T_LSTNR, 0, 0, 0, 0);
        !           150:                                bp->type = M_IOCACK;
        !           151:                                bp->rptr = bp->wptr;
        !           152:                                qreply(q, bp);
        !           153:                                return;
        !           154:                        }
        !           155:                        break;
        !           156: 
        !           157:                /* delay input */
        !           158:                case DIOCSTOP:
        !           159:                        RD(q)->ptr = (caddr_t)1;
        !           160:                        bp->type = M_IOCACK;
        !           161:                        bp->rptr = bp->wptr;
        !           162:                        qreply(q, bp);
        !           163:                        return;
        !           164: 
        !           165:                /* suggest a free outgoing channel */
        !           166:                case DIOCCHAN:
        !           167:                        for (i=modp->lo + 3; i<modp->hi; i+=2) {
        !           168:                                if (modp->dkstate[i]==DKCLOSED) {
        !           169:                                        stiodata(bp)[0] = i;
        !           170:                                        for (i = 1; i < sizeof(int); i++)
        !           171:                                                stiodata(bp)[i] = 0;    /* silly */
        !           172:                                        bp->wptr = bp->rptr+STIOCHDR+sizeof(int);
        !           173:                                        bp->type = M_IOCACK;
        !           174:                                        break;
        !           175:                                }
        !           176:                        }
        !           177:                        qreply(q, bp);
        !           178:                        return;
        !           179: 
        !           180:                default:
        !           181:                        (*q->next->qinfo->putp)(q->next, bp);
        !           182:                        return;
        !           183:                }
        !           184:                bp->type = M_IOCNAK;
        !           185:                bp->wptr = bp->rptr;
        !           186:                qreply(q, bp);
        !           187:                return;
        !           188:        }
        !           189:        putq(q, bp);
        !           190: }
        !           191: 
        !           192: adkosrv(q)
        !           193: register struct queue *q;
        !           194: {
        !           195:        register struct block *bp;
        !           196: 
        !           197:        while ((q->next->flag&QFULL)==0 && (bp = getq(q)))
        !           198:                (*q->next->qinfo->putp)(q->next, bp);
        !           199: }
        !           200: 
        !           201: /*
        !           202:  * input put procedure
        !           203:  *   -- ignores all control bytes
        !           204:  */
        !           205: adkiput(q, bp)
        !           206: register struct queue *q;
        !           207: register struct block *bp;
        !           208: {
        !           209:        register struct adk *dkp = (struct adk *)WR(q)->ptr;
        !           210:        register int delim;
        !           211: 
        !           212:        switch (bp->type) {
        !           213: 
        !           214:        case M_DATA:
        !           215:                if (WR(q) == dkp->module->listnrq) {
        !           216:                        delim = bp->class & S_DELIM;
        !           217:                        putq(q, bp);
        !           218:                        if (delim)
        !           219:                                qenable(q);
        !           220:                        return;
        !           221:                }
        !           222:                if (q->next->flag&QFULL) { /* you lose */
        !           223:                        freeb(bp);
        !           224:                        return;
        !           225:                }
        !           226:        /*      bp->class |= S_DELIM; always push through; this seems wrong */
        !           227:                if (q->ptr) {   /* input delayed */
        !           228:                        putq(q, bp);
        !           229:                        return;
        !           230:                }
        !           231:                (*q->next->qinfo->putp)(q->next, bp);
        !           232:                return;
        !           233: 
        !           234:        case M_IOCACK:
        !           235:        case M_IOCNAK:
        !           236:        case M_HANGUP:
        !           237:                (*q->next->qinfo->putp)(q->next, bp);
        !           238:                return;
        !           239: 
        !           240:        case M_PRICTL:
        !           241:                switch (*bp->rptr) {
        !           242:                case DKMCLOSE:
        !           243:                        if (dkp->module->dkstate[bp->rptr[1]] == DKRCLOSE)
        !           244:                                adkmesg(dkp->module, T_CHG, D_ISCLOSED, 0, bp->rptr[1], 0);
        !           245:                        else
        !           246:                                adkmesg(dkp->module, T_CHG, D_CLOSE, 0, bp->rptr[1], 0);
        !           247:                        freeb(bp);
        !           248:                        return;
        !           249: 
        !           250:                default:
        !           251:                        freeb(bp);
        !           252:                        return;
        !           253:                }
        !           254: 
        !           255:        default:
        !           256:                freeb(bp);
        !           257:        }
        !           258: }
        !           259: 
        !           260: /*
        !           261:  * listener sends a message to CMC
        !           262:  */
        !           263: adkmesg(modp, type, srv, p0, p1, p2)
        !           264: register struct dkmodule *modp;
        !           265: {
        !           266:        register struct dialout *dp;
        !           267:        register struct block *bp;
        !           268: 
        !           269:        if (modp->listnrq==NULL || modp->listnrq->next->flag&QFULL)
        !           270:                return;
        !           271:        if ((bp = allocb(sizeof(struct dialout))) == NULL)
        !           272:                return;         /* hope it will be retried later */
        !           273:        dp = (struct dialout *)bp->wptr;
        !           274:        dp->chan = ((struct adk *)modp->listnrq->ptr)->chan;
        !           275:        dp->d.type = type;
        !           276:        dp->d.srv = srv;
        !           277:        dp->d.param0 = p0;
        !           278:        dp->d.param1 = p1;
        !           279:        dp->d.param2 = p2;
        !           280:        bp->wptr += sizeof(struct dialout);
        !           281:        bp->class |= S_DELIM;
        !           282:        (*modp->listnrq->next->qinfo->putp)(modp->listnrq->next, bp);
        !           283: }
        !           284: 
        !           285: 
        !           286: /* try to construct a struct dialin from the message */
        !           287: struct block *
        !           288: adkdialin(q, bp)
        !           289: register struct queue *q;
        !           290: register struct block *bp;
        !           291: {
        !           292:        register struct block *nbp;
        !           293:        register int len;
        !           294:        register int delim;
        !           295:        register int n;
        !           296:        register int over;
        !           297: 
        !           298:        if ((len = bp->wptr - bp->rptr) == sizeof(struct dialin))
        !           299:                return bp;
        !           300:        n = sizeof(struct dialin) - len;
        !           301:        delim = bp->class & S_DELIM;
        !           302: 
        !           303:        if (bp->lim - bp->rptr >= sizeof(struct dialin))
        !           304:                nbp = bp;
        !           305:        else if ((nbp = allocb(sizeof(struct dialin))) == NULL) {
        !           306:                freeb(bp);
        !           307:                return NULL;
        !           308:        } else {
        !           309:                bcopy(bp->rptr, nbp->wptr, len);
        !           310:                nbp->wptr += len;
        !           311:                freeb(bp);
        !           312:        }
        !           313: 
        !           314:        over = 0;
        !           315:        while (!delim && (bp = getq(q))) {
        !           316:                len = bp->wptr - bp->rptr <= n ? bp->wptr - bp->rptr : (over = 1, n);
        !           317:                bcopy(bp->rptr, nbp->wptr, len);
        !           318:                nbp->wptr += len;
        !           319:                n -= len;
        !           320:                delim = bp->class & S_DELIM;
        !           321:                freeb(bp);
        !           322:        }
        !           323:        if (n == 0 && !over && delim)
        !           324:                return nbp;
        !           325:        freeb(nbp);
        !           326:        return NULL;
        !           327: }
        !           328: 
        !           329: /*
        !           330:  * Receive message for listener
        !           331:  */
        !           332: adkisrv(q)
        !           333: register struct queue *q;
        !           334: {
        !           335:        register struct adk *dkp = (struct adk *)WR(q)->ptr;
        !           336:        struct dkmodule *modp = dkp->module;
        !           337:        register struct queue *listnrq = modp->listnrq;
        !           338:        register struct block *bp;
        !           339:        register struct dialin *dialp;
        !           340:        register int i;
        !           341: 
        !           342:        if (WR(q) != modp->listnrq)
        !           343:                return;
        !           344: 
        !           345:        while (bp = getq(q)) {
        !           346:        
        !           347:                switch (*bp->rptr) {
        !           348:        
        !           349:                case T_CALL:
        !           350:                        bp->rptr++;
        !           351:                        if (bp->wptr - bp->rptr <= 0 &&
        !           352:                           ((bp->class & S_DELIM) == 0 || (bp = getq(q)) == NULL))
        !           353:                                return;
        !           354:                        do {
        !           355:                                i = bp->class & S_DELIM;
        !           356:                                if (q->next->flag & QFULL)
        !           357:                                        free(bp);
        !           358:                                else
        !           359:                                        (*q->next->qinfo->putp)(q->next, bp);
        !           360:                        } while (i == 0 && (bp = getq(q)));
        !           361:                        break;
        !           362:                case T_CHG:     
        !           363:                        if ((bp = adkdialin(q, bp)) == NULL)
        !           364:                                break;
        !           365:                        dialp = (struct dialin *)bp->rptr;
        !           366:                        i = dialp->param1;
        !           367:                        if (i <= 0 || i >= modp->hi - modp->lo) {
        !           368:                                dkstat.chgstrange++;
        !           369:                                if (dialp->srv)
        !           370:                                        adkmesg(modp, T_CHG, D_ISCLOSED, 0, i, 0);
        !           371:                                freeb(bp);
        !           372:                                break;
        !           373:                        }
        !           374:                        switch (dialp->srv) {
        !           375:        
        !           376:                        case D_CLOSE:           /* remote shutdown */
        !           377:                                switch (modp->dkstate[i]) {
        !           378:        
        !           379:                                case DKRCLOSE:
        !           380:                                        dkstat.notclosed++;
        !           381:                                case DKOPEN:
        !           382:                                        putctl2(listnrq->next, M_PRICTL, DKMCLOSE, i);
        !           383:                                        break;
        !           384:        
        !           385:                                case DKLCLOSE:
        !           386:                                case DKCLOSED:
        !           387:                                        adkmesg(modp, T_CHG, D_ISCLOSED, 0, i, 0);
        !           388:                                        putctl2(listnrq->next, M_PRICTL, DKMCLOSE, i);
        !           389:                                        break;
        !           390:                                }
        !           391:                                break;
        !           392:                        
        !           393:                        case D_ISCLOSED:
        !           394:                                switch (modp->dkstate[i]) {
        !           395:        
        !           396:                                case DKLCLOSE:
        !           397:                                case DKCLOSED:
        !           398:                                        putctl2(listnrq->next, M_PRICTL, DKMCLOSE, i);
        !           399:                                        break;
        !           400:        
        !           401:                                case DKOPEN:
        !           402:                                case DKRCLOSE:
        !           403:                                        dkstat.isclosed++;
        !           404:                                        break;
        !           405:                                }
        !           406:                                break;
        !           407:        
        !           408:                        case D_ENQ:
        !           409:                                adkmesg(modp, T_CHG, D_ENQANS, 0, i, modp->dkstate[i]);
        !           410:                                break;
        !           411:                        }
        !           412:                        freeb(bp);
        !           413:                        break;
        !           414:        
        !           415:                case T_REPLY:   /* CMC sends reply; find, and hand to process */
        !           416:                        if ((bp = adkdialin(q, bp)) == NULL)
        !           417:                                break;
        !           418:                        dialp = (struct dialin *)bp->rptr;
        !           419:                        i = dialp->param0;
        !           420:                        if (i < 0 || i >= modp->hi - modp->lo) {
        !           421:                                free(bp);
        !           422:                                break;
        !           423:                        }
        !           424:                        for (dkp=adk; dkp<&adk[NDKRAW]; dkp++) {
        !           425:                                if (dkp->module==modp && dkp->chan==i) {
        !           426:                                        bp->class |= S_DELIM;
        !           427:                                        (*dkp->q->next->qinfo->putp)(dkp->q->next, bp);
        !           428:                                        break;
        !           429:                                }
        !           430:                        }
        !           431:                        if (dkp == &adk[NDKRAW])
        !           432:                                free(bp);
        !           433:                        break;
        !           434:        
        !           435:                default:
        !           436:                        free(bp);
        !           437:                        break;
        !           438:                }
        !           439:        }
        !           440: }
        !           441: 
        !           442: /*
        !           443:  * 15-second timer
        !           444:  * -- should look at dkmod->type, so different
        !           445:  * listeners can coexist
        !           446:  */
        !           447: adktimer()
        !           448: {
        !           449:        register i;
        !           450:        register struct dkmodule *dkp;
        !           451: 
        !           452:        for (dkp = dkmod; dkp < &dkmod[dkmodcnt]; dkp++) {
        !           453:                if (dkp->listnrq && dkp->type == CMCLD) {
        !           454:                        adkmesg(dkp, T_LSTNR, 0, 0, 0, 0);
        !           455:                        for (i=dkp->hi - dkp->lo - 1; i >= 0; --i)
        !           456:                                if (dkp->dkstate[i] == DKLCLOSE)
        !           457:                                        adkmesg(dkp, T_CHG, D_CLOSE, 0, i, 0);
        !           458:                }
        !           459:        }
        !           460:        timeout(adktimer, (caddr_t)NULL, 15*HZ);
        !           461: }

unix.superglobalmegacorp.com

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