Annotation of 42BSD/sys/vaxuba/ut.c, revision 1.1.1.1

1.1       root        1: /*     ut.c    6.1     83/07/29        */
                      2: 
                      3: #include "tj.h"
                      4: #if NUT > 0
                      5: /*
                      6:  * System Industries Model 9700 Tape Drive
                      7:  *   emulates a TU45 on the UNIBUS
                      8:  *
                      9:  * TODO:
                     10:  *     check out attention processing
                     11:  *     try reset code and dump code
                     12:  */
                     13: #include "../machine/pte.h"
                     14: 
                     15: #include "../h/param.h"
                     16: #include "../h/systm.h"
                     17: #include "../h/buf.h"
                     18: #include "../h/conf.h"
                     19: #include "../h/dir.h"
                     20: #include "../h/file.h"
                     21: #include "../h/user.h"
                     22: #include "../h/map.h"
                     23: #include "../h/ioctl.h"
                     24: #include "../h/mtio.h"
                     25: #include "../h/cmap.h"
                     26: #include "../h/uio.h"
                     27: #include "../h/kernel.h"
                     28: 
                     29: #include "../vax/cpu.h"
                     30: #include "../vaxuba/ubareg.h"
                     31: #include "../vaxuba/ubavar.h"
                     32: #include "../vaxuba/utreg.h"
                     33: 
                     34: struct buf     rutbuf[NUT];    /* bufs for raw i/o */
                     35: struct buf     cutbuf[NUT];    /* bufs for control operations */
                     36: struct buf     tjutab[NTJ];    /* bufs for slave queue headers */
                     37: 
                     38: struct uba_ctlr *utminfo[NUT];
                     39: struct uba_device *tjdinfo[NTJ];
                     40: int utprobe(), utslave(), utattach(), utdgo(), utintr(), uttimer();
                     41: u_short utstd[] = { 0772440, 0 };
                     42: struct uba_driver utdriver =
                     43:   { utprobe, utslave, utattach, utdgo, utstd, "tj", tjdinfo, "ut", utminfo, 0 };
                     44: 
                     45: #define        MASKREG(reg)    ((reg)&0xffff)
                     46: 
                     47: /* bits in minor device */
                     48: #define        TJUNIT(dev)     (minor(dev)&03)
                     49: #define        T_NOREWIND      04
                     50: #define        T_1600BPI       010
                     51: #define        T_6250BPI       020
                     52: short  utdens[] = { UT_NRZI, UT_PE, UT_GCR, UT_NRZI };
                     53: 
                     54: /* slave to controller mapping table */
                     55: short  tjtout[NTJ];
                     56: #define UTUNIT(dev)    (tjtout[TJUNIT(dev)])
                     57: 
                     58: #define        INF     (daddr_t)1000000L       /* a block number that wont exist */
                     59: 
                     60: struct tj_softc {
                     61:        char    sc_openf;       /* exclusive open */
                     62:        char    sc_lastiow;     /* last I/O operation was a write */
                     63:        daddr_t sc_blkno;       /* next block to transfer */
                     64:        daddr_t sc_nxrec;       /* next record on tape */
                     65:        u_short sc_erreg;       /* image of uter */
                     66:        u_short sc_dsreg;       /* image of utds */
                     67:        u_short sc_resid;       /* residual from transfer */
                     68:        u_short sc_dens;        /* sticky selected density */
                     69:        daddr_t sc_timo;        /* time until timeout expires */
                     70:        short   sc_tact;        /* timeout is active flag */
                     71: } tj_softc[NTJ];
                     72: 
                     73: /*
                     74:  * Internal per/slave states found in sc_state
                     75:  */
                     76: #define        SSEEK           1       /* seeking */
                     77: #define        SIO             2       /* doing sequential I/O */
                     78: #define        SCOM            3       /* sending a control command */
                     79: #define        SREW            4       /* doing a rewind op */
                     80: #define        SERASE          5       /* erase inter-record gap */
                     81: #define        SERASED         6       /* erased inter-record gap */
                     82: 
                     83: /*ARGSUSED*/
                     84: utprobe(reg)
                     85:        caddr_t reg;
                     86: {
                     87:        register int br, cvec;
                     88: #ifdef lint
                     89:        br=0; cvec=br; br=cvec;
                     90:        utintr(0);
                     91: #endif
                     92:        /*
                     93:         * The SI documentation says you must set the RDY bit
                     94:         * (even though it's read-only) to force an interrupt.
                     95:         */
                     96:        ((struct utdevice *) reg)->utcs1 = UT_IE|UT_NOP|UT_RDY;
                     97:        DELAY(10000);
                     98:        return (sizeof (struct utdevice));
                     99: }
                    100: 
                    101: /*ARGSUSED*/
                    102: utslave(ui, reg)
                    103:        struct uba_device *ui;
                    104:        caddr_t reg;
                    105: {
                    106:        /*
                    107:         * A real TU45 would support the slave present bit
                    108:         * int the drive type register, but this thing doesn't,
                    109:         * so there's no way to determine if a slave is present or not.
                    110:         */
                    111:         return(1);
                    112: }
                    113: 
                    114: utattach(ui)
                    115:        struct uba_device *ui;
                    116: {
                    117:        tjtout[ui->ui_unit] = ui->ui_mi->um_ctlr;
                    118: }
                    119: 
                    120: /*
                    121:  * Open the device with exclusive access.
                    122:  */
                    123: utopen(dev, flag)
                    124:        dev_t dev;
                    125:        int flag;
                    126: {
                    127:        register int tjunit = TJUNIT(dev);
                    128:        register struct uba_device *ui;
                    129:        register struct tj_softc *sc;
                    130:        int olddens, dens;
                    131:        register int s;
                    132: 
                    133:        if (tjunit >= NTJ || (sc = &tj_softc[tjunit])->sc_openf ||
                    134:            (ui = tjdinfo[tjunit]) == 0 || ui->ui_alive == 0)
                    135:                return (ENXIO);
                    136:        olddens = sc->sc_dens;
                    137:        dens = sc->sc_dens =
                    138:            utdens[(minor(dev)&(T_1600BPI|T_6250BPI))>>3]|
                    139:              PDP11FMT|(ui->ui_slave&07);
                    140: get:
                    141:        utcommand(dev, UT_SENSE, 1);
                    142:        if (sc->sc_dsreg&UTDS_PIP) {
                    143:                sleep((caddr_t)&lbolt, PZERO+1);
                    144:                goto get;
                    145:        }
                    146:        sc->sc_dens = olddens;
                    147:        if ((sc->sc_dsreg&UTDS_MOL) == 0) {
                    148:                uprintf("tj%d: not online\n", tjunit);
                    149:                return (EIO);
                    150:        }
                    151:        if ((flag&FWRITE) && (sc->sc_dsreg&UTDS_WRL)) {
                    152:                uprintf("tj%d: no write ring\n", tjunit);
                    153:                return (EIO);
                    154:        }
                    155:        if ((sc->sc_dsreg&UTDS_BOT) == 0 && (flag&FWRITE) &&
                    156:            dens != sc->sc_dens) {
                    157:                uprintf("tj%d: can't change density in mid-tape\n", tjunit);
                    158:                return (EIO);
                    159:        }
                    160:        sc->sc_openf = 1;
                    161:        sc->sc_blkno = (daddr_t)0;
                    162:        sc->sc_nxrec = INF;
                    163:        sc->sc_lastiow = 0;
                    164:        sc->sc_dens = dens;
                    165:        /*
                    166:         * For 6250 bpi take exclusive use of the UNIBUS.
                    167:         */
                    168:        ui->ui_driver->ud_xclu = (dens&(T_1600BPI|T_6250BPI)) == T_6250BPI;
                    169:        s = spl6();
                    170:        if (sc->sc_tact == 0) {
                    171:                sc->sc_timo = INF;
                    172:                sc->sc_tact = 1;
                    173:                timeout(uttimer, (caddr_t)dev, 5*hz);
                    174:        }
                    175:        splx(s);
                    176:        return (0);
                    177: }
                    178: 
                    179: utclose(dev, flag)
                    180:        register dev_t dev;
                    181:        register flag;
                    182: {
                    183:        register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
                    184: 
                    185:        if (flag == FWRITE || ((flag&FWRITE) && sc->sc_lastiow)) {
                    186:                utcommand(dev, UT_WEOF, 1);
                    187:                utcommand(dev, UT_WEOF, 1);
                    188:                utcommand(dev, UT_SREV, 1);
                    189:        }
                    190:        if ((minor(dev)&T_NOREWIND) == 0)
                    191:                utcommand(dev, UT_REW, 0);
                    192:        sc->sc_openf = 0;
                    193: }
                    194: 
                    195: utcommand(dev, com, count)
                    196:        dev_t dev;
                    197:        int com, count;
                    198: {
                    199:        register struct buf *bp;
                    200:        register int s;
                    201: 
                    202:        bp = &cutbuf[UTUNIT(dev)];
                    203:        s = spl5();
                    204:        while (bp->b_flags&B_BUSY) {
                    205:                if(bp->b_repcnt == 0 && (bp->b_flags&B_DONE))
                    206:                        break;
                    207:                bp->b_flags |= B_WANTED;
                    208:                sleep((caddr_t)bp, PRIBIO);
                    209:        }
                    210:        bp->b_flags = B_BUSY|B_READ;
                    211:        splx(s);
                    212:        bp->b_dev = dev;
                    213:        bp->b_command = com;
                    214:        bp->b_repcnt = count;
                    215:        bp->b_blkno = 0;
                    216:        utstrategy(bp);
                    217:        if (count == 0)
                    218:                return;
                    219:        iowait(bp);
                    220:        if (bp->b_flags&B_WANTED)
                    221:                wakeup((caddr_t)bp);
                    222:        bp->b_flags &= B_ERROR;
                    223: }
                    224: 
                    225: /*
                    226:  * Queue a tape operation.
                    227:  */
                    228: utstrategy(bp)
                    229:        register struct buf *bp;
                    230: {
                    231:        int tjunit = TJUNIT(bp->b_dev);
                    232:        register struct uba_ctlr *um;
                    233:        register struct buf *dp;
                    234: 
                    235:        /*
                    236:         * Put transfer at end of unit queue
                    237:         */
                    238:        dp = &tjutab[tjunit];
                    239:        bp->av_forw = NULL;
                    240:        (void) spl5();
                    241:        if (dp->b_actf == NULL) {
                    242:                dp->b_actf = bp;
                    243:                /*
                    244:                 * Transport not active, so...
                    245:                 * put at end of controller queue
                    246:                 */
                    247:                dp->b_forw = NULL;
                    248:                um = tjdinfo[tjunit]->ui_mi;
                    249:                if (um->um_tab.b_actf == NULL)
                    250:                        um->um_tab.b_actf = dp;
                    251:                else
                    252:                        um->um_tab.b_actl->b_forw = dp;
                    253:                um->um_tab.b_actl = dp;
                    254:        } else
                    255:                dp->b_actl->av_forw = bp;
                    256:        dp->b_actl = bp;
                    257:        /*
                    258:         * If the controller is not busy, set it going.
                    259:         */
                    260:        if (um->um_tab.b_state == 0)
                    261:                utstart(um);
                    262:        (void) spl0();
                    263: }
                    264: 
                    265: utstart(um)
                    266:        register struct uba_ctlr *um;
                    267: {
                    268:        register struct utdevice *addr;
                    269:        register struct buf *bp, *dp;
                    270:        register struct tj_softc *sc;
                    271:        struct uba_device *ui;
                    272:        int tjunit;
                    273:        daddr_t blkno;
                    274: 
                    275: loop:
                    276:        /*
                    277:         * Scan controller queue looking for units with
                    278:         * transaction queues to dispatch
                    279:         */
                    280:        if ((dp = um->um_tab.b_actf) == NULL)
                    281:                return;
                    282:        if ((bp = dp->b_actf) == NULL) {
                    283:                um->um_tab.b_actf = dp->b_forw;
                    284:                goto loop;
                    285:        }
                    286:        addr = (struct utdevice *)um->um_addr;
                    287:        tjunit = TJUNIT(bp->b_dev);
                    288:        ui = tjdinfo[tjunit];
                    289:        sc = &tj_softc[tjunit];
                    290:        /* note slave select, density, and format were merged on open */
                    291:        addr->uttc = sc->sc_dens;
                    292:        sc->sc_dsreg = addr->utds;
                    293:        sc->sc_erreg = addr->uter;
                    294:        sc->sc_resid = MASKREG(addr->utfc);
                    295:        /*
                    296:         * Default is that last command was NOT a write command;
                    297:         * if we do a write command we will notice this in utintr().
                    298:         */
                    299:        sc->sc_lastiow = 0;
                    300:        if (sc->sc_openf < 0 || (addr->utds&UTDS_MOL) == 0) {
                    301:                /*
                    302:                 * Have had a hard error on a non-raw tape
                    303:                 * or the tape unit is now unavailable
                    304:                 * (e.g. taken off line).
                    305:                 */
                    306:                bp->b_flags |= B_ERROR;
                    307:                goto next;
                    308:        }
                    309:        if (bp == &cutbuf[UTUNIT(bp->b_dev)]) {
                    310:                /*
                    311:                 * Execute a control operation with the specified
                    312:                 * count.
                    313:                 */
                    314:                if (bp->b_command == UT_SENSE)
                    315:                        goto next;
                    316:                if (bp->b_command == UT_SFORW && (addr->utds & UTDS_EOT)) {
                    317:                        bp->b_resid = bp->b_bcount;
                    318:                        goto next;
                    319:                }
                    320:                /*
                    321:                 * Set next state; handle timeouts
                    322:                 */
                    323:                if (bp->b_command == UT_REW) {
                    324:                        um->um_tab.b_state = SREW;
                    325:                        sc->sc_timo = 5*60;
                    326:                } else {
                    327:                        um->um_tab.b_state = SCOM;
                    328:                        sc->sc_timo = imin(imax(10*(int)-bp->b_repcnt,60),5*60);
                    329:                }
                    330:                /* NOTE: this depends on the ut command values */
                    331:                if (bp->b_command >= UT_SFORW && bp->b_command <= UT_SREVF)
                    332:                        addr->utfc = -bp->b_repcnt;
                    333:                goto dobpcmd;
                    334:        }
                    335:        /*
                    336:         * The following checks boundary conditions for operations
                    337:         * on non-raw tapes.  On raw tapes the initialization of
                    338:         * sc->sc_nxrec by utphys causes them to be skipped normally
                    339:         * (except in the case of retries).
                    340:         */
                    341:        if (bdbtofsb(bp->b_blkno) > sc->sc_nxrec) {
                    342:                /* can't read past end of file */
                    343:                bp->b_flags |= B_ERROR;
                    344:                bp->b_error = ENXIO;
                    345:                goto next;
                    346:        }
                    347:        if (bdbtofsb(bp->b_blkno) == sc->sc_nxrec && (bp->b_flags&B_READ)) {
                    348:                /* read at eof returns 0 count */
                    349:                bp->b_resid = bp->b_bcount;
                    350:                clrbuf(bp);
                    351:                goto next;
                    352:        }
                    353:        if ((bp->b_flags&B_READ) == 0)
                    354:                sc->sc_nxrec = bdbtofsb(bp->b_blkno)+1;
                    355:        /*
                    356:         * If the tape is correctly positioned, set up all the
                    357:         * registers but the csr, and give control over to the
                    358:         * UNIBUS adaptor routines, to wait for resources to
                    359:         * start I/O.
                    360:         */
                    361:        if ((blkno = sc->sc_blkno) == bdbtofsb(bp->b_blkno)) {
                    362:                addr->utwc = -(((bp->b_bcount)+1)>>1);
                    363:                addr->utfc = -bp->b_bcount;
                    364:                if ((bp->b_flags&B_READ) == 0) {
                    365:                        /*
                    366:                         * On write error retries erase the
                    367:                         * inter-record gap before rewriting.
                    368:                         */
                    369:                        if (um->um_tab.b_errcnt) {
                    370:                                if (um->um_tab.b_state != SERASED) {
                    371:                                        um->um_tab.b_state = SERASE;
                    372:                                        sc->sc_timo = 60;
                    373:                                        addr->utcs1 = UT_ERASE|UT_IE|UT_GO;
                    374:                                        return;
                    375:                                }
                    376:                        }
                    377:                        if (addr->utds & UTDS_EOT) {
                    378:                                bp->b_resid = bp->b_bcount;
                    379:                                um->um_tab.b_state = 0;
                    380:                                goto next;
                    381:                        }
                    382:                        um->um_cmd = UT_WCOM;
                    383:                } else
                    384:                        um->um_cmd = UT_RCOM;
                    385:                sc->sc_timo = 60;
                    386:                um->um_tab.b_state = SIO;
                    387:                (void) ubago(ui);
                    388:                return;
                    389:        }
                    390:        /*
                    391:         * Tape positioned incorrectly; seek forwards or
                    392:         * backwards to the correct spot.  This happens for
                    393:         * raw tapes only on error retries.
                    394:         */
                    395:        um->um_tab.b_state = SSEEK;
                    396:        if (blkno < bdbtofsb(bp->b_blkno)) {
                    397:                addr->utfc = blkno - bdbtofsb(bp->b_blkno);
                    398:                bp->b_command = UT_SFORW;
                    399:        } else {
                    400:                addr->utfc = bdbtofsb(bp->b_blkno) - blkno;
                    401:                bp->b_command = UT_SREV;
                    402:        }
                    403:        sc->sc_timo = imin(imax(10 * -addr->utfc, 60), 5*60);
                    404: 
                    405: dobpcmd:
                    406:        /*
                    407:         * Perform the command setup in bp.
                    408:         */
                    409:        addr->utcs1 = bp->b_command|UT_IE|UT_GO;
                    410:        return;
                    411: next:
                    412:        /*
                    413:         * Advance to the next command in the slave queue,
                    414:         * posting notice and releasing resources as needed.
                    415:         */
                    416:        if (um->um_ubinfo)
                    417:                ubadone(um);
                    418:        um->um_tab.b_errcnt = 0;
                    419:        dp->b_actf = bp->av_forw;
                    420:        iodone(bp);
                    421:        goto loop;
                    422: }
                    423: 
                    424: /*
                    425:  * Start operation on controller --
                    426:  * UNIBUS resources have been allocated.
                    427:  */
                    428: utdgo(um)
                    429:        register struct uba_ctlr *um;
                    430: {
                    431:        register struct utdevice *addr = (struct utdevice *)um->um_addr;
                    432: 
                    433:        addr->utba = (u_short) um->um_ubinfo;
                    434:        addr->utcs1 = um->um_cmd|((um->um_ubinfo>>8)&0x300)|UT_IE|UT_GO;
                    435: }
                    436: 
                    437: /*
                    438:  * Ut interrupt handler
                    439:  */
                    440: /*ARGSUSED*/
                    441: utintr(ut11)
                    442:        int ut11;
                    443: {
                    444:        struct buf *dp;
                    445:        register struct buf *bp;
                    446:        register struct uba_ctlr *um = utminfo[ut11];
                    447:        register struct utdevice *addr;
                    448:        register struct tj_softc *sc;
                    449:        u_short tjunit, cs2, cs1;
                    450:        register state;
                    451: 
                    452:        if ((dp = um->um_tab.b_actf) == NULL)
                    453:                return;
                    454:        bp = dp->b_actf;
                    455:        tjunit = TJUNIT(bp->b_dev);
                    456:        addr = (struct utdevice *)tjdinfo[tjunit]->ui_addr;
                    457:        sc = &tj_softc[tjunit];
                    458:        /*
                    459:         * Record status...
                    460:         */
                    461:        sc->sc_timo = INF;
                    462:        sc->sc_dsreg = addr->utds;
                    463:        sc->sc_erreg = addr->uter;
                    464:        sc->sc_resid = MASKREG(addr->utfc);
                    465:        if ((bp->b_flags&B_READ) == 0)
                    466:                sc->sc_lastiow = 1;
                    467:        state = um->um_tab.b_state;
                    468:        um->um_tab.b_state = 0;
                    469:        /*
                    470:         * Check for errors...
                    471:         */
                    472:        if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE)) {
                    473:                /*
                    474:                 * To clear the ERR bit, we must issue a drive clear
                    475:                 * command, and to clear the TRE bit we must set the
                    476:                 * controller clear bit.
                    477:                 */
                    478:                cs2 = addr->utcs2;
                    479:                if ((cs1 = addr->utcs1)&UT_TRE)
                    480:                        addr->utcs2 |= UTCS2_CLR;
                    481:                /* is this dangerous ?? */
                    482:                while ((addr->utcs1&UT_RDY) == 0)
                    483:                        ;
                    484:                addr->utcs1 = UT_CLEAR|UT_GO;
                    485:                /*
                    486:                 * If we were reading at 1600 or 6250 bpi and the error
                    487:                 * was corrected, then don't consider this an error.
                    488:                 */
                    489:                if (sc->sc_erreg & UTER_COR && (bp->b_flags & B_READ) &&
                    490:                    (addr->uttc & UTTC_DEN) != UT_NRZI) {
                    491:                        printf(
                    492:                          "ut%d: soft error bn%d cs1=%b er=%b cs2=%b ds=%b\n",
                    493:                          tjunit, bp->b_blkno, cs1, UT_BITS, sc->sc_erreg,
                    494:                          UTER_BITS, cs2, UTCS2_BITS, sc->sc_dsreg, UTDS_BITS);
                    495:                        sc->sc_erreg &= ~UTER_COR;
                    496:                }
                    497:                /*
                    498:                 * If we were reading from a raw tape and the only error
                    499:                 * was that the record was too long, then we don't consider
                    500:                 * this an error.
                    501:                 */
                    502:                if (bp == &rutbuf[UTUNIT(bp->b_dev)] && (bp->b_flags&B_READ) &&
                    503:                    (sc->sc_erreg&UTER_FCE))
                    504:                        sc->sc_erreg &= ~UTER_FCE;
                    505:                if (sc->sc_erreg == 0)
                    506:                        goto ignoreerr;
                    507:                /*
                    508:                 * Fix up errors which occur due to backspacing
                    509:                 * "over" the front of the tape.
                    510:                 */
                    511:                if ((sc->sc_dsreg & UTDS_BOT) && bp->b_command == UT_SREV &&
                    512:                    ((sc->sc_erreg &= ~(UTER_NEF|UTER_FCE)) == 0))
                    513:                        goto opdone;
                    514:                /*
                    515:                 * Retry soft errors up to 8 times
                    516:                 */
                    517:                if ((sc->sc_erreg&UTER_HARD) == 0 && state == SIO) {
                    518:                        if (++um->um_tab.b_errcnt < 7) {
                    519:                                sc->sc_blkno++;
                    520:                                ubadone(um);
                    521:                                goto opcont;
                    522:                        }
                    523:                }
                    524:                /*
                    525:                 * Hard or non-I/O errors on non-raw tape
                    526:                 * cause it to close.
                    527:                 */
                    528:                if (sc->sc_openf > 0 && bp != &rutbuf[UTUNIT(bp->b_dev)])
                    529:                        sc->sc_openf = -1;
                    530:                /*
                    531:                 * Couldn't recover error.
                    532:                 */
                    533:                printf("ut%d: hard error bn%d cs1=%b er=%b cs2=%b ds=%b\n",
                    534:                        tjunit, bp->b_blkno, cs1, UT_BITS, sc->sc_erreg,
                    535:                        UTER_BITS, cs2, UTCS2_BITS, sc->sc_dsreg, UTDS_BITS);
                    536:                bp->b_flags |= B_ERROR;
                    537:                goto opdone;
                    538:        }
                    539: 
                    540: ignoreerr:
                    541:        /*
                    542:         * If we hit a tape mark update our position.
                    543:         */
                    544:        if (sc->sc_dsreg & UTDS_TM && bp->b_flags & B_READ) {
                    545:                /*
                    546:                 * Set blkno and nxrec
                    547:                 */
                    548:                if (bp == &cutbuf[UTUNIT(bp->b_dev)]) {
                    549:                        if (sc->sc_blkno > bdbtofsb(bp->b_blkno)) {
                    550:                                sc->sc_nxrec =
                    551:                                     bdbtofsb(bp->b_blkno) - addr->utfc;
                    552:                                sc->sc_blkno = sc->sc_nxrec;
                    553:                        } else {
                    554:                                sc->sc_blkno =
                    555:                                     bdbtofsb(bp->b_blkno) + addr->utfc;
                    556:                                sc->sc_nxrec = sc->sc_blkno-1;
                    557:                        }
                    558:                } else
                    559:                        sc->sc_nxrec = bdbtofsb(bp->b_blkno);
                    560:                /*
                    561:                 * Note: if we get a tape mark on a read, the
                    562:                 * frame count register will be zero, so b_resid
                    563:                 * will be calculated correctly below.
                    564:                 */
                    565:                goto opdone;
                    566:        }
                    567:        /*
                    568:         * Advance tape control FSM.
                    569:         */
                    570:        switch (state) {
                    571: 
                    572:        case SIO:               /* read/write increments tape block # */
                    573:                sc->sc_blkno++;
                    574:                break;
                    575: 
                    576:        case SCOM:              /* motion commands update current position */
                    577:                if (bp == &cutbuf[UTUNIT(bp->b_dev)])
                    578:                switch (bp->b_command) {
                    579: 
                    580:                case UT_SFORW:
                    581:                        sc->sc_blkno -= bp->b_repcnt;
                    582:                        break;
                    583: 
                    584:                case UT_SREV:
                    585:                        sc->sc_blkno += bp->b_repcnt;
                    586:                        break;
                    587: 
                    588:                case UT_REWOFFL:
                    589:                        addr->utcs1 = UT_CLEAR|UT_GO;
                    590:                        break;
                    591:                }
                    592:                break;
                    593: 
                    594:        case SSEEK:
                    595:                sc->sc_blkno = bdbtofsb(bp->b_blkno);
                    596:                goto opcont;
                    597: 
                    598:        case SERASE:
                    599:                /*
                    600:                 * Completed erase of the inter-record gap due to a
                    601:                 * write error; now retry the write operation.
                    602:                 */
                    603:                um->um_tab.b_state = SERASED;
                    604:                goto opcont;
                    605: 
                    606:        case SREW:                      /* clear attention bit */
                    607:                addr->utcs1 = UT_CLEAR|UT_GO;
                    608:                break;
                    609: 
                    610:        default:
                    611:                printf("bad state %d\n", state);
                    612:                panic("utintr");
                    613:        }
                    614: 
                    615: opdone:
                    616:        /*
                    617:         * Reset error count and remove
                    618:         * from device queue
                    619:         */
                    620:        um->um_tab.b_errcnt = 0;
                    621:        dp->b_actf = bp->av_forw;
                    622:        /*
                    623:         * For read command, frame count register contains
                    624:         * actual length of tape record.  Otherwise, it
                    625:         * holds negative residual count.
                    626:         */
                    627:        if (state == SIO && um->um_cmd == UT_RCOM) {
                    628:                bp->b_resid = 0;
                    629:                if (bp->b_bcount > MASKREG(addr->utfc))
                    630:                        bp->b_resid = bp->b_bcount - MASKREG(addr->utfc);
                    631:        } else
                    632:                bp->b_resid = MASKREG(-addr->utfc);
                    633:        ubadone(um);
                    634:        iodone(bp);
                    635:        /*
                    636:         * Circulate slave to end of controller queue
                    637:         * to give other slaves a chance
                    638:         */
                    639:        um->um_tab.b_actf = dp->b_forw;
                    640:        if (dp->b_actf) {
                    641:                dp->b_forw = NULL;
                    642:                if (um->um_tab.b_actf == NULL)
                    643:                        um->um_tab.b_actf = dp;
                    644:                else
                    645:                        um->um_tab.b_actl->b_forw = dp;
                    646:                um->um_tab.b_actl = dp;
                    647:        }
                    648:        if (um->um_tab.b_actf == 0)
                    649:                return;
                    650: opcont:
                    651:        utstart(um);
                    652: }
                    653: 
                    654: /*
                    655:  * Watchdog timer routine.
                    656:  */
                    657: uttimer(dev)
                    658:        int dev;
                    659: {
                    660:        register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
                    661:        register short x;
                    662: 
                    663:        if (sc->sc_timo != INF && (sc->sc_timo -= 5) < 0) {
                    664:                printf("tj%d: lost interrupt\n", TJUNIT(dev));
                    665:                sc->sc_timo = INF;
                    666:                x = spl5();
                    667:                utintr(UTUNIT(dev));
                    668:                (void) splx(x);
                    669:        }
                    670:        timeout(uttimer, (caddr_t)dev, 5*hz);
                    671: }
                    672: 
                    673: /*
                    674:  * Raw interface for a read
                    675:  */
                    676: utread(dev, uio)
                    677:        dev_t dev;
                    678:        struct uio *uio;
                    679: {
                    680:        int errno;
                    681: 
                    682:        errno = utphys(dev, uio);
                    683:        if (errno)
                    684:                return (errno);
                    685:        return (physio(utstrategy, &rutbuf[UTUNIT(dev)], dev, B_READ, minphys, uio));
                    686: }
                    687: 
                    688: /*
                    689:  * Raw interface for a write
                    690:  */
                    691: utwrite(dev, uio)
                    692:        dev_t dev;
                    693:        struct uio *uio;
                    694: {
                    695:        int errno;
                    696: 
                    697:        errno = utphys(dev, uio);
                    698:        if (errno)
                    699:                return (errno);
                    700:        return (physio(utstrategy, &rutbuf[UTUNIT(dev)], dev, B_WRITE, minphys, uio));
                    701: }
                    702: 
                    703: /*
                    704:  * Check for valid device number dev and update our notion
                    705:  * of where we are on the tape
                    706:  */
                    707: utphys(dev, uio)
                    708:        dev_t dev;
                    709:        struct uio *uio;
                    710: {
                    711:        register int tjunit = TJUNIT(dev);
                    712:        register struct tj_softc *sc;
                    713:        register struct uba_device *ui;
                    714: 
                    715:        if (tjunit >= NTJ || (ui=tjdinfo[tjunit]) == 0 || ui->ui_alive == 0)
                    716:                return (ENXIO);
                    717:        sc = &tj_softc[tjunit];
                    718:        sc->sc_blkno = bdbtofsb(uio->uio_offset>>9);
                    719:        sc->sc_nxrec = sc->sc_blkno+1;
                    720:        return (0);
                    721: }
                    722: 
                    723: /*ARGSUSED*/
                    724: utioctl(dev, cmd, data, flag)
                    725:        dev_t dev;
                    726:        caddr_t data;
                    727: {
                    728:        register struct tj_softc *sc = &tj_softc[TJUNIT(dev)];
                    729:        register struct buf *bp = &cutbuf[UTUNIT(dev)];
                    730:        register callcount;
                    731:        int fcount;
                    732:        struct mtop *mtop;
                    733:        struct mtget *mtget;
                    734:        /* we depend of the values and order of the MT codes here */
                    735:        static utops[] =
                    736:       {UT_WEOF,UT_SFORWF,UT_SREVF,UT_SFORW,UT_SREV,UT_REW,UT_REWOFFL,UT_SENSE};
                    737: 
                    738:        switch (cmd) {
                    739: 
                    740:        case MTIOCTOP:
                    741:                mtop = (struct mtop *)data;
                    742:                switch(mtop->mt_op) {
                    743: 
                    744:                case MTWEOF:
                    745:                case MTFSF: case MTBSF:
                    746:                case MTFSR: case MTBSR:
                    747:                        callcount = mtop->mt_count;
                    748:                        fcount = 1;
                    749:                        break;
                    750: 
                    751:                case MTREW: case MTOFFL: case MTNOP:
                    752:                        callcount = 1;
                    753:                        fcount = 1;
                    754:                        break;
                    755: 
                    756:                default:
                    757:                        return (ENXIO);
                    758:                }
                    759:                if (callcount <= 0 || fcount <= 0)
                    760:                        return (EINVAL);
                    761:                while (--callcount >= 0) {
                    762:                        utcommand(dev, utops[mtop->mt_op], fcount);
                    763:                        if ((bp->b_flags&B_ERROR) || (sc->sc_dsreg&UTDS_BOT))
                    764:                                break;
                    765:                }
                    766:                return (geterror(bp));
                    767: 
                    768:        case MTIOCGET:
                    769:                mtget = (struct mtget *)data;
                    770:                mtget->mt_dsreg = sc->sc_dsreg;
                    771:                mtget->mt_erreg = sc->sc_erreg;
                    772:                mtget->mt_resid = sc->sc_resid;
                    773:                mtget->mt_type = MT_ISUT;
                    774:                break;
                    775: 
                    776:        default:
                    777:                return (ENXIO);
                    778:        }
                    779:        return (0);
                    780: }
                    781: 
                    782: utreset(uban)
                    783:        int uban;
                    784: {
                    785:        register struct uba_ctlr *um;
                    786:        register ut11, tjunit;
                    787:        register struct uba_device *ui;
                    788:        register struct buf *dp;
                    789: 
                    790:        for (ut11 = 0; ut11 < NUT; ut11++) {
                    791:                if ((um = utminfo[ut11]) == 0 || um->um_alive == 0 ||
                    792:                   um->um_ubanum != uban)
                    793:                        continue;
                    794:                printf(" ut%d", ut11);
                    795:                um->um_tab.b_state = 0;
                    796:                um->um_tab.b_actf = um->um_tab.b_actl = 0;
                    797:                if (um->um_ubinfo) {
                    798:                        printf("<%d>", (um->um_ubinfo>>28)&0xf);
                    799:                        um->um_ubinfo = 0;
                    800:                }
                    801:                ((struct utdevice *)(um->um_addr))->utcs1 = UT_CLEAR|UT_GO;
                    802:                ((struct utdevice *)(um->um_addr))->utcs2 |= UTCS2_CLR;
                    803:                for (tjunit = 0; tjunit < NTJ; tjunit++) {
                    804:                        if ((ui = tjdinfo[tjunit]) == 0 || ui->ui_mi != um ||
                    805:                            ui->ui_alive == 0)
                    806:                                continue;
                    807:                        dp = &tjutab[tjunit];
                    808:                        dp->b_state = 0;
                    809:                        dp->b_forw = 0;
                    810:                        if (um->um_tab.b_actf == NULL)
                    811:                                um->um_tab.b_actf = dp;
                    812:                        else
                    813:                                um->um_tab.b_actl->b_forw = dp;
                    814:                        um->um_tab.b_actl = dp;
                    815:                        if (tj_softc[tjunit].sc_openf > 0)
                    816:                                tj_softc[tjunit].sc_openf = -1;
                    817:                }
                    818:                utstart(um);
                    819:        }
                    820: }
                    821: 
                    822: /*
                    823:  * Do a stand-alone core dump to tape --
                    824:  * from here down, routines are used only in dump context
                    825:  */
                    826: #define        DBSIZE  20
                    827: 
                    828: utdump()
                    829: {
                    830:        register struct uba_device *ui;
                    831:        register struct uba_regs *up;
                    832:        register struct utdevice *addr;
                    833:        int blk, num = maxfree;
                    834:        int start = 0;
                    835: 
                    836: #define        phys(a,b)               ((b)((int)(a)&0x7fffffff))
                    837:        if (tjdinfo[0] == 0)
                    838:                return (ENXIO);
                    839:        ui = phys(tjdinfo[0], struct uba_device *);
                    840:        up = phys(ui->ui_hd, struct uba_hd *)->uh_physuba;
                    841:        ubainit(up);
                    842:        DELAY(1000000);
                    843:        addr = (struct utdevice *)ui->ui_physaddr;
                    844:        utwait(addr);
                    845:        /*
                    846:         * Be sure to set the appropriate density here.  We use
                    847:         * 6250, but maybe it should be done at 1600 to insure the
                    848:         * tape can be read by most any other tape drive available.
                    849:         */
                    850:        addr->uttc = UT_GCR|PDP11FMT;   /* implicit slave 0 or-ed in */
                    851:        addr->utcs1 = UT_CLEAR|UT_GO;
                    852:        while (num > 0) {
                    853:                blk = num > DBSIZE ? DBSIZE : num;
                    854:                utdwrite(start, blk, addr, up);
                    855:                if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))
                    856:                        return(EIO);
                    857:                start += blk;
                    858:                num -= blk;
                    859:        }
                    860:        uteof(addr);
                    861:        uteof(addr);
                    862:        utwait(addr);
                    863:        if ((addr->utds&UTDS_ERR) || (addr->utcs1&UT_TRE))
                    864:                return(EIO);
                    865:        addr->utcs1 = UT_REW|UT_GO;
                    866:        return (0);
                    867: }
                    868: 
                    869: utdwrite(dbuf, num, addr, up)
                    870:        register dbuf, num;
                    871:        register struct utdevice *addr;
                    872:        struct uba_regs *up;
                    873: {
                    874:        register struct pte *io;
                    875:        register int npf;
                    876: 
                    877:        utwait(addr);
                    878:        io = up->uba_map;
                    879:        npf = num + 1;
                    880:        while (--npf != 0)
                    881:                *(int *)io++ = (dbuf++ | (1<<UBAMR_DPSHIFT) | UBAMR_MRV);
                    882:        *(int *)io = 0;
                    883:        addr->utwc = -((num*NBPG)>>1);
                    884:        addr->utfc = -(num*NBPG);
                    885:        addr->utba = 0;
                    886:        addr->utcs1 = UT_WCOM|UT_GO;
                    887: }
                    888: 
                    889: utwait(addr)
                    890:        struct utdevice *addr;
                    891: {
                    892:        register s;
                    893: 
                    894:        do
                    895:                s = addr->utds;
                    896:        while ((s&UTDS_DRY) == 0);
                    897: }
                    898: 
                    899: uteof(addr)
                    900:        struct utdevice *addr;
                    901: {
                    902: 
                    903:        utwait(addr);
                    904:        addr->utcs1 = UT_WEOF|UT_GO;
                    905: }
                    906: #endif

unix.superglobalmegacorp.com

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