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

unix.superglobalmegacorp.com

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