[BACK]Return to st.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / scsipi

Annotation of src/sys/dev/scsipi/st.c, Revision 1.67

1.67    ! thorpej     1: /*     $NetBSD: st.c,v 1.66 1996/05/05 19:53:01 christos Exp $ */
1.35      cgd         2:
1.1       cgd         3: /*
1.20      mycroft     4:  * Copyright (c) 1994 Charles Hannum.  All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  * 3. All advertising materials mentioning features or use of this software
                     15:  *    must display the following acknowledgement:
                     16:  *     This product includes software developed by Charles Hannum.
                     17:  * 4. The name of the author may not be used to endorse or promote products
                     18:  *    derived from this software without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     21:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     22:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     23:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     24:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     25:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     26:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     27:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     28:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     29:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: /*
                     33:  * Originally written by Julian Elischer (julian@tfs.com)
1.7       deraadt    34:  * for TRW Financial Systems for use under the MACH(2.5) operating system.
1.1       cgd        35:  *
                     36:  * TRW Financial Systems, in accordance with their agreement with Carnegie
                     37:  * Mellon University, makes this software available to CMU to distribute
                     38:  * or use in any manner that they see fit as long as this message is kept with
                     39:  * the software. For this reason TFS also grants any other persons or
                     40:  * organisations permission to use or modify this software.
                     41:  *
                     42:  * TFS supplies this software to be publicly redistributed
                     43:  * on the understanding that TFS is not responsible for the correct
                     44:  * functioning of this software in any circumstances.
1.8       cgd        45:  *
1.20      mycroft    46:  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
                     47:  * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993
1.1       cgd        48:  */
                     49:
                     50: /*
                     51:  * To do:
                     52:  * work out some better way of guessing what a good timeout is going
                     53:  * to be depending on whether we expect to retension or not.
                     54:  */
                     55:
1.17      mycroft    56: #include <sys/types.h>
                     57: #include <sys/param.h>
                     58: #include <sys/systm.h>
1.20      mycroft    59: #include <sys/fcntl.h>
1.17      mycroft    60: #include <sys/errno.h>
1.20      mycroft    61: #include <sys/ioctl.h>
1.17      mycroft    62: #include <sys/malloc.h>
                     63: #include <sys/buf.h>
                     64: #include <sys/proc.h>
                     65: #include <sys/user.h>
                     66: #include <sys/mtio.h>
1.20      mycroft    67: #include <sys/device.h>
1.65      christos   68: #include <sys/conf.h>
1.17      mycroft    69:
                     70: #include <scsi/scsi_all.h>
                     71: #include <scsi/scsi_tape.h>
                     72: #include <scsi/scsiconf.h>
1.1       cgd        73:
1.20      mycroft    74: /* Defines for device specific stuff */
                     75: #define DEF_FIXED_BSIZE  512
                     76: #define        ST_RETRIES      4       /* only on non IO commands */
                     77:
                     78: #define STMODE(z)      ( minor(z)       & 0x03)
                     79: #define STDSTY(z)      ((minor(z) >> 2) & 0x03)
                     80: #define STUNIT(z)      ((minor(z) >> 4)       )
                     81: #define CTLMODE        3
1.1       cgd        82:
1.67    ! thorpej    83: /*
        !            84:  * Maximum density code known.
        !            85:  */
        !            86: #define SCSI_2_MAX_DENSITY_CODE        0x45
        !            87:
1.20      mycroft    88: /*
                     89:  * Define various devices that we know mis-behave in some way,
                     90:  * and note how they are bad, so we can correct for them
                     91:  */
                     92: struct modes {
1.44      mycroft    93:        u_int quirks;                   /* same definitions as in quirkdata */
                     94:        int blksize;
                     95:        u_int8_t density;
1.20      mycroft    96: };
                     97:
1.44      mycroft    98: struct quirkdata {
                     99:        u_int quirks;
                    100: #define        ST_Q_FORCE_BLKSIZE      0x0001
                    101: #define        ST_Q_SENSE_HELP         0x0002  /* must do READ for good MODE SENSE */
                    102: #define        ST_Q_IGNORE_LOADS       0x0004
                    103: #define        ST_Q_BLKSIZE            0x0008  /* variable-block media_blksize > 0 */
1.67    ! thorpej   104: #define        ST_Q_UNIMODAL           0x0010  /* unimode drive rejects mode select */
1.36      mycroft   105:        u_int page_0_size;
                    106: #define        MAX_PAGE_0_SIZE 64
1.20      mycroft   107:        struct modes modes[4];
                    108: };
                    109:
1.44      mycroft   110: struct st_quirk_inquiry_pattern {
                    111:        struct scsi_inquiry_pattern pattern;
                    112:        struct quirkdata quirkdata;
                    113: };
                    114:
                    115: struct st_quirk_inquiry_pattern st_quirk_patterns[] = {
1.59      christos  116:        {{T_SEQUENTIAL, T_REMOV,
                    117:         "        ", "                ", "    "}, {0, 0, {
                    118:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    119:                {ST_Q_FORCE_BLKSIZE, 512, QIC_24},      /* minor 4-7 */
                    120:                {ST_Q_FORCE_BLKSIZE, 0, HALFINCH_1600}, /* minor 8-11 */
                    121:                {ST_Q_FORCE_BLKSIZE, 0, HALFINCH_6250}  /* minor 12-15 */
                    122:        }}},
                    123:        {{T_SEQUENTIAL, T_REMOV,
                    124:         "TANDBERG", " TDC 3600       ", ""},     {0, 12, {
                    125:                {0, 0, 0},                              /* minor 0-3 */
                    126:                {ST_Q_FORCE_BLKSIZE, 0, QIC_525},       /* minor 4-7 */
                    127:                {0, 0, QIC_150},                        /* minor 8-11 */
                    128:                {0, 0, QIC_120}                         /* minor 12-15 */
                    129:        }}},
                    130:        {{T_SEQUENTIAL, T_REMOV,
                    131:         "TANDBERG", " TDC 3800       ", ""},     {0, 0, {
                    132:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    133:                {0, 0, QIC_525},                        /* minor 4-7 */
                    134:                {0, 0, QIC_150},                        /* minor 8-11 */
                    135:                {0, 0, QIC_120}                         /* minor 12-15 */
                    136:        }}},
1.44      mycroft   137:        /*
                    138:         * At least -005 and -007 need this.  I'll assume they all do unless I
                    139:         * hear otherwise.  - mycroft, 31MAR1994
                    140:         */
1.59      christos  141:        {{T_SEQUENTIAL, T_REMOV,
                    142:         "ARCHIVE ", "VIPER 2525 25462", ""},     {0, 0, {
                    143:                {ST_Q_SENSE_HELP, 0, 0},                /* minor 0-3 */
                    144:                {ST_Q_SENSE_HELP, 0, QIC_525},          /* minor 4-7 */
                    145:                {0, 0, QIC_150},                        /* minor 8-11 */
                    146:                {0, 0, QIC_120}                         /* minor 12-15 */
                    147:        }}},
1.44      mycroft   148:        /*
                    149:         * One user reports that this works for his tape drive.  It probably
                    150:         * needs more work.  - mycroft, 09APR1994
                    151:         */
1.59      christos  152:        {{T_SEQUENTIAL, T_REMOV,
                    153:         "SANKYO  ", "CP525           ", ""},    {0, 0, {
                    154:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    155:                {ST_Q_FORCE_BLKSIZE, 512, QIC_525},     /* minor 4-7 */
                    156:                {0, 0, QIC_150},                        /* minor 8-11 */
                    157:                {0, 0, QIC_120}                         /* minor 12-15 */
                    158:        }}},
                    159:        {{T_SEQUENTIAL, T_REMOV,
                    160:         "ANRITSU ", "DMT780          ", ""},     {0, 0, {
                    161:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    162:                {ST_Q_FORCE_BLKSIZE, 512, QIC_525},     /* minor 4-7 */
                    163:                {0, 0, QIC_150},                        /* minor 8-11 */
                    164:                {0, 0, QIC_120}                         /* minor 12-15 */
                    165:        }}},
                    166:        {{T_SEQUENTIAL, T_REMOV,
                    167:         "ARCHIVE ", "VIPER 150  21247", ""},     {0, 12, {
                    168:                {0, 0, 0},                              /* minor 0-3 */
                    169:                {0, 0, QIC_150},                        /* minor 4-7 */
                    170:                {0, 0, QIC_120},                        /* minor 8-11 */
                    171:                {0, 0, QIC_24}                          /* minor 12-15 */
                    172:        }}},
                    173:        {{T_SEQUENTIAL, T_REMOV,
                    174:         "WANGTEK ", "5099ES SCSI", ""},          {0, 0, {
                    175:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    176:                {0, 0, QIC_11},                         /* minor 4-7 */
                    177:                {0, 0, QIC_24},                         /* minor 8-11 */
                    178:                {0, 0, QIC_24}                          /* minor 12-15 */
                    179:        }}},
                    180:        {{T_SEQUENTIAL, T_REMOV,
                    181:         "WANGTEK ", "5150ES SCSI", ""},          {0, 0, {
                    182:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    183:                {0, 0, QIC_24},                         /* minor 4-7 */
                    184:                {0, 0, QIC_120},                        /* minor 8-11 */
                    185:                {0, 0, QIC_150}                         /* minor 12-15 */
                    186:        }}},
                    187:        {{T_SEQUENTIAL, T_REMOV,
                    188:         "WANGTEK ", "5525ES SCSI REV7", ""},     {0, 0, {
                    189:                {0, 0, 0},                              /* minor 0-3 */
                    190:                {ST_Q_BLKSIZE, 0, QIC_525},             /* minor 4-7 */
                    191:                {0, 0, QIC_150},                        /* minor 8-11 */
                    192:                {0, 0, QIC_120}                         /* minor 12-15 */
                    193:        }}},
                    194:        {{T_SEQUENTIAL, T_REMOV,
                    195:         "WangDAT ", "Model 1300      ", ""},     {0, 0, {
                    196:                {0, 0, 0},                              /* minor 0-3 */
                    197:                {ST_Q_FORCE_BLKSIZE, 512, DDS},         /* minor 4-7 */
                    198:                {ST_Q_FORCE_BLKSIZE, 1024, DDS},        /* minor 8-11 */
                    199:                {ST_Q_FORCE_BLKSIZE, 0, DDS}            /* minor 12-15 */
                    200:        }}},
                    201:        {{T_SEQUENTIAL, T_REMOV,
                    202:         "EXABYTE ", "EXB-8200        ", "263H"}, {0, 5, {
                    203:                {0, 0, 0},                              /* minor 0-3 */
                    204:                {0, 0, 0},                              /* minor 4-7 */
                    205:                {0, 0, 0},                              /* minor 8-11 */
                    206:                {0, 0, 0}                               /* minor 12-15 */
                    207:        }}},
1.67    ! thorpej   208:        {{T_SEQUENTIAL, T_REMOV,
        !           209:         "HP      ", "T4000s          ", ""},     {ST_Q_UNIMODAL, 0, {
        !           210:                {0, 0, QIC_3095},                       /* minor 0-3 */
        !           211:                {0, 0, QIC_3095},                       /* minor 4-7 */
        !           212:                {0, 0, QIC_3095},                       /* minor 8-11 */
        !           213:                {0, 0, QIC_3095},                       /* minor 12-15 */
        !           214:        }}},
1.36      mycroft   215: #if 0
1.59      christos  216:        {{T_SEQUENTIAL, T_REMOV,
                    217:         "EXABYTE ", "EXB-8200        ", ""},     {0, 12, {
                    218:                {0, 0, 0},                              /* minor 0-3 */
                    219:                {0, 0, 0},                              /* minor 4-7 */
                    220:                {0, 0, 0},                              /* minor 8-11 */
                    221:                {0, 0, 0}                               /* minor 12-15 */
                    222:        }}},
1.36      mycroft   223: #endif
1.20      mycroft   224: };
                    225:
                    226: #define NOEJECT 0
                    227: #define EJECT 1
                    228:
