Annotation of researchv8dc/sys/dev/tu.c, revision 1.1

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

unix.superglobalmegacorp.com

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