Annotation of 41BSD/4.0.upgrade/sys/dev/tu.c, revision 1.1

1.1     ! root        1: /*     tu.c    82/02/01        4.5     */
        !             2: 
        !             3: #if defined(VAX750) || defined(VAX7ZZ)
        !             4: /*
        !             5:  * TU58 DECtape II device driver
        !             6:  *
        !             7:  * This driver controls the console TU58s on a VAX-11/750 or VAX-11/7ZZ.
        !             8:  * It could be easily modified for a Unibus TU58.  The TU58
        !             9:  * is treated as a block device (only).  Error detection and
        !            10:  * recovery is almost non-existant.  It is assumed that the
        !            11:  * TU58 will follow the RSP protocol exactly, very few protocol
        !            12:  * errors are checked for.  It is assumed that the 750 uses standard
        !            13:  * RSP while the 7ZZ uses Modified RSP (MRSP).  At the time when 750's
        !            14:  * are converted to MRSP (by replacing EPROMS in the TU58), the tests
        !            15:  * based on MRSP can be removed.
        !            16:  */
        !            17: #define        NTU     ((cpu == VAX_750) ? 1 : 2)
        !            18: 
        !            19: #define        MRSP    (cpu != VAX_750)
        !            20: 
        !            21: #include "../h/param.h"
        !            22: #include "../h/systm.h"
        !            23: #include "../h/buf.h"
        !            24: #include "../h/conf.h"
        !            25: #include "../h/dir.h"
        !            26: #include "../h/user.h"
        !            27: #include "../h/mtpr.h"
        !            28: #include "../h/cpu.h"
        !            29: 
        !            30: #define        printd  if(tudebug) printf
        !            31: #ifdef printd
        !            32: int    tudebug;        /* printd */
        !            33: #endif printd
        !            34: 
        !            35: #define        NTUBLK  512             /* number of blocks on a TU58 cassette */
        !            36: 
        !            37: #define        TUIPL   ((cpu == VAX_750) ? 0x17 : 0x14)
        !            38: 
        !            39: /*
        !            40:  * Device register bits
        !            41:  */
        !            42: #define        READY   0200            /* transmitter ready */
        !            43: #define        DONE    0200            /* receiver done */
        !            44: #define        IE      0100            /* interrupt enable */
        !            45: #define        BREAK   1               /* send break */
        !            46: 
        !            47: /*
        !            48:  * Structure of a command packet
        !            49:  */
        !            50: struct packet {
        !            51:        u_char  pk_flag;        /* indicates packet type (cmd, data, etc.) */
        !            52:        u_char  pk_mcount;      /* length of packet (bytes) */
        !            53:        u_char  pk_op;          /* operation to perform (read, write, etc.) */
        !            54:        char    pk_mod;         /* modifier for op or returned status */
        !            55:        u_char  pk_unit;        /* unit number */
        !            56:        u_char  pk_sw;          /* switches */
        !            57:        u_short pk_seq;         /* sequence number, always zero */
        !            58:        u_short pk_count;       /* requested byte count for read or write */
        !            59:        u_short pk_block;       /* block number for read, write, or seek */
        !            60:        u_short pk_chksum;      /* checksum, by words with end around carry */
        !            61: };
        !            62: 
        !            63: struct packet tucmd;           /* a command sent to the TU58 */
        !            64: struct packet tudata;          /* a command or data returned from TU58 */
        !            65: 
        !            66: /*
        !            67:  * State information
        !            68:  */
        !            69: struct tu {
        !            70:        u_char  *rbptr;         /* pointer to buffer for read */
        !            71:        int     rcnt;           /* how much to read */
        !            72:        u_char  *wbptr;         /* pointer to buffer for write */
        !            73:        int     wcnt;           /* how much to write */
        !            74:        int     state;          /* current state of tansfer operation */
        !            75:        int     flag;           /* read in progress flag */
        !            76:        char    *addr;          /* real buffer data address */
        !            77:        int     count;          /* real requested count */
        !            78:        int     serrs;          /* count of soft errors */
        !            79:        int     cerrs;          /* count of checksum errors */
        !            80:        int     herrs;          /* count of hard errors */
        !            81: } tu;
        !            82: 
        !            83: /*
        !            84:  * States
        !            85:  */
        !            86: #define        INIT1   0               /* sending nulls */
        !            87: #define        INIT2   1               /* sending inits */
        !            88: #define        IDLE    2               /* initialized, no transfer in progress */
        !            89: #define        SENDH   3               /* sending header */
        !            90: #define        SENDD   4               /* sending data */
        !            91: #define        SENDC   5               /* sending checksum */
        !            92: #define        SENDR   6               /* sending read command packet */
        !            93: #define        SENDW   7               /* sending write command packet */
        !            94: #define        GETH    8               /* reading header */
        !            95: #define        GETD    9               /* reading data */
        !            96: #define        GETC    10              /* reading checksum */
        !            97: #define        GET     11              /* reading an entire packet */
        !            98: #define        WAIT    12              /* waiting for continue */
        !            99: 
        !           100: /*
        !           101:  * Packet Flags
        !           102:  */
        !           103: #define        TUF_DATA        1               /* data packet */
        !           104: #define        TUF_CMD         2               /* command packet */
        !           105: #define        TUF_INITF       4               /* initialize */
        !           106: #define        TUF_CONT        020             /* continue */
        !           107: #define        TUF_XOFF        023             /* flow control */
        !           108: 
        !           109: /*
        !           110:  * Op Codes
        !           111:  */
        !           112: #define        TUOP_INIT       1               /* initialize */
        !           113: #define        TUOP_READ       2               /* read block */
        !           114: #define        TUOP_WRITE      3               /* write block */
        !           115: #define        TUOP_SEEK       5               /* seek to block */
        !           116: #define TUOP_DIAGNOSE  7               /* run micro-diagnostics */
        !           117: #define        TUOP_END        0100            /* end packet */
        !           118: 
        !           119: /*
        !           120:  * Switches
        !           121:  */
        !           122: #define        TUSW_MRSP       010             /* use Modified RSP */
        !           123: 
        !           124: u_char tunull[2] = { 0, 0 };   /* nulls to send for initialization */
        !           125: u_char tuinit[2] = { TUF_INITF, TUF_INITF };   /* inits to send */
        !           126: 
        !           127: int    tutimer = 0;
        !           128: 
        !           129: struct buf tutab;              /* I/O queue header */
        !           130: 
        !           131: /*
        !           132:  * Open the TU58
        !           133:  */
        !           134: /*ARGSUSED*/
        !           135: tuopen(dev, flag)
        !           136: {
        !           137:        extern int tuwatch();
        !           138:        register s;
        !           139: 
        !           140: #ifdef lint
        !           141:        turintr(); tuwintr();
        !           142: #endif
        !           143:        if (minor(dev) >= NTU) {
        !           144:                u.u_error = ENXIO;
        !           145:                return;
        !           146:        }
        !           147:        if (tutimer == 0) {
        !           148:                tutimer++;
        !           149:                timeout(tuwatch, (caddr_t)0, hz);
        !           150:        }
        !           151:        s = splx(TUIPL);
        !           152:        if (tu.state != IDLE) {
        !           153:                tureset();
        !           154:                sleep((caddr_t)&tu, PZERO);
        !           155:                tutab.b_active = NULL;
        !           156:                if (tu.state != IDLE) {         /* couldn't initialize */
        !           157:                        u.u_error = ENXIO;
        !           158:                        tu.state = INIT1;
        !           159:                        tu.rcnt = tu.wcnt = 0;
        !           160:                        mtpr(CSTS, 0);
        !           161:                        mtpr(CSRS, 0);
        !           162:                }
        !           163:        } else
        !           164:                mtpr(CSRS, IE);
        !           165:        splx(s);
        !           166: }
        !           167: 
        !           168: /*
        !           169:  * Close the TU58
        !           170:  */
        !           171: tuclose(dev)
        !           172: {
        !           173: 
        !           174:        if (tutab.b_active == 0) {
        !           175:                mtpr(CSRS, 0);
        !           176:                tutimer = 0;
        !           177:        }
        !           178:        if (tu.serrs + tu.cerrs + tu.herrs != 0) {      /* any errors ? */
        !           179:                uprintf("tu%d: %d soft errors, %d chksum errors, %d hard errors\n",
        !           180:                        minor(dev), tu.serrs, tu.cerrs, tu.herrs);
        !           181:                tu.serrs = tu.cerrs = tu.herrs = 0;
        !           182:        }
        !           183: }
        !           184: 
        !           185: /*
        !           186:  * Reset the TU58
        !           187:  */
        !           188: tureset()
        !           189: {
        !           190: 
        !           191:        tu.state = INIT1;
        !           192:        tu.wbptr = tunull;
        !           193:        tu.wcnt = sizeof tunull;
        !           194:        tucmd.pk_flag = TUF_CMD;
        !           195:        tucmd.pk_mcount = sizeof tucmd - 4;
        !           196:        tucmd.pk_mod = 0;
        !           197:        tucmd.pk_seq = 0;
        !           198:        tucmd.pk_sw = MRSP ? TUSW_MRSP : 0;
        !           199:        tutab.b_active++;
        !           200:        mtpr(CSRS, 0);
        !           201:        mtpr(CSTS, IE|BREAK);
        !           202:        tuxintr();              /* start output */
        !           203:        return;
        !           204: }
        !           205: 
        !           206: /*
        !           207:  * Strategy routine for block I/O
        !           208:  */
        !           209: tustrategy(bp)
        !           210:        register struct buf *bp;
        !           211: {
        !           212:        register int s;
        !           213: 
        !           214:        if (bp->b_blkno >= NTUBLK) {    /* block number out of range? */
        !           215:                bp->b_flags |= B_ERROR;
        !           216:                iodone(bp);
        !           217:                return;
        !           218:        }
        !           219:        bp->av_forw = NULL;
        !           220:        s = splx(TUIPL);
        !           221:        if (tutab.b_actf == NULL)
        !           222:                tutab.b_actf = bp;
        !           223:        else
        !           224:                tutab.b_actl->av_forw = bp;
        !           225:        tutab.b_actl = bp;
        !           226:        if (tutab.b_active == NULL)
        !           227:                tustart();
        !           228:        splx(s);
        !           229: }
        !           230: 
        !           231: /*
        !           232:  * Start the transfer
        !           233:  */
        !           234: tustart()
        !           235: {
        !           236:        register struct buf *bp;
        !           237: 
        !           238:        if ((bp = tutab.b_actf) == NULL)
        !           239:                return;
        !           240:        if (tu.state != IDLE) {
        !           241:                tureset();
        !           242:                return;
        !           243:        }
        !           244:        tutab.b_active++;
        !           245:        tutab.b_errcnt = 0;
        !           246:        tucmd.pk_op = bp->b_flags&B_READ ? TUOP_READ : TUOP_WRITE;
        !           247:        tucmd.pk_unit = minor(bp->b_dev);
        !           248:        tucmd.pk_count = tu.count = bp->b_bcount;
        !           249:        tucmd.pk_block = bp->b_blkno;
        !           250:        tucmd.pk_chksum =
        !           251:            tuchk(*((short *)&tucmd), (caddr_t)&tucmd.pk_op,
        !           252:                (int)tucmd.pk_mcount);
        !           253:        tu.state = bp->b_flags&B_READ ? SENDR : SENDW;
        !           254:        tu.addr = bp->b_un.b_addr;
        !           255:        tu.count = bp->b_bcount;
        !           256:        tu.wbptr = (u_char *)&tucmd;
        !           257:        tu.wcnt = sizeof tucmd;
        !           258:        tuxintr();
        !           259: }
        !           260: 
        !           261: /*
        !           262:  * TU58 receiver interrupt
        !           263:  */
        !           264: turintr()
        !           265: {
        !           266:        register struct buf *bp;
        !           267:        register int c;
        !           268: 
        !           269:        c = mfpr(CSRD)&0xff;            /* get the char, clear the interrupt */
        !           270:        if (MRSP) {
        !           271:                while ((mfpr(CSTS)&READY) == 0)
        !           272:                        ;
        !           273:                mtpr(CSTD, TUF_CONT);   /* ACK */
        !           274:        }
        !           275:        if (tu.rcnt) {                  /* still waiting for data? */
        !           276:                *tu.rbptr++ = c;        /* yup, put it there */
        !           277:                if (--tu.rcnt)          /* decrement count, any left? */
        !           278:                        return;         /* get some more */
        !           279:        }
        !           280: 
        !           281:        /*
        !           282:         * We got all the data we were expecting for now,
        !           283:         * switch on the state of the transfer.
        !           284:         */
        !           285:        switch(tu.state) {
        !           286: 
        !           287:        case INIT2:
        !           288:                if (c == TUF_CONT)      /* did we get the expected continue? */
        !           289:                        tu.state = IDLE;
        !           290:                else
        !           291:                        tu.state = INIT1;       /* bad news... */
        !           292:                tu.flag = 0;
        !           293:                wakeup((caddr_t)&tu);
        !           294:                tustart();
        !           295:                break;
        !           296: 
        !           297:        case WAIT:                      /* waiting for continue */
        !           298:                if (c != TUF_CONT) {
        !           299:                        tu.state = INIT1;       /* bad news... */
        !           300:                        break;
        !           301:                }
        !           302:                tu.flag = 0;
        !           303:                tudata.pk_flag = TUF_DATA;
        !           304:                tudata.pk_mcount = MIN(128, tu.count);
        !           305:                tudata.pk_chksum =
        !           306:                    tuchk(*((short *)&tudata), (caddr_t)tu.addr,
        !           307:                        (int)tudata.pk_mcount);
        !           308:                tu.state = SENDH;
        !           309:                tu.wbptr = (u_char *)&tudata;
        !           310:                tu.wcnt = 2;
        !           311:                tuxintr();
        !           312:                break;
        !           313: 
        !           314:        case GETH:              /* got header, get data */
        !           315:                if (tudata.pk_flag == TUF_DATA)         /* data message? */
        !           316:                        tu.rbptr = (u_char *)tu.addr;   /* yes put in buffer */
        !           317:                tu.rcnt = tudata.pk_mcount;             /* amount to get */
        !           318:                tu.state = GETD;
        !           319:                break;
        !           320: 
        !           321:        case GETD:              /* got data, get checksum */
        !           322:                tu.rbptr = (u_char *)&tudata.pk_chksum;
        !           323:                tu.rcnt = sizeof tudata.pk_chksum;
        !           324:                tu.state = GETC;
        !           325:                break;
        !           326: 
        !           327:        case GET:
        !           328:        case GETC:              /* got entire packet */
        !           329: #ifdef notdef
        !           330:                if (tudata.pk_chksum !=
        !           331:                    tuchk(*((short *)&tudata),
        !           332:                     tudata.pk_flag == TUF_DATA ? tu.addr : &tudata.pk_op,
        !           333:                     (int)tudata.pk_mcount))
        !           334:                        tu.cerrs++;
        !           335: #endif
        !           336:                if (tudata.pk_flag == TUF_DATA) {
        !           337:                        /* data packet, advance to next */
        !           338:                        tu.addr += tudata.pk_mcount;
        !           339:                        tu.count -= tudata.pk_mcount;
        !           340:                        tu.state = GETH;
        !           341:                        tu.rbptr = (u_char *)&tudata;   /* next packet */
        !           342:                        tu.rcnt = 2;
        !           343:                } else if (tudata.pk_flag==TUF_CMD && tudata.pk_op==TUOP_END) {
        !           344:                        /* end packet, idle and reenable transmitter */
        !           345:                        tu.state = IDLE;
        !           346:                        tu.flag = 0;
        !           347:                        mtpr(CSTS, IE);
        !           348:                        printd("ON ");
        !           349:                        if ((bp = tutab.b_actf) == NULL) {
        !           350:                                printf("tu: no bp!\n");
        !           351:                                printf("active %d\n", tutab.b_active);
        !           352:                                tustart();
        !           353:                                return;
        !           354:                        }
        !           355:                        if (tudata.pk_mod < 0) {        /* hard error */
        !           356:                                bp->b_flags |= B_ERROR;
        !           357:                                tu.herrs++;
        !           358:                                harderr(bp, "tu");
        !           359:                                printf("  pk_mod %d\n", -tudata.pk_mod);
        !           360:                        } else if (tudata.pk_mod > 0)   /* soft error */
        !           361:                                tu.serrs++;
        !           362:                        tutab.b_active = NULL;
        !           363:                        tutab.b_actf = bp->av_forw;
        !           364:                        bp->b_resid = tu.count;
        !           365:                        iodone(bp);
        !           366:                        tustart();
        !           367:                } else {
        !           368:                        printf("neither data nor end: %o %o\n",
        !           369:                            tudata.pk_flag&0xff, tudata.pk_op&0xff);
        !           370:                        mtpr(CSRS, 0);          /* flush the rest */
        !           371:                        tu.state = INIT1;
        !           372:                }
        !           373:                break;
        !           374: 
        !           375:        case IDLE:
        !           376:        case INIT1:
        !           377:                break;
        !           378: 
        !           379:        default:
        !           380:                if (c == TUF_INITF) {
        !           381:                        printf("TU protocol error, state %d\n", tu.state);
        !           382:                        printf("%o %d %d\n",
        !           383:                            tucmd.pk_op, tucmd.pk_count, tucmd.pk_block);
        !           384:                        tutab.b_active = NULL;
        !           385:                        if (bp = tutab.b_actf) {
        !           386:                                bp->b_flags |= B_ERROR;
        !           387:                                tutab.b_actf = bp->av_forw;
        !           388:                                iodone(bp);
        !           389:                        }
        !           390:                        tu.state = INIT1;
        !           391:                } else {
        !           392:                        printf("TU receive state error %d %o\n", tu.state, c);
        !           393:                /*      tu.state = INIT1; */
        !           394:                        wakeup((caddr_t)&tu);
        !           395:                }
        !           396:        }
        !           397: }
        !           398: 
        !           399: /*
        !           400:  * TU58 transmitter interrupt
        !           401:  */
        !           402: tuxintr()
        !           403: {
        !           404: 
        !           405: top:
        !           406:        if (tu.wcnt) {
        !           407:                /* still stuff to send, send one byte */
        !           408:                while ((mfpr(CSTS) & READY) == 0)
        !           409:                        ;
        !           410:                mtpr(CSTD, *tu.wbptr++);
        !           411:                tu.wcnt--;
        !           412:                return;
        !           413:        }
        !           414: 
        !           415:        /*
        !           416:         * Last message byte was sent out.
        !           417:         * Switch on state of transfer.
        !           418:         */
        !           419:        printd("tuxintr: state %d\n", tu.state);
        !           420:        switch(tu.state) {
        !           421: 
        !           422:        case INIT1:             /* two nulls sent, remove break, send inits */
        !           423:                mtpr(CSTS, IE);
        !           424:                printd("ON2 ");
        !           425:                tu.state = INIT2;
        !           426:                tu.wbptr = tuinit;
        !           427:                tu.wcnt = sizeof tuinit;
        !           428:                goto top;
        !           429: 
        !           430:        case INIT2:             /* inits sent, wait for continue */
        !           431:                (void) mfpr(CSRD);
        !           432:                mtpr(CSRS, IE);
        !           433:                tu.flag = 1;
        !           434:                break;
        !           435: 
        !           436:        case IDLE:              /* stray interrupt? */
        !           437:                break;
        !           438: 
        !           439:        case SENDR:             /* read cmd packet sent, get ready for data */
        !           440:                tu.state = GETH;
        !           441:                tu.rbptr = (u_char *)&tudata;
        !           442:                tu.rcnt = 2;
        !           443:                tu.flag = 1;
        !           444:                mtpr(CSTS, 0);  /* disable transmitter interrupts */
        !           445:                printd("OFF ");
        !           446:                break;
        !           447: 
        !           448:        case SENDW:             /* write cmd packet sent, wait for continue */
        !           449:                tu.state = WAIT;
        !           450:                tu.flag = 1;
        !           451:                if ((mfpr(CSRS)&IE) == 0) {
        !           452:                        printf("NO IE\n");
        !           453:                        mtpr(CSRS, IE);
        !           454:                }
        !           455:                break;
        !           456: 
        !           457:        case SENDH:             /* header sent, send data */
        !           458:                tu.state = SENDD;
        !           459:                tu.wbptr = (u_char *)tu.addr;
        !           460:                tu.wcnt = tudata.pk_mcount;
        !           461:                goto top;
        !           462: 
        !           463:        case SENDD:             /* data sent, send checksum */
        !           464:                tu.state = SENDC;
        !           465:                tu.wbptr = (u_char *)&tudata.pk_chksum;
        !           466:                tu.wcnt = sizeof tudata.pk_chksum;
        !           467:                goto top;
        !           468: 
        !           469:        case SENDC:             /* checksum sent, wait for continue */
        !           470:                tu.addr += tudata.pk_mcount;    /* update buffer address */
        !           471:                tu.count -= tudata.pk_mcount;   /* and count */
        !           472:                if (tu.count == 0) {            /* all done? */
        !           473:                        tu.state = GET;         /* set up to get end packet */
        !           474:                        tu.rbptr = (u_char *)&tudata;
        !           475:                        tu.rcnt = sizeof tudata;
        !           476:                        tu.flag = 1;
        !           477:                        mtpr(CSTS, 0);
        !           478:                        printd("OFF2 ");
        !           479:                } else {
        !           480:                        tu.state = WAIT;        /* wait for continue */
        !           481:                        tu.flag = 1;
        !           482:                }
        !           483:                break;
        !           484: 
        !           485:        default:        /* random interrupt, probably from MRSP ACK */
        !           486:                break;
        !           487:        }
        !           488:        printd("  new state %d\n", tu.state);
        !           489: }
        !           490: 
        !           491: /*
        !           492:  * Compute checksum TU58 fashion
        !           493:  */
        !           494: tuchk(word, cp, n)
        !           495:        register word;
        !           496:        register unsigned short *cp;
        !           497: {
        !           498:        register c = n >> 1;
        !           499:        register long temp;
        !           500: 
        !           501:        do {
        !           502:                temp = *cp++;   /* temp, only because vax cc won't *r++ */
        !           503:                word += temp;
        !           504:        } while (--c > 0);
        !           505:        if (n & 1)
        !           506:                word += *(unsigned char *)cp;
        !           507:        while (word & 0xFFFF0000)
        !           508:                word = (word & 0xFFFF) + (word >> 16);
        !           509:        return (word);
        !           510: }
        !           511: 
        !           512: tuwatch()
        !           513: {
        !           514:        register int s;
        !           515:        register struct buf *bp;
        !           516: 
        !           517:        if (tutimer == 0) {
        !           518:                tu.flag = 0;
        !           519:                return;
        !           520:        }
        !           521:        if (tu.flag)
        !           522:                tu.flag++;
        !           523:        if (tu.flag > 40) {
        !           524:                printf("tu: read stalled\n");
        !           525:                printf("%X %X %X %X %X %X %X %X\n", tu.rbptr, tu.rcnt,
        !           526:                tu.wbptr, tu.wcnt, tu.state, tu.flag, tu.addr, tu.count);
        !           527:                tu.flag = 0;
        !           528:                s = splx(TUIPL);
        !           529:                (void) mfpr(CSRD);
        !           530:                mtpr(CSRS, IE);         /* in case we were flushing */
        !           531:                mtpr(CSTS, IE);
        !           532:                tu.state = IDLE;
        !           533:                if (tutab.b_active) {
        !           534:                        if (++tutab.b_errcnt > 1) {
        !           535:                                if (bp = tutab.b_actf) {
        !           536:                                        bp->b_flags |= B_ERROR;
        !           537:                                        iodone(bp);
        !           538:                                }
        !           539:                        } else
        !           540:                                tustart();
        !           541:                } else
        !           542:                        wakeup((caddr_t)&tu);
        !           543:                splx(s);
        !           544:        }
        !           545:        timeout(tuwatch, (caddr_t)0, hz);
        !           546: }
        !           547: #endif

unix.superglobalmegacorp.com

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