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

unix.superglobalmegacorp.com

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