1.44      mycroft   229: struct st_softc {
1.20      mycroft   230:        struct device sc_dev;
                    231: /*--------------------present operating parameters, flags etc.----------------*/
1.27      mycroft   232:        int flags;              /* see below                          */
1.20      mycroft   233:        u_int quirks;           /* quirks for the open mode           */
1.44      mycroft   234:        int blksize;            /* blksize we are using                */
                    235:        u_int8_t density;       /* present density                    */
1.36      mycroft   236:        u_int page_0_size;      /* size of page 0 data                */
1.44      mycroft   237:        u_int last_dsty;        /* last density opened               */
1.20      mycroft   238: /*--------------------device/scsi parameters----------------------------------*/
                    239:        struct scsi_link *sc_link;      /* our link to the adpter etc.        */
                    240: /*--------------------parameters reported by the device ----------------------*/
1.44      mycroft   241:        int blkmin;             /* min blk size                       */
                    242:        int blkmax;             /* max blk size                       */
                    243:        struct quirkdata *quirkdata;    /* if we have a rogue entry           */
1.20      mycroft   244: /*--------------------parameters reported by the device for this media--------*/
1.44      mycroft   245:        u_long numblks;         /* nominal blocks capacity            */
                    246:        int media_blksize;      /* 0 if not ST_FIXEDBLOCKS            */
                    247:        u_int8_t media_density; /* this is what it said when asked    */
1.20      mycroft   248: /*--------------------quirks for the whole drive------------------------------*/
                    249:        u_int drive_quirks;     /* quirks of this drive               */
1.44      mycroft   250: /*--------------------How we should set up when opening each minor device----*/
1.20      mycroft   251:        struct modes modes[4];  /* plus more for each mode            */
1.44      mycroft   252:        u_int8_t  modeflags[4]; /* flags for the modes                */
1.20      mycroft   253: #define DENSITY_SET_BY_USER    0x01
                    254: #define DENSITY_SET_BY_QUIRK   0x02
                    255: #define BLKSIZE_SET_BY_USER    0x04
                    256: #define BLKSIZE_SET_BY_QUIRK   0x08
                    257: /*--------------------storage for sense data returned by the drive------------*/
1.36      mycroft   258:        u_char sense_data[MAX_PAGE_0_SIZE];     /*
                    259:                                                 * additional sense data needed
                    260:                                                 * for mode sense/select.
                    261:                                                 */
1.20      mycroft   262:        struct buf buf_queue;           /* the queue of pending IO operations */
                    263: };
                    264:
1.59      christos  265:
                    266: int    stmatch __P((struct device *, void *, void *));
                    267: void   stattach __P((struct device *, struct device *, void *));
                    268: void   st_identify_drive __P((struct st_softc *, struct scsi_inquiry_data *));
                    269: void   st_loadquirks __P((struct st_softc *));
                    270: int    st_mount_tape __P((dev_t, int));
                    271: void   st_unmount __P((struct st_softc *, boolean));
                    272: int    st_decide_mode __P((struct st_softc *, boolean));
                    273: void   ststart __P((void *));
                    274: int    st_read __P((struct st_softc *, char *, int, int));
                    275: int    st_read_block_limits __P((struct st_softc *, int));
                    276: int    st_mode_sense __P((struct st_softc *, int));
                    277: int    st_mode_select __P((struct st_softc *, int));
                    278: int    st_space __P((struct st_softc *, int, u_int, int));
                    279: int    st_write_filemarks __P((struct st_softc *, int, int));
                    280: int    st_check_eod __P((struct st_softc *, boolean, int *, int));
                    281: int    st_load __P((struct st_softc *, u_int, int));
                    282: int    st_rewind __P((struct st_softc *, u_int, int));
                    283: int    st_interpret_sense __P((struct scsi_xfer *));
                    284: int    st_touch_tape __P((struct st_softc *));
                    285: int    st_erase __P((struct st_softc *, int full, int flags));
1.20      mycroft   286:
1.63      thorpej   287: struct cfattach st_ca = {
                    288:        sizeof(struct st_softc), stmatch, stattach
                    289: };
                    290:
                    291: struct cfdriver st_cd = {
                    292:        NULL, "st", DV_TAPE
1.20      mycroft   293: };
                    294:
                    295: struct scsi_device st_switch = {
                    296:        st_interpret_sense,
                    297:        ststart,
                    298:        NULL,
                    299:        NULL,
                    300: };
                    301:
1.41      mycroft   302: #define        ST_INFO_VALID   0x0001
                    303: #define        ST_BLOCK_SET    0x0002  /* block size, mode set by ioctl      */
                    304: #define        ST_WRITTEN      0x0004  /* data have been written, EOD needed */
                    305: #define        ST_FIXEDBLOCKS  0x0008
                    306: #define        ST_AT_FILEMARK  0x0010
                    307: #define        ST_EIO_PENDING  0x0020  /* we couldn't report it then (had data) */
                    308: #define        ST_NEW_MOUNT    0x0040  /* still need to decide mode              */
                    309: #define        ST_READONLY     0x0080  /* st_mode_sense says write protected */
                    310: #define        ST_FM_WRITTEN   0x0100  /*
1.20      mycroft   311:                                 * EOF file mark written  -- used with
                    312:                                 * ~ST_WRITTEN to indicate that multiple file
                    313:                                 * marks have been written
                    314:                                 */
1.41      mycroft   315: #define        ST_BLANK_READ   0x0200  /* BLANK CHECK encountered already */
                    316: #define        ST_2FM_AT_EOD   0x0400  /* write 2 file marks at EOD */
                    317: #define        ST_MOUNTED      0x0800  /* Device is presently mounted */
1.57      thorpej   318: #define        ST_DONTBUFFER   0x1000  /* Disable buffering/caching */
1.20      mycroft   319:
                    320: #define        ST_PER_ACTION   (ST_AT_FILEMARK | ST_EIO_PENDING | ST_BLANK_READ)
                    321: #define        ST_PER_MOUNT    (ST_INFO_VALID | ST_BLOCK_SET | ST_WRITTEN | \
1.44      mycroft   322:                         ST_FIXEDBLOCKS | ST_READONLY | ST_FM_WRITTEN | \
                    323:                         ST_2FM_AT_EOD | ST_PER_ACTION)
                    324:
                    325: struct scsi_inquiry_pattern st_patterns[] = {
                    326:        {T_SEQUENTIAL, T_REMOV,
                    327:         "",         "",                 ""},
                    328: };
                    329:
                    330: int
                    331: stmatch(parent, match, aux)
                    332:        struct device *parent;
                    333:        void *match, *aux;
                    334: {
                    335:        struct scsibus_attach_args *sa = aux;
                    336:        int priority;
                    337:
                    338:        (void)scsi_inqmatch(sa->sa_inqbuf,
                    339:            (caddr_t)st_patterns, sizeof(st_patterns)/sizeof(st_patterns[0]),
                    340:            sizeof(st_patterns[0]), &priority);
                    341:        return (priority);
                    342: }
1.1       cgd       343:
1.3       deraadt   344: /*
                    345:  * The routine called by the low level scsi routine when it discovers
                    346:  * A device suitable for this driver
                    347:  */
1.51      mycroft   348: void
1.20      mycroft   349: stattach(parent, self, aux)
                    350:        struct device *parent, *self;
                    351:        void *aux;
1.1       cgd       352: {
1.44      mycroft   353:        struct st_softc *st = (void *)self;
                    354:        struct scsibus_attach_args *sa = aux;
                    355:        struct scsi_link *sc_link = sa->sa_sc_link;
1.1       cgd       356:
1.20      mycroft   357:        SC_DEBUG(sc_link, SDEV_DB2, ("stattach: "));
1.1       cgd       358:
1.20      mycroft   359:        /*
                    360:         * Store information needed to contact our base driver
                    361:         */
                    362:        st->sc_link = sc_link;
1.44      mycroft   363:        sc_link->device = &st_switch;
                    364:        sc_link->device_softc = st;
                    365:        sc_link->openings = 1;
1.3       deraadt   366:
1.20      mycroft   367:        /*
                    368:         * Check if the drive is a known criminal and take
                    369:         * Any steps needed to bring it into line
                    370:         */
1.44      mycroft   371:        st_identify_drive(st, sa->sa_inqbuf);
1.3       deraadt   372:
                    373:        /*
                    374:         * Use the subdriver to request information regarding
                    375:         * the drive. We cannot use interrupts yet, so the
                    376:         * request must specify this.
                    377:         */
1.62      thorpej   378:        printf("\n");
                    379:        printf("%s: %s", st->sc_dev.dv_xname, st->quirkdata ? "rogue, " : "");
1.44      mycroft   380:        if (scsi_test_unit_ready(sc_link,
                    381:            SCSI_AUTOCONF | SCSI_SILENT | SCSI_IGNORE_MEDIA_CHANGE) ||
                    382:            st_mode_sense(st,
                    383:            SCSI_AUTOCONF | SCSI_SILENT | SCSI_IGNORE_MEDIA_CHANGE))
1.20      mycroft   384:                printf("drive empty\n");
                    385:        else {
                    386:                printf("density code 0x%x, ", st->media_density);
1.44      mycroft   387:                if (st->media_blksize > 0)
                    388:                        printf("%d-byte", st->media_blksize);
1.20      mycroft   389:                else
                    390:                        printf("variable");
                    391:                printf(" blocks, write-%s\n",
                    392:                    (st->flags & ST_READONLY) ? "protected" : "enabled");
                    393:        }
1.1       cgd       394:
1.3       deraadt   395:        /*
1.20      mycroft   396:         * Set up the buf queue for this device
1.3       deraadt   397:         */
                    398:        st->buf_queue.b_active = 0;
                    399:        st->buf_queue.b_actf = 0;
1.19      mycroft   400:        st->buf_queue.b_actb = &st->buf_queue.b_actf;
1.20      mycroft   401: }
                    402:
                    403: /*
                    404:  * Use the inquiry routine in 'scsi_base' to get drive info so we can
                    405:  * Further tailor our behaviour.
                    406:  */
                    407: void
1.44      mycroft   408: st_identify_drive(st, inqbuf)
                    409:        struct st_softc *st;
                    410:        struct scsi_inquiry_data *inqbuf;
                    411: {
                    412:        struct st_quirk_inquiry_pattern *finger;
                    413:        int priority;
                    414:
                    415:        finger = (struct st_quirk_inquiry_pattern *)scsi_inqmatch(inqbuf,
                    416:            (caddr_t)st_quirk_patterns,
                    417:            sizeof(st_quirk_patterns)/sizeof(st_quirk_patterns[0]),
                    418:            sizeof(st_quirk_patterns[0]), &priority);
                    419:        if (priority != 0) {
                    420:                st->quirkdata = &finger->quirkdata;
                    421:                st->drive_quirks = finger->quirkdata.quirks;
                    422:                st->quirks = finger->quirkdata.quirks;  /* start value */
                    423:                st->page_0_size = finger->quirkdata.page_0_size;
                    424:                st_loadquirks(st);
1.20      mycroft   425:        }
                    426: }
                    427:
                    428: /*
                    429:  * initialise the subdevices to the default (QUIRK) state.
                    430:  * this will remove any setting made by the system operator or previous
                    431:  * operations.
                    432:  */
                    433: void
                    434: st_loadquirks(st)
