Annotation of researchv8dc/sys/dev/tu.c, revision 1.1.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.