Annotation of 41BSD/4.0.upgrade/sys/dev/tu.c, revision 1.1.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.