1.44      mycroft   435:        struct st_softc *st;
1.20      mycroft   436: {
                    437:        int i;
                    438:        struct  modes *mode;
                    439:        struct  modes *mode2;
                    440:
1.44      mycroft   441:        mode = st->quirkdata->modes;
1.20      mycroft   442:        mode2 = st->modes;
                    443:        for (i = 0; i < 4; i++) {
                    444:                bzero(mode2, sizeof(struct modes));
                    445:                st->modeflags[i] &= ~(BLKSIZE_SET_BY_QUIRK |
                    446:                    DENSITY_SET_BY_QUIRK | BLKSIZE_SET_BY_USER |
                    447:                    DENSITY_SET_BY_USER);
1.44      mycroft   448:                if ((mode->quirks | st->drive_quirks) & ST_Q_FORCE_BLKSIZE) {
                    449:                        mode2->blksize = mode->blksize;
1.20      mycroft   450:                        st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK;
                    451:                }
                    452:                if (mode->density) {
                    453:                        mode2->density = mode->density;
                    454:                        st->modeflags[i] |= DENSITY_SET_BY_QUIRK;
                    455:                }
                    456:                mode++;
                    457:                mode2++;
                    458:        }
1.1       cgd       459: }
                    460:
1.3       deraadt   461: /*
1.20      mycroft   462:  * open the device.
                    463:  */
1.59      christos  464: int
                    465: stopen(dev, flags, mode, p)
1.20      mycroft   466:        dev_t dev;
1.27      mycroft   467:        int flags;
1.59      christos  468:        int mode;
                    469:        struct proc *p;
1.1       cgd       470: {
1.20      mycroft   471:        int unit;
1.59      christos  472:        u_int stmode, dsty;
1.20      mycroft   473:        int error = 0;
1.44      mycroft   474:        struct st_softc *st;
1.20      mycroft   475:        struct scsi_link *sc_link;
1.1       cgd       476:
1.20      mycroft   477:        unit = STUNIT(dev);
1.63      thorpej   478:        if (unit >= st_cd.cd_ndevs)
1.4       deraadt   479:                return ENXIO;
1.63      thorpej   480:        st = st_cd.cd_devs[unit];
1.27      mycroft   481:        if (!st)
1.4       deraadt   482:                return ENXIO;
1.3       deraadt   483:
1.59      christos  484:        stmode = STMODE(dev);
1.41      mycroft   485:        dsty = STDSTY(dev);
1.20      mycroft   486:        sc_link = st->sc_link;
1.41      mycroft   487:
1.20      mycroft   488:        SC_DEBUG(sc_link, SDEV_DB1, ("open: dev=0x%x (unit %d (of %d))\n", dev,
1.63      thorpej   489:            unit, st_cd.cd_ndevs));
1.20      mycroft   490:
1.41      mycroft   491:        /*
                    492:         * Only allow one at a time
                    493:         */
                    494:        if (sc_link->flags & SDEV_OPEN) {
                    495:                printf("%s: already open\n", st->sc_dev.dv_xname);
1.20      mycroft   496:                return EBUSY;
1.41      mycroft   497:        }
1.20      mycroft   498:
1.3       deraadt   499:        /*
1.41      mycroft   500:         * Catch any unit attention errors.
1.3       deraadt   501:         */
1.59      christos  502:        error = scsi_test_unit_ready(sc_link,
                    503:                                     SCSI_IGNORE_MEDIA_CHANGE |
                    504:                                     (stmode == CTLMODE ?
                    505:                                        SCSI_IGNORE_NOT_READY : 0));
1.60      jtk       506:        if (error)
1.44      mycroft   507:                goto bad;
1.20      mycroft   508:
                    509:        sc_link->flags |= SDEV_OPEN;    /* unit attn are now errors */
1.41      mycroft   510:
1.3       deraadt   511:        /*
1.20      mycroft   512:         * If the mode is 3 (e.g. minor = 3,7,11,15)
1.44      mycroft   513:         * then the device has been opened to set defaults
1.20      mycroft   514:         * This mode does NOT ALLOW I/O, only ioctls
1.3       deraadt   515:         */
1.59      christos  516:        if (stmode == CTLMODE)
1.20      mycroft   517:                return 0;
                    518:
1.3       deraadt   519:        /*
1.20      mycroft   520:         * if it's a different mode, or if the media has been
                    521:         * invalidated, unmount the tape from the previous
                    522:         * session but continue with open processing
                    523:         */
                    524:        if (st->last_dsty != dsty || !(sc_link->flags & SDEV_MEDIA_LOADED))
                    525:                st_unmount(st, NOEJECT);
1.3       deraadt   526:
                    527:        /*
1.51      mycroft   528:         * If we are not mounted, then we should start a new
1.20      mycroft   529:         * mount session.
1.3       deraadt   530:         */
1.20      mycroft   531:        if (!(st->flags & ST_MOUNTED)) {
                    532:                st_mount_tape(dev, flags);
                    533:                st->last_dsty = dsty;
1.3       deraadt   534:        }
1.1       cgd       535:
1.3       deraadt   536:        /*
1.20      mycroft   537:         * Make sure that a tape opened in write-only mode will have
                    538:         * file marks written on it when closed, even if not written to.
                    539:         * This is for SUN compatibility
1.3       deraadt   540:         */
1.20      mycroft   541:        if ((flags & O_ACCMODE) == FWRITE)
                    542:                st->flags |= ST_WRITTEN;
                    543:
1.41      mycroft   544:        SC_DEBUG(sc_link, SDEV_DB2, ("open complete\n"));
                    545:        return 0;
1.1       cgd       546:
1.41      mycroft   547: bad:
1.44      mycroft   548:        st_unmount(st, NOEJECT);
1.41      mycroft   549:        sc_link->flags &= ~SDEV_OPEN;
                    550:        return error;
1.20      mycroft   551: }
1.1       cgd       552:
1.20      mycroft   553: /*
                    554:  * close the device.. only called if we are the LAST
                    555:  * occurence of an open device
                    556:  */
1.59      christos  557: int
                    558: stclose(dev, flags, mode, p)
1.20      mycroft   559:        dev_t dev;
1.59      christos  560:        int flags;
                    561:        int mode;
                    562:        struct proc *p;
1.20      mycroft   563: {
1.63      thorpej   564:        struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
1.1       cgd       565:
1.41      mycroft   566:        SC_DEBUG(st->sc_link, SDEV_DB1, ("closing\n"));
1.20      mycroft   567:        if ((st->flags & (ST_WRITTEN | ST_FM_WRITTEN)) == ST_WRITTEN)
                    568:                st_write_filemarks(st, 1, 0);
1.41      mycroft   569:        switch (STMODE(dev)) {
1.20      mycroft   570:        case 0:
                    571:        case 3:         /* for now */
                    572:                st_unmount(st, NOEJECT);
                    573:                break;
                    574:        case 1:
                    575:                /* leave mounted unless media seems to have been removed */
1.41      mycroft   576:                if (!(st->sc_link->flags & SDEV_MEDIA_LOADED))
1.20      mycroft   577:                        st_unmount(st, NOEJECT);
                    578:                break;
                    579:        case 2:
                    580:                st_unmount(st, EJECT);
                    581:                break;
                    582:        }
1.41      mycroft   583:        st->sc_link->flags &= ~SDEV_OPEN;
                    584:
1.20      mycroft   585:        return 0;
                    586: }
1.1       cgd       587:
1.20      mycroft   588: /*
                    589:  * Start a new mount session.
                    590:  * Copy in all the default parameters from the selected device mode.
                    591:  * and try guess any that seem to be defaulted.
                    592:  */
                    593: int
                    594: st_mount_tape(dev, flags)
                    595:        dev_t dev;
1.27      mycroft   596:        int flags;
1.20      mycroft   597: {
                    598:        int unit;
                    599:        u_int mode, dsty;
1.44      mycroft   600:        struct st_softc *st;
1.20      mycroft   601:        struct scsi_link *sc_link;
                    602:        int error = 0;
1.1       cgd       603:
1.20      mycroft   604:        unit = STUNIT(dev);
                    605:        mode = STMODE(dev);
                    606:        dsty = STDSTY(dev);
1.63      thorpej   607:        st = st_cd.cd_devs[unit];
1.20      mycroft   608:        sc_link = st->sc_link;
1.1       cgd       609:
1.20      mycroft   610:        if (st->flags & ST_MOUNTED)
                    611:                return 0;
1.1       cgd       612:
1.20      mycroft   613:        SC_DEBUG(sc_link, SDEV_DB1, ("mounting\n "));
                    614:        st->flags |= ST_NEW_MOUNT;
                    615:        st->quirks = st->drive_quirks | st->modes[dsty].quirks;
                    616:        /*
                    617:         * If the media is new, then make sure we give it a chance to
                    618:         * to do a 'load' instruction.  (We assume it is new.)
                    619:         */
1.59      christos  620:        if ((error = st_load(st, LD_LOAD, 0)) != 0)
1.20      mycroft   621:                return error;
                    622:        /*
                    623:         * Throw another dummy instruction to catch
                    624:         * 'Unit attention' errors. Some drives appear to give
                    625:         * these after doing a Load instruction.
                    626:         * (noteably some DAT drives)
                    627:         */
1.44      mycroft   628:        scsi_test_unit_ready(sc_link, SCSI_SILENT);     /* XXX */
1.1       cgd       629:
1.3       deraadt   630:        /*
1.20      mycroft   631:         * Some devices can't tell you much until they have been
                    632:         * asked to look at the media. This quirk does this.
                    633:         */
1.28      mycroft   634:        if (st->quirks & ST_Q_SENSE_HELP)
1.59      christos  635:                if ((error = st_touch_tape(st)) != 0)
1.20      mycroft   636:                        return error;
                    637:        /*
1.3       deraadt   638:         * Load the physical device parameters
1.20      mycroft   639:         * loads: blkmin, blkmax
                    640:         */
1.59      christos  641:        if ((error = st_read_block_limits(st, 0)) != 0)
1.20      mycroft   642:                return error;
                    643:        /*
                    644:         * Load the media dependent parameters
1.44      mycroft   645:         * includes: media_blksize,media_density,numblks
1.20      mycroft   646:         * As we have a tape in, it should be reflected here.
                    647:         * If not you may need the "quirk" above.
                    648:         */
1.59      christos  649:        if ((error = st_mode_sense(st, 0)) != 0)
1.20      mycroft   650:                return error;
                    651:        /*
                    652:         * If we have gained a permanent density from somewhere,
                    653:         * then use it in preference to the one supplied by
                    654:         * default by the driver.
1.3       deraadt   655:         */
1.20      mycroft   656:        if (st->modeflags[dsty] & (DENSITY_SET_BY_QUIRK | DENSITY_SET_BY_USER))
                    657:                st->density = st->modes[dsty].density;
                    658:        else
                    659:                st->density = st->media_density;
                    660:        /*
                    661:         * If we have gained a permanent blocksize
                    662:         * then use it in preference to the one supplied by
                    663:         * default by the driver.
                    664:         */
                    665:        st->flags &= ~ST_FIXEDBLOCKS;
                    666:        if (st->modeflags[dsty] & (BLKSIZE_SET_BY_QUIRK | BLKSIZE_SET_BY_USER)) {
1.44      mycroft   667:                st->blksize = st->modes[dsty].blksize;
                    668:                if (st->blksize)
1.20      mycroft   669:                        st->flags |= ST_FIXEDBLOCKS;
                    670:        } else {
1.59      christos  671:                if ((error = st_decide_mode(st, FALSE)) != 0)
1.20      mycroft   672:                        return error;
                    673:        }
1.59      christos  674:        if ((error = st_mode_select(st, 0)) != 0) {
1.20      mycroft   675:                printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname);
                    676:                return error;
                    677:        }
1.44      mycroft   678:        scsi_prevent(sc_link, PR_PREVENT,
                    679:            SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY);
1.20      mycroft   680:        st->flags &= ~ST_NEW_MOUNT;
                    681:        st->flags |= ST_MOUNTED;
                    682:        sc_link->flags |= SDEV_MEDIA_LOADED;    /* move earlier? */
