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

1.1     ! root        1: /*
        !             2:  * simple CURE datakit driver
        !             3:  * -- assumes it is the first CURE, 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/kc.h"
        !            12: #include "sys/dkstat.h"
        !            13: #include "sys/dkmod.h"
        !            14: #include "sys/buf.h"
        !            15: 
        !            16: /*
        !            17:  * hardware stuff
        !            18:  */
        !            19: struct device {
        !            20:        unsigned short  buf;
        !            21:        unsigned char   csr;
        !            22:        char    fill1;
        !            23:        short   fill2;
        !            24:        char    reset;
        !            25: };
        !            26: 
        !            27: /*
        !            28:  * status bits
        !            29:  */
        !            30: #define        SSEQ    01      /* 1-bit command sequence # */
        !            31: #define        SRRDY   02      /* receive ready */
        !            32: #define        SXRDY   04      /* transmit ready */
        !            33: #define        SUBERR  010     /* unibus error */
        !            34: #define        SERR    020     /* protocol error */
        !            35: #define        STATE   0300    /* booting state mask... */
        !            36: #define        SOK     0200     /* ready for real IO */
        !            37: #define        SBOOT   0100     /* ready for download (just been reset) */
        !            38: #define        SBOOTING 0       /* in middle of download */
        !            39: #define        SRESET  0300     /* finished download, must reset UB base, vector */
        !            40: 
        !            41: /*
        !            42:  * command bits
        !            43:  */
        !            44: #define        CSEND   02              /* send */
        !            45: #define        CSETB   03              /* announce location of control buffers */
        !            46: #define        CRCV    04              /* receive */
        !            47: #define        CBA     06              /* set bus address */
        !            48: #define        CBC     010             /* set buffer count */
        !            49: #define        CINTR   012             /* set vector address */
        !            50: #define        CRESET  014             /* reset interface */
        !            51: #define        CIACK   016             /* ack interrupt or reset */
        !            52: 
        !            53: #define        CXA     0140            /* high address bits */
        !            54: #define        XASHIFT 11              /* shift high address bits this much */
        !            55: 
        !            56: typedef short Env;             /* datakit envelope in our buffers */
        !            57: 
        !            58: /*
        !            59:  * bits in transmit buffer
        !            60:  */
        !            61: #define        XDATA   0400            /* data, not control */
        !            62: 
        !            63: /*
        !            64:  * bits in receive buffer
        !            65:  */
        !            66: #define        RMARK   01000           /* channel mark */
        !            67: #define        RDATA   0400            /* this is data */
        !            68: #define        RSPCL   0100000         /* special (sign bit): mark or control */
        !            69: #define        REOT    (RSPCL|RMARK)   /* end of receive buffer, if short */
        !            70: 
        !            71: /*
        !            72:  * per-channel stuff
        !            73:  */
        !            74: #define        NCHAN   256
        !            75: struct kc kc[NCHAN];
        !            76: int    kccnt = NCHAN;
        !            77: char   kcstate[NCHAN];
        !            78: 
        !            79: /*
        !            80:  * kc flags
        !            81:  */
        !            82: #define        DKXCL   01              /* exclusive open */
        !            83: #define        DKXWANT 02              /* output pending this channel */
        !            84: 
        !            85: /*
        !            86:  * per-controller stuff;
        !            87:  * always just one for now
        !            88:  */
        !            89: 
        !            90: extern struct ubaddr cureaddr[];
        !            91: struct kccure kccure[1];
        !            92: #define        KBNO    0       /* always this kc for now */
        !            93: int    kcxfirst;
        !            94: int    kcxnext;
        !            95: int    kcrfirst;
        !            96: int    kcrnext;
        !            97: 
        !            98: /*
        !            99:  * kccure flags
        !           100:  */
        !           101: #define        XBUSY   01      /* transmit busy */
        !           102: #define        XWANT   02      /* output needed */
        !           103: #define        INIT    04
        !           104: 
        !           105: /*
        !           106:  * illicit linkage to other datakit code
        !           107:  */
        !           108: 
        !           109: struct dkstat  dkstat;
        !           110: 
        !           111: #define        KNO     0
        !           112: 
        !           113: #define        DKISML  16      /* smallest interesting allocation */
        !           114: #define        DKITHRES 200
        !           115: 
        !           116: long kcopen();
        !           117: int kcclose(), kcput(), kcosrv();
        !           118: 
        !           119: static struct qinit kcrinit = { noput, NULL, kcopen, kcclose, 0, 0 };
        !           120:        struct qinit kcwinit = { kcput, kcosrv, kcopen, kcclose, 1500, 600 };
        !           121: struct streamtab kcinfo = { &kcrinit, &kcwinit };
        !           122: struct cdevsw curecdev = cstrinit(&kcinfo);
        !           123: 
        !           124: static kclastseq;
        !           125: 
        !           126: /*
        !           127:  * open DK channel
        !           128:  */
        !           129: long
        !           130: kcopen(q, dev)
        !           131: register struct queue *q;
        !           132: register dev_t dev;
        !           133: {
        !           134:        register struct kc *dkp;
        !           135:        register struct kccure *kk;
        !           136:        register chan;
        !           137:        extern struct dkmodule *dkmodall();
        !           138:        int kcclock();
        !           139: 
        !           140:        chan = minor(dev);
        !           141:        if (chan<=0 || chan>=kccnt)
        !           142:                return(0);
        !           143:        kk = &kccure[KBNO];
        !           144:        if ((kk->flags & INIT) == 0) {
        !           145:                if ((kk->modp = dkmodall(dev, 0, kccnt)) == NULL)
        !           146:                        return (0);
        !           147:                kk->modp->dkstate = kcstate;
        !           148:                if (kcinit(kk, 1) == 0)
        !           149:                        return (0);
        !           150:                kk->flags |= INIT;
        !           151:                timeout(kcclock, (caddr_t)minor(dev), 10*HZ);
        !           152:        }
        !           153:        dkp = &kc[chan];
        !           154:        if (kcstate[chan] != DKCLOSED) {        /* already open */
        !           155:                if (dkp->flag & DKXCL)
        !           156:                        return(0);
        !           157:                if (kcstate[chan] != DKOPEN)
        !           158:                        return(0);      /* closing channels can't reopen */
        !           159:                return(1);
        !           160:        }
        !           161:        dkp->dkrq = q;
        !           162:        q->ptr = (caddr_t)dkp;
        !           163:        WR(q)->ptr = (caddr_t)dkp;
        !           164:        WR(q)->flag |= QNOENB|QBIGB;
        !           165:        dkp->flag = DKXCL;
        !           166:        kcstate[chan] = DKOPEN;
        !           167:        return(1);
        !           168: }
        !           169: 
        !           170: /*
        !           171:  * make sure cure is alive;
        !           172:  * init data structures once
        !           173:  * it might be better to deal with BDPs dynamically somehow,
        !           174:  * e.g. on the comet where there are very few
        !           175:  */
        !           176: kcinit(kk, firsttime)
        !           177: register struct kccure *kk;
        !           178: {
        !           179:        register struct device *reg;
        !           180:        register int i;
        !           181:        register struct kc *dkp;
        !           182:        static ubm_t map;
        !           183:        uaddr_t uaddr;
        !           184:        extern cure0int(), kcreset();
        !           185: 
        !           186:        kk->kno = KNO;
        !           187:        if ((reg = (struct device *)ubaddr(&cureaddr[0])) == NULL
        !           188:        ||  badaddr(reg, 2)) {
        !           189:                printf("cure0 absent\n");
        !           190:                return (0);
        !           191:        }
        !           192:        for (i = kccnt - 1, dkp = &kc[i]; i >= 0; --dkp, --i)
        !           193:                dkp->chan = i;
        !           194:        kk->addr = reg;
        !           195:        if ((reg->csr&STATE) != SRESET && (reg->csr&STATE) != SOK)
        !           196:                return(0);              /* check downloaded OK */
        !           197:        kclastseq = (reg->csr^SSEQ) & SSEQ;
        !           198:        if (kcwcmd(kk, CINTR, cureaddr[0].vec) == 0)
        !           199:                return (0);
        !           200:        /* allocate and announce command buffers */
        !           201:        if (firsttime)
        !           202:                map = ubmalloc(kk->ubno, (2*NCBUF+1)*sizeof(struct cmd), 0);
        !           203:        else {          /* resetting; free blocks in use */
        !           204:                for (i=0; i<NCBUF; i++) {
        !           205:                        if (kk->ibp[i])
        !           206:                                freeb(kk->ibp[i]);
        !           207:                        if (kk->obp[i])
        !           208:                                freeb(kk->obp[i]);
        !           209:                        kk->ibp[i] = NULL;
        !           210:                        kk->obp[i] = NULL;
        !           211:                }
        !           212:                kcxfirst = kcrfirst = kcxnext = kcrnext = 0;
        !           213:        }
        !           214:        uaddr = ubmaddr(kk->ubno, kk->xcbuf, (2*NCBUF+1)*sizeof(struct cmd), map);
        !           215:        printf("cure reset, uaddr %x map %x\n", uaddr, map);
        !           216:        kcwcmd(kk, CBA, uaddr);
        !           217:        kcwcmd(kk, CBC, NCBUF);
        !           218:        kcwcmd(kk, CSETB|((uaddr>>XASHIFT)&CXA), 0);
        !           219:        kcwcmd(kk, CIACK, 0);   /* to delay until CSETB processed */
        !           220:        if ((reg->csr&STATE)!=SOK) {
        !           221:                printf("cure not ready, state %o\n", reg->csr);
        !           222:                return(0);
        !           223:        }
        !           224:        kcistart(kk);
        !           225:        return (1);
        !           226: }
        !           227: 
        !           228: /*
        !           229:  * close DK channel
        !           230:  */
        !           231: kcclose(q)
        !           232: register struct queue *q;
        !           233: {
        !           234:        register struct kc *dkp;
        !           235:        register struct kccure *kk;
        !           236: 
        !           237:        kk = &kccure[KBNO];
        !           238:        dkp = (struct kc *)q->ptr;
        !           239:        if (dkp == NULL)
        !           240:                panic("kcclose");
        !           241:        dkp->dkrq = NULL;
        !           242:        dkp->flag = 0;
        !           243:        if (kcstate[dkp->chan] == DKRCLOSE || kk->modp->listnrq==NULL)
        !           244:                kcstate[dkp->chan] = DKCLOSED;
        !           245:        else if (kcstate[dkp->chan] == DKOPEN)
        !           246:                kcstate[dkp->chan] = DKLCLOSE;
        !           247:        if (kk->modp->listnrq)
        !           248:                putctl2(RD(kk->modp->listnrq), M_PRICTL, DKMCLOSE, dkp->chan);
        !           249: }
        !           250: 
        !           251: /*
        !           252:  * interrupt
        !           253:  */
        !           254: cure1int(dev) {}
        !           255: cure0int(dev)
        !           256: {
        !           257:        register struct kccure *kk;
        !           258:        register struct device *reg;
        !           259:        register doneb, i, csr;
        !           260: 
        !           261: 
        !           262:        kk = &kccure[KBNO];
        !           263:        if ((reg = kk->addr) == NULL)
        !           264:                return;
        !           265:        csr = reg->csr;
        !           266:        i = csr&STATE;
        !           267:        if (i!=SOK && i!=SRESET)
        !           268:                return;
        !           269:        if (csr & (SERR|SUBERR))
        !           270:                printf("cure status %o\n", reg->csr);
        !           271:        doneb = reg->buf;
        !           272:        i = doneb&0377;                 /* first rcv buf not done */
        !           273:        while (i != kcrfirst) {
        !           274:                kcrecv(kk, kcrfirst);
        !           275:                kcrfirst = (kcrfirst+1)%NCBUF;
        !           276:        }
        !           277:        kcistart(kk);
        !           278:        i = (doneb>>8)&0377;            /* first xmit buf not done */
        !           279:        while (i != kcxfirst) {
        !           280:                kk->flags &=~ XBUSY;
        !           281:                if (kk->obp[kcxfirst]) {
        !           282:                        freeb(kk->obp[kcxfirst]);
        !           283:                        ubmfree(kk->ubno, kk->omap[kcxfirst]);
        !           284:                }
        !           285:                kk->obp[kcxfirst] = NULL;
        !           286:                kcxfirst = (kcxfirst+1)%NCBUF;
        !           287:        }
        !           288:        if (kk->xfirst)
        !           289:                kcosrv((struct queue *)NULL);
        !           290: }
        !           291: 
        !           292: /*
        !           293:  * receive a buffer
        !           294:  */
        !           295: kcrecv(kk, i)
        !           296: register struct kccure *kk;
        !           297: {
        !           298:        register struct block *bp, *nbp;
        !           299:        register struct queue *q;
        !           300:        register c;
        !           301:        struct cmd rcbuf;
        !           302: 
        !           303:        rcbuf = kk->rcbuf[i];
        !           304:        bp = kk->ibp[i];
        !           305:        if (bp==NULL) {
        !           306:                printf("null bp in kcrecv\n");
        !           307:                return;
        !           308:        }
        !           309:        kk->ibp[i] = NULL;
        !           310:        c = rcbuf.chan;
        !           311:        if (c==0 || c>=kccnt || (q = kc[c].dkrq)==NULL) {
        !           312:                if (c==0)
        !           313:                        dkstat.pack0++;
        !           314:                else if (c>=kccnt)
        !           315:                        dkstat.packstrange++;
        !           316:                else
        !           317:                        dkstat.closepack++;
        !           318:                freeb(bp);
        !           319:                return;
        !           320:        }
        !           321:        if (q->next->flag&QFULL) {      /* channel overflow */
        !           322:                freeb(bp);
        !           323:                return;
        !           324:        }
        !           325:        if (rcbuf.count==0)
        !           326:                freeb(bp);
        !           327:        else {                  /* use small buffer if not much data */
        !           328:                 if (rcbuf.count<=64 && (nbp=allocb(rcbuf.count))) {
        !           329:                        bcopy(bp->rptr, nbp->rptr, rcbuf.count);
        !           330:                        freeb(bp);
        !           331:                        bp = nbp;
        !           332:                }
        !           333:                bp->wptr += rcbuf.count;
        !           334:                dkstat.input += rcbuf.count;
        !           335:                (*q->next->qinfo->putp)(q->next, bp);
        !           336:        }
        !           337:        for (c=0; c<NCTL; c++) {
        !           338:                if (rcbuf.ctl[c]==0)
        !           339:                        continue;
        !           340:                bp = allocb(1);
        !           341:                *bp->wptr++ = rcbuf.ctl[c];
        !           342:                if ((rcbuf.ctl[c]&RDATA)==0)
        !           343:                        bp->type = M_CTL;
        !           344:                (*q->next->qinfo->putp)(q->next, bp);
        !           345:        }
        !           346: }
        !           347: 
        !           348: /*
        !           349:  * start new input buffers
        !           350:  */
        !           351: kcistart(kk)
        !           352: register struct kccure *kk;
        !           353: {
        !           354:        register struct device *reg;
        !           355:        register struct block *bp;
        !           356:        register i;
        !           357: 
        !           358:        if ((reg = kk->addr) == NULL)
        !           359:                return;
        !           360:        while((kcrnext+1)%NCBUF != kcrfirst) {
        !           361:                i = kcrnext;
        !           362:                kk->ibp[i] = bp = allocb(1024);
        !           363:                kk->imap[i] = ubmblk(kk->ubno, bp, 0);
        !           364:                kk->rcbuf[i].ubaddr = ubadrptr(kk->ubno, bp, kk->imap[i]);
        !           365:                kk->rcbuf[i].count = bp->lim - bp->base;
        !           366:                kcwcmd(kk, CRCV, i);
        !           367:                kcrnext = (i+1)%NCBUF;
        !           368:        }
        !           369: }
        !           370: 
        !           371: /*
        !           372:  * put procedure for output
        !           373:  */
        !           374: kcput(q, bp)
        !           375: register struct queue *q;
        !           376: register struct block *bp;
        !           377: {
        !           378:        register struct kc *dkp;
        !           379:        register struct kccure *kk;
        !           380:        register int n;
        !           381: 
        !           382:        dkp = (struct kc *)q->ptr;
        !           383:        kk = &kccure[KBNO];
        !           384:        switch (bp->type) {
        !           385: 
        !           386:        case M_IOCTL:
        !           387:                switch (stiocom(bp)) {
        !           388:                case DIOCNXCL:
        !           389:                        dkp->flag &=~ DKXCL;
        !           390:                        bp->wptr = bp->rptr;
        !           391:                        bp->type = M_IOCACK;
        !           392:                        break;
        !           393: 
        !           394:                case KIOCINIT:
        !           395:                        /* eventually, reset things here */
        !           396: 
        !           397:                default:
        !           398:                        bp->type = M_IOCNAK;
        !           399:                        break;
        !           400:                }
        !           401:                qreply(q, bp);
        !           402:                return;
        !           403: 
        !           404:        case M_CTL:
        !           405:        case M_DATA:
        !           406:                dkstat.output += bp->wptr - bp->rptr;
        !           407:                putq(q, bp);
        !           408:                n = spl5();
        !           409:                if ((dkp->flag & DKXWANT) == 0) {
        !           410:                        if (kk->xfirst == NULL)
        !           411:                                kk->xfirst = dkp;
        !           412:                        else
        !           413:                                kk->xlast->link = dkp;
        !           414:                        dkp->link = NULL;
        !           415:                        kk->xlast = dkp;
        !           416:                        dkp->flag |= DKXWANT;
        !           417:                }
        !           418:                if ((kk->flags & XBUSY) == 0)
        !           419:                        qenable(q);
        !           420:                splx(n);
        !           421:                return;
        !           422: 
        !           423:        case M_PRICTL:
        !           424:                switch (*bp->rptr) {
        !           425:                case DKMCLOSE:
        !           426:                        n = bp->rptr[1];
        !           427:                        if (n < kccnt) {
        !           428:                                if (kcstate[n] == DKOPEN) {
        !           429:                                        kcstate[n] = DKRCLOSE;
        !           430:                                        putctl(kc[n].dkrq->next, M_HANGUP);
        !           431:                                } else if (kcstate[n] == DKLCLOSE)
        !           432:                                        kcstate[n] = DKCLOSED;
        !           433:                        }
        !           434:                        freeb(bp);
        !           435:                        return;
        !           436: 
        !           437:                case DKMXINIT:
        !           438:                        n = bp->rptr[1];
        !           439:                        if (n < kccnt && kcstate[n] == DKOPEN)
        !           440:                                (*kc[n].dkrq->next->qinfo->putp)(kc[n].dkrq->next, bp);
        !           441:                        else
        !           442:                                freeb(bp);
        !           443:                        return;                         
        !           444: 
        !           445:                default:
        !           446:                        freeb(bp);
        !           447:                        return;
        !           448:                }
        !           449: 
        !           450:        default:
        !           451:                freeb(bp);
        !           452:                return;
        !           453:        }
        !           454: }
        !           455: 
        !           456: kcosrv(junk)
        !           457: struct queue *junk;
        !           458: {
        !           459:        register struct kccure *kk = &kccure[KBNO];
        !           460:        register s;
        !           461: 
        !           462:        s = spl5();
        !           463:        while (kk->xfirst) {
        !           464:                if ((kcxnext+1)%NCBUF == kcxfirst) {
        !           465:                        kk->flags |= XBUSY;
        !           466:                        return;
        !           467:                }
        !           468:                if (kcosrvbuf(kcxnext))
        !           469:                        kcxnext = (kcxnext+1)%NCBUF;
        !           470:        }
        !           471:        splx(s);
        !           472: }
        !           473: 
        !           474: /*
        !           475:  * fill up one buffer and send it
        !           476:  */
        !           477: 
        !           478: kcosrvbuf(i)
        !           479: register i;
        !           480: {
        !           481: 
        !           482:        register struct kccure *kk;
        !           483:        register struct block *bp;
        !           484:        register struct queue *q;
        !           485:        register struct device *reg;
        !           486:        register struct kc *dkp;
        !           487:        int c;
        !           488: 
        !           489:        kk = &kccure[KBNO];
        !           490:        reg = kk->addr;
        !           491:        dkp = kk->xfirst;
        !           492: more:
        !           493:        if (dkp==NULL) {
        !           494:                printf("null dkp in kcosrvbuf\n");
        !           495:                return 0;
        !           496:        }
        !           497:        if (dkp->dkrq==NULL) {
        !           498:                dkp->flag &=~ DKXWANT;
        !           499:                dkp = dkp->link;
        !           500:                if ((kk->xfirst = dkp) == NULL) {
        !           501:                        kk->xlast = NULL;
        !           502:                        return 0;
        !           503:                }
        !           504:                goto more;
        !           505:        }
        !           506:        q = WR(dkp->dkrq);
        !           507:        kk->xcbuf[i].chan = dkp->chan;
        !           508:        c = 0;
        !           509:        kk->xcbuf[i].count = 0;
        !           510:        while ((bp = getq(q)) != NULL) {
        !           511:                if (bp->type == M_CTL || bp->rptr+NCTL >= bp->wptr) {
        !           512:                        while (bp->rptr < bp->wptr && c < NCTL) {
        !           513:                                kk->xcbuf[i].ctl[c++] = *bp->rptr++ |
        !           514:                                   (bp->type==M_CTL?0:XDATA);
        !           515:                                bp->type = M_DATA;
        !           516:                        }
        !           517:                        if (bp->rptr >= bp->wptr) {
        !           518:                                freeb(bp);
        !           519:                                continue;
        !           520:                        }
        !           521:                } else if (c==0 && kk->xcbuf[i].count==0) {
        !           522:                        kk->omap[i] = ubmblk(kk->ubno, bp, 0);
        !           523:                        kk->xcbuf[i].ubaddr = ubadrptr(kk->ubno, bp, kk->omap[i]);
        !           524:                        kk->xcbuf[i].count = bp->wptr - bp->rptr;
        !           525:                        kk->obp[i] = bp;
        !           526:                        continue;
        !           527:                }
        !           528:                putbq(q, bp);
        !           529:                break;
        !           530:        }
        !           531:        if (bp==NULL) {
        !           532:                dkp->flag &=~ DKXWANT;
        !           533:                dkp = dkp->link;
        !           534:                if ((kk->xfirst = dkp) == NULL)
        !           535:                        kk->xlast = NULL;
        !           536:        }
        !           537:        while (c<NCTL)
        !           538:                kk->xcbuf[i].ctl[c++] = 0;
        !           539:        kcwcmd(kk, CSEND, i);
        !           540:        return 1;
        !           541: }
        !           542: 
        !           543: kcwcmd(kk, cmd, buf)
        !           544: register struct kccure *kk;
        !           545: {
        !           546:        register ocsr;
        !           547:        register count = 0;
        !           548:        register state;
        !           549: 
        !           550:        ocsr = kk->addr->csr;
        !           551:        state = ocsr&STATE;
        !           552:        if (state != SOK) {
        !           553:                if (state!=SRESET)
        !           554:                        return(0);
        !           555:                switch(cmd&037) {
        !           556:                case CSETB:
        !           557:                case CBA:
        !           558:                case CBC:
        !           559:                case CINTR:
        !           560:                case CIACK:
        !           561:                        break;
        !           562:                default:
        !           563:                        if (kcinit(kk, 0)==0)
        !           564:                                return(0);
        !           565:                        break;
        !           566:                }
        !           567:        }
        !           568:        /* wait for last command to be accepted */
        !           569:        while ((kk->addr->csr&SSEQ) == kclastseq) {
        !           570:                if (++count > 100000) {
        !           571:                        printf("cure not responding: csr %o\n", kk->addr->csr);
        !           572:                        return(0);
        !           573:                }
        !           574:        }
        !           575:        if (kk->addr->csr & (SERR|SUBERR))
        !           576:                printf("cure csr %o\n", kk->addr->csr);
        !           577:        kclastseq = kk->addr->csr&SSEQ;
        !           578:        kk->addr->buf = buf;
        !           579:        kk->addr->csr = cmd;
        !           580:        return(1);
        !           581: }
        !           582: 
        !           583: kcclock(dev)
        !           584: caddr_t dev;
        !           585: {
        !           586:        cure0int(minor((int)dev));
        !           587:        timeout(kcclock, dev, 10*HZ);
        !           588: }
        !           589: 
        !           590: /*
        !           591:  * raw cure device for downloading
        !           592:  */
        !           593: long rcureopen();
        !           594: int rcureclose(), rcureoput();
        !           595: 
        !           596: static struct qinit rcurerinit = {
        !           597:        noput, NULL, rcureopen, nulldev, 0, 0
        !           598: };
        !           599: static struct qinit rcurewinit = {
        !           600:        rcureoput, NULL, rcureopen, nulldev, 200, 100
        !           601: };
        !           602: struct streamtab rcureinfo = {
        !           603:        &rcurerinit, &rcurewinit
        !           604: };
        !           605: 
        !           606: /*
        !           607:  * config glue
        !           608:  */
        !           609: extern struct ubaddr rcureaddr[];              /* one per device */
        !           610: extern int rcurecnt;                   /* one per device or what? */
        !           611: struct cdevsw rcurecdev = cstrinit(&rcureinfo);
        !           612: 
        !           613: long
        !           614: rcureopen(q, d)
        !           615: register struct queue *q;
        !           616: {
        !           617:        register dev;
        !           618:        register struct device *mp;
        !           619: 
        !           620:        if((dev = minor(d)) >= rcurecnt)
        !           621:                return 0;
        !           622:        if((mp = (struct device *)ubaddr(&rcureaddr[dev])) == 0
        !           623:          || badaddr(mp, sizeof(u_char))) {
        !           624:                printf("cure %d absent\n", d);
        !           625:                return 0;
        !           626:        }
        !           627:        WR(q)->ptr = q->ptr = (caddr_t) dev;
        !           628:        return 1;
        !           629: }
        !           630: 
        !           631: rcureoput(q, bp)
        !           632: register struct queue *q;
        !           633: register struct block *bp;
        !           634: {
        !           635: #define        DV      017             /* actual device number */
        !           636: #define        BOOTOK  020             /* initialization flag */
        !           637: 
        !           638:        register struct device *mp =
        !           639:             (struct device *)ubaddr(&rcureaddr[(int)q->ptr & DV]);
        !           640:        register int csr, n;
        !           641: 
        !           642:        switch(bp->type) {
        !           643: 
        !           644:        case M_IOCTL:
        !           645:                bp->type = M_IOCNAK;
        !           646:                bp->wptr = bp->rptr;
        !           647:                switch(stiocom(bp)) {
        !           648:                case KIOCINIT:                  /* reboot cure */
        !           649:                        mp->reset = 1;
        !           650:                        delay(10);
        !           651:                        mp->reset = 0;
        !           652:                        bp->type = M_IOCACK;
        !           653:                        break;
        !           654:                }
        !           655:                qreply(q, bp);
        !           656:                return;
        !           657: 
        !           658:        case M_DATA:
        !           659:                if (((int)q->ptr&BOOTOK) == 0) {                /* first write */
        !           660:                        if ((mp->csr&STATE) != SBOOT) {
        !           661:                                printf("cure not ready to load, %o\n", mp->csr);
        !           662:                                goto err;
        !           663:                        }
        !           664:                        mp->buf = 070707;       /* magic number starts bootload */
        !           665:                        delay(10);
        !           666:                        if ((mp->csr&STATE) != SBOOTING) {
        !           667:                                printf("cure load err0 %o\n", mp->csr);
        !           668:                                goto err;
        !           669:                        }
        !           670:                        q->ptr = (caddr_t)((int)q->ptr | BOOTOK);
        !           671:                }
        !           672:                while (bp->rptr < bp->wptr) {
        !           673:                        if ((mp->csr&STATE) != SBOOTING) {
        !           674:                                printf("cure load err1\n");
        !           675:                                goto err;
        !           676:                        }
        !           677:                        csr = mp->csr;
        !           678:                        mp->buf = *bp->rptr++;
        !           679:                        for (n=0; ((csr ^ mp->csr)&SSEQ)==0 && n<100000; ++n) {
        !           680:                                if (mp->csr&SERR || (mp->csr&STATE)!=SBOOTING) {
        !           681:                                        printf("cure load err2 %o\n", mp->csr);
        !           682:                                        goto err;
        !           683:                                }
        !           684:                        }
        !           685:                        if (n==100000) {
        !           686:                                printf("cure load err3\n");
        !           687:                                goto err;
        !           688:                        }
        !           689:                }
        !           690:                break;
        !           691:        }
        !           692:        freeb(bp);
        !           693:        return;
        !           694:   err:
        !           695:        bp->type = M_HANGUP;
        !           696:        qreply(q, bp);
        !           697: }

unix.superglobalmegacorp.com

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