[BACK]Return to mt.c CVS log [TXT][DIR] Up to [local] / sys / arch / hp300 / dev

Annotation of sys/arch/hp300/dev/mt.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: mt.c,v 1.18 2007/06/06 17:15:11 deraadt Exp $ */
        !             2: /*     $NetBSD: mt.c,v 1.8 1997/03/31 07:37:29 scottr Exp $    */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1996, 1997 Jason R. Thorpe.  All rights reserved.
        !             6:  * Copyright (c) 1992, The University of Utah and
        !             7:  * the Computer Systems Laboratory at the University of Utah (CSL).
        !             8:  * All rights reserved.
        !             9:  *
        !            10:  * Permission to use, copy, modify and distribute this software is hereby
        !            11:  * granted provided that (1) source code retains these copyright, permission,
        !            12:  * and disclaimer notices, and (2) redistributions including binaries
        !            13:  * reproduce the notices in supporting documentation, and (3) all advertising
        !            14:  * materials mentioning features or use of this software display the following
        !            15:  * acknowledgement: ``This product includes software developed by the
        !            16:  * Computer Systems Laboratory at the University of Utah.''
        !            17:  *
        !            18:  * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
        !            19:  * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
        !            20:  * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
        !            21:  *
        !            22:  * CSL requests users of this software to return to csl-dist@cs.utah.edu any
        !            23:  * improvements that they make and grant CSL redistribution rights.
        !            24:  *
        !            25:  *     Utah $Hdr: mt.c 1.8 95/09/12$
        !            26:  */
        !            27: /*     @(#)mt.c        3.9     90/07/10        mt Xinu
        !            28:  *
        !            29:  * Magnetic tape driver (7974a, 7978a/b, 7979a, 7980a, 7980xc)
        !            30:  * Original version contributed by Mt. Xinu.
        !            31:  * Modified for 4.4BSD by Mark Davies and Andrew Vignaux, Department of
        !            32:  * Computer Science, Victoria University of Wellington
        !            33:  */
        !            34:
        !            35: #include <sys/param.h>
        !            36: #include <sys/systm.h>
        !            37: #include <sys/buf.h>
        !            38: #include <sys/ioctl.h>
        !            39: #include <sys/mtio.h>
        !            40: #include <sys/file.h>
        !            41: #include <sys/proc.h>
        !            42: #include <sys/errno.h>
        !            43: #include <sys/syslog.h>
        !            44: #include <sys/tty.h>
        !            45: #include <sys/kernel.h>
        !            46: #include <sys/device.h>
        !            47: #include <sys/conf.h>
        !            48:
        !            49: #include <hp300/dev/hpibvar.h>
        !            50:
        !            51: #include <hp300/dev/mtreg.h>
        !            52:
        !            53: struct mtinfo {
        !            54:        u_short hwid;
        !            55:        char    *desc;
        !            56: } mtinfo[] = {
        !            57:        { MT7978ID,     "7978"  },
        !            58:        { MT7979AID,    "7979A" },
        !            59:        { MT7980ID,     "7980"  },
        !            60:        { MT7974AID,    "7974A" },
        !            61: };
        !            62: int    nmtinfo = sizeof(mtinfo) / sizeof(mtinfo[0]);
        !            63:
        !            64: struct mt_softc {
        !            65:        struct  device sc_dev;
        !            66:        int     sc_hpibno;      /* logical HPIB this slave it attached to */
        !            67:        int     sc_slave;       /* HPIB slave address (0-6) */
        !            68:        short   sc_flags;       /* see below */
        !            69:        u_char  sc_lastdsj;     /* place for DSJ in mtreaddsj() */
        !            70:        u_char  sc_lastecmd;    /* place for End Command in mtreaddsj() */
        !            71:        short   sc_recvtimeo;   /* count of hpibsend timeouts to prevent hang */
        !            72:        short   sc_statindex;   /* index for next sc_stat when MTF_STATTIMEO */
        !            73:        struct  mt_stat sc_stat;/* status bytes last read from device */
        !            74:        short   sc_density;     /* current density of tape (mtio.h format) */
        !            75:        short   sc_type;        /* tape drive model (hardware IDs) */
        !            76:        struct  hpibqueue sc_hq; /* HPIB device queue member */
        !            77:        struct buf sc_tab;      /* buf queue */
        !            78:        struct buf sc_bufstore; /* XXX buffer storage */
        !            79:        struct timeout sc_start_to; /* spl_mtstart timeout */
        !            80:        struct timeout sc_intr_to; /* spl_mtintr timeout */
        !            81: };
        !            82:
        !            83: #ifdef DEBUG
        !            84: int    mtdebug = 0;
        !            85: #define        dlog    if (mtdebug) log
        !            86: #else
        !            87: #define        dlog    if (0) log
        !            88: #endif
        !            89:
        !            90: #define        UNIT(x)         (minor(x) & 3)
        !            91:
        !            92: #define B_CMD          B_XXX           /* command buf instead of data */
        !            93: #define        b_cmd           b_blkno         /* blkno holds cmd when B_CMD */
        !            94:
        !            95: int    mtmatch(struct device *, void *, void *);
        !            96: void   mtattach(struct device *, struct device *, void *);
        !            97:
        !            98: struct cfattach mt_ca = {
        !            99:        sizeof(struct mt_softc), mtmatch, mtattach
        !           100: };
        !           101:
        !           102: struct cfdriver mt_cd = {
        !           103:        NULL, "mt", DV_TAPE
        !           104: };
        !           105:
        !           106: int    mtident(struct mt_softc *, struct hpibbus_attach_args *);
        !           107: void   mtustart(struct mt_softc *);
        !           108: int    mtreaddsj(struct mt_softc *, int);
        !           109: int    mtcommand(dev_t, int, int);
        !           110: void   spl_mtintr(void *);
        !           111: void   spl_mtstart(void *);
        !           112:
        !           113: void   mtstart(void *);
        !           114: void   mtgo(void *);
        !           115: void   mtintr(void *);
        !           116:
        !           117: bdev_decl(mt);
        !           118: cdev_decl(mt);
        !           119:
        !           120: int
        !           121: mtmatch(parent, match, aux)
        !           122:        struct device *parent;
        !           123:        void *match, *aux;
        !           124: {
        !           125:        struct hpibbus_attach_args *ha = aux;
        !           126:
        !           127:        return (mtident(NULL, ha));
        !           128: }
        !           129:
        !           130: void
        !           131: mtattach(parent, self, aux)
        !           132:        struct device *parent, *self;
        !           133:        void *aux;
        !           134: {
        !           135:        struct mt_softc *sc = (struct mt_softc *)self;
        !           136:        struct hpibbus_attach_args *ha = aux;
        !           137:        int unit, hpibno, slave;
        !           138:
        !           139:        if (mtident(sc, ha) == 0) {
        !           140:                printf("\n%s: impossible!\n", sc->sc_dev.dv_xname);
        !           141:                return;
        !           142:        }
        !           143:
        !           144:        unit = self->dv_unit;
        !           145:        hpibno = parent->dv_unit;
        !           146:        slave = ha->ha_slave;
        !           147:
        !           148:        sc->sc_tab.b_actb = &sc->sc_tab.b_actf;
        !           149:
        !           150:        sc->sc_hpibno = hpibno;
        !           151:        sc->sc_slave = slave;
        !           152:        sc->sc_flags = MTF_EXISTS;
        !           153:
        !           154:        /* Initialize hpib job queue entry. */
        !           155:        sc->sc_hq.hq_softc = sc;
        !           156:        sc->sc_hq.hq_slave = sc->sc_slave;
        !           157:        sc->sc_hq.hq_start = mtstart;
        !           158:        sc->sc_hq.hq_go = mtgo;
        !           159:        sc->sc_hq.hq_intr = mtintr;
        !           160:
        !           161:        /* Initialize timeout structures */
        !           162:        timeout_set(&sc->sc_start_to, spl_mtstart, sc);
        !           163:        timeout_set(&sc->sc_intr_to, spl_mtintr, sc);
        !           164: }
        !           165:
        !           166: int
        !           167: mtident(sc, ha)
        !           168:        struct mt_softc *sc;
        !           169:        struct hpibbus_attach_args *ha;
        !           170: {
        !           171:        int i;
        !           172:
        !           173:        for (i = 0; i < nmtinfo; i++) {
        !           174:                if (ha->ha_id == mtinfo[i].hwid &&
        !           175:                    ha->ha_punit == 0) {
        !           176:                        if (sc != NULL) {
        !           177:                                sc->sc_type = mtinfo[i].hwid;
        !           178:                                printf(": %s tape\n", mtinfo[i].desc);
        !           179:                        }
        !           180:                        return (1);
        !           181:                }
        !           182:        }
        !           183:        return (0);
        !           184: }
        !           185:
        !           186: /*
        !           187:  * Perform a read of "Device Status Jump" register and update the
        !           188:  * status if necessary.  If status is read, the given "ecmd" is also
        !           189:  * performed, unless "ecmd" is zero.  Returns DSJ value, -1 on failure
        !           190:  * and -2 on "temporary" failure.
        !           191:  */
        !           192: int
        !           193: mtreaddsj(sc, ecmd)
        !           194:        struct mt_softc *sc;
        !           195:        int ecmd;
        !           196: {
        !           197:        int retval;
        !           198:
        !           199:        if (sc->sc_flags & MTF_STATTIMEO)
        !           200:                goto getstats;
        !           201:        retval = hpibrecv(sc->sc_hpibno,
        !           202:            (sc->sc_flags & MTF_DSJTIMEO) ? -1 : sc->sc_slave,
        !           203:            MTT_DSJ, &(sc->sc_lastdsj), 1);
        !           204:        sc->sc_flags &= ~MTF_DSJTIMEO;
        !           205:        if (retval != 1) {
        !           206:                dlog(LOG_DEBUG, "%s can't hpibrecv DSJ",
        !           207:                    sc->sc_dev.dv_xname);
        !           208:                if (sc->sc_recvtimeo == 0)
        !           209:                        sc->sc_recvtimeo = hz;
        !           210:                if (--sc->sc_recvtimeo == 0)
        !           211:                        return (-1);
        !           212:                if (retval == 0)
        !           213:                        sc->sc_flags |= MTF_DSJTIMEO;
        !           214:                return (-2);
        !           215:        }
        !           216:        sc->sc_recvtimeo = 0;
        !           217:        sc->sc_statindex = 0;
        !           218:        dlog(LOG_DEBUG, "%s readdsj: 0x%x", sc->sc_dev.dv_xname,
        !           219:            sc->sc_lastdsj);
        !           220:        sc->sc_lastecmd = ecmd;
        !           221:        switch (sc->sc_lastdsj) {
        !           222:            case 0:
        !           223:                if (ecmd & MTE_DSJ_FORCE)
        !           224:                        break;
        !           225:                return (0);
        !           226:
        !           227:            case 2:
        !           228:                sc->sc_lastecmd = MTE_COMPLETE;
        !           229:            case 1:
        !           230:                break;
        !           231:
        !           232:            default:
        !           233:                log(LOG_ERR, "%s readdsj: DSJ 0x%x\n", sc->sc_dev.dv_xname,
        !           234:                    sc->sc_lastdsj);
        !           235:                return (-1);
        !           236:        }
        !           237:     getstats:
        !           238:        retval = hpibrecv(sc->sc_hpibno,
        !           239:            (sc->sc_flags & MTF_STATCONT) ? -1 : sc->sc_slave,
        !           240:            MTT_STAT, ((char *)&(sc->sc_stat)) + sc->sc_statindex,
        !           241:            sizeof(sc->sc_stat) - sc->sc_statindex);
        !           242:        sc->sc_flags &= ~(MTF_STATTIMEO | MTF_STATCONT);
        !           243:        if (retval != sizeof(sc->sc_stat) - sc->sc_statindex) {
        !           244:                if (sc->sc_recvtimeo == 0)
        !           245:                        sc->sc_recvtimeo = hz;
        !           246:                if (--sc->sc_recvtimeo != 0) {
        !           247:                        if (retval >= 0) {
        !           248:                                sc->sc_statindex += retval;
        !           249:                                sc->sc_flags |= MTF_STATCONT;
        !           250:                        }
        !           251:                        sc->sc_flags |= MTF_STATTIMEO;
        !           252:                        return (-2);
        !           253:                }
        !           254:                log(LOG_ERR, "%s readdsj: can't read status",
        !           255:                    sc->sc_dev.dv_xname);
        !           256:                return (-1);
        !           257:        }
        !           258:        sc->sc_recvtimeo = 0;
        !           259:        sc->sc_statindex = 0;
        !           260:        dlog(LOG_DEBUG, "%s readdsj: status is %x %x %x %x %x %x",
        !           261:            sc->sc_dev.dv_xname,
        !           262:            sc->sc_stat1, sc->sc_stat2, sc->sc_stat3,
        !           263:            sc->sc_stat4, sc->sc_stat5, sc->sc_stat6);
        !           264:        if (sc->sc_lastecmd)
        !           265:                (void) hpibsend(sc->sc_hpibno, sc->sc_slave,
        !           266:                    MTL_ECMD, &(sc->sc_lastecmd), 1);
        !           267:        return ((int) sc->sc_lastdsj);
        !           268: }
        !           269:
        !           270: int
        !           271: mtopen(dev, flag, mode, p)
        !           272:        dev_t dev;
        !           273:        int flag, mode;
        !           274:        struct proc *p;
        !           275: {
        !           276:        int unit = UNIT(dev);
        !           277:        struct mt_softc *sc;
        !           278:        int req_den;
        !           279:        int error;
        !           280:
        !           281:        if (unit >= mt_cd.cd_ndevs ||
        !           282:            (sc = mt_cd.cd_devs[unit]) == NULL ||
        !           283:            (sc->sc_flags & MTF_EXISTS) == 0)
        !           284:                return (ENXIO);
        !           285:
        !           286:        dlog(LOG_DEBUG, "%s open: flags 0x%x", sc->sc_dev.dv_xname,
        !           287:            sc->sc_flags);
        !           288:        if (sc->sc_flags & MTF_OPEN)
        !           289:                return (EBUSY);
        !           290:        sc->sc_flags |= MTF_OPEN;
        !           291:        if ((sc->sc_flags & MTF_ALIVE) == 0) {
        !           292:                error = mtcommand(dev, MTRESET, 0);
        !           293:                if (error != 0 || (sc->sc_flags & MTF_ALIVE) == 0)
        !           294:                        goto errout;
        !           295:                if ((sc->sc_stat1 & (SR1_BOT | SR1_ONLINE)) == SR1_ONLINE)
        !           296:                        (void) mtcommand(dev, MTREW, 0);
        !           297:        }
        !           298:        for (;;) {
        !           299:                if ((error = mtcommand(dev, MTNOP, 0)) != 0)
        !           300:                        goto errout;
        !           301:                if (!(sc->sc_flags & MTF_REW))
        !           302:                        break;
        !           303:                if (tsleep((caddr_t) &lbolt, PCATCH | (PZERO + 1),
        !           304:                    "mt", 0) != 0) {
        !           305:                        error = EINTR;
        !           306:                        goto errout;
        !           307:                }
        !           308:        }
        !           309:        if ((flag & FWRITE) && (sc->sc_stat1 & SR1_RO)) {
        !           310:                error = EROFS;
        !           311:                goto errout;
        !           312:        }
        !           313:        if (!(sc->sc_stat1 & SR1_ONLINE)) {
        !           314:                uprintf("%s: not online\n", sc->sc_dev.dv_xname);
        !           315:                error = EIO;
        !           316:                goto errout;
        !           317:        }
        !           318:        /*
        !           319:         * Select density:
        !           320:         *  - find out what density the drive is set to
        !           321:         *      (i.e. the density of the current tape)
        !           322:         *  - if we are going to write
        !           323:         *    - if we're not at the beginning of the tape
        !           324:         *      - complain if we want to change densities
        !           325:         *    - otherwise, select the mtcommand to set the density
        !           326:         *
        !           327:         * If the drive doesn't support it then don't change the recorded
        !           328:         * density.
        !           329:         *
        !           330:         * The original MOREbsd code had these additional conditions
        !           331:         * for the mid-tape change
        !           332:         *
        !           333:         *      req_den != T_BADBPI &&
        !           334:         *      sc->sc_density != T_6250BPI
        !           335:         *
        !           336:         * which suggests that it would be possible to write multiple
        !           337:         * densities if req_den == T_BAD_BPI or the current tape
        !           338:         * density was 6250.  Testing of our 7980 suggests that the
        !           339:         * device cannot change densities mid-tape.
        !           340:         *
        !           341:         * ajv@comp.vuw.ac.nz
        !           342:         */
        !           343:        sc->sc_density = (sc->sc_stat2 & SR2_6250) ? T_6250BPI : (
        !           344:                         (sc->sc_stat3 & SR3_1600) ? T_1600BPI : (
        !           345:                         (sc->sc_stat3 & SR3_800) ? T_800BPI : -1));
        !           346:        req_den = (dev & T_DENSEL);
        !           347:
        !           348:        if (flag & FWRITE) {
        !           349:                if (!(sc->sc_stat1 & SR1_BOT)) {
        !           350:                        if (sc->sc_density != req_den) {
        !           351:                                uprintf("%s: can't change density mid-tape\n",
        !           352:                                    sc->sc_dev.dv_xname);
        !           353:                                error = EIO;
        !           354:                                goto errout;
        !           355:                        }
        !           356:                }
        !           357:                else {
        !           358:                        int mtset_density =
        !           359:                            (req_den == T_800BPI  ? MTSET800BPI : (
        !           360:                             req_den == T_1600BPI ? MTSET1600BPI : (
        !           361:                             req_den == T_6250BPI ? MTSET6250BPI : (
        !           362:                             sc->sc_type == MT7980ID
        !           363:                                                  ? MTSET6250DC
        !           364:                                                  : MTSET6250BPI))));
        !           365:                        if (mtcommand(dev, mtset_density, 0) == 0)
        !           366:                                sc->sc_density = req_den;
        !           367:                }
        !           368:        }
        !           369:        return (0);
        !           370: errout:
        !           371:        sc->sc_flags &= ~MTF_OPEN;
        !           372:        return (error);
        !           373: }
        !           374:
        !           375: int
        !           376: mtclose(dev, flag, fmt, p)
        !           377:        dev_t dev;
        !           378:        int flag, fmt;
        !           379:        struct proc *p;
        !           380: {
        !           381:        struct mt_softc *sc = mt_cd.cd_devs[UNIT(dev)];
        !           382:
        !           383:        if (sc->sc_flags & MTF_WRT) {
        !           384:                (void) mtcommand(dev, MTWEOF, 2);
        !           385:                (void) mtcommand(dev, MTBSF, 0);
        !           386:        }
        !           387:        if ((minor(dev) & T_NOREWIND) == 0)
        !           388:                (void) mtcommand(dev, MTREW, 0);
        !           389:        sc->sc_flags &= ~MTF_OPEN;
        !           390:        return (0);
        !           391: }
        !           392:
        !           393: int
        !           394: mtcommand(dev, cmd, cnt)
        !           395:        dev_t dev;
        !           396:        int cmd;
        !           397:        int cnt;
        !           398: {
        !           399:        struct mt_softc *sc = mt_cd.cd_devs[UNIT(dev)];
        !           400:        struct buf *bp = &sc->sc_bufstore;
        !           401:        int error = 0;
        !           402:
        !           403: #if 1
        !           404:        if (bp->b_flags & B_BUSY)
        !           405:                return (EBUSY);
        !           406: #endif
        !           407:        bp->b_cmd = cmd;
        !           408:        bp->b_dev = dev;
        !           409:        do {
        !           410:                bp->b_flags = B_BUSY | B_CMD;
        !           411:                mtstrategy(bp);
        !           412:                biowait(bp);
        !           413:                if (bp->b_flags & B_ERROR) {
        !           414:                        error = (int) (unsigned) bp->b_error;
        !           415:                        break;
        !           416:                }
        !           417:        } while (--cnt > 0);
        !           418: #if 0
        !           419:        bp->b_flags = 0 /*&= ~B_BUSY*/;
        !           420: #else
        !           421:        bp->b_flags &= ~B_BUSY;
        !           422: #endif
        !           423:        return (error);
        !           424: }
        !           425:
        !           426: /*
        !           427:  * Only thing to check here is for legal record lengths (writes only).
        !           428:  */
        !           429: void
        !           430: mtstrategy(bp)
        !           431:        struct buf *bp;
        !           432: {
        !           433:        struct mt_softc *sc;
        !           434:        struct buf *dp;
        !           435:        int unit;
        !           436:        int s;
        !           437:
        !           438:        unit = UNIT(bp->b_dev);
        !           439:        sc = mt_cd.cd_devs[unit];
        !           440:        dlog(LOG_DEBUG, "%s strategy", sc->sc_dev.dv_xname);
        !           441:        if ((bp->b_flags & (B_CMD | B_READ)) == 0) {
        !           442: #define WRITE_BITS_IGNORED     8
        !           443: #if 0
        !           444:                if (bp->b_bcount & ((1 << WRITE_BITS_IGNORED) - 1)) {
        !           445:                        printf("%s: write record must be multiple of %d\n",
        !           446:                                sc->sc_dev.dv_xname, 1 << WRITE_BITS_IGNORED);
        !           447:                        goto error;
        !           448:                }
        !           449: #endif
        !           450:                s = 16 * 1024;
        !           451:                if (sc->sc_stat2 & SR2_LONGREC) {
        !           452:                        switch (sc->sc_density) {
        !           453:                            case T_1600BPI:
        !           454:                                s = 32 * 1024;
        !           455:                                break;
        !           456:
        !           457:                            case T_6250BPI:
        !           458:                            case T_BADBPI:
        !           459:                                s = 60 * 1024;
        !           460:                                break;
        !           461:                        }
        !           462:                }
        !           463:                if (bp->b_bcount > s) {
        !           464:                        printf("%s: write record (%ld) too big: limit (%d)\n",
        !           465:                                sc->sc_dev.dv_xname, bp->b_bcount, s);
        !           466: #if 0 /* XXX see above */
        !           467:            error:
        !           468: #endif
        !           469:                        bp->b_flags |= B_ERROR;
        !           470:                        bp->b_error = EIO;
        !           471:                        s = splbio();
        !           472:                        biodone(bp);
        !           473:                        splx(s);
        !           474:                        return;
        !           475:                }
        !           476:        }
        !           477:        dp = &sc->sc_tab;
        !           478:        bp->b_actf = NULL;
        !           479:        s = splbio();
        !           480:        bp->b_actb = dp->b_actb;
        !           481:        *dp->b_actb = bp;
        !           482:        dp->b_actb = &bp->b_actf;
        !           483:        if (dp->b_active == 0) {
        !           484:                dp->b_active = 1;
        !           485:                mtustart(sc);
        !           486:        }
        !           487:        splx(s);
        !           488: }
        !           489:
        !           490: void
        !           491: mtustart(sc)
        !           492:        struct mt_softc *sc;
        !           493: {
        !           494:
        !           495:        dlog(LOG_DEBUG, "%s ustart", sc->sc_dev.dv_xname);
        !           496:        if (hpibreq(sc->sc_dev.dv_parent, &sc->sc_hq))
        !           497:                mtstart(sc);
        !           498: }
        !           499:
        !           500: void
        !           501: spl_mtintr(arg)
        !           502:        void *arg;
        !           503: {
        !           504:        struct mt_softc *sc = arg;
        !           505:        int s = splbio();
        !           506:
        !           507:        hpibppclear(sc->sc_hpibno);
        !           508:        mtintr(sc);
        !           509:        splx(s);
        !           510: }
        !           511:
        !           512: void
        !           513: spl_mtstart(arg)
        !           514:        void *arg;
        !           515: {
        !           516:        int s = splbio();
        !           517:
        !           518:        mtstart(arg);
        !           519:        splx(s);
        !           520: }
        !           521:
        !           522: void
        !           523: mtstart(arg)
        !           524:        void *arg;
        !           525: {
        !           526:        struct mt_softc *sc = arg;
        !           527:        struct buf *bp, *dp;
        !           528:        short   cmdcount = 1;
        !           529:        u_char  cmdbuf[2];
        !           530:        int s;
        !           531:
        !           532:        dlog(LOG_DEBUG, "%s start", sc->sc_dev.dv_xname);
        !           533:        sc->sc_flags &= ~MTF_WRT;
        !           534:        bp = sc->sc_tab.b_actf;
        !           535:        if ((sc->sc_flags & MTF_ALIVE) == 0 &&
        !           536:            ((bp->b_flags & B_CMD) == 0 || bp->b_cmd != MTRESET))
        !           537:                goto fatalerror;
        !           538:
        !           539:        if (sc->sc_flags & MTF_REW) {
        !           540:                if (!hpibpptest(sc->sc_hpibno, sc->sc_slave))
        !           541:                        goto stillrew;
        !           542:                switch (mtreaddsj(sc, MTE_DSJ_FORCE|MTE_COMPLETE|MTE_IDLE)) {
        !           543:                    case 0:
        !           544:                    case 1:
        !           545:                stillrew:
        !           546:                        if ((sc->sc_stat1 & SR1_BOT) ||
        !           547:                            !(sc->sc_stat1 & SR1_ONLINE)) {
        !           548:                                sc->sc_flags &= ~MTF_REW;
        !           549:                                break;
        !           550:                        }
        !           551:                    case -2:
        !           552:                        /*
        !           553:                         * -2 means "timeout" reading DSJ, which is probably
        !           554:                         * temporary.  This is considered OK when doing a NOP,
        !           555:                         * but not otherwise.
        !           556:                         */
        !           557:                        if (sc->sc_flags & (MTF_DSJTIMEO | MTF_STATTIMEO)) {
        !           558:                                timeout_add(&sc->sc_start_to, hz >> 5);
        !           559:                                return;
        !           560:                        }
        !           561:                    case 2:
        !           562:                        if (bp->b_cmd != MTNOP || !(bp->b_flags & B_CMD)) {
        !           563:                                bp->b_error = EBUSY;
        !           564:                                goto errdone;
        !           565:                        }
        !           566:                        goto done;
        !           567:
        !           568:                    default:
        !           569:                        goto fatalerror;
        !           570:                }
        !           571:        }
        !           572:        if (bp->b_flags & B_CMD) {
        !           573:                if (sc->sc_flags & MTF_PASTEOT) {
        !           574:                        switch(bp->b_cmd) {
        !           575:                            case MTFSF:
        !           576:                            case MTWEOF:
        !           577:                            case MTFSR:
        !           578:                                bp->b_error = ENOSPC;
        !           579:                                goto errdone;
        !           580:
        !           581:                            case MTBSF:
        !           582:                            case MTOFFL:
        !           583:                            case MTBSR:
        !           584:                            case MTREW:
        !           585:                                sc->sc_flags &= ~(MTF_PASTEOT | MTF_ATEOT);
        !           586:                                break;
        !           587:                        }
        !           588:                }
        !           589:                switch(bp->b_cmd) {
        !           590:                    case MTFSF:
        !           591:                        if (sc->sc_flags & MTF_HITEOF)
        !           592:                                goto done;
        !           593:                        cmdbuf[0] = MTTC_FSF;
        !           594:                        break;
        !           595:
        !           596:                    case MTBSF:
        !           597:                        if (sc->sc_flags & MTF_HITBOF)
        !           598:                                goto done;
        !           599:                        cmdbuf[0] = MTTC_BSF;
        !           600:                        break;
        !           601:
        !           602:                    case MTOFFL:
        !           603:                        sc->sc_flags |= MTF_REW;
        !           604:                        cmdbuf[0] = MTTC_REWOFF;
        !           605:                        break;
        !           606:
        !           607:                    case MTWEOF:
        !           608:                        cmdbuf[0] = MTTC_WFM;
        !           609:                        break;
        !           610:
        !           611:                    case MTBSR:
        !           612:                        cmdbuf[0] = MTTC_BSR;
        !           613:                        break;
        !           614:
        !           615:                    case MTFSR:
        !           616:                        cmdbuf[0] = MTTC_FSR;
        !           617:                        break;
        !           618:
        !           619:                    case MTREW:
        !           620:                        sc->sc_flags |= MTF_REW;
        !           621:                        cmdbuf[0] = MTTC_REW;
        !           622:                        break;
        !           623:
        !           624:                    case MTNOP:
        !           625:                        /*
        !           626:                         * NOP is supposed to set status bits.
        !           627:                         * Force readdsj to do it.
        !           628:                         */
        !           629:                        switch (mtreaddsj(sc,
        !           630:                          MTE_DSJ_FORCE | MTE_COMPLETE | MTE_IDLE)) {
        !           631:                            default:
        !           632:                                goto done;
        !           633:
        !           634:                            case -1:
        !           635:                                /*
        !           636:                                 * If this fails, perform a device clear
        !           637:                                 * to fix any protocol problems and (most
        !           638:                                 * likely) get the status.
        !           639:                                 */
        !           640:                                bp->b_cmd = MTRESET;
        !           641:                                break;
        !           642:
        !           643:                            case -2:
        !           644:                                timeout_add(&sc->sc_start_to, hz >> 5);
        !           645:                                return;
        !           646:                        }
        !           647:
        !           648:                    case MTRESET:
        !           649:                        /*
        !           650:                         * 1) selected device clear (send with "-2" secondary)
        !           651:                         * 2) set timeout, then wait for "service request"
        !           652:                         * 3) interrupt will read DSJ (and END COMPLETE-IDLE)
        !           653:                         */
        !           654:                        if (hpibsend(sc->sc_hpibno, sc->sc_slave, -2, NULL, 0)){
        !           655:                                log(LOG_ERR, "%s can't reset",
        !           656:                                    sc->sc_dev.dv_xname);
        !           657:                                goto fatalerror;
        !           658:                        }
        !           659:                        timeout_add(&sc->sc_intr_to, 4 * hz);
        !           660:                        hpibawait(sc->sc_hpibno);
        !           661:                        return;
        !           662:
        !           663:                    case MTSET800BPI:
        !           664:                        cmdbuf[0] = MTTC_800;
        !           665:                        break;
        !           666:
        !           667:                    case MTSET1600BPI:
        !           668:                        cmdbuf[0] = MTTC_1600;
        !           669:                        break;
        !           670:
        !           671:                    case MTSET6250BPI:
        !           672:                        cmdbuf[0] = MTTC_6250;
        !           673:                        break;
        !           674:
        !           675:                    case MTSET6250DC:
        !           676:                        cmdbuf[0] = MTTC_DC6250;
        !           677:                        break;
        !           678:                }
        !           679:        } else {
        !           680:                if (sc->sc_flags & MTF_PASTEOT) {
        !           681:                        bp->b_error = ENOSPC;
        !           682:                        goto errdone;
        !           683:                }
        !           684:                if (bp->b_flags & B_READ) {
        !           685:                        sc->sc_flags |= MTF_IO;
        !           686:                        cmdbuf[0] = MTTC_READ;
        !           687:                } else {
        !           688:                        sc->sc_flags |= MTF_WRT | MTF_IO;
        !           689:                        cmdbuf[0] = MTTC_WRITE;
        !           690:                        cmdbuf[1] = (bp->b_bcount + ((1 << WRITE_BITS_IGNORED) - 1)) >> WRITE_BITS_IGNORED;
        !           691:                        cmdcount = 2;
        !           692:                }
        !           693:        }
        !           694:        if (hpibsend(sc->sc_hpibno, sc->sc_slave, MTL_TCMD, cmdbuf, cmdcount)
        !           695:            == cmdcount) {
        !           696:                if (sc->sc_flags & MTF_REW)
        !           697:                        goto done;
        !           698:                hpibawait(sc->sc_hpibno);
        !           699:                return;
        !           700:        }
        !           701: fatalerror:
        !           702:        /*
        !           703:         * If anything fails, the drive is probably hosed, so mark it not
        !           704:         * "ALIVE" (but it EXISTS and is OPEN or we wouldn't be here, and
        !           705:         * if, last we heard, it was REWinding, remember that).
        !           706:         */
        !           707:        sc->sc_flags &= MTF_EXISTS | MTF_OPEN | MTF_REW;
        !           708:        bp->b_error = EIO;
        !           709: errdone:
        !           710:        bp->b_flags |= B_ERROR;
        !           711: done:
        !           712:        sc->sc_flags &= ~(MTF_HITEOF | MTF_HITBOF);
        !           713:        s = splbio();
        !           714:        biodone(bp);
        !           715:        splx(s);
        !           716:        if ((dp = bp->b_actf))
        !           717:                dp->b_actb = bp->b_actb;
        !           718:        else
        !           719:                sc->sc_tab.b_actb = bp->b_actb;
        !           720:        *bp->b_actb = dp;
        !           721:        hpibfree(sc->sc_dev.dv_parent, &sc->sc_hq);
        !           722:        if ((bp = dp) == NULL)
        !           723:                sc->sc_tab.b_active = 0;
        !           724:        else
        !           725:                mtustart(sc);
        !           726: }
        !           727:
        !           728: /*
        !           729:  * The Utah code had a bug which meant that the driver was unable to read.
        !           730:  * "rw" was initialized to bp->b_flags & B_READ before "bp" was initialized.
        !           731:  *   -- ajv@comp.vuw.ac.nz
        !           732:  */
        !           733: void
        !           734: mtgo(arg)
        !           735:        void *arg;
        !           736: {
        !           737:        struct mt_softc *sc = arg;
        !           738:        struct buf *bp;
        !           739:        int rw;
        !           740:
        !           741:        dlog(LOG_DEBUG, "%s go", sc->sc_dev.dv_xname);
        !           742:        bp = sc->sc_tab.b_actf;
        !           743:        rw = bp->b_flags & B_READ;
        !           744:        hpibgo(sc->sc_hpibno, sc->sc_slave, rw ? MTT_READ : MTL_WRITE,
        !           745:            bp->b_data, bp->b_bcount, rw, rw != 0);
        !           746: }
        !           747:
        !           748: void
        !           749: mtintr(arg)
        !           750:        void *arg;
        !           751: {
        !           752:        struct mt_softc *sc = arg;
        !           753:        struct buf *bp, *dp;
        !           754:        int i;
        !           755:        u_char cmdbuf[4];
        !           756:
        !           757:        bp = sc->sc_tab.b_actf;
        !           758:        if (bp == NULL) {
        !           759:                log(LOG_ERR, "%s intr: bp == NULL", sc->sc_dev.dv_xname);
        !           760:                return;
        !           761:        }
        !           762:
        !           763:        dlog(LOG_DEBUG, "%s intr", sc->sc_dev.dv_xname);
        !           764:
        !           765:        /*
        !           766:         * Some operation completed.  Read status bytes and report errors.
        !           767:         * Clear EOF flags here `cause they're set once on specific conditions
        !           768:         * below when a command succeeds.
        !           769:         * A DSJ of 2 always means keep waiting.  If the command was READ
        !           770:         * (and we're in data DMA phase) stop data transfer first.
        !           771:         */
        !           772:        sc->sc_flags &= ~(MTF_HITEOF | MTF_HITBOF);
        !           773:        if ((bp->b_flags & (B_CMD|B_READ)) == B_READ &&
        !           774:            !(sc->sc_flags & (MTF_IO | MTF_STATTIMEO | MTF_DSJTIMEO))){
        !           775:                cmdbuf[0] = MTE_STOP;
        !           776:                (void) hpibsend(sc->sc_hpibno, sc->sc_slave, MTL_ECMD,cmdbuf,1);
        !           777:        }
        !           778:        switch (mtreaddsj(sc, 0)) {
        !           779:            case 0:
        !           780:                break;
        !           781:
        !           782:            case 1:
        !           783:                /*
        !           784:                 * If we're in the middle of a READ/WRITE and have yet to
        !           785:                 * start the data transfer, a DSJ of one should terminate it.
        !           786:                 */
        !           787:                sc->sc_flags &= ~MTF_IO;
        !           788:                break;
        !           789:
        !           790:            case 2:
        !           791:                (void) hpibawait(sc->sc_hpibno);
        !           792:                return;
        !           793:
        !           794:            case -2:
        !           795:                /*
        !           796:                 * -2 means that the drive failed to respond quickly enough
        !           797:                 * to the request for DSJ.  It's probably just "busy" figuring
        !           798:                 * it out and will know in a little bit...
        !           799:                 */
        !           800:                timeout_add(&sc->sc_intr_to, hz >> 5);
        !           801:                return;
        !           802:
        !           803:            default:
        !           804:                log(LOG_ERR, "%s intr: can't get drive stat",
        !           805:                    sc->sc_dev.dv_xname);
        !           806:                goto error;
        !           807:        }
        !           808:        if (sc->sc_stat1 & (SR1_ERR | SR1_REJECT)) {
        !           809:                i = sc->sc_stat4 & SR4_ERCLMASK;
        !           810:                log(LOG_ERR, "%s: %s error, retry %d, SR2/3 %x/%x, code %d",
        !           811:                        sc->sc_dev.dv_xname, i == SR4_DEVICE ? "device" :
        !           812:                        (i == SR4_PROTOCOL ? "protocol" :
        !           813:                        (i == SR4_SELFTEST ? "selftest" : "unknown")),
        !           814:                        sc->sc_stat4 & SR4_RETRYMASK, sc->sc_stat2,
        !           815:                        sc->sc_stat3, sc->sc_stat5);
        !           816:
        !           817:                if ((bp->b_flags & B_CMD) && bp->b_cmd == MTRESET)
        !           818:                        timeout_del(&sc->sc_intr_to);
        !           819:                if (sc->sc_stat3 & SR3_POWERUP)
        !           820:                        sc->sc_flags &= MTF_OPEN | MTF_EXISTS;
        !           821:                goto error;
        !           822:        }
        !           823:        /*
        !           824:         * Report and clear any soft errors.
        !           825:         */
        !           826:        if (sc->sc_stat1 & SR1_SOFTERR) {
        !           827:                log(LOG_WARNING, "%s: soft error, retry %d\n",
        !           828:                        sc->sc_dev.dv_xname, sc->sc_stat4 & SR4_RETRYMASK);
        !           829:                sc->sc_stat1 &= ~SR1_SOFTERR;
        !           830:        }
        !           831:        /*
        !           832:         * We've initiated a read or write, but haven't actually started to
        !           833:         * DMA the data yet.  At this point, the drive's ready.
        !           834:         */
        !           835:        if (sc->sc_flags & MTF_IO) {
        !           836:                sc->sc_flags &= ~MTF_IO;
        !           837:                if (hpibustart(sc->sc_hpibno))
        !           838:                        mtgo(sc);
        !           839:                return;
        !           840:        }
        !           841:        /*
        !           842:         * Check for End Of Tape - we're allowed to hit EOT and then write (or
        !           843:         * read) one more record.  If we get here and have not already hit EOT,
        !           844:         * return ENOSPC to inform the process that it's hit it.  If we get
        !           845:         * here and HAVE already hit EOT, don't allow any more operations that
        !           846:         * move the tape forward.
        !           847:         */
        !           848:        if (sc->sc_stat1 & SR1_EOT) {
        !           849:                if (sc->sc_flags & MTF_ATEOT)
        !           850:                        sc->sc_flags |= MTF_PASTEOT;
        !           851:                else {
        !           852:                        bp->b_flags |= B_ERROR;
        !           853:                        bp->b_error = ENOSPC;
        !           854:                        sc->sc_flags |= MTF_ATEOT;
        !           855:                }
        !           856:        }
        !           857:        /*
        !           858:         * If a motion command was being executed, check for Tape Marks.
        !           859:         * If we were doing data, make sure we got the right amount, and
        !           860:         * check for hitting tape marks on reads.
        !           861:         */
        !           862:        if (bp->b_flags & B_CMD) {
        !           863:                if (sc->sc_stat1 & SR1_EOF) {
        !           864:                        if (bp->b_cmd == MTFSR)
        !           865:                                sc->sc_flags |= MTF_HITEOF;
        !           866:                        if (bp->b_cmd == MTBSR)
        !           867:                                sc->sc_flags |= MTF_HITBOF;
        !           868:                }
        !           869:                if (bp->b_cmd == MTRESET) {
        !           870:                        timeout_del(&sc->sc_intr_to);
        !           871:                        sc->sc_flags |= MTF_ALIVE;
        !           872:                }
        !           873:        } else {
        !           874:                i = hpibrecv(sc->sc_hpibno, sc->sc_slave, MTT_BCNT, cmdbuf, 2);
        !           875:                if (i != 2) {
        !           876:                        log(LOG_ERR, "%s intr: can't get xfer length\n",
        !           877:                            sc->sc_dev.dv_xname);
        !           878:                        goto error;
        !           879:                }
        !           880:                i = (int) *((u_short *) cmdbuf);
        !           881:                if (i <= bp->b_bcount) {
        !           882:                        if (i == 0)
        !           883:                                sc->sc_flags |= MTF_HITEOF;
        !           884:                        bp->b_resid = bp->b_bcount - i;
        !           885:                        dlog(LOG_DEBUG, "%s intr: bcount %ld, resid %d",
        !           886:                            sc->sc_dev.dv_xname, bp->b_bcount, bp->b_resid);
        !           887:                } else {
        !           888:                        printf("%s: record (%d) larger than wanted (%ld)\n",
        !           889:                                sc->sc_dev.dv_xname, i, bp->b_bcount);
        !           890:     error:
        !           891:                        sc->sc_flags &= ~MTF_IO;
        !           892:                        bp->b_error = EIO;
        !           893:                        bp->b_flags |= B_ERROR;
        !           894:                }
        !           895:        }
        !           896:        /*
        !           897:         * The operation is completely done.
        !           898:         * Let the drive know with an END command.
        !           899:         */
        !           900:        cmdbuf[0] = MTE_COMPLETE | MTE_IDLE;
        !           901:        (void) hpibsend(sc->sc_hpibno, sc->sc_slave, MTL_ECMD, cmdbuf, 1);
        !           902:        bp->b_flags &= ~B_CMD;
        !           903:        biodone(bp);
        !           904:        if ((dp = bp->b_actf))
        !           905:                dp->b_actb = bp->b_actb;
        !           906:        else
        !           907:                sc->sc_tab.b_actb = bp->b_actb;
        !           908:        *bp->b_actb = dp;
        !           909:        hpibfree(sc->sc_dev.dv_parent, &sc->sc_hq);
        !           910: #if 0
        !           911:        if (bp /*sc->sc_tab.b_actf*/ == NULL)
        !           912: #else
        !           913:        if (sc->sc_tab.b_actf == NULL)
        !           914: #endif
        !           915:                sc->sc_tab.b_active = 0;
        !           916:        else
        !           917:                mtustart(sc);
        !           918: }
        !           919:
        !           920: int
        !           921: mtread(dev, uio, flags)
        !           922:        dev_t dev;
        !           923:        struct uio *uio;
        !           924:        int flags;
        !           925: {
        !           926:        struct mt_softc *sc = mt_cd.cd_devs[UNIT(dev)];
        !           927:
        !           928:        return(physio(mtstrategy, &sc->sc_bufstore,
        !           929:            dev, B_READ, minphys, uio));
        !           930: }
        !           931:
        !           932: int
        !           933: mtwrite(dev, uio, flags)
        !           934:        dev_t dev;
        !           935:        struct uio *uio;
        !           936:        int flags;
        !           937: {
        !           938:        struct mt_softc *sc = mt_cd.cd_devs[UNIT(dev)];
        !           939:
        !           940:        return(physio(mtstrategy, &sc->sc_bufstore,
        !           941:            dev, B_WRITE, minphys, uio));
        !           942: }
        !           943:
        !           944: int
        !           945: mtioctl(dev, cmd, data, flag, p)
        !           946:        dev_t dev;
        !           947:        u_long cmd;
        !           948:        caddr_t data;
        !           949:        int flag;
        !           950:        struct proc *p;
        !           951: {
        !           952:        struct mtop *op;
        !           953:        int cnt;
        !           954:
        !           955:        switch (cmd) {
        !           956:            case MTIOCTOP:
        !           957:                op = (struct mtop *)data;
        !           958:                switch(op->mt_op) {
        !           959:                    case MTWEOF:
        !           960:                    case MTFSF:
        !           961:                    case MTBSR:
        !           962:                    case MTBSF:
        !           963:                    case MTFSR:
        !           964:                        cnt = op->mt_count;
        !           965:                        break;
        !           966:
        !           967:                    case MTOFFL:
        !           968:                    case MTREW:
        !           969:                    case MTNOP:
        !           970:                        cnt = 0;
        !           971:                        break;
        !           972:
        !           973:                    default:
        !           974:                        return (EINVAL);
        !           975:                }
        !           976:                return (mtcommand(dev, op->mt_op, cnt));
        !           977:
        !           978:            case MTIOCGET:
        !           979:                break;
        !           980:
        !           981:            default:
        !           982:                return (EINVAL);
        !           983:        }
        !           984:        return (0);
        !           985: }
        !           986:
        !           987: /*ARGSUSED*/
        !           988: int
        !           989: mtdump(dev, blkno, va, size)
        !           990:        dev_t dev;
        !           991:        daddr64_t blkno;
        !           992:        caddr_t va;
        !           993:        size_t size;
        !           994: {
        !           995:        return (ENODEV);
        !           996: }

CVSweb