1.1       cgd       683:
1.20      mycroft   684:        return 0;
1.1       cgd       685: }
                    686:
1.3       deraadt   687: /*
1.20      mycroft   688:  * End the present mount session.
                    689:  * Rewind, and optionally eject the tape.
                    690:  * Reset various flags to indicate that all new
                    691:  * operations require another mount operation
                    692:  */
                    693: void
                    694: st_unmount(st, eject)
1.44      mycroft   695:        struct st_softc *st;
1.20      mycroft   696:        boolean eject;
1.1       cgd       697: {
1.20      mycroft   698:        struct scsi_link *sc_link = st->sc_link;
                    699:        int nmarks;
                    700:
                    701:        if (!(st->flags & ST_MOUNTED))
                    702:                return;
                    703:        SC_DEBUG(sc_link, SDEV_DB1, ("unmounting\n"));
1.44      mycroft   704:        st_check_eod(st, FALSE, &nmarks, SCSI_IGNORE_NOT_READY);
                    705:        st_rewind(st, 0, SCSI_IGNORE_NOT_READY);
                    706:        scsi_prevent(sc_link, PR_ALLOW,
                    707:            SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_IGNORE_NOT_READY);
1.20      mycroft   708:        if (eject)
1.44      mycroft   709:                st_load(st, LD_UNLOAD, SCSI_IGNORE_NOT_READY);
1.20      mycroft   710:        st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT);
                    711:        sc_link->flags &= ~SDEV_MEDIA_LOADED;
                    712: }
                    713:
                    714: /*
                    715:  * Given all we know about the device, media, mode, 'quirks' and
                    716:  * initial operation, make a decision as to how we should be set
                    717:  * to run (regarding blocking and EOD marks)
                    718:  */
1.51      mycroft   719: int
1.20      mycroft   720: st_decide_mode(st, first_read)
1.44      mycroft   721:        struct st_softc *st;
1.20      mycroft   722:        boolean first_read;
                    723: {
                    724: #ifdef SCSIDEBUG
                    725:        struct scsi_link *sc_link = st->sc_link;
                    726: #endif
                    727:
                    728:        SC_DEBUG(sc_link, SDEV_DB2, ("starting block mode decision\n"));
                    729:
                    730:        /*
                    731:         * If the drive can only handle fixed-length blocks and only at
                    732:         * one size, perhaps we should just do that.
                    733:         */
                    734:        if (st->blkmin && (st->blkmin == st->blkmax)) {
                    735:                st->flags |= ST_FIXEDBLOCKS;
1.44      mycroft   736:                st->blksize = st->blkmin;
1.20      mycroft   737:                SC_DEBUG(sc_link, SDEV_DB3,
                    738:                    ("blkmin == blkmax of %d\n", st->blkmin));
                    739:                goto done;
                    740:        }
                    741:        /*
                    742:         * If the tape density mandates (or even suggests) use of fixed
                    743:         * or variable-length blocks, comply.
                    744:         */
                    745:        switch (st->density) {
                    746:        case HALFINCH_800:
                    747:        case HALFINCH_1600:
                    748:        case HALFINCH_6250:
                    749:        case DDS:
                    750:                st->flags &= ~ST_FIXEDBLOCKS;
1.44      mycroft   751:                st->blksize = 0;
1.20      mycroft   752:                SC_DEBUG(sc_link, SDEV_DB3, ("density specified variable\n"));
                    753:                goto done;
                    754:        case QIC_11:
                    755:        case QIC_24:
                    756:        case QIC_120:
                    757:        case QIC_150:
                    758:        case QIC_525:
                    759:        case QIC_1320:
                    760:                st->flags |= ST_FIXEDBLOCKS;
1.44      mycroft   761:                if (st->media_blksize > 0)
                    762:                        st->blksize = st->media_blksize;
1.20      mycroft   763:                else
1.44      mycroft   764:                        st->blksize = DEF_FIXED_BSIZE;
1.20      mycroft   765:                SC_DEBUG(sc_link, SDEV_DB3, ("density specified fixed\n"));
                    766:                goto done;
                    767:        }
                    768:        /*
                    769:         * If we're about to read the tape, perhaps we should choose
                    770:         * fixed or variable-length blocks and block size according to
                    771:         * what the drive found on the tape.
                    772:         */
                    773:        if (first_read &&
1.44      mycroft   774:            (!(st->quirks & ST_Q_BLKSIZE) || (st->media_blksize == 0) ||
                    775:            (st->media_blksize == DEF_FIXED_BSIZE) ||
                    776:            (st->media_blksize == 1024))) {
                    777:                if (st->media_blksize > 0)
                    778:                        st->flags |= ST_FIXEDBLOCKS;
                    779:                else
1.20      mycroft   780:                        st->flags &= ~ST_FIXEDBLOCKS;
1.44      mycroft   781:                st->blksize = st->media_blksize;
1.20      mycroft   782:                SC_DEBUG(sc_link, SDEV_DB3,
1.44      mycroft   783:                    ("Used media_blksize of %d\n", st->media_blksize));
1.20      mycroft   784:                goto done;
                    785:        }
                    786:        /*
                    787:         * We're getting no hints from any direction.  Choose variable-
                    788:         * length blocks arbitrarily.
                    789:         */
                    790:        st->flags &= ~ST_FIXEDBLOCKS;
1.44      mycroft   791:        st->blksize = 0;
1.20      mycroft   792:        SC_DEBUG(sc_link, SDEV_DB3,
                    793:            ("Give up and default to variable mode\n"));
1.44      mycroft   794:
1.20      mycroft   795: done:
                    796:        /*
                    797:         * Decide whether or not to write two file marks to signify end-
                    798:         * of-data.  Make the decision as a function of density.  If
                    799:         * the decision is not to use a second file mark, the SCSI BLANK
                    800:         * CHECK condition code will be recognized as end-of-data when
                    801:         * first read.
                    802:         * (I think this should be a by-product of fixed/variable..julian)
                    803:         */
                    804:        switch (st->density) {
                    805: /*      case 8 mm:   What is the SCSI density code for 8 mm, anyway? */
                    806:        case QIC_11:
                    807:        case QIC_24:
                    808:        case QIC_120:
                    809:        case QIC_150:
                    810:        case QIC_525:
                    811:        case QIC_1320:
                    812:                st->flags &= ~ST_2FM_AT_EOD;
1.1       cgd       813:                break;
                    814:        default:
1.20      mycroft   815:                st->flags |= ST_2FM_AT_EOD;
1.1       cgd       816:        }
1.3       deraadt   817:        return 0;
1.1       cgd       818: }
                    819:
1.3       deraadt   820: /*
                    821:  * Actually translate the requested transfer into
                    822:  * one the physical driver can understand
                    823:  * The transfer is described by a buf and will include
                    824:  * only one physical transfer.
                    825:  */
1.51      mycroft   826: void
1.20      mycroft   827: ststrategy(bp)
                    828:        struct buf *bp;
