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