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

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

1.1     ! nbrk        1: /*     $OpenBSD: ct.c,v 1.18 2007/06/06 17:15:11 deraadt Exp $ */
        !             2: /*     $NetBSD: ct.c,v 1.21 1997/04/02 22:37:23 scottr Exp $   */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1996, 1997 Jason R. Thorpe.  All rights reserved.
        !             6:  * Copyright (c) 1982, 1990, 1993
        !             7:  *     The Regents of the University of California.  All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. Neither the name of the University nor the names of its contributors
        !            18:  *    may be used to endorse or promote products derived from this software
        !            19:  *    without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            31:  * SUCH DAMAGE.
        !            32:  *
        !            33:  *     @(#)ct.c        8.2 (Berkeley) 1/12/94
        !            34:  */
        !            35:
        !            36: /*
        !            37:  * CS80 cartridge tape driver (9144, 88140, 9145)
        !            38:  *
        !            39:  * Reminder:
        !            40:  *     C_CC bit (character count option) when used in the CS/80 command
        !            41:  *     'set options' will cause the tape not to stream.
        !            42:  *
        !            43:  * TODO:
        !            44:  *     make filesystem compatible
        !            45:  *     make block mode work according to mtio(4) spec. (if possible)
        !            46:  *     merge with cs80 disk driver
        !            47:  *     finish support of 9145
        !            48:  */
        !            49:
        !            50: #include <sys/param.h>
        !            51: #include <sys/systm.h>
        !            52: #include <sys/buf.h>
        !            53: #include <sys/conf.h>
        !            54: #include <sys/device.h>
        !            55: #include <sys/ioctl.h>
        !            56: #include <sys/mtio.h>
        !            57: #include <sys/proc.h>
        !            58:
        !            59: #include <hp300/dev/hpibvar.h>
        !            60:
        !            61: #include <hp300/dev/ctreg.h>
        !            62:
        !            63: /* number of eof marks to remember */
        !            64: #define EOFS   128
        !            65:
        !            66: struct ct_softc {
        !            67:        struct  device sc_dev;
        !            68:        int     sc_slave;               /* HP-IB slave ID */
        !            69:        int     sc_punit;               /* physical unit */
        !            70:        struct  ct_iocmd sc_ioc;
        !            71:        struct  ct_rscmd sc_rsc;
        !            72:        struct  ct_stat sc_stat;
        !            73:        struct  ct_ssmcmd sc_ssmc;
        !            74:        struct  ct_srcmd sc_src;
        !            75:        struct  ct_soptcmd sc_soptc;
        !            76:        struct  ct_ulcmd sc_ul;
        !            77:        struct  ct_wfmcmd sc_wfm;
        !            78:        struct  ct_clearcmd sc_clear;
        !            79:        struct  buf sc_tab;
        !            80:        struct  buf *sc_bp;
        !            81:        struct  buf sc_bufstore;        /* XXX */
        !            82:        int     sc_blkno;
        !            83:        int     sc_cmd;
        !            84:        int     sc_resid;
        !            85:        char    *sc_addr;
        !            86:        int     sc_flags;
        !            87:        short   sc_type;
        !            88:        struct  hpibqueue sc_hq;        /* entry on hpib job queue */
        !            89:        int     sc_eofp;
        !            90:        int     sc_eofs[EOFS];
        !            91: };
        !            92:
        !            93: /* flags */
        !            94: #define        CTF_OPEN        0x01
        !            95: #define        CTF_ALIVE       0x02
        !            96: #define        CTF_WRT         0x04
        !            97: #define        CTF_CMD         0x08
        !            98: #define        CTF_IO          0x10
        !            99: #define        CTF_BEOF        0x20
        !           100: #define        CTF_AEOF        0x40
        !           101: #define        CTF_EOT         0x80
        !           102: #define        CTF_STATWAIT    0x100
        !           103: #define CTF_CANSTREAM  0x200
        !           104: #define        CTF_WRTTN       0x400
        !           105:
        !           106: int    ctmatch(struct device *, void *, void *);
        !           107: void   ctattach(struct device *, struct device *, void *);
        !           108:
        !           109: struct cfattach ct_ca = {
        !           110:        sizeof(struct ct_softc), ctmatch, ctattach
        !           111: };
        !           112:
        !           113: struct cfdriver ct_cd = {
        !           114:        NULL, "ct", DV_TAPE
        !           115: };
        !           116:
        !           117: int    ctident(struct device *, struct ct_softc *,
        !           118:            struct hpibbus_attach_args *);
        !           119:
        !           120: void   ctreset(struct ct_softc *);
        !           121: void   ctaddeof(struct ct_softc *);
        !           122: void   ctustart(struct ct_softc *);
        !           123: void   cteof(struct ct_softc *, struct buf *);
        !           124: void   ctdone(struct ct_softc *, struct buf *);
        !           125:
        !           126: void   ctstart(void *);
        !           127: void   ctgo(void *);
        !           128: void   ctintr(void *);
        !           129:
        !           130: void   ctcommand(dev_t, int, int);
        !           131:
        !           132: cdev_decl(ct);
        !           133: bdev_decl(ct);
        !           134:
        !           135: const struct   ctinfo {
        !           136:        short   hwid;
        !           137:        short   punit;
        !           138:        char    *desc;
        !           139: } ctinfo[] = {
        !           140:        { CT7946ID,     1,      "7946A" },
        !           141:        { CT7912PID,    1,      "7912P" },
        !           142:        { CT7914PID,    1,      "7914P" },
        !           143:        { CT9144ID,     0,      "9144"  },
        !           144:        { CT9145ID,     0,      "9145"  },
        !           145: };
        !           146: int    nctinfo = sizeof(ctinfo) / sizeof(ctinfo[0]);
        !           147:
        !           148: #define        CT_NOREW        4
        !           149: #define        CT_STREAM       8
        !           150: #define        UNIT(x)         (minor(x) & 3)
        !           151: #define        ctpunit(x)      ((x) & 7)
        !           152:
        !           153: #ifdef DEBUG
        !           154: int ctdebug = 0;
        !           155: #define CDB_FILES      0x01
        !           156: #define CT_BSF         0x02
        !           157: #endif
        !           158:
        !           159: int
        !           160: ctmatch(parent, match, aux)
        !           161:        struct device *parent;
        !           162:        void *match, *aux;
        !           163: {
        !           164:        struct hpibbus_attach_args *ha = aux;
        !           165:
        !           166:        return (ctident(parent, NULL, ha));
        !           167: }
        !           168:
        !           169: void
        !           170: ctattach(parent, self, aux)
        !           171:        struct device *parent, *self;
        !           172:        void *aux;
        !           173: {
        !           174:        struct ct_softc *sc = (struct ct_softc *)self;
        !           175:        struct hpibbus_attach_args *ha = aux;
        !           176:
        !           177:        if (ctident(parent, sc, ha) == 0) {
        !           178:                /* can't happen */
        !           179:                printf("\n%s: didn't respond to describe command!\n",
        !           180:                    sc->sc_dev.dv_xname);
        !           181:                return;
        !           182:        }
        !           183:
        !           184:        sc->sc_slave = ha->ha_slave;
        !           185:        sc->sc_punit = ha->ha_punit;
        !           186:
        !           187:        sc->sc_tab.b_actb = &sc->sc_tab.b_actf;
        !           188:
        !           189:        /* Initialize hpib job queue entry. */
        !           190:        sc->sc_hq.hq_softc = sc;
        !           191:        sc->sc_hq.hq_slave = sc->sc_slave;
        !           192:        sc->sc_hq.hq_start = ctstart;
        !           193:        sc->sc_hq.hq_go = ctgo;
        !           194:        sc->sc_hq.hq_intr = ctintr;
        !           195:
        !           196:        ctreset(sc);
        !           197:        sc->sc_flags |= CTF_ALIVE;
        !           198: }
        !           199:
        !           200: int
        !           201: ctident(parent, sc, ha)
        !           202:        struct device *parent;
        !           203:        struct ct_softc *sc;
        !           204:        struct hpibbus_attach_args *ha;
        !           205: {
        !           206:        struct cs80_describe desc;
        !           207:        u_char stat, cmd[3];
        !           208:        char name[7];
        !           209:        int i, id, n, type, canstream;
        !           210:
        !           211:        type = canstream = 0;
        !           212:
        !           213:        /* Verify that we have a CS80 device. */
        !           214:        if ((ha->ha_id & 0x200) == 0)
        !           215:                return (0);
        !           216:
        !           217:        /* Is it one of the tapes we support? */
        !           218:        for (id = 0; id < nctinfo; id++)
        !           219:                if (ha->ha_id == ctinfo[id].hwid &&
        !           220:                    ha->ha_punit == ctinfo[id].punit)
        !           221:                        break;
        !           222:        if (id == nctinfo)
        !           223:                return (0);
        !           224:
        !           225:        /*
        !           226:         * So far, so good.  Get drive parameters.  Note command
        !           227:         * is always issued to unit 0.
        !           228:         */
        !           229:        bzero(&desc, sizeof(desc));
        !           230:        stat = 0;
        !           231:        cmd[0] = C_SUNIT(0);
        !           232:        cmd[1] = C_SVOL(0);
        !           233:        cmd[2] = C_DESC;
        !           234:        hpibsend(parent->dv_unit, ha->ha_slave, C_CMD, cmd, sizeof(cmd));
        !           235:        hpibrecv(parent->dv_unit, ha->ha_slave, C_EXEC, &desc, sizeof(desc));
        !           236:        hpibrecv(parent->dv_unit, ha->ha_slave, C_QSTAT, &stat, sizeof(stat));
        !           237:
        !           238:        if (desc.d_name == 0 && stat != 0)
        !           239:                return (0);
        !           240:
        !           241:        bzero(name, sizeof(name));
        !           242:        n = desc.d_name;
        !           243:        for (i = 5; i >= 0; i--) {
        !           244:                name[i] = (n & 0xf) + '0';
        !           245:                n >>= 4;
        !           246:        }
        !           247:
        !           248:        switch (ha->ha_id) {
        !           249:        case CT7946ID:
        !           250:                if (bcmp(name, "079450", 6) == 0)
        !           251:                        return (0);             /* not really a 7946 */
        !           252:                /* FALLTHROUGH */
        !           253:        case CT9144ID:
        !           254:        case CT9145ID:
        !           255:                type = CT9144;
        !           256:                canstream = 1;
        !           257:                break;
        !           258:
        !           259:        case CT7912PID:
        !           260:        case CT7914PID:
        !           261:                type = CT88140;
        !           262:                break;
        !           263:        }
        !           264:
        !           265:        if (sc != NULL) {
        !           266:                sc->sc_type = type;
        !           267:                sc->sc_flags = canstream ? CTF_CANSTREAM : 0;
        !           268:                printf(": %s %stape\n", ctinfo[id].desc,
        !           269:                    canstream ? "streaming " : "");
        !           270:        }
        !           271:
        !           272:        return (1);
        !           273: }
        !           274:
        !           275: void
        !           276: ctreset(sc)
        !           277:        struct ct_softc *sc;
        !           278: {
        !           279:        int ctlr, slave;
        !           280:        u_char stat;
        !           281:
        !           282:        ctlr = sc->sc_dev.dv_parent->dv_unit;
        !           283:        slave = sc->sc_slave;
        !           284:
        !           285:        sc->sc_clear.unit = C_SUNIT(sc->sc_punit);
        !           286:        sc->sc_clear.cmd = C_CLEAR;
        !           287:        hpibsend(ctlr, slave, C_TCMD, &sc->sc_clear, sizeof(sc->sc_clear));
        !           288:        hpibswait(ctlr, slave);
        !           289:        hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
        !           290:
        !           291:        sc->sc_src.unit = C_SUNIT(CTCTLR);
        !           292:        sc->sc_src.nop = C_NOP;
        !           293:        sc->sc_src.cmd = C_SREL;
        !           294:        sc->sc_src.param = C_REL;
        !           295:        hpibsend(ctlr, slave, C_CMD, &sc->sc_src, sizeof(sc->sc_src));
        !           296:        hpibswait(ctlr, slave);
        !           297:        hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
        !           298:
        !           299:        sc->sc_ssmc.unit = C_SUNIT(sc->sc_punit);
        !           300:        sc->sc_ssmc.cmd = C_SSM;
        !           301:        sc->sc_ssmc.refm = REF_MASK;
        !           302:        sc->sc_ssmc.fefm = FEF_MASK;
        !           303:        sc->sc_ssmc.aefm = AEF_MASK;
        !           304:        sc->sc_ssmc.iefm = IEF_MASK;
        !           305:        hpibsend(ctlr, slave, C_CMD, &sc->sc_ssmc, sizeof(sc->sc_ssmc));
        !           306:        hpibswait(ctlr, slave);
        !           307:        hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
        !           308:
        !           309:        sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
        !           310:        sc->sc_soptc.nop = C_NOP;
        !           311:        sc->sc_soptc.cmd = C_SOPT;
        !           312:        sc->sc_soptc.opt = C_SPAR;
        !           313:        hpibsend(ctlr, slave, C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc));
        !           314:        hpibswait(ctlr, slave);
        !           315:        hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
        !           316: }
        !           317:
        !           318: /*ARGSUSED*/
        !           319: int
        !           320: ctopen(dev, flag, type, p)
        !           321:        dev_t dev;
        !           322:        int flag, type;
        !           323:        struct proc *p;
        !           324: {
        !           325:        struct ct_softc *sc;
        !           326:        u_char stat;
        !           327:        int cc, ctlr, slave;
        !           328:
        !           329:        if (UNIT(dev) >= ct_cd.cd_ndevs ||
        !           330:            (sc = ct_cd.cd_devs[UNIT(dev)]) == NULL ||
        !           331:            (sc->sc_flags & CTF_ALIVE) == 0)
        !           332:                return (ENXIO);
        !           333:
        !           334:        if (sc->sc_flags & CTF_OPEN)
        !           335:                return (EBUSY);
        !           336:
        !           337:        ctlr = sc->sc_dev.dv_parent->dv_unit;
        !           338:        slave = sc->sc_slave;
        !           339:
        !           340:        sc->sc_soptc.unit = C_SUNIT(sc->sc_punit);
        !           341:        sc->sc_soptc.nop = C_NOP;
        !           342:        sc->sc_soptc.cmd = C_SOPT;
        !           343:        if ((dev & CT_STREAM) && (sc->sc_flags & CTF_CANSTREAM))
        !           344:                sc->sc_soptc.opt = C_SPAR | C_IMRPT;
        !           345:        else
        !           346:                sc->sc_soptc.opt = C_SPAR;
        !           347:
        !           348:        /*
        !           349:         * Check the return of hpibsend() and hpibswait().
        !           350:         * Drive could be loading/unloading a tape. If not checked,
        !           351:         * driver hangs.
        !           352:         */
        !           353:        cc = hpibsend(ctlr, slave, C_CMD, &sc->sc_soptc, sizeof(sc->sc_soptc));
        !           354:        if (cc != sizeof(sc->sc_soptc))
        !           355:                return (EBUSY);
        !           356:
        !           357:        hpibswait(ctlr, slave);
        !           358:        cc = hpibrecv(ctlr, slave, C_QSTAT, &stat, sizeof(stat));
        !           359:        if (cc != sizeof(stat))
        !           360:                return(EBUSY);
        !           361:
        !           362:        sc->sc_flags |= CTF_OPEN;
        !           363:        return(0);
        !           364: }
        !           365:
        !           366: /*ARGSUSED*/
        !           367: int
        !           368: ctclose(dev, flag, fmt, p)
        !           369:        dev_t dev;
        !           370:        int flag, fmt;
        !           371:        struct proc *p;
        !           372: {
        !           373:        struct ct_softc *sc = ct_cd.cd_devs[UNIT(dev)];
        !           374:
        !           375:        if ((sc->sc_flags & (CTF_WRT|CTF_WRTTN)) == (CTF_WRT|CTF_WRTTN) &&
        !           376:            (sc->sc_flags & CTF_EOT) == 0 ) { /* XXX return error if EOT ?? */
        !           377:                ctcommand(dev, MTWEOF, 2);
        !           378:                ctcommand(dev, MTBSR, 1);
        !           379:                if (sc->sc_eofp == EOFS - 1)
        !           380:                        sc->sc_eofs[EOFS - 1]--;
        !           381:                else
        !           382:                        sc->sc_eofp--;
        !           383: #ifdef DEBUG
        !           384:                if(ctdebug & CT_BSF)
        !           385:                        printf("%s: ctclose backup eofs prt %d blk %d\n",
        !           386:                               sc->sc_dev.dv_xname, sc->sc_eofp,
        !           387:                               sc->sc_eofs[sc->sc_eofp]);
        !           388: #endif
        !           389:        }
        !           390:        if ((minor(dev) & CT_NOREW) == 0)
        !           391:                ctcommand(dev, MTREW, 1);
        !           392:        sc->sc_flags &= ~(CTF_OPEN | CTF_WRT | CTF_WRTTN);
        !           393: #ifdef DEBUG
        !           394:        if (ctdebug & CDB_FILES)
        !           395:                printf("ctclose: flags %x\n", sc->sc_flags);
        !           396: #endif
        !           397:        return(0);      /* XXX */
        !           398: }
        !           399:
        !           400: void
        !           401: ctcommand(dev, cmd, cnt)
        !           402:        dev_t dev;
        !           403:        int cmd;
        !           404:        int cnt;
        !           405: {
        !           406:        struct ct_softc *sc = ct_cd.cd_devs[UNIT(dev)];
        !           407:        struct buf *bp = &sc->sc_bufstore;
        !           408:        struct buf *nbp = 0;
        !           409:
        !           410:        if (cmd == MTBSF && sc->sc_eofp == EOFS - 1) {
        !           411:                cnt = sc->sc_eofs[EOFS - 1] - cnt;
        !           412:                ctcommand(dev, MTREW, 1);
        !           413:                ctcommand(dev, MTFSF, cnt);
        !           414:                cnt = 2;
        !           415:                cmd = MTBSR;
        !           416:        }
        !           417:
        !           418:        if (cmd == MTBSF && sc->sc_eofp - cnt < 0) {
        !           419:                cnt = 1;
        !           420:                cmd = MTREW;
        !           421:        }
        !           422:
        !           423:        sc->sc_flags |= CTF_CMD;
        !           424:        sc->sc_bp = bp;
        !           425:        sc->sc_cmd = cmd;
        !           426:        bp->b_dev = dev;
        !           427:        if (cmd == MTFSF) {
        !           428:                nbp = (struct buf *)geteblk(MAXBSIZE);
        !           429:                bp->b_data = nbp->b_data;
        !           430:                bp->b_bcount = MAXBSIZE;
        !           431:        }
        !           432:
        !           433:        while (cnt-- > 0) {
        !           434:                bp->b_flags = B_BUSY;
        !           435:                if (cmd == MTBSF) {
        !           436:                        sc->sc_blkno = sc->sc_eofs[sc->sc_eofp];
        !           437:                        sc->sc_eofp--;
        !           438: #ifdef DEBUG
        !           439:                        if (ctdebug & CT_BSF)
        !           440:                                printf("%s: backup eof pos %d blk %d\n",
        !           441:                                    sc->sc_dev.dv_xname, sc->sc_eofp,
        !           442:                                    sc->sc_eofs[sc->sc_eofp]);
        !           443: #endif
        !           444:                }
        !           445:                ctstrategy(bp);
        !           446:                biowait(bp);
        !           447:        }
        !           448:        bp->b_flags = 0;
        !           449:        sc->sc_flags &= ~CTF_CMD;
        !           450:        if (nbp)
        !           451:                brelse(nbp);
        !           452: }
        !           453:
        !           454: void
        !           455: ctstrategy(bp)
        !           456:        struct buf *bp;
        !           457: {
        !           458:        struct buf *dp;
        !           459:        int s, unit;
        !           460:        struct ct_softc *sc;
        !           461:
        !           462:        unit = UNIT(bp->b_dev);
        !           463:        sc = ct_cd.cd_devs[unit];
        !           464:
        !           465:        dp = &sc->sc_tab;
        !           466:        bp->b_actf = NULL;
        !           467:        s = splbio();
        !           468:        bp->b_actb = dp->b_actb;
        !           469:        *(dp->b_actb) = bp;
        !           470:        dp->b_actb = &bp->b_actf;
        !           471:        if (dp->b_active == 0) {
        !           472:                dp->b_active = 1;
        !           473:                ctustart(sc);
        !           474:        }
        !           475:        splx(s);
        !           476: }
        !           477:
        !           478: void
        !           479: ctustart(sc)
        !           480:        struct ct_softc *sc;
        !           481: {
        !           482:        struct buf *bp;
        !           483:
        !           484:        bp = sc->sc_tab.b_actf;
        !           485:        sc->sc_addr = bp->b_data;
        !           486:        sc->sc_resid = bp->b_bcount;
        !           487:        if (hpibreq(sc->sc_dev.dv_parent, &sc->sc_hq))
        !           488:                ctstart(sc);
        !           489: }
        !           490:
        !           491: void
        !           492: ctstart(arg)
        !           493:        void *arg;
        !           494: {
        !           495:        struct ct_softc *sc = arg;
        !           496:        struct buf *bp;
        !           497:        int i, ctlr, slave;
        !           498:
        !           499:        ctlr = sc->sc_dev.dv_parent->dv_unit;
        !           500:        slave = sc->sc_slave;
        !           501:
        !           502:        bp = sc->sc_tab.b_actf;
        !           503:        if ((sc->sc_flags & CTF_CMD) && sc->sc_bp == bp) {
        !           504:                switch(sc->sc_cmd) {
        !           505:                case MTFSF:
        !           506:                        bp->b_flags |= B_READ;
        !           507:                        goto mustio;
        !           508:
        !           509:                case MTBSF:
        !           510:                        goto gotaddr;
        !           511:
        !           512:                case MTOFFL:
        !           513:                        sc->sc_blkno = 0;
        !           514:                        sc->sc_ul.unit = C_SUNIT(sc->sc_punit);
        !           515:                        sc->sc_ul.cmd = C_UNLOAD;
        !           516:                        hpibsend(ctlr, slave, C_CMD, &sc->sc_ul,
        !           517:                            sizeof(sc->sc_ul));
        !           518:                        break;
        !           519:
        !           520:                case MTWEOF:
        !           521:                        sc->sc_blkno++;
        !           522:                        sc->sc_flags |= CTF_WRT;
        !           523:                        sc->sc_wfm.unit = C_SUNIT(sc->sc_punit);
        !           524:                        sc->sc_wfm.cmd = C_WFM;
        !           525:                        hpibsend(ctlr, slave, C_CMD, &sc->sc_wfm,
        !           526:                            sizeof(sc->sc_wfm));
        !           527:                        ctaddeof(sc);
        !           528:                        break;
        !           529:
        !           530:                case MTBSR:
        !           531:                        sc->sc_blkno--;
        !           532:                        goto gotaddr;
        !           533:
        !           534:                case MTFSR:
        !           535:                        sc->sc_blkno++;
        !           536:                        goto gotaddr;
        !           537:
        !           538:                case MTREW:
        !           539:                        sc->sc_blkno = 0;
        !           540: #ifdef DEBUG
        !           541:                        if(ctdebug & CT_BSF)
        !           542:                                printf("%s: clearing eofs\n",
        !           543:                                    sc->sc_dev.dv_xname);
        !           544: #endif
        !           545:                        for (i=0; i<EOFS; i++)
        !           546:                                sc->sc_eofs[i] = 0;
        !           547:                        sc->sc_eofp = 0;
        !           548:
        !           549: gotaddr:
        !           550:                        sc->sc_ioc.saddr = C_SADDR;
        !           551:                        sc->sc_ioc.addr0 = 0;
        !           552:                        sc->sc_ioc.addr = sc->sc_blkno;
        !           553:                        sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
        !           554:                        sc->sc_ioc.nop2 = C_NOP;
        !           555:                        sc->sc_ioc.slen = C_SLEN;
        !           556:                        sc->sc_ioc.len = 0;
        !           557:                        sc->sc_ioc.nop3 = C_NOP;
        !           558:                        sc->sc_ioc.cmd = C_READ;
        !           559:                        hpibsend(ctlr, slave, C_CMD, &sc->sc_ioc,
        !           560:                            sizeof(sc->sc_ioc));
        !           561:                        break;
        !           562:                }
        !           563:        } else {
        !           564: mustio:
        !           565:                if ((bp->b_flags & B_READ) &&
        !           566:                    sc->sc_flags & (CTF_BEOF|CTF_EOT)) {
        !           567: #ifdef DEBUG
        !           568:                        if (ctdebug & CDB_FILES)
        !           569:                                printf("ctstart: before flags %x\n",
        !           570:                                    sc->sc_flags);
        !           571: #endif
        !           572:                        if (sc->sc_flags & CTF_BEOF) {
        !           573:                                sc->sc_flags &= ~CTF_BEOF;
        !           574:                                sc->sc_flags |= CTF_AEOF;
        !           575: #ifdef DEBUG
        !           576:                                if (ctdebug & CDB_FILES)
        !           577:                                        printf("ctstart: after flags %x\n",
        !           578:                                            sc->sc_flags);
        !           579: #endif
        !           580:                        }
        !           581:                        bp->b_resid = bp->b_bcount;
        !           582:                        ctdone(sc, bp);
        !           583:                        return;
        !           584:                }
        !           585:                sc->sc_flags |= CTF_IO;
        !           586:                sc->sc_ioc.unit = C_SUNIT(sc->sc_punit);
        !           587:                sc->sc_ioc.saddr = C_SADDR;
        !           588:                sc->sc_ioc.addr0 = 0;
        !           589:                sc->sc_ioc.addr = sc->sc_blkno;
        !           590:                sc->sc_ioc.nop2 = C_NOP;
        !           591:                sc->sc_ioc.slen = C_SLEN;
        !           592:                sc->sc_ioc.len = sc->sc_resid;
        !           593:                sc->sc_ioc.nop3 = C_NOP;
        !           594:                if (bp->b_flags & B_READ)
        !           595:                        sc->sc_ioc.cmd = C_READ;
        !           596:                else {
        !           597:                        sc->sc_ioc.cmd = C_WRITE;
        !           598:                        sc->sc_flags |= (CTF_WRT | CTF_WRTTN);
        !           599:                }
        !           600:                hpibsend(ctlr, slave, C_CMD, &sc->sc_ioc, sizeof(sc->sc_ioc));
        !           601:        }
        !           602:        hpibawait(ctlr);
        !           603: }
        !           604:
        !           605: void
        !           606: ctgo(arg)
        !           607:        void *arg;
        !           608: {
        !           609:        struct ct_softc *sc = arg;
        !           610:        struct buf *bp;
        !           611:        int rw;
        !           612:
        !           613:        bp = sc->sc_tab.b_actf;
        !           614:        rw = bp->b_flags & B_READ;
        !           615:        hpibgo(sc->sc_dev.dv_parent->dv_unit, sc->sc_slave, C_EXEC,
        !           616:            sc->sc_addr, sc->sc_resid, rw, rw != 0);
        !           617: }
        !           618:
        !           619: /*
        !           620:  * Hideous grue to handle EOF/EOT (mostly for reads)
        !           621:  */
        !           622: void
        !           623: cteof(sc, bp)
        !           624:        struct ct_softc *sc;
        !           625:        struct buf *bp;
        !           626: {
        !           627:        long blks;
        !           628:
        !           629:        /*
        !           630:         * EOT on a write is an error.
        !           631:         */
        !           632:        if ((bp->b_flags & B_READ) == 0) {
        !           633:                bp->b_resid = bp->b_bcount;
        !           634:                bp->b_flags |= B_ERROR;
        !           635:                bp->b_error = ENOSPC;
        !           636:                sc->sc_flags |= CTF_EOT;
        !           637:                return;
        !           638:        }
        !           639:        /*
        !           640:         * Use returned block position to determine how many blocks
        !           641:         * we really read and update b_resid.
        !           642:         */
        !           643:        blks = sc->sc_stat.c_blk - sc->sc_blkno - 1;
        !           644: #ifdef DEBUG
        !           645:        if (ctdebug & CDB_FILES)
        !           646:                printf("cteof: bc %ld oblk %d nblk %ld read %ld, resid %ld\n",
        !           647:                       bp->b_bcount, sc->sc_blkno, sc->sc_stat.c_blk,
        !           648:                       blks, bp->b_bcount - CTKTOB(blks));
        !           649: #endif
        !           650:        if (blks == -1) { /* 9145 on EOF does not change sc_stat.c_blk */
        !           651:                blks = 0;
        !           652:                sc->sc_blkno++;
        !           653:        }
        !           654:        else {
        !           655:                sc->sc_blkno = sc->sc_stat.c_blk;
        !           656:        }
        !           657:        bp->b_resid = bp->b_bcount - CTKTOB(blks);
        !           658:        /*
        !           659:         * If we are at physical EOV or were after an EOF,
        !           660:         * we are now at logical EOT.
        !           661:         */
        !           662:        if ((sc->sc_stat.c_aef & AEF_EOV) ||
        !           663:            (sc->sc_flags & CTF_AEOF)) {
        !           664:                sc->sc_flags |= CTF_EOT;
        !           665:                sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF);
        !           666:        }
        !           667:        /*
        !           668:         * If we were before an EOF or we have just completed a FSF,
        !           669:         * we are now after EOF.
        !           670:         */
        !           671:        else if ((sc->sc_flags & CTF_BEOF) ||
        !           672:                 ((sc->sc_flags & CTF_CMD) && sc->sc_cmd == MTFSF)) {
        !           673:                sc->sc_flags |= CTF_AEOF;
        !           674:                sc->sc_flags &= ~CTF_BEOF;
        !           675:        }
        !           676:        /*
        !           677:         * Otherwise if we read something we are now before EOF
        !           678:         * (and no longer after EOF).
        !           679:         */
        !           680:        else if (blks) {
        !           681:                sc->sc_flags |= CTF_BEOF;
        !           682:                sc->sc_flags &= ~CTF_AEOF;
        !           683:        }
        !           684:        /*
        !           685:         * Finally, if we didn't read anything we just passed an EOF
        !           686:         */
        !           687:        else
        !           688:                sc->sc_flags |= CTF_AEOF;
        !           689: #ifdef DEBUG
        !           690:        if (ctdebug & CDB_FILES)
        !           691:                printf("cteof: leaving flags %x\n", sc->sc_flags);
        !           692: #endif
        !           693: }
        !           694:
        !           695: /* ARGSUSED */
        !           696: void
        !           697: ctintr(arg)
        !           698:        void *arg;
        !           699: {
        !           700:        struct ct_softc *sc = arg;
        !           701:        struct buf *bp;
        !           702:        u_char stat;
        !           703:        int ctlr, slave, unit;
        !           704:
        !           705:        ctlr = sc->sc_dev.dv_parent->dv_unit;
        !           706:        slave = sc->sc_slave;
        !           707:        unit = sc->sc_dev.dv_unit;
        !           708:
        !           709:        bp = sc->sc_tab.b_actf;
        !           710:        if (bp == NULL) {
        !           711:                printf("%s: bp == NULL\n", sc->sc_dev.dv_xname);
        !           712:                return;
        !           713:        }
        !           714:        if (sc->sc_flags & CTF_IO) {
        !           715:                sc->sc_flags &= ~CTF_IO;
        !           716:                if (hpibustart(ctlr))
        !           717:                        ctgo(sc);
        !           718:                return;
        !           719:        }
        !           720:        if ((sc->sc_flags & CTF_STATWAIT) == 0) {
        !           721:                if (hpibpptest(ctlr, slave) == 0) {
        !           722:                        sc->sc_flags |= CTF_STATWAIT;
        !           723:                        hpibawait(ctlr);
        !           724:                        return;
        !           725:                }
        !           726:        } else
        !           727:                sc->sc_flags &= ~CTF_STATWAIT;
        !           728:        hpibrecv(ctlr, slave, C_QSTAT, &stat, 1);
        !           729: #ifdef DEBUG
        !           730:        if (ctdebug & CDB_FILES)
        !           731:                printf("ctintr: before flags %x\n", sc->sc_flags);
        !           732: #endif
        !           733:        if (stat) {
        !           734:                sc->sc_rsc.unit = C_SUNIT(sc->sc_punit);
        !           735:                sc->sc_rsc.cmd = C_STATUS;
        !           736:                hpibsend(ctlr, slave, C_CMD, &sc->sc_rsc, sizeof(sc->sc_rsc));
        !           737:                hpibrecv(ctlr, slave, C_EXEC, &sc->sc_stat,
        !           738:                    sizeof(sc->sc_stat));
        !           739:                hpibrecv(ctlr, slave, C_QSTAT, &stat, 1);
        !           740: #ifdef DEBUG
        !           741:                if (ctdebug & CDB_FILES)
        !           742:                        printf("ctintr: return stat 0x%x, A%x F%x blk %ld\n",
        !           743:                               stat, sc->sc_stat.c_aef,
        !           744:                               sc->sc_stat.c_fef, sc->sc_stat.c_blk);
        !           745: #endif
        !           746:                if (stat == 0) {
        !           747:                        if (sc->sc_stat.c_aef & (AEF_EOF | AEF_EOV)) {
        !           748:                                cteof(sc, bp);
        !           749:                                ctaddeof(sc);
        !           750:                                goto done;
        !           751:                        }
        !           752:                        if (sc->sc_stat.c_fef & FEF_PF) {
        !           753:                                ctreset(sc);
        !           754:                                ctstart(sc);
        !           755:                                return;
        !           756:                        }
        !           757:                        if (sc->sc_stat.c_fef & FEF_REXMT) {
        !           758:                                ctstart(sc);
        !           759:                                return;
        !           760:                        }
        !           761:                        if (sc->sc_stat.c_aef & 0x5800) {
        !           762:                                if (sc->sc_stat.c_aef & 0x4000)
        !           763:                                        printf("%s: uninitialized media\n",
        !           764:                                                sc->sc_dev.dv_xname);
        !           765:                                if (sc->sc_stat.c_aef & 0x1000)
        !           766:                                        printf("%s: not ready\n",
        !           767:                                                sc->sc_dev.dv_xname);
        !           768:                                if (sc->sc_stat.c_aef & 0x0800)
        !           769:                                        printf("%s: write protect\n",
        !           770:                                                sc->sc_dev.dv_xname);
        !           771:                        } else {
        !           772:                                printf("%s err: v%d u%d ru%d bn%ld, ",
        !           773:                                       sc->sc_dev.dv_xname,
        !           774:                                       (sc->sc_stat.c_vu>>4)&0xF,
        !           775:                                       sc->sc_stat.c_vu&0xF,
        !           776:                                       sc->sc_stat.c_pend,
        !           777:                                       sc->sc_stat.c_blk);
        !           778:                                printf("R0x%x F0x%x A0x%x I0x%x\n",
        !           779:                                       sc->sc_stat.c_ref,
        !           780:                                       sc->sc_stat.c_fef,
        !           781:                                       sc->sc_stat.c_aef,
        !           782:                                       sc->sc_stat.c_ief);
        !           783:                        }
        !           784:                } else
        !           785:                        printf("%s: request status failed\n",
        !           786:                            sc->sc_dev.dv_xname);
        !           787:                bp->b_flags |= B_ERROR;
        !           788:                bp->b_error = EIO;
        !           789:                goto done;
        !           790:        } else
        !           791:                bp->b_resid = 0;
        !           792:        if (sc->sc_flags & CTF_CMD) {
        !           793:                switch (sc->sc_cmd) {
        !           794:                case MTFSF:
        !           795:                        sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF);
        !           796:                        sc->sc_blkno += CTBTOK(sc->sc_resid);
        !           797:                        ctstart(sc);
        !           798:                        return;
        !           799:                case MTBSF:
        !           800:                        sc->sc_flags &= ~(CTF_AEOF|CTF_BEOF|CTF_EOT);
        !           801:                        break;
        !           802:                case MTBSR:
        !           803:                        sc->sc_flags &= ~CTF_BEOF;
        !           804:                        if (sc->sc_flags & CTF_EOT) {
        !           805:                                sc->sc_flags |= CTF_AEOF;
        !           806:                                sc->sc_flags &= ~CTF_EOT;
        !           807:                        } else if (sc->sc_flags & CTF_AEOF) {
        !           808:                                sc->sc_flags |= CTF_BEOF;
        !           809:                                sc->sc_flags &= ~CTF_AEOF;
        !           810:                        }
        !           811:                        break;
        !           812:                case MTWEOF:
        !           813:                        sc->sc_flags &= ~CTF_BEOF;
        !           814:                        if (sc->sc_flags & (CTF_AEOF|CTF_EOT)) {
        !           815:                                sc->sc_flags |= CTF_EOT;
        !           816:                                sc->sc_flags &= ~CTF_AEOF;
        !           817:                        } else
        !           818:                                sc->sc_flags |= CTF_AEOF;
        !           819:                        break;
        !           820:                case MTREW:
        !           821:                case MTOFFL:
        !           822:                        sc->sc_flags &= ~(CTF_BEOF|CTF_AEOF|CTF_EOT);
        !           823:                        break;
        !           824:                }
        !           825:        } else {
        !           826:                sc->sc_flags &= ~CTF_AEOF;
        !           827:                sc->sc_blkno += CTBTOK(sc->sc_resid);
        !           828:        }
        !           829: done:
        !           830: #ifdef DEBUG
        !           831:        if (ctdebug & CDB_FILES)
        !           832:                printf("ctintr: after flags %x\n", sc->sc_flags);
        !           833: #endif
        !           834:        ctdone(sc, bp);
        !           835: }
        !           836:
        !           837: void
        !           838: ctdone(sc, bp)
        !           839:        struct ct_softc *sc;
        !           840:        struct buf *bp;
        !           841: {
        !           842:        struct buf *dp;
        !           843:        int s;
        !           844:
        !           845:        if ((dp = bp->b_actf) != NULL)
        !           846:                dp->b_actb = bp->b_actb;
        !           847:        else
        !           848:                sc->sc_tab.b_actb = bp->b_actb;
        !           849:        *bp->b_actb = dp;
        !           850:        s = splbio();
        !           851:        biodone(bp);
        !           852:        splx(s);
        !           853:        hpibfree(sc->sc_dev.dv_parent, &sc->sc_hq);
        !           854:        if (sc->sc_tab.b_actf == NULL) {
        !           855:                sc->sc_tab.b_active = 0;
        !           856:                return;
        !           857:        }
        !           858:        ctustart(sc);
        !           859: }
        !           860:
        !           861: int
        !           862: ctread(dev, uio, flags)
        !           863:        dev_t dev;
        !           864:        struct uio *uio;
        !           865:        int flags;
        !           866: {
        !           867:        return (physio(ctstrategy, NULL, dev, B_READ, minphys, uio));
        !           868: }
        !           869:
        !           870: int
        !           871: ctwrite(dev, uio, flags)
        !           872:        dev_t dev;
        !           873:        struct uio *uio;
        !           874:        int flags;
        !           875: {
        !           876:        /* XXX: check for hardware write-protect? */
        !           877:        return (physio(ctstrategy, NULL, dev, B_WRITE, minphys, uio));
        !           878: }
        !           879:
        !           880: /*ARGSUSED*/
        !           881: int
        !           882: ctioctl(dev, cmd, data, flag, p)
        !           883:        dev_t dev;
        !           884:        u_long cmd;
        !           885:        int flag;
        !           886:        caddr_t data;
        !           887:        struct proc *p;
        !           888: {
        !           889:        struct mtop *op;
        !           890:        int cnt;
        !           891:
        !           892:        switch (cmd) {
        !           893:
        !           894:        case MTIOCTOP:
        !           895:                op = (struct mtop *)data;
        !           896:                switch(op->mt_op) {
        !           897:
        !           898:                case MTWEOF:
        !           899:                case MTFSF:
        !           900:                case MTBSR:
        !           901:                case MTBSF:
        !           902:                case MTFSR:
        !           903:                        cnt = op->mt_count;
        !           904:                        break;
        !           905:
        !           906:                case MTREW:
        !           907:                case MTOFFL:
        !           908:                        cnt = 1;
        !           909:                        break;
        !           910:
        !           911:                default:
        !           912:                        return(EINVAL);
        !           913:                }
        !           914:                ctcommand(dev, op->mt_op, cnt);
        !           915:                break;
        !           916:
        !           917:        case MTIOCGET:
        !           918:                break;
        !           919:
        !           920:        default:
        !           921:                return(EINVAL);
        !           922:        }
        !           923:        return(0);
        !           924: }
        !           925:
        !           926: /* ARGSUSED */
        !           927: int
        !           928: ctdump(dev, blkno, va, size)
        !           929:        dev_t dev;
        !           930:        daddr64_t blkno;
        !           931:        caddr_t va;
        !           932:        size_t size;
        !           933: {
        !           934:
        !           935:        return (ENODEV);
        !           936: }
        !           937:
        !           938: void
        !           939: ctaddeof(sc)
        !           940:        struct ct_softc *sc;
        !           941: {
        !           942:
        !           943:        if (sc->sc_eofp == EOFS - 1)
        !           944:                sc->sc_eofs[EOFS - 1]++;
        !           945:        else {
        !           946:                sc->sc_eofp++;
        !           947:                if (sc->sc_eofp == EOFS - 1)
        !           948:                        sc->sc_eofs[EOFS - 1] = EOFS;
        !           949:                else
        !           950:                        /* save blkno */
        !           951:                        sc->sc_eofs[sc->sc_eofp] = sc->sc_blkno - 1;
        !           952:        }
        !           953: #ifdef DEBUG
        !           954:        if (ctdebug & CT_BSF)
        !           955:                printf("%s: add eof pos %d blk %d\n",
        !           956:                       sc->sc_dev.dv_xname, sc->sc_eofp,
        !           957:                       sc->sc_eofs[sc->sc_eofp]);
        !           958: #endif
        !           959: }

CVSweb