Annotation of researchv10dc/sys/io/kb.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: /*
        !            17:  * hardware stuff
        !            18:  */
        !            19: 
        !            20: struct device {
        !            21:        short   sts;    /* written by KMC */
        !            22:        short   cmd;    /* command and transmit chan -- written by host */
        !            23:        short   ba;     /* low bus address -- written by host */
        !            24:        short   bc;     /* negative buffer size -- written by host */
        !            25: };
        !            26: 
        !            27: /*
        !            28:  * status info
        !            29:  */
        !            30: #define        SCOUNT  0xfff   /* receive buffer resid count */
        !            31: #define        SRRDY   (020<<8)        /* receive ready */
        !            32: #define        SOK     (040<<8)        /* init ok */
        !            33: #define        SERROR  (0100<<8)       /* transfer or other error */
        !            34: #define        SXRDY   (0200<<8)       /* transmit ready */
        !            35: 
        !            36: /*
        !            37:  * commands
        !            38:  */
        !            39: #define        CGO     (01<<8)         /* turned off when command read */
        !            40: #define        CRCV    (01<<8)         /* here is a receive buffer */
        !            41: #define        CSEND   (03<<8)         /* send this buffer of data */
        !            42: #define        CSCTL   (043<<8)        /* send this data, first char is ctl */
        !            43: #define        CIE     (020<<8)        /* interrupt after this command */
        !            44: #define        CXA     (014<<8)        /* high address bits */
        !            45: #define        XASHIFT 10              /* shift high address bits this much */
        !            46: 
        !            47: #define        STALL   10000           /* max time to stall waiting for ready */
        !            48: /*
        !            49:  * per-channel stuff
        !            50:  */
        !            51: extern struct kb kb[];
        !            52: extern int kbcnt;
        !            53: extern char kbstate[];
        !            54: 
        !            55: /*
        !            56:  * kb flags
        !            57:  */
        !            58: #define        DKXCL   01              /* exclusive open */
        !            59: #define        DKXWANT 02              /* output pending this channel */
        !            60: 
        !            61: /*
        !            62:  * per-controller stuff;
        !            63:  * always just one for now
        !            64:  */
        !            65: 
        !            66: struct kbkmc kbkmc[1];
        !            67: #define        KBNO    0       /* always this kb for now */
        !            68: 
        !            69: /*
        !            70:  * kbkmc flags
        !            71:  */
        !            72: #define        INIT    01
        !            73: 
        !            74: /*
        !            75:  * illicit linkage to other datakit code
        !            76:  */
        !            77: 
        !            78: struct dkstat  dkstat;
        !            79: 
        !            80: /*
        !            81:  * illicit linkage to kmc driver
        !            82:  */
        !            83: 
        !            84: extern struct kmc kmc[];
        !            85: extern struct ubaddr kmcaddr[];
        !            86: extern int kmccnt;
        !            87: #define        KNO     0               /* kmc0 is ours, by fiat */
        !            88: 
        !            89: #define        DKISIZE 1024            /* preferred input buffer size */
        !            90: #define        MAXOBUF 4096            /* max allowed output buffer -- for unibus map */
        !            91: 
        !            92: long kbopen();
        !            93: int kbclose(), kbput(), kbosrv();
        !            94: 
        !            95: static struct qinit kbrinit = { nodev, NULL, kbopen, kbclose, 0, 0 };
        !            96:        struct qinit kbwinit = { kbput, NULL, kbopen, kbclose, 1500, 600 };
        !            97: struct streamtab kbinfo = { &kbrinit, &kbwinit };
        !            98: struct cdevsw kbcdev = cstrinit(&kbinfo);
        !            99: 
        !           100: /*
        !           101:  * open DK channel
        !           102:  */
        !           103: long
        !           104: kbopen(q, dev)
        !           105: register struct queue *q;
        !           106: register dev_t dev;
        !           107: {
        !           108:        register struct kb *dkp;
        !           109:        register struct kbkmc *kk;
        !           110:        register chan;
        !           111: 
        !           112:        chan = minor(dev);
        !           113:        if (chan<=0 || chan>=kbcnt)
        !           114:                return(0);
        !           115:        kk = &kbkmc[KBNO];
        !           116:        if ((kk->flags & INIT) == 0) {
        !           117:                if ((kk->modp = dkmodall(dev, 0, kbcnt)) == NULL)
        !           118:                        return (0);
        !           119:                kk->modp->dkstate = kbstate;
        !           120:                if (kbinit(kk) == 0)
        !           121:                        return (0);
        !           122:                kk->flags |= INIT;
        !           123:        }
        !           124:        dkp = &kb[chan];
        !           125:        if (kbstate[chan] != DKCLOSED) {        /* already open */
        !           126:                if (dkp->flag & DKXCL)
        !           127:                        return(0);
        !           128:                if (kbstate[chan] != DKOPEN)
        !           129:                        return(0);      /* closing channels can't reopen */
        !           130:                return(1);
        !           131:        }
        !           132:        dkp->dkrq = q;
        !           133:        q->ptr = (caddr_t)dkp;
        !           134:        WR(q)->ptr = (caddr_t)dkp;
        !           135:        WR(q)->flag |= QNOENB|QBIGB;
        !           136:        dkp->flag = DKXCL;
        !           137:        dkp->chan = chan;
        !           138:        kbstate[chan] = DKOPEN;
        !           139:        return(1);
        !           140: }
        !           141: 
        !           142: /*
        !           143:  * make sure kmc is alive;
        !           144:  * init data structures once
        !           145:  */
        !           146: kbinit(kk)
        !           147: register struct kbkmc *kk;
        !           148: {
        !           149:        register struct kmc *kp;
        !           150:        register struct device *reg;
        !           151:        register int i;
        !           152:        extern kbintr(), kbreset();
        !           153: 
        !           154:        kk->kno = KNO;
        !           155:        kk->ubno = kmcaddr[KNO].ubno;   /* cheat */
        !           156:        kp = &kmc[kk->kno];
        !           157:        if ((reg = kp->k_addr) == 0)
        !           158:                return (0);
        !           159:        if ((reg->sts & SOK) == 0)
        !           160:                return (0);
        !           161:        if ((kk->omap = ubmalloc(kk->ubno, MAXOBUF, UBDP)) == 0)
        !           162:                return (0);
        !           163:        kp->k_rint = kbintr;
        !           164:        kp->k_xint = kbintr;
        !           165:        kp->k_reset = kbreset;
        !           166:        kk->addr = reg;
        !           167:        i = spl5();
        !           168:        kbistart(kk);
        !           169:        splx(i);
        !           170:        return (1);
        !           171: }
        !           172: 
        !           173: /*
        !           174:  * called when, e.g., kmc is reloaded
        !           175:  */
        !           176: kbreset(kno)
        !           177: int kno;
        !           178: {
        !           179:        register struct kbkmc *kk;
        !           180:        register int s;
        !           181: 
        !           182:        kk = &kbkmc[KNO];
        !           183:        if (kk->obuf) {
        !           184:                freeb(kk->obuf);
        !           185:                kk->obuf = NULL;
        !           186:        }
        !           187:        if (kk->imap) {
        !           188:                ubmfree(kk->ubno, kk->imap);
        !           189:                kk->imap = 0;
        !           190:        }
        !           191:        if (kk->ibuf) {
        !           192:                freeb(kk->ibuf);
        !           193:                kk->ibuf = NULL;
        !           194:        }
        !           195:        s = spl5();
        !           196:        kbistart(kk);
        !           197:        splx(s);
        !           198: }
        !           199: 
        !           200: /*
        !           201:  * close DK channel
        !           202:  */
        !           203: kbclose(q)
        !           204: register struct queue *q;
        !           205: {
        !           206:        register struct kb *dkp;
        !           207:        register struct kbkmc *kk;
        !           208: 
        !           209:        kk = &kbkmc[KBNO];
        !           210:        dkp = (struct kb *)q->ptr;
        !           211:        if (dkp == NULL)
        !           212:                panic("kbclose");
        !           213:        dkp->dkrq = NULL;
        !           214:        dkp->flag = 0;
        !           215:        if (kbstate[dkp->chan] == DKRCLOSE || kk->modp->listnrq==NULL)
        !           216:                kbstate[dkp->chan] = DKCLOSED;
        !           217:        else if (kbstate[dkp->chan] == DKOPEN)
        !           218:                kbstate[dkp->chan] = DKLCLOSE;
        !           219:        if (kk->modp->listnrq)
        !           220:                putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan);
        !           221: }
        !           222: 
        !           223: /*
        !           224:  * interrupt -- receiver only
        !           225:  * try to short-circuit interrupts;
        !           226:  * data often comes in a large piece, followed by two small ones (URP trailer)
        !           227:  */
        !           228: 
        !           229: kbintr(dev)
        !           230: {
        !           231:        register struct kbkmc *kk;
        !           232:        register struct block *bp;
        !           233:        register struct queue *q;
        !           234:        register int i;
        !           235: 
        !           236:        kk = &kbkmc[KBNO];
        !           237:        if (kk->addr == NULL)
        !           238:                return;
        !           239:        i = kk->addr->sts;
        !           240:        if ((bp = kk->ibuf) == NULL) {  /* shouldn't happen */
        !           241:                kbistart(kk);
        !           242:                return;
        !           243:        }
        !           244:        ubmfree(kk->ubno, kk->imap);
        !           245:        kk->ibuf = NULL;
        !           246:        kbistart(kk);
        !           247:        i |= ~SCOUNT;   /* crypto-sign-extend */
        !           248:        if ((i & SCOUNT) == 0)
        !           249:                i = 0;  /* overflow just means buffer full */
        !           250:        bp->wptr = bp->lim + i;         /* lim - residue */
        !           251:        i = *bp->rptr;                  /* channel */
        !           252:        bp->rptr++;
        !           253:        if (*bp->rptr)                  /* ctl flag */
        !           254:                bp->type = M_CTL;
        !           255:        bp->rptr++;
        !           256:        if (i == 0 || i >= kbcnt || (q = kb[i].dkrq) == NULL) {
        !           257:                if (i == 0)
        !           258:                        dkstat.pack0++;
        !           259:                else if (i >= kbcnt)
        !           260:                        dkstat.packstrange++;
        !           261:                else
        !           262:                        dkstat.closepack++;
        !           263:                freeb(bp);
        !           264:                return;
        !           265:        }
        !           266:        dkstat.input += bp->wptr - bp->rptr;
        !           267:        if ((q->next->flag & QFULL) == 0)
        !           268:                (*q->next->qinfo->putp)(q->next, bp);
        !           269:        else
        !           270:                freeb(bp);
        !           271: }
        !           272: 
        !           273: /*
        !           274:  * start the next input buffer
        !           275:  */
        !           276: kbistart(kk)
        !           277: register struct kbkmc *kk;
        !           278: {
        !           279:        register struct device *reg;
        !           280:        register int sts;
        !           281:        register struct block *bp;
        !           282:        register int n;
        !           283:        register uaddr_t ua;
        !           284: 
        !           285:        if ((reg = kk->addr) == NULL)
        !           286:                return;
        !           287:        if (kk->ibuf)
        !           288:                return;
        !           289:        for (sts = 0, n = 0; n < STALL; n++) {
        !           290:                if ((reg->cmd & CGO) == 0
        !           291:                &&  (sts = reg->sts) & SRRDY)
        !           292:                        break;
        !           293:                /* delay to free up unibus? */
        !           294:        }
        !           295:        if ((sts & SRRDY) == 0) {
        !           296:                printf("kb rcv not ready, sts %o cmd %o\n", reg->sts, reg->cmd);
        !           297:                panic("kbistart");
        !           298:                return;
        !           299:        }
        !           300:        if (sts & SERROR)
        !           301:                printf("kb err, sts %o\n", sts&0177777);
        !           302:        if ((bp = allocb(DKISIZE)) == NULL
        !           303:        ||  (kk->imap = ubmblk(kk->ubno, bp, 0)) == 0) {
        !           304:                panic("kbistart can't alloc\n");        /* later printf */
        !           305:                if (bp)
        !           306:                        freeb(bp);
        !           307:                return;
        !           308:        }
        !           309:        kk->ibuf = bp;
        !           310:        if ((int)bp->rptr & 01)
        !           311:                bp->rptr++;
        !           312:        kk->iaddr = ua = ubadrptr(kk->ubno, bp, kk->imap);
        !           313:        reg->bc = bp->rptr - bp->lim;   /* sic - negative count */
        !           314:        reg->ba = ua;
        !           315:        n = (ua >> 16) << XASHIFT;
        !           316:        n &= CXA;
        !           317:        n |= CIE|CRCV;
        !           318:        reg->cmd = n;
        !           319: }
        !           320: 
        !           321: /*
        !           322:  * put procedure for output
        !           323:  */
        !           324: kbput(q, bp)
        !           325: struct queue *q;
        !           326: register struct block *bp;
        !           327: {
        !           328:        register struct kb *dkp;
        !           329:        register struct kbkmc *kk;
        !           330:        register int n;
        !           331:        register struct device *reg;
        !           332:        register int sts;
        !           333:        int s;
        !           334: 
        !           335:        dkp = (struct kb *)q->ptr;
        !           336:        kk = &kbkmc[KBNO];
        !           337:        switch (bp->type) {
        !           338: 
        !           339:        case M_IOCTL:
        !           340:                switch (stiocom(bp)) {
        !           341:                case DIOCNXCL:
        !           342:                        dkp->flag &=~ DKXCL;
        !           343:                        bp->wptr = bp->rptr;
        !           344:                        bp->type = M_IOCACK;
        !           345:                        break;
        !           346: 
        !           347:                case KIOCINIT:
        !           348:                        /* eventually, reset things here */
        !           349: 
        !           350:                default:
        !           351:                        bp->type = M_IOCNAK;
        !           352:                        break;
        !           353:                }
        !           354:                qreply(q, bp);
        !           355:                return;
        !           356: 
        !           357:        case M_CTL:
        !           358:        case M_DATA:
        !           359:                if (bp->rptr == bp->wptr) {
        !           360:                        freeb(bp);
        !           361:                        return;
        !           362:                }
        !           363:                dkstat.output += bp->wptr - bp->rptr;
        !           364:                s = spl5();
        !           365:                reg = kk->addr;
        !           366:                for (sts = 0, n = 0; n < STALL; n++) {
        !           367:                        if ((reg->cmd & CGO) == 0
        !           368:                        &&  (sts = reg->sts) & SXRDY)
        !           369:                                break;
        !           370:                        DELAY(40);      /* get off the UNIBUS */
        !           371:                }
        !           372:                if ((sts & SXRDY) == 0) {       /* n >= STALL */
        !           373:                        printf("kb xmit not ready, sts %o, cmd %o\n", sts, reg->cmd);
        !           374:                        splx(s);
        !           375:                        freeb(bp);
        !           376:                        return;
        !           377:                }
        !           378:                if (sts & SERROR)
        !           379:                        printf("kb err, sts %o\n", sts&0177777);
        !           380:                ubmflush(kk->ubno, ubmpath(kk->omap));
        !           381:                if (kk->obuf) {
        !           382:                        freeb(kk->obuf);
        !           383:                        kk->obuf = NULL;
        !           384:                }
        !           385:                n = bp->wptr - bp->rptr;
        !           386:                kk->oaddr = ubmaddr(kk->ubno, bp->rptr, n, kk->omap);
        !           387:                reg->bc = -n;
        !           388:                reg->ba = kk->oaddr;
        !           389:                n = (kk->oaddr >> 16)<<XASHIFT;
        !           390:                n &= CXA;
        !           391:                n |= dkp->chan;
        !           392:                if (bp->type == M_DATA)
        !           393:                        n |= CSEND;
        !           394:                else
        !           395:                        n |= CSCTL;
        !           396:                reg->cmd = n;
        !           397:                kk->obuf = bp;
        !           398:                splx(s);
        !           399:                return;
        !           400: 
        !           401:        case M_PRICTL:
        !           402:                switch (*bp->rptr) {
        !           403:                case DKMCLOSE:
        !           404:                        n = bp->rptr[1];
        !           405:                        if (n < kbcnt) {
        !           406:                                if (kbstate[n] == DKOPEN) {
        !           407:                                        kbstate[n] = DKRCLOSE;
        !           408:                                        putctl(kb[n].dkrq->next, M_HANGUP);
        !           409:                                } else if (kbstate[n] == DKLCLOSE)
        !           410:                                        kbstate[n] = DKCLOSED;
        !           411:                        }
        !           412:                        freeb(bp);
        !           413:                        return;
        !           414: 
        !           415:                case DKMXINIT:
        !           416:                        n = bp->rptr[1];
        !           417:                        if (n < kbcnt && kbstate[n] == DKOPEN)
        !           418:                                (*kb[n].dkrq->next->qinfo->putp)(kb[n].dkrq->next, bp);
        !           419:                        else
        !           420:                                freeb(bp);
        !           421:                        return;                         
        !           422: 
        !           423:                default:
        !           424:                        freeb(bp);
        !           425:                        return;
        !           426:                }
        !           427: 
        !           428:        default:
        !           429:                freeb(bp);
        !           430:                return;
        !           431:        }
        !           432: }

unix.superglobalmegacorp.com

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