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