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

1.1     ! root        1: /*
        !             2:  * stream driver for DK via KMC-11/KDI board
        !             3:  * delicately intertwined with kmc.c
        !             4:  */
        !             5: 
        !             6: #include "sys/param.h"
        !             7: #include "sys/stream.h"
        !             8: #include "sys/ttyio.h"
        !             9: #include "sys/dkio.h"
        !            10: #include "sys/conf.h"
        !            11: #include "sys/dkstat.h"
        !            12: #include "sys/dkmod.h"
        !            13: #include "sys/ubaddr.h"
        !            14: #include "sys/kmc.h"
        !            15: #include "sys/kdi.h"
        !            16: #include "sys/buf.h"
        !            17: #include "sys/dkwindow.h"
        !            18: 
        !            19: #define        KDIPRI  28
        !            20: 
        !            21: /*
        !            22:  * flags
        !            23:  */
        !            24: #define        KMBUSY  0x01
        !            25: #define        KMSTOP  0x02
        !            26: #define        KMINC   0x04
        !            27: #define        KMBIG   0x3c            /* rcvd lots last time, use big rcv buffer */
        !            28: #define        KMXCL   0x40            /* exclusive use */
        !            29: #define        KMXBIG  0x80            /* tell KMC to use large messages */
        !            30: #define BIGSET(c) ((((c)<<1)|KMINC)&KMBIG | ((c)&~KMBIG))
        !            31: #define BIGCLR(c) (((c)<<1)&KMBIG | ((c)&~KMBIG))
        !            32: 
        !            33: /*
        !            34:  * device structure
        !            35:  */
        !            36: struct device {
        !            37:        char    sts;
        !            38:        char    x1;
        !            39:        union {
        !            40:                struct {
        !            41:                        u_short lo;
        !            42:                        u_char  hi;
        !            43:                } a;
        !            44:                struct {
        !            45:                        u_char  x2;
        !            46:                        u_char  x3;
        !            47:                        u_char  ch;
        !            48:                        u_char  ct;
        !            49:                        u_char  sh;
        !            50:                        u_char  st;
        !            51:                } q;
        !            52:        } u;
        !            53: };
        !            54: 
        !            55: /*
        !            56:  * KMC commands
        !            57:  */
        !            58: #define        KC_INIT         1
        !            59: #define        KC_SEND         2
        !            60: #define        KC_RCVB         3
        !            61: #define        KC_CLOSE        4
        !            62: #define        KC_XINIT        5
        !            63: #define        KC_CMD          6
        !            64: #define        KC_FLAG         7
        !            65: #define        KC_SOI          8
        !            66: 
        !            67: /*
        !            68:  * subcommands of KC_CMD or KC_SEND
        !            69:  */
        !            70: #define        OFLUSH          02      /* flush output */
        !            71: #define        OSPND           04      /* suspend output */
        !            72: #define        ORSME           010     /* resume output */
        !            73: #define        OBOTM           0200    /* send BOTM trailer, not BOT */
        !            74: 
        !            75: /*
        !            76:  * KMC reports
        !            77:  */
        !            78: #define        KS_SEND         024
        !            79: #define        KS_RDB          025
        !            80: #define        KS_EOI          026
        !            81: #define        KS_CNTL         027
        !            82: #define        KS_ERR          030
        !            83: 
        !            84: /*
        !            85:  * KC_RCV modes
        !            86:  */
        !            87: #define        CBLOCK          0040    /* return on block boundary */
        !            88: #define        CTIME           0100    /* return when time expires */
        !            89: 
        !            90: /*
        !            91:  * KS_RDB mode
        !            92:  */
        !            93: #define        SFULL           0001    /* buffer full */
        !            94: #define        SCNTL           0002    /* cntl char recv */
        !            95: #define        SABORT          0010    /* rcv aborted */
        !            96: #define        SBLOCK          0040    /* block boundary */
        !            97: #define        STIME           0100    /* time limit expired */
        !            98: 
        !            99: /*
        !           100:  * URP control characters
        !           101:  */
        !           102: #define        D_DELAY 0100
        !           103: #define        D_BREAK 0110
        !           104: 
        !           105: /*
        !           106:  *  KMC errors
        !           107:  */
        !           108: #define        E_NOQB  4               /* internal buffer runout */
        !           109: #define        E_DUP   5               /* duplicate send (shouldn't but does happen) */
        !           110: #define        E_UMETA 7               /* unknown control character */
        !           111: 
        !           112: /*
        !           113:  * tracing
        !           114:  */
        !           115: #define DEBUG
        !           116: #ifdef DEBUG
        !           117: struct kin ktrbuf[256];
        !           118: struct kin *ktrp = ktrbuf;
        !           119: #define        TRACE(x) *ktrp++ = x; if (ktrp >= &ktrbuf[256]) ktrp = ktrbuf;
        !           120: #else
        !           121: #define        TRACE(x)        ;
        !           122: #endif
        !           123: 
        !           124: int    kdiclose(), kdiput(), kdiisrv();
        !           125: long   kdiopen();
        !           126: struct qinit kdirinit = { noput, kdiisrv, kdiopen, kdiclose, 0, 0 };
        !           127: struct qinit kdiwinit = { kdiput, NULL, kdiopen, kdiclose, 512, 128 };
        !           128: struct streamtab kdiinfo = { &kdirinit, &kdiwinit };
        !           129: struct cdevsw kdicdev = cstrinit(&kdiinfo);
        !           130: 
        !           131: struct kmaddr kmcubaddr();
        !           132: extern struct kdikmc kdikmc[];
        !           133: extern struct kmcdk k[];
        !           134: extern int kdicnt;
        !           135: extern struct kmc kmc[];
        !           136: extern struct ubaddr kmcaddr[];
        !           137: extern int kmccnt;
        !           138: struct dkstat  dkstat;
        !           139: 
        !           140: #define        KDICHAN 96              /* channels per kdi (== per kmc) */
        !           141: #define        KMC(d)  ((d)/KDICHAN)
        !           142: #define        CHAN(d) ((d)%KDICHAN)
        !           143: 
        !           144: /*
        !           145:  * open channel
        !           146:  */
        !           147: long
        !           148: kdiopen(q, dev)
        !           149: register struct queue *q;
        !           150: dev_t dev;
        !           151: {
        !           152:        register struct kdi *kp;
        !           153:        register struct block *bp;
        !           154:        register struct kdikmc *xp;
        !           155:        register int kno, chan;
        !           156: 
        !           157:        kno = KMC(minor(dev));
        !           158:        chan = CHAN(minor(dev));
        !           159:        if (kno >= kdicnt || kno >= kmccnt || chan >= KDICHAN)
        !           160:                return (0);
        !           161:        xp = &kdikmc[kno];
        !           162:        if (xp->bad)
        !           163:                return (0);
        !           164:        if (xp->init == 0)
        !           165:                if (kdiinit(dev) == 0)
        !           166:                        return (0);
        !           167:        kp = &xp->kdi[chan];
        !           168:        if (xp->state[chan] != DKCLOSED) {
        !           169:                if (kp->ostate&KMXCL)   /* exclusive use until reset */
        !           170:                        return(0);
        !           171:                if (xp->state[chan] != DKOPEN)
        !           172:                        return(0);      /* closing channels cannot reopen */
        !           173:                return(1);
        !           174:        }
        !           175:        kp->dkrq = q;
        !           176:        q->ptr = (caddr_t)kp;
        !           177:        WR(q)->flag |= QDELIM|QBIGB;
        !           178:        q->flag |= QDELIM;
        !           179:        WR(q)->ptr = (caddr_t)kp;
        !           180:        xp->state[chan] = DKOPEN;
        !           181:        kp->ostate = KMXCL;
        !           182:        kcmd(kno, KC_INIT, kp->chan, 0, 0, 0, (uaddr_t)NULL);
        !           183:        if ((bp = allocb(64)) == NULL) {
        !           184:                xp->state[chan] = 0;
        !           185:                return(0);
        !           186:        }
        !           187:        kp->lastctl = 0;
        !           188:        kp->ibp = bp;
        !           189:        kp->imap = ubmblk(xp->ubno, bp, 0);
        !           190:        kcmd(kno, KC_RCVB, chan, bp->lim-bp->wptr, 50,
        !           191:             CBLOCK|CTIME, ubadwptr(xp->ubno, bp, kp->imap));
        !           192:        return(1);
        !           193: }
        !           194: 
        !           195: kdiclose(q)
        !           196: register struct queue *q;
        !           197: {
        !           198:        register struct kdi *kp = (struct kdi *)q->ptr;
        !           199:        register s, i;
        !           200:        register struct kdikmc *xp;
        !           201: 
        !           202:        xp = &kdikmc[kp->kno];
        !           203:        if (xp->modp == NULL || xp->modp->listnrq == NULL
        !           204:        ||  xp->state[kp->chan]==DKRCLOSE)
        !           205:                xp->state[kp->chan] = DKCLOSED;
        !           206:        else if (xp->state[kp->chan] == DKOPEN) {
        !           207:                xp->state[kp->chan] = DKLCLOSE;
        !           208:                for (i=0; i<30 && (WR(q)->count || kp->obp); i++)
        !           209:                        tsleep((caddr_t)kp, KDIPRI, 1);
        !           210:        }
        !           211:        kp->dkrq = NULL;
        !           212:        if (xp->modp && xp->modp->listnrq)
        !           213:                putctl2(RD(xp->modp->listnrq), M_PRICTL, DKMCLOSE, kp->chan);
        !           214:        s = spl6();
        !           215:        if (kp->obp) {
        !           216:                freeb(kp->obp);
        !           217:                kp->obp = NULL;
        !           218:        }
        !           219:        splx(s);
        !           220:        kp->ostate &= ~KMXCL;
        !           221:        kcmd(kp->kno, KC_CLOSE, kp->chan, 0, 0, 0, (uaddr_t)NULL);
        !           222: }
        !           223: 
        !           224: kdiput(q, bp)
        !           225: register struct queue *q;
        !           226: register struct block *bp;
        !           227: {
        !           228:        register struct kdi *kdp = (struct kdi *)q->ptr;
        !           229:        register char *sp;
        !           230:        register s;
        !           231:        register struct kdikmc *xp;
        !           232:        struct block *xbp;
        !           233:        int t;
        !           234: 
        !           235:        xp = &kdikmc[kdp->kno];
        !           236:        switch(bp->type) {
        !           237: 
        !           238:        case M_CTL:
        !           239:        case M_DATA:
        !           240:        case M_DELAY:
        !           241:        case M_BREAK:
        !           242:                if (xp->state[kdp->chan] < DKLCLOSE) {
        !           243:                        freeb(bp);
        !           244:                        return;
        !           245:                }
        !           246:                putq(q, bp);
        !           247:                if ((kdp->ostate&KMBUSY)==0)
        !           248:                        kmstart(kdp);
        !           249:                return;
        !           250: 
        !           251:        case M_PRICTL:
        !           252:                switch (*bp->rptr) {
        !           253:                case DKMCLOSE:
        !           254:                        s = bp->rptr[1];
        !           255:                        if (s < KDICHAN) {
        !           256:                                flushq(q, 1);
        !           257:                                if (xp->state[s] == DKOPEN) {
        !           258:                                        xp->state[s] = DKRCLOSE;
        !           259:                                        putctl(xp->kdi[s].dkrq->next, M_HANGUP);
        !           260:                                } else if (xp->state[s] == DKLCLOSE)
        !           261:                                        xp->state[s] = DKCLOSED;
        !           262:                                kcmd(kdp->kno, KC_CLOSE, s, 0, 0, 0, (uaddr_t)NULL);
        !           263:                        }
        !           264:                        break;
        !           265: 
        !           266:                case DKMXINIT:
        !           267:                        /* retrieve channel number */
        !           268:                        bp->rptr++;
        !           269:                        s = *bp->rptr++;
        !           270:        
        !           271:                        /* forget it if this isn't a valid channel */
        !           272:                        if (s >= KDICHAN || xp->state[s] != DKOPEN)
        !           273:                                break;
        !           274:                        
        !           275:                        /* next two bytes (if there) are the traffic type */
        !           276:                        if(bp->wptr-bp->rptr>=2){
        !           277:                                t = (*bp->rptr++<<8) & 0xff00;
        !           278:                                t |= *bp->rptr++ & 0xff;
        !           279:        
        !           280:                                /* check window sizes */
        !           281:                                if (W_VALID(t)) {
        !           282:        
        !           283:                                        /* kmc has only two possible window sizes */
        !           284:                                        t = W_VALUE(W_ORIG(t));
        !           285:                                        if(t<1024)
        !           286:                                                xp->kdi[s].ostate &= ~KMXBIG;
        !           287:                                        else
        !           288:                                                xp->kdi[s].ostate |= KMXBIG;
        !           289:                                }
        !           290:                        }
        !           291: 
        !           292:                        /* restart urp on the channel, with the correct window */
        !           293:                        kdixinit(&xp->kdi[s]);
        !           294:                        break;
        !           295: 
        !           296:                default:
        !           297:                        break;
        !           298:                }
        !           299:                break;          /* and freeb */
        !           300: 
        !           301:        case M_IOCTL:
        !           302:                sp = stiodata(bp);
        !           303:                bp->type = M_IOCACK;
        !           304:                switch (stiocom(bp)) {
        !           305: 
        !           306:                case TIOCSDEV:
        !           307:                        if (((struct ttydevb *)sp)->ispeed == 0)
        !           308:                                putctl2(q, M_PRICTL, DKMCLOSE, kdp->chan);
        !           309:                case KIOCISURP:
        !           310:                        bp->wptr = bp->rptr;
        !           311:                        break;
        !           312: 
        !           313:                case DIOCSCTL:
        !           314:                        bp->wptr = bp->rptr;
        !           315:                        if (*sp == 0)
        !           316:                                break;
        !           317:                        if ((xbp = allocb(1)) == NULL)
        !           318:                                bp->type = M_IOCNAK;
        !           319:                        else {
        !           320:                                xbp->type = M_CTL;
        !           321:                                *xbp->wptr++ = *sp;
        !           322:                                putq(q, xbp);
        !           323:                                if ((kdp->ostate&KMBUSY) == 0)
        !           324:                                        kmstart(kdp);
        !           325:                        }
        !           326:                        break;
        !           327: 
        !           328:                case DIOCRCTL:
        !           329:                        *sp = kdp->lastctl;
        !           330:                        kdp->lastctl = 0;
        !           331:                        bp->wptr = (unsigned char *)sp + 1;
        !           332:                        break;
        !           333: 
        !           334:                case DIOCNXCL:
        !           335:                        kdp->ostate &= ~KMXCL;
        !           336:                        bp->wptr = bp->rptr;
        !           337:                        break;
        !           338: 
        !           339:                case TIOCGDEV:
        !           340:                        ((struct ttydevb *)sp)->ispeed =
        !           341:                          ((struct ttydevb *)sp)->ospeed = B9600;
        !           342:                        break;
        !           343: 
        !           344:                case KIOCINIT:
        !           345:                        kdixinit(kdp);
        !           346:                        bp->rptr = bp->wptr;
        !           347:                        break;
        !           348: 
        !           349:                case KIOCSHUT:
        !           350:                        if (kdp->chan > 2) {    /* hackish security attempt */
        !           351:                                bp->type = M_IOCNAK;
        !           352:                                break;
        !           353:                        }
        !           354:                        kdireset(kdp->kno);
        !           355:                        bp->rptr = bp->wptr;
        !           356:                        break;
        !           357: 
        !           358:                case DIOCSTREAM:
        !           359:                        RD(q)->flag &= ~QDELIM;
        !           360:                        bp->rptr = bp->wptr;
        !           361:                        break;
        !           362: 
        !           363:                case DIOCRECORD:
        !           364:                        RD(q)->flag |= QDELIM;
        !           365:                        bp->rptr = bp->wptr;
        !           366:                        break;
        !           367: 
        !           368:                case DIOCXWIN: {
        !           369:                        unsigned int wins;
        !           370:                        /* KMC does big (756) or small (84) windows currently */
        !           371:                        wins = (sp[0] + (sp[1]<<8))*sp[4];
        !           372:                        kdp->ostate &= ~KMXBIG;
        !           373:                        if (wins>=756)
        !           374:                                kdp->ostate |= KMXBIG;
        !           375:                        /* will take effect next XINIT */
        !           376:                        bp->rptr = bp->wptr;
        !           377:                        break;
        !           378:                    }
        !           379: 
        !           380:                default:
        !           381:                        bp->wptr = bp->rptr;
        !           382:                        bp->type = M_IOCNAK;
        !           383:                        break;
        !           384:                }
        !           385:                qreply(q, bp);
        !           386:                return;
        !           387: 
        !           388:        case M_STOP:
        !           389:                s = OSPND;
        !           390:                kdp->ostate |= KMSTOP;
        !           391:                goto dontcmd;
        !           392: 
        !           393:        case M_FLUSH:
        !           394:                flushq(q, 0);
        !           395:                s = spl6();
        !           396:                if (kdp->obp) {
        !           397:                        freeb(kdp->obp);        /* this cannot be right -- too early */
        !           398:                        kdp->obp = 0;
        !           399:                }
        !           400:                kdp->ostate &= ~(KMSTOP|KMBUSY);
        !           401:                splx(s);
        !           402:                s = OFLUSH|ORSME;
        !           403:                goto docmd;
        !           404: 
        !           405:        case M_START:
        !           406:        case M_HANGUP:
        !           407:                s = ORSME;
        !           408:                kdp->ostate &= ~KMSTOP;
        !           409:                goto dontcmd;
        !           410:        docmd:
        !           411:                kcmd(kdp->kno, KC_CMD, kdp->chan, 0, s, 0, (uaddr_t)NULL);
        !           412:        dontcmd:
        !           413:                kmstart(kdp);
        !           414:                break;
        !           415: 
        !           416:        default:                /* not handled; just toss */
        !           417:                break;
        !           418:        }
        !           419:        freeb(bp);
        !           420: }
        !           421: 
        !           422: /*
        !           423:  * restart URP on some channel:
        !           424:  * send XINIT to KMC;
        !           425:  * discard any pending transmit block
        !           426:  *
        !           427:  * should pending block really be discarded, or requeued?
        !           428:  * former seems to match real cases
        !           429:  */
        !           430: 
        !           431: kdixinit(kp)
        !           432: register struct kdi *kp;
        !           433: {
        !           434:        register int s;
        !           435: 
        !           436:        s = spl6();
        !           437:        kcmd(kp->kno, KC_XINIT, kp->chan, 0, 0, (kp->ostate&KMXBIG)!=0, (uaddr_t)NULL);
        !           438:        if (kp->obp) {
        !           439:                freeb(kp->obp);
        !           440:                kp->obp = NULL;
        !           441:        }
        !           442:        if (kp->omap) {
        !           443:                ubmfree(kdikmc[kp->kno].ubno, kp->omap);
        !           444:                kp->omap = 0;
        !           445:        }
        !           446:        kp->ostate &=~ (KMSTOP|KMBUSY);
        !           447:        splx(s);
        !           448: }
        !           449: 
        !           450: kdiisrv(q)
        !           451: register struct queue *q;
        !           452: {
        !           453:        register struct kdi *kp = (struct kdi *)q->ptr;
        !           454:        register int ubno;
        !           455:        register struct block *bp;
        !           456: 
        !           457:        if ((q->next->flag&QFULL)==0 && kp->ibp==NULL) {
        !           458:                bp = allocb(kp->ostate&KMBIG? 1024:64);
        !           459:                if (bp == NULL)
        !           460:                        panic("kdi: can't alloc");
        !           461:                kp->ibp = bp;
        !           462:                ubno = kdikmc[kp->kno].ubno;
        !           463:                kp->imap = ubmblk(ubno, bp, 0);
        !           464:                kcmd(kp->kno, KC_RCVB, kp->chan, bp->lim - bp->wptr,
        !           465:                     50, CBLOCK|CTIME, ubadwptr(ubno, bp, kp->imap));
        !           466:        }
        !           467: }
        !           468: 
        !           469: kmstart(kdp)
        !           470: register struct kdi *kdp;
        !           471: {
        !           472:        register s = spl5();
        !           473:        register struct block *bp;
        !           474:        register struct queue *qp;
        !           475:        register c;
        !           476:        register struct kdikmc *xp;
        !           477: 
        !           478:        if (kdp->ostate&(KMBUSY|KMSTOP)) {
        !           479:                splx(s);
        !           480:                return;
        !           481:        }
        !           482:        if ((qp = kdp->dkrq)==NULL || (qp = WR(qp))==NULL) {
        !           483:                splx(s);
        !           484:                return;
        !           485:        }
        !           486:        xp = &kdikmc[kdp->kno];
        !           487:        if (bp = getq(qp)) switch (bp->type) {
        !           488: 
        !           489:        case M_DATA:
        !           490:                c = OBOTM;
        !           491:                if (bp->class&S_DELIM)
        !           492:                        c = 0;
        !           493:                kdp->omap = ubmblk(xp->ubno, bp, 0);
        !           494:                kcmd(kdp->kno, KC_SEND, kdp->chan, bp->wptr-bp->rptr,
        !           495:                     0, c, ubadrptr(xp->ubno, bp, kdp->omap));
        !           496:                kdp->ostate |= KMBUSY;
        !           497:                dkstat.output += bp->wptr - bp->rptr;
        !           498:                kdp->obp = bp;
        !           499:                break;
        !           500: 
        !           501:        case M_DELAY:
        !           502:                c = D_DELAY;
        !           503:                while (*bp->rptr>0) {
        !           504:                        c++;
        !           505:                        *bp->rptr >>= 1;
        !           506:                }
        !           507:                kdp->omap = ubmblk(xp->ubno, bp, 0);
        !           508:                kcmd(kdp->kno, KC_SEND, kdp->chan, 1, c, 0, ubadrptr(xp->ubno, bp, kdp->omap));
        !           509:                kdp->ostate |= KMBUSY;
        !           510:                kdp->obp = bp;
        !           511:                break;
        !           512: 
        !           513:        case M_CTL:
        !           514:                kdp->omap = ubmblk(xp->ubno, bp, 0);
        !           515:                kcmd(kdp->kno, KC_SEND, kdp->chan, 0, *bp->rptr, 0, ubadrptr(xp->ubno, bp, kdp->omap));
        !           516:                kdp->ostate |= KMBUSY;
        !           517:                kdp->obp = bp;
        !           518:                break;
        !           519: 
        !           520:        case M_BREAK:
        !           521:                kdp->omap = ubmblk(xp->ubno, bp, 0);
        !           522:                kcmd(kdp->kno, KC_SEND, kdp->chan, 0, D_BREAK, 0, ubadrptr(xp->ubno, bp, kdp->omap));
        !           523:                kdp->ostate |= KMBUSY;
        !           524:                kdp->obp = bp;
        !           525:                break;
        !           526: 
        !           527:        default:
        !           528:                printf("mesg %o in kdi\n", bp->type);
        !           529:                freeb(bp);
        !           530:                break;
        !           531:        }
        !           532:        splx(s);
        !           533: }
        !           534: 
        !           535: int kcmdovern[10];
        !           536: long kcmdovert[10];
        !           537: 
        !           538: kcmd(kno, type, chan, len, ctl, mode, addr)
        !           539: uaddr_t addr;
        !           540: {
        !           541:        register i;
        !           542:        register struct device *dp = kmc[kno].k_addr;
        !           543:        register struct kin *kp;
        !           544:        register s;
        !           545:        static struct kmaddr nulladr = {0, 0};
        !           546:        static serno;
        !           547:        register long loop;
        !           548: 
        !           549:        /*
        !           550:         *  if the kmc is dead, don't ask it to do things
        !           551:         */
        !           552:        if(dp->sts ==3)
        !           553:                return;
        !           554: 
        !           555:        if (dp->u.q.x3)
        !           556:                dp->u.q.x3 = 0;
        !           557: busywait:
        !           558:        /*
        !           559:         *  wait at low priority till there's a free command.  No
        !           560:         *  sense slowing all processes down.
        !           561:         */
        !           562:        if(((dp->u.q.ch+1)%NKMB)==dp->u.q.ct) {
        !           563:                loop = 0;
        !           564:                while (((dp->u.q.ch+1)%NKMB)==dp->u.q.ct) {
        !           565:                        if (loop == 1000)
        !           566:                                printf("waiting for kdi%d\n", kno);
        !           567:                        if(loop++>1000000) {
        !           568:                                printf("kmc%d died, restart\n", kno);
        !           569:                                kdireset(kno);
        !           570:                                return;
        !           571:                        }
        !           572:                }
        !           573:                kcmdovern[kno]++;
        !           574:                if(kcmdovert[kno]<loop)
        !           575:                        kcmdovert[kno] = loop;
        !           576:        }
        !           577:        s = spl5();
        !           578:        /*
        !           579:         *  someone else might have gotten in at low priority.  check
        !           580:         *  again.
        !           581:         */
        !           582:        if(((dp->u.q.ch+1)%NKMB)==dp->u.q.ct) {
        !           583:                splx(s);
        !           584:                goto busywait;
        !           585:        }
        !           586:        i = dp->u.q.ch;
        !           587:        if (i >= NKMB)
        !           588:                panic("kcmd");
        !           589:        kp = &k[kno].cmd[i];
        !           590:        kp->type = type;
        !           591:        kp->serno = ++serno;
        !           592:        kp->chan = chan;
        !           593:        kp->len = len;
        !           594:        kp->ctl = ctl;
        !           595:        kp->mode = mode;
        !           596:        kp->addr.hi = addr>>16;
        !           597:        kp->addr.lo = addr;
        !           598:        i++;
        !           599:        if (i >= NKMB)
        !           600:                i = 0;
        !           601:        dp->u.q.ch = i;
        !           602:        TRACE(*kp);
        !           603:        splx(s);
        !           604: }
        !           605: 
        !           606: u_char kdiseqno[10];
        !           607: 
        !           608: /*
        !           609:  * Interrupt routine-- unload status buffer:
        !           610:  * release write blocks, collect input
        !           611:  */
        !           612: kdiintr(kno)
        !           613: {
        !           614:        register struct device *dp = kmc[kno].k_addr;
        !           615:        register struct kin *sp;
        !           616:        register struct kdi *kp;
        !           617:        register struct block *bp;
        !           618:        register c;
        !           619:        register struct kdikmc *xp;
        !           620: 
        !           621:        xp = &kdikmc[kno];
        !           622:        if (dp->u.q.x3)
        !           623:                dp->u.q.x3 = 0;
        !           624:        for ( ; (c = dp->u.q.st) != dp->u.q.sh; dp->u.q.st = c) {
        !           625:                if (c >= NKMB) {
        !           626:                        printf("kdi stat buf is %d\n", c);
        !           627:                        panic("kdiintr");
        !           628:                }
        !           629:                sp = &k[kno].stat[c];
        !           630:                TRACE(*sp);
        !           631:                c++;
        !           632:                if (c >= NKMB)
        !           633:                        c = 0;
        !           634:                if (sp->chan >= KDICHAN) {
        !           635:                        printf("kdi%d stat chan is 0%o\n", kno, sp->chan);
        !           636:                        printf("type: %o len: 0%o mode: 0%o\n");
        !           637:                        continue;
        !           638:                }
        !           639:                if(sp->serno!=kdiseqno[kno]){
        !           640:                        printf("kdi%d stat chan is 0%o\n", kno, sp->chan);
        !           641:                        printf("seqno is %d, should be %d\n",sp->serno,
        !           642:                                kdiseqno[kno]);
        !           643:                }
        !           644:                kdiseqno[kno]=(sp->serno+1)%256;
        !           645:                kp = &xp->kdi[sp->chan];
        !           646:                switch (sp->type) {
        !           647: 
        !           648:                case KS_SEND:
        !           649:                        if (kp->obp) {
        !           650:                                freeb(kp->obp);
        !           651:                                kp->obp = NULL;
        !           652:                        }
        !           653:                        kp->ostate &= ~KMBUSY;
        !           654:                        if (kp->omap) {
        !           655:                                ubmfree(xp->ubno, kp->omap);
        !           656:                                kp->omap = 0;
        !           657:                        }
        !           658:                        if (kp->dkrq && WR(kp->dkrq)->first)
        !           659:                                kmstart(kp);
        !           660:                        break;
        !           661: 
        !           662:                case KS_RDB:
        !           663:                        if (kp->imap) {
        !           664:                                ubmfree(xp->ubno, kp->imap);
        !           665:                                kp->imap = 0;
        !           666:                        }
        !           667:                        bp = kp->ibp;
        !           668:                        kp->ibp = NULL;
        !           669:                        if (kp->dkrq==NULL || xp->state[kp->chan]!=DKOPEN) {
        !           670:                                if (bp)
        !           671:                                        freeb(bp);
        !           672:                                break;
        !           673:                        }
        !           674:                        if (sp->mode & SABORT) {
        !           675:                                printf("kdi%d rcv abort chan %d mode %o bp %x\n",
        !           676:                                  kno, kp->chan, sp->mode, bp);
        !           677:                                if (bp)
        !           678:                                        kp->ibp = bp;
        !           679:                                kp->rsize = 0;
        !           680:                                kp->ostate &= ~KMBIG;
        !           681:                                break;
        !           682:                        }
        !           683:                        if (bp == NULL) {
        !           684:                                printf("kdi%d: no ibp\n", kno);
        !           685:                                break;
        !           686:                        }
        !           687:                        /* special hacks */
        !           688:                        if (sp->mode&020
        !           689:                        ||  sp->mode==0100 && bp->wptr+sp->len==bp->lim) {
        !           690:                                /*
        !           691:                                 *  Something no one understands.  Print out
        !           692:                                 *  some info so that we might figure out
        !           693:                                 *  why this freeb is in the code.
        !           694:                                 */
        !           695:                                printf("kdi%d rcv chan %d mode %o bp %x len %d\n",
        !           696:                                  kno, kp->chan, sp->mode, bp, sp->len);
        !           697:                                freeb(bp);
        !           698:                        } else {
        !           699:                                bp->wptr = bp->lim - sp->len;
        !           700:                                kp->rsize += bp->wptr - bp->rptr;
        !           701:                                dkstat.input += bp->wptr - bp->rptr;
        !           702:                                if(sp->mode&(SBLOCK|STIME)) {
        !           703:                                        bp->class |= S_DELIM;
        !           704:                                        if (kp->rsize >= 512)
        !           705:                                                kp->ostate = BIGSET(kp->ostate);
        !           706:                                        else
        !           707:                                                kp->ostate = BIGCLR(kp->ostate);
        !           708:                                        kp->rsize = 0;
        !           709:                                }
        !           710:                                (*kp->dkrq->next->qinfo->putp)
        !           711:                                       (kp->dkrq->next, bp);
        !           712:                                kp->ibp = NULL;
        !           713:                                if (sp->mode&SCNTL) {
        !           714:                                        switch (sp->ctl) {
        !           715: 
        !           716:                                        case D_BREAK:
        !           717:                                                putctl(kp->dkrq->next, M_BREAK);
        !           718:                                                break;
        !           719: 
        !           720:                                        default:
        !           721:                                                kp->lastctl = sp->ctl;
        !           722:                                                putctl1(kp->dkrq->next, M_CTL, sp->ctl);
        !           723:                                                break;
        !           724: 
        !           725:                                        }
        !           726:                                }
        !           727:                        }
        !           728:                        if ((kp->dkrq->next->flag&QFULL) == 0) {
        !           729:                                bp = allocb(kp->ostate&KMBIG? 1024:64);
        !           730:                                if (bp == NULL)
        !           731:                                        panic("kdi: can't alloc");
        !           732:                                kp->ibp = bp;
        !           733:                                kp->imap = ubmblk(xp->ubno, bp, 0);
        !           734:                                kcmd(kno, KC_RCVB, kp->chan, bp->lim - bp->wptr,
        !           735:                                     50, CBLOCK|CTIME, ubadwptr(xp->ubno, bp, kp->imap));
        !           736:                        }
        !           737:                        break;
        !           738:                
        !           739:                case KS_EOI:
        !           740:                        printf("kdi%d chan %d rcv EOI %x\n", kno, sp->chan, sp->len);
        !           741:                        break;
        !           742: 
        !           743:                case KS_CNTL:
        !           744:                        /*
        !           745:                        printf("kdi%d chan %d rcv ctl %x\n", kno, sp->chan, sp->len);
        !           746:                        */
        !           747:                        break;
        !           748: 
        !           749:                case KS_ERR:
        !           750:                        printf("kdi%d chan %d error %d\n", kno, sp->chan, sp->len);
        !           751:                        if (sp->len==E_NOQB || sp->len==E_UMETA
        !           752:                         || sp->len==E_DUP) {
        !           753:                                printf("ignored\n");
        !           754:                                break;
        !           755:                        }
        !           756:                        kdireset(kno);
        !           757:                        break;
        !           758: 
        !           759:                }
        !           760:        }
        !           761: }
        !           762: 
        !           763: /*
        !           764:  * init things, including data structures
        !           765:  * -- assume KDICHAN struct kdis and KDICHAN chars for state
        !           766:  * will fit in a buffer.  when BSIZE is 4096, it's true.
        !           767:  */
        !           768: int kdireload();
        !           769: 
        !           770: kdiinit(dev)
        !           771: int dev;
        !           772: {
        !           773:        register struct device *kp;
        !           774:        register i;
        !           775:        register struct kdikmc *xp;
        !           776:        register int kno;
        !           777:        struct kmaddr ka;
        !           778:        extern time_t time;
        !           779: 
        !           780:        kno = KMC(minor(dev));
        !           781:        /* close all open channels? */
        !           782:        if ((kp = kmc[kno].k_addr) == NULL)
        !           783:                return (0);
        !           784:        xp = &kdikmc[kno];
        !           785:        if (xp->badtime+30 > time)      /* UGH */
        !           786:                return(0);
        !           787:        kp->sts = 0;                    /* initialize KMC */
        !           788:        if (xp->buf == NULL) {
        !           789:                if ((xp->buf = geteblk()) == NULL)
        !           790:                        return (0);
        !           791:                clrbuf(xp->buf);
        !           792:                xp->kdi = (struct kdi *)xp->buf->b_un.b_addr;
        !           793:                xp->state = (char *)&xp->kdi[KDICHAN];
        !           794:                for (i = 0; i < KDICHAN; i++) {
        !           795:                        xp->kdi[i].chan = i;
        !           796:                        xp->kdi[i].kno = kno;
        !           797:                }
        !           798:        }
        !           799:        if ((xp->modp = dkmodall(dev, kno*KDICHAN, (kno+1)*KDICHAN)) == 0)
        !           800:                return (0);
        !           801:        xp->modp->dkstate = xp->state;
        !           802:        xp->ubno = kmcaddr[kno].ubno;
        !           803:        if (xp->umap == 0) {
        !           804:                if ((xp->umap = ubmalloc(xp->ubno, sizeof(struct kmcdk), 0)) == 0) {
        !           805:                        printf("kdi%d: no map\n", kno);
        !           806:                        return (0);
        !           807:                }
        !           808:        }
        !           809:        xp->ubad = ubmaddr(xp->ubno, (caddr_t)&k[kno], sizeof(struct kmcdk), xp->umap);
        !           810:        k[kno].kinit.cmdaddr = kmcubaddr((caddr_t)k[kno].cmd, (caddr_t)&k[kno], xp->ubad);
        !           811:        k[kno].kinit.stataddr = kmcubaddr((caddr_t)k[kno].stat, (caddr_t)&k[kno], xp->ubad);
        !           812:        k[kno].kinit.bufaddr = kmcubaddr((caddr_t)k[kno].kmcbuf, (caddr_t)&k[kno], xp->ubad);
        !           813:        ka = kmcubaddr((caddr_t)&k[kno].kinit, (caddr_t)&k[kno], xp->ubad);
        !           814:        kp->u.a.lo = ka.lo;
        !           815:        kp->u.a.hi = ka.hi;
        !           816:        xp->badtime = time;
        !           817:        kp->sts = 1;                    /* start handshake */
        !           818:        for (i = 0; i<100000; i++) {
        !           819:                if (kp->sts == 2) {
        !           820:                        kmc[kno].k_rint = kdiintr;
        !           821:                        kmc[kno].k_xint = kdiintr;
        !           822:                        kmc[kno].k_reset = kdireload;
        !           823:                        xp->init = 1;
        !           824:                        return(1);                      /* KMC is running OK */
        !           825:                }
        !           826:                if (kp->sts == 3) {
        !           827:                        printf("kdi%d: entered state 3\n", kno);
        !           828:                        return(0);
        !           829:                }
        !           830:        }
        !           831:        printf("kdi%d: kmc not ready\n", kno);
        !           832:        return(0);
        !           833: }
        !           834: 
        !           835: struct kmaddr
        !           836: kmcubaddr(memaddr, membase, ubbase)
        !           837: caddr_t memaddr, membase;
        !           838: uaddr_t ubbase;
        !           839: {
        !           840:        register struct kmaddr r;
        !           841:        register long a;
        !           842: 
        !           843:        a = (long)memaddr - (long)membase + (long)ubbase;
        !           844:        r.hi = a >> 16;
        !           845:        r.lo = (u_short)a;
        !           846:        return(r);
        !           847: }
        !           848: 
        !           849: /*
        !           850:  * kmc reload
        !           851:  */
        !           852: kdireload(kno)
        !           853: {
        !           854:        register struct kdikmc *xp;
        !           855: 
        !           856:        xp = &kdikmc[kno];
        !           857:        xp->init = 0;
        !           858:        xp->modp = 0;
        !           859:        xp->bad = 0;
        !           860: }
        !           861: 
        !           862: /*
        !           863:  * zap all open channels
        !           864:  */
        !           865: kdireset(kno)
        !           866: {
        !           867:        register struct kdi *kp;
        !           868:        register struct kdikmc *xp;
        !           869:        register struct device *dp;
        !           870: 
        !           871:        xp = &kdikmc[kno];
        !           872:        if (xp->modp==0)
        !           873:                return;
        !           874:        if ((dp = kmc[kno].k_addr) != NULL)
        !           875:                dp->sts = 3;    /* disable kdi kmc code */
        !           876:        for (kp = &xp->kdi[KDICHAN-1]; kp >= xp->kdi; --kp) {
        !           877:                register state = xp->state[kp->chan];
        !           878:                if ((state==DKOPEN || state==DKLCLOSE) && kp->dkrq) {
        !           879:                        flushq(WR(kp->dkrq), 1);
        !           880:                        xp->state[kp->chan] = state==DKOPEN? DKRCLOSE: DKCLOSED;
        !           881:                        putctl(kp->dkrq->next, M_HANGUP);
        !           882:                }
        !           883:                if (kp->imap)
        !           884:                        ubmfree(xp->ubno, kp->imap);
        !           885:                if (kp->omap)
        !           886:                        ubmfree(xp->ubno, kp->omap);
        !           887:                kp->imap = kp->omap = 0;
        !           888:        }
        !           889:        xp->bad = 1;
        !           890: }

unix.superglobalmegacorp.com

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