[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     ! 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