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

1.1     ! root        1: /*     mt.c    6.1.1   84/03/28        */
        !             2: 
        !             3: #include "mu.h"
        !             4: #if NMT > 0
        !             5: /*
        !             6:  * TM78/TU78 tape driver
        !             7:  *
        !             8:  *     Original author - ?
        !             9:  *     Most error recovery bug fixes - ggs (ulysses!ggs)
        !            10:  *
        !            11:  * OPTIONS:
        !            12:  *     MTLERRM - Long error message text - twd, Brown University
        !            13:  *     MTRDREV - `read reverse' error recovery - ggs (ulysses!ggs)
        !            14:  *
        !            15:  * TODO:
        !            16:  *     Add odd byte count kludge from VMS driver (?)
        !            17:  *     Write dump routine
        !            18:  */
        !            19: 
        !            20: #define MTLERRM 0
        !            21: #define MTRDREV 0
        !            22: 
        !            23: #include "../h/param.h"
        !            24: #include "../h/systm.h"
        !            25: #include "../h/buf.h"
        !            26: #include "../h/conf.h"
        !            27: #include "../h/dir.h"
        !            28: #include "../h/file.h"
        !            29: #include "../h/user.h"
        !            30: #include "../h/map.h"
        !            31: #include "../h/pte.h"
        !            32: #include "../h/mbareg.h"
        !            33: #include "../h/mbavar.h"
        !            34: #include "../h/mtio.h"
        !            35: #include "../h/ioctl.h"
        !            36: #include "../h/cmap.h"
        !            37: #include "../h/cpu.h"
        !            38: 
        !            39: #include "../h/mtreg.h"
        !            40: 
        !            41: #define MTTIMEOUT      10000           /* loop limit for controller test */
        !            42: #define        INF             1000000L        /* a block number that won't exist */
        !            43: #define MASKREG(r)     ((r) & 0xffff)  /* the control registers have 16 bits */
        !            44: 
        !            45: /* Bits for sc_flags */
        !            46: 
        !            47: #define        H_WRITTEN       01              /* last operation was a write */
        !            48: #define H_EOT          02              /* end of tape encountered */
        !            49: #define H_IEOT         04              /* ignore EOT condition */
        !            50: 
        !            51: /* Bits in minor device */
        !            52: 
        !            53: #define        MUUNIT(dev)     (minor(dev)&03)
        !            54: #define        H_NOREWIND      04
        !            55: #define        H_6250BPI       010
        !            56: 
        !            57: #define MTUNIT(dev)    (mutomt[MUUNIT(dev)])
        !            58: 
        !            59: #ifdef MTRDREV
        !            60:        int mt_do_readrev = 1;
        !            61: #else
        !            62:        int mt_do_readrev = 0;
        !            63: #endif
        !            64: 
        !            65: /* Per unit status information */
        !            66: 
        !            67: struct mu_softc {
        !            68:        char    sc_openf;               /* unit is open if != 0 */
        !            69:        char    sc_flags;               /* state flags */
        !            70:        daddr_t sc_blkno;               /* current physical block number */
        !            71:        daddr_t sc_nxrec;               /* firewall input block number */
        !            72:        int     sc_erreg;               /* copy of mter or mtner */
        !            73:        int     sc_dsreg;               /* copy of mtds */
        !            74:        short   sc_resid;               /* residual function count for ioctl */
        !            75:        short   sc_dens;                /* density code - MT_GCR or zero */
        !            76:        struct  mba_device *sc_mi;      /* massbus structure for unit */
        !            77:        int     sc_slave;               /* slave number for unit */
        !            78:        int     sc_i_mtas;              /* mtas at slave attach time */
        !            79:        int     sc_i_mtner;             /* mtner at slave attach time */
        !            80:        int     sc_i_mtds;              /* mtds at slave attach time */
        !            81: #ifdef MTLERRM
        !            82:        char    *sc_mesg;               /* text for interrupt type code */
        !            83:        char    *sc_fmesg;              /* text for tape error code */
        !            84: #endif
        !            85: } mu_softc[NMU];
        !            86: 
        !            87: struct buf     rmtbuf[NMT];            /* data transfer buffer structures */
        !            88: struct buf     cmtbuf[NMT];            /* tape command buffer structures */
        !            89: 
        !            90: struct mba_device *mtinfo[NMT];        /* unit massbus structure pointers */
        !            91: short  mutomt[NMU];                    /* tape unit to controller number map */
        !            92: char   mtds_bits[] = MTDS_BITS;        /* mtds bit names for error messages */
        !            93: short  mttypes[] = { MBDT_TU78, 0 };
        !            94: 
        !            95: int    mtattach(), mtslave(), mtustart(), mtstart(), mtndtint(), mtdtint();
        !            96: struct mba_driver mtdriver =
        !            97:        { mtattach, mtslave, mtustart, mtstart, mtdtint, mtndtint,
        !            98:          mttypes, "mt", "mu", mtinfo };
        !            99: 
        !           100: void mtcreset();
        !           101: 
        !           102: /*ARGSUSED*/
        !           103: mtattach(mi)
        !           104:        struct mba_device *mi;
        !           105: {
        !           106: #ifdef lint
        !           107:        mtread(0); mtwrite(0); mtioctl(0, 0, 0, 0);
        !           108: #endif
        !           109: }
        !           110: 
        !           111: mtslave(mi, ms)
        !           112:        struct mba_device *mi;
        !           113:        struct mba_slave *ms;
        !           114: {
        !           115:        register struct mu_softc *sc = &mu_softc[ms->ms_unit];
        !           116:        register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
        !           117:        int s = spl7(), rtn = 0, i;
        !           118: 
        !           119:        /* Just in case the controller is ill, reset it.  Then issue    */
        !           120:        /* a sense operation and wait about a second for it to respond. */
        !           121: 
        !           122:        mtcreset(mtaddr);
        !           123:        mtaddr->mtas = -1;
        !           124:        mtaddr->mtncs[ms->ms_slave] = MT_SENSE|MT_GO;
        !           125:        for (i = MTTIMEOUT; i> 0; i--) {
        !           126:                DELAY(50);
        !           127:                if (MASKREG(mtaddr->mtas) != 0)
        !           128:                        break;
        !           129:        }
        !           130:        sc->sc_i_mtas = mtaddr->mtas;
        !           131:        sc->sc_i_mtner = mtaddr->mtner;
        !           132:        sc->sc_i_mtds = mtaddr->mtds;
        !           133: 
        !           134:        /* If no response, whimper.  If wrong response, call it an      */
        !           135:        /* unsolicited interrupt and use mtndtint to log and correct.   */
        !           136:        /* Otherwise, note whether this slave exists.                   */
        !           137: 
        !           138:        if (i <= 0) {
        !           139:                printf("mt: controller hung\n");
        !           140:        } else if ((mtaddr->mtner & MTER_INTCODE) != MTER_DONE) {
        !           141:                (void) mtndtint(mi);
        !           142:        } else if (mtaddr->mtds & MTDS_PRES) {
        !           143:                sc->sc_mi = mi;
        !           144:                sc->sc_slave = ms->ms_slave;
        !           145:                mutomt[ms->ms_unit] = mi->mi_unit;
        !           146:                rtn = 1;
        !           147:        }
        !           148: 
        !           149:        /* Cancel the interrupt, then wait a little while for it to go away. */
        !           150: 
        !           151:        mtaddr->mtas = mtaddr->mtas;
        !           152:        DELAY(10);
        !           153:        splx(s);
        !           154:        return (rtn);
        !           155: }
        !           156: 
        !           157: mtopen(dev, flag)
        !           158:        dev_t dev;
        !           159:        int flag;
        !           160: {
        !           161:        register int muunit;
        !           162:        register struct mba_device *mi;
        !           163:        register struct mu_softc *sc;
        !           164: 
        !           165:        muunit = MUUNIT(dev);
        !           166:        if (   (muunit >= NMU)
        !           167:            || ((mi = mtinfo[MTUNIT(dev)]) == 0)
        !           168:            || (mi->mi_alive == 0) ) {
        !           169:                u.u_error = ENXIO;
        !           170:                return;
        !           171:        }
        !           172:        if ((sc = &mu_softc[muunit])->sc_openf) {
        !           173:                u.u_error = EBUSY;
        !           174:                return;
        !           175:        }
        !           176:        sc->sc_dens = (minor(dev) & H_6250BPI) ? MT_GCR : 0;
        !           177:        mtcommand(dev, MT_SENSE, 1);
        !           178:        if ((sc->sc_dsreg & MTDS_ONL) == 0) {
        !           179:                uprintf("mu%d: not online\n", muunit);
        !           180:                u.u_error = EIO;
        !           181:                return;
        !           182:        }
        !           183:        if ((sc->sc_dsreg & MTDS_AVAIL) == 0) {
        !           184:                uprintf("mu%d: not online (port selector)\n", muunit);
        !           185:                u.u_error = EIO;
        !           186:                return;
        !           187:        }
        !           188:        if ((flag & FWRITE) && (sc->sc_dsreg & MTDS_FPT)) {
        !           189:                uprintf("mu%d: no write ring\n", muunit);
        !           190:                u.u_error = EIO;
        !           191:                return;
        !           192:        }
        !           193:        if (   ((sc->sc_dsreg & MTDS_BOT) == 0)
        !           194:            && (flag & FWRITE)
        !           195:            && (   (   (sc->sc_dens == MT_GCR)
        !           196:                    && (sc->sc_dsreg & MTDS_PE) )
        !           197:                || (   (sc->sc_dens != MT_GCR)
        !           198:                    && ((sc->sc_dsreg & MTDS_PE) == 0)))) {
        !           199:                uprintf("mu%d: can't change density in mid-tape\n", muunit);
        !           200:                u.u_error = EIO;
        !           201:                return;
        !           202:        }
        !           203:        sc->sc_openf = 1;
        !           204:        sc->sc_blkno = (daddr_t)0;
        !           205: 
        !           206:        /* Since cooked I/O may do a read-ahead before a write, trash   */
        !           207:        /* on a tape can make the first write fail.  Suppress the first */
        !           208:        /* read-ahead unless definitely doing read-write                */
        !           209: 
        !           210:        sc->sc_nxrec =  ((flag & (FREAD | FWRITE)) == FWRITE)
        !           211:                      ? (daddr_t)0
        !           212:                      : (daddr_t)INF;
        !           213:        sc->sc_flags = 0;
        !           214: }
        !           215: 
        !           216: mtclose(dev, flag)
        !           217:        register dev_t dev;
        !           218:        register int flag;
        !           219: {
        !           220:        register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
        !           221: 
        !           222:        if (   ((flag & (FREAD | FWRITE)) == FWRITE)
        !           223:            || (   (flag & FWRITE)
        !           224:                && (sc->sc_flags & H_WRITTEN) ))
        !           225:                mtcommand(dev, MT_CLS|sc->sc_dens, 1);
        !           226:        if ((minor(dev) & H_NOREWIND) == 0)
        !           227:                mtcommand(dev, MT_REW, 0);
        !           228:        sc->sc_openf = 0;
        !           229: }
        !           230: 
        !           231: mtcommand(dev, com, count)
        !           232:        dev_t dev;
        !           233:        int com, count;
        !           234: {
        !           235:        register struct buf *bp;
        !           236:        register int s;
        !           237: 
        !           238:        bp = &cmtbuf[MTUNIT(dev)];
        !           239:        s = spl5();
        !           240:        while (bp->b_flags & B_BUSY) {
        !           241:                if((bp->b_repcnt == 0) && (bp->b_flags & B_DONE))
        !           242:                        break;
        !           243:                bp->b_flags |= B_WANTED;
        !           244:                sleep((caddr_t)bp, PRIBIO);
        !           245:        }
        !           246:        bp->b_flags = B_BUSY|B_READ;
        !           247:        splx(s);
        !           248:        bp->b_dev = dev;
        !           249:        bp->b_command = com;
        !           250:        bp->b_repcnt = count;
        !           251:        bp->b_blkno = 0;
        !           252:        bp->b_error = 0;
        !           253:        mtstrategy(bp);
        !           254:        if (count == 0)
        !           255:                return;
        !           256:        iowait(bp);
        !           257:        if (bp->b_flags & B_WANTED)
        !           258:                wakeup((caddr_t)bp);
        !           259:        bp->b_flags &= B_ERROR;
        !           260: }
        !           261: 
        !           262: mtstrategy(bp)
        !           263:        register struct buf *bp;
        !           264: {
        !           265:        register struct mba_device *mi = mtinfo[MTUNIT(bp->b_dev)];
        !           266:        register struct buf *dp;
        !           267:        register int s;
        !           268: 
        !           269:        /* If this is a data transfer operation, set the resid to a     */
        !           270:        /* default value (EOF) to simplify getting it right during      */
        !           271:        /* error recovery or bail out.                                  */
        !           272: 
        !           273:        if (bp != &cmtbuf[MTUNIT(bp->b_dev)])
        !           274:                bp->b_resid = bp->b_bcount;
        !           275: 
        !           276:        /* Link this request onto the end of the queue for this         */
        !           277:        /* controller, then start I/O if not already active.            */
        !           278: 
        !           279:        bp->av_forw = NULL;
        !           280:        dp = &mi->mi_tab;
        !           281:        s = spl5();
        !           282:        if (dp->b_actf == NULL)
        !           283:                dp->b_actf = bp;
        !           284:        else
        !           285:                dp->b_actl->av_forw = bp;
        !           286:        dp->b_actl = bp;
        !           287:        if (dp->b_active == 0)
        !           288:                mbustart(mi);
        !           289:        splx(s);
        !           290: }
        !           291: 
        !           292: mtustart(mi)
        !           293:        register struct mba_device *mi;
        !           294: {
        !           295:        register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
        !           296:        register struct buf *bp = mi->mi_tab.b_actf;
        !           297:        register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
        !           298:        daddr_t blkno;
        !           299: 
        !           300:        if (sc->sc_openf < 0) {
        !           301:                bp->b_flags |= B_ERROR;
        !           302:                return (MBU_NEXT);
        !           303:        }
        !           304:        if (bp != &cmtbuf[MTUNIT(bp->b_dev)]) {
        !           305: 
        !           306:                /* Signal "no space" if out of tape unless suppressed   */
        !           307:                /* by MTIOCIEOT.                                        */
        !           308: 
        !           309:                if (   ((sc->sc_flags & (H_EOT | H_IEOT)) == H_EOT)
        !           310:                    && ((bp->b_flags & B_READ) == 0) ) {
        !           311:                        bp->b_flags |= B_ERROR;
        !           312:                        bp->b_error = ENOSPC;
        !           313:                        return (MBU_NEXT);
        !           314:                }
        !           315: 
        !           316:                /* special case tests for cooked mode */
        !           317: 
        !           318:                if (bp != &rmtbuf[MTUNIT(bp->b_dev)]) {
        !           319: 
        !           320:                        /* seek beyond end of file */
        !           321: 
        !           322:                        if (dbtofsb(0, bp->b_blkno) > sc->sc_nxrec) {
        !           323:                                bp->b_flags |= B_ERROR;
        !           324:                                bp->b_error = ENXIO;
        !           325:                                return (MBU_NEXT);
        !           326:                        }
        !           327: 
        !           328:                        /* This should be end of file, but the buffer      */
        !           329:                        /* system wants a one-block look-ahead.  Humor it. */
        !           330: 
        !           331:                        if (   (dbtofsb(0, bp->b_blkno) == sc->sc_nxrec)
        !           332:                            && (bp->b_flags & B_READ) ) {
        !           333:                                clrbuf(bp);
        !           334:                                return (MBU_NEXT);
        !           335:                        }
        !           336: 
        !           337:                        /* If writing, mark the next block invalid. */
        !           338: 
        !           339:                        if ((bp->b_flags & B_READ) == 0)
        !           340:                                sc->sc_nxrec = dbtofsb(0, bp->b_blkno) + 1;
        !           341:                }
        !           342:        } else {
        !           343: 
        !           344:                /* It's a command, do it now. */
        !           345: 
        !           346:                mtaddr->mtncs[MUUNIT(bp->b_dev)] =
        !           347:                        (bp->b_repcnt<<8)|bp->b_command|MT_GO;
        !           348:                return (MBU_STARTED);
        !           349:        }
        !           350: 
        !           351:        /* If raw I/O, or if the tape is positioned correctly for       */
        !           352:        /* cooked I/O, set the byte count, unit number and repeat count */
        !           353:        /* then tell the MASSBUS to proceed.  Note that a negative      */
        !           354:        /* bcount tells mbstart to map the buffer for "read backwards". */
        !           355: 
        !           356:        if (   (bp == &rmtbuf[MTUNIT(bp->b_dev)])
        !           357:            || ((blkno = sc->sc_blkno) == dbtofsb(0, bp->b_blkno)) ) {
        !           358:                if (mi->mi_tab.b_errcnt == 2) {
        !           359:                        mtaddr->mtbc = -(bp->b_bcount);
        !           360:                        mtaddr->mtca = MUUNIT(bp->b_dev);
        !           361:                } else {
        !           362:                        mtaddr->mtbc = bp->b_bcount;
        !           363:                        mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev);
        !           364:                }
        !           365:                return (MBU_DODATA);
        !           366:        }
        !           367: 
        !           368:        /* Issue skip operations to position the next block for cooked I/O. */
        !           369: 
        !           370:        if (blkno < dbtofsb(0, bp->b_blkno))
        !           371:                mtaddr->mtncs[MUUNIT(bp->b_dev)] =
        !           372:                  (min(dbtofsb(0, bp->b_blkno) - blkno, 0377)<<8)| MT_SFORW|MT_GO;
        !           373:        else
        !           374:                mtaddr->mtncs[MUUNIT(bp->b_dev)] =
        !           375:                  (min(blkno - dbtofsb(0, bp->b_blkno), 0377)<<8)| MT_SREV|MT_GO;
        !           376:        return (MBU_STARTED);
        !           377: }
        !           378: 
        !           379: mtstart(mi)
        !           380:        register struct mba_device *mi;
        !           381: {
        !           382:        register struct buf *bp = mi->mi_tab.b_actf;
        !           383:        register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)];
        !           384: 
        !           385:        if (bp->b_flags & B_READ)
        !           386:                if (mi->mi_tab.b_errcnt == 2)
        !           387:                        return(MT_READREV|MT_GO);
        !           388:                else
        !           389:                        return(MT_READ|MT_GO);
        !           390:        else
        !           391:                return(MT_WRITE|sc->sc_dens|MT_GO);
        !           392: }
        !           393: 
        !           394: mtdtint(mi, mbsr)
        !           395:        register struct mba_device *mi;
        !           396:        int mbsr;
        !           397: {
        !           398:        register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
        !           399:        register struct buf *bp = mi->mi_tab.b_actf;
        !           400:        register struct mu_softc *sc;
        !           401:        register int er;
        !           402: 
        !           403:        /* I'M still NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */
        !           404: 
        !           405:        if ((mtaddr->mtca & 3) != MUUNIT(bp->b_dev)) {
        !           406:                printf("mt: wrong unit!\n");
        !           407:                mtaddr->mtca = MUUNIT(bp->b_dev);
        !           408:        }
        !           409: 
        !           410:        er = MASKREG(mtaddr->mter);
        !           411:        sc = &mu_softc[MUUNIT(bp->b_dev)];
        !           412:        sc->sc_erreg = er;
        !           413:        if (bp->b_flags & B_READ)
        !           414:                sc->sc_flags &= ~H_WRITTEN;
        !           415:        else
        !           416:                sc->sc_flags |= H_WRITTEN;
        !           417:        switch (er & MTER_INTCODE) {
        !           418: 
        !           419:        case MTER_EOT:
        !           420:                sc->sc_flags |= H_EOT;
        !           421: 
        !           422:                /* fall into MTER_DONE */
        !           423: 
        !           424:        case MTER_DONE:
        !           425:                sc->sc_blkno++;
        !           426:                if (mi->mi_tab.b_errcnt == 2) {
        !           427:                        bp->b_bcount = bp->b_resid;
        !           428:                        bp->b_resid -= MASKREG(mtaddr->mtbc);
        !           429:                        if (   (bp->b_resid > 0)
        !           430:                            && (bp != &rmtbuf[MTUNIT(bp->b_dev)]) )
        !           431:                                bp->b_flags |= B_ERROR;
        !           432:                } else {
        !           433:                        bp->b_resid = 0;
        !           434:                }
        !           435:                break;
        !           436: 
        !           437:        case MTER_SHRTREC:
        !           438:                sc->sc_blkno++;
        !           439:                bp->b_bcount = bp->b_resid;
        !           440:                bp->b_resid -= MASKREG(mtaddr->mtbc);
        !           441:                if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
        !           442:                        bp->b_flags |= B_ERROR;
        !           443:                break;
        !           444: 
        !           445:        case MTER_RETRY:
        !           446: 
        !           447:                /* Simple re-try.  Since resid is always a copy of the  */
        !           448:                /* original byte count, use it to restore the count.    */
        !           449: 
        !           450:                mi->mi_tab.b_errcnt = 1;
        !           451:                bp->b_bcount = bp->b_resid;
        !           452:                return(MBD_RETRY);
        !           453: 
        !           454:        case MTER_RDOPP:
        !           455: 
        !           456:                /* The controller just decided to read it backwards.    */
        !           457:                /* The byte count in the controller may be larger than  */
        !           458:                /* the size of the buffer, so don't bother to re-try if */
        !           459:                /* it will eventually be an error anyway.  If the       */
        !           460:                /* controller returns a byte count of zero, change it   */
        !           461:                /* to 1, since zero encodes 65536, which isn't quite    */
        !           462:                /* what we had in mind.  If the count is reasonable,    */
        !           463:                /* set bcount to the negative of the controller's       */
        !           464:                /* version of the byte count so that the start address  */
        !           465:                /* for the transfer is set up correctly.                */
        !           466: 
        !           467:                if (MASKREG(mtaddr->mtbc) <= bp->b_resid) {
        !           468:                        if (mt_do_readrev) {
        !           469:                                mi->mi_tab.b_errcnt = 2;
        !           470:                                if ((bp->b_bcount = -MASKREG(mtaddr->mtbc)) == 0)
        !           471:                                        bp->b_bcount = -1;
        !           472:                                return(MBD_RETRY);
        !           473:                        } else {
        !           474:                                sc->sc_blkno++;
        !           475:                                bp->b_bcount = bp->b_resid;
        !           476:                                bp->b_resid -= MASKREG(mtaddr->mtbc);
        !           477:                                bp->b_flags |= B_ERROR;
        !           478:                                break;
        !           479:                        }
        !           480:                }
        !           481:                bp->b_flags |= B_ERROR;
        !           482: 
        !           483:                /* fall into MTER_LONGREC */
        !           484: 
        !           485:        case MTER_LONGREC:
        !           486:                sc->sc_blkno++;
        !           487:                bp->b_bcount = bp->b_resid;
        !           488:                bp->b_resid = 0;
        !           489:                bp->b_error = ENOMEM;
        !           490:                bp->b_flags |= B_ERROR;
        !           491:                break;
        !           492: 
        !           493:        case MTER_NOTCAP:
        !           494:                printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
        !           495:                goto err;
        !           496: 
        !           497:        case MTER_TM:
        !           498: 
        !           499:                /* End of file.  Since the default byte count has       */
        !           500:                /* already been set, just count the block and proceed.  */
        !           501: 
        !           502:                sc->sc_blkno++;
        !           503:        err:
        !           504:                if (bp != &rmtbuf[MTUNIT(bp->b_dev)])
        !           505:                        sc->sc_nxrec = dbtofsb(0, bp->b_blkno);
        !           506:                break;
        !           507: 
        !           508:        case MTER_OFFLINE:
        !           509:                if (sc->sc_openf > 0) {
        !           510:                        sc->sc_openf = -1;
        !           511:                        printf("mu%d: offline\n", MUUNIT(bp->b_dev));
        !           512:                }
        !           513:                bp->b_flags |= B_ERROR;
        !           514:                break;
        !           515: 
        !           516:        case MTER_NOTAVL:
        !           517:                if (sc->sc_openf > 0) {
        !           518:                        sc->sc_openf = -1;
        !           519:                        printf("mu%d: offline (port selector)\n", MUUNIT(bp->b_dev));
        !           520:                }
        !           521:                bp->b_flags |= B_ERROR;
        !           522:                break;
        !           523: 
        !           524:        case MTER_FPT:
        !           525:                printf("mu%d: no write ring\n", MUUNIT(bp->b_dev));
        !           526:                bp->b_flags |= B_ERROR;
        !           527:                break;
        !           528: 
        !           529:        case MTER_UNREAD:
        !           530:                sc->sc_blkno++;
        !           531:                bp->b_bcount = bp->b_resid;
        !           532:                bp->b_resid -= min(MASKREG(mtaddr->mtbc), bp->b_bcount);
        !           533: 
        !           534:                /* Code 010 means a garbage record, nothing serious. */
        !           535: 
        !           536:                if (((er & MTER_FAILCODE) >> 10) == 010) {
        !           537:                        printf("mu%d: rn=%d bn=%d unreadable record\n",
        !           538:                            MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno);
        !           539:                        bp->b_flags |= B_ERROR;
        !           540:                        break;
        !           541:                }
        !           542: 
        !           543:                /* Anything else might be a hardware problem,   */
        !           544:                /* fall into the error report.                  */
        !           545: 
        !           546:        default:
        !           547: 
        !           548:                /* The bits in sc->sc_dsreg are from the last sense     */
        !           549:                /* command.  To get the most recent copy, you have to   */
        !           550:                /* do a sense at interrupt level, which requires nested */
        !           551:                /* error processing.  This is a bit messy, so leave     */
        !           552:                /* well enough alone.                                   */
        !           553: 
        !           554:                printf("mu%d: hard error (data transfer) rn=%d bn=%d mbsr=%b er=%o (octal) ds=%b\n",
        !           555:                    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
        !           556:                    mbsr, mbsr_bits, er,
        !           557:                    MASKREG(sc->sc_dsreg), mtds_bits);
        !           558: #ifdef MTLERRM
        !           559:                mtintfail(sc);
        !           560:                printf("     interrupt code = %o (octal) <%s>\n     failure code = %o (octal) <%s>\n",
        !           561:                    er & MTER_INTCODE, sc->sc_mesg,
        !           562:                    (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
        !           563: #endif
        !           564:                bp->b_flags |= B_ERROR;
        !           565: 
        !           566:                /* The TM78 manual says to reset the controller after   */
        !           567:                /* TM fault B or MASSBUS fault.                         */
        !           568: 
        !           569:                if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
        !           570:                    || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
        !           571:                        mtcreset(mtaddr);
        !           572:                }
        !           573:        }
        !           574: 
        !           575:        /* Just in case some strange error slipped through, (drive off  */
        !           576:        /* line during read-reverse error recovery comes to mind) make  */
        !           577:        /* sure the byte count is reasonable.                           */
        !           578: 
        !           579:        if (bp->b_bcount < 0)
        !           580:                bp->b_bcount = bp->b_resid;
        !           581:        return (MBD_DONE);
        !           582: }
        !           583: 
        !           584: mtndtint(mi)
        !           585:        register struct mba_device *mi;
        !           586: {
        !           587:        register struct mtdevice *mtaddr = (struct mtdevice *)mi->mi_drv;
        !           588:        register struct buf *bp = mi->mi_tab.b_actf;
        !           589:        register struct mu_softc *sc;
        !           590:        register int er, fc;
        !           591:        int unit;
        !           592: 
        !           593:        unit = (mtaddr->mtner >> 8) & 3;
        !           594:        er = MASKREG(mtaddr->mtner);
        !           595:        sc = &mu_softc[unit];
        !           596:        sc->sc_erreg = er;
        !           597: 
        !           598:        /* Check for unsolicited interrupts. */
        !           599: 
        !           600:        if (bp == 0 || unit != MUUNIT(bp->b_dev)) {     /* consistency check */
        !           601:                if ((er & MTER_INTCODE) != MTER_ONLINE) {
        !           602:                        printf("mt: unit %d unexpected interrupt (non data transfer) er=%o (octal) ds=%b\n",
        !           603:                            unit, er, MASKREG(sc->sc_dsreg), mtds_bits);
        !           604: #ifdef MTLERRM
        !           605:                        mtintfail(sc);
        !           606:                        printf("    interrupt code = %o (octal) <%s>\n    failure code = %o (octal) <%s>\n",
        !           607:                            er & MTER_INTCODE, sc->sc_mesg,
        !           608:                            (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
        !           609: #endif
        !           610:                        if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
        !           611:                            || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
        !           612: 
        !           613:                                /* Reset the controller, then set error */
        !           614:                                /* status if there was anything active  */
        !           615:                                /* when the fault occurred.  This may   */
        !           616:                                /* shoot an innocent bystander, but     */
        !           617:                                /* it's better than letting an error    */
        !           618:                                /* slip through.                        */
        !           619: 
        !           620:                                mtcreset(mtaddr);
        !           621:                                if (bp != 0) {
        !           622:                                        bp->b_flags |= B_ERROR;
        !           623:                                        return (MBN_DONE);
        !           624:                                }
        !           625:                        }
        !           626:                }
        !           627:                return (MBN_SKIP);
        !           628:        }
        !           629:        if (bp == 0)
        !           630:                return (MBN_SKIP);
        !           631: 
        !           632:        fc = (mtaddr->mtncs[unit] >> 8) & 0xff;
        !           633:        sc->sc_resid = fc;
        !           634: 
        !           635:        /* Clear the "written" flag after any operation that changes    */
        !           636:        /* the position of the tape.                                    */
        !           637: 
        !           638:        if (   (bp != &cmtbuf[MTUNIT(bp->b_dev)])
        !           639:            || (bp->b_command != MT_SENSE) )
        !           640:                sc->sc_flags &= ~H_WRITTEN;
        !           641: 
        !           642:        switch (er & MTER_INTCODE) {
        !           643: 
        !           644:        case MTER_EOT:
        !           645:                sc->sc_flags |= H_EOT;
        !           646: 
        !           647:                /* fall into MTER_DONE */
        !           648: 
        !           649:        case MTER_DONE:
        !           650: 
        !           651:                /* If this is a command buffer, just update the status. */
        !           652: 
        !           653:                if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
        !           654:        done:
        !           655:                        if (bp->b_command == MT_SENSE)
        !           656:                                sc->sc_dsreg = MASKREG(mtaddr->mtds);
        !           657:                        return (MBN_DONE);
        !           658:                }
        !           659: 
        !           660:                /* It's not a command buffer, must be a cooked I/O      */
        !           661:                /* skip operation (perhaps a shaky assumption, but it   */
        !           662:                /* wasn't my idea).                                     */
        !           663: 
        !           664:                if ((fc = dbtofsb(0, bp->b_blkno) - sc->sc_blkno) < 0)
        !           665:                        sc->sc_blkno -= min(0377, -fc);
        !           666:                else
        !           667:                        sc->sc_blkno += min(0377, fc);
        !           668:                return (MBN_RETRY);
        !           669: 
        !           670:        case MTER_ONLINE:               /* ddj -- shouldn't happen but did */
        !           671:        case MTER_RWDING:
        !           672:                return (MBN_SKIP);      /* ignore "rewind started" interrupt */
        !           673: 
        !           674:        case MTER_NOTCAP:
        !           675:                printf("mu%d: blank tape\n", MUUNIT(bp->b_dev));
        !           676:                bp->b_flags |= B_ERROR;
        !           677:                return (MBN_DONE);
        !           678: 
        !           679:        case MTER_TM:
        !           680:        case MTER_LEOT:
        !           681: 
        !           682:                /* For an ioctl skip operation, count a tape mark as    */
        !           683:                /* a record.  If there's anything left to do, update    */
        !           684:                /* the repeat count and re-start the command.           */
        !           685: 
        !           686:                if (bp == &cmtbuf[MTUNIT(bp->b_dev)]) {
        !           687:                        if ((sc->sc_resid = bp->b_repcnt = fc - 1) == 0)
        !           688:                                return (MBN_DONE);
        !           689:                        else
        !           690:                                return (MBN_RETRY);
        !           691: 
        !           692:                /* Cooked I/O again.  Just update the books and wait    */
        !           693:                /* for someone else to return end of file or complain   */
        !           694:                /* about a bad seek.                                    */
        !           695: 
        !           696:                } else if (sc->sc_blkno > dbtofsb(0, bp->b_blkno)) {
        !           697:                        sc->sc_nxrec = dbtofsb(0, bp->b_blkno) + fc - 1;
        !           698:                        sc->sc_blkno = sc->sc_nxrec;
        !           699:                } else {
        !           700:                        sc->sc_nxrec = dbtofsb(0, bp->b_blkno) - fc;
        !           701:                        sc->sc_blkno = sc->sc_nxrec + 1;
        !           702:                }
        !           703:                return (MBN_RETRY);
        !           704: 
        !           705:        case MTER_FPT:
        !           706:                printf("mu%d: no write ring\n", MUUNIT(bp->b_dev));
        !           707:                bp->b_flags |= B_ERROR;
        !           708:                return (MBN_DONE);
        !           709: 
        !           710:        case MTER_OFFLINE:
        !           711: 
        !           712:                /* If `off line' was intentional, don't complain. */
        !           713: 
        !           714:                if (   (bp == &cmtbuf[MTUNIT(bp->b_dev)])
        !           715:                    && (bp->b_command == MT_UNLOAD) )
        !           716:                        return(MBN_DONE);
        !           717:                if (sc->sc_openf > 0) {
        !           718:                        sc->sc_openf = -1;
        !           719:                        printf("mu%d: offline\n", MUUNIT(bp->b_dev));
        !           720:                }
        !           721:                bp->b_flags |= B_ERROR;
        !           722:                return (MBN_DONE);
        !           723: 
        !           724:        case MTER_NOTAVL:
        !           725:                if (sc->sc_openf > 0) {
        !           726:                        sc->sc_openf = -1;
        !           727:                        printf("mu%d: offline (port selector)\n", MUUNIT(bp->b_dev));
        !           728:                }
        !           729:                bp->b_flags |= B_ERROR;
        !           730:                return (MBN_DONE);
        !           731: 
        !           732:        case MTER_BOT:
        !           733:                if (bp == &cmtbuf[MTUNIT(bp->b_dev)])
        !           734:                        goto done;
        !           735: 
        !           736:                /* fall through */
        !           737: 
        !           738:        default:
        !           739:                printf("mu%d: hard error (non data transfer) rn=%d bn=%d er=%o (octal) ds=%b\n",
        !           740:                    MUUNIT(bp->b_dev), sc->sc_blkno, bp->b_blkno,
        !           741:                    er, MASKREG(sc->sc_dsreg), mtds_bits);
        !           742: #ifdef MTLERRM
        !           743:                mtintfail(sc);
        !           744:                printf("     interrupt code = %o (octal) <%s>\n     failure code = %o (octal) <%s>\n",
        !           745:                    (er & MTER_INTCODE), sc->sc_mesg,
        !           746:                    (er & MTER_FAILCODE) >> 10, sc->sc_fmesg);
        !           747: #endif
        !           748:                if (   ((er & MTER_INTCODE) == MTER_TMFLTB)
        !           749:                    || ((er & MTER_INTCODE) == MTER_MBFLT) ) {
        !           750:                        mtcreset(mtaddr);       /* reset the controller */
        !           751:                }
        !           752:                bp->b_flags |= B_ERROR;
        !           753:                return (MBN_DONE);
        !           754:        }
        !           755:        /* NOTREACHED */
        !           756: }
        !           757: 
        !           758: void mtcreset(mtaddr)
        !           759:        register struct mtdevice *mtaddr;
        !           760: {
        !           761:        register int i;
        !           762: 
        !           763:        mtaddr->mtid = MTID_CLR;                /* reset the TM78 */
        !           764:        DELAY(200);
        !           765:        for (i = MTTIMEOUT; i > 0; i--) {
        !           766:                DELAY(50);                      /* don't nag */
        !           767:                if ((mtaddr->mtid & MTID_RDY) != 0)
        !           768:                        return;                 /* exit when ready */
        !           769:        }
        !           770:        printf("mt: controller hung\n");
        !           771: }
        !           772: 
        !           773: mtread(dev)
        !           774:        dev_t dev;
        !           775: {
        !           776: 
        !           777:        mtphys(dev);
        !           778:        if (u.u_error)
        !           779:                return;
        !           780:        physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_READ, minphys);
        !           781: }
        !           782: 
        !           783: 
        !           784: mtwrite(dev)
        !           785: {
        !           786: 
        !           787:        mtphys(dev);
        !           788:        if (u.u_error)
        !           789:                return;
        !           790:        physio(mtstrategy, &rmtbuf[MTUNIT(dev)], dev, B_WRITE, minphys);
        !           791: }
        !           792: 
        !           793: mtphys(dev)
        !           794:        dev_t dev;
        !           795: {
        !           796:        register int mtunit;
        !           797:        struct mba_device *mi;
        !           798: 
        !           799:        mtunit = MTUNIT(dev);
        !           800:        if (   (mtunit >= NMT)
        !           801:            || ((mi = mtinfo[mtunit]) == 0)
        !           802:            || (mi->mi_alive == 0) ) {
        !           803:                u.u_error = ENXIO;
        !           804:                return;
        !           805:        }
        !           806: }
        !           807: 
        !           808: /*ARGSUSED*/
        !           809: mtioctl(dev, cmd, addr, flag)
        !           810:        dev_t dev;
        !           811:        int cmd;
        !           812:        caddr_t addr;
        !           813:        int flag;
        !           814: {
        !           815:        register struct mu_softc *sc = &mu_softc[MUUNIT(dev)];
        !           816:        register struct buf *bp = &cmtbuf[MTUNIT(dev)];
        !           817:        struct mtop mtop;
        !           818:        struct mtget mtget;
        !           819:        register int callcount, fcount;
        !           820:        register int op;
        !           821: 
        !           822:        /* We depend on the values and order of the MT codes here. */
        !           823: 
        !           824:        static mtops[] =
        !           825:        {MT_WTM,MT_SFORWF,MT_SREVF,MT_SFORW,MT_SREV,MT_REW,MT_UNLOAD,MT_SENSE};
        !           826: 
        !           827:        switch (cmd) {
        !           828: 
        !           829:        /* tape operation */
        !           830: 
        !           831:        case MTIOCTOP:
        !           832:                if (copyin((caddr_t)addr, (caddr_t)&mtop, sizeof(mtop))) {
        !           833:                        u.u_error = EFAULT;
        !           834:                        return;
        !           835:                }
        !           836:                switch(mtop.mt_op) {
        !           837:                case MTWEOF:
        !           838:                        callcount = mtop.mt_count;
        !           839:                        fcount = 1;
        !           840:                        break;
        !           841:                case MTFSF: case MTBSF:
        !           842:                        callcount = mtop.mt_count;
        !           843:                        fcount = 1;
        !           844:                        break;
        !           845:                case MTFSR: case MTBSR:
        !           846:                        callcount = 1;
        !           847:                        fcount = mtop.mt_count;
        !           848:                        break;
        !           849:                case MTREW: case MTOFFL:
        !           850:                        callcount = 1;
        !           851:                        fcount = 1;
        !           852:                        break;
        !           853:                default:
        !           854:                        u.u_error = ENXIO;
        !           855:                        return;
        !           856:                }
        !           857:                if ((callcount <= 0) || (fcount <= 0)) {
        !           858:                        u.u_error = EINVAL;
        !           859:                        return;
        !           860:                }
        !           861:                op = mtops[mtop.mt_op];
        !           862:                if (op == MT_WTM)
        !           863:                        op |= sc->sc_dens;
        !           864:                while (--callcount >= 0) {
        !           865:                        register int n, fc = fcount;
        !           866: 
        !           867:                        do {
        !           868:                                n = min(fc, 0xff);
        !           869:                                mtcommand(dev, op, n);
        !           870:                                n -= sc->sc_resid;
        !           871:                                fc -= n;
        !           872:                                switch (mtop.mt_op) {
        !           873: 
        !           874:                                case MTWEOF:
        !           875:                                        sc->sc_blkno += (daddr_t)n;
        !           876:                                        sc->sc_nxrec = sc->sc_blkno - 1;
        !           877:                                        break;
        !           878: 
        !           879:                                case MTOFFL:
        !           880:                                case MTREW:
        !           881:                                case MTFSF:
        !           882:                                        sc->sc_blkno = (daddr_t)0;
        !           883:                                        sc->sc_nxrec = (daddr_t)INF;
        !           884:                                        break;
        !           885: 
        !           886:                                case MTBSF:
        !           887:                                        if (sc->sc_resid) {
        !           888:                                                sc->sc_blkno = (daddr_t)0;
        !           889:                                                sc->sc_nxrec = (daddr_t)INF;
        !           890:                                        } else {
        !           891:                                                sc->sc_blkno = (daddr_t)(-1);
        !           892:                                                sc->sc_nxrec = (daddr_t)(-1);
        !           893:                                        }
        !           894:                                        break;
        !           895: 
        !           896:                                case MTFSR:
        !           897:                                        sc->sc_blkno += (daddr_t)n;
        !           898:                                        break;
        !           899: 
        !           900:                                case MTBSR:
        !           901:                                        sc->sc_blkno -= (daddr_t)n;
        !           902:                                        break;
        !           903:                                }
        !           904:                                if (sc->sc_resid)
        !           905:                                        break;
        !           906:                        } while (fc);
        !           907:                        if (fc) {
        !           908:                                sc->sc_resid = callcount + fc;
        !           909:                                if (   (mtop.mt_op == MTFSR)
        !           910:                                    || (mtop.mt_op == MTBSR) ) {
        !           911:                                        u.u_error = EIO;
        !           912:                                        break;
        !           913:                                }
        !           914:                                else
        !           915:                                        break;
        !           916:                        }
        !           917:                        if (bp->b_flags & B_ERROR)
        !           918:                                break;
        !           919:                }
        !           920:                geterror(bp);
        !           921:                return;
        !           922: 
        !           923:        /* tape status */
        !           924: 
        !           925:        case MTIOCGET:
        !           926:                mtget.mt_erreg = sc->sc_erreg;
        !           927:                mtget.mt_resid = sc->sc_resid;
        !           928:                mtcommand(dev, MT_SENSE, 1);    /* update drive status */
        !           929:                mtget.mt_dsreg = sc->sc_dsreg;
        !           930:                mtget.mt_type = MT_ISMT;
        !           931:                if (copyout((caddr_t)&mtget, addr, sizeof(mtget)))
        !           932:                        u.u_error = EFAULT;
        !           933:                return;
        !           934: 
        !           935:        /* ignore EOT condition */
        !           936: 
        !           937:        case MTIOCIEOT:
        !           938:                sc->sc_flags |= H_IEOT;
        !           939:                break;
        !           940: 
        !           941:        /* enable EOT condition */
        !           942: 
        !           943:        case MTIOCEEOT:
        !           944:                sc->sc_flags &= ~H_IEOT;
        !           945:                break;
        !           946: 
        !           947:        default:
        !           948:                u.u_error = ENXIO;
        !           949:        }
        !           950: }
        !           951: 
        !           952: #define        DBSIZE  20
        !           953: 
        !           954: mtdump()
        !           955: {
        !           956:        register struct mba_device *mi;
        !           957:        register struct mba_regs *mp;
        !           958:        int blk, num;
        !           959:        int start;
        !           960: 
        !           961:        start = 0;
        !           962:        num = maxfree;
        !           963: #define        phys(a,b)               ((b)((int)(a)&0x7fffffff))
        !           964:        if (mtinfo[0] == 0)
        !           965:                return (ENXIO);
        !           966:        mi = phys(mtinfo[0], struct mba_device *);
        !           967:        mp = phys(mi->mi_hd, struct mba_hd *)->mh_physmba;
        !           968:        mp->mba_cr = MBCR_IE;
        !           969: #if lint
        !           970:        blk = 0; num = blk; start = num; blk = start;
        !           971:        return (0);
        !           972: #endif
        !           973: #ifdef notyet
        !           974:        mtaddr = (struct mtdevice *)&mp->mba_drv[mi->mi_drive];
        !           975:        mtaddr->mttc = MTTC_PDP11|MTTC_1600BPI;
        !           976:        mtaddr->mtcs1 = MT_DCLR|MT_GO;
        !           977:        while (num > 0) {
        !           978:                blk = num > DBSIZE ? DBSIZE : num;
        !           979:                mtdwrite(start, blk, mtaddr, mp);
        !           980:                start += blk;
        !           981:                num -= blk;
        !           982:        }
        !           983:        mteof(mtaddr);
        !           984:        mteof(mtaddr);
        !           985:        mtwait(mtaddr);
        !           986:        if (mtaddr->mtds&MTDS_ERR)
        !           987:                return (EIO);
        !           988:        mtaddr->mtcs1 = MT_REW|MT_GO;
        !           989:        return (0);
        !           990: }
        !           991: 
        !           992: mtdwrite(dbuf, num, mtaddr, mp)
        !           993:        register dbuf, num;
        !           994:        register struct mtdevice *mtaddr;
        !           995:        struct mba_regs *mp;
        !           996: {
        !           997:        register struct pte *io;
        !           998:        register int i;
        !           999: 
        !          1000:        mtwait(mtaddr);
        !          1001:        io = mp->mba_map;
        !          1002:        for (i = 0; i < num; i++)
        !          1003:                *(int *)io++ = dbuf++ | PG_V;
        !          1004:        mtaddr->mtfc = -(num*NBPG);
        !          1005:        mp->mba_sr = -1;
        !          1006:        mp->mba_bcr = -(num*NBPG);
        !          1007:        mp->mba_var = 0;
        !          1008:        mtaddr->mtcs1 = MT_WCOM|MT_GO;
        !          1009: }
        !          1010: 
        !          1011: mtwait(mtaddr)
        !          1012:        struct mtdevice *mtaddr;
        !          1013: {
        !          1014:        register s;
        !          1015: 
        !          1016:        do
        !          1017:                s = mtaddr->mtds;
        !          1018:        while ((s & MTDS_DRY) == 0);
        !          1019: }
        !          1020: 
        !          1021: mteof(mtaddr)
        !          1022:        struct mtdevice *mtaddr;
        !          1023: {
        !          1024: 
        !          1025:        mtwait(mtaddr);
        !          1026:        mtaddr->mtcs1 = MT_WEOF|MT_GO;
        !          1027: #endif notyet
        !          1028: }
        !          1029: 
        !          1030: #ifdef MTLERRM
        !          1031: mtintfail(sc)
        !          1032:        register struct mu_softc *sc;
        !          1033: {
        !          1034:        switch (sc->sc_erreg & MTER_INTCODE) {
        !          1035: 
        !          1036:        /* unexpected BOT detected */
        !          1037: 
        !          1038:        case MTER_BOT:
        !          1039:                sc->sc_mesg = "unexpected BOT";
        !          1040:                switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
        !          1041:                case 01:
        !          1042:                        sc->sc_fmesg = "tape was at BOT";
        !          1043:                        break;
        !          1044:                case 02:
        !          1045:                        sc->sc_fmesg = "BOT seen after tape started";
        !          1046:                        break;
        !          1047:                case 03:
        !          1048:                        sc->sc_fmesg = "ARA ID detected";
        !          1049:                        break;
        !          1050:                default:
        !          1051:                        sc->sc_fmesg = "unclassified failure code";
        !          1052:                }
        !          1053:                break;
        !          1054: 
        !          1055:        /* unexpected LEOT detected */
        !          1056: 
        !          1057:        case MTER_LEOT:
        !          1058:                sc->sc_mesg = "unexpected LEOT";
        !          1059:                sc->sc_fmesg = "";
        !          1060:                break;
        !          1061: 
        !          1062:        /* rewinding */
        !          1063: 
        !          1064:        case MTER_RWDING:
        !          1065:                sc->sc_mesg = "tape rewinding";
        !          1066:                sc->sc_fmesg = "";
        !          1067:                break;
        !          1068: 
        !          1069:        /* not ready */
        !          1070: 
        !          1071:        case MTER_NOTRDY:
        !          1072:                sc->sc_mesg = "drive not ready";
        !          1073:                switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
        !          1074:                case 01:
        !          1075:                        sc->sc_fmesg = "TU on-line but not ready";
        !          1076:                        break;
        !          1077:                case 02:
        !          1078:                        sc->sc_fmesg = "fatal error has occurred";
        !          1079:                        break;
        !          1080:                case 03:
        !          1081:                        sc->sc_fmesg = "access allowed but not really";
        !          1082:                        break;
        !          1083:                default:
        !          1084:                        sc->sc_fmesg = "unclassified failure code";
        !          1085:                }
        !          1086:                break;
        !          1087: 
        !          1088:        /* not available */
        !          1089: 
        !          1090:        case MTER_NOTAVL:
        !          1091:                sc->sc_mesg = "drive not available";
        !          1092:                sc->sc_fmesg = "";
        !          1093:                break;
        !          1094: 
        !          1095:        /* unit does not exist */
        !          1096: 
        !          1097:        case MTER_NONEX:
        !          1098:                sc->sc_mesg = "unit does not exist";
        !          1099:                sc->sc_fmesg = "";
        !          1100:                break;
        !          1101: 
        !          1102:        /* not capable */
        !          1103: 
        !          1104:        case MTER_NOTCAP:
        !          1105:                sc->sc_mesg = "not capable";
        !          1106:                switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
        !          1107:                case 01:
        !          1108:                        sc->sc_fmesg = "no record found within 25 feet";
        !          1109:                        break;
        !          1110:                case 02:
        !          1111:                        sc->sc_fmesg = "ID burst neither PE nor GCR";
        !          1112:                        break;
        !          1113:                case 03:
        !          1114:                        sc->sc_fmesg = "ARA ID not found";
        !          1115:                        break;
        !          1116:                case 04:
        !          1117:                        sc->sc_fmesg = "no gap found after ID burst";
        !          1118:                        break;
        !          1119:                default:
        !          1120:                        sc->sc_fmesg = "unclassified failure code";
        !          1121:                }
        !          1122:                break;
        !          1123: 
        !          1124:        /* long tape record */
        !          1125: 
        !          1126:        case MTER_LONGREC:
        !          1127:                sc->sc_mesg = "long record";
        !          1128:                switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
        !          1129:                case 00:
        !          1130:                        sc->sc_fmesg = "extended sense data not found";
        !          1131:                        break;
        !          1132:                case 01:
        !          1133:                        sc->sc_fmesg = "extended sense data updated";
        !          1134:                        break;
        !          1135:                default:
        !          1136:                        sc->sc_fmesg = "unclassified failure code";
        !          1137:                }
        !          1138:                break;
        !          1139: 
        !          1140:        /* unreadable */
        !          1141: 
        !          1142:        case MTER_UNREAD:
        !          1143:                sc->sc_mesg = "unreadable record";
        !          1144:                goto code22;
        !          1145: 
        !          1146:        /* error */
        !          1147: 
        !          1148:        case MTER_ERROR:
        !          1149:                sc->sc_mesg = "error";
        !          1150:                goto code22;
        !          1151: 
        !          1152:        /* EOT error */
        !          1153: 
        !          1154:        case MTER_EOTERR:
        !          1155:                sc->sc_mesg = "EOT error";
        !          1156:                goto code22;
        !          1157: 
        !          1158:        /* tape position lost */
        !          1159: 
        !          1160:        case MTER_BADTAPE:
        !          1161:                sc->sc_mesg = "bad tape";
        !          1162:        code22:
        !          1163:                switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
        !          1164:                case 01:
        !          1165:                        sc->sc_fmesg = "GCR write error";
        !          1166:                        break;
        !          1167:                case 02:
        !          1168:                        sc->sc_fmesg = "GCR read error";
        !          1169:                        break;
        !          1170:                case 03:
        !          1171:                        sc->sc_fmesg = "PE read error";
        !          1172:                        break;
        !          1173:                case 04:
        !          1174:                        sc->sc_fmesg = "PE write error";
        !          1175:                        break;
        !          1176:                case 05:
        !          1177:                        sc->sc_fmesg = "at least 1 bit set in ECCSTA";
        !          1178:                        break;
        !          1179:                case 06:
        !          1180:                        sc->sc_fmesg = "PE write error";
        !          1181:                        break;
        !          1182:                case 07:
        !          1183:                        sc->sc_fmesg = "GCR write error";
        !          1184:                        break;
        !          1185:                case 010:
        !          1186:                        sc->sc_fmesg = "RSTAT contains bad code";
        !          1187:                        break;
        !          1188:                case 011:
        !          1189:                        sc->sc_fmesg = "PE write error";
        !          1190:                        break;
        !          1191:                case 012:
        !          1192:                        sc->sc_fmesg = "MASSBUS parity error";
        !          1193:                        break;
        !          1194:                case 013:
        !          1195:                        sc->sc_fmesg = "invalid data transferred";
        !          1196:                        break;
        !          1197:                default:
        !          1198:                        sc->sc_fmesg = "unclassified failure code";
        !          1199:                }
        !          1200:                break;
        !          1201: 
        !          1202:        /* TM fault A */
        !          1203: 
        !          1204:        case MTER_TMFLTA:
        !          1205:                sc->sc_mesg = "TM fault A";
        !          1206:                switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
        !          1207:                case 01:
        !          1208:                        sc->sc_fmesg = "illegal command code";
        !          1209:                        break;
        !          1210:                case 02:
        !          1211:                        sc->sc_fmesg = "DT command issued when NDT command active";
        !          1212:                        break;
        !          1213:                case 03:
        !          1214:                        sc->sc_fmesg = "WMC error";
        !          1215:                        break;
        !          1216:                case 04:
        !          1217:                        sc->sc_fmesg = "RUN not received from MASSBUS controller";
        !          1218:                        break;
        !          1219:                case 05:
        !          1220:                        sc->sc_fmesg = "mismatch in command read - function routine";
        !          1221:                        break;
        !          1222:                case 06:
        !          1223:                        sc->sc_fmesg = "ECC ROM parity error";
        !          1224:                        break;
        !          1225:                case 07:
        !          1226:                        sc->sc_fmesg = "XMC ROM parity error";
        !          1227:                        break;
        !          1228:                case 010:
        !          1229:                        sc->sc_fmesg = "mismatch in command read - ID burst command";
        !          1230:                        break;
        !          1231:                case 011:
        !          1232:                        sc->sc_fmesg = "mismatch in command read - verify ARA burst command";
        !          1233:                        break;
        !          1234:                case 012:
        !          1235:                        sc->sc_fmesg = "mismatch in command read - verify ARA ID command";
        !          1236:                        break;
        !          1237:                case 013:
        !          1238:                        sc->sc_fmesg = "mismatch in command read - verify gap command";
        !          1239:                        break;
        !          1240:                case 014:
        !          1241:                        sc->sc_fmesg = "mismatch in command read - read id burst command";
        !          1242:                        break;
        !          1243:                case 015:
        !          1244:                        sc->sc_fmesg = "mismatch in command read - verify ARA ID command";
        !          1245:                        break;
        !          1246:                case 016:
        !          1247:                        sc->sc_fmesg = "mismatch in command read - verify gap command";
        !          1248:                        break;
        !          1249:                case 017:
        !          1250:                        sc->sc_fmesg = "mismatch in command read - find gap command";
        !          1251:                        break;
        !          1252:                case 020:
        !          1253:                        sc->sc_fmesg = "WMC LEFT failed to set";
        !          1254:                        break;
        !          1255:                case 021:
        !          1256:                        sc->sc_fmesg = "XL PE set in INTSTA register";
        !          1257:                        break;
        !          1258:                case 022:
        !          1259:                        sc->sc_fmesg = "XMC DONE did not set";
        !          1260:                        break;
        !          1261:                case 023:
        !          1262:                        sc->sc_fmesg = "WMC ROM PE or RD PE set in WMCERR register";
        !          1263:                        break;
        !          1264:                default:
        !          1265:                        sc->sc_fmesg = "unclassified failure code";
        !          1266:                }
        !          1267:                break;
        !          1268: 
        !          1269:        /* TU fault A */
        !          1270: 
        !          1271:        case MTER_TUFLTA:
        !          1272:                sc->sc_mesg = "TU fault A";
        !          1273:                switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
        !          1274:                case 01:
        !          1275:                        sc->sc_fmesg = "TU status parity error";
        !          1276:                        break;
        !          1277:                case 02:
        !          1278:                        sc->sc_fmesg = "TU command parity error";
        !          1279:                        break;
        !          1280:                case 03:
        !          1281:                        sc->sc_fmesg = "rewinding tape went offline";
        !          1282:                        break;
        !          1283:                case 04:
        !          1284:                        sc->sc_fmesg = "tape went not ready during DSE";
        !          1285:                        break;
        !          1286:                case 05:
        !          1287:                        sc->sc_fmesg = "TU CMD status changed during DSE";
        !          1288:                        break;
        !          1289:                case 06:
        !          1290:                        sc->sc_fmesg = "TU never came up to speed";
        !          1291:                        break;
        !          1292:                case 07:
        !          1293:                        sc->sc_fmesg = "TU velocity changed";
        !          1294:                        break;
        !          1295:                case 010:
        !          1296:                        sc->sc_fmesg = "TU CMD did not load correctly to start tape motion";
        !          1297:                        break;
        !          1298:                case 011:
        !          1299:                        sc->sc_fmesg = "TU CMD did not load correctly to set drive density";
        !          1300:                        break;
        !          1301:                case 012:
        !          1302:                        sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to write BOT ID";
        !          1303:                        break;
        !          1304:                case 013:
        !          1305:                        sc->sc_fmesg = "TU CMD did not load correctly to backup tape to BOT after failing to write BOT ID";
        !          1306:                        break;
        !          1307:                case 014:
        !          1308:                        sc->sc_fmesg = "failed to write density ID burst";
        !          1309:                        break;
        !          1310:                case 015:
        !          1311:                        sc->sc_fmesg = "failed to write ARA burst";
        !          1312:                        break;
        !          1313:                case 016:
        !          1314:                        sc->sc_fmesg = "failed to write ARA ID";
        !          1315:                        break;
        !          1316:                case 017:
        !          1317:                        sc->sc_fmesg = "ARA error bit set in MTA status B register";
        !          1318:                        break;
        !          1319:                case 021:
        !          1320:                        sc->sc_fmesg = "could not find a gap after ID code was written correctly";
        !          1321:                        break;
        !          1322:                case 022:
        !          1323:                        sc->sc_fmesg = "TU CMD did not load correctly to start tape motion to read ID burst";
        !          1324:                        break;
        !          1325:                case 023:
        !          1326:                        sc->sc_fmesg = "timeout looking for BOT after detecting ARA ID burst";
        !          1327:                        break;
        !          1328:                case 024:
        !          1329:                        sc->sc_fmesg = "failed to write tape mark";
        !          1330:                        break;
        !          1331:                case 025:
        !          1332:                        sc->sc_fmesg = "tape never came up to speed while trying to reposition for retry of writing tape mark";
        !          1333:                        break;
        !          1334:                case 026:
        !          1335:                        sc->sc_fmesg = "TU CMD did not load correctly to start tape motion in erase gap routine";
        !          1336:                        break;
        !          1337:                case 027:
        !          1338:                        sc->sc_fmesg = "could not detect a gap in in erase gap routine";
        !          1339:                        break;
        !          1340:                case 030:
        !          1341:                        sc->sc_fmesg = "could not detect a gap after writing record";
        !          1342:                        break;
        !          1343:                case 031:
        !          1344:                        sc->sc_fmesg = "read path terminated before entire record was written";
        !          1345:                        break;
        !          1346:                case 032:
        !          1347:                        sc->sc_fmesg = "could not find a gap after writing record and read path terminated early";
        !          1348:                        break;
        !          1349:                case 033:
        !          1350:                        sc->sc_fmesg = "TU CMD did not load correctly to backup for retry of write tape mark";
        !          1351:                        break;
        !          1352:                case 034:
        !          1353:                        sc->sc_fmesg = "TU velocity changed after up to speed while trying to reposition for retry of writing tape mark";
        !          1354:                        break;
        !          1355:                case 035:
        !          1356:                        sc->sc_fmesg = "TU CMD did not load correctly to backup to retry a load of BOT ID";
        !          1357:                        break;
        !          1358:                case 036:
        !          1359:                        sc->sc_fmesg = "timeout looking for BOT after failing to write BOT ID";
        !          1360:                        break;
        !          1361:                case 037:
        !          1362:                        sc->sc_fmesg = "TU velocity changed while writing PE gap before starting to write record";
        !          1363:                        break;
        !          1364:                case 040:
        !          1365:                        sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of write BOT ID burst";
        !          1366:                        break;
        !          1367:                case 041:
        !          1368:                        sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after writing Density ID";
        !          1369:                        break;
        !          1370:                case 042:
        !          1371:                        sc->sc_fmesg = "TU CMD did not load correctly to set PE tape density at start of read from BOT";
        !          1372:                        break;
        !          1373:                case 043:
        !          1374:                        sc->sc_fmesg = "TU CMD did not load correctly to set GCR tape density after reading a GCR Density ID burst";
        !          1375:                        break;
        !          1376:                default:
        !          1377:                        sc->sc_fmesg = "unclassified failure code";
        !          1378:                }
        !          1379:                break;
        !          1380: 
        !          1381:        /* TM fault B */
        !          1382: 
        !          1383:        case MTER_TMFLTB:
        !          1384:                sc->sc_mesg = "TM fault B";
        !          1385:                switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
        !          1386:                case 00:
        !          1387:                        sc->sc_fmesg = "RST0 interrupt occurred with TM RDY set";
        !          1388:                        break;
        !          1389:                case 01:
        !          1390:                        sc->sc_fmesg = "power failed to interrupt";
        !          1391:                        break;
        !          1392:                case 02:
        !          1393:                        sc->sc_fmesg = "unknown interrupt on channel 5.5";
        !          1394:                        break;
        !          1395:                case 03:
        !          1396:                        sc->sc_fmesg = "unknown interrupt on channel 6.5";
        !          1397:                        break;
        !          1398:                case 04:
        !          1399:                        sc->sc_fmesg = "unknown interrupt on channel 7";
        !          1400:                        break;
        !          1401:                case 05:
        !          1402:                        sc->sc_fmesg = "unknown interrupt on channel 7.5";
        !          1403:                        break;
        !          1404:                case 06:
        !          1405:                        sc->sc_fmesg = "CAS contention retry count expired";
        !          1406:                        break;
        !          1407:                case 07:
        !          1408:                        sc->sc_fmesg = "CAS contention error not retryable";
        !          1409:                        break;
        !          1410:                case 010:
        !          1411:                        sc->sc_fmesg = "queue error, could not find queue entry";
        !          1412:                        break;
        !          1413:                case 011:
        !          1414:                        sc->sc_fmesg = "queue entry already full";
        !          1415:                        break;
        !          1416:                case 012:
        !          1417:                        sc->sc_fmesg = "8085 ROM parity error";
        !          1418:                        break;
        !          1419:                case 013:
        !          1420:                case 014:
        !          1421:                case 015:
        !          1422:                case 016:
        !          1423:                case 017:
        !          1424:                case 020:
        !          1425:                case 021:
        !          1426:                case 022:
        !          1427:                case 023:
        !          1428:                case 024:
        !          1429:                case 025:
        !          1430:                case 026:
        !          1431:                case 027:
        !          1432:                case 030:
        !          1433:                case 031:
        !          1434:                case 032:
        !          1435:                case 033:
        !          1436:                case 034:
        !          1437:                case 035:
        !          1438:                case 036:
        !          1439:                case 037:
        !          1440:                case 040:
        !          1441:                case 041:
        !          1442:                case 042:
        !          1443:                case 043:
        !          1444:                case 044:
        !          1445:                case 045:
        !          1446:                case 046:
        !          1447:                case 047:
        !          1448:                case 050:
        !          1449:                case 051:
        !          1450:                case 052:
        !          1451:                case 053:
        !          1452:                case 054:
        !          1453:                case 055:
        !          1454:                case 056:
        !          1455:                case 057:
        !          1456:                        sc->sc_fmesg = "inline test failed";
        !          1457:                        break;
        !          1458:                default:
        !          1459:                        sc->sc_fmesg = "unclassified failure code";
        !          1460:                }
        !          1461:                break;
        !          1462: 
        !          1463:        /* MASSBUS fault */
        !          1464: 
        !          1465:        case MTER_MBFLT:
        !          1466:                sc->sc_mesg = "MB fault";
        !          1467:                switch ((sc->sc_erreg & MTER_FAILCODE) >> 10) {
        !          1468:                case 01:
        !          1469:                        sc->sc_fmesg = "control bus parity error";
        !          1470:                        break;
        !          1471:                case 02:
        !          1472:                        sc->sc_fmesg = "illegal register referenced";
        !          1473:                        break;
        !          1474:                default:
        !          1475:                        sc->sc_fmesg = "unclassified failure code";
        !          1476:                }
        !          1477:                break;
        !          1478: 
        !          1479:        /* keypad entry error */
        !          1480: 
        !          1481:        case MTER_KEYFAIL:
        !          1482:                sc->sc_mesg = "keypad entry error";
        !          1483:                sc->sc_fmesg = "";
        !          1484:                break;
        !          1485:        default:
        !          1486:                sc->sc_mesg = "unclassified error";
        !          1487:                sc->sc_fmesg = "";
        !          1488:                break;
        !          1489:        }
        !          1490: }
        !          1491: #endif MTLERRM
        !          1492: #endif

unix.superglobalmegacorp.com

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