Annotation of researchv10no/sys/io/archosld.c, revision 1.1.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.