Annotation of Net2/scsi/st.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Written by Julian Elischer ([email protected])
        !             3:  * for TRW Financial Systems for use under the MACH(2.5) operating system.
        !             4:  *
        !             5:  * TRW Financial Systems, in accordance with their agreement with Carnegie
        !             6:  * Mellon University, makes this software available to CMU to distribute
        !             7:  * or use in any manner that they see fit as long as this message is kept with
        !             8:  * the software. For this reason TFS also grants any other persons or
        !             9:  * organisations permission to use or modify this software.
        !            10:  *
        !            11:  * TFS supplies this software to be publicly redistributed
        !            12:  * on the understanding that TFS is not responsible for the correct
        !            13:  * functioning of this software in any circumstances.
        !            14:  *
        !            15:  *
        !            16:  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
        !            17:  * --------------------         -----   ----------------------
        !            18:  * CURRENT PATCH LEVEL:         1       00098
        !            19:  * --------------------         -----   ----------------------
        !            20:  *
        !            21:  * 16 Feb 93   Julian Elischer         ADDED for SCSI system
        !            22:  */
        !            23: 
        !            24: /*
        !            25:  * Ported to run under 386BSD by Julian Elischer ([email protected]) Sept 1992
        !            26:  */
        !            27: 
        !            28: 
        !            29: /*
        !            30:  * To do:
        !            31:  * work out some better way of guessing what a good timeout is going
        !            32:  * to be depending on whether we expect to retension or not.
        !            33:  *
        !            34:  */
        !            35: 
        !            36: #include       <sys/types.h>
        !            37: #include       <st.h>
        !            38: 
        !            39: #include <sys/param.h>
        !            40: #include <sys/systm.h>
        !            41: 
        !            42: #include <sys/errno.h>
        !            43: #include <sys/ioctl.h>
        !            44: #include <sys/buf.h>
        !            45: #include <sys/proc.h>
        !            46: #include <sys/user.h>
        !            47: #include <sys/mtio.h>
        !            48: 
        !            49: #if defined(OSF)
        !            50: #define SECSIZE        512
        !            51: #endif /* defined(OSF) */
        !            52: 
        !            53: #include <scsi/scsi_all.h>
        !            54: #include <scsi/scsi_tape.h>
        !            55: #include <scsi/scsiconf.h>
        !            56: 
        !            57: 
        !            58: long int ststrats,stqueues;
        !            59: 
        !            60: 
        !            61: #define PAGESIZ        4096
        !            62: #define STQSIZE                4
        !            63: #define        ST_RETRIES      4
        !            64: 
        !            65: 
        !            66: #define MODE(z)                (  (minor(z)       & 0x03) )
        !            67: #define DSTY(z)         ( ((minor(z) >> 2) & 0x03) )
        !            68: #define UNIT(z)                (  (minor(z) >> 4) )
        !            69: 
        !            70: #define DSTY_QIC120  3
        !            71: #define DSTY_QIC150  2
        !            72: #define DSTY_QIC525  1
        !            73: 
        !            74: #define QIC120     0x0f
        !            75: #define QIC150     0x10
        !            76: #define QIC525     0x11
        !            77: 
        !            78: 
        !            79: 
        !            80: 
        !            81: #ifndef        __386BSD__
        !            82: struct buf stbuf[NST][STQSIZE];        /* buffer for raw io (one per device) */
        !            83: struct buf *stbuf_free[NST];   /* queue of free buffers for raw io */
        !            84: #endif __386BSD__
        !            85: struct buf st_buf_queue[NST];
        !            86: int    ststrategy();
        !            87: void   stminphys();
        !            88: struct scsi_xfer st_scsi_xfer[NST];
        !            89: int    st_xfer_block_wait[NST];
        !            90: 
        !            91: #if defined(OSF)
        !            92: caddr_t                st_window[NST];
        !            93: #endif /* defined(OSF) */
        !            94: #ifndef        MACH
        !            95: #define ESUCCESS 0
        !            96: #endif MACH
        !            97: 
        !            98: int    st_info_valid[NST];     /* the info about the device is valid */
        !            99: int    st_initialized[NST] ;
        !           100: int    st_debug = 0;
        !           101: 
        !           102: int stattach();
        !           103: int st_done();
        !           104: struct st_data
        !           105: {
        !           106:        int     flags;
        !           107:        struct  scsi_switch *sc_sw;     /* address of scsi low level switch */
        !           108:        int     ctlr;                   /* so they know which one we want */
        !           109:        int     targ;                   /* our scsi target ID */
        !           110:        int     lu;                     /* out scsi lu */
        !           111:        int     blkmin;                 /* min blk size */
        !           112:        int     blkmax;                 /* max blk size */
        !           113:        int     numblks;                /* nominal blocks capacity */
        !           114:        int     blksiz;                 /* nominal block size */
        !           115: }st_data[NST];
        !           116: #define ST_OPEN                0x01
        !           117: #define        ST_NOREWIND     0x02
        !           118: #define        ST_WRITTEN      0x04
        !           119: #define        ST_FIXEDBLOCKS  0x10
        !           120: #define        ST_AT_FILEMARK  0x20
        !           121: #define        ST_AT_EOM       0x40
        !           122: 
        !           123: #define        ST_PER_ACTION   (ST_AT_FILEMARK | ST_AT_EOM)
        !           124: #define        ST_PER_OPEN     (ST_OPEN | ST_NOREWIND | ST_WRITTEN | ST_PER_ACTION)
        !           125: #define        ST_PER_MEDIA    ST_FIXEDBLOCKS
        !           126: 
        !           127: static int     next_st_unit = 0;
        !           128: /***********************************************************************\
        !           129: * The routine called by the low level scsi routine when it discovers   *
        !           130: * A device suitable for this driver                                    *
        !           131: \***********************************************************************/
        !           132: 
        !           133: int    stattach(ctlr,targ,lu,scsi_switch)
        !           134: struct scsi_switch *scsi_switch;
        !           135: {
        !           136:        int     unit,i;
        !           137:        unsigned char *tbl;
        !           138:        struct st_data *st;
        !           139: 
        !           140:        if(scsi_debug & PRINTROUTINES) printf("stattach: ");
        !           141:        /*******************************************************\
        !           142:        * Check we have the resources for another drive         *
        !           143:        \*******************************************************/
        !           144:        unit = next_st_unit++;
        !           145:        if( unit >= NST)
        !           146:        {
        !           147:                printf("Too many scsi tapes..(%d > %d) reconfigure kernel",(unit + 1),NST);
        !           148:                return(0);
        !           149:        }
        !           150:        st = st_data + unit;
        !           151:        /*******************************************************\
        !           152:        * Store information needed to contact our base driver   *
        !           153:        \*******************************************************/
        !           154:        st->sc_sw       =       scsi_switch;
        !           155:        st->ctlr        =       ctlr;
        !           156:        st->targ        =       targ;
        !           157:        st->lu  =       lu;
        !           158: 
        !           159:        /*******************************************************\
        !           160:        * Use the subdriver to request information regarding    *
        !           161:        * the drive. We cannot use interrupts yet, so the       *
        !           162:        * request must specify this.                            *
        !           163:        \*******************************************************/
        !           164:        if((st_mode_sense(unit,  SCSI_NOSLEEP |  SCSI_NOMASK | SCSI_SILENT)))
        !           165:        {
        !           166:                printf("        st%d: scsi tape drive, %d blocks of %d bytes\n",
        !           167:                        unit, st->numblks, st->blksiz);
        !           168:        }
        !           169:        else
        !           170:        {
        !           171:                printf("        st%d: scsi tape drive :- offline\n", unit);
        !           172:        }
        !           173:        /*******************************************************\
        !           174:        * Set up the bufs for this device                       *
        !           175:        \*******************************************************/
        !           176: #ifndef        __386BSD__
        !           177:        stbuf_free[unit] = (struct buf *)0;
        !           178:        for (i = 1; i < STQSIZE; i++)
        !           179:        {
        !           180:                stbuf[unit][i].b_forw = stbuf_free[unit];
        !           181:                stbuf_free[unit]=&stbuf[unit][i];
        !           182:        }
        !           183: #endif __386BSD__
        !           184:        st_buf_queue[unit].b_active     =       0;
        !           185:        st_buf_queue[unit].b_actf       =       st_buf_queue[unit].b_actl = 0;
        !           186:        st_initialized[unit] = 1;
        !           187: 
        !           188: #if defined(OSF)
        !           189:        st_window[unit] = (caddr_t)alloc_kva(SECSIZE*256+PAGESIZ);
        !           190: #endif /* defined(OSF) */
        !           191: 
        !           192:        return;
        !           193: 
        !           194: }
        !           195: 
        !           196: 
        !           197: 
        !           198: /*******************************************************\
        !           199: *      open the device.                                *
        !           200: \*******************************************************/
        !           201: stopen(dev)
        !           202: {
        !           203:        int errcode = 0;
        !           204:        int unit,mode,dsty;
        !           205:         int dsty_code;
        !           206:        struct st_data *st;
        !           207:        unit = UNIT(dev);
        !           208:        mode = MODE(dev);
        !           209:        dsty = DSTY(dev);
        !           210:        st = st_data + unit;
        !           211: 
        !           212:        /*******************************************************\
        !           213:        * Check the unit is legal                               *
        !           214:        \*******************************************************/
        !           215:        if ( unit >= NST )
        !           216:        {
        !           217:                errcode = ENXIO;
        !           218:                return(errcode);
        !           219:        }
        !           220:        /*******************************************************\
        !           221:        * Only allow one at a time                              *
        !           222:        \*******************************************************/
        !           223:        if(st->flags & ST_OPEN)
        !           224:        {
        !           225:                errcode = EBUSY;
        !           226:                goto bad;
        !           227:        }
        !           228:        /*******************************************************\
        !           229:        * Set up the mode flags according to the minor number   *
        !           230:        * ensure all open flags are in a known state            *
        !           231:        \*******************************************************/
        !           232:        st->flags &= ~ST_PER_OPEN;
        !           233:        switch(mode)
        !           234:        {
        !           235:        case    2:
        !           236:        case    0:
        !           237:                st->flags &= ~ST_NOREWIND;
        !           238:                break;
        !           239:        case    3:
        !           240:        case    1:
        !           241:                st->flags |= ST_NOREWIND;
        !           242:                break;
        !           243:        default:
        !           244:                printf("st%d: Bad mode (minor number)%d\n",unit,mode);
        !           245:                return(EINVAL);
        !           246:        }
        !           247:         /*******************************************************\
        !           248:         * Check density code: 0 is drive default               *
        !           249:         \*******************************************************/
        !           250:         switch(dsty)
        !           251:        {
        !           252:        case    0:              dsty_code = 0;          break;
        !           253:        case    DSTY_QIC120:    dsty_code = QIC120;     break;
        !           254:        case    DSTY_QIC150:    dsty_code = QIC150;     break;
        !           255:        case    DSTY_QIC525:    dsty_code = QIC525;     break;
        !           256:        default:
        !           257:                printf("st%d: Bad density (minor number)%d\n",unit,dsty);
        !           258:                return(EINVAL);
        !           259:        }
        !           260:        if(scsi_debug & (PRINTROUTINES | TRACEOPENS))
        !           261:                printf("stopen: dev=0x%x (unit %d (of %d))\n"
        !           262:                                ,   dev,      unit,   NST);
        !           263:        /*******************************************************\
        !           264:        * Make sure the device has been initialised             *
        !           265:        \*******************************************************/
        !           266: 
        !           267:        if (!st_initialized[unit])
        !           268:                return(ENXIO);
        !           269:        /*******************************************************\
        !           270:        * Check that it is still responding and ok.             *
        !           271:        \*******************************************************/
        !           272: 
        !           273:        if(scsi_debug & TRACEOPENS)
        !           274:                printf("device is ");
        !           275:        if (!(st_req_sense(unit, 0)))
        !           276:        {
        !           277:                errcode = ENXIO;
        !           278:                if(scsi_debug & TRACEOPENS)
        !           279:                        printf("not responding\n");
        !           280:                goto bad;
        !           281:        }
        !           282:        if(scsi_debug & TRACEOPENS)
        !           283:                printf("ok\n");
        !           284: 
        !           285:        if(!(st_test_ready(unit,0)))
        !           286:        {
        !           287:                printf("st%d not ready\n",unit);
        !           288:                return(EIO);
        !           289:        }
        !           290: 
        !           291:        if(!st_info_valid[unit])                /* is media new? */
        !           292:                if(!st_load(unit,LD_LOAD,0))
        !           293:                {
        !           294:                        return(EIO);
        !           295:                }
        !           296: 
        !           297:        if(!st_rd_blk_lim(unit,0))
        !           298:        {
        !           299:                return(EIO);
        !           300:        }
        !           301: 
        !           302:        if(!st_mode_sense(unit,0))
        !           303:        {
        !           304:                return(EIO);
        !           305:        }
        !           306: 
        !           307:        if(!st_mode_select(unit,0,dsty_code))
        !           308:        {
        !           309:                return(EIO);
        !           310:        }
        !           311: 
        !           312:        st_info_valid[unit] = TRUE;
        !           313: 
        !           314:        st_prevent(unit,PR_PREVENT,0); /* who cares if it fails? */
        !           315: 
        !           316:        /*******************************************************\
        !           317:        * Load the physical device parameters                   *
        !           318:        \*******************************************************/
        !           319:        if(scsi_debug & TRACEOPENS)
        !           320:                printf("Params loaded ");
        !           321: 
        !           322: 
        !           323:        st->flags |= ST_OPEN;
        !           324: 
        !           325: bad:
        !           326:        return(errcode);
        !           327: }
        !           328: 
        !           329: /*******************************************************\
        !           330: * close the device.. only called if we are the LAST    *
        !           331: * occurence of an open device                          *
        !           332: \*******************************************************/
        !           333: stclose(dev)
        !           334: {
        !           335:        unsigned char unit,mode;
        !           336:        struct  st_data *st;
        !           337: 
        !           338:        unit = UNIT(dev);
        !           339:        mode = MODE(dev);
        !           340:        st = st_data + unit;
        !           341: 
        !           342:        if(scsi_debug & TRACEOPENS)
        !           343:                printf("Closing device");
        !           344:        if(st->flags & ST_WRITTEN)
        !           345:        {
        !           346:                st_write_filemarks(unit,1,0);
        !           347:        }
        !           348:        st->flags &= ~ST_WRITTEN;
        !           349:        switch(mode)
        !           350:        {
        !           351:        case    0:
        !           352:                st_rewind(unit,FALSE,SCSI_SILENT);
        !           353:                st_prevent(unit,PR_ALLOW,SCSI_SILENT);
        !           354:                break;
        !           355:        case    1:
        !           356:                st_prevent(unit,PR_ALLOW,SCSI_SILENT);
        !           357:                break;
        !           358:        case    2:
        !           359:                st_rewind(unit,FALSE,SCSI_SILENT);
        !           360:                st_prevent(unit,PR_ALLOW,SCSI_SILENT);
        !           361:                st_load(unit,LD_UNLOAD,SCSI_SILENT);
        !           362:                break;
        !           363:        case    3:
        !           364:                st_prevent(unit,PR_ALLOW,SCSI_SILENT);
        !           365:                st_load(unit,LD_UNLOAD,SCSI_SILENT);
        !           366:                break;
        !           367:        default:
        !           368:                printf("st%d:close: Bad mode (minor number)%d how's it open?\n"
        !           369:                                ,unit,mode);
        !           370:                return(EINVAL);
        !           371:        }
        !           372:        st->flags &= ~ST_PER_OPEN;
        !           373:        return(0);
        !           374: }
        !           375: 
        !           376: #ifndef        __386BSD__
        !           377: /*******************************************************\
        !           378: * Get ownership of this unit's buf                     *
        !           379: * If need be, sleep on it, until it comes free         *
        !           380: \*******************************************************/
        !           381: struct buf *
        !           382: st_get_buf(unit) {
        !           383:        struct buf *rc;
        !           384: 
        !           385:        while (!(rc = stbuf_free[unit]))
        !           386:                sleep((caddr_t)&stbuf_free[unit], PRIBIO+1);
        !           387:        stbuf_free[unit] = stbuf_free[unit]->b_forw;
        !           388:        rc->b_error = 0;
        !           389:        rc->b_resid = 0;
        !           390:        rc->b_flags = 0;
        !           391:        return(rc);
        !           392: }
        !           393: 
        !           394: /*******************************************************\
        !           395: * Free this unit's buf, wake processes waiting for it  *
        !           396: \*******************************************************/
        !           397: st_free_buf(unit,bp)
        !           398: struct buf *bp;
        !           399: {
        !           400:        if (!stbuf_free[unit])
        !           401:                wakeup((caddr_t)&stbuf_free[unit]);
        !           402:        bp->b_forw = stbuf_free[unit];
        !           403:        stbuf_free[unit] = bp;
        !           404: }
        !           405:        
        !           406: 
        !           407: /*******************************************************\
        !           408: * Get the buf for this unit and use physio to do it    *
        !           409: \*******************************************************/
        !           410: stread(dev,uio)
        !           411: register short  dev;
        !           412: struct uio     *uio;
        !           413: {
        !           414:        int     unit = UNIT(dev);
        !           415:        struct buf *bp = st_get_buf(unit);
        !           416:        int rc;
        !           417:        rc = physio(ststrategy, bp, dev, B_READ, stminphys, uio);
        !           418:        st_free_buf(unit,bp);
        !           419:        return(rc);
        !           420: }
        !           421: 
        !           422: /*******************************************************\
        !           423: * Get the buf for this unit and use physio to do it    *
        !           424: \*******************************************************/
        !           425: stwrite(dev,uio)
        !           426: dev_t          dev;
        !           427: struct uio     *uio;
        !           428: {
        !           429:        int     unit = UNIT(dev);
        !           430:        struct buf *bp = st_get_buf(unit);
        !           431:        int rc;
        !           432: 
        !           433:        rc = physio(ststrategy, bp, dev, B_WRITE, stminphys, uio);
        !           434:        st_free_buf(unit,bp);
        !           435:        return(rc);
        !           436: }
        !           437: 
        !           438: 
        !           439: #endif __386BSD__
        !           440: /*******************************************************\
        !           441: * trim the size of the transfer if needed,             *
        !           442: * called by physio                                     *
        !           443: * basically the smaller of our min and the scsi driver's*
        !           444: * minphys                                              *
        !           445: \*******************************************************/
        !           446: void   stminphys(bp)
        !           447: struct buf     *bp;
        !           448: {
        !           449:        (*(st_data[UNIT(bp->b_dev)].sc_sw->scsi_minphys))(bp);
        !           450: }
        !           451: 
        !           452: /*******************************************************\
        !           453: * Actually translate the requested transfer into       *
        !           454: * one the physical driver can understand               *
        !           455: * The transfer is described by a buf and will include  *
        !           456: * only one physical transfer.                          *
        !           457: \*******************************************************/
        !           458: 
        !           459: int    ststrategy(bp)
        !           460: struct buf     *bp;
        !           461: {
        !           462:        struct  buf     *dp;
        !           463:        unsigned char unit;
        !           464:        unsigned int opri;
        !           465: 
        !           466:        ststrats++;
        !           467:        unit = UNIT((bp->b_dev));
        !           468:        if(scsi_debug & PRINTROUTINES) printf("\nststrategy ");
        !           469:        if(scsi_debug & SHOWREQUESTS) printf("st%d: %d bytes @ blk%d\n",
        !           470:                                        unit,bp->b_bcount,bp->b_blkno);
        !           471:        /*******************************************************\
        !           472:        * If it's a null transfer, return immediatly            *
        !           473:        \*******************************************************/
        !           474:        if (bp->b_bcount == 0) {
        !           475:                goto done;
        !           476:        }
        !           477: 
        !           478:        /*******************************************************\
        !           479:        * Odd sized request on fixed drives are verboten        *
        !           480:        \*******************************************************/
        !           481:        if((st_data[unit].flags & ST_FIXEDBLOCKS)
        !           482:                && bp->b_bcount % st_data[unit].blkmin)
        !           483:        {
        !           484:                printf("st%d: bad request, must be multiple of %d\n",
        !           485:                        unit, st_data[unit].blkmin);
        !           486:                bp->b_error = EIO;
        !           487:                goto bad;
        !           488:        }
        !           489: 
        !           490: #ifdef __386BSD__
        !           491:        stminphys(bp);
        !           492: #endif __386BSD__
        !           493:        opri = splbio();
        !           494:        dp = &st_buf_queue[unit];
        !           495: 
        !           496:        /*******************************************************\
        !           497:        * Place it in the queue of disk activities for this tape*
        !           498:        * at the end                                            *
        !           499:        \*******************************************************/
        !           500:        while ( dp->b_actf) 
        !           501:        {
        !           502:                dp = dp->b_actf;
        !           503:        }       
        !           504:        dp->b_actf = bp;
        !           505:        bp->b_actf = NULL;
        !           506: 
        !           507:        /*******************************************************\
        !           508:        * Tell the device to get going on the transfer if it's  *
        !           509:        * not doing anything, otherwise just wait for completion*
        !           510:        \*******************************************************/
        !           511:        ststart(unit);
        !           512: 
        !           513:        splx(opri);
        !           514:        return;
        !           515: bad:
        !           516:        bp->b_flags |= B_ERROR;
        !           517: done:
        !           518:        /*******************************************************\
        !           519:        * Correctly set the buf to indicate a completed xfer    *
        !           520:        \*******************************************************/
        !           521:        iodone(bp);
        !           522:        return;
        !           523: }
        !           524: 
        !           525: 
        !           526: /***************************************************************\
        !           527: * ststart looks to see if there is a buf waiting for the device        *
        !           528: * and that the device is not already busy. If both are true,   *
        !           529: * It deques the buf and creates a scsi command to perform the  *
        !           530: * transfer in the buf. The transfer request will call st_done  *
        !           531: * on completion, which will in turn call this routine again    *
        !           532: * so that the next queued transfer is performed.               *
        !           533: * The bufs are queued by the strategy routine (ststrategy)     *
        !           534: *                                                              *
        !           535: * This routine is also called after other non-queued requests  *
        !           536: * have been made of the scsi driver, to ensure that the queue  *
        !           537: * continues to be drained.                                     *
        !           538: \***************************************************************/
        !           539: /* ststart() is called at splbio */
        !           540: ststart(unit)
        !           541: {
        !           542:        int                     drivecount;
        !           543:        register struct buf     *bp = 0;
        !           544:        register struct buf     *dp;
        !           545:        struct  scsi_xfer       *xs;
        !           546:        struct  scsi_rw_tape    cmd;
        !           547:        int                     blkno, nblk;
        !           548:        struct  st_data *st;
        !           549: 
        !           550: 
        !           551:        st = st_data + unit;
        !           552: 
        !           553:        if(scsi_debug & PRINTROUTINES) printf("ststart%d ",unit);
        !           554:        /*******************************************************\
        !           555:        * See if there is a buf to do and we are not already    *
        !           556:        * doing one                                             *
        !           557:        \*******************************************************/
        !           558:        xs=&st_scsi_xfer[unit];
        !           559:        if(xs->flags & INUSE)
        !           560:        {
        !           561:                return;    /* unit already underway */
        !           562:        }
        !           563: trynext:
        !           564:        if(st_xfer_block_wait[unit]) /* a special awaits, let it proceed first */
        !           565:        {
        !           566:                wakeup(&st_xfer_block_wait[unit]);
        !           567:                return;
        !           568:        }
        !           569: 
        !           570:        dp = &st_buf_queue[unit];
        !           571:        if ((bp = dp->b_actf) != NULL)
        !           572:        {
        !           573:                dp->b_actf = bp->b_actf;
        !           574:        }
        !           575:        else /* no work to do */
        !           576:        {
        !           577:                return;
        !           578:        }
        !           579:        xs->flags = INUSE;    /* Now ours */
        !           580: 
        !           581: 
        !           582:        /*******************************************************\
        !           583:        * We have a buf, now we should move the data into       *
        !           584:        * a scsi_xfer definition and try start it               *
        !           585:        \*******************************************************/
        !           586: 
        !           587:        /*******************************************************\
        !           588:        *  If we are at a filemark but have not reported it yet *
        !           589:        * then we should report it now                          *
        !           590:        \*******************************************************/
        !           591:        if(st->flags & ST_AT_FILEMARK)
        !           592:        {
        !           593:                bp->b_error = 0;
        !           594:                bp->b_flags |= B_ERROR; /* EOF*/
        !           595:                st->flags &= ~ST_AT_FILEMARK;
        !           596:                biodone(bp);
        !           597:                xs->flags = 0; /* won't need it now */
        !           598:                goto trynext;
        !           599:        }
        !           600:        /*******************************************************\
        !           601:        *  If we are at EOM but have not reported it yet        *
        !           602:        * then we should report it now                          *
        !           603:        \*******************************************************/
        !           604:        if(st->flags & ST_AT_EOM)
        !           605:        {
        !           606:                bp->b_error = EIO;
        !           607:                bp->b_flags |= B_ERROR;
        !           608:                st->flags &= ~ST_AT_EOM;
        !           609:                biodone(bp);
        !           610:                xs->flags = 0; /* won't need it now */
        !           611:                goto trynext;
        !           612:        }
        !           613:        /*******************************************************\
        !           614:        *  Fill out the scsi command                            *
        !           615:        \*******************************************************/
        !           616:        bzero(&cmd, sizeof(cmd));
        !           617:        if((bp->b_flags & B_READ) == B_WRITE)
        !           618:        {
        !           619:                st->flags |= ST_WRITTEN;
        !           620:                xs->flags |= SCSI_DATA_OUT;
        !           621:        }
        !           622:        else
        !           623:        {
        !           624:                xs->flags |= SCSI_DATA_IN;
        !           625:        }
        !           626:        cmd.op_code = (bp->b_flags & B_READ) 
        !           627:                                        ? READ_COMMAND_TAPE
        !           628:                                        : WRITE_COMMAND_TAPE;
        !           629: 
        !           630:        /*******************************************************\
        !           631:        * Handle "fixed-block-mode" tape drives by using the    *
        !           632:        * block count instead of the length.                    *
        !           633:        \*******************************************************/
        !           634:        if(st->flags & ST_FIXEDBLOCKS)
        !           635:        {
        !           636:                cmd.fixed = 1;
        !           637:                lto3b(bp->b_bcount/st->blkmin,cmd.len);
        !           638:        }
        !           639:        else
        !           640:        {
        !           641:                lto3b(bp->b_bcount,cmd.len);
        !           642:        }
        !           643: 
        !           644:        /*******************************************************\
        !           645:        * Fill out the scsi_xfer structure                      *
        !           646:        *       Note: we cannot sleep as we may be an interrupt *
        !           647:        \*******************************************************/
        !           648:        xs->flags       |=      SCSI_NOSLEEP;
        !           649:        xs->adapter     =       st->ctlr;
        !           650:        xs->targ        =       st->targ;
        !           651:        xs->lu          =       st->lu;
        !           652:        xs->retries     =       1;      /* can't retry on tape*/
        !           653:        xs->timeout     =       100000; /* allow 100 secs for retension */
        !           654:        xs->cmd         =       (struct scsi_generic *)&cmd;
        !           655:        xs->cmdlen      =       sizeof(cmd);
        !           656:        xs->data        =       (u_char *)bp->b_un.b_addr;
        !           657:        xs->datalen     =       bp->b_bcount;
        !           658:        xs->resid       =       bp->b_bcount;
        !           659:        xs->when_done   =       st_done;
        !           660:        xs->done_arg    =       unit;
        !           661:        xs->done_arg2   =       (int)xs;
        !           662:        xs->error       =       XS_NOERROR;
        !           663:        xs->bp          =       bp;
        !           664:        /*******************************************************\
        !           665:        * Pass all this info to the scsi driver.                *
        !           666:        \*******************************************************/
        !           667: 
        !           668: 
        !           669: #if defined(OSF)||defined(FIX_ME)
        !           670:        if (bp->b_flags & B_PHYS) {
        !           671:                xs->data = (u_char*)map_pva_kva(bp->b_proc, bp->b_un.b_addr,
        !           672:                        bp->b_bcount, st_window[unit],
        !           673:                        (bp->b_flags&B_READ)?B_WRITE:B_READ);
        !           674:        } else {
        !           675:                xs->data = (u_char*)bp->b_un.b_addr;
        !           676:        }
        !           677: #endif /* defined(OSF) */
        !           678: 
        !           679:        if ( (*(st->sc_sw->scsi_cmd))(xs) != SUCCESSFULLY_QUEUED)
        !           680:        {
        !           681:                printf("st%d: oops not queued",unit);
        !           682:                xs->error = XS_DRIVER_STUFFUP;
        !           683:                st_done(unit,xs);
        !           684:        }
        !           685:        stqueues++;
        !           686: }
        !           687: 
        !           688: /*******************************************************\
        !           689: * This routine is called by the scsi interrupt when    *
        !           690: * the transfer is complete.
        !           691: \*******************************************************/
        !           692: int    st_done(unit,xs)
        !           693: int    unit;
        !           694: struct scsi_xfer       *xs;
        !           695: {
        !           696:        struct  buf             *bp;
        !           697:        int     retval;
        !           698: 
        !           699:        if(scsi_debug & PRINTROUTINES) printf("st_done%d ",unit);
        !           700:        if (! (xs->flags & INUSE))
        !           701:                panic("scsi_xfer not in use!");
        !           702:        if(bp = xs->bp)
        !           703:        {
        !           704:                switch(xs->error)
        !           705:                {
        !           706:                case    XS_NOERROR:
        !           707:                        bp->b_flags &= ~B_ERROR;
        !           708:                        bp->b_error = 0;
        !           709:                        bp->b_resid = 0;
        !           710:                        break;
        !           711:                case    XS_SENSE:
        !           712:                        retval = (st_interpret_sense(unit,xs));
        !           713:                        if(retval)
        !           714:                        {
        !           715:                                /***************************************\
        !           716:                                * We have a real error, the bit should  *
        !           717:                                * be set to indicate this. The return   *
        !           718:                                * value will contain the unix error code*
        !           719:                                * that the error interpretation routine *
        !           720:                                * thought was suitable, so pass this    *
        !           721:                                * value back in the buf structure.      *
        !           722:                                * Furthermore we return information     *
        !           723:                                * saying that no data was transferred   *
        !           724:                                \***************************************/
        !           725:                                bp->b_flags |= B_ERROR;
        !           726:                                bp->b_error = retval;
        !           727:                                bp->b_resid =  bp->b_bcount;
        !           728:                                st_data[unit].flags 
        !           729:                                        &= ~(ST_AT_FILEMARK|ST_AT_EOM);
        !           730:                        }
        !           731:                        else
        !           732:                        {
        !           733:                        /***********************************************\
        !           734:                        * The error interpretation code has declared    *
        !           735:                        * that it wasn't a real error, or at least that *
        !           736:                        * we should be ignoring it if it was.           *
        !           737:                        \***********************************************/
        !           738:                            if(xs->resid && ( xs->resid != xs->datalen ))
        !           739:                            {
        !           740:                                /***************************************\
        !           741:                                * Here we have the tricky part..        *
        !           742:                                * We successfully read less data than   *
        !           743:                                * we requested. (but not 0)             *
        !           744:                                *------for variable blocksize tapes:----*
        !           745:                                * UNDER 386BSD:                         *
        !           746:                                * We should legitimatly have the error  *
        !           747:                                * bit set, with the error value set to  *
        !           748:                                * zero.. This is to indicate to the     *
        !           749:                                * physio code that while we didn't get  *
        !           750:                                * as much information as was requested, *
        !           751:                                * we did reach the end of the record    *
        !           752:                                * and so physio should not call us      *
        !           753:                                * again for more data... we have it all *
        !           754:                                * SO SET THE ERROR BIT!                 *
        !           755:                                *                                       *
        !           756:                                * UNDER MACH:(CMU)                      *
        !           757:                                * To indicate the same as above, we     *
        !           758:                                * need only have a non 0 resid that is  *
        !           759:                                * less than the b_bcount, but the       *
        !           760:                                * ERROR BIT MUST BE CLEAR! (sigh)       *
        !           761:                                *                                       *
        !           762:                                * UNDER OSF1:                           *
        !           763:                                * To indicate the same as above, we     *
        !           764:                                * need to have a non 0 resid that is    *
        !           765:                                * less than the b_bcount, but the       *
        !           766:                                * ERROR BIT MUST BE SET! (gasp)(sigh)   *
        !           767:                                *                                       *
        !           768:                                *-------for fixed blocksize device------*
        !           769:                                * We could have read some successful    *
        !           770:                                * records before hitting                *
        !           771:                                * the EOF or EOT. These must be passed  *
        !           772:                                * to the user, before we report the     *
        !           773:                                * EOx. Only if there is no data for the *
        !           774:                                * user do we report it now. (via an EIO *
        !           775:                                * for EOM and resid == count for EOF).  *
        !           776:                                * We will report the EOx NEXT time..    *
        !           777:                                \***************************************/
        !           778: #ifdef MACH /*osf and cmu varieties */
        !           779: #ifdef OSF
        !           780:                                bp->b_flags |= B_ERROR;
        !           781: #else  OSF
        !           782:                                bp->b_flags &= ~B_ERROR;
        !           783: #endif OSF
        !           784: #endif MACH
        !           785: #ifdef __386BSD__
        !           786:                                bp->b_flags |= B_ERROR;
        !           787: #endif __386BSD__
        !           788:                                bp->b_error = 0;
        !           789:                                bp->b_resid = xs->resid;
        !           790:                                if((st_data[unit].flags & ST_FIXEDBLOCKS))
        !           791:                                {
        !           792:                                        bp->b_resid *= st_data[unit].blkmin;
        !           793:                                        if(  (st_data[unit].flags & ST_AT_EOM)
        !           794:                                          && (bp->b_resid == bp->b_bcount))
        !           795:                                        {
        !           796:                                                bp->b_error = EIO;
        !           797:                                                st_data[unit].flags
        !           798:                                                        &= ~ST_AT_EOM;
        !           799:                                        }
        !           800:                                }
        !           801:                                xs->error = XS_NOERROR;
        !           802:                                break;
        !           803:                            }
        !           804:                            else
        !           805:                            {
        !           806:                                /***************************************\
        !           807:                                * We have come out of the error handler *
        !           808:                                * with no error code.. we have also     *
        !           809:                                * not had an ili (would have gone to    *
        !           810:                                * the previous clause). Now we need to  *
        !           811:                                * distiguish between succesful read of  *
        !           812:                                * no data (EOF or EOM) and successfull  *
        !           813:                                * read of all requested data.           *
        !           814:                                * At least all o/s agree that:          *
        !           815:                                * 0 bytes read with no error is EOF     *
        !           816:                                * 0 bytes read with an EIO is EOM       *
        !           817:                                \***************************************/
        !           818: 
        !           819:                                bp->b_resid = bp->b_bcount;
        !           820:                                if(st_data[unit].flags & ST_AT_FILEMARK)
        !           821:                                {
        !           822:                                        st_data[unit].flags &= ~ST_AT_FILEMARK;
        !           823:                                        bp->b_flags &= ~B_ERROR;
        !           824:                                        bp->b_error = 0;
        !           825:                                        break;
        !           826:                                }
        !           827:                                if(st_data[unit].flags & ST_AT_EOM)
        !           828:                                {
        !           829:                                        bp->b_flags |= B_ERROR;
        !           830:                                        bp->b_error = EIO;
        !           831:                                        st_data[unit].flags &= ~ST_AT_EOM;
        !           832:                                        break;
        !           833:                                }
        !           834:                                printf("st%d:error ignored\n" ,unit);
        !           835:                            }
        !           836:                        }
        !           837:                        break;
        !           838: 
        !           839:                case    XS_TIMEOUT:
        !           840:                        printf("st%d timeout\n",unit);
        !           841:                        break;
        !           842: 
        !           843:                case    XS_BUSY:        /* should retry */ /* how? */
        !           844:                        /************************************************/
        !           845:                        /* SHOULD put buf back at head of queue         */
        !           846:                        /* and decrement retry count in (*xs)           */
        !           847:                        /* HOWEVER, this should work as a kludge        */
        !           848:                        /************************************************/
        !           849:                        if(xs->retries--)
        !           850:                        {
        !           851:                                xs->flags &= ~ITSDONE;
        !           852:                                xs->error = XS_NOERROR;
        !           853:                                if ( (*(st_data[unit].sc_sw->scsi_cmd))(xs)
        !           854:                                        == SUCCESSFULLY_QUEUED)
        !           855:                                {       /* don't wake the job, ok? */
        !           856:                                        return;
        !           857:                                }
        !           858:                                printf("device busy");
        !           859:                                xs->flags |= ITSDONE;
        !           860:                        }
        !           861: 
        !           862:                case    XS_DRIVER_STUFFUP:
        !           863:                        bp->b_flags |= B_ERROR;
        !           864:                        bp->b_error = EIO;
        !           865:                        break;
        !           866:                default:
        !           867:                        printf("st%d: unknown error category from scsi driver\n"
        !           868:                                ,unit);
        !           869:                }       
        !           870:                biodone(bp);
        !           871:                xs->flags = 0;  /* no longer in use */
        !           872:                ststart(unit);          /* If there's another waiting.. do it */
        !           873:        }
        !           874:        else
        !           875:        {
        !           876:                wakeup(xs);
        !           877:        }
        !           878: }
        !           879: /*******************************************************\
        !           880: * Perform special action on behalf of the user         *
        !           881: * Knows about the internals of this device             *
        !           882: \*******************************************************/
        !           883: stioctl(dev, cmd, arg, mode)
        !           884: dev_t dev;
        !           885: int cmd;
        !           886: caddr_t arg;
        !           887: {
        !           888:        register i,j;
        !           889:        unsigned int opri;
        !           890:        int errcode = 0;
        !           891:        unsigned char unit;
        !           892:        int number,flags,ret;
        !           893: 
        !           894:        /*******************************************************\
        !           895:        * Find the device that the user is talking about        *
        !           896:        \*******************************************************/
        !           897:        flags = 0;      /* give error messages, act on errors etc. */
        !           898:        unit = UNIT(dev);
        !           899: 
        !           900:        switch(cmd)
        !           901:        {
        !           902: 
        !           903:        case MTIOCGET:
        !           904:            {
        !           905:                struct mtget *g = (struct mtget *) arg;
        !           906: 
        !           907:                bzero(g, sizeof(struct mtget));
        !           908:                g->mt_type = 0x7;       /* Ultrix compat */ /*?*/
        !           909:                ret=TRUE;
        !           910:                break;
        !           911:            }
        !           912: 
        !           913: 
        !           914:        case MTIOCTOP:
        !           915:            {
        !           916:                struct mtop *mt = (struct mtop *) arg;
        !           917: 
        !           918:                if (st_debug)
        !           919:                        printf("[sctape_sstatus: %x %x]\n",
        !           920:                                 mt->mt_op, mt->mt_count);
        !           921: 
        !           922: 
        !           923: 
        !           924:                /* compat: in U*x it is a short */
        !           925:                number = mt->mt_count;
        !           926:                switch ((short)(mt->mt_op))
        !           927:                {
        !           928:                case MTWEOF:    /* write an end-of-file record */
        !           929:                        ret = st_write_filemarks(unit,number,flags);
        !           930:                        st_data[unit].flags &= ~ST_WRITTEN;
        !           931:                        break;
        !           932:                case MTFSF:     /* forward space file */
        !           933:                        ret = st_space(unit,number,SP_FILEMARKS,flags);
        !           934:                        break;
        !           935:                case MTBSF:     /* backward space file */
        !           936:                        ret = st_space(unit,-number,SP_FILEMARKS,flags);
        !           937:                        break;
        !           938:                case MTFSR:     /* forward space record */
        !           939:                        ret = st_space(unit,number,SP_BLKS,flags);
        !           940:                        break;
        !           941:                case MTBSR:     /* backward space record */
        !           942:                        ret = st_space(unit,-number,SP_BLKS,flags);
        !           943:                        break;
        !           944:                case MTREW:     /* rewind */
        !           945:                        ret = st_rewind(unit,FALSE,flags);
        !           946:                        break;
        !           947:                case MTOFFL:    /* rewind and put the drive offline */
        !           948:                        if((ret = st_rewind(unit,FALSE,flags)))
        !           949:                        {
        !           950:                                st_prevent(unit,PR_ALLOW,0);
        !           951:                                ret = st_load(unit,LD_UNLOAD,flags);
        !           952:                        }
        !           953:                        else
        !           954:                        {
        !           955:                                printf("rewind failed, unit still loaded\n");
        !           956:                        }
        !           957:                        break;
        !           958:                case MTNOP:     /* no operation, sets status only */
        !           959:                case MTCACHE:   /* enable controller cache */
        !           960:                case MTNOCACHE: /* disable controller cache */
        !           961:                        ret = TRUE;;
        !           962:                        break;
        !           963:                default:
        !           964:                        return EINVAL;
        !           965:                }
        !           966:                break;
        !           967:            }
        !           968:        case MTIOCIEOT:
        !           969:        case MTIOCEEOT:
        !           970:                ret=TRUE;
        !           971:                break;
        !           972:        }
        !           973: 
        !           974:        return(ret?ESUCCESS:EIO);
        !           975: }
        !           976: 
        !           977: 
        !           978: /*******************************************************\
        !           979: * Check with the device that it is ok, (via scsi driver)*
        !           980: \*******************************************************/
        !           981: st_req_sense(unit, flags)
        !           982: int    flags;
        !           983: {
        !           984:        struct  scsi_sense_data sense;
        !           985:        struct  scsi_sense      scsi_cmd;
        !           986: 
        !           987:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !           988:        scsi_cmd.op_code = REQUEST_SENSE;
        !           989:        scsi_cmd.length = sizeof(sense);
        !           990: 
        !           991:        if (st_scsi_cmd(unit,
        !           992:                        &scsi_cmd,
        !           993:                        sizeof(scsi_cmd),
        !           994:                        &sense,
        !           995:                        sizeof(sense),
        !           996:                        100000,
        !           997:                        flags | SCSI_DATA_IN) != 0)
        !           998:        {
        !           999:                return(FALSE);
        !          1000:        }
        !          1001:        else 
        !          1002:                return(TRUE);
        !          1003: }
        !          1004: 
        !          1005: /*******************************************************\
        !          1006: * Get scsi driver to send a "are you ready" command    *
        !          1007: \*******************************************************/
        !          1008: st_test_ready(unit,flags)
        !          1009: int    unit,flags;
        !          1010: {
        !          1011:        struct  scsi_test_unit_ready scsi_cmd;
        !          1012: 
        !          1013:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1014:        scsi_cmd.op_code = TEST_UNIT_READY;
        !          1015: 
        !          1016:        if (st_scsi_cmd(unit,
        !          1017:                        &scsi_cmd,
        !          1018:                        sizeof(scsi_cmd),
        !          1019:                        0,
        !          1020:                        0,
        !          1021:                        100000,
        !          1022:                        flags) != 0) {
        !          1023:                return(FALSE);
        !          1024:        } else 
        !          1025:                return(TRUE);
        !          1026: }
        !          1027: 
        !          1028: 
        !          1029: #ifdef __STDC__
        !          1030: #define b2tol(a)       (((unsigned)(a##_1) << 8) + (unsigned)a##_0 )
        !          1031: #else
        !          1032: #define b2tol(a)       (((unsigned)(a/**/_1) << 8) + (unsigned)a/**/_0 )
        !          1033: #endif
        !          1034: 
        !          1035: /*******************************************************\
        !          1036: * Ask the drive what it's min and max blk sizes are.   *
        !          1037: \*******************************************************/
        !          1038: st_rd_blk_lim(unit, flags)
        !          1039: int    unit,flags;
        !          1040: {
        !          1041:        struct  scsi_blk_limits scsi_cmd;
        !          1042:        struct scsi_blk_limits_data scsi_blkl;
        !          1043:        struct st_data *st = st_data + unit;
        !          1044:        /*******************************************************\
        !          1045:        * First check if we have it all loaded                  *
        !          1046:        \*******************************************************/
        !          1047:        if (st_info_valid[unit]) goto done;
        !          1048: 
        !          1049:        /*******************************************************\
        !          1050:        * do a 'Read Block Limits'                              *
        !          1051:        \*******************************************************/
        !          1052:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1053:        scsi_cmd.op_code = READ_BLK_LIMITS;
        !          1054: 
        !          1055:        /*******************************************************\
        !          1056:        * do the command,       update the global values        *
        !          1057:        \*******************************************************/
        !          1058:        if (st_scsi_cmd(unit,
        !          1059:                        &scsi_cmd,
        !          1060:                        sizeof(scsi_cmd),
        !          1061:                        &scsi_blkl,
        !          1062:                        sizeof(scsi_blkl),
        !          1063:                        5000,
        !          1064:                        flags | SCSI_DATA_IN) != 0)
        !          1065:        {
        !          1066:                if(!(flags & SCSI_SILENT))
        !          1067:                        printf("could not get blk limits for unit %d\n", unit);
        !          1068:                st_info_valid[unit] = FALSE;
        !          1069:                return(FALSE);
        !          1070:        } 
        !          1071:        if (st_debug)
        !          1072:        {
        !          1073:                printf(" (%d <= blksiz <= %d\n) ",
        !          1074:                        b2tol(scsi_blkl.min_length),
        !          1075:                        _3btol(&scsi_blkl.max_length_2));
        !          1076:        }
        !          1077:        st->blkmin = b2tol(scsi_blkl.min_length);
        !          1078:        st->blkmax = _3btol(&scsi_blkl.max_length_2);
        !          1079: 
        !          1080: done:
        !          1081:        if(st->blkmin && (st->blkmin == st->blkmax))
        !          1082:        {
        !          1083:                st->flags |= ST_FIXEDBLOCKS;
        !          1084:        }
        !          1085:        return(TRUE);
        !          1086: }
        !          1087: /*******************************************************\
        !          1088: * Get the scsi driver to send a full inquiry to the    *
        !          1089: * device and use the results to fill out the global    *
        !          1090: * parameter structure.                                 *
        !          1091: \*******************************************************/
        !          1092: st_mode_sense(unit, flags)
        !          1093: int    unit,flags;
        !          1094: {
        !          1095:        struct scsi_mode_sense          scsi_cmd;
        !          1096:        struct 
        !          1097:        {
        !          1098:                struct  scsi_mode_header_tape header;
        !          1099:                struct  blk_desc        blk_desc;
        !          1100:        }scsi_sense;
        !          1101:        struct  st_data *st = st_data + unit;
        !          1102: 
        !          1103:        /*******************************************************\
        !          1104:        * First check if we have it all loaded                  *
        !          1105:        \*******************************************************/
        !          1106:        if (st_info_valid[unit]) return(TRUE);
        !          1107:        /*******************************************************\
        !          1108:        * First do a mode sense                                 *
        !          1109:        \*******************************************************/
        !          1110:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1111:        scsi_cmd.op_code = MODE_SENSE;
        !          1112:        scsi_cmd.length = sizeof(scsi_sense);
        !          1113:        /*******************************************************\
        !          1114:        * do the command, but we don't need the results         *
        !          1115:        * just print them for our interest's sake               *
        !          1116:        \*******************************************************/
        !          1117:        if (st_scsi_cmd(unit,
        !          1118:                        &scsi_cmd,
        !          1119:                        sizeof(scsi_cmd),
        !          1120:                        &scsi_sense,
        !          1121:                        sizeof(scsi_sense),
        !          1122:                        5000,
        !          1123:                        flags | SCSI_DATA_IN) != 0)
        !          1124:        {
        !          1125:                if(!(flags & SCSI_SILENT))
        !          1126:                        printf("could not mode sense for unit %d\n", unit);
        !          1127:                st_info_valid[unit] = FALSE;
        !          1128:                return(FALSE);
        !          1129:        } 
        !          1130:        if (st_debug)
        !          1131:        {
        !          1132:                printf("unit %d: %d blocks of %d bytes, write %s, %sbuffered",
        !          1133:                        unit,
        !          1134:                        _3btol(&scsi_sense.blk_desc.nblocks),
        !          1135:                        _3btol(&scsi_sense.blk_desc.blklen),
        !          1136:                        (scsi_sense.header.write_protected ?
        !          1137:                                "protected" : "enabled"),
        !          1138:                        (scsi_sense.header.buf_mode ?
        !          1139:                                "" : "un")
        !          1140:                        );
        !          1141:        }
        !          1142:        st->numblks = _3btol(&scsi_sense.blk_desc.nblocks);
        !          1143:        st->blksiz = _3btol(&scsi_sense.blk_desc.blklen);
        !          1144:        return(TRUE);
        !          1145: }
        !          1146: 
        !          1147: /*******************************************************\
        !          1148: * Get the scsi driver to send a full inquiry to the    *
        !          1149: * device and use the results to fill out the global    *
        !          1150: * parameter structure.                                 *
        !          1151: \*******************************************************/
        !          1152: st_mode_select(unit, flags, dsty_code)
        !          1153: int    unit,flags,dsty_code;
        !          1154: {
        !          1155:        struct scsi_mode_select scsi_cmd;
        !          1156:        struct
        !          1157:        {
        !          1158:                struct  scsi_mode_header_tape header;
        !          1159:                struct  blk_desc        blk_desc;
        !          1160:        }dat;
        !          1161:        struct  st_data *st = st_data + unit;
        !          1162: 
        !          1163:        /*******************************************************\
        !          1164:        * Set up for a mode select                              *
        !          1165:        \*******************************************************/
        !          1166:        bzero(&dat, sizeof(dat));
        !          1167:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1168:        scsi_cmd.op_code = MODE_SELECT;
        !          1169:        scsi_cmd.length = sizeof(dat);
        !          1170:        dat.header.blk_desc_len = sizeof(struct  blk_desc);
        !          1171:        dat.header.buf_mode = 1;
        !          1172:         dat.blk_desc.density = dsty_code;
        !          1173:        if(st->flags & ST_FIXEDBLOCKS)
        !          1174:        {
        !          1175:                lto3b( st->blkmin , dat.blk_desc.blklen);
        !          1176:        }
        !          1177: /*     lto3b( st->numblks , dat.blk_desc.nblocks); use defaults!!!!
        !          1178:        lto3b( st->blksiz , dat.blk_desc.blklen);
        !          1179: */
        !          1180:        /*******************************************************\
        !          1181:        * do the command                                        *
        !          1182:        \*******************************************************/
        !          1183:        if (st_scsi_cmd(unit,
        !          1184:                        &scsi_cmd,
        !          1185:                        sizeof(scsi_cmd),
        !          1186:                        &dat,
        !          1187:                        sizeof(dat),
        !          1188:                        5000,
        !          1189:                        flags | SCSI_DATA_OUT) != 0)
        !          1190:        {
        !          1191:                if(!(flags & SCSI_SILENT))
        !          1192:                        printf("could not mode select for unit %d\n", unit);
        !          1193:                st_info_valid[unit] = FALSE;
        !          1194:                return(FALSE);
        !          1195:        } 
        !          1196:        return(TRUE);
        !          1197: }
        !          1198: 
        !          1199: /*******************************************************\
        !          1200: * skip N blocks/filemarks/seq filemarks/eom            *
        !          1201: \*******************************************************/
        !          1202: st_space(unit,number,what,flags)
        !          1203: int    unit,number,what,flags;
        !          1204: {
        !          1205:        struct scsi_space scsi_cmd;
        !          1206: 
        !          1207:        /* if we are at a filemark now, we soon won't be*/
        !          1208:        st_data[unit].flags &= ~(ST_AT_FILEMARK | ST_AT_EOM);
        !          1209:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1210:        scsi_cmd.op_code = SPACE;
        !          1211:        scsi_cmd.code = what;
        !          1212:        lto3b(number,scsi_cmd.number);
        !          1213:        if (st_scsi_cmd(unit,
        !          1214:                        &scsi_cmd,
        !          1215:                        sizeof(scsi_cmd),
        !          1216:                        0,
        !          1217:                        0,
        !          1218:                        600000, /* 10 mins enough? */
        !          1219:                        flags) != 0)
        !          1220:        {
        !          1221:                if(!(flags & SCSI_SILENT))
        !          1222:                        printf("could not space st%d\n", unit);
        !          1223:                st_info_valid[unit] = FALSE;
        !          1224:                return(FALSE);
        !          1225:        }
        !          1226:        return(TRUE);
        !          1227: }
        !          1228: /*******************************************************\
        !          1229: * write N filemarks                                    *
        !          1230: \*******************************************************/
        !          1231: st_write_filemarks(unit,number,flags)
        !          1232: int    unit,number,flags;
        !          1233: {
        !          1234:        struct scsi_write_filemarks scsi_cmd;
        !          1235: 
        !          1236:        st_data[unit].flags &= ~(ST_AT_FILEMARK);
        !          1237:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1238:        scsi_cmd.op_code = WRITE_FILEMARKS;
        !          1239:        lto3b(number,scsi_cmd.number);
        !          1240:        if (st_scsi_cmd(unit,
        !          1241:                        &scsi_cmd,
        !          1242:                        sizeof(scsi_cmd),
        !          1243:                        0,
        !          1244:                        0,
        !          1245:                        100000, /* 10 secs.. (may need to repos head )*/
        !          1246:                        flags) != 0)
        !          1247:        {
        !          1248:                if(!(flags & SCSI_SILENT))
        !          1249:                        printf("could not write_filemarks st%d\n", unit);
        !          1250:                st_info_valid[unit] = FALSE;
        !          1251:                return(FALSE);
        !          1252:        }
        !          1253:        return(TRUE);
        !          1254: }
        !          1255: /*******************************************************\
        !          1256: * load /unload (with retension if true)                        *
        !          1257: \*******************************************************/
        !          1258: st_load(unit,type,flags)
        !          1259: int    unit,type,flags;
        !          1260: {
        !          1261:        struct  scsi_load  scsi_cmd;
        !          1262: 
        !          1263:        st_data[unit].flags &= ~(ST_AT_FILEMARK | ST_AT_EOM);
        !          1264:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1265:        scsi_cmd.op_code = LOAD_UNLOAD;
        !          1266:        scsi_cmd.load=type;
        !          1267:        if (type == LD_LOAD)
        !          1268:        {
        !          1269:                /*scsi_cmd.reten=TRUE;*/
        !          1270:                scsi_cmd.reten=FALSE;
        !          1271:        }
        !          1272:        else
        !          1273:        {
        !          1274:                scsi_cmd.reten=FALSE;
        !          1275:        }
        !          1276:        if (st_scsi_cmd(unit,
        !          1277:                        &scsi_cmd,
        !          1278:                        sizeof(scsi_cmd),
        !          1279:                        0,
        !          1280:                        0,
        !          1281:                        30000, /* 30 secs */
        !          1282:                        flags) != 0)
        !          1283:        {
        !          1284:                if(!(flags & SCSI_SILENT))
        !          1285:                        printf("cannot load/unload  st%d\n", unit);
        !          1286:                st_info_valid[unit] = FALSE;
        !          1287:                return(FALSE);
        !          1288:        }
        !          1289:        return(TRUE);
        !          1290: }
        !          1291: /*******************************************************\
        !          1292: * Prevent or allow the user to remove the tape         *
        !          1293: \*******************************************************/
        !          1294: st_prevent(unit,type,flags)
        !          1295: int    unit,type,flags;
        !          1296: {
        !          1297:        struct  scsi_prevent    scsi_cmd;
        !          1298: 
        !          1299:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1300:        scsi_cmd.op_code = PREVENT_ALLOW;
        !          1301:        scsi_cmd.prevent=type;
        !          1302:        if (st_scsi_cmd(unit,
        !          1303:                        &scsi_cmd,
        !          1304:                        sizeof(scsi_cmd),
        !          1305:                        0,
        !          1306:                        0,
        !          1307:                        5000,
        !          1308:                        flags) != 0)
        !          1309:        {
        !          1310:                if(!(flags & SCSI_SILENT))
        !          1311:                        printf("cannot prevent/allow on st%d\n", unit);
        !          1312:                st_info_valid[unit] = FALSE;
        !          1313:                return(FALSE);
        !          1314:        }
        !          1315:        return(TRUE);
        !          1316: }
        !          1317: /*******************************************************\
        !          1318: *  Rewind the device                                   *
        !          1319: \*******************************************************/
        !          1320: st_rewind(unit,immed,flags)
        !          1321: int    unit,immed,flags;
        !          1322: {
        !          1323:        struct  scsi_rewind     scsi_cmd;
        !          1324: 
        !          1325:        st_data[unit].flags &= ~(ST_AT_FILEMARK | ST_AT_EOM);
        !          1326:        bzero(&scsi_cmd, sizeof(scsi_cmd));
        !          1327:        scsi_cmd.op_code = REWIND;
        !          1328:        scsi_cmd.immed=immed;
        !          1329:        if (st_scsi_cmd(unit,
        !          1330:                        &scsi_cmd,
        !          1331:                        sizeof(scsi_cmd),
        !          1332:                        0,
        !          1333:                        0,
        !          1334:                        immed?5000:300000, /* 5 sec or 5 min */
        !          1335:                        flags) != 0)
        !          1336:        {
        !          1337:                if(!(flags & SCSI_SILENT))
        !          1338:                        printf("could not rewind st%d\n", unit);
        !          1339:                st_info_valid[unit] = FALSE;
        !          1340:                return(FALSE);
        !          1341:        }
        !          1342:        return(TRUE);
        !          1343: }
        !          1344: /*******************************************************\
        !          1345: * ask the scsi driver to perform a command for us.     *
        !          1346: * Call it through the switch table, and tell it which  *
        !          1347: * sub-unit we want, and what target and lu we wish to  *
        !          1348: * talk to. Also tell it where to find the command      *
        !          1349: * how long int is.                                     *
        !          1350: * Also tell it where to read/write the data, and how   *
        !          1351: * long the data is supposed to be                      *
        !          1352: \*******************************************************/
        !          1353: int    st_scsi_cmd(unit,scsi_cmd,cmdlen,data_addr,datalen,timeout,flags)
        !          1354: 
        !          1355: int    unit,flags;
        !          1356: struct scsi_generic *scsi_cmd;
        !          1357: int    cmdlen;
        !          1358: int    timeout;
        !          1359: u_char *data_addr;
        !          1360: int    datalen;
        !          1361: {
        !          1362:        struct  scsi_xfer *xs;
        !          1363:        int     retval;
        !          1364:        int     s;
        !          1365:        struct  st_data *st = st_data + unit;
        !          1366: 
        !          1367:        if(scsi_debug & PRINTROUTINES) printf("\nst_scsi_cmd%d ",unit);
        !          1368:        if(st->sc_sw)   /* If we have a scsi driver */
        !          1369:        {
        !          1370: 
        !          1371:                xs = &(st_scsi_xfer[unit]);
        !          1372:                if(!(flags & SCSI_NOMASK))
        !          1373:                        s = splbio();
        !          1374:                st_xfer_block_wait[unit]++;     /* there is someone waiting */
        !          1375:                while (xs->flags & INUSE)
        !          1376:                {
        !          1377:                        sleep(&st_xfer_block_wait[unit],PRIBIO+1);
        !          1378:                }
        !          1379:                st_xfer_block_wait[unit]--;
        !          1380:                xs->flags = INUSE;
        !          1381:                if(!(flags & SCSI_NOMASK))
        !          1382:                        splx(s);
        !          1383: 
        !          1384:                /*******************************************************\
        !          1385:                * Fill out the scsi_xfer structure                      *
        !          1386:                \*******************************************************/
        !          1387:                xs->flags       |=      flags;
        !          1388:                xs->adapter     =       st->ctlr;
        !          1389:                xs->targ        =       st->targ;
        !          1390:                xs->lu          =       st->lu;
        !          1391:                xs->retries     =       ST_RETRIES;
        !          1392:                xs->timeout     =       timeout;
        !          1393:                xs->cmd         =       scsi_cmd;
        !          1394:                xs->cmdlen      =       cmdlen;
        !          1395:                xs->data        =       data_addr;
        !          1396:                xs->datalen     =       datalen;
        !          1397:                xs->resid       =       datalen;
        !          1398:                xs->when_done   =       (flags & SCSI_NOMASK)
        !          1399:                                        ?(int (*)())0
        !          1400:                                        :st_done;
        !          1401:                xs->done_arg    =       unit;
        !          1402:                xs->done_arg2   =       (int)xs;
        !          1403: retry:         xs->error       =       XS_NOERROR;
        !          1404:                xs->bp          =       0;
        !          1405:                retval = (*(st->sc_sw->scsi_cmd))(xs);
        !          1406:                switch(retval)
        !          1407:                {
        !          1408:                case    SUCCESSFULLY_QUEUED:
        !          1409:                        s = splbio();
        !          1410:                        while(!(xs->flags & ITSDONE))
        !          1411:                                sleep(xs,PRIBIO+1);
        !          1412:                        splx(s);
        !          1413: 
        !          1414:                case    HAD_ERROR:
        !          1415:                case    COMPLETE:
        !          1416:                        switch(xs->error)
        !          1417:                        {
        !          1418:                        case    XS_NOERROR:
        !          1419:                                retval = ESUCCESS;
        !          1420:                                break;
        !          1421:                        case    XS_SENSE:
        !          1422:                                retval = (st_interpret_sense(unit,xs));
        !          1423:                                /* only useful for reads */
        !          1424:                                if (retval)
        !          1425:                                { /* error... don't care about filemarks */
        !          1426:                                        st->flags &= ~(ST_AT_FILEMARK
        !          1427:                                                        | ST_AT_EOM);
        !          1428:                                }
        !          1429:                                else
        !          1430:                                {
        !          1431:                                        xs->error = XS_NOERROR;
        !          1432:                                        retval = ESUCCESS;
        !          1433:                                }
        !          1434:                                break;
        !          1435:                        case    XS_DRIVER_STUFFUP:
        !          1436:                                retval = EIO;
        !          1437:                                break;
        !          1438:                        case    XS_TIMEOUT:
        !          1439:                                if(xs->retries-- )
        !          1440:                                {
        !          1441:                                        xs->flags &= ~ITSDONE;
        !          1442:                                        goto retry;
        !          1443:                                }
        !          1444:                                retval = EIO;
        !          1445:                                break;
        !          1446:                        case    XS_BUSY:
        !          1447:                                if(xs->retries-- )
        !          1448:                                {
        !          1449:                                        xs->flags &= ~ITSDONE;
        !          1450:                                        goto retry;
        !          1451:                                }
        !          1452:                                retval = EIO;
        !          1453:                                break;
        !          1454:                        default:
        !          1455:                                retval = EIO;
        !          1456:                                printf("st%d: unknown error category from scsi driver\n"
        !          1457:                                        ,unit);
        !          1458:                                break;
        !          1459:                        }       
        !          1460:                        break;
        !          1461:                case    TRY_AGAIN_LATER:
        !          1462:                        if(xs->retries-- )
        !          1463:                        {
        !          1464:                                xs->flags &= ~ITSDONE;
        !          1465:                                goto retry;
        !          1466:                        }
        !          1467:                        retval = EIO;
        !          1468:                        break;
        !          1469:                default:
        !          1470:                        retval = EIO;
        !          1471:                }
        !          1472:                xs->flags = 0;  /* it's free! */
        !          1473:                ststart(unit);
        !          1474:        }
        !          1475:        else
        !          1476:        {
        !          1477:                printf("st%d: not set up\n",unit);
        !          1478:                return(EINVAL);
        !          1479:        }
        !          1480:        return(retval);
        !          1481: }
        !          1482: /***************************************************************\
        !          1483: * Look at the returned sense and act on the error and detirmine        *
        !          1484: * The unix error number to pass back... (0 = report no error)  *
        !          1485: \***************************************************************/
        !          1486: 
        !          1487: int    st_interpret_sense(unit,xs)
        !          1488: int    unit;
        !          1489: struct scsi_xfer       *xs;
        !          1490: {
        !          1491:        struct  scsi_sense_data *sense;
        !          1492:        int     key;
        !          1493:        int     silent = xs->flags & SCSI_SILENT;
        !          1494: 
        !          1495:        /***************************************************************\
        !          1496:        * If errors are ok, report a success                            *
        !          1497:        \***************************************************************/
        !          1498:        if(xs->flags & SCSI_ERR_OK) return(ESUCCESS);
        !          1499: 
        !          1500:        /***************************************************************\
        !          1501:        * Get the sense fields and work out what CLASS                  *
        !          1502:        \***************************************************************/
        !          1503:        sense = &(xs->sense);
        !          1504:        if(st_debug)
        !          1505:        {
        !          1506:                int count = 0;
        !          1507:                printf("code%x class%x valid%x\n"
        !          1508:                                ,sense->error_code
        !          1509:                                ,sense->error_class
        !          1510:                                ,sense->valid);
        !          1511:                printf("seg%x key%x ili%x eom%x fmark%x\n"
        !          1512:                                ,sense->ext.extended.segment
        !          1513:                                ,sense->ext.extended.sense_key
        !          1514:                                ,sense->ext.extended.ili
        !          1515:                                ,sense->ext.extended.eom
        !          1516:                                ,sense->ext.extended.filemark);
        !          1517:                printf("info: %x %x %x %x followed by %d extra bytes\n"
        !          1518:                                ,sense->ext.extended.info[0]
        !          1519:                                ,sense->ext.extended.info[1]
        !          1520:                                ,sense->ext.extended.info[2]
        !          1521:                                ,sense->ext.extended.info[3]
        !          1522:                                ,sense->ext.extended.extra_len);
        !          1523:                printf("extra: ");
        !          1524:                while(count < sense->ext.extended.extra_len)
        !          1525:                {
        !          1526:                        printf ("%x ",sense->ext.extended.extra_bytes[count++]);
        !          1527:                }
        !          1528:                printf("\n");
        !          1529:        }
        !          1530:        switch(sense->error_class)
        !          1531:        {
        !          1532:        /***************************************************************\
        !          1533:        * If it's class 7, use the extended stuff and interpret the key *
        !          1534:        \***************************************************************/
        !          1535:        case 7:
        !          1536:        {
        !          1537:                if(sense->ext.extended.eom)
        !          1538:                {
        !          1539:                        st_data[unit].flags |= ST_AT_EOM;
        !          1540:                }
        !          1541: 
        !          1542:                if(sense->ext.extended.filemark)
        !          1543:                {
        !          1544:                        st_data[unit].flags |= ST_AT_FILEMARK;
        !          1545:                }
        !          1546: 
        !          1547:                if(sense->ext.extended.ili)
        !          1548:                {
        !          1549:                        if(sense->valid)
        !          1550:                        {
        !          1551:                                /*******************************\
        !          1552:                                * In all ili cases, note that   *
        !          1553:                                * the resid is non-0 AND not    *
        !          1554:                                * unchanged.                    *
        !          1555:                                \*******************************/
        !          1556:                                xs->resid
        !          1557:                                   = ntohl(*((long *)sense->ext.extended.info));
        !          1558:                                if(xs->bp)
        !          1559:                                {
        !          1560:                                        if(xs->resid < 0)
        !          1561:                                        { /* never on block devices */
        !          1562:                                                /***********************\
        !          1563:                                                * it's only really bad  *
        !          1564:                                                * if we have lost data  *
        !          1565:                                                * (the record was       *
        !          1566:                                                * bigger than the read) *
        !          1567:                                                \***********************/
        !          1568:                                                return(EIO);
        !          1569:                                        }
        !          1570:                                }       
        !          1571:                        }
        !          1572:                        else
        !          1573:                        { /* makes no sense.. complain */
        !          1574:                                printf("BAD length error?");
        !          1575:                        }
        !          1576:                }/* there may be some other error. check the rest */
        !          1577: 
        !          1578:                key=sense->ext.extended.sense_key;
        !          1579:                switch(key)
        !          1580:                {
        !          1581:                case    0x0:
        !          1582:                        return(ESUCCESS);
        !          1583:                case    0x1:
        !          1584:                        if(!silent)
        !          1585:                        {
        !          1586:                                printf("st%d: soft error(corrected) ", unit); 
        !          1587:                                if(sense->valid)
        !          1588:                                {
        !          1589:                                        printf("block no. %d (decimal)\n",
        !          1590:                                        (sense->ext.extended.info[0] <<24)|
        !          1591:                                        (sense->ext.extended.info[1] <<16)|
        !          1592:                                        (sense->ext.extended.info[2] <<8)|
        !          1593:                                        (sense->ext.extended.info[3] ));
        !          1594:                                }
        !          1595:                                else
        !          1596:                                {
        !          1597:                                        printf("\n");
        !          1598:                                }
        !          1599:                        }
        !          1600:                        return(ESUCCESS);
        !          1601:                case    0x2:
        !          1602:                        if(!silent) printf("st%d: not ready\n ", unit); 
        !          1603:                        return(ENODEV);
        !          1604:                case    0x3:
        !          1605:                        if(!silent)
        !          1606:                        {
        !          1607:                                printf("st%d: medium error ", unit); 
        !          1608:                                if(sense->valid)
        !          1609:                                {
        !          1610:                                        printf("block no. %d (decimal)\n",
        !          1611:                                        (sense->ext.extended.info[0] <<24)|
        !          1612:                                        (sense->ext.extended.info[1] <<16)|
        !          1613:                                        (sense->ext.extended.info[2] <<8)|
        !          1614:                                        (sense->ext.extended.info[3] ));
        !          1615:                                }
        !          1616:                                else
        !          1617:                                {
        !          1618:                                        printf("\n");
        !          1619:                                }
        !          1620:                        }
        !          1621:                        return(EIO);
        !          1622:                case    0x4:
        !          1623:                        if(!silent) printf("st%d: non-media hardware failure\n ",
        !          1624:                                unit); 
        !          1625:                        return(EIO);
        !          1626:                case    0x5:
        !          1627:                        if(!silent) printf("st%d: illegal request\n ", unit); 
        !          1628:                        return(EINVAL);
        !          1629:                case    0x6:
        !          1630:                        if(!silent) printf("st%d: Unit attention.\n ", unit); 
        !          1631:                        st_data[unit].flags &= ~(ST_AT_FILEMARK|ST_AT_EOM);
        !          1632:                        st_info_valid[unit] = FALSE;
        !          1633:                        if (st_data[unit].flags & ST_OPEN) /* TEMP!!!! */
        !          1634:                                return(EIO);
        !          1635:                        else
        !          1636:                                return(ESUCCESS);
        !          1637:                case    0x7:
        !          1638:                        if(!silent)
        !          1639:                        {
        !          1640:                                printf("st%d: attempted protection violation "
        !          1641:                                                                , unit); 
        !          1642:                                if(sense->valid)
        !          1643:                                {
        !          1644:                                        printf("block no. %d (decimal)\n",
        !          1645:                                        (sense->ext.extended.info[0] <<24)|
        !          1646:                                        (sense->ext.extended.info[1] <<16)|
        !          1647:                                        (sense->ext.extended.info[2] <<8)|
        !          1648:                                        (sense->ext.extended.info[3] ));
        !          1649:                                }
        !          1650:                                else
        !          1651:                                {
        !          1652:                                        printf("\n");
        !          1653:                                }
        !          1654:                        }
        !          1655:                        return(EACCES);
        !          1656:                case    0x8:
        !          1657:                        if(!silent)
        !          1658:                        {
        !          1659:                                printf("st%d: block wrong state (worm)\n "
        !          1660:                                                        , unit); 
        !          1661:                                if(sense->valid)
        !          1662:                                {
        !          1663:                                        printf("block no. %d (decimal)\n",
        !          1664:                                        (sense->ext.extended.info[0] <<24)|
        !          1665:                                        (sense->ext.extended.info[1] <<16)|
        !          1666:                                        (sense->ext.extended.info[2] <<8)|
        !          1667:                                        (sense->ext.extended.info[3] ));
        !          1668:                                }
        !          1669:                                else
        !          1670:                                {
        !          1671:                                        printf("\n");
        !          1672:                                }
        !          1673:                        }
        !          1674:                        return(EIO);
        !          1675:                case    0x9:
        !          1676:                        if(!silent) printf("st%d: vendor unique\n",
        !          1677:                                unit); 
        !          1678:                        return(EIO);
        !          1679:                case    0xa:
        !          1680:                        if(!silent) printf("st%d: copy aborted\n ",
        !          1681:                                unit); 
        !          1682:                        return(EIO);
        !          1683:                case    0xb:
        !          1684:                        if(!silent) printf("st%d: command aborted\n ",
        !          1685:                                unit); 
        !          1686:                        return(EIO);
        !          1687:                case    0xc:
        !          1688:                        if(!silent)
        !          1689:                        {
        !          1690:                                printf("st%d: search returned\n ", unit); 
        !          1691:                                if(sense->valid)
        !          1692:                                {
        !          1693:                                        printf("block no. %d (decimal)\n",
        !          1694:                                        (sense->ext.extended.info[0] <<24)|
        !          1695:                                        (sense->ext.extended.info[1] <<16)|
        !          1696:                                        (sense->ext.extended.info[2] <<8)|
        !          1697:                                        (sense->ext.extended.info[3] ));
        !          1698:                                }
        !          1699:                                else
        !          1700:                                {
        !          1701:                                        printf("\n");
        !          1702:                                }
        !          1703:                        }
        !          1704:                        return(ESUCCESS);
        !          1705:                case    0xd:
        !          1706:                        if(!silent) printf("st%d: volume overflow\n ",
        !          1707:                                unit); 
        !          1708:                        return(ENOSPC);
        !          1709:                case    0xe:
        !          1710:                        if(!silent)
        !          1711:                        {
        !          1712:                                printf("st%d: verify miscompare\n ", unit); 
        !          1713:                                if(sense->valid)
        !          1714:                                {
        !          1715:                                        printf("block no. %d (decimal)\n",
        !          1716:                                        (sense->ext.extended.info[0] <<24)|
        !          1717:                                        (sense->ext.extended.info[1] <<16)|
        !          1718:                                        (sense->ext.extended.info[2] <<8)|
        !          1719:                                        (sense->ext.extended.info[3] ));
        !          1720:                                }
        !          1721:                                else
        !          1722:                                {
        !          1723:                                        printf("\n");
        !          1724:                                }
        !          1725:                        }
        !          1726:                        return(EIO);
        !          1727:                case    0xf:
        !          1728:                        if(!silent) printf("st%d: unknown error key\n ",
        !          1729:                                unit); 
        !          1730:                        return(EIO);
        !          1731:                }
        !          1732:                break;
        !          1733:        }
        !          1734:        /***************************************************************\
        !          1735:        * If it's NOT class 7, just report it.                          *
        !          1736:        \***************************************************************/
        !          1737:        case 0:
        !          1738:        case 1:
        !          1739:        case 2:
        !          1740:        case 3:
        !          1741:        case 4:
        !          1742:        case 5:
        !          1743:        case 6:
        !          1744:                {
        !          1745:                        if(!silent) printf("st%d: error class %d code %d\n",
        !          1746:                                unit,
        !          1747:                                sense->error_class,
        !          1748:                                sense->error_code);
        !          1749:                if(sense->valid)
        !          1750:                        if(!silent) printf("block no. %d (decimal)\n",
        !          1751:                        (sense->ext.unextended.blockhi <<16),
        !          1752:                        + (sense->ext.unextended.blockmed <<8),
        !          1753:                        + (sense->ext.unextended.blocklow ));
        !          1754:                }
        !          1755:                return(EIO);
        !          1756:        }
        !          1757: }
        !          1758: 
        !          1759: #if defined(OSF)
        !          1760: 
        !          1761: stsize(dev_t dev)
        !          1762: {
        !          1763:     printf("stsize()        -- not implemented\n");
        !          1764:     return(0);
        !          1765: }
        !          1766: 
        !          1767: stdump()
        !          1768: {
        !          1769:     printf("stdump()        -- not implemented\n");
        !          1770:     return(-1);
        !          1771: }
        !          1772: 
        !          1773: #endif /* defined(OSF) */
        !          1774: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.