Annotation of researchv10no/sys/io/kb.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: /*
                     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.