1.1       cgd       829: {
1.63      thorpej   830:        struct st_softc *st = st_cd.cd_devs[STUNIT(bp->b_dev)];
1.20      mycroft   831:        struct buf *dp;
1.53      mycroft   832:        int s;
1.1       cgd       833:
1.20      mycroft   834:        SC_DEBUG(st->sc_link, SDEV_DB1,
1.66      christos  835:            ("ststrategy %ld bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));
1.20      mycroft   836:        /*
                    837:         * If it's a null transfer, return immediatly
                    838:         */
1.40      mycroft   839:        if (bp->b_bcount == 0)
1.3       deraadt   840:                goto done;
                    841:        /*
                    842:         * Odd sized request on fixed drives are verboten
                    843:         */
1.20      mycroft   844:        if (st->flags & ST_FIXEDBLOCKS) {
1.44      mycroft   845:                if (bp->b_bcount % st->blksize) {
1.20      mycroft   846:                        printf("%s: bad request, must be multiple of %d\n",
1.44      mycroft   847:                            st->sc_dev.dv_xname, st->blksize);
1.20      mycroft   848:                        bp->b_error = EIO;
                    849:                        goto bad;
                    850:                }
                    851:        }
                    852:        /*
                    853:         * as are out-of-range requests on variable drives.
                    854:         */
1.29      mycroft   855:        else if (bp->b_bcount < st->blkmin ||
                    856:                 (st->blkmax && bp->b_bcount > st->blkmax)) {
1.20      mycroft   857:                printf("%s: bad request, must be between %d and %d\n",
                    858:                    st->sc_dev.dv_xname, st->blkmin, st->blkmax);
1.1       cgd       859:                bp->b_error = EIO;
                    860:                goto bad;
                    861:        }
1.53      mycroft   862:        s = splbio();
1.1       cgd       863:
1.3       deraadt   864:        /*
1.20      mycroft   865:         * Place it in the queue of activities for this tape
                    866:         * at the end (a bit silly because we only have on user..
                    867:         * (but it could fork()))
1.3       deraadt   868:         */
1.20      mycroft   869:        dp = &st->buf_queue;
1.1       cgd       870:        bp->b_actf = NULL;
1.19      mycroft   871:        bp->b_actb = dp->b_actb;
                    872:        *dp->b_actb = bp;
                    873:        dp->b_actb = &bp->b_actf;
1.1       cgd       874:
1.3       deraadt   875:        /*
                    876:         * Tell the device to get going on the transfer if it's
1.20      mycroft   877:         * not doing anything, otherwise just wait for completion
                    878:         * (All a bit silly if we're only allowing 1 open but..)
1.3       deraadt   879:         */
1.40      mycroft   880:        ststart(st);
1.1       cgd       881:
1.53      mycroft   882:        splx(s);
1.1       cgd       883:        return;
                    884: bad:
                    885:        bp->b_flags |= B_ERROR;
                    886: done:
1.3       deraadt   887:        /*
                    888:         * Correctly set the buf to indicate a completed xfer
                    889:         */
1.56      pk        890:        bp->b_resid = bp->b_bcount;
                    891:        biodone(bp);
1.1       cgd       892:        return;
                    893: }
                    894:
1.3       deraadt   895: /*
                    896:  * ststart looks to see if there is a buf waiting for the device
                    897:  * and that the device is not already busy. If both are true,
1.20      mycroft   898:  * It dequeues the buf and creates a scsi command to perform the
                    899:  * transfer required. The transfer request will call scsi_done
1.3       deraadt   900:  * on completion, which will in turn call this routine again
                    901:  * so that the next queued transfer is performed.
                    902:  * The bufs are queued by the strategy routine (ststrategy)
                    903:  *
                    904:  * This routine is also called after other non-queued requests
                    905:  * have been made of the scsi driver, to ensure that the queue
                    906:  * continues to be drained.
1.20      mycroft   907:  * ststart() is called at splbio
                    908:  */
1.59      christos  909: void
                    910: ststart(v)
                    911:        void *v;
1.1       cgd       912: {
1.59      christos  913:        struct st_softc *st = v;
1.20      mycroft   914:        struct scsi_link *sc_link = st->sc_link;
                    915:        register struct buf *bp, *dp;
1.3       deraadt   916:        struct scsi_rw_tape cmd;
1.27      mycroft   917:        int flags;
1.3       deraadt   918:
1.20      mycroft   919:        SC_DEBUG(sc_link, SDEV_DB2, ("ststart "));
1.3       deraadt   920:        /*
                    921:         * See if there is a buf to do and we are not already
                    922:         * doing one
                    923:         */
1.44      mycroft   924:        while (sc_link->openings > 0) {
1.20      mycroft   925:                /* if a special awaits, let it proceed first */
                    926:                if (sc_link->flags & SDEV_WAITING) {
                    927:                        sc_link->flags &= ~SDEV_WAITING;
                    928:                        wakeup((caddr_t)sc_link);
                    929:                        return;
                    930:                }
                    931:
1.61      mycroft   932:                dp = &st->buf_queue;
                    933:                if ((bp = dp->b_actf) == NULL)
                    934:                        return;
1.59      christos  935:                if ((dp = bp->b_actf) != NULL)
1.20      mycroft   936:                        dp->b_actb = bp->b_actb;
                    937:                else
                    938:                        st->buf_queue.b_actb = bp->b_actb;
                    939:                *bp->b_actb = dp;
                    940:
                    941:                /*
                    942:                 * if the device has been unmounted byt the user
                    943:                 * then throw away all requests until done
                    944:                 */
                    945:                if (!(st->flags & ST_MOUNTED) ||
                    946:                    !(sc_link->flags & SDEV_MEDIA_LOADED)) {
                    947:                        /* make sure that one implies the other.. */
                    948:                        sc_link->flags &= ~SDEV_MEDIA_LOADED;
1.33      chopps    949:                        bp->b_flags |= B_ERROR;
                    950:                        bp->b_error = EIO;
                    951:                        biodone(bp);
                    952:                        continue;
1.20      mycroft   953:                }
                    954:                /*
                    955:                 * only FIXEDBLOCK devices have pending operations
                    956:                 */
                    957:                if (st->flags & ST_FIXEDBLOCKS) {
                    958:                        /*
                    959:                         * If we are at a filemark but have not reported it yet
                    960:                         * then we should report it now
                    961:                         */
                    962:                        if (st->flags & ST_AT_FILEMARK) {
                    963:                                if ((bp->b_flags & B_READ) == B_WRITE) {
                    964:                                        /*
                    965:                                         * Handling of ST_AT_FILEMARK in
                    966:                                         * st_space will fill in the right file
                    967:                                         * mark count.
                    968:                                         * Back up over filemark
                    969:                                         */
1.33      chopps    970:                                        if (st_space(st, 0, SP_FILEMARKS, 0)) {
                    971:                                                bp->b_flags |= B_ERROR;
                    972:                                                bp->b_error = EIO;
                    973:                                                biodone(bp);
                    974:                                                continue;
                    975:                                        }
1.20      mycroft   976:                                } else {
                    977:                                        bp->b_resid = bp->b_bcount;
                    978:                                        bp->b_error = 0;
                    979:                                        bp->b_flags &= ~B_ERROR;
                    980:                                        st->flags &= ~ST_AT_FILEMARK;
                    981:                                        biodone(bp);
                    982:                                        continue;       /* seek more work */
                    983:                                }
                    984:                        }
                    985:                        /*
                    986:                         * If we are at EIO (e.g. EOM) but have not reported it
                    987:                         * yet then we should report it now
                    988:                         */
                    989:                        if (st->flags & ST_EIO_PENDING) {
                    990:                                bp->b_resid = bp->b_bcount;
                    991:                                bp->b_error = EIO;
                    992:                                bp->b_flags |= B_ERROR;
                    993:                                st->flags &= ~ST_EIO_PENDING;
                    994:                                biodone(bp);
                    995:                                continue;       /* seek more work */
                    996:                        }
                    997:                }
1.28      mycroft   998:
1.20      mycroft   999:                /*
                   1000:                 *  Fill out the scsi command
                   1001:                 */
                   1002:                bzero(&cmd, sizeof(cmd));
                   1003:                if ((bp->b_flags & B_READ) == B_WRITE) {
1.44      mycroft  1004:                        cmd.opcode = WRITE;
1.20      mycroft  1005:                        st->flags &= ~ST_FM_WRITTEN;
                   1006:                        st->flags |= ST_WRITTEN;
                   1007:                        flags = SCSI_DATA_OUT;
                   1008:                } else {
1.44      mycroft  1009:                        cmd.opcode = READ;
1.20      mycroft  1010:                        flags = SCSI_DATA_IN;
                   1011:                }
1.28      mycroft  1012:
1.20      mycroft  1013:                /*
                   1014:                 * Handle "fixed-block-mode" tape drives by using the
                   1015:                 * block count instead of the length.
                   1016:                 */
                   1017:                if (st->flags & ST_FIXEDBLOCKS) {
1.28      mycroft  1018:                        cmd.byte2 |= SRW_FIXED;
1.64      mycroft  1019:                        _lto3b(bp->b_bcount / st->blksize, cmd.len);
1.28      mycroft  1020:                } else
1.64      mycroft  1021:                        _lto3b(bp->b_bcount, cmd.len);
1.28      mycroft  1022:
1.20      mycroft  1023:                /*
                   1024:                 * go ask the adapter to do all this for us
                   1025:                 */
                   1026:                if (scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd,
1.32      mycroft  1027:                    sizeof(cmd), (u_char *) bp->b_data, bp->b_bcount, 0,
1.44      mycroft  1028:                    100000, bp, flags | SCSI_NOSLEEP))
1.20      mycroft  1029:                        printf("%s: not queued\n", st->sc_dev.dv_xname);
                   1030:        } /* go back and see if we can cram more work in.. */
1.49      mycroft  1031: }
                   1032:
                   1033: int
1.59      christos 1034: stread(dev, uio, iomode)
1.49      mycroft  1035:        dev_t dev;
                   1036:        struct uio *uio;
1.59      christos 1037:        int iomode;
1.49      mycroft  1038: {
1.63      thorpej  1039:        struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
1.49      mycroft  1040:
1.51      mycroft  1041:        return (physio(ststrategy, NULL, dev, B_READ,
                   1042:                       st->sc_link->adapter->scsi_minphys, uio));
1.49      mycroft  1043: }
                   1044:
                   1045: int
1.59      christos 1046: stwrite(dev, uio, iomode)
1.49      mycroft  1047:        dev_t dev;
                   1048:        struct uio *uio;
1.59      christos 1049:        int iomode;
1.49      mycroft  1050: {
1.63      thorpej  1051:        struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
1.49      mycroft  1052:
1.51      mycroft  1053:        return (physio(ststrategy, NULL, dev, B_WRITE,
                   1054:                       st->sc_link->adapter->scsi_minphys, uio));
1.20      mycroft  1055: }
1.1       cgd      1056:
1.20      mycroft  1057: /*
                   1058:  * Perform special action on behalf of the user;
                   1059:  * knows about the internals of this device
                   1060:  */
1.51      mycroft  1061: int
1.44      mycroft  1062: stioctl(dev, cmd, arg, flag, p)
1.20      mycroft  1063:        dev_t dev;
1.39      cgd      1064:        u_long cmd;
1.20      mycroft  1065:        caddr_t arg;
                   1066:        int flag;
1.44      mycroft  1067:        struct proc *p;
1.20      mycroft  1068: {
                   1069:        int error = 0;
                   1070:        int unit;
                   1071:        int number, nmarks, dsty;
1.27      mycroft  1072:        int flags;
1.44      mycroft  1073:        struct st_softc *st;
                   1074:        int hold_blksize;
                   1075:        u_int8_t hold_density;
1.20      mycroft  1076:        struct mtop *mt = (struct mtop *) arg;
1.1       cgd      1077:
1.3       deraadt  1078:        /*
1.20      mycroft  1079:         * Find the device that the user is talking about
1.3       deraadt  1080:         */
1.20      mycroft  1081:        flags = 0;              /* give error messages, act on errors etc. */
                   1082:        unit = STUNIT(dev);
                   1083:        dsty = STDSTY(dev);
1.63      thorpej  1084:        st = st_cd.cd_devs[unit];
1.44      mycroft  1085:        hold_blksize = st->blksize;
1.20      mycroft  1086:        hold_density = st->density;
                   1087:
                   1088:        switch (cmd) {
                   1089:
                   1090:        case MTIOCGET: {
                   1091:                struct mtget *g = (struct mtget *) arg;
                   1092:
                   1093:                SC_DEBUG(st->sc_link, SDEV_DB1, ("[ioctl: get status]\n"));
                   1094:                bzero(g, sizeof(struct mtget));
                   1095:                g->mt_type = 0x7;       /* Ultrix compat *//*? */
1.44      mycroft  1096:                g->mt_blksiz = st->blksize;
1.20      mycroft  1097:                g->mt_density = st->density;
1.44      mycroft  1098:                g->mt_mblksiz[0] = st->modes[0].blksize;
                   1099:                g->mt_mblksiz[1] = st->modes[1].blksize;
                   1100:                g->mt_mblksiz[2] = st->modes[2].blksize;
                   1101:                g->mt_mblksiz[3] = st->modes[3].blksize;
1.20      mycroft  1102:                g->mt_mdensity[0] = st->modes[0].density;
                   1103:                g->mt_mdensity[1] = st->modes[1].density;
                   1104:                g->mt_mdensity[2] = st->modes[2].density;
                   1105:                g->mt_mdensity[3] = st->modes[3].density;
                   1106:                break;
1.1       cgd      1107:        }
1.20      mycroft  1108:        case MTIOCTOP: {
1.1       cgd      1109:
1.20      mycroft  1110:                SC_DEBUG(st->sc_link, SDEV_DB1,
                   1111:                    ("[ioctl: op=0x%x count=0x%x]\n", mt->mt_op, mt->mt_count));
1.1       cgd      1112:
                   1113:                /* compat: in U*x it is a short */
                   1114:                number = mt->mt_count;
1.20      mycroft  1115:                switch ((short) (mt->mt_op)) {
1.1       cgd      1116:                case MTWEOF:    /* write an end-of-file record */
1.20      mycroft  1117:                        error = st_write_filemarks(st, number, flags);
1.1       cgd      1118:                        break;
1.20      mycroft  1119:                case MTBSF:     /* backward space file */
                   1120:                        number = -number;
1.1       cgd      1121:                case MTFSF:     /* forward space file */
1.28      mycroft  1122:                        error = st_check_eod(st, FALSE, &nmarks, flags);
1.20      mycroft  1123:                        if (!error)
                   1124:                                error = st_space(st, number - nmarks,
                   1125:                                    SP_FILEMARKS, flags);
1.1       cgd      1126:                        break;
1.20      mycroft  1127:                case MTBSR:     /* backward space record */
                   1128:                        number = -number;
1.1       cgd      1129:                case MTFSR:     /* forward space record */
1.28      mycroft  1130:                        error = st_check_eod(st, TRUE, &nmarks, flags);
1.20      mycroft  1131:                        if (!error)
                   1132:                                error = st_space(st, number, SP_BLKS, flags);
1.1       cgd      1133:                        break;
                   1134:                case MTREW:     /* rewind */
1.28      mycroft  1135:                        error = st_rewind(st, 0, flags);
1.1       cgd      1136:                        break;
                   1137:                case MTOFFL:    /* rewind and put the drive offline */
1.20      mycroft  1138:                        st_unmount(st, EJECT);
1.1       cgd      1139:                        break;
                   1140:                case MTNOP:     /* no operation, sets status only */
1.22      mycroft  1141:                        break;
1.23      mycroft  1142:                case MTRETEN:   /* retension the tape */
1.28      mycroft  1143:                        error = st_load(st, LD_RETENSION, flags);
1.24      mycroft  1144:                        if (!error)
                   1145:                                error = st_load(st, LD_LOAD, flags);
1.23      mycroft  1146:                        break;
1.22      mycroft  1147:                case MTEOM:     /* forward space to end of media */
1.28      mycroft  1148:                        error = st_check_eod(st, FALSE, &nmarks, flags);
1.22      mycroft  1149:                        if (!error)
                   1150:                                error = st_space(st, 1, SP_EOM, flags);
                   1151:                        break;
1.1       cgd      1152:                case MTCACHE:   /* enable controller cache */
1.57      thorpej  1153:                        st->flags &= ~ST_DONTBUFFER;
                   1154:                        goto try_new_value;
1.1       cgd      1155:                case MTNOCACHE: /* disable controller cache */
1.57      thorpej  1156:                        st->flags |= ST_DONTBUFFER;
                   1157:                        goto try_new_value;
                   1158:                case MTERASE:   /* erase volume */
                   1159:                        error = st_erase(st, number, flags);
1.1       cgd      1160:                        break;
1.20      mycroft  1161:                case MTSETBSIZ: /* Set block size for device */
                   1162: #ifdef NOTYET
                   1163:                        if (!(st->flags & ST_NEW_MOUNT)) {
                   1164:                                uprintf("re-mount tape before changing blocksize");
                   1165:                                error = EINVAL;
                   1166:                                break;
                   1167:                        }
                   1168: #endif
                   1169:                        if (number == 0) {
                   1170:                                st->flags &= ~ST_FIXEDBLOCKS;
                   1171:                        } else {
                   1172:                                if ((st->blkmin || st->blkmax) &&
                   1173:                                    (number < st->blkmin ||
                   1174:                                    number > st->blkmax)) {
                   1175:                                        error = EINVAL;
                   1176:                                        break;
                   1177:                                }
                   1178:                                st->flags |= ST_FIXEDBLOCKS;
                   1179:                        }
1.44      mycroft  1180:                        st->blksize = number;
1.20      mycroft  1181:                        st->flags |= ST_BLOCK_SET;      /*XXX */
                   1182:                        goto try_new_value;
                   1183:
                   1184:                case MTSETDNSTY:        /* Set density for device and mode */
1.57      thorpej  1185:                        if (number > SCSI_2_MAX_DENSITY_CODE) {
1.20      mycroft  1186:                                error = EINVAL;
1.57      thorpej  1187:                                break;
                   1188:                        } else
1.20      mycroft  1189:                                st->density = number;
                   1190:                        goto try_new_value;
                   1191:
1.1       cgd      1192:                default:
1.20      mycroft  1193:                        error = EINVAL;
1.1       cgd      1194:                }
                   1195:                break;
1.20      mycroft  1196:        }
1.1       cgd      1197:        case MTIOCIEOT:
                   1198:        case MTIOCEEOT:
1.20      mycroft  1199:                break;
                   1200:        default:
                   1201:                if (STMODE(dev) == CTLMODE)
1.44      mycroft  1202:                        error = scsi_do_ioctl(st->sc_link, dev, cmd, arg, flag, p);
1.20      mycroft  1203:                else
                   1204:                        error = ENOTTY;
1.1       cgd      1205:                break;
                   1206:        }
1.20      mycroft  1207:        return error;
                   1208: /*-----------------------------*/
                   1209: try_new_value:
                   1210:        /*
                   1211:         * Check that the mode being asked for is aggreeable to the
                   1212:         * drive. If not, put it back the way it was.
                   1213:         */
1.59      christos 1214:        if ((error = st_mode_select(st, 0)) != 0) {/* put it back as it was */
1.20      mycroft  1215:                printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname);
                   1216:                st->density = hold_density;
1.44      mycroft  1217:                st->blksize = hold_blksize;
                   1218:                if (st->blksize)
1.20      mycroft  1219:                        st->flags |= ST_FIXEDBLOCKS;
                   1220:                else
                   1221:                        st->flags &= ~ST_FIXEDBLOCKS;
                   1222:                return error;
                   1223:        }
                   1224:        /*
                   1225:         * As the drive liked it, if we are setting a new default,
                   1226:         * set it into the structures as such.
1.51      mycroft  1227:         *
1.20      mycroft  1228:         * The means for deciding this are not finalised yet
                   1229:         */
                   1230:        if (STMODE(dev) == 0x03) {
                   1231:                /* special mode */
                   1232:                /* XXX */
                   1233:                switch ((short) (mt->mt_op)) {
                   1234:                case MTSETBSIZ:
1.44      mycroft  1235:                        st->modes[dsty].blksize = st->blksize;
1.20      mycroft  1236:                        st->modeflags[dsty] |= BLKSIZE_SET_BY_USER;
                   1237:                        break;
                   1238:                case MTSETDNSTY:
                   1239:                        st->modes[dsty].density = st->density;
                   1240:                        st->modeflags[dsty] |= DENSITY_SET_BY_USER;
                   1241:                        break;
                   1242:                }
                   1243:        }
                   1244:        return 0;
1.1       cgd      1245: }
                   1246:
