Annotation of 43BSDTahoe/sys/vaxuba/ut.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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