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

1.1     ! root        1: /*
        !             2:  * simple two-stream kmc datakit driver
        !             3:  * -- assumes it is the first kmc, and only one allowed for now
        !             4:  *     (the latter not severe, as 256 channels are permitted)
        !             5:  */
        !             6: #include "sys/param.h"
        !             7: #include "sys/stream.h"
        !             8: #include "sys/dkio.h"
        !             9: #include "sys/ubaddr.h"
        !            10: #include "sys/conf.h"
        !            11: #include "sys/kb.h"
        !            12: #include "sys/kmc.h"
        !            13: #include "sys/dkstat.h"
        !            14: #include "sys/dkmod.h"
        !            15: 
        !            16: #define        TRACE   0       /* turn on to provoke tracing */
        !            17: 
        !            18: /*
        !            19:  * hardware stuff
        !            20:  */
        !            21: 
        !            22: struct device {
        !            23:        char ctl;       /* control -- written by host */
        !            24:        unsigned char sts;      /* status -- written by device */
        !            25:        short xlo;      /* xmit descriptor, low address */
        !            26:        short rlo;      /* rcv descriptor, low address */
        !            27:        char xhi, rhi;  /* high addresses and flags */
        !            28: };
        !            29: 
        !            30: /*
        !            31:  * control bits
        !            32:  */
        !            33: #define        CXIE    01      /* transmit interrupt enable */
        !            34: #define        CRIE    02      /* receive interrupt enable */
        !            35: 
        !            36: /*
        !            37:  * status bits
        !            38:  */
        !            39: #define        SERROR  0200    /* some error, usually NXM */
        !            40: 
        !            41: /*
        !            42:  * flags in xhi and rhi
        !            43:  */
        !            44: #define        CNOADDR 0200    /* OK to give another descriptor address */
        !            45: #define        CNODESC 0100    /* no descriptor being processed */
        !            46: #define        CXA     014     /* high address bits */
        !            47: #define        CXSHIFT 2       /* shift high bits this much */
        !            48: 
        !            49: /*
        !            50:  * descriptor flags
        !            51:  */
        !            52: #define        DVALID  0200    /* valid descriptor for device */
        !            53: #define        DCHAIN  020     /* `buffer' is a fresh descriptor address */
        !            54: #define        DXA     014     /* high buffer address bits */
        !            55: #define        DSCTL   01      /* first char of buffer is a control char */
        !            56: 
        !            57: #define        DXSHIFT 2       /* shift high addr bits this much */
        !            58: 
        !            59: /*
        !            60:  * per-channel stuff
        !            61:  */
        !            62: struct kb kb[];
        !            63: extern int kbcnt;
        !            64: char   kbstate[];
        !            65: 
        !            66: /*
        !            67:  * kb flags
        !            68:  */
        !            69: #define        DKXCL   01              /* exclusive open */
        !            70: #define        DKXWANT 02              /* output pending this channel */
        !            71: 
        !            72: /*
        !            73:  * per-controller stuff;
        !            74:  * always just one for now
        !            75:  */
        !            76: 
        !            77: struct kbkmc kbkmc[1];
        !            78: #define        KBNO    0       /* always this kb for now */
        !            79: 
        !            80: /*
        !            81:  * kbkmc flags
        !            82:  */
        !            83: #define        INIT    01
        !            84: 
        !            85: /*
        !            86:  * illicit linkage to other datakit code
        !            87:  */
        !            88: 
        !            89: struct dkstat  dkstat;
        !            90: 
        !            91: /*
        !            92:  * illicit linkage to kmc driver
        !            93:  */
        !            94: 
        !            95: extern struct kmc kmc[];
        !            96: extern struct ubaddr kmcaddr[];
        !            97: extern int kmccnt;
        !            98: #define        KNO     0               /* kmc0 is ours, by fiat */
        !            99: 
        !           100: #define        RBSIZE  1024    /* desired receive buffer size */
        !           101: #define        MINRBYTES       4096    /* desired total receive buffer */
        !           102: 
        !           103: #define        XNEXT(i)        ((i)>=XRING-1?0:(i)+1)
        !           104: #define        RNEXT(i)        ((i)>=RRING-1?0:(i)+1)
        !           105: 
        !           106: long kbopen();
        !           107: int kbclose(), kbput(), kbosrv();
        !           108: 
        !           109: static struct qinit kbrinit = { nodev, NULL, kbopen, kbclose, 0, 0 };
        !           110:        struct qinit kbwinit = { kbput, NULL, kbopen, kbclose, 1500, 600 };
        !           111: struct streamtab kbinfo = { &kbrinit, &kbwinit };
        !           112: struct cdevsw kbcdev = cstrinit(&kbinfo);
        !           113: 
        !           114: /*
        !           115:  * open DK channel
        !           116:  */
        !           117: long
        !           118: kbopen(q, dev)
        !           119: register struct queue *q;
        !           120: register dev_t dev;
        !           121: {
        !           122:        register struct kb *dkp;
        !           123:        register struct kbkmc *kk;
        !           124:        register chan;
        !           125: 
        !           126:        chan = minor(dev);
        !           127:        if (chan<=0 || chan>=kbcnt)
        !           128:                return(0);
        !           129:        kk = &kbkmc[KBNO];
        !           130:        if ((kk->flags & INIT) == 0) {
        !           131:                if ((kk->modp = dkmodall(dev, 0, kbcnt)) == NULL)
        !           132:                        return (0);
        !           133:                kk->modp->dkstate = kbstate;
        !           134:                if (kbinit(kk) == 0)
        !           135:                        return (0);
        !           136:                kk->flags |= INIT;
        !           137:        }
        !           138:        dkp = &kb[chan];
        !           139:        if (kbstate[chan] != DKCLOSED) {        /* already open */
        !           140:                if (dkp->flag & DKXCL)
        !           141:                        return(0);
        !           142:                if (kbstate[chan] != DKOPEN)
        !           143:                        return(0);      /* closing channels can't reopen */
        !           144:                return(1);
        !           145:        }
        !           146:        dkp->dkrq = q;
        !           147:        q->ptr = (caddr_t)dkp;
        !           148:        WR(q)->ptr = (caddr_t)dkp;
        !           149:        WR(q)->flag |= QNOENB|QBIGB;
        !           150:        dkp->flag = DKXCL;
        !           151:        dkp->chan = chan;
        !           152:        kbstate[chan] = DKOPEN;
        !           153:        return(1);
        !           154: }
        !           155: 
        !           156: /*
        !           157:  * make sure kmc is alive;
        !           158:  * init data structures once
        !           159:  */
        !           160: kbinit(kk)
        !           161: register struct kbkmc *kk;
        !           162: {
        !           163:        register struct kmc *kp;
        !           164:        struct device *reg;
        !           165:        uaddr_t ua;
        !           166:        extern kbintr(), kbreset();
        !           167: 
        !           168:        kk->kno = KNO;
        !           169:        kk->ubno = kmcaddr[KNO].ubno;   /* cheat */
        !           170:        kp = &kmc[kk->kno];
        !           171:        if ((reg = kp->k_addr) == 0)
        !           172:                return (0);
        !           173:        if ((kk->ringmap = ubmalloc(kk->ubno, sizeof(kk->rings), 0)) == 0) {
        !           174:                printf("kb init no map\n");
        !           175:                return (0);
        !           176:        }
        !           177:        ua = ubmaddr(kk->ubno, (caddr_t)&kk->rings, sizeof(kk->rings), kk->ringmap);
        !           178:        kk->xrua = ua + ((caddr_t)kk->xring - (caddr_t)&kk->rings);
        !           179:        kk->rrua = ua + ((caddr_t)kk->rring - (caddr_t)&kk->rings);
        !           180:        kp->k_rint = kbintr;
        !           181:        kp->k_xint = kbintr;
        !           182:        kp->k_reset = kbreset;
        !           183:        kk->addr = reg;
        !           184:        kbreset(KNO);
        !           185:        return (1);
        !           186: }
        !           187: 
        !           188: /*
        !           189:  * called when, e.g., kmc is reloaded
        !           190:  */
        !           191: kbreset(kno)
        !           192: int kno;
        !           193: {
        !           194:        register struct kbkmc *kk;
        !           195:        register int i;
        !           196:        register struct device *reg;
        !           197: 
        !           198:        kk = &kbkmc[kno];
        !           199:        bzero((caddr_t)&kk->rings, sizeof(kk->rings));
        !           200:        kk->rrp = 0;
        !           201:        kk->rwp = 0;
        !           202:        kk->xrp = 0;
        !           203:        kk->xwp = 0;
        !           204:        for (i = 0; i < XRING; i++) {
        !           205:                if (kk->xmap[i]) {
        !           206:                        ubmfree(kk->ubno, kk->xmap[i]);
        !           207:                        kk->xmap[i] = 0;
        !           208:                }
        !           209:                if (kk->xblock[i]) {
        !           210:                        freeb(kk->xblock[i]);
        !           211:                        kk->xblock[i] = 0;
        !           212:                }
        !           213:        }
        !           214:        kk->xring[XRING].loaddr = kk->xrua;
        !           215:        kk->xring[XRING].flag = DVALID|DCHAIN|((kk->xrua>>16)<<DXSHIFT);
        !           216:        for (i = 0; i < RRING; i++) {
        !           217:                if (kk->rmap[i]) {
        !           218:                        ubmfree(kk->ubno, kk->rmap[i]);
        !           219:                        kk->rmap[i] = 0;
        !           220:                }
        !           221:                if (kk->rblock[i]) {
        !           222:                        freeb(kk->rblock[i]);
        !           223:                        kk->rblock[i] = 0;
        !           224:                }
        !           225:        }
        !           226:        kk->rring[RRING].loaddr = kk->rrua;
        !           227:        kk->rring[RRING].flag = DVALID|DCHAIN|((kk->rrua>>16)<<DXSHIFT);
        !           228:        kk->rbytes = 0;
        !           229:        reg = kk->addr;
        !           230:        reg->ctl = CRIE;
        !           231:        i = spl5();
        !           232:        kbibufs(kk);
        !           233:        reg->rlo = kk->rrua;    /* kk->rring[0] */
        !           234:        reg->rhi = (kk->rrua>>16)<<CXSHIFT;
        !           235:        splx(i);
        !           236: }
        !           237: 
        !           238: /*
        !           239:  * close DK channel
        !           240:  */
        !           241: kbclose(q)
        !           242: register struct queue *q;
        !           243: {
        !           244:        register struct kb *dkp;
        !           245:        register struct kbkmc *kk;
        !           246: 
        !           247:        kk = &kbkmc[KBNO];
        !           248:        dkp = (struct kb *)q->ptr;
        !           249:        if (dkp == NULL)
        !           250:                panic("kbclose");
        !           251:        dkp->dkrq = NULL;
        !           252:        dkp->flag = 0;
        !           253:        if (kbstate[dkp->chan] == DKRCLOSE || kk->modp->listnrq==NULL)
        !           254:                kbstate[dkp->chan] = DKCLOSED;
        !           255:        else if (kbstate[dkp->chan] == DKOPEN)
        !           256:                kbstate[dkp->chan] = DKLCLOSE;
        !           257:        if (kk->modp->listnrq)
        !           258:                putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan);
        !           259: }
        !           260: 
        !           261: /*
        !           262:  * interrupt
        !           263:  * receive any blocks that have arrived;
        !           264:  * reload receive buffers;
        !           265:  * clean up finished transmit buffers
        !           266:  * restart receiver or transmitter if needed
        !           267:  */
        !           268: 
        !           269: int kbxrst;            /* debugging count */
        !           270: int kbxnst;            /* debugging count */
        !           271: 
        !           272: kbintr(dev)
        !           273: {
        !           274:        register struct kbkmc *kk;
        !           275:        register struct device *reg;
        !           276:        register int i;
        !           277:        register uaddr_t ua;
        !           278: 
        !           279:        kk = &kbkmc[dev];
        !           280:        if ((reg = kk->addr) == NULL)
        !           281:                return;
        !           282: #if NOTDEF     /* straighten out protocol */
        !           283:        i = reg->sts;
        !           284:        if (i & SERROR) {
        !           285:                reg->sts = 0;
        !           286:                printf("kb sts %o\n", i);
        !           287:        }
        !           288: #endif
        !           289:        for (i = kk->rrp; i != kk->rwp; i = RNEXT(i)) {
        !           290:                if (kk->rring[i].flag & DVALID)
        !           291:                        break;
        !           292:                kbrcv(kk, i);
        !           293:        }
        !           294:        if (kk->rbytes < MINRBYTES)
        !           295:                kbibufs(kk);
        !           296:        if ((reg->rhi & (CNOADDR|CNODESC)) == (CNOADDR|CNODESC)) {
        !           297:                /*
        !           298:                 * receiver has stopped, but may have finished
        !           299:                 * another block or two since the loop above
        !           300:                 */
        !           301:                for (; i != kk->rwp; i = RNEXT(i)) {
        !           302:                        if (kk->rring[i].flag & DVALID)
        !           303:                                break;
        !           304:                        kbrcv(kk, i);
        !           305:                }
        !           306:                if (kk->rbytes < MINRBYTES)
        !           307:                        kbibufs(kk);
        !           308:                if (kk->rwp != i) {     /* safety check */
        !           309:                        ua = kk->rrua + i * sizeof(struct kbdesc);
        !           310:                        reg->rlo = ua;
        !           311:                        reg->rhi = (ua>>16)<<CXSHIFT;
        !           312:                }
        !           313:        }
        !           314:        kk->rrp = i;
        !           315:        i = reg->xhi;
        !           316:        if (kk->xrp != kk->xwp)
        !           317:                kbxscan(kk);
        !           318:        if ((i & (CNOADDR|CNODESC)) == (CNOADDR|CNODESC)
        !           319:        &&  kk->xrp != kk->xwp) {
        !           320:                ua = kk->xrua + kk->xrp * sizeof(struct kbdesc);
        !           321:                reg->xlo = ua;
        !           322:                reg->xhi = (ua>>16)<<CXSHIFT;
        !           323:                kbxrst++;
        !           324:        }
        !           325: }
        !           326: 
        !           327: /*
        !           328:  * receive a block
        !           329:  */
        !           330: kbrcv(kk, i)
        !           331: register struct kbkmc *kk;
        !           332: register int i;
        !           333: {
        !           334:        register struct kbdesc *dxp;
        !           335:        register struct queue *q;
        !           336:        register int chan;
        !           337:        register struct block *bp;
        !           338:        struct block *xbp;
        !           339: 
        !           340:        dxp = &kk->rring[i];
        !           341: #if TRACE
        !           342:        trace('i', (i<<24)|(dxp->chan<<16)|dxp->flag, -dxp->len,
        !           343:                *(int *)(kk->rblock[i]->rptr));
        !           344: #endif
        !           345:        if (kk->rmap[i] == 0)
        !           346:                panic("kbrcv");
        !           347:        ubmfree(kk->ubno, kk->rmap[i]);
        !           348:        kk->rmap[i] = 0;
        !           349:        bp = kk->rblock[i];
        !           350:        kk->rblock[i] = NULL;
        !           351:        kk->rbytes -= bp->lim - bp->wptr;
        !           352:        bp->wptr = bp->lim + dxp->len;  /* negative residual length */
        !           353:        if (dxp->flag & DSCTL) {
        !           354:                /*
        !           355:                 * special hack to save big blocks
        !           356:                 */
        !           357:                if (bp->wptr == bp->rptr + 1
        !           358:                &&  (xbp = allocb(1)) != NULL) {
        !           359:                        *xbp->wptr++ = *bp->rptr;
        !           360:                        freeb(bp);
        !           361:                        bp = xbp;
        !           362:                }
        !           363:                bp->type = M_CTL;
        !           364:        }
        !           365:        if (bp->wptr <= bp->base || bp->wptr > bp->lim) {
        !           366:                printf("kb ch%d bad len %d\n", dxp->chan, -dxp->len);
        !           367:                freeb(bp);
        !           368:                return;
        !           369:        }
        !           370:        chan = dxp->chan;
        !           371:        if (chan == 0 || chan >= kbcnt || (q = kb[chan].dkrq) == NULL) {
        !           372:                if (chan == 0)
        !           373:                        dkstat.pack0++;
        !           374:                else if (chan >= kbcnt)
        !           375:                        dkstat.packstrange++;
        !           376:                else
        !           377:                        dkstat.closepack++;
        !           378:                freeb(bp);
        !           379:                return;
        !           380:        }
        !           381:        dkstat.input += bp->wptr - bp->rptr;
        !           382:        if ((q->next->flag & QFULL) == 0)
        !           383:                (*q->next->qinfo->putp)(q->next, bp);
        !           384:        else
        !           385:                freeb(bp);
        !           386: }
        !           387: 
        !           388: /*
        !           389:  * refresh our supply of input buffers
        !           390:  */
        !           391: kbibufs(kk)
        !           392: register struct kbkmc *kk;
        !           393: {
        !           394:        register struct block *bp;
        !           395:        register int i;
        !           396:        register struct kbdesc *dxp;
        !           397:        register uaddr_t ua;
        !           398: 
        !           399:        i = kk->rwp;
        !           400:        while (kk->rbytes < MINRBYTES) {
        !           401:                if (RNEXT(i) == kk->rrp)        /* all descriptors used */
        !           402:                        break;
        !           403:                if ((bp = allocb(RBSIZE)) == NULL)
        !           404:                        break;
        !           405:                if ((kk->rmap[i] = ubmblk(kk->ubno, bp, 0)) == 0) {
        !           406:                        printf("kb no rcv map\n");
        !           407:                        freeb(bp);
        !           408:                        break;
        !           409:                }
        !           410:                kk->rblock[i] = bp;
        !           411:                ua = ubadrptr(kk->ubno, bp, kk->rmap[i]);
        !           412:                dxp = &kk->rring[i];
        !           413:                dxp->loaddr = ua;
        !           414:                dxp->len = bp->wptr - bp->lim;  /* negative length */
        !           415:                dxp->flag = ((ua>>16)<<DXSHIFT)|DVALID;
        !           416:                kk->rbytes += bp->lim - bp->wptr;
        !           417:                i = RNEXT(i);
        !           418:        }
        !           419:        kk->rwp = i;
        !           420: }
        !           421: 
        !           422: /*
        !           423:  * put procedure for output
        !           424:  */
        !           425: kbput(q, bp)
        !           426: struct queue *q;
        !           427: register struct block *bp;
        !           428: {
        !           429:        register struct kb *dkp;
        !           430:        register struct kbkmc *kk;
        !           431:        register int i;
        !           432:        register struct device *reg;
        !           433:        register struct kbdesc *dxp;
        !           434:        uaddr_t ua;
        !           435:        int s;
        !           436: 
        !           437:        dkp = (struct kb *)q->ptr;
        !           438:        kk = &kbkmc[KBNO];
        !           439:        switch (bp->type) {
        !           440: 
        !           441:        case M_IOCTL:
        !           442:                switch (stiocom(bp)) {
        !           443:                case DIOCNXCL:
        !           444:                        dkp->flag &=~ DKXCL;
        !           445:                        bp->wptr = bp->rptr;
        !           446:                        bp->type = M_IOCACK;
        !           447:                        break;
        !           448: 
        !           449:                case KIOCINIT:
        !           450:                        /* eventually, reset things here */
        !           451: 
        !           452:                default:
        !           453:                        bp->type = M_IOCNAK;
        !           454:                        break;
        !           455:                }
        !           456:                qreply(q, bp);
        !           457:                return;
        !           458: 
        !           459:        case M_CTL:
        !           460:        case M_DATA:
        !           461:                if (bp->rptr == bp->wptr) {
        !           462:                        freeb(bp);
        !           463:                        return;
        !           464:                }
        !           465:                s = spl5();
        !           466:                i = kk->xwp - kk->xrp;
        !           467:                if (i < 0)
        !           468:                        i += XRING;
        !           469:                if (i > XRING/2)
        !           470:                        kbxscan(kk);
        !           471:                if (XNEXT(kk->xwp) == kk->xrp) {        /* no desc available? */
        !           472:                        splx(s);
        !           473:                        printf("kb xmt ch%d lost block\n", dkp->chan);
        !           474:                        freeb(bp);
        !           475:                        return;
        !           476:                }
        !           477:                i = kk->xwp;
        !           478:                kk->xwp = XNEXT(i);
        !           479:                if ((kk->xmap[i] = ubmblk(kk->ubno, bp, 0)) == 0) {
        !           480:                        splx(s);
        !           481:                        printf("kb xmt ch%d no map\n", dkp->chan);
        !           482:                        freeb(bp);
        !           483:                        return;
        !           484:                }
        !           485: #if TRACE
        !           486:                trace('x', (i<<24)|(dkp->chan<<16)|bp->type, bp->wptr - bp->rptr,
        !           487:                        *(int *)bp->rptr);
        !           488: #endif
        !           489:                kk->xblock[i] = bp;
        !           490:                ua = ubadrptr(kk->ubno, bp, kk->xmap[i]);
        !           491:                dxp = &kk->xring[i];
        !           492:                dxp->loaddr = ua;
        !           493:                dxp->len = bp->rptr - bp->wptr; /* negative length */
        !           494:                dxp->chan = dkp->chan;
        !           495:                dxp->flag = (ua>>16)<<DXSHIFT;
        !           496:                if (bp->type != M_DATA)
        !           497:                        dxp->flag |= DSCTL;
        !           498:                reg = kk->addr;
        !           499:                dxp->flag |= DVALID;
        !           500:                if ((reg->xhi & (CNOADDR|CNODESC)) == (CNOADDR|CNODESC)) {
        !           501:                        if (i != kk->xrp)
        !           502:                                kbxscan(kk);
        !           503:                        if (kk->xwp != kk->xrp) {       /* maybe it finished it off -- unlikely */
        !           504:                                ua = kk->xrua + kk->xrp * sizeof(struct kbdesc);
        !           505:                                reg->xlo = ua;
        !           506:                                reg->xhi = ((ua>>16)<<CXSHIFT);
        !           507:                        }
        !           508:                }
        !           509:                else    /* debug */
        !           510:                        kbxnst++;       /* debug */
        !           511:                dkstat.output += bp->wptr - bp->rptr;
        !           512:                splx(s);
        !           513:                return;
        !           514: 
        !           515:        case M_PRICTL:
        !           516:                switch (*bp->rptr) {
        !           517:                case DKMCLOSE:
        !           518:                        i = bp->rptr[1];
        !           519:                        if (i < kbcnt) {
        !           520:                                if (kbstate[i] == DKOPEN) {
        !           521:                                        kbstate[i] = DKRCLOSE;
        !           522:                                        putctl(kb[i].dkrq->next, M_HANGUP);
        !           523:                                } else if (kbstate[i] == DKLCLOSE)
        !           524:                                        kbstate[i] = DKCLOSED;
        !           525:                        }
        !           526:                        freeb(bp);
        !           527:                        return;
        !           528: 
        !           529:                case DKMXINIT:
        !           530:                        i = bp->rptr[1];
        !           531:                        if (i < kbcnt && kbstate[i] == DKOPEN)
        !           532:                                (*kb[i].dkrq->next->qinfo->putp)(kb[i].dkrq->next, bp);
        !           533:                        else
        !           534:                                freeb(bp);
        !           535:                        return;                         
        !           536: 
        !           537:                default:
        !           538:                        freeb(bp);
        !           539:                        return;
        !           540:                }
        !           541: 
        !           542:        default:
        !           543:                freeb(bp);
        !           544:                return;
        !           545:        }
        !           546: }
        !           547: 
        !           548: /*
        !           549:  * clean up finished transmit buffers
        !           550:  * call at spl5
        !           551:  */
        !           552: 
        !           553: kbxscan(kk)
        !           554: register struct kbkmc *kk;
        !           555: {
        !           556:        register int i;
        !           557: 
        !           558:        for (i = kk->xrp; i != kk->xwp; i = XNEXT(i)) {
        !           559:                if (kk->xring[i].flag & DVALID)
        !           560:                        break;
        !           561:                if (kk->xblock[i] == NULL)
        !           562:                        panic("kbxscan");
        !           563:                ubmfree(kk->ubno, kk->xmap[i]);
        !           564:                kk->xmap[i] = 0;
        !           565:                freeb(kk->xblock[i]);
        !           566:                kk->xblock[i] = NULL;
        !           567:        }
        !           568:        kk->xrp = i;
        !           569: }

unix.superglobalmegacorp.com

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