1.3       deraadt  1247: /*
1.20      mycroft  1248:  * Do a synchronous read.
                   1249:  */
1.51      mycroft  1250: int
1.20      mycroft  1251: st_read(st, buf, size, flags)
1.44      mycroft  1252:        struct st_softc *st;
                   1253:        int size;
1.27      mycroft  1254:        int flags;
1.20      mycroft  1255:        char *buf;
1.1       cgd      1256: {
1.28      mycroft  1257:        struct scsi_rw_tape cmd;
1.1       cgd      1258:
1.20      mycroft  1259:        /*
                   1260:         * If it's a null transfer, return immediatly
                   1261:         */
                   1262:        if (size == 0)
                   1263:                return 0;
1.28      mycroft  1264:        bzero(&cmd, sizeof(cmd));
1.44      mycroft  1265:        cmd.opcode = READ;
1.20      mycroft  1266:        if (st->flags & ST_FIXEDBLOCKS) {
1.28      mycroft  1267:                cmd.byte2 |= SRW_FIXED;
1.64      mycroft  1268:                _lto3b(size / (st->blksize ? st->blksize : DEF_FIXED_BSIZE),
1.28      mycroft  1269:                    cmd.len);
1.20      mycroft  1270:        } else
1.64      mycroft  1271:                _lto3b(size, cmd.len);
1.28      mycroft  1272:        return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
                   1273:            sizeof(cmd), (u_char *) buf, size, 0, 100000, NULL,
1.20      mycroft  1274:            flags | SCSI_DATA_IN);
1.1       cgd      1275: }
                   1276:
1.3       deraadt  1277: /*
                   1278:  * Ask the drive what it's min and max blk sizes are.
1.20      mycroft  1279:  */
1.51      mycroft  1280: int
1.28      mycroft  1281: st_read_block_limits(st, flags)
1.44      mycroft  1282:        struct st_softc *st;
1.27      mycroft  1283:        int flags;
1.1       cgd      1284: {
1.28      mycroft  1285:        struct scsi_block_limits cmd;
                   1286:        struct scsi_block_limits_data block_limits;
                   1287:        struct scsi_link *sc_link = st->sc_link;
1.20      mycroft  1288:        int error;
1.3       deraadt  1289:
                   1290:        /*
                   1291:         * First check if we have it all loaded
                   1292:         */
1.20      mycroft  1293:        if ((sc_link->flags & SDEV_MEDIA_LOADED))
                   1294:                return 0;
1.3       deraadt  1295:
                   1296:        /*
                   1297:         * do a 'Read Block Limits'
                   1298:         */
1.28      mycroft  1299:        bzero(&cmd, sizeof(cmd));
1.44      mycroft  1300:        cmd.opcode = READ_BLOCK_LIMITS;
1.1       cgd      1301:
1.3       deraadt  1302:        /*
1.20      mycroft  1303:         * do the command, update the global values
1.3       deraadt  1304:         */
1.59      christos 1305:        error = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd,
                   1306:                              sizeof(cmd), (u_char *) &block_limits,
                   1307:                              sizeof(block_limits), ST_RETRIES, 5000,
                   1308:                              NULL, flags | SCSI_DATA_IN);
                   1309:        if (error)
1.20      mycroft  1310:                return error;
1.3       deraadt  1311:
1.64      mycroft  1312:        st->blkmin = _2btol(block_limits.min_length);
                   1313:        st->blkmax = _3btol(block_limits.max_length);
1.1       cgd      1314:
1.20      mycroft  1315:        SC_DEBUG(sc_link, SDEV_DB3,
1.44      mycroft  1316:            ("(%d <= blksize <= %d)\n", st->blkmin, st->blkmax));
1.20      mycroft  1317:        return 0;
1.1       cgd      1318: }
1.3       deraadt  1319:
                   1320: /*
                   1321:  * Get the scsi driver to send a full inquiry to the
1.51      mycroft  1322:  * device and use the results to fill out the global
1.3       deraadt  1323:  * parameter structure.
1.20      mycroft  1324:  *
                   1325:  * called from:
                   1326:  * attach
                   1327:  * open
                   1328:  * ioctl (to reset original blksize)
                   1329:  */
1.51      mycroft  1330: int
1.20      mycroft  1331: st_mode_sense(st, flags)
1.44      mycroft  1332:        struct st_softc *st;
1.27      mycroft  1333:        int flags;
1.1       cgd      1334: {
1.20      mycroft  1335:        u_int scsi_sense_len;
                   1336:        int error;
1.28      mycroft  1337:        struct scsi_mode_sense cmd;
1.20      mycroft  1338:        struct scsi_sense {
                   1339:                struct scsi_mode_header header;
1.44      mycroft  1340:                struct scsi_blk_desc blk_desc;
1.36      mycroft  1341:                u_char sense_data[MAX_PAGE_0_SIZE];
1.20      mycroft  1342:        } scsi_sense;
1.36      mycroft  1343:        struct scsi_link *sc_link = st->sc_link;
1.20      mycroft  1344:
1.36      mycroft  1345:        scsi_sense_len = 12 + st->page_0_size;
1.3       deraadt  1346:
                   1347:        /*
1.51      mycroft  1348:         * Set up a mode sense
1.3       deraadt  1349:         */
1.28      mycroft  1350:        bzero(&cmd, sizeof(cmd));
1.44      mycroft  1351:        cmd.opcode = MODE_SENSE;
1.28      mycroft  1352:        cmd.length = scsi_sense_len;
1.3       deraadt  1353:
                   1354:        /*
                   1355:         * do the command, but we don't need the results
1.20      mycroft  1356:         * just print them for our interest's sake, if asked,
                   1357:         * or if we need it as a template for the mode select
                   1358:         * store it away.
                   1359:         */
1.59      christos 1360:        error = scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd,
                   1361:                              sizeof(cmd), (u_char *) &scsi_sense,
                   1362:                              scsi_sense_len, ST_RETRIES, 5000, NULL,
                   1363:                              flags | SCSI_DATA_IN);
                   1364:        if (error)
1.20      mycroft  1365:                return error;
                   1366:
1.36      mycroft  1367:        st->numblks = _3btol(scsi_sense.blk_desc.nblocks);
1.44      mycroft  1368:        st->media_blksize = _3btol(scsi_sense.blk_desc.blklen);
1.36      mycroft  1369:        st->media_density = scsi_sense.blk_desc.density;
                   1370:        if (scsi_sense.header.dev_spec & SMH_DSP_WRITE_PROT)
1.20      mycroft  1371:                st->flags |= ST_READONLY;
                   1372:        SC_DEBUG(sc_link, SDEV_DB3,
                   1373:            ("density code 0x%x, %d-byte blocks, write-%s, ",
1.44      mycroft  1374:            st->media_density, st->media_blksize,
1.20      mycroft  1375:            st->flags & ST_READONLY ? "protected" : "enabled"));
                   1376:        SC_DEBUG(sc_link, SDEV_DB3,
                   1377:            ("%sbuffered\n",
1.36      mycroft  1378:            scsi_sense.header.dev_spec & SMH_DSP_BUFF_MODE ? "" : "un"));
                   1379:        if (st->page_0_size)
                   1380:                bcopy(scsi_sense.sense_data, st->sense_data, st->page_0_size);
1.20      mycroft  1381:        sc_link->flags |= SDEV_MEDIA_LOADED;
                   1382:        return 0;
1.1       cgd      1383: }
                   1384:
1.3       deraadt  1385: /*
1.20      mycroft  1386:  * Send a filled out parameter structure to the drive to
                   1387:  * set it into the desire modes etc.
                   1388:  */
