Annotation of 43BSDReno/sys/vaxmba/mt.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1982, 1986 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  *
                      6:  *     @(#)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.