[BACK]Return to mscp_tape.c CVS log [TXT][DIR] Up to [local] / sys / arch / vax / mscp

Annotation of sys/arch/vax/mscp/mscp_tape.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: mscp_tape.c,v 1.10 2007/06/06 17:15:13 deraadt Exp $ */
                      2: /*     $NetBSD: mscp_tape.c,v 1.16 2001/11/13 07:38:28 lukem Exp $ */
                      3: /*
                      4:  * Copyright (c) 1996 Ludd, University of Lule}, Sweden.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed at Ludd, University of
                     18:  *     Lule}, Sweden and its contributors.
                     19:  * 4. The name of the author may not be used to endorse or promote products
                     20:  *    derived from this software without specific prior written permission
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     32:  */
                     33:
                     34:
                     35: /*
                     36:  * MSCP tape device driver
                     37:  */
                     38:
                     39: /*
                     40:  * TODO
                     41:  *     Write status handling code.
                     42:  */
                     43:
                     44: #include <sys/cdefs.h>
                     45:
                     46: #include <sys/param.h>
                     47: #include <sys/device.h>
                     48: #include <sys/kernel.h>
                     49: #include <sys/buf.h>
                     50: #include <sys/ioccom.h>
                     51: #include <sys/mtio.h>
                     52: #include <sys/fcntl.h>
                     53: #include <sys/malloc.h>
                     54: #include <sys/systm.h>
                     55: #include <sys/proc.h>
                     56:
                     57: #include <machine/bus.h>
                     58: #include <machine/cpu.h>
                     59:
                     60: #include <arch/vax/mscp/mscp.h>
                     61: #include <arch/vax/mscp/mscpreg.h>
                     62: #include <arch/vax/mscp/mscpvar.h>
                     63:
                     64: /*
                     65:  * Drive status, per drive
                     66:  */
                     67: struct mt_softc {
                     68:        struct  device mt_dev;  /* Autoconf struct */
                     69:        int     mt_state;       /* open/closed state */
                     70:        int     mt_hwunit;      /* Hardware unit number */
                     71:        int     mt_inuse;       /* Locks the tape drive for others */
                     72:        int     mt_waswrite;    /* Last operation was a write op */
                     73:        int     mt_serex;       /* Got serious exception */
                     74:        int     mt_ioctlerr;    /* Error after last ioctl */
                     75: };
                     76:
                     77: #define MT_OFFLINE     0
                     78: #define MT_ONLINE      1
                     79:
                     80: int    mtmatch(struct device *, struct cfdata *, void *);
                     81: void   mtattach(struct device *, struct device *, void *);
                     82: void   mtdgram(struct device *, struct mscp *, struct mscp_softc *);
                     83: void   mtiodone(struct device *, struct buf *);
                     84: int    mtonline(struct device *, struct mscp *);
                     85: int    mtgotstatus(struct device *, struct mscp *);
                     86: int    mtioerror(struct device *, struct mscp *, struct buf *);
                     87: void   mtfillin(struct buf *, struct mscp *);
                     88: int    mtopen(dev_t, int, int, struct proc *);
                     89: int    mtclose(dev_t, int, int, struct proc *);
                     90: void   mtstrategy(struct buf *);
                     91: int    mtread(dev_t, struct uio *);
                     92: int    mtwrite(dev_t, struct uio *);
                     93: int    mtioctl(dev_t, int, caddr_t, int, struct proc *);
                     94: int    mtdump(dev_t, daddr64_t, caddr_t, size_t);
                     95: int    mtcmd(struct mt_softc *, int, int, int);
                     96: void   mtcmddone(struct device *, struct mscp *);
                     97: int    mt_putonline(struct mt_softc *);
                     98:
                     99: struct mscp_device mt_device = {
                    100:        mtdgram,
                    101:        mtiodone,
                    102:        mtonline,
                    103:        mtgotstatus,
                    104:        0,
                    105:        mtioerror,
                    106:        0,
                    107:        mtfillin,
                    108:        mtcmddone,
                    109: };
                    110:
                    111: /* This is not good, should allow more than 4 tapes/device type */
                    112: #define mtunit(dev)    (minor(dev) & T_UNIT)
                    113: #define mtnorewind(dev) (dev & T_NOREWIND)
                    114: #define mthdensity(dev) (dev & T_1600BPI)
                    115:
                    116: struct cfattach mt_ca = {
                    117:        sizeof(struct mt_softc), (cfmatch_t)mtmatch, mtattach
                    118: };
                    119:
                    120: struct cfdriver mt_cd = {
                    121:        NULL, "mt", DV_TAPE
                    122: };
                    123:
                    124: /*
                    125:  * More driver definitions, for generic MSCP code.
                    126:  */
                    127:
                    128: int
                    129: mtmatch(parent, cf, aux)
                    130:        struct  device *parent;
                    131:        struct  cfdata *cf;
                    132:        void    *aux;
                    133: {
                    134:        struct  drive_attach_args *da = aux;
                    135:        struct  mscp *mp = da->da_mp;
                    136:
                    137:        if ((da->da_typ & MSCPBUS_TAPE) == 0)
                    138:                return 0;
                    139:        if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != mp->mscp_unit)
                    140:                return 0;
                    141:        return 1;
                    142: }
                    143:
                    144: /*
                    145:  * The attach routine only checks and prints drive type.
                    146:  */
                    147: void
                    148: mtattach(parent, self, aux)
                    149:        struct  device *parent, *self;
                    150:        void    *aux;
                    151: {
                    152:        struct  mt_softc *mt = (void *)self;
                    153:        struct  drive_attach_args *da = aux;
                    154:        struct  mscp *mp = da->da_mp;
                    155:        struct  mscp_softc *mi = (void *)parent;
                    156:
                    157:        mt->mt_hwunit = mp->mscp_unit;
                    158:        mi->mi_dp[mp->mscp_unit] = self;
                    159:
                    160:        disk_printtype(mp->mscp_unit, mp->mscp_guse.guse_mediaid);
                    161: }
                    162:
                    163: /*
                    164:  * (Try to) put the drive online. This is done the first time the
                    165:  * drive is opened, or if it has fallen offline.
                    166:  */
                    167: int
                    168: mt_putonline(mt)
                    169:        struct mt_softc *mt;
                    170: {
                    171:        struct  mscp *mp;
                    172:        struct  mscp_softc *mi = (struct mscp_softc *)mt->mt_dev.dv_parent;
                    173:        volatile int i;
                    174:
                    175:        (volatile int)mt->mt_state = MT_OFFLINE;
                    176:        mp = mscp_getcp(mi, MSCP_WAIT);
                    177:        mp->mscp_opcode = M_OP_ONLINE;
                    178:        mp->mscp_unit = mt->mt_hwunit;
                    179:        mp->mscp_cmdref = (long)&mt->mt_state;
                    180:        *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
                    181:
                    182:        /* Poll away */
                    183:        i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
                    184:        if (tsleep(&mt->mt_state, PRIBIO, "mtonline", 240 * hz))
                    185:                return MSCP_FAILED;
                    186:
                    187:        if ((volatile int)mt->mt_state != MT_ONLINE)
                    188:                return MSCP_FAILED;
                    189:
                    190:        return MSCP_DONE;
                    191: }
                    192: /*
                    193:  * Open a drive.
                    194:  */
                    195: /*ARGSUSED*/
                    196: int
                    197: mtopen(dev, flag, fmt, p)
                    198:        dev_t dev;
                    199:        int flag, fmt;
                    200:        struct  proc *p;
                    201: {
                    202:        struct mt_softc *mt;
                    203:        int unit;
                    204:
                    205:        /*
                    206:         * Make sure this is a reasonable open request.
                    207:         */
                    208:        unit = mtunit(dev);
                    209:        if (unit >= mt_cd.cd_ndevs)
                    210:                return ENXIO;
                    211:        mt = mt_cd.cd_devs[unit];
                    212:        if (mt == 0)
                    213:                return ENXIO;
                    214:
                    215:        if (mt->mt_inuse)
                    216:                        return EBUSY;
                    217:        mt->mt_inuse = 1;
                    218:
                    219:        if (mt_putonline(mt) == MSCP_FAILED) {
                    220:                mt->mt_inuse = 0;
                    221:                return EIO;
                    222:        }
                    223:
                    224:        return 0;
                    225: }
                    226:
                    227: /* ARGSUSED */
                    228: int
                    229: mtclose(dev, flags, fmt, p)
                    230:        dev_t dev;
                    231:        int flags, fmt;
                    232:        struct  proc *p;
                    233: {
                    234:        int unit = mtunit(dev);
                    235:        struct mt_softc *mt = mt_cd.cd_devs[unit];
                    236:
                    237:        /*
                    238:         * If we just have finished a writing, write EOT marks.
                    239:         */
                    240:        if ((flags & FWRITE) && mt->mt_waswrite) {
                    241:                mtcmd(mt, MTWEOF, 0, 0);
                    242:                mtcmd(mt, MTWEOF, 0, 0);
                    243:                mtcmd(mt, MTBSR, 1, 0);
                    244:        }
                    245:        if (mtnorewind(dev) == 0)
                    246:                mtcmd(mt, MTREW, 0, 1);
                    247:        if (mt->mt_serex)
                    248:                mtcmd(mt, -1, 0, 0);
                    249:
                    250:        mt->mt_inuse = 0; /* Release the tape */
                    251:        return 0;
                    252: }
                    253:
                    254: void
                    255: mtstrategy(bp)
                    256:        struct buf *bp;
                    257: {
                    258:        int unit;
                    259:        struct mt_softc *mt;
                    260:        int s;
                    261:
                    262:        /*
                    263:         * Make sure this is a reasonable drive to use.
                    264:         */
                    265:        unit = mtunit(bp->b_dev);
                    266:        if (unit >= mt_cd.cd_ndevs || (mt = mt_cd.cd_devs[unit]) == NULL) {
                    267:                bp->b_error = ENXIO;
                    268:                goto bad;
                    269:        }
                    270:
                    271:        mt->mt_waswrite = bp->b_flags & B_READ ? 0 : 1;
                    272:        mscp_strategy(bp, mt->mt_dev.dv_parent);
                    273:        return;
                    274:
                    275: bad:
                    276:        bp->b_flags |= B_ERROR;
                    277:        s = splbio();
                    278:        biodone(bp);
                    279:        splx(s);
                    280: }
                    281:
                    282: int
                    283: mtread(dev, uio)
                    284:        dev_t dev;
                    285:        struct uio *uio;
                    286: {
                    287:
                    288:        return (physio(mtstrategy, NULL, dev, B_READ, minphys, uio));
                    289: }
                    290:
                    291: int
                    292: mtwrite(dev, uio)
                    293:        dev_t dev;
                    294:        struct uio *uio;
                    295: {
                    296:
                    297:        return (physio(mtstrategy, NULL, dev, B_WRITE, minphys, uio));
                    298: }
                    299:
                    300: void
                    301: mtiodone(usc, bp)
                    302:        struct device *usc;
                    303:        struct buf *bp;
                    304: {
                    305:        int s;
                    306:
                    307:        s = splbio();
                    308:        biodone(bp);
                    309:        splx(s);
                    310: }
                    311:
                    312: /*
                    313:  * Fill in drive addresses in a mscp packet waiting for transfer.
                    314:  */
                    315: void
                    316: mtfillin(bp, mp)
                    317:        struct buf *bp;
                    318:        struct mscp *mp;
                    319: {
                    320:        int unit = mtunit(bp->b_dev);
                    321:        struct mt_softc *mt = mt_cd.cd_devs[unit];
                    322:
                    323:        mp->mscp_unit = mt->mt_hwunit;
                    324:        if (mt->mt_serex == 2) {
                    325:                mp->mscp_modifier = M_MD_CLSEX;
                    326:                mt->mt_serex = 0;
                    327:        } else
                    328:                mp->mscp_modifier = 0;
                    329:
                    330:        mp->mscp_seq.seq_bytecount = bp->b_bcount;
                    331: }
                    332:
                    333: /*
                    334:  * Handle an error datagram.
                    335:  */
                    336: void
                    337: mtdgram(usc, mp, mi)
                    338:        struct device *usc;
                    339:        struct mscp *mp;
                    340:        struct mscp_softc *mi;
                    341: {
                    342:        if (mscp_decodeerror(usc == NULL?"unconf mt" : usc->dv_xname, mp, mi))
                    343:                return;
                    344: }
                    345:
                    346: /*
                    347:  * A drive came on line, make sure it really _is_ on line before
                    348:  * trying to use it.
                    349:  */
                    350: int
                    351: mtonline(usc, mp)
                    352:        struct device *usc;
                    353:        struct mscp *mp;
                    354: {
                    355:        struct mt_softc *mt = (void *)usc;
                    356:
                    357:        wakeup((caddr_t)&mt->mt_state);
                    358:        if ((mp->mscp_status & M_ST_MASK) == M_ST_SUCCESS)
                    359:                mt->mt_state = MT_ONLINE;
                    360:
                    361:        return (MSCP_DONE);
                    362: }
                    363:
                    364: /*
                    365:  * We got some (configured) unit's status.  Return DONE.
                    366:  */
                    367: int
                    368: mtgotstatus(usc, mp)
                    369:        struct device *usc;
                    370:        struct mscp *mp;
                    371: {
                    372:        return (MSCP_DONE);
                    373: }
                    374:
                    375: static char *mt_ioerrs[] = {
                    376:        "invalid command",      /* 1 M_ST_INVALCMD */
                    377:        "command aborted",      /* 2 M_ST_ABORTED */
                    378:        "unit offline",         /* 3 M_ST_OFFLINE */
                    379:        "unknown",              /* 4 M_ST_AVAILABLE */
                    380:        "unknown",              /* 5 M_ST_MFMTERR */
                    381:        "unit write protected", /* 6 M_ST_WRPROT */
                    382:        "compare error",        /* 7 M_ST_COMPERR */
                    383:        "data error",           /* 8 M_ST_DATAERR */
                    384:        "host buffer access error",     /* 9 M_ST_HOSTBUFERR */
                    385:        "controller error",     /* 10 M_ST_CTLRERR */
                    386:        "drive error",          /* 11 M_ST_DRIVEERR */
                    387:        "formatter error",      /* 12 M_ST_FORMATTERR */
                    388:        "BOT encountered",      /* 13 M_ST_BOT */
                    389:        "tape mark encountered",/* 14 M_ST_TAPEMARK */
                    390:        "unknown",              /* 15 */
                    391:        "record data truncated",/* 16 M_ST_RDTRUNC */
                    392: };
                    393:
                    394: /*
                    395:  * An I/O error, may be because of a tapemark encountered.
                    396:  * Check that before failing.
                    397:  */
                    398: /*ARGSUSED*/
                    399: int
                    400: mtioerror(usc, mp, bp)
                    401:        struct device *usc;
                    402:        struct mscp *mp;
                    403:        struct buf *bp;
                    404: {
                    405:        struct mt_softc *mt = (void *)usc;
                    406:        int st = mp->mscp_status & M_ST_MASK;
                    407:
                    408:        if (mp->mscp_flags & M_EF_SEREX)
                    409:                mt->mt_serex = 1;
                    410:        if (st == M_ST_TAPEMARK)
                    411:                mt->mt_serex = 2;
                    412:        else {
                    413:                if (st && st < 17)
                    414:                        printf("%s: error %d (%s)\n", mt->mt_dev.dv_xname, st,
                    415:                            mt_ioerrs[st-1]);
                    416:                else
                    417:                        printf("%s: error %d\n", mt->mt_dev.dv_xname, st);
                    418:                bp->b_flags |= B_ERROR;
                    419:                bp->b_error = EROFS;
                    420:        }
                    421:
                    422:        return (MSCP_DONE);
                    423: }
                    424:
                    425: /*
                    426:  * I/O controls.
                    427:  */
                    428: int
                    429: mtioctl(dev, cmd, data, flag, p)
                    430:        dev_t dev;
                    431:        int cmd;
                    432:        caddr_t data;
                    433:        int flag;
                    434:        struct proc *p;
                    435: {
                    436:        int unit = mtunit(dev);
                    437:        struct mt_softc *mt = mt_cd.cd_devs[unit];
                    438:        struct  mtop *mtop;
                    439:        struct  mtget *mtget;
                    440:        int error = 0, count;
                    441:
                    442:        count = mtop->mt_count;
                    443:
                    444:        switch (cmd) {
                    445:
                    446:        case MTIOCTOP:
                    447:                mtop = (void *)data;
                    448:                if (mtop->mt_op == MTWEOF) {
                    449:                        while (mtop->mt_count-- > 0)
                    450:                                if ((error = mtcmd(mt, mtop->mt_op, 0, 0)))
                    451:                                        break;
                    452:                } else
                    453:                        error = mtcmd(mt, mtop->mt_op, mtop->mt_count, 0);
                    454:
                    455:        case MTIOCGET:
                    456:                mtget = (void *)data;
                    457:                mtget->mt_type = MT_ISTMSCP;
                    458:                /* XXX we need to fill in more fields here */
                    459:                break;
                    460:
                    461:        default:
                    462:                error = ENXIO;
                    463:                break;
                    464:        }
                    465:        return (error);
                    466: }
                    467:
                    468: /*
                    469:  * No crash dump support...
                    470:  */
                    471: int
                    472: mtdump(dev, blkno, va, size)
                    473:        dev_t   dev;
                    474:        daddr64_t blkno;
                    475:        caddr_t va;
                    476:        size_t  size;
                    477: {
                    478:        return -1;
                    479: }
                    480:
                    481: /*
                    482:  * Send a command to the tape drive. Wait until the command is
                    483:  * finished before returning.
                    484:  * This routine must only be called when there are no data transfer
                    485:  * active on this device. Can we be sure of this? Or does the ctlr
                    486:  * queue up all command packets and take them in sequential order?
                    487:  * It sure would be nice if my manual stated this... /ragge
                    488:  */
                    489: int
                    490: mtcmd(mt, cmd, count, complete)
                    491:        struct mt_softc *mt;
                    492:        int cmd, count, complete;
                    493: {
                    494:        struct mscp *mp;
                    495:        struct mscp_softc *mi = (void *)mt->mt_dev.dv_parent;
                    496:        volatile int i;
                    497:
                    498:        mp = mscp_getcp(mi, MSCP_WAIT);
                    499:
                    500:        mt->mt_ioctlerr = 0;
                    501:        mp->mscp_unit = mt->mt_hwunit;
                    502:        mp->mscp_cmdref = -1;
                    503:        *mp->mscp_addr |= MSCP_OWN | MSCP_INT;
                    504:
                    505:        switch (cmd) {
                    506:        case MTWEOF:
                    507:                mp->mscp_opcode = M_OP_WRITM;
                    508:                break;
                    509:
                    510:        case MTBSF:
                    511:                mp->mscp_modifier = M_MD_REVERSE;
                    512:        case MTFSF:
                    513:                mp->mscp_opcode = M_OP_POS;
                    514:                mp->mscp_seq.seq_buffer = count;
                    515:                break;
                    516:
                    517:        case MTBSR:
                    518:                mp->mscp_modifier = M_MD_REVERSE;
                    519:        case MTFSR:
                    520:                mp->mscp_opcode = M_OP_POS;
                    521:                mp->mscp_modifier |= M_MD_OBJCOUNT;
                    522:                mp->mscp_seq.seq_bytecount = count;
                    523:                break;
                    524:
                    525:        case MTREW:
                    526:                mp->mscp_opcode = M_OP_POS;
                    527:                mp->mscp_modifier = M_MD_REWIND | M_MD_CLSEX;
                    528:                if (complete)
                    529:                        mp->mscp_modifier |= M_MD_IMMEDIATE;
                    530:                mt->mt_serex = 0;
                    531:                break;
                    532:
                    533:        case MTOFFL:
                    534:                mp->mscp_opcode = M_OP_AVAILABLE;
                    535:                mp->mscp_modifier = M_MD_UNLOAD | M_MD_CLSEX;
                    536:                mt->mt_serex = 0;
                    537:                break;
                    538:
                    539:        case MTNOP:
                    540:                mp->mscp_opcode = M_OP_GETUNITST;
                    541:                break;
                    542:
                    543:        case -1: /* Clear serious exception only */
                    544:                mp->mscp_opcode = M_OP_POS;
                    545:                mp->mscp_modifier = M_MD_CLSEX;
                    546:                mt->mt_serex = 0;
                    547:                break;
                    548:
                    549:        default:
                    550:                printf("Bad ioctl %x\n", cmd);
                    551:                mp->mscp_opcode = M_OP_POS;
                    552:                break;
                    553:        }
                    554:
                    555:        i = bus_space_read_2(mi->mi_iot, mi->mi_iph, 0);
                    556:        tsleep(&mt->mt_inuse, PRIBIO, "mtioctl", 0);
                    557:        return mt->mt_ioctlerr;
                    558: }
                    559:
                    560: /*
                    561:  * Called from bus routines whenever a non-data transfer is finished.
                    562:  */
                    563: void
                    564: mtcmddone(usc, mp)
                    565:        struct device *usc;
                    566:        struct mscp *mp;
                    567: {
                    568:        struct mt_softc *mt = (void *)usc;
                    569:
                    570:        if (mp->mscp_status) {
                    571:                mt->mt_ioctlerr = EIO;
                    572:                printf("%s: bad status %x\n", mt->mt_dev.dv_xname,
                    573:                    mp->mscp_status);
                    574:        }
                    575:        wakeup(&mt->mt_inuse);
                    576: }

CVSweb