1.51      mycroft  1389: int
1.20      mycroft  1390: st_mode_select(st, flags)
1.44      mycroft  1391:        struct st_softc *st;
1.27      mycroft  1392:        int flags;
1.1       cgd      1393: {
1.36      mycroft  1394:        u_int scsi_select_len;
1.28      mycroft  1395:        struct scsi_mode_select cmd;
1.36      mycroft  1396:        struct scsi_select {
1.20      mycroft  1397:                struct scsi_mode_header header;
1.44      mycroft  1398:                struct scsi_blk_desc blk_desc;
1.36      mycroft  1399:                u_char sense_data[MAX_PAGE_0_SIZE];
                   1400:        } scsi_select;
                   1401:        struct scsi_link *sc_link = st->sc_link;
                   1402:
                   1403:        scsi_select_len = 12 + st->page_0_size;
1.67    ! thorpej  1404:
        !          1405:        /*
        !          1406:         * This quirk deals with drives that have only one valid mode
        !          1407:         * and think this gives them license to reject all mode selects,
        !          1408:         * even if the selected mode is the one that is supported.
        !          1409:         */
        !          1410:        if (st->quirks & ST_Q_UNIMODAL) {
        !          1411:                SC_DEBUG(sc_link, SDEV_DB3,
        !          1412:                    ("not setting density 0x%x blksize 0x%x\n",
        !          1413:                    st->density, st->blksize));
        !          1414:                return 0;
        !          1415:        }
1.3       deraadt  1416:
                   1417:        /*
                   1418:         * Set up for a mode select
                   1419:         */
1.28      mycroft  1420:        bzero(&cmd, sizeof(cmd));
1.44      mycroft  1421:        cmd.opcode = MODE_SELECT;
1.36      mycroft  1422:        cmd.length = scsi_select_len;
1.28      mycroft  1423:
1.36      mycroft  1424:        bzero(&scsi_select, scsi_select_len);
1.44      mycroft  1425:        scsi_select.header.blk_desc_len = sizeof(struct scsi_blk_desc);
1.57      thorpej  1426:        scsi_select.header.dev_spec &= ~SMH_DSP_BUFF_MODE;
1.36      mycroft  1427:        scsi_select.blk_desc.density = st->density;
1.57      thorpej  1428:        if (st->flags & ST_DONTBUFFER)
                   1429:                scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_OFF;
                   1430:        else
                   1431:                scsi_select.header.dev_spec |= SMH_DSP_BUFF_MODE_ON;
1.20      mycroft  1432:        if (st->flags & ST_FIXEDBLOCKS)
1.64      mycroft  1433:                _lto3b(st->blksize, scsi_select.blk_desc.blklen);
1.36      mycroft  1434:        if (st->page_0_size)
                   1435:                bcopy(st->sense_data, scsi_select.sense_data, st->page_0_size);
1.28      mycroft  1436:
1.3       deraadt  1437:        /*
                   1438:         * do the command
                   1439:         */
1.36      mycroft  1440:        return scsi_scsi_cmd(sc_link, (struct scsi_generic *) &cmd,
                   1441:            sizeof(cmd), (u_char *) &scsi_select, scsi_select_len,
                   1442:            ST_RETRIES, 5000, NULL, flags | SCSI_DATA_OUT);
1.57      thorpej  1443: }
                   1444:
                   1445: /*
                   1446:  * issue an erase command
                   1447:  */
                   1448: int
                   1449: st_erase(st, full, flags)
                   1450:        struct st_softc *st;
                   1451:        int full, flags;
                   1452: {
                   1453:        struct scsi_erase cmd;
                   1454:
                   1455:        /*
                   1456:         * Full erase means set LONG bit in erase command, which asks
                   1457:         * the drive to erase the entire unit.  Without this bit, we're
                   1458:         * asking the drive to write an erase gap.
                   1459:         */
                   1460:        bzero(&cmd, sizeof(cmd));
                   1461:        cmd.opcode = ERASE;
                   1462:        if (full)
                   1463:                cmd.byte2 = SE_IMMED|SE_LONG;
                   1464:        else
                   1465:                cmd.byte2 = SE_IMMED;
                   1466:
                   1467:        /*
                   1468:         * XXX We always do this asynchronously, for now.  How long should
                   1469:         * we wait if we want to (eventually) to it synchronously?
                   1470:         */
                   1471:        return (scsi_scsi_cmd(st->sc_link, (struct scsi_generic *)&cmd,
                   1472:            sizeof(cmd), 0, 0, ST_RETRIES, 5000, NULL, flags));
1.1       cgd      1473: }
                   1474:
1.3       deraadt  1475: /*
                   1476:  * skip N blocks/filemarks/seq filemarks/eom
1.20      mycroft  1477:  */
1.51      mycroft  1478: int
1.20      mycroft  1479: st_space(st, number, what, flags)
1.44      mycroft  1480:        struct st_softc *st;
1.20      mycroft  1481:        u_int what;
1.27      mycroft  1482:        int flags;
1.20      mycroft  1483:        int number;
1.1       cgd      1484: {
1.28      mycroft  1485:        struct scsi_space cmd;
1.20      mycroft  1486:        int error;
1.1       cgd      1487:
1.20      mycroft  1488:        switch (what) {
                   1489:        case SP_BLKS:
                   1490:                if (st->flags & ST_PER_ACTION) {
                   1491:                        if (number > 0) {
                   1492:                                st->flags &= ~ST_PER_ACTION;
                   1493:                                return EIO;
                   1494:                        } else if (number < 0) {
                   1495:                                if (st->flags & ST_AT_FILEMARK) {
                   1496:                                        /*
                   1497:                                         * Handling of ST_AT_FILEMARK
                   1498:                                         * in st_space will fill in the
                   1499:                                         * right file mark count.
                   1500:                                         */
                   1501:                                        error = st_space(st, 0, SP_FILEMARKS,
                   1502:                                                flags);
                   1503:                                        if (error)
                   1504:                                                return error;
                   1505:                                }
                   1506:                                if (st->flags & ST_BLANK_READ) {
                   1507:                                        st->flags &= ~ST_BLANK_READ;
                   1508:                                        return EIO;
                   1509:                                }
                   1510:                                st->flags &= ~ST_EIO_PENDING;
                   1511:                        }
                   1512:                }
                   1513:                break;
                   1514:        case SP_FILEMARKS:
                   1515:                if (st->flags & ST_EIO_PENDING) {
                   1516:                        if (number > 0) {
1.22      mycroft  1517:                                /* pretend we just discovered the error */
1.20      mycroft  1518:                                st->flags &= ~ST_EIO_PENDING;
                   1519:                                return EIO;
                   1520:                        } else if (number < 0) {
                   1521:                                /* back away from the error */
                   1522:                                st->flags &= ~ST_EIO_PENDING;
                   1523:                        }
                   1524:                }
                   1525:                if (st->flags & ST_AT_FILEMARK) {
                   1526:                        st->flags &= ~ST_AT_FILEMARK;
                   1527:                        number--;
                   1528:                }
                   1529:                if ((st->flags & ST_BLANK_READ) && (number < 0)) {
                   1530:                        /* back away from unwritten tape */
                   1531:                        st->flags &= ~ST_BLANK_READ;
                   1532:                        number++;       /* XXX dubious */
                   1533:                }
1.22      mycroft  1534:                break;
                   1535:        case SP_EOM:
                   1536:                if (st->flags & ST_EIO_PENDING) {
                   1537:                        /* pretend we just discovered the error */
                   1538:                        st->flags &= ~ST_EIO_PENDING;
                   1539:                        return EIO;
                   1540:                }
                   1541:                if (st->flags & ST_AT_FILEMARK)
                   1542:                        st->flags &= ~ST_AT_FILEMARK;
                   1543:                break;
1.20      mycroft  1544:        }
                   1545:        if (number == 0)
                   1546:                return 0;
1.28      mycroft  1547:
                   1548:        bzero(&cmd, sizeof(cmd));
1.44      mycroft  1549:        cmd.opcode = SPACE;
1.28      mycroft  1550:        cmd.byte2 = what;
1.64      mycroft  1551:        _lto3b(number, cmd.number);
1.28      mycroft  1552:
                   1553:        return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
1.45      mycroft  1554:            sizeof(cmd), 0, 0, 0, 900000, NULL, flags);
1.1       cgd      1555: }
1.3       deraadt  1556:
                   1557: /*
                   1558:  * write N filemarks
1.20      mycroft  1559:  */
1.51      mycroft  1560: int
1.20      mycroft  1561: st_write_filemarks(st, number, flags)
1.44      mycroft  1562:        struct st_softc *st;
1.27      mycroft  1563:        int flags;
1.20      mycroft  1564:        int number;
1.1       cgd      1565: {
1.28      mycroft  1566:        struct scsi_write_filemarks cmd;
1.1       cgd      1567:
1.20      mycroft  1568:        /*
                   1569:         * It's hard to write a negative number of file marks.
                   1570:         * Don't try.
                   1571:         */
                   1572:        if (number < 0)
                   1573:                return EINVAL;
                   1574:        switch (number) {
                   1575:        case 0:         /* really a command to sync the drive's buffers */
                   1576:                break;
                   1577:        case 1:
                   1578:                if (st->flags & ST_FM_WRITTEN)  /* already have one down */
                   1579:                        st->flags &= ~ST_WRITTEN;
                   1580:                else
                   1581:                        st->flags |= ST_FM_WRITTEN;
                   1582:                st->flags &= ~ST_PER_ACTION;
                   1583:                break;
                   1584:        default:
                   1585:                st->flags &= ~(ST_PER_ACTION | ST_WRITTEN);
                   1586:        }
1.28      mycroft  1587:
                   1588:        bzero(&cmd, sizeof(cmd));
1.44      mycroft  1589:        cmd.opcode = WRITE_FILEMARKS;
1.64      mycroft  1590:        _lto3b(number, cmd.number);
1.28      mycroft  1591:
                   1592:        return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
                   1593:            sizeof(cmd), 0, 0, 0, 100000, NULL, flags);
1.1       cgd      1594: }
1.3       deraadt  1595:
                   1596: /*
1.20      mycroft  1597:  * Make sure the right number of file marks is on tape if the
                   1598:  * tape has been written.  If the position argument is true,
                   1599:  * leave the tape positioned where it was originally.
                   1600:  *
                   1601:  * nmarks returns the number of marks to skip (or, if position
                   1602:  * true, which were skipped) to get back original position.
                   1603:  */
1.51      mycroft  1604: int
1.28      mycroft  1605: st_check_eod(st, position, nmarks, flags)
1.44      mycroft  1606:        struct st_softc *st;
1.20      mycroft  1607:        boolean position;
                   1608:        int *nmarks;
1.27      mycroft  1609:        int flags;
1.1       cgd      1610: {
1.20      mycroft  1611:        int error;
1.1       cgd      1612:
1.20      mycroft  1613:        switch (st->flags & (ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD)) {
                   1614:        default:
                   1615:                *nmarks = 0;
                   1616:                return 0;
                   1617:        case ST_WRITTEN:
                   1618:        case ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD:
                   1619:                *nmarks = 1;
                   1620:                break;
                   1621:        case ST_WRITTEN | ST_2FM_AT_EOD:
                   1622:                *nmarks = 2;
1.1       cgd      1623:        }
1.20      mycroft  1624:        error = st_write_filemarks(st, *nmarks, flags);
                   1625:        if (position && !error)
                   1626:                error = st_space(st, -*nmarks, SP_FILEMARKS, flags);
                   1627:        return error;
1.1       cgd      1628: }
1.3       deraadt  1629:
                   1630: /*
1.23      mycroft  1631:  * load/unload/retension
1.20      mycroft  1632:  */
1.51      mycroft  1633: int
1.20      mycroft  1634: st_load(st, type, flags)
1.44      mycroft  1635:        struct st_softc *st;
1.20      mycroft  1636:        u_int type;
1.27      mycroft  1637:        int flags;
1.1       cgd      1638: {
1.28      mycroft  1639:        struct scsi_load cmd;
1.1       cgd      1640:
1.20      mycroft  1641:        if (type != LD_LOAD) {
                   1642:                int error;
                   1643:                int nmarks;
                   1644:
1.28      mycroft  1645:                error = st_check_eod(st, FALSE, &nmarks, flags);
1.20      mycroft  1646:                if (error)
                   1647:                        return error;
1.1       cgd      1648:        }
1.20      mycroft  1649:        if (st->quirks & ST_Q_IGNORE_LOADS)
                   1650:                return 0;
1.28      mycroft  1651:
                   1652:        bzero(&cmd, sizeof(cmd));
1.44      mycroft  1653:        cmd.opcode = LOAD;
1.28      mycroft  1654:        cmd.how = type;
                   1655:
                   1656:        return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
                   1657:            sizeof(cmd), 0, 0, ST_RETRIES, 300000, NULL, flags);
1.1       cgd      1658: }
1.3       deraadt  1659:
                   1660: /*
                   1661:  *  Rewind the device
1.20      mycroft  1662:  */
1.51      mycroft  1663: int
1.28      mycroft  1664: st_rewind(st, immediate, flags)
1.44      mycroft  1665:        struct st_softc *st;
1.28      mycroft  1666:        u_int immediate;
1.27      mycroft  1667:        int flags;
1.1       cgd      1668: {
1.28      mycroft  1669:        struct scsi_rewind cmd;
1.20      mycroft  1670:        int error;
                   1671:        int nmarks;
                   1672:
1.28      mycroft  1673:        error = st_check_eod(st, FALSE, &nmarks, flags);
1.20      mycroft  1674:        if (error)
                   1675:                return error;
                   1676:        st->flags &= ~ST_PER_ACTION;
1.28      mycroft  1677:
                   1678:        bzero(&cmd, sizeof(cmd));
1.44      mycroft  1679:        cmd.opcode = REWIND;
1.28      mycroft  1680:        cmd.byte2 = immediate;
                   1681:
                   1682:        return scsi_scsi_cmd(st->sc_link, (struct scsi_generic *) &cmd,
                   1683:            sizeof(cmd), 0, 0, ST_RETRIES, immediate ? 5000 : 300000, NULL,
1.20      mycroft  1684:            flags);
1.1       cgd      1685: }
1.3       deraadt  1686:
                   1687: /*
                   1688:  * Look at the returned sense and act on the error and detirmine
                   1689:  * The unix error number to pass back... (0 = report no error)
1.20      mycroft  1690:  *                            (-1 = continue processing)
                   1691:  */
1.51      mycroft  1692: int
1.20      mycroft  1693: st_interpret_sense(xs)
                   1694:        struct scsi_xfer *xs;
1.1       cgd      1695: {
1.20      mycroft  1696:        struct scsi_link *sc_link = xs->sc_link;
                   1697:        struct scsi_sense_data *sense = &xs->sense;
                   1698:        struct buf *bp = xs->bp;
1.44      mycroft  1699:        struct st_softc *st = sc_link->device_softc;
                   1700:        u_int8_t key;
1.56      pk       1701:        int32_t info;
1.3       deraadt  1702:
                   1703:        /*
1.20      mycroft  1704:         * Get the sense fields and work out what code
1.3       deraadt  1705:         */
1.64      mycroft  1706:        if (sense->error_code & SSD_ERRCODE_VALID)
                   1707:                info = _4btol(sense->info);
                   1708:        else
1.20      mycroft  1709:                info = xs->datalen;     /* bad choice if fixed blocks */
                   1710:        if ((sense->error_code & SSD_ERRCODE) != 0x70)
                   1711:                return -1;      /* let the generic code handle it */
                   1712:        if (st->flags & ST_FIXEDBLOCKS) {
1.44      mycroft  1713:                xs->resid = info * st->blksize;
1.64      mycroft  1714:                if (sense->flags & SSD_EOM) {
1.20      mycroft  1715:                        st->flags |= ST_EIO_PENDING;
                   1716:                        if (bp)
                   1717:                                bp->b_resid = xs->resid;
                   1718:                }
1.64      mycroft  1719:                if (sense->flags & SSD_FILEMARK) {
1.20      mycroft  1720:                        st->flags |= ST_AT_FILEMARK;
                   1721:                        if (bp)
                   1722:                                bp->b_resid = xs->resid;
                   1723:                }
1.64      mycroft  1724:                if (sense->flags & SSD_ILI) {
1.20      mycroft  1725:                        st->flags |= ST_EIO_PENDING;
                   1726:                        if (bp)
                   1727:                                bp->b_resid = xs->resid;
1.44      mycroft  1728:                        if (sense->error_code & SSD_ERRCODE_VALID &&
                   1729:                            (xs->flags & SCSI_SILENT) == 0)
1.20      mycroft  1730:                                printf("%s: block wrong size, %d blocks residual\n",
                   1731:                                    st->sc_dev.dv_xname, info);
1.3       deraadt  1732:
1.20      mycroft  1733:                        /*
                   1734:                         * This quirk code helps the drive read
                   1735:                         * the first tape block, regardless of
                   1736:                         * format.  That is required for these
                   1737:                         * drives to return proper MODE SENSE
                   1738:                         * information.
                   1739:                         */
1.28      mycroft  1740:                        if ((st->quirks & ST_Q_SENSE_HELP) &&
1.20      mycroft  1741:                            !(sc_link->flags & SDEV_MEDIA_LOADED))
1.44      mycroft  1742:                                st->blksize -= 512;
1.6       mycroft  1743:                }
1.3       deraadt  1744:                /*
1.20      mycroft  1745:                 * If no data was tranfered, do it immediatly
1.3       deraadt  1746:                 */
1.20      mycroft  1747:                if (xs->resid >= xs->datalen) {
                   1748:                        if (st->flags & ST_EIO_PENDING)
                   1749:                                return EIO;
                   1750:                        if (st->flags & ST_AT_FILEMARK) {
                   1751:                                if (bp)
                   1752:                                        bp->b_resid = xs->resid;
                   1753:                                return 0;
                   1754:                        }
                   1755:                }
                   1756:        } else {                /* must be variable mode */
                   1757:                xs->resid = xs->datalen;        /* to be sure */
1.64      mycroft  1758:                if (sense->flags & SSD_EOM)
1.20      mycroft  1759:                        return EIO;
1.64      mycroft  1760:                if (sense->flags & SSD_FILEMARK) {
1.20      mycroft  1761:                        if (bp)
                   1762:                                bp->b_resid = bp->b_bcount;
                   1763:                        return 0;
                   1764:                }
1.64      mycroft  1765:                if (sense->flags & SSD_ILI) {
1.20      mycroft  1766:                        if (info < 0) {
1.3       deraadt  1767:                                /*
1.20      mycroft  1768:                                 * the record was bigger than the read
1.3       deraadt  1769:                                 */
1.44      mycroft  1770:                                if ((xs->flags & SCSI_SILENT) == 0)
1.20      mycroft  1771:                                        printf("%s: %d-byte record too big\n",
                   1772:                                            st->sc_dev.dv_xname,
                   1773:                                            xs->datalen - info);
                   1774:                                return EIO;
                   1775:                        }
                   1776:                        xs->resid = info;
                   1777:                        if (bp)
                   1778:                                bp->b_resid = info;
1.3       deraadt  1779:                }
1.20      mycroft  1780:        }
1.64      mycroft  1781:        key = sense->flags & SSD_KEY;
1.1       cgd      1782:
1.20      mycroft  1783:        if (key == 0x8) {
                   1784:                /*
                   1785:                 * This quirk code helps the drive read the
                   1786:                 * first tape block, regardless of format.  That
                   1787:                 * is required for these drives to return proper
                   1788:                 * MODE SENSE information.
                   1789:                 */
1.28      mycroft  1790:                if ((st->quirks & ST_Q_SENSE_HELP) &&
1.20      mycroft  1791:                    !(sc_link->flags & SDEV_MEDIA_LOADED)) {
                   1792:                        /* still starting */
1.44      mycroft  1793:                        st->blksize -= 512;
1.20      mycroft  1794:                } else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) {
                   1795:                        st->flags |= ST_BLANK_READ;
                   1796:                        xs->resid = xs->datalen;
                   1797:                        if (bp) {
                   1798:                                bp->b_resid = xs->resid;
                   1799:                                /* return an EOF */
1.1       cgd      1800:                        }
1.20      mycroft  1801:                        return 0;
1.1       cgd      1802:                }
                   1803:        }
1.20      mycroft  1804:        return -1;              /* let the default/generic handler handle it */
                   1805: }
                   1806:
                   1807: /*
                   1808:  * The quirk here is that the drive returns some value to st_mode_sense
                   1809:  * incorrectly until the tape has actually passed by the head.
                   1810:  *
                   1811:  * The method is to set the drive to large fixed-block state (user-specified
                   1812:  * density and 1024-byte blocks), then read and rewind to get it to sense the
                   1813:  * tape.  If that doesn't work, try 512-byte fixed blocks.  If that doesn't
                   1814:  * work, as a last resort, try variable- length blocks.  The result will be
                   1815:  * the ability to do an accurate st_mode_sense.
                   1816:  *
                   1817:  * We know we can do a rewind because we just did a load, which implies rewind.
                   1818:  * Rewind seems preferable to space backward if we have a virgin tape.
                   1819:  *
                   1820:  * The rest of the code for this quirk is in ILI processing and BLANK CHECK
                   1821:  * error processing, both part of st_interpret_sense.
                   1822:  */
                   1823: int
                   1824: st_touch_tape(st)
1.44      mycroft  1825:        struct st_softc *st;
1.20      mycroft  1826: {
1.44      mycroft  1827:        char *buf;
                   1828:        int readsize;
1.20      mycroft  1829:        int error;
                   1830:
                   1831:        buf = malloc(1024, M_TEMP, M_NOWAIT);
                   1832:        if (!buf)
                   1833:                return ENOMEM;
                   1834:
1.59      christos 1835:        if ((error = st_mode_sense(st, 0)) != 0)
1.20      mycroft  1836:                goto bad;
1.44      mycroft  1837:        st->blksize = 1024;
1.20      mycroft  1838:        do {
1.44      mycroft  1839:                switch (st->blksize) {
1.20      mycroft  1840:                case 512:
                   1841:                case 1024:
1.44      mycroft  1842:                        readsize = st->blksize;
1.20      mycroft  1843:                        st->flags |= ST_FIXEDBLOCKS;
                   1844:                        break;
                   1845:                default:
1.44      mycroft  1846:                        readsize = 1;
1.20      mycroft  1847:                        st->flags &= ~ST_FIXEDBLOCKS;
                   1848:                }
1.59      christos 1849:                if ((error = st_mode_select(st, 0)) != 0)
1.20      mycroft  1850:                        goto bad;
1.44      mycroft  1851:                st_read(st, buf, readsize, SCSI_SILENT);        /* XXX */
1.59      christos 1852:                if ((error = st_rewind(st, 0, 0)) != 0) {
1.20      mycroft  1853: bad:                   free(buf, M_TEMP);
                   1854:                        return error;
                   1855:                }
1.44      mycroft  1856:        } while (readsize != 1 && readsize > st->blksize);
                   1857:
1.20      mycroft  1858:        free(buf, M_TEMP);
1.3       deraadt  1859:        return 0;
1.31      mycroft  1860: }
                   1861:
                   1862: int
1.48      cgd      1863: stdump(dev, blkno, va, size)
                   1864:        dev_t dev;
                   1865:        daddr_t blkno;
                   1866:        caddr_t va;
                   1867:        size_t size;
1.31      mycroft  1868: {
                   1869:
                   1870:        /* Not implemented. */
1.48      cgd      1871:        return ENXIO;
1.1       cgd      1872: }

CVSweb <webmaster@jp.NetBSD.org>