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

1.1     ! root        1: /*
        !             2:  * DHV11 driver for Ninth Edition UNIX
        !             3:  * by Andrew Hume (loosely based on dh driver from toronto)
        !             4:  */
        !             5: 
        !             6: #include "sys/param.h"
        !             7: #include "sys/systm.h"
        !             8: #include "sys/stream.h"
        !             9: #include "sys/ttyio.h"
        !            10: #include "sys/ubaddr.h"
        !            11: #include "sys/conf.h"
        !            12: #include "sys/dhv11.h"
        !            13: 
        !            14: #define NPER   8               /* lines per board */
        !            15: 
        !            16: /* bits in dhv[]->state */
        !            17: #define        ISOPEN  0x0002
        !            18: #define        WOPEN   0x0004
        !            19: #define        TIMEOUT 0x0008
        !            20: #define        CARRIER 0x0010
        !            21: #define        DHSTOP  0x0020
        !            22: #define        HPCL    0x0040
        !            23: #define        BRKING  0x0080
        !            24: #define BUSY   0x0100
        !            25: #define FLUSH  0x0200
        !            26: 
        !            27: #define SSPEED B9600   /* reasonable default nowadays */
        !            28: #define DHPRI  30
        !            29: 
        !            30: /* hardware structure */
        !            31: struct dhvreg
        !            32: {
        !            33:        unsigned short csr;
        !            34:        short rbuf;             /* coincides with txchar (not used) */
        !            35:        unsigned short lpr;     /* line param */
        !            36:        unsigned short lstat;   /* line status */
        !            37:        unsigned short lctl;    /* line control */
        !            38:        unsigned short addr1;
        !            39:        unsigned short addr2;
        !            40:        unsigned short cnt;
        !            41: };
        !            42: 
        !            43: struct hilo    /* for utterly wretched appalling hardware */
        !            44: {
        !            45:        char low;
        !            46:        char high;
        !            47: };
        !            48: #define        LOW(ptr)        ((struct hilo *)&(ptr))->low
        !            49: #define        HIGH(ptr)       ((struct hilo *)&(ptr))->high
        !            50: 
        !            51: /* csr bits */
        !            52: #define        TXACT           0x8000
        !            53: #define        TXIE            0x4000
        !            54: #define        DIAGFAIL        0x2000
        !            55: #define        TXERR           0x1000
        !            56: #define        TXLINE(csr)     (((csr)>>8)&0xF)
        !            57: #define        RXAVAIL         0x0080
        !            58: #define        RXIE            0x0040
        !            59: #define        MRESET          0x0020
        !            60: #define        POINT(r, l)     LOW((r)->csr) = (((l)&0xF) | RXIE)
        !            61: 
        !            62: /* rbuf */
        !            63: #define        VALID           0x8000
        !            64: #define        OERR            0x4000
        !            65: #define        FERR            0x2000
        !            66: #define        PERR            0x1000
        !            67: #define        LINE(rbuf)      (((rbuf)>>8)&0xF)
        !            68: #define        ISMODEM(rbuf)   (((rbuf)&0x7000)==0x7000)
        !            69: #define        DCD             0x10    /* note that it is shifted left 8 bits in lstat */
        !            70: 
        !            71: /* lpr bits */
        !            72: #define        BITS5           0x00
        !            73: #define        BITS6           0x08
        !            74: #define        BITS7           0x10
        !            75: #define        BITS8           0x18
        !            76: #define        PENAB           0x20
        !            77: #define        EPARITY         0x40
        !            78: #define        STOP2           0x80
        !            79: 
        !            80: /* lctl bits */
        !            81: #define        TXABORT         0x0001
        !            82: #define        RXENABLE        0x0004
        !            83: #define        BREAK           0x0008
        !            84: #define        MODEM           0x0100
        !            85: #define        DTR             0x0200
        !            86: #define        RTS             0x1000
        !            87: 
        !            88: /* addr2 */
        !            89: #define        TXEN            0x8000
        !            90: #define        TXSTART         0x0080
        !            91: 
        !            92: #define        RESETSECS       5       /* seconds to wait for master reset */
        !            93: #define        RESETJUNK       8       /* number of bytes reset puts in the fifo */
        !            94: #define        RSDIAG  0200            /* some sort of diag message */
        !            95: #define        RSNULL  0201            /* ok self-test status */
        !            96: #define        RSSKIP  0203            /* self-test skipped */
        !            97: 
        !            98: char dhvsp[16] =
        !            99: {
        !           100:        0, 0, 1, 2, 3, 4 ,0, 5, 6, 7, 8, 10, 11, 13, 14, 0
        !           101: };
        !           102: 
        !           103: /*
        !           104:  * interface with i/o system
        !           105:  */
        !           106: long   dhvopen();
        !           107: int    dhvclose(), dhvoput();
        !           108: static struct qinit dhvrinit = { noput, NULL, dhvopen, dhvclose, 0, 0 };
        !           109: static struct qinit dhvwinit = { dhvoput, NULL, dhvopen, dhvclose, 200, 100 };
        !           110: static struct streamtab dhvinfo = { &dhvrinit, &dhvwinit };
        !           111: struct cdevsw dhvcdev = cstrinit(&dhvinfo);
        !           112: 
        !           113: extern struct ubaddr dhvaddr[];
        !           114: extern struct dhv dhv[];
        !           115: extern int dhvcnt;
        !           116: 
        !           117: /*
        !           118:  * misc private data
        !           119:  */
        !           120: int    dhvoverrun;
        !           121: int    dhvmiss;                        /* chars lost due to q full */
        !           122: 
        !           123: /*
        !           124:        use tsleep so user can interrupt without wrecking accounting
        !           125: */
        !           126: long
        !           127: dhvopen(q, d)
        !           128:        register struct queue *q;
        !           129:        dev_t d;
        !           130: {
        !           131:        register int dev;
        !           132:        register struct dhv *dhvp;
        !           133:        register int s;
        !           134: 
        !           135:        dev = minor(d);
        !           136:        if(dev >= dhvcnt)
        !           137:                return(0);
        !           138:        dhvp = &dhv[dev];
        !           139:        q->ptr = (caddr_t)dhvp;
        !           140:        WR(q)->ptr = (caddr_t)dhvp;
        !           141:        /*
        !           142:                If this is first open, initialise tty state to default.
        !           143:         */
        !           144:        if(((dhvp->state&ISOPEN)==0) || ((dhvp->state&CARRIER)==0)){
        !           145:                if (dhvinit(dev) == 0)          /* reset the hardware */
        !           146:                        return(0);
        !           147:                dhvp->flags = ODDP|EPARITY;
        !           148:                dhvp->ispeed = dhvp->ospeed = SSPEED;
        !           149:                dhvp->lctl = MODEM|DTR|RTS|RXENABLE;
        !           150:                dhvp->state = 0;
        !           151:                s = spl5();
        !           152:                dhvparam(dhvp);
        !           153:                while(!(dhvp->state & CARRIER))
        !           154:                        if(tsleep((caddr_t)dhvp, DHPRI, 0) != TS_OK){
        !           155:                                splx(s);
        !           156:                                return(0);
        !           157:                        }
        !           158:                dhvp->rdq = q;
        !           159:                dhvp->oblock = 0;
        !           160:                dhvp->state |= ISOPEN;
        !           161:                splx(s);
        !           162:        }
        !           163:        return 1;
        !           164: }
        !           165: 
        !           166: /*
        !           167:  * reset the DHV hardware
        !           168:  * -- be sure address is correct for first line of board
        !           169:  */
        !           170: dhvinit(dev)
        !           171: int dev;
        !           172: {
        !           173:        register struct dhvreg *regs;
        !           174:        register struct ubaddr *ap;
        !           175:        register int bd, i, c;
        !           176:        int s, bad;
        !           177: 
        !           178:        bd = dev / NPER;
        !           179:        ap = &dhvaddr[bd];
        !           180:        bd *= NPER;             /* first line of this board */
        !           181:        if (dhv[bd].regs) {
        !           182:                dhv[dev].regs = dhv[bd].regs;
        !           183:                dhv[dev].adno = ap->ubno;
        !           184:                dhv[dev].line = dev%NPER;
        !           185:                return (1);             /* already set up */
        !           186:        }
        !           187:        if ((regs = (struct dhvreg *)ubaddr(ap)) == 0
        !           188:        ||  ubbadaddr(ap->ubno, &regs->csr, sizeof(short))) {
        !           189:                printf("dhv11 %d absent\n", bd/NPER);
        !           190:                return (0);
        !           191:        }
        !           192:        s = spl5();
        !           193:        regs->csr = MRESET;
        !           194:        for (i = 0; i < RESETSECS; i++) {
        !           195:                sleep((caddr_t)&lbolt, PZERO);
        !           196:                if ((regs->csr & MRESET) == 0)
        !           197:                        break;
        !           198:        }
        !           199:        splx(s);
        !           200:        if (regs->csr & (MRESET|DIAGFAIL)) {
        !           201:                printf("dhv11 %d: bad reset: csr %o\n", bd/NPER, regs->csr);
        !           202:                return (0);
        !           203:        }
        !           204:        bad = 0;
        !           205:        for (i = 0; i < RESETJUNK; i++) {
        !           206:                c = regs->rbuf & 0377;
        !           207:                if ((c & RSDIAG) == 0)          /* just a ROM version */
        !           208:                        continue;
        !           209:                if (c == RSNULL || c == RSSKIP)
        !           210:                        continue;
        !           211:                bad++;
        !           212:                printf("dhv11 %d: diag err %o\n", bd/NPER, c);
        !           213:        }
        !           214:        if (bad)
        !           215:                return (0);
        !           216:        dhv[dev].regs = regs;
        !           217:        dhv[dev].adno = ap->ubno;
        !           218:        dhv[dev].line = dev%NPER;
        !           219:        if (dev != bd) {
        !           220:                dhv[bd].regs = regs;
        !           221:                dhv[bd].adno = ap->ubno;
        !           222:        }
        !           223:        return (1);
        !           224: }
        !           225: 
        !           226: /*
        !           227:  * Close a DHV11 line.
        !           228:  */
        !           229: dhvclose(q)
        !           230:        register struct queue *q;
        !           231: {
        !           232:        register struct dhv *dhvp;
        !           233:        int s = spl5();
        !           234: 
        !           235:        dhvp = (struct dhv *)q->ptr;
        !           236:        if(dhvp->oblock){
        !           237:                freeb(dhvp->oblock);
        !           238:                dhvp->oblock = 0;
        !           239:        }
        !           240:        flushq(WR(q), 1);
        !           241:        dhvp->rdq = NULL;
        !           242:        POINT(dhvp->regs, dhvp->line);
        !           243:        dhvp->regs->lctl = 0;
        !           244:        dhvp->state = 0;
        !           245:        splx(s);
        !           246: }
        !           247: 
        !           248: 
        !           249: /*
        !           250:  * dhv11 write put routine
        !           251:  */
        !           252: dhvoput(q, bp)
        !           253:        register struct queue *q;
        !           254:        register struct block *bp;
        !           255: {
        !           256:        register struct dhv *dhvp = (struct dhv *)q->ptr;
        !           257:        register struct ttydevb *sp;
        !           258:        register int s;
        !           259:        int delaytime;
        !           260: 
        !           261:        switch(bp->type)
        !           262:        {
        !           263:        case M_IOCTL:
        !           264:                sp = (struct ttydevb *)stiodata(bp);
        !           265:                switch(stiocom(bp))
        !           266:                {
        !           267:                case TIOCSDEV:
        !           268:                        delaytime = 0;
        !           269:                        if(dhvp->ispeed != sp->ispeed)
        !           270:                                delaytime = 20;
        !           271:                        dhvp->ospeed = sp->ospeed;
        !           272:                        dhvp->ispeed = sp->ispeed;
        !           273:                        dhvp->flags = sp->flags;
        !           274:                        bp->type = M_IOCACK;
        !           275:                        bp->wptr = bp->rptr;
        !           276:                        qreply(q, bp);
        !           277:                        qpctl1(q, M_DELAY, delaytime);  /* wait a bit */
        !           278:                        qpctl(q, M_CTL);                /* means do dhvparam */
        !           279:                        dhvstart(dhvp);
        !           280:                        return;
        !           281:                case TIOCGDEV:
        !           282:                        sp->ispeed = dhvp->ispeed;
        !           283:                        sp->ospeed = dhvp->ospeed;
        !           284:                        sp->flags = dhvp->flags & (F8BIT|EVENP|ODDP);
        !           285:                        bp->type = M_IOCACK;
        !           286:                        qreply(q, bp);
        !           287:                        return;
        !           288:                default:
        !           289:                        bp->wptr = bp->rptr;
        !           290:                        bp->type = M_IOCNAK;
        !           291:                        qreply(q, bp);
        !           292:                        return;
        !           293:                }
        !           294:        case M_STOP:
        !           295:                s = spl5();
        !           296:                dhvp->state |= DHSTOP;
        !           297:                freeb(bp);
        !           298:                dhvstop(dhvp);
        !           299:                splx(s);
        !           300:                return;
        !           301:        case M_START:
        !           302:                dhvp->state &= ~DHSTOP;
        !           303:                dhvstart(dhvp);
        !           304:                break;
        !           305:        case M_FLUSH:
        !           306:                flushq(q, 1);
        !           307:                freeb(bp);
        !           308:                return;
        !           309:        case M_BREAK:
        !           310:                qpctl1(q, M_DELAY, 10);
        !           311:                putq(q, bp);
        !           312:                qpctl1(q, M_DELAY, 10);
        !           313:                dhvstart(dhvp);
        !           314:                return;
        !           315:        case M_HANGUP:
        !           316:                dhvp->state &= ~DHSTOP;
        !           317:        case M_DELAY:
        !           318:        case M_DATA:
        !           319:                putq(q, bp);
        !           320:                dhvstart(dhvp);
        !           321:                return;
        !           322:        default:                /* not handled; just toss */
        !           323:                break;
        !           324:        }
        !           325:        freeb(bp);
        !           326: }
        !           327: 
        !           328: /*
        !           329:        Set parameters from open or stty into the DH hardware
        !           330:        registers.
        !           331: */
        !           332: dhvparam(dhvp)
        !           333:        register struct dhv *dhvp;
        !           334: {
        !           335:        register struct dhvreg *regs;
        !           336:        register int lpar;
        !           337:        register s;
        !           338: 
        !           339:        regs = dhvp->regs;
        !           340:        if(dhvp->ospeed)
        !           341:                dhvp->lctl |= (DTR|RTS);
        !           342:        else
        !           343:                dhvp->lctl &= ~(DTR|RTS);
        !           344:        lpar = (dhvsp[dhvp->ospeed]<<12) | (dhvsp[dhvp->ispeed]<<8);
        !           345:        if((dhvp->ospeed) == B134)
        !           346:                lpar |= BITS6|PENAB;
        !           347:        else if (dhvp->flags & F8BIT)
        !           348:                lpar |= BITS8;
        !           349:        else if(((s = dhvp->flags&(EVENP|ODDP)) == (EVENP|ODDP)) || (s == 0))
        !           350:                lpar |= BITS8;
        !           351:        else {
        !           352:                lpar |= BITS7|PENAB;
        !           353:                if(dhvp->flags&EVENP)
        !           354:                        lpar |= EPARITY;
        !           355:        }
        !           356:        if ((dhvp->ospeed) == B110)     /* 110 baud (ugh!): 2 stop bits */
        !           357:                lpar |= STOP2;
        !           358:        dhvp->state &= ~CARRIER;
        !           359:        POINT(regs, dhvp->line);
        !           360:        regs->lpr = lpar;
        !           361:        regs->lctl = dhvp->lctl;
        !           362:        if(regs->lstat&(DCD<<8))
        !           363:                dhvp->state |= CARRIER;
        !           364: }
        !           365: 
        !           366: /*
        !           367:        DHV11 receiver interrupt.
        !           368: */
        !           369: dhv0int(dev)
        !           370:        int dev;
        !           371: {
        !           372:        register struct block *bp;
        !           373:        register struct dhvreg *regs;
        !           374:        register struct dhv *dhvp;
        !           375:        register int c;
        !           376:        int hangup;
        !           377: 
        !           378:        if(dev/NPER >= dhvcnt) {
        !           379:                printf("dhv%d: stray rcv intr\n", dev);
        !           380:                return;
        !           381:        }
        !           382:        regs = dhv[dev*NPER].regs;
        !           383:        /*
        !           384:                get chars from the silo for this line
        !           385:        */
        !           386:        while((c = regs->rbuf) < 0) { /* char present */
        !           387:                dhvp = &dhv[dev*NPER + LINE(c)];
        !           388:                hangup = 0;
        !           389:                if(ISMODEM(c)){
        !           390:                        dhvp->state &= ~CARRIER;
        !           391:                        if((c&DCD) == 0)
        !           392:                                hangup = 1;
        !           393:                        else {
        !           394:                                dhvp->state |= CARRIER;
        !           395:                                wakeup((caddr_t)dhvp);
        !           396:                                continue;
        !           397:                        }
        !           398:                        c &= ~(OERR|FERR|PERR);
        !           399:                }
        !           400:                if(c&OERR){
        !           401:                        ++dhvoverrun;
        !           402:                        continue;
        !           403:                }
        !           404:                if(dhvp->rdq == NULL)
        !           405:                        continue;
        !           406:                if(dhvp->rdq->next->flag & QFULL) {
        !           407:                        dhvmiss++;      /* you lose */
        !           408:                        continue;
        !           409:                }
        !           410:                if((bp = allocb(16)) == NULL){
        !           411:                        printf("rint: out of space\n");
        !           412:                        continue;       /* out of space - you lose */
        !           413:                }
        !           414:                if(hangup)
        !           415:                        bp->type = M_HANGUP;
        !           416:                else if(c&FERR)         /* frame error == BREAK */
        !           417:                        bp->type = M_BREAK;
        !           418:                else
        !           419:                        *bp->wptr++ = c;
        !           420:                (*dhvp->rdq->next->qinfo->putp)(dhvp->rdq->next, bp);
        !           421:        }
        !           422: }
        !           423: 
        !           424: 
        !           425: /*
        !           426:        DHV11 transmitter interrupt. Dev is board number.
        !           427:        Restart each line which used to be active but has
        !           428:        terminated transmission since the last interrupt.
        !           429: */
        !           430: dhv1int(dev)
        !           431:        int dev;
        !           432: {
        !           433:        register struct dhvreg *regs;
        !           434:        register struct dhv *dhvp;
        !           435:        register struct block *bp;
        !           436:        register int unit;
        !           437:        register short csr;
        !           438: 
        !           439:        regs = dhv[dev*NPER].regs;
        !           440:        while((csr = regs->csr) < 0){
        !           441:                unit = TXLINE(csr);
        !           442:                dhvp = &dhv[unit + dev*NPER];
        !           443:                dhvp->state &= ~BUSY;
        !           444:                POINT(regs, unit);
        !           445:                if((csr&(TXACT|TXERR)) == (TXACT|TXERR)){       /* somebody goofed */
        !           446:                        printf("dhv%d: txerr csr=0x%x addr2=0x%x addr1=0x%x\n",
        !           447:                                dev, csr, regs->addr2, regs->addr1);
        !           448:                        regs->cnt = 0;  /* allow progress */
        !           449:                }
        !           450:                if(bp = dhvp->oblock){
        !           451:                        bp->rptr = bp->wptr - regs->cnt;
        !           452:                        if(bp->rptr == bp->wptr){
        !           453:                                dhvp->oblock = 0;
        !           454:                                freeb(bp);
        !           455:                        }
        !           456:                }
        !           457:                dhvstart(dhvp);
        !           458:        }
        !           459: }
        !           460: 
        !           461: dhvtimo(dhvp)
        !           462:        register struct dhv *dhvp;
        !           463: {
        !           464: 
        !           465:        if(dhvp->state&BRKING) {
        !           466:                int s = spl5();
        !           467:                POINT(dhvp->regs, dhvp->line);
        !           468:                dhvp->regs->lctl &= ~BREAK;
        !           469:                splx(s);
        !           470:        }
        !           471:        dhvp->state &= ~(TIMEOUT|BRKING);
        !           472:        dhvstart(dhvp);
        !           473: }
        !           474: 
        !           475: /*
        !           476:        Start (restart) transmission on the given DH11 line.
        !           477: */
        !           478: dhvstart(dhvp)
        !           479: register struct dhv *dhvp;
        !           480: {
        !           481:        register struct dhvreg *regs;
        !           482:        register int unit;
        !           483:        register int s = spl5();
        !           484:        register struct block *bp;
        !           485:        register uaddr_t addr;
        !           486:        ubm_t um;
        !           487: 
        !           488:        unit = dhvp->line;
        !           489:        if(dhvp->state & BUSY)
        !           490:                goto done;
        !           491:        regs = dhvp->regs;
        !           492: again:
        !           493:        if(dhvp->state&(TIMEOUT|DHSTOP|BRKING) || (dhvp->rdq == NULL))
        !           494:                goto done;
        !           495:        if((bp = dhvp->oblock) == NULL){
        !           496:                if((bp = getq(WR(dhvp->rdq))) == NULL)
        !           497:                        goto done;
        !           498:        }
        !           499:        switch(bp->type)
        !           500:        {
        !           501:        case M_DATA:
        !           502:                if (bp->wptr <= bp->rptr) {
        !           503:                        freeb(bp);
        !           504:                        dhvp->oblock = 0;
        !           505:                        break;
        !           506:                }
        !           507:                if ((um = ubmblk(dhvp->adno, bp, 0)) == 0) {    /* snh */
        !           508:                        freeb(bp);
        !           509:                        break;
        !           510:                }
        !           511:                addr = ubadrptr(dhvp->adno, bp, um);
        !           512:                LOW(regs->csr) = RXIE | (unit&0xF);
        !           513:                while(regs->addr2&TXSTART)
        !           514:                        printf("dhv: start set\n");
        !           515:                if(regs->lctl&TXABORT)
        !           516:                        regs->lctl &= ~TXABORT;
        !           517:                HIGH(regs->csr) = TXIE>>8;
        !           518:                regs->addr1 = addr;
        !           519:                regs->cnt = bp->wptr - bp->rptr;
        !           520:                HIGH(regs->addr2) = TXEN>>8;
        !           521:                LOW(regs->addr2) = (addr>>16) | TXSTART;
        !           522:                dhvp->state |= BUSY;
        !           523:                dhvp->oblock = bp;
        !           524:                break;
        !           525:        case M_BREAK:
        !           526:                dhvp->state |= BRKING|TIMEOUT;
        !           527:                timeout(dhvtimo, (caddr_t)dhvp, 15);    /* about 250 ms */
        !           528:                freeb(bp);
        !           529:                break;
        !           530:        case M_DELAY:
        !           531:                dhvp->state |= TIMEOUT;
        !           532:                timeout(dhvtimo, (caddr_t)dhvp, (int)*bp->rptr + 6);
        !           533:                freeb(bp);
        !           534:                break;
        !           535:        case M_HANGUP:
        !           536:                dhvp->ispeed = dhvp->ospeed = 0;
        !           537:                /* fall through */
        !           538:        case M_CTL:
        !           539:                freeb(bp);
        !           540:                dhvparam(dhvp);
        !           541:                goto again;
        !           542: 
        !           543:        }
        !           544: done:
        !           545:        splx(s);
        !           546: }
        !           547: 
        !           548: 
        !           549: /*
        !           550:        Stop output on a line, e.g. for ^S/^Q or output flush (e.g. ^O).
        !           551: */
        !           552: dhvstop(dhvp)
        !           553:        register struct dhv *dhvp;
        !           554: {
        !           555:        register int s = spl5();
        !           556: 
        !           557:        if(dhvp->state & BUSY){
        !           558:                /*
        !           559:                        just stop it, tint looks at the count
        !           560:                */
        !           561:                POINT(dhvp->regs, dhvp->line);
        !           562:                dhvp->regs->lctl |= TXABORT;
        !           563:        }
        !           564:        splx(s);
        !           565: }

unix.superglobalmegacorp.com

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