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