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

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

unix.superglobalmegacorp.com

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