[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

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