[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.134.2.8

1.134.2.8! nathanw     1: /*     $NetBSD$ */
1.101     mycroft     2: /*-
                      3:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
                      4:  * All rights reserved.
                      5:  *
                      6:  * This code is derived from software contributed to The NetBSD Foundation
                      7:  * by Charles M. Hannum.
1.20      mycroft     8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
1.101     mycroft    19:  *        This product includes software developed by the NetBSD
                     20:  *        Foundation, Inc. and its contributors.
                     21:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     22:  *    contributors may be used to endorse or promote products derived
                     23:  *    from this software without specific prior written permission.
1.20      mycroft    24:  *
1.101     mycroft    25:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     26:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     27:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     28:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     29:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     30:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     31:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     32:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     33:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     34:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     35:  * POSSIBILITY OF SUCH DAMAGE.
1.20      mycroft    36:  */
                     37:
                     38: /*
                     39:  * Originally written by Julian Elischer (julian@tfs.com)
1.7       deraadt    40:  * for TRW Financial Systems for use under the MACH(2.5) operating system.
1.1       cgd        41:  *
                     42:  * TRW Financial Systems, in accordance with their agreement with Carnegie
                     43:  * Mellon University, makes this software available to CMU to distribute
                     44:  * or use in any manner that they see fit as long as this message is kept with
                     45:  * the software. For this reason TFS also grants any other persons or
                     46:  * organisations permission to use or modify this software.
                     47:  *
                     48:  * TFS supplies this software to be publicly redistributed
                     49:  * on the understanding that TFS is not responsible for the correct
                     50:  * functioning of this software in any circumstances.
1.8       cgd        51:  *
1.20      mycroft    52:  * Ported to run under 386BSD by Julian Elischer (julian@tfs.com) Sept 1992
                     53:  * major changes by Julian Elischer (julian@jules.dialix.oz.au) May 1993
1.95      mjacob     54:  *
                     55:  * A lot of rewhacking done by mjacob (mjacob@nas.nasa.gov).
1.1       cgd        56:  */
1.134.2.3  nathanw    57:
                     58: #include <sys/cdefs.h>
1.134.2.8! nathanw    59: __KERNEL_RCSID(0, "$NetBSD$");
1.74      enami      60:
1.93      mjacob     61: #include "opt_scsi.h"
1.1       cgd        62:
1.17      mycroft    63: #include <sys/param.h>
                     64: #include <sys/systm.h>
1.20      mycroft    65: #include <sys/fcntl.h>
1.17      mycroft    66: #include <sys/errno.h>
1.20      mycroft    67: #include <sys/ioctl.h>
1.17      mycroft    68: #include <sys/malloc.h>
                     69: #include <sys/buf.h>
                     70: #include <sys/proc.h>
                     71: #include <sys/user.h>
                     72: #include <sys/mtio.h>
1.20      mycroft    73: #include <sys/device.h>
1.65      christos   74: #include <sys/conf.h>
1.115     mjacob     75: #include <sys/kernel.h>
1.134.2.4  nathanw    76: #include <sys/vnode.h>
1.17      mycroft    77:
1.73      bouyer     78: #include <dev/scsipi/scsi_all.h>
                     79: #include <dev/scsipi/scsi_tape.h>
1.134.2.1  nathanw    80: #include <dev/scsipi/stvar.h>
1.1       cgd        81:
1.20      mycroft    82: /* Defines for device specific stuff */
                     83: #define DEF_FIXED_BSIZE  512
                     84:
                     85: #define STMODE(z)      ( minor(z)       & 0x03)
                     86: #define STDSTY(z)      ((minor(z) >> 2) & 0x03)
                     87: #define STUNIT(z)      ((minor(z) >> 4)       )
1.134.2.4  nathanw    88: #define STNMINOR       16
1.94      mjacob     89:
                     90: #define NORMAL_MODE    0
                     91: #define NOREW_MODE     1
                     92: #define EJECT_MODE     2
                     93: #define CTRL_MODE      3
1.83      mycroft    94:
                     95: #define        FALSE           0
                     96: #define        TRUE            1
1.1       cgd        97:
1.134.2.1  nathanw    98: #ifndef                ST_MOUNT_DELAY
                     99: #define                ST_MOUNT_DELAY          0
1.115     mjacob    100: #endif
                    101:
1.67      thorpej   102: /*
1.20      mycroft   103:  * Define various devices that we know mis-behave in some way,
                    104:  * and note how they are bad, so we can correct for them
                    105:  */
1.44      mycroft   106:
1.134     jdolecek  107: const struct st_quirk_inquiry_pattern st_quirk_patterns[] = {
1.59      christos  108:        {{T_SEQUENTIAL, T_REMOV,
                    109:         "        ", "                ", "    "}, {0, 0, {
                    110:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    111:                {ST_Q_FORCE_BLKSIZE, 512, QIC_24},      /* minor 4-7 */
                    112:                {ST_Q_FORCE_BLKSIZE, 0, HALFINCH_1600}, /* minor 8-11 */
                    113:                {ST_Q_FORCE_BLKSIZE, 0, HALFINCH_6250}  /* minor 12-15 */
                    114:        }}},
                    115:        {{T_SEQUENTIAL, T_REMOV,
                    116:         "TANDBERG", " TDC 3600       ", ""},     {0, 12, {
                    117:                {0, 0, 0},                              /* minor 0-3 */
                    118:                {ST_Q_FORCE_BLKSIZE, 0, QIC_525},       /* minor 4-7 */
                    119:                {0, 0, QIC_150},                        /* minor 8-11 */
                    120:                {0, 0, QIC_120}                         /* minor 12-15 */
                    121:        }}},
                    122:        {{T_SEQUENTIAL, T_REMOV,
                    123:         "TANDBERG", " TDC 3800       ", ""},     {0, 0, {
1.104     mjacob    124:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    125:                {0, 0, QIC_525},                        /* minor 4-7 */
                    126:                {0, 0, QIC_150},                        /* minor 8-11 */
                    127:                {0, 0, QIC_120}                         /* minor 12-15 */
                    128:        }}},
                    129:        /*
                    130:         * lacking a manual for the 4200, it's not clear what the
                    131:         * specific density codes should be- the device is a 2.5GB
                    132:         * capable QIC drive, those density codes aren't readily
                    133:         * availabel. The 'default' will just have to do.
                    134:         */
                    135:        {{T_SEQUENTIAL, T_REMOV,
                    136:         "TANDBERG", " TDC 4200       ", ""},     {0, 0, {
1.59      christos  137:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    138:                {0, 0, QIC_525},                        /* minor 4-7 */
                    139:                {0, 0, QIC_150},                        /* minor 8-11 */
                    140:                {0, 0, QIC_120}                         /* minor 12-15 */
                    141:        }}},
1.44      mycroft   142:        /*
                    143:         * At least -005 and -007 need this.  I'll assume they all do unless I
                    144:         * hear otherwise.  - mycroft, 31MAR1994
                    145:         */
1.59      christos  146:        {{T_SEQUENTIAL, T_REMOV,
                    147:         "ARCHIVE ", "VIPER 2525 25462", ""},     {0, 0, {
                    148:                {ST_Q_SENSE_HELP, 0, 0},                /* minor 0-3 */
                    149:                {ST_Q_SENSE_HELP, 0, QIC_525},          /* minor 4-7 */
                    150:                {0, 0, QIC_150},                        /* minor 8-11 */
                    151:                {0, 0, QIC_120}                         /* minor 12-15 */
                    152:        }}},
1.44      mycroft   153:        /*
                    154:         * One user reports that this works for his tape drive.  It probably
                    155:         * needs more work.  - mycroft, 09APR1994
                    156:         */
1.59      christos  157:        {{T_SEQUENTIAL, T_REMOV,
                    158:         "SANKYO  ", "CP525           ", ""},    {0, 0, {
                    159:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    160:                {ST_Q_FORCE_BLKSIZE, 512, QIC_525},     /* minor 4-7 */
                    161:                {0, 0, QIC_150},                        /* minor 8-11 */
                    162:                {0, 0, QIC_120}                         /* minor 12-15 */
                    163:        }}},
                    164:        {{T_SEQUENTIAL, T_REMOV,
                    165:         "ANRITSU ", "DMT780          ", ""},     {0, 0, {
                    166:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    167:                {ST_Q_FORCE_BLKSIZE, 512, QIC_525},     /* minor 4-7 */
                    168:                {0, 0, QIC_150},                        /* minor 8-11 */
                    169:                {0, 0, QIC_120}                         /* minor 12-15 */
                    170:        }}},
                    171:        {{T_SEQUENTIAL, T_REMOV,
1.129     pk        172:         "ARCHIVE ", "VIPER 150  21247", ""},     {ST_Q_ERASE_NOIMM, 12, {
1.86      is        173:                {ST_Q_SENSE_HELP, 0, 0},                /* minor 0-3 */
1.59      christos  174:                {0, 0, QIC_150},                        /* minor 4-7 */
                    175:                {0, 0, QIC_120},                        /* minor 8-11 */
                    176:                {0, 0, QIC_24}                          /* minor 12-15 */
                    177:        }}},
                    178:        {{T_SEQUENTIAL, T_REMOV,
1.129     pk        179:         "ARCHIVE ", "VIPER 150  21531", ""},     {ST_Q_ERASE_NOIMM, 12, {
1.88      pk        180:                {ST_Q_SENSE_HELP, 0, 0},                /* minor 0-3 */
                    181:                {0, 0, QIC_150},                        /* minor 4-7 */
                    182:                {0, 0, QIC_120},                        /* minor 8-11 */
                    183:                {0, 0, QIC_24}                          /* minor 12-15 */
                    184:        }}},
                    185:        {{T_SEQUENTIAL, T_REMOV,
1.59      christos  186:         "WANGTEK ", "5099ES SCSI", ""},          {0, 0, {
                    187:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    188:                {0, 0, QIC_11},                         /* minor 4-7 */
                    189:                {0, 0, QIC_24},                         /* minor 8-11 */
                    190:                {0, 0, QIC_24}                          /* minor 12-15 */
                    191:        }}},
                    192:        {{T_SEQUENTIAL, T_REMOV,
                    193:         "WANGTEK ", "5150ES SCSI", ""},          {0, 0, {
                    194:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    195:                {0, 0, QIC_24},                         /* minor 4-7 */
                    196:                {0, 0, QIC_120},                        /* minor 8-11 */
                    197:                {0, 0, QIC_150}                         /* minor 12-15 */
                    198:        }}},
                    199:        {{T_SEQUENTIAL, T_REMOV,
                    200:         "WANGTEK ", "5525ES SCSI REV7", ""},     {0, 0, {
                    201:                {0, 0, 0},                              /* minor 0-3 */
                    202:                {ST_Q_BLKSIZE, 0, QIC_525},             /* minor 4-7 */
                    203:                {0, 0, QIC_150},                        /* minor 8-11 */
                    204:                {0, 0, QIC_120}                         /* minor 12-15 */
                    205:        }}},
                    206:        {{T_SEQUENTIAL, T_REMOV,
                    207:         "WangDAT ", "Model 1300      ", ""},     {0, 0, {
                    208:                {0, 0, 0},                              /* minor 0-3 */
                    209:                {ST_Q_FORCE_BLKSIZE, 512, DDS},         /* minor 4-7 */
                    210:                {ST_Q_FORCE_BLKSIZE, 1024, DDS},        /* minor 8-11 */
                    211:                {ST_Q_FORCE_BLKSIZE, 0, DDS}            /* minor 12-15 */
                    212:        }}},
                    213:        {{T_SEQUENTIAL, T_REMOV,
                    214:         "EXABYTE ", "EXB-8200        ", "263H"}, {0, 5, {
                    215:                {0, 0, 0},                              /* minor 0-3 */
                    216:                {0, 0, 0},                              /* minor 4-7 */
                    217:                {0, 0, 0},                              /* minor 8-11 */
                    218:                {0, 0, 0}                               /* minor 12-15 */
                    219:        }}},
1.67      thorpej   220:        {{T_SEQUENTIAL, T_REMOV,
1.131     pk        221:         "STK",      "9490",             ""},
1.112     mjacob    222:                                {ST_Q_FORCE_BLKSIZE, 0, {
1.90      mjacob    223:                {0, 0, 0},                              /* minor 0-3 */
                    224:                {0, 0, 0},                              /* minor 4-7 */
                    225:                {0, 0, 0},                              /* minor 8-11 */
                    226:                {0, 0, 0}                               /* minor 12-15 */
                    227:        }}},
                    228:        {{T_SEQUENTIAL, T_REMOV,
                    229:         "STK",      "SD-3",             ""},
1.112     mjacob    230:                                {ST_Q_FORCE_BLKSIZE, 0, {
1.90      mjacob    231:                {0, 0, 0},                              /* minor 0-3 */
                    232:                {0, 0, 0},                              /* minor 4-7 */
                    233:                {0, 0, 0},                              /* minor 8-11 */
                    234:                {0, 0, 0}                               /* minor 12-15 */
                    235:        }}},
                    236:        {{T_SEQUENTIAL, T_REMOV,
1.78      mjacob    237:         "IBM",      "03590",            ""},     {ST_Q_IGNORE_LOADS, 0, {
                    238:                {0, 0, 0},                              /* minor 0-3 */
                    239:                {0, 0, 0},                              /* minor 4-7 */
                    240:                {0, 0, 0},                              /* minor 8-11 */
                    241:                {0, 0, 0}                               /* minor 12-15 */
                    242:        }}},
                    243:        {{T_SEQUENTIAL, T_REMOV,
1.67      thorpej   244:         "HP      ", "T4000s          ", ""},     {ST_Q_UNIMODAL, 0, {
                    245:                {0, 0, QIC_3095},                       /* minor 0-3 */
                    246:                {0, 0, QIC_3095},                       /* minor 4-7 */
                    247:                {0, 0, QIC_3095},                       /* minor 8-11 */
                    248:                {0, 0, QIC_3095},                       /* minor 12-15 */
                    249:        }}},
1.36      mycroft   250: #if 0
1.59      christos  251:        {{T_SEQUENTIAL, T_REMOV,
                    252:         "EXABYTE ", "EXB-8200        ", ""},     {0, 12, {
                    253:                {0, 0, 0},                              /* minor 0-3 */
                    254:                {0, 0, 0},                              /* minor 4-7 */
                    255:                {0, 0, 0},                              /* minor 8-11 */
                    256:                {0, 0, 0}                               /* minor 12-15 */
                    257:        }}},
1.36      mycroft   258: #endif
1.116     nisimura  259:        {{T_SEQUENTIAL, T_REMOV,
                    260:         "TEAC    ", "MT-2ST/N50      ", ""},     {ST_Q_IGNORE_LOADS, 0, {
1.134.2.1  nathanw   261:                {0, 0, 0},                              /* minor 0-3 */
                    262:                {0, 0, 0},                              /* minor 4-7 */
                    263:                {0, 0, 0},                              /* minor 8-11 */
                    264:                {0, 0, 0}                               /* minor 12-15 */
1.122     kleink    265:        }}},
                    266:        {{T_SEQUENTIAL, T_REMOV,
                    267:         "OnStream", "ADR50 Drive", ""},          {ST_Q_UNIMODAL, 0, {
1.134.2.1  nathanw   268:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 0-3 */
                    269:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 4-7 */
                    270:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 8-11 */
                    271:                {ST_Q_FORCE_BLKSIZE, 512, 0},           /* minor 12-15 */
1.116     nisimura  272:        }}},
1.125     matt      273:        {{T_SEQUENTIAL, T_REMOV,
1.134.2.4  nathanw   274:         "OnStream DI-30",      "",   "1.0"},  {ST_Q_NOFILEMARKS, 0, {
                    275:                {0, 0, 0},                              /* minor 0-3 */
                    276:                {0, 0, 0},                              /* minor 4-7 */
                    277:                {0, 0, 0},                              /* minor 8-11 */
                    278:                {0, 0, 0}                               /* minor 12-15 */
                    279:        }}},
                    280:        {{T_SEQUENTIAL, T_REMOV,
1.125     matt      281:         "NCR H621", "0-STD-03-46F880 ", ""},     {ST_Q_NOPREVENT, 0, {
1.134.2.1  nathanw   282:                {0, 0, 0},                             /* minor 0-3 */
                    283:                {0, 0, 0},                             /* minor 4-7 */
                    284:                {0, 0, 0},                             /* minor 8-11 */
                    285:                {0, 0, 0}                              /* minor 12-15 */
                    286:        }}},
1.20      mycroft   287: };
                    288:
                    289: #define NOEJECT 0
                    290: #define EJECT 1
                    291:
1.73      bouyer    292: void   st_identify_drive __P((struct st_softc *,
1.76      enami     293:            struct scsipi_inquiry_pattern *));
1.59      christos  294: void   st_loadquirks __P((struct st_softc *));
                    295: int    st_mount_tape __P((dev_t, int));
                    296: void   st_unmount __P((struct st_softc *, boolean));
                    297: int    st_decide_mode __P((struct st_softc *, boolean));
1.134.2.1  nathanw   298: void   ststart __P((struct scsipi_periph *));
1.80      explorer  299: void   stdone __P((struct scsipi_xfer *));
1.59      christos  300: int    st_read __P((struct st_softc *, char *, int, int));
                    301: int    st_space __P((struct st_softc *, int, u_int, int));
                    302: int    st_write_filemarks __P((struct st_softc *, int, int));
                    303: int    st_check_eod __P((struct st_softc *, boolean, int *, int));
                    304: int    st_load __P((struct st_softc *, u_int, int));
                    305: int    st_rewind __P((struct st_softc *, u_int, int));
1.73      bouyer    306: int    st_interpret_sense __P((struct scsipi_xfer *));
1.59      christos  307: int    st_touch_tape __P((struct st_softc *));
                    308: int    st_erase __P((struct st_softc *, int full, int flags));
1.75      mjacob    309: int    st_rdpos __P((struct st_softc *, int, u_int32_t *));
                    310: int    st_setpos __P((struct st_softc *, int, u_int32_t *));
1.20      mycroft   311:
1.134.2.1  nathanw   312: const struct scsipi_periphsw st_switch = {
1.20      mycroft   313:        st_interpret_sense,
                    314:        ststart,
                    315:        NULL,
1.96      mjacob    316:        stdone
1.20      mycroft   317: };
                    318:
1.93      mjacob    319: #if    defined(ST_ENABLE_EARLYWARN)
                    320: #define        ST_INIT_FLAGS   ST_EARLYWARN
                    321: #else
                    322: #define        ST_INIT_FLAGS   0
                    323: #endif
                    324:
1.3       deraadt   325: /*
                    326:  * The routine called by the low level scsi routine when it discovers
                    327:  * A device suitable for this driver
                    328:  */
1.51      mycroft   329: void
1.134.2.1  nathanw   330: stattach(parent, st, aux)
                    331:        struct device *parent;
                    332:        struct st_softc *st;
1.20      mycroft   333:        void *aux;
1.1       cgd       334: {
1.73      bouyer    335:        struct scsipibus_attach_args *sa = aux;
1.134.2.1  nathanw   336:        struct scsipi_periph *periph = sa->sa_periph;
1.1       cgd       337:
1.134.2.1  nathanw   338:        SC_DEBUG(periph, SCSIPI_DB2, ("stattach: "));
1.1       cgd       339:
1.20      mycroft   340:        /*
                    341:         * Store information needed to contact our base driver
                    342:         */
1.134.2.1  nathanw   343:        st->sc_periph = periph;
                    344:        periph->periph_dev = &st->sc_dev;
                    345:        periph->periph_switch = &st_switch;
1.3       deraadt   346:
1.20      mycroft   347:        /*
1.93      mjacob    348:         * Set initial flags
                    349:         */
                    350:
                    351:        st->flags = ST_INIT_FLAGS;
                    352:
                    353:        /*
1.134.2.8! nathanw   354:         * Set up the buf queue for this device
        !           355:         */
        !           356:        bufq_alloc(&st->buf_queue, BUFQ_FCFS);
        !           357:
        !           358:        /*
1.20      mycroft   359:         * Check if the drive is a known criminal and take
                    360:         * Any steps needed to bring it into line
                    361:         */
1.73      bouyer    362:        st_identify_drive(st, &sa->sa_inqbuf);
1.3       deraadt   363:        /*
1.133     soren     364:         * Use the subdriver to request information regarding the drive.
1.3       deraadt   365:         */
1.69      christos  366:        printf("\n");
                    367:        printf("%s: %s", st->sc_dev.dv_xname, st->quirkdata ? "rogue, " : "");
1.134.2.1  nathanw   368:        if (scsipi_test_unit_ready(periph,
1.114     thorpej   369:            XS_CTL_DISCOVERY | XS_CTL_SILENT | XS_CTL_IGNORE_MEDIA_CHANGE) ||
1.134.2.1  nathanw   370:            st->ops(st, ST_OPS_MODESENSE,
1.114     thorpej   371:            XS_CTL_DISCOVERY | XS_CTL_SILENT | XS_CTL_IGNORE_MEDIA_CHANGE))
1.69      christos  372:                printf("drive empty\n");
1.20      mycroft   373:        else {
1.123     soren     374:                printf("density code %d, ", st->media_density);
1.44      mycroft   375:                if (st->media_blksize > 0)
1.69      christos  376:                        printf("%d-byte", st->media_blksize);
1.20      mycroft   377:                else
1.69      christos  378:                        printf("variable");
                    379:                printf(" blocks, write-%s\n",
1.20      mycroft   380:                    (st->flags & ST_READONLY) ? "protected" : "enabled");
                    381:        }
1.1       cgd       382:
1.82      explorer  383: #if NRND > 0
1.110     explorer  384:        rnd_attach_source(&st->rnd_source, st->sc_dev.dv_xname,
                    385:                          RND_TYPE_TAPE, 0);
1.82      explorer  386: #endif
1.20      mycroft   387: }
                    388:
1.134.2.4  nathanw   389: int
                    390: stactivate(self, act)
                    391:        struct device *self;
                    392:        enum devact act;
                    393: {
                    394:        int rv = 0;
                    395:
                    396:        switch (act) {
                    397:        case DVACT_ACTIVATE:
                    398:                rv = EOPNOTSUPP;
                    399:                break;
                    400:
                    401:        case DVACT_DEACTIVATE:
                    402:                /*
                    403:                 * Nothing to do; we key off the device's DVF_ACTIVE.
                    404:                 */
                    405:                break;
                    406:        }
                    407:        return (rv);
                    408: }
                    409:
                    410: int
                    411: stdetach(self, flags)
                    412:        struct device *self;
                    413:        int flags;
                    414: {
                    415:        struct st_softc *st = (struct st_softc *)self;
                    416:        struct buf *bp;
                    417:        int s, bmaj, cmaj, mn;
                    418:
                    419:        /* locate the major number */
                    420:        for (bmaj = 0; bmaj <= nblkdev; bmaj++)
                    421:                if (bdevsw[bmaj].d_open == stopen)
                    422:                        break;
                    423:        for (cmaj = 0; cmaj <= nchrdev; cmaj++)
                    424:                if (cdevsw[cmaj].d_open == stopen)
                    425:                        break;
                    426:
                    427:        s = splbio();
                    428:
                    429:        /* Kill off any queued buffers. */
1.134.2.8! nathanw   430:        while ((bp = BUFQ_GET(&st->buf_queue)) != NULL) {
1.134.2.4  nathanw   431:                bp->b_error = EIO;
                    432:                bp->b_flags |= B_ERROR;
                    433:                bp->b_resid = bp->b_bcount;
                    434:                biodone(bp);
                    435:        }
                    436:
1.134.2.8! nathanw   437:        bufq_free(&st->buf_queue);
        !           438:
1.134.2.4  nathanw   439:        /* Kill off any pending commands. */
                    440:        scsipi_kill_pending(st->sc_periph);
                    441:
                    442:        splx(s);
                    443:
                    444:        /* Nuke the vnodes for any open instances */
                    445:        mn = STUNIT(self->dv_unit);
                    446:        vdevgone(bmaj, mn, mn+STNMINOR-1, VBLK);
                    447:        vdevgone(cmaj, mn, mn+STNMINOR-1, VCHR);
                    448:
                    449:
                    450: #if NRND > 0
                    451:        /* Unhook the entropy source. */
                    452:        rnd_detach_source(&st->rnd_source);
                    453: #endif
                    454:
                    455:        return (0);
                    456: }
                    457:
1.20      mycroft   458: /*
                    459:  * Use the inquiry routine in 'scsi_base' to get drive info so we can
                    460:  * Further tailor our behaviour.
                    461:  */
                    462: void
1.44      mycroft   463: st_identify_drive(st, inqbuf)
                    464:        struct st_softc *st;
1.73      bouyer    465:        struct scsipi_inquiry_pattern *inqbuf;
1.44      mycroft   466: {
                    467:        struct st_quirk_inquiry_pattern *finger;
                    468:        int priority;
                    469:
1.73      bouyer    470:        finger = (struct st_quirk_inquiry_pattern *)scsipi_inqmatch(inqbuf,
1.44      mycroft   471:            (caddr_t)st_quirk_patterns,
1.76      enami     472:            sizeof(st_quirk_patterns) / sizeof(st_quirk_patterns[0]),
1.44      mycroft   473:            sizeof(st_quirk_patterns[0]), &priority);
                    474:        if (priority != 0) {
                    475:                st->quirkdata = &finger->quirkdata;
                    476:                st->drive_quirks = finger->quirkdata.quirks;
                    477:                st->quirks = finger->quirkdata.quirks;  /* start value */
                    478:                st->page_0_size = finger->quirkdata.page_0_size;
                    479:                st_loadquirks(st);
1.20      mycroft   480:        }
                    481: }
                    482:
                    483: /*
                    484:  * initialise the subdevices to the default (QUIRK) state.
                    485:  * this will remove any setting made by the system operator or previous
                    486:  * operations.
                    487:  */
                    488: void
                    489: st_loadquirks(st)
1.44      mycroft   490:        struct st_softc *st;
1.20      mycroft   491: {
                    492:        int i;
                    493:        struct  modes *mode;
                    494:        struct  modes *mode2;
                    495:
1.44      mycroft   496:        mode = st->quirkdata->modes;
1.20      mycroft   497:        mode2 = st->modes;
                    498:        for (i = 0; i < 4; i++) {
1.134.2.2  nathanw   499:                memset(mode2, 0, sizeof(struct modes));
1.20      mycroft   500:                st->modeflags[i] &= ~(BLKSIZE_SET_BY_QUIRK |
                    501:                    DENSITY_SET_BY_QUIRK | BLKSIZE_SET_BY_USER |
                    502:                    DENSITY_SET_BY_USER);
1.44      mycroft   503:                if ((mode->quirks | st->drive_quirks) & ST_Q_FORCE_BLKSIZE) {
                    504:                        mode2->blksize = mode->blksize;
1.20      mycroft   505:                        st->modeflags[i] |= BLKSIZE_SET_BY_QUIRK;
                    506:                }
                    507:                if (mode->density) {
                    508:                        mode2->density = mode->density;
                    509:                        st->modeflags[i] |= DENSITY_SET_BY_QUIRK;
                    510:                }
1.126     pk        511:                mode2->quirks |= mode->quirks;
1.20      mycroft   512:                mode++;
                    513:                mode2++;
                    514:        }
1.1       cgd       515: }
                    516:
1.3       deraadt   517: /*
1.20      mycroft   518:  * open the device.
                    519:  */
1.76      enami     520: int
1.59      christos  521: stopen(dev, flags, mode, p)
1.20      mycroft   522:        dev_t dev;
1.27      mycroft   523:        int flags;
1.59      christos  524:        int mode;
                    525:        struct proc *p;
1.1       cgd       526: {
1.59      christos  527:        u_int stmode, dsty;
1.115     mjacob    528:        int error, sflags, unit, tries, ntries;
1.44      mycroft   529:        struct st_softc *st;
1.134.2.1  nathanw   530:        struct scsipi_periph *periph;
                    531:        struct scsipi_adapter *adapt;
1.1       cgd       532:
1.20      mycroft   533:        unit = STUNIT(dev);
1.63      thorpej   534:        if (unit >= st_cd.cd_ndevs)
1.76      enami     535:                return (ENXIO);
1.63      thorpej   536:        st = st_cd.cd_devs[unit];
1.76      enami     537:        if (st == NULL)
                    538:                return (ENXIO);
1.3       deraadt   539:
1.59      christos  540:        stmode = STMODE(dev);
1.41      mycroft   541:        dsty = STDSTY(dev);
                    542:
1.134.2.1  nathanw   543:        periph = st->sc_periph;
                    544:        adapt = periph->periph_channel->chan_adapter;
                    545:
                    546:        SC_DEBUG(periph, SCSIPI_DB1, ("open: dev=0x%x (unit %d (of %d))\n", dev,
1.63      thorpej   547:            unit, st_cd.cd_ndevs));
1.20      mycroft   548:
1.96      mjacob    549:
1.41      mycroft   550:        /*
                    551:         * Only allow one at a time
                    552:         */
1.134.2.1  nathanw   553:        if (periph->periph_flags & PERIPH_OPEN) {
1.69      christos  554:                printf("%s: already open\n", st->sc_dev.dv_xname);
1.76      enami     555:                return (EBUSY);
1.41      mycroft   556:        }
1.20      mycroft   557:
1.134.2.1  nathanw   558:        if ((error = scsipi_adapter_addref(adapt)) != 0)
1.106     thorpej   559:                return (error);
                    560:
1.3       deraadt   561:        /*
1.96      mjacob    562:         * clear any latched errors.
                    563:         */
                    564:        st->mt_resid = 0;
                    565:        st->mt_erreg = 0;
1.115     mjacob    566:        st->asc = 0;
                    567:        st->ascq = 0;
                    568:
                    569:        /*
                    570:         * Catch any unit attention errors. Be silent about this
                    571:         * unless we're already mounted. We ignore media change
                    572:         * if we're in control mode or not mounted yet.
                    573:         */
                    574:        if ((st->flags & ST_MOUNTED) == 0 || stmode == CTRL_MODE) {
1.134.2.1  nathanw   575: #ifdef SCSIDEBUG
1.115     mjacob    576:                sflags = XS_CTL_IGNORE_MEDIA_CHANGE;
                    577: #else
                    578:                sflags = XS_CTL_SILENT|XS_CTL_IGNORE_MEDIA_CHANGE;
                    579: #endif
                    580:        } else
                    581:                sflags = 0;
1.134.2.1  nathanw   582:
1.96      mjacob    583:        /*
1.115     mjacob    584:         * If we're already mounted or we aren't configured for
                    585:         * a mount delay, only try a test unit ready once. Otherwise,
                    586:         * try up to ST_MOUNT_DELAY times with a rest interval of
                    587:         * one second between each try.
1.3       deraadt   588:         */
1.134.2.1  nathanw   589:
1.115     mjacob    590:        if ((st->flags & ST_MOUNTED) || ST_MOUNT_DELAY == 0) {
                    591:                ntries = 1;
                    592:        } else {
                    593:                ntries = ST_MOUNT_DELAY;
1.96      mjacob    594:        }
1.115     mjacob    595:
                    596:        for (error = tries = 0; tries < ntries; tries++) {
                    597:                int slpintr, oflags;
                    598:
                    599:                /*
                    600:                 * If we had no error, or we're opening the control mode
                    601:                 * device, we jump out right away.
                    602:                 */
                    603:
1.134.2.1  nathanw   604:                error = scsipi_test_unit_ready(periph, sflags);
1.115     mjacob    605:                if (error == 0 || stmode == CTRL_MODE) {
                    606:                        break;
                    607:                }
                    608:
                    609:                /*
                    610:                 * We had an error.
                    611:                 *
                    612:                 * If we're already mounted or we aren't configured for
                    613:                 * a mount delay, or the error isn't a NOT READY error,
                    614:                 * skip to the error exit now.
                    615:                 */
                    616:                if ((st->flags & ST_MOUNTED) || ST_MOUNT_DELAY == 0 ||
                    617:                    (st->mt_key != SKEY_NOT_READY)) {
                    618:                        goto bad;
                    619:                }
                    620:
                    621:                /*
                    622:                 * clear any latched errors.
                    623:                 */
                    624:                st->mt_resid = 0;
                    625:                st->mt_erreg = 0;
                    626:                st->asc = 0;
                    627:                st->ascq = 0;
                    628:
                    629:                /*
                    630:                 * Fake that we have the device open so
                    631:                 * we block other apps from getting in.
                    632:                 */
                    633:
1.134.2.1  nathanw   634:                oflags = periph->periph_flags;
                    635:                periph->periph_flags |= PERIPH_OPEN;
1.115     mjacob    636:
                    637:                slpintr = tsleep(&lbolt, PUSER|PCATCH, "stload", 0);
                    638:
1.134.2.1  nathanw   639:                periph->periph_flags = oflags;  /* restore flags */
1.115     mjacob    640:                if (slpintr) {
                    641:                        goto bad;
                    642:                }
1.134.2.1  nathanw   643:        }
1.115     mjacob    644:
1.41      mycroft   645:
1.3       deraadt   646:        /*
1.96      mjacob    647:         * If the mode is 3 (e.g. minor = 3,7,11,15) then the device has
                    648:         * been opened to set defaults and perform other, usually non-I/O
                    649:         * related, operations. In this case, do a quick check to see
                    650:         * whether the unit actually had a tape loaded (this will be known
                    651:         * as to whether or not we got a NOT READY for the above
                    652:         * unit attention). If a tape is there, go do a mount sequence.
1.3       deraadt   653:         */
1.115     mjacob    654:        if (stmode == CTRL_MODE && st->mt_key == SKEY_NOT_READY) {
1.134.2.1  nathanw   655:                periph->periph_flags |= PERIPH_OPEN;
1.76      enami     656:                return (0);
1.94      mjacob    657:        }
1.20      mycroft   658:
1.3       deraadt   659:        /*
1.115     mjacob    660:         * If we get this far and had an error set, that means we failed
                    661:         * to pass the 'test unit ready' test for the non-controlmode device,
                    662:         * so we bounce the open.
                    663:         */
1.134.2.1  nathanw   664:
1.115     mjacob    665:        if (error)
                    666:                return (error);
1.134.2.1  nathanw   667:
1.115     mjacob    668:        /*
                    669:         * Else, we're now committed to saying we're open.
                    670:         */
1.134.2.1  nathanw   671:
                    672:        periph->periph_flags |= PERIPH_OPEN; /* unit attn are now errors */
                    673:
1.115     mjacob    674:        /*
1.96      mjacob    675:         * If it's a different mode, or if the media has been
1.20      mycroft   676:         * invalidated, unmount the tape from the previous
                    677:         * session but continue with open processing
                    678:         */
1.134.2.1  nathanw   679:        if (st->last_dsty != dsty ||
                    680:            (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)
1.20      mycroft   681:                st_unmount(st, NOEJECT);
1.3       deraadt   682:
                    683:        /*
1.51      mycroft   684:         * If we are not mounted, then we should start a new
1.20      mycroft   685:         * mount session.
1.3       deraadt   686:         */
1.20      mycroft   687:        if (!(st->flags & ST_MOUNTED)) {
1.130     pk        688:                if ((error = st_mount_tape(dev, flags)) != 0)
                    689:                        goto bad;
1.20      mycroft   690:                st->last_dsty = dsty;
1.3       deraadt   691:        }
1.134.2.6  nathanw   692:        if (!(st->quirks & ST_Q_NOPREVENT)) {
                    693:                scsipi_prevent(periph, PR_PREVENT,
                    694:                    XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_NOT_READY);
                    695:        }
1.1       cgd       696:
1.134.2.1  nathanw   697:        SC_DEBUG(periph, SCSIPI_DB2, ("open complete\n"));
1.76      enami     698:        return (0);
1.1       cgd       699:
1.41      mycroft   700: bad:
1.44      mycroft   701:        st_unmount(st, NOEJECT);
1.134.2.1  nathanw   702:        scsipi_adapter_delref(adapt);
                    703:        periph->periph_flags &= ~PERIPH_OPEN;
1.76      enami     704:        return (error);
1.20      mycroft   705: }
1.1       cgd       706:
1.20      mycroft   707: /*
                    708:  * close the device.. only called if we are the LAST
                    709:  * occurence of an open device
                    710:  */
1.76      enami     711: int
1.59      christos  712: stclose(dev, flags, mode, p)
1.20      mycroft   713:        dev_t dev;
1.59      christos  714:        int flags;
                    715:        int mode;
                    716:        struct proc *p;
1.20      mycroft   717: {
1.97      mjacob    718:        int stxx, error = 0;
1.63      thorpej   719:        struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
1.134.2.1  nathanw   720:        struct scsipi_periph *periph = st->sc_periph;
                    721:        struct scsipi_adapter *adapt = periph->periph_channel->chan_adapter;
1.1       cgd       722:
1.134.2.1  nathanw   723:        SC_DEBUG(st->sc_periph, SCSIPI_DB1, ("closing\n"));
1.96      mjacob    724:
                    725:        /*
                    726:         * Make sure that a tape opened in write-only mode will have
                    727:         * file marks written on it when closed, even if not written to.
                    728:         *
                    729:         * This is for SUN compatibility. Actually, the Sun way of
                    730:         * things is to:
                    731:         *
                    732:         *      only write filemarks if there are fmks to be written and
                    733:         *              - open for write (possibly read/write)
                    734:         *              - the last operation was a write
                    735:         *      or:
                    736:         *              - opened for wronly
                    737:         *              - no data was written (including filemarks)
                    738:         */
                    739:
                    740:        stxx = st->flags & (ST_WRITTEN | ST_FM_WRITTEN);
1.99      mjacob    741:        if (((flags & FWRITE) && stxx == ST_WRITTEN) ||
                    742:            ((flags & O_ACCMODE) == FWRITE && stxx == 0)) {
                    743:                int nm;
                    744:                error = st_check_eod(st, FALSE, &nm, 0);
                    745:        }
                    746:
1.134.2.6  nathanw   747:        /*
                    748:         * Allow robots to eject tape if needed.
                    749:         */
                    750:        scsipi_prevent(periph, PR_ALLOW,
                    751:            XS_CTL_IGNORE_ILLEGAL_REQUEST | XS_CTL_IGNORE_NOT_READY);
                    752:
1.41      mycroft   753:        switch (STMODE(dev)) {
1.94      mjacob    754:        case NORMAL_MODE:
1.20      mycroft   755:                st_unmount(st, NOEJECT);
                    756:                break;
1.94      mjacob    757:        case NOREW_MODE:
1.96      mjacob    758:        case CTRL_MODE:
1.99      mjacob    759:                /*
                    760:                 * Leave mounted unless media seems to have been removed.
                    761:                 *
                    762:                 * Otherwise, if we're to terminate a tape with more than one
                    763:                 * filemark [ and because we're not rewinding here ], backspace
                    764:                 * one filemark so that later appends will see an unbroken
                    765:                 * sequence of:
                    766:                 *
                    767:                 *      file - FMK - file - FMK ... file - FMK FMK (EOM)
                    768:                 */
1.134.2.1  nathanw   769:                if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
1.20      mycroft   770:                        st_unmount(st, NOEJECT);
1.99      mjacob    771:                } else if (error == 0) {
                    772:                        /*
                    773:                         * ST_WRITTEN was preserved from above.
                    774:                         *
                    775:                         * All we need to know here is:
                    776:                         *
                    777:                         *      Were we writing this tape and was the last
                    778:                         *      operation a write?
                    779:                         *
                    780:                         *      Are there supposed to be 2FM at EOD?
1.131     pk        781:                         *
1.99      mjacob    782:                         * If both statements are true, then we backspace
                    783:                         * one filemark.
                    784:                         */
                    785:                        stxx |= (st->flags & ST_2FM_AT_EOD);
                    786:                        if ((flags & FWRITE) != 0 &&
                    787:                            (stxx == (ST_2FM_AT_EOD|ST_WRITTEN))) {
                    788:                                error = st_space(st, -1, SP_FILEMARKS, 0);
                    789:                        }
                    790:                }
1.20      mycroft   791:                break;
1.94      mjacob    792:        case EJECT_MODE:
1.20      mycroft   793:                st_unmount(st, EJECT);
                    794:                break;
                    795:        }
1.107     thorpej   796:
1.134.2.1  nathanw   797:        scsipi_wait_drain(periph);
1.106     thorpej   798:
1.134.2.1  nathanw   799:        scsipi_adapter_delref(adapt);
                    800:        periph->periph_flags &= ~PERIPH_OPEN;
1.41      mycroft   801:
1.97      mjacob    802:        return (error);
1.20      mycroft   803: }
1.1       cgd       804:
1.20      mycroft   805: /*
                    806:  * Start a new mount session.
                    807:  * Copy in all the default parameters from the selected device mode.
                    808:  * and try guess any that seem to be defaulted.
                    809:  */
                    810: int
                    811: st_mount_tape(dev, flags)
                    812:        dev_t dev;
1.27      mycroft   813:        int flags;
1.20      mycroft   814: {
                    815:        int unit;
1.94      mjacob    816:        u_int dsty;
1.44      mycroft   817:        struct st_softc *st;
1.134.2.1  nathanw   818:        struct scsipi_periph *periph;
1.20      mycroft   819:        int error = 0;
1.1       cgd       820:
1.20      mycroft   821:        unit = STUNIT(dev);
                    822:        dsty = STDSTY(dev);
1.63      thorpej   823:        st = st_cd.cd_devs[unit];
1.134.2.1  nathanw   824:        periph = st->sc_periph;
1.1       cgd       825:
1.20      mycroft   826:        if (st->flags & ST_MOUNTED)
1.76      enami     827:                return (0);
1.1       cgd       828:
1.134.2.1  nathanw   829:        SC_DEBUG(periph, SCSIPI_DB1, ("mounting\n "));
1.20      mycroft   830:        st->flags |= ST_NEW_MOUNT;
                    831:        st->quirks = st->drive_quirks | st->modes[dsty].quirks;
                    832:        /*
                    833:         * If the media is new, then make sure we give it a chance to
                    834:         * to do a 'load' instruction.  (We assume it is new.)
                    835:         */
1.115     mjacob    836:        if ((error = st_load(st, LD_LOAD, XS_CTL_SILENT)) != 0)
1.76      enami     837:                return (error);
1.20      mycroft   838:        /*
                    839:         * Throw another dummy instruction to catch
1.90      mjacob    840:         * 'Unit attention' errors. Many drives give
                    841:         * these after doing a Load instruction (with
                    842:         * the MEDIUM MAY HAVE CHANGED asc/ascq).
1.20      mycroft   843:         */
1.134.2.1  nathanw   844:        scsipi_test_unit_ready(periph, XS_CTL_SILENT);  /* XXX */
1.1       cgd       845:
1.3       deraadt   846:        /*
1.20      mycroft   847:         * Some devices can't tell you much until they have been
                    848:         * asked to look at the media. This quirk does this.
                    849:         */
1.28      mycroft   850:        if (st->quirks & ST_Q_SENSE_HELP)
1.59      christos  851:                if ((error = st_touch_tape(st)) != 0)
1.76      enami     852:                        return (error);
1.20      mycroft   853:        /*
1.3       deraadt   854:         * Load the physical device parameters
1.20      mycroft   855:         * loads: blkmin, blkmax
                    856:         */
1.134.2.1  nathanw   857:        if ((error = st->ops(st, ST_OPS_RBL, 0)) != 0)
1.76      enami     858:                return (error);
1.20      mycroft   859:        /*
                    860:         * Load the media dependent parameters
1.44      mycroft   861:         * includes: media_blksize,media_density,numblks
1.20      mycroft   862:         * As we have a tape in, it should be reflected here.
                    863:         * If not you may need the "quirk" above.
                    864:         */
1.134.2.1  nathanw   865:        if ((error = st->ops(st, ST_OPS_MODESENSE, 0)) != 0)
1.76      enami     866:                return (error);
1.20      mycroft   867:        /*
                    868:         * If we have gained a permanent density from somewhere,
                    869:         * then use it in preference to the one supplied by
                    870:         * default by the driver.
1.3       deraadt   871:         */
1.20      mycroft   872:        if (st->modeflags[dsty] & (DENSITY_SET_BY_QUIRK | DENSITY_SET_BY_USER))
                    873:                st->density = st->modes[dsty].density;
                    874:        else
                    875:                st->density = st->media_density;
                    876:        /*
                    877:         * If we have gained a permanent blocksize
                    878:         * then use it in preference to the one supplied by
                    879:         * default by the driver.
                    880:         */
                    881:        st->flags &= ~ST_FIXEDBLOCKS;
1.76      enami     882:        if (st->modeflags[dsty] &
                    883:            (BLKSIZE_SET_BY_QUIRK | BLKSIZE_SET_BY_USER)) {
1.44      mycroft   884:                st->blksize = st->modes[dsty].blksize;
                    885:                if (st->blksize)
1.20      mycroft   886:                        st->flags |= ST_FIXEDBLOCKS;
                    887:        } else {
1.59      christos  888:                if ((error = st_decide_mode(st, FALSE)) != 0)
1.76      enami     889:                        return (error);
1.20      mycroft   890:        }
1.134.2.1  nathanw   891:        if ((error = st->ops(st, ST_OPS_MODESELECT, 0)) != 0) {
                    892:                /* ATAPI will return ENODEV for this, and this may be OK */
                    893:                if (error != ENODEV) {
                    894:                        printf("%s: cannot set selected mode\n",
                    895:                            st->sc_dev.dv_xname);
                    896:                        return (error);
                    897:                }
1.20      mycroft   898:        }
                    899:        st->flags &= ~ST_NEW_MOUNT;
                    900:        st->flags |= ST_MOUNTED;
1.134.2.1  nathanw   901:        periph->periph_flags |= PERIPH_MEDIA_LOADED;    /* move earlier? */
1.134.2.6  nathanw   902:        st->blkno = st->fileno = (daddr_t) 0;
1.76      enami     903:        return (0);
1.1       cgd       904: }
                    905:
1.3       deraadt   906: /*
1.20      mycroft   907:  * End the present mount session.
                    908:  * Rewind, and optionally eject the tape.
                    909:  * Reset various flags to indicate that all new
                    910:  * operations require another mount operation
                    911:  */
                    912: void
                    913: st_unmount(st, eject)
1.44      mycroft   914:        struct st_softc *st;
1.20      mycroft   915:        boolean eject;
1.1       cgd       916: {
1.134.2.1  nathanw   917:        struct scsipi_periph *periph = st->sc_periph;
1.20      mycroft   918:        int nmarks;
                    919:
1.134.2.1  nathanw   920:        if ((st->flags & ST_MOUNTED) == 0)
1.20      mycroft   921:                return;
1.134.2.1  nathanw   922:        SC_DEBUG(periph, SCSIPI_DB1, ("unmounting\n"));
1.114     thorpej   923:        st_check_eod(st, FALSE, &nmarks, XS_CTL_IGNORE_NOT_READY);
                    924:        st_rewind(st, 0, XS_CTL_IGNORE_NOT_READY);
1.131     pk        925:
                    926:        /*
                    927:         * Section 9.3.3 of the SCSI specs states that a device shall return
                    928:         * the density value specified in the last succesfull MODE SELECT
                    929:         * after an unload operation, in case it is not able to
                    930:         * automatically determine the density of the new medium.
                    931:         *
                    932:         * So we instruct the device to use the default density, which will
                    933:         * prevent the use of stale density values (in particular,
                    934:         * in st_touch_tape().
                    935:         */
                    936:        st->density = 0;
1.134.2.1  nathanw   937:        if (st->ops(st, ST_OPS_MODESELECT, 0) != 0) {
1.131     pk        938:                printf("%s: WARNING: cannot revert to default density\n",
                    939:                        st->sc_dev.dv_xname);
                    940:        }
                    941:
1.134.2.6  nathanw   942:        if (eject) {
                    943:                if (!(st->quirks & ST_Q_NOPREVENT)) {
                    944:                        scsipi_prevent(periph, PR_ALLOW,
                    945:                            XS_CTL_IGNORE_ILLEGAL_REQUEST |
                    946:                            XS_CTL_IGNORE_NOT_READY);
                    947:                }
1.114     thorpej   948:                st_load(st, LD_UNLOAD, XS_CTL_IGNORE_NOT_READY);
1.134.2.6  nathanw   949:                st->blkno = st->fileno = (daddr_t) -1;
                    950:        } else {
                    951:                st->blkno = st->fileno = (daddr_t) 0;
                    952:        }
1.20      mycroft   953:        st->flags &= ~(ST_MOUNTED | ST_NEW_MOUNT);
1.134.2.1  nathanw   954:        periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
1.20      mycroft   955: }
                    956:
                    957: /*
                    958:  * Given all we know about the device, media, mode, 'quirks' and
                    959:  * initial operation, make a decision as to how we should be set
                    960:  * to run (regarding blocking and EOD marks)
                    961:  */
1.51      mycroft   962: int
1.20      mycroft   963: st_decide_mode(st, first_read)
1.44      mycroft   964:        struct st_softc *st;
1.20      mycroft   965:        boolean first_read;
                    966: {
                    967:
1.134.2.1  nathanw   968:        SC_DEBUG(st->sc_periph, SCSIPI_DB2, ("starting block mode decision\n"));
1.20      mycroft   969:
                    970:        /*
                    971:         * If the drive can only handle fixed-length blocks and only at
                    972:         * one size, perhaps we should just do that.
                    973:         */
                    974:        if (st->blkmin && (st->blkmin == st->blkmax)) {
                    975:                st->flags |= ST_FIXEDBLOCKS;
1.44      mycroft   976:                st->blksize = st->blkmin;
1.134.2.1  nathanw   977:                SC_DEBUG(st->sc_periph, SCSIPI_DB3,
1.20      mycroft   978:                    ("blkmin == blkmax of %d\n", st->blkmin));
                    979:                goto done;
                    980:        }
                    981:        /*
                    982:         * If the tape density mandates (or even suggests) use of fixed
                    983:         * or variable-length blocks, comply.
                    984:         */
                    985:        switch (st->density) {
                    986:        case HALFINCH_800:
                    987:        case HALFINCH_1600:
                    988:        case HALFINCH_6250:
                    989:        case DDS:
                    990:                st->flags &= ~ST_FIXEDBLOCKS;
1.44      mycroft   991:                st->blksize = 0;
1.134.2.1  nathanw   992:                SC_DEBUG(st->sc_periph, SCSIPI_DB3,
                    993:                    ("density specified variable\n"));
1.20      mycroft   994:                goto done;
                    995:        case QIC_11:
                    996:        case QIC_24:
                    997:        case QIC_120:
                    998:        case QIC_150:
                    999:        case QIC_525:
                   1000:        case QIC_1320:
1.118     mjacob   1001:        case QIC_3095:
1.120     mjacob   1002:        case QIC_3220:
1.20      mycroft  1003:                st->flags |= ST_FIXEDBLOCKS;
1.44      mycroft  1004:                if (st->media_blksize > 0)
                   1005:                        st->blksize = st->media_blksize;
1.20      mycroft  1006:                else
1.44      mycroft  1007:                        st->blksize = DEF_FIXED_BSIZE;
1.134.2.1  nathanw  1008:                SC_DEBUG(st->sc_periph, SCSIPI_DB3,
                   1009:                    ("density specified fixed\n"));
1.20      mycroft  1010:                goto done;
                   1011:        }
                   1012:        /*
                   1013:         * If we're about to read the tape, perhaps we should choose
                   1014:         * fixed or variable-length blocks and block size according to
                   1015:         * what the drive found on the tape.
                   1016:         */
                   1017:        if (first_read &&
1.44      mycroft  1018:            (!(st->quirks & ST_Q_BLKSIZE) || (st->media_blksize == 0) ||
                   1019:            (st->media_blksize == DEF_FIXED_BSIZE) ||
                   1020:            (st->media_blksize == 1024))) {
                   1021:                if (st->media_blksize > 0)
                   1022:                        st->flags |= ST_FIXEDBLOCKS;
                   1023:                else
1.20      mycroft  1024:                        st->flags &= ~ST_FIXEDBLOCKS;
1.44      mycroft  1025:                st->blksize = st->media_blksize;
1.134.2.1  nathanw  1026:                SC_DEBUG(st->sc_periph, SCSIPI_DB3,
1.44      mycroft  1027:                    ("Used media_blksize of %d\n", st->media_blksize));
1.20      mycroft  1028:                goto done;
                   1029:        }
                   1030:        /*
                   1031:         * We're getting no hints from any direction.  Choose variable-
                   1032:         * length blocks arbitrarily.
                   1033:         */
                   1034:        st->flags &= ~ST_FIXEDBLOCKS;
1.44      mycroft  1035:        st->blksize = 0;
1.134.2.1  nathanw  1036:        SC_DEBUG(st->sc_periph, SCSIPI_DB3,
1.20      mycroft  1037:            ("Give up and default to variable mode\n"));
1.44      mycroft  1038:
1.20      mycroft  1039: done:
                   1040:        /*
                   1041:         * Decide whether or not to write two file marks to signify end-
                   1042:         * of-data.  Make the decision as a function of density.  If
                   1043:         * the decision is not to use a second file mark, the SCSI BLANK
                   1044:         * CHECK condition code will be recognized as end-of-data when
                   1045:         * first read.
                   1046:         * (I think this should be a by-product of fixed/variable..julian)
                   1047:         */
                   1048:        switch (st->density) {
                   1049: /*      case 8 mm:   What is the SCSI density code for 8 mm, anyway? */
                   1050:        case QIC_11:
                   1051:        case QIC_24:
                   1052:        case QIC_120:
                   1053:        case QIC_150:
                   1054:        case QIC_525:
                   1055:        case QIC_1320:
1.118     mjacob   1056:        case QIC_3095:
1.120     mjacob   1057:        case QIC_3220:
1.20      mycroft  1058:                st->flags &= ~ST_2FM_AT_EOD;
1.1       cgd      1059:                break;
                   1060:        default:
1.20      mycroft  1061:                st->flags |= ST_2FM_AT_EOD;
1.1       cgd      1062:        }
1.76      enami    1063:        return (0);
1.1       cgd      1064: }
                   1065:
1.3       deraadt  1066: /*
                   1067:  * Actually translate the requested transfer into
                   1068:  * one the physical driver can understand
                   1069:  * The transfer is described by a buf and will include
                   1070:  * only one physical transfer.
                   1071:  */
1.51      mycroft  1072: void
1.20      mycroft  1073: ststrategy(bp)
                   1074:        struct buf *bp;
1.1       cgd      1075: {
1.63      thorpej  1076:        struct st_softc *st = st_cd.cd_devs[STUNIT(bp->b_dev)];
1.53      mycroft  1077:        int s;
1.1       cgd      1078:
1.134.2.1  nathanw  1079:        SC_DEBUG(st->sc_periph, SCSIPI_DB1,
1.66      christos 1080:            ("ststrategy %ld bytes @ blk %d\n", bp->b_bcount, bp->b_blkno));
1.20      mycroft  1081:        /*
                   1082:         * If it's a null transfer, return immediatly
                   1083:         */
1.40      mycroft  1084:        if (bp->b_bcount == 0)
1.3       deraadt  1085:                goto done;
1.109     bouyer   1086:
                   1087:        /* If offset is negative, error */
                   1088:        if (bp->b_blkno < 0) {
                   1089:                bp->b_error = EINVAL;
                   1090:                goto bad;
                   1091:        }
                   1092:
1.3       deraadt  1093:        /*
                   1094:         * Odd sized request on fixed drives are verboten
                   1095:         */
1.20      mycroft  1096:        if (st->flags & ST_FIXEDBLOCKS) {
1.44      mycroft  1097:                if (bp->b_bcount % st->blksize) {
1.69      christos 1098:                        printf("%s: bad request, must be multiple of %d\n",
1.44      mycroft  1099:                            st->sc_dev.dv_xname, st->blksize);
1.20      mycroft  1100:                        bp->b_error = EIO;
                   1101:                        goto bad;
                   1102:                }
                   1103:        }
                   1104:        /*
                   1105:         * as are out-of-range requests on variable drives.
                   1106:         */
1.29      mycroft  1107:        else if (bp->b_bcount < st->blkmin ||
1.76      enami    1108:            (st->blkmax && bp->b_bcount > st->blkmax)) {
1.69      christos 1109:                printf("%s: bad request, must be between %d and %d\n",
1.20      mycroft  1110:                    st->sc_dev.dv_xname, st->blkmin, st->blkmax);
1.1       cgd      1111:                bp->b_error = EIO;
                   1112:                goto bad;
                   1113:        }
1.53      mycroft  1114:        s = splbio();
1.1       cgd      1115:
1.3       deraadt  1116:        /*
1.20      mycroft  1117:         * Place it in the queue of activities for this tape
                   1118:         * at the end (a bit silly because we only have on user..
                   1119:         * (but it could fork()))
1.3       deraadt  1120:         */
1.134.2.8! nathanw  1121:        BUFQ_PUT(&st->buf_queue, bp);
1.1       cgd      1122:
1.3       deraadt  1123:        /*
                   1124:         * Tell the device to get going on the transfer if it's
1.20      mycroft  1125:         * not doing anything, otherwise just wait for completion
                   1126:         * (All a bit silly if we're only allowing 1 open but..)
1.3       deraadt  1127:         */
1.134.2.1  nathanw  1128:        ststart(st->sc_periph);
1.1       cgd      1129:
1.53      mycroft  1130:        splx(s);
1.1       cgd      1131:        return;
                   1132: bad:
                   1133:        bp->b_flags |= B_ERROR;
                   1134: done:
1.3       deraadt  1135:        /*
                   1136:         * Correctly set the buf to indicate a completed xfer
                   1137:         */
1.56      pk       1138:        bp->b_resid = bp->b_bcount;
                   1139:        biodone(bp);
1.1       cgd      1140:        return;
                   1141: }
                   1142:
1.3       deraadt  1143: /*
                   1144:  * ststart looks to see if there is a buf waiting for the device
                   1145:  * and that the device is not already busy. If both are true,
1.20      mycroft  1146:  * It dequeues the buf and creates a scsi command to perform the
1.73      bouyer   1147:  * transfer required. The transfer request will call scsipi_done
1.3       deraadt  1148:  * on completion, which will in turn call this routine again
                   1149:  * so that the next queued transfer is performed.
                   1150:  * The bufs are queued by the strategy routine (ststrategy)
                   1151:  *
                   1152:  * This routine is also called after other non-queued requests
                   1153:  * have been made of the scsi driver, to ensure that the queue
                   1154:  * continues to be drained.
1.20      mycroft  1155:  * ststart() is called at splbio
                   1156:  */
1.76      enami    1157: void
1.134.2.1  nathanw  1158: ststart(periph)
                   1159:        struct scsipi_periph *periph;
1.1       cgd      1160: {
1.134.2.1  nathanw  1161:        struct st_softc *st = (void *)periph->periph_dev;
1.121     augustss 1162:        struct buf *bp;
1.3       deraadt  1163:        struct scsi_rw_tape cmd;
1.111     mycroft  1164:        int flags, error;
1.3       deraadt  1165:
1.134.2.1  nathanw  1166:        SC_DEBUG(periph, SCSIPI_DB2, ("ststart "));
1.3       deraadt  1167:        /*
                   1168:         * See if there is a buf to do and we are not already
                   1169:         * doing one
                   1170:         */
1.134.2.1  nathanw  1171:        while (periph->periph_active < periph->periph_openings) {
1.20      mycroft  1172:                /* if a special awaits, let it proceed first */
1.134.2.1  nathanw  1173:                if (periph->periph_flags & PERIPH_WAITING) {
                   1174:                        periph->periph_flags &= ~PERIPH_WAITING;
                   1175:                        wakeup((caddr_t)periph);
1.20      mycroft  1176:                        return;
                   1177:                }
                   1178:
1.134.2.8! nathanw  1179:                if ((bp = BUFQ_GET(&st->buf_queue)) == NULL)
1.61      mycroft  1180:                        return;
1.20      mycroft  1181:
                   1182:                /*
1.119     mjacob   1183:                 * If the device has been unmounted by the user
                   1184:                 * then throw away all requests until done.
1.20      mycroft  1185:                 */
1.134.2.1  nathanw  1186:                if ((st->flags & ST_MOUNTED) == 0 ||
                   1187:                    (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
1.20      mycroft  1188:                        /* make sure that one implies the other.. */
1.134.2.1  nathanw  1189:                        periph->periph_flags &= ~PERIPH_MEDIA_LOADED;
1.33      chopps   1190:                        bp->b_flags |= B_ERROR;
                   1191:                        bp->b_error = EIO;
1.71      thorpej  1192:                        bp->b_resid = bp->b_bcount;
1.33      chopps   1193:                        biodone(bp);
                   1194:                        continue;
1.20      mycroft  1195:                }
                   1196:                /*
1.93      mjacob   1197:                 * only FIXEDBLOCK devices have pending I/O or space operations.
1.20      mycroft  1198:                 */
                   1199:                if (st->flags & ST_FIXEDBLOCKS) {
                   1200:                        /*
                   1201:                         * If we are at a filemark but have not reported it yet
                   1202:                         * then we should report it now
                   1203:                         */
                   1204:                        if (st->flags & ST_AT_FILEMARK) {
                   1205:                                if ((bp->b_flags & B_READ) == B_WRITE) {
                   1206:                                        /*
                   1207:                                         * Handling of ST_AT_FILEMARK in
                   1208:                                         * st_space will fill in the right file
                   1209:                                         * mark count.
                   1210:                                         * Back up over filemark
                   1211:                                         */
1.33      chopps   1212:                                        if (st_space(st, 0, SP_FILEMARKS, 0)) {
                   1213:                                                bp->b_flags |= B_ERROR;
                   1214:                                                bp->b_error = EIO;
                   1215:                                                biodone(bp);
                   1216:                                                continue;
                   1217:                                        }
1.20      mycroft  1218:                                } else {
                   1219:                                        bp->b_resid = bp->b_bcount;
                   1220:                                        bp->b_error = 0;
                   1221:                                        bp->b_flags &= ~B_ERROR;
                   1222:                                        st->flags &= ~ST_AT_FILEMARK;
                   1223:                                        biodone(bp);
                   1224:                                        continue;       /* seek more work */
                   1225:                                }
                   1226:                        }
1.93      mjacob   1227:                }
                   1228:                /*
                   1229:                 * If we are at EOM but have not reported it
1.131     pk       1230:                 * yet then we should report it now.
1.93      mjacob   1231:                 */
                   1232:                if (st->flags & (ST_EOM_PENDING|ST_EIO_PENDING)) {
                   1233:                        bp->b_resid = bp->b_bcount;
1.20      mycroft  1234:                        if (st->flags & ST_EIO_PENDING) {
                   1235:                                bp->b_error = EIO;
                   1236:                                bp->b_flags |= B_ERROR;
                   1237:                        }
1.93      mjacob   1238:                        st->flags &= ~(ST_EOM_PENDING|ST_EIO_PENDING);
                   1239:                        biodone(bp);
                   1240:                        continue;       /* seek more work */
1.20      mycroft  1241:                }
1.28      mycroft  1242:
1.20      mycroft  1243:                /*
1.134.2.1  nathanw  1244:                 * Fill out the scsi command
1.20      mycroft  1245:                 */
1.134.2.2  nathanw  1246:                memset(&cmd, 0, sizeof(cmd));
1.134.2.1  nathanw  1247:                flags = XS_CTL_NOSLEEP | XS_CTL_ASYNC;
1.20      mycroft  1248:                if ((bp->b_flags & B_READ) == B_WRITE) {
1.44      mycroft  1249:                        cmd.opcode = WRITE;
1.20      mycroft  1250:                        st->flags &= ~ST_FM_WRITTEN;
1.134.2.1  nathanw  1251:                        flags |= XS_CTL_DATA_OUT;
1.20      mycroft  1252:                } else {
1.44      mycroft  1253:                        cmd.opcode = READ;
1.134.2.1  nathanw  1254:                        flags |= XS_CTL_DATA_IN;
1.20      mycroft  1255:                }
1.28      mycroft  1256:
1.20      mycroft  1257:                /*
                   1258:                 * Handle "fixed-block-mode" tape drives by using the
                   1259:                 * block count instead of the length.
                   1260:                 */
                   1261:                if (st->flags & ST_FIXEDBLOCKS) {
1.28      mycroft  1262:                        cmd.byte2 |= SRW_FIXED;
1.64      mycroft  1263:                        _lto3b(bp->b_bcount / st->blksize, cmd.len);
1.28      mycroft  1264:                } else
1.64      mycroft  1265:                        _lto3b(bp->b_bcount, cmd.len);
1.28      mycroft  1266:
1.20      mycroft  1267:                /*
1.134.2.6  nathanw  1268:                 * Clear 'position updated' indicator
                   1269:                 */
                   1270:                st->flags &= ~ST_POSUPDATED;
                   1271:
                   1272:                /*
1.20      mycroft  1273:                 * go ask the adapter to do all this for us
                   1274:                 */
1.134.2.1  nathanw  1275:                error = scsipi_command(periph,
1.76      enami    1276:                    (struct scsipi_generic *)&cmd, sizeof(cmd),
                   1277:                    (u_char *)bp->b_data, bp->b_bcount,
1.134.2.1  nathanw  1278:                    0, ST_IO_TIME, bp, flags);
1.111     mycroft  1279:                if (error) {
                   1280:                        printf("%s: not queued, error %d\n",
                   1281:                            st->sc_dev.dv_xname, error);
                   1282:                }
1.20      mycroft  1283:        } /* go back and see if we can cram more work in.. */
1.80      explorer 1284: }
                   1285:
                   1286: void
                   1287: stdone(xs)
                   1288:        struct scsipi_xfer *xs;
                   1289: {
1.134.2.1  nathanw  1290:        struct st_softc *st = (void *)xs->xs_periph->periph_dev;
1.80      explorer 1291:
1.96      mjacob   1292:        if (xs->bp != NULL) {
                   1293:                if ((xs->bp->b_flags & B_READ) == B_WRITE) {
                   1294:                        st->flags |= ST_WRITTEN;
1.99      mjacob   1295:                } else {
                   1296:                        st->flags &= ~ST_WRITTEN;
1.96      mjacob   1297:                }
                   1298: #if NRND > 0
1.80      explorer 1299:                rnd_add_uint32(&st->rnd_source, xs->bp->b_blkno);
1.96      mjacob   1300: #endif
1.134.2.6  nathanw  1301:
                   1302:                if ((st->flags & ST_POSUPDATED) == 0) {
                   1303:                        if (xs->bp->b_flags & B_ERROR) {
                   1304:                                st->fileno = st->blkno = -1;
                   1305:                        } else if (st->blkno != -1) {
                   1306:                                if (st->flags & ST_FIXEDBLOCKS) {
                   1307:                                        st->blkno +=
                   1308:                                            (xs->bp->b_bcount / st->blksize);
                   1309:                                } else {
                   1310:                                        st->blkno++;
                   1311:                                }
                   1312:                        }
                   1313:                }
1.96      mjacob   1314:        }
1.49      mycroft  1315: }
                   1316:
                   1317: int
1.59      christos 1318: stread(dev, uio, iomode)
1.49      mycroft  1319:        dev_t dev;
                   1320:        struct uio *uio;
1.59      christos 1321:        int iomode;
1.49      mycroft  1322: {
1.63      thorpej  1323:        struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
1.49      mycroft  1324:
1.51      mycroft  1325:        return (physio(ststrategy, NULL, dev, B_READ,
1.134.2.1  nathanw  1326:            st->sc_periph->periph_channel->chan_adapter->adapt_minphys, uio));
1.49      mycroft  1327: }
                   1328:
                   1329: int
1.59      christos 1330: stwrite(dev, uio, iomode)
1.49      mycroft  1331:        dev_t dev;
                   1332:        struct uio *uio;
1.59      christos 1333:        int iomode;
1.49      mycroft  1334: {
1.63      thorpej  1335:        struct st_softc *st = st_cd.cd_devs[STUNIT(dev)];
1.49      mycroft  1336:
1.51      mycroft  1337:        return (physio(ststrategy, NULL, dev, B_WRITE,
1.134.2.1  nathanw  1338:            st->sc_periph->periph_channel->chan_adapter->adapt_minphys, uio));
1.20      mycroft  1339: }
1.1       cgd      1340:
1.20      mycroft  1341: /*
                   1342:  * Perform special action on behalf of the user;
                   1343:  * knows about the internals of this device
                   1344:  */
1.51      mycroft  1345: int
1.44      mycroft  1346: stioctl(dev, cmd, arg, flag, p)
1.20      mycroft  1347:        dev_t dev;
1.39      cgd      1348:        u_long cmd;
1.20      mycroft  1349:        caddr_t arg;
                   1350:        int flag;
1.44      mycroft  1351:        struct proc *p;
1.20      mycroft  1352: {
                   1353:        int error = 0;
                   1354:        int unit;
                   1355:        int number, nmarks, dsty;
1.27      mycroft  1356:        int flags;
1.44      mycroft  1357:        struct st_softc *st;
                   1358:        int hold_blksize;
                   1359:        u_int8_t hold_density;
1.20      mycroft  1360:        struct mtop *mt = (struct mtop *) arg;
1.1       cgd      1361:
1.3       deraadt  1362:        /*
1.20      mycroft  1363:         * Find the device that the user is talking about
1.3       deraadt  1364:         */
1.20      mycroft  1365:        flags = 0;              /* give error messages, act on errors etc. */
                   1366:        unit = STUNIT(dev);
                   1367:        dsty = STDSTY(dev);
1.63      thorpej  1368:        st = st_cd.cd_devs[unit];
1.44      mycroft  1369:        hold_blksize = st->blksize;
1.20      mycroft  1370:        hold_density = st->density;
                   1371:
1.75      mjacob   1372:        switch ((u_int) cmd) {
1.20      mycroft  1373:
                   1374:        case MTIOCGET: {
                   1375:                struct mtget *g = (struct mtget *) arg;
1.90      mjacob   1376:                /*
                   1377:                 * (to get the current state of READONLY)
                   1378:                 */
1.134.2.1  nathanw  1379:                error = st->ops(st, ST_OPS_MODESENSE, XS_CTL_SILENT);
1.130     pk       1380:                if (error) {
                   1381:                        /*
                   1382:                         * Ignore the error if in control mode;
                   1383:                         * this is mandated by st(4).
                   1384:                         */
                   1385:                        if (STMODE(dev) != CTRL_MODE)
                   1386:                                break;
                   1387:                        error = 0;
                   1388:                }
1.134.2.1  nathanw  1389:                SC_DEBUG(st->sc_periph, SCSIPI_DB1, ("[ioctl: get status]\n"));
1.134.2.2  nathanw  1390:                memset(g, 0, sizeof(struct mtget));
1.20      mycroft  1391:                g->mt_type = 0x7;       /* Ultrix compat *//*? */
1.44      mycroft  1392:                g->mt_blksiz = st->blksize;
1.20      mycroft  1393:                g->mt_density = st->density;
1.44      mycroft  1394:                g->mt_mblksiz[0] = st->modes[0].blksize;
                   1395:                g->mt_mblksiz[1] = st->modes[1].blksize;
                   1396:                g->mt_mblksiz[2] = st->modes[2].blksize;
                   1397:                g->mt_mblksiz[3] = st->modes[3].blksize;
1.20      mycroft  1398:                g->mt_mdensity[0] = st->modes[0].density;
                   1399:                g->mt_mdensity[1] = st->modes[1].density;
                   1400:                g->mt_mdensity[2] = st->modes[2].density;
                   1401:                g->mt_mdensity[3] = st->modes[3].density;
1.134.2.6  nathanw  1402:                g->mt_fileno = st->fileno;
                   1403:                g->mt_blkno = st->blkno;
1.90      mjacob   1404:                if (st->flags & ST_READONLY)
                   1405:                        g->mt_dsreg |= MT_DS_RDONLY;
                   1406:                if (st->flags & ST_MOUNTED)
                   1407:                        g->mt_dsreg |= MT_DS_MOUNTED;
                   1408:                g->mt_resid = st->mt_resid;
                   1409:                g->mt_erreg = st->mt_erreg;
                   1410:                /*
                   1411:                 * clear latched errors.
                   1412:                 */
                   1413:                st->mt_resid = 0;
                   1414:                st->mt_erreg = 0;
1.115     mjacob   1415:                st->asc = 0;
                   1416:                st->ascq = 0;
1.20      mycroft  1417:                break;
1.1       cgd      1418:        }
1.20      mycroft  1419:        case MTIOCTOP: {
1.1       cgd      1420:
1.134.2.1  nathanw  1421:                SC_DEBUG(st->sc_periph, SCSIPI_DB1,
1.76      enami    1422:                    ("[ioctl: op=0x%x count=0x%x]\n", mt->mt_op,
                   1423:                        mt->mt_count));
1.1       cgd      1424:
                   1425:                /* compat: in U*x it is a short */
                   1426:                number = mt->mt_count;
1.20      mycroft  1427:                switch ((short) (mt->mt_op)) {
1.1       cgd      1428:                case MTWEOF:    /* write an end-of-file record */
1.20      mycroft  1429:                        error = st_write_filemarks(st, number, flags);
1.1       cgd      1430:                        break;
1.20      mycroft  1431:                case MTBSF:     /* backward space file */
                   1432:                        number = -number;
1.1       cgd      1433:                case MTFSF:     /* forward space file */
1.28      mycroft  1434:                        error = st_check_eod(st, FALSE, &nmarks, flags);
1.20      mycroft  1435:                        if (!error)
                   1436:                                error = st_space(st, number - nmarks,
                   1437:                                    SP_FILEMARKS, flags);
1.1       cgd      1438:                        break;
1.20      mycroft  1439:                case MTBSR:     /* backward space record */
                   1440:                        number = -number;
1.1       cgd      1441:                case MTFSR:     /* forward space record */
1.28      mycroft  1442:                        error = st_check_eod(st, TRUE, &nmarks, flags);
1.20      mycroft  1443:                        if (!error)
                   1444:                                error = st_space(st, number, SP_BLKS, flags);
1.1       cgd      1445:                        break;
                   1446:                case MTREW:     /* rewind */
1.28      mycroft  1447:                        error = st_rewind(st, 0, flags);
1.1       cgd      1448:                        break;
                   1449:                case MTOFFL:    /* rewind and put the drive offline */
1.20      mycroft  1450:                        st_unmount(st, EJECT);
1.1       cgd      1451:                        break;
                   1452:                case MTNOP:     /* no operation, sets status only */
1.22      mycroft  1453:                        break;
1.23      mycroft  1454:                case MTRETEN:   /* retension the tape */
1.28      mycroft  1455:                        error = st_load(st, LD_RETENSION, flags);
1.24      mycroft  1456:                        if (!error)
                   1457:                                error = st_load(st, LD_LOAD, flags);
1.23      mycroft  1458:                        break;
1.22      mycroft  1459:                case MTEOM:     /* forward space to end of media */
1.28      mycroft  1460:                        error = st_check_eod(st, FALSE, &nmarks, flags);
1.22      mycroft  1461:                        if (!error)
                   1462:                                error = st_space(st, 1, SP_EOM, flags);
                   1463:                        break;
1.1       cgd      1464:                case MTCACHE:   /* enable controller cache */
1.57      thorpej  1465:                        st->flags &= ~ST_DONTBUFFER;
                   1466:                        goto try_new_value;
1.1       cgd      1467:                case MTNOCACHE: /* disable controller cache */
1.57      thorpej  1468:                        st->flags |= ST_DONTBUFFER;
                   1469:                        goto try_new_value;
                   1470:                case MTERASE:   /* erase volume */
                   1471:                        error = st_erase(st, number, flags);
1.1       cgd      1472:                        break;
1.20      mycroft  1473:                case MTSETBSIZ: /* Set block size for device */
                   1474: #ifdef NOTYET
                   1475:                        if (!(st->flags & ST_NEW_MOUNT)) {
                   1476:                                uprintf("re-mount tape before changing blocksize");
                   1477:                                error = EINVAL;
                   1478:                                break;
                   1479:                        }
                   1480: #endif
1.76      enami    1481:                        if (number == 0)
1.20      mycroft  1482:                                st->flags &= ~ST_FIXEDBLOCKS;
1.76      enami    1483:                        else {
1.20      mycroft  1484:                                if ((st->blkmin || st->blkmax) &&
                   1485:                                    (number < st->blkmin ||
                   1486:                                    number > st->blkmax)) {
                   1487:                                        error = EINVAL;
                   1488:                                        break;
                   1489:                                }
                   1490:                                st->flags |= ST_FIXEDBLOCKS;
                   1491:                        }
1.44      mycroft  1492:                        st->blksize = number;
1.20      mycroft  1493:                        st->flags |= ST_BLOCK_SET;      /*XXX */
                   1494:                        goto try_new_value;
                   1495:
                   1496:                case MTSETDNSTY:        /* Set density for device and mode */
1.94      mjacob   1497:                        /*
                   1498:                         * Any number >= 0 and <= 0xff is legal. Numbers
                   1499:                         * above 0x80 are 'vendor unique'.
                   1500:                         */
                   1501:                        if (number < 0 || number > 255) {
1.20      mycroft  1502:                                error = EINVAL;
1.57      thorpej  1503:                                break;
                   1504:                        } else
1.20      mycroft  1505:                                st->density = number;
                   1506:                        goto try_new_value;
                   1507:
1.75      mjacob   1508:                case MTCMPRESS:
1.134.2.1  nathanw  1509:                        error = st->ops(st, (number == 0) ?
                   1510:                            ST_OPS_CMPRSS_OFF : ST_OPS_CMPRSS_ON,
                   1511:                            XS_CTL_SILENT);
1.75      mjacob   1512:                        break;
                   1513:
1.93      mjacob   1514:                case MTEWARN:
                   1515:                        if (number)
                   1516:                                st->flags |= ST_EARLYWARN;
                   1517:                        else
                   1518:                                st->flags &= ~ST_EARLYWARN;
                   1519:                        break;
                   1520:
1.1       cgd      1521:                default:
1.20      mycroft  1522:                        error = EINVAL;
1.1       cgd      1523:                }
                   1524:                break;
1.20      mycroft  1525:        }
1.1       cgd      1526:        case MTIOCIEOT:
                   1527:        case MTIOCEEOT:
1.20      mycroft  1528:                break;
1.75      mjacob   1529:
                   1530:        case MTIOCRDSPOS:
                   1531:                error = st_rdpos(st, 0, (u_int32_t *) arg);
                   1532:                break;
                   1533:
                   1534:        case MTIOCRDHPOS:
                   1535:                error = st_rdpos(st, 1, (u_int32_t *) arg);
                   1536:                break;
                   1537:
                   1538:        case MTIOCSLOCATE:
                   1539:                error = st_setpos(st, 0, (u_int32_t *) arg);
                   1540:                break;
                   1541:
                   1542:        case MTIOCHLOCATE:
                   1543:                error = st_setpos(st, 1, (u_int32_t *) arg);
                   1544:                break;
                   1545:
1.93      mjacob   1546:
1.20      mycroft  1547:        default:
1.134.2.1  nathanw  1548:                error = scsipi_do_ioctl(st->sc_periph, dev, cmd, arg,
1.92      drochner 1549:                                        flag, p);
1.1       cgd      1550:                break;
                   1551:        }
1.76      enami    1552:        return (error);
1.20      mycroft  1553: /*-----------------------------*/
                   1554: try_new_value:
                   1555:        /*
                   1556:         * Check that the mode being asked for is aggreeable to the
                   1557:         * drive. If not, put it back the way it was.
1.130     pk       1558:         *
                   1559:         * If in control mode, we can make (persistent) mode changes
                   1560:         * even if no medium is loaded (see st(4)).
1.20      mycroft  1561:         */
1.130     pk       1562:        if ((STMODE(dev) != CTRL_MODE || (st->flags & ST_MOUNTED) != 0) &&
1.134.2.1  nathanw  1563:            (error = st->ops(st, ST_OPS_MODESELECT, 0)) != 0) {
1.130     pk       1564:                /* put it back as it was */
1.69      christos 1565:                printf("%s: cannot set selected mode\n", st->sc_dev.dv_xname);
1.20      mycroft  1566:                st->density = hold_density;
1.44      mycroft  1567:                st->blksize = hold_blksize;
                   1568:                if (st->blksize)
1.20      mycroft  1569:                        st->flags |= ST_FIXEDBLOCKS;
                   1570:                else
                   1571:                        st->flags &= ~ST_FIXEDBLOCKS;
1.76      enami    1572:                return (error);
1.20      mycroft  1573:        }
                   1574:        /*
                   1575:         * As the drive liked it, if we are setting a new default,
                   1576:         * set it into the structures as such.
1.51      mycroft  1577:         *
1.94      mjacob   1578:         * The means for deciding this are not finalised yet- but
                   1579:         * if the device was opened in Control Mode, the values
                   1580:         * are persistent now across mounts.
1.20      mycroft  1581:         */
1.94      mjacob   1582:        if (STMODE(dev) == CTRL_MODE) {
1.20      mycroft  1583:                switch ((short) (mt->mt_op)) {
                   1584:                case MTSETBSIZ:
1.44      mycroft  1585:                        st->modes[dsty].blksize = st->blksize;
1.20      mycroft  1586:                        st->modeflags[dsty] |= BLKSIZE_SET_BY_USER;
                   1587:                        break;
                   1588:                case MTSETDNSTY:
                   1589:                        st->modes[dsty].density = st->density;
                   1590:                        st->modeflags[dsty] |= DENSITY_SET_BY_USER;
                   1591:                        break;
                   1592:                }
                   1593:        }
1.76      enami    1594:        return (0);
1.1       cgd      1595: }
                   1596:
1.3       deraadt  1597: /*
1.20      mycroft  1598:  * Do a synchronous read.
                   1599:  */
1.51      mycroft  1600: int
1.20      mycroft  1601: st_read(st, buf, size, flags)
1.44      mycroft  1602:        struct st_softc *st;
                   1603:        int size;
1.27      mycroft  1604:        int flags;
1.20      mycroft  1605:        char *buf;
1.1       cgd      1606: {
1.28      mycroft  1607:        struct scsi_rw_tape cmd;
1.1       cgd      1608:
1.20      mycroft  1609:        /*
                   1610:         * If it's a null transfer, return immediatly
                   1611:         */
                   1612:        if (size == 0)
1.76      enami    1613:                return (0);
1.134.2.2  nathanw  1614:        memset(&cmd, 0, sizeof(cmd));
1.44      mycroft  1615:        cmd.opcode = READ;
1.20      mycroft  1616:        if (st->flags & ST_FIXEDBLOCKS) {
1.28      mycroft  1617:                cmd.byte2 |= SRW_FIXED;
1.64      mycroft  1618:                _lto3b(size / (st->blksize ? st->blksize : DEF_FIXED_BSIZE),
1.28      mycroft  1619:                    cmd.len);
1.20      mycroft  1620:        } else
1.64      mycroft  1621:                _lto3b(size, cmd.len);
1.134.2.1  nathanw  1622:        return (scsipi_command(st->sc_periph,
1.76      enami    1623:            (struct scsipi_generic *)&cmd, sizeof(cmd),
1.114     thorpej  1624:            (u_char *)buf, size, 0, ST_IO_TIME, NULL, flags | XS_CTL_DATA_IN));
1.1       cgd      1625: }
                   1626:
1.3       deraadt  1627: /*
1.57      thorpej  1628:  * issue an erase command
                   1629:  */
                   1630: int
                   1631: st_erase(st, full, flags)
                   1632:        struct st_softc *st;
                   1633:        int full, flags;
                   1634: {
1.90      mjacob   1635:        int tmo;
1.57      thorpej  1636:        struct scsi_erase cmd;
                   1637:
                   1638:        /*
                   1639:         * Full erase means set LONG bit in erase command, which asks
                   1640:         * the drive to erase the entire unit.  Without this bit, we're
                   1641:         * asking the drive to write an erase gap.
                   1642:         */
1.134.2.2  nathanw  1643:        memset(&cmd, 0, sizeof(cmd));
1.57      thorpej  1644:        cmd.opcode = ERASE;
1.90      mjacob   1645:        if (full) {
1.129     pk       1646:                cmd.byte2 = SE_LONG;
1.90      mjacob   1647:                tmo = ST_SPC_TIME;
                   1648:        } else {
                   1649:                tmo = ST_IO_TIME;
                   1650:        }
1.57      thorpej  1651:
                   1652:        /*
1.129     pk       1653:         * XXX We always do this asynchronously, for now, unless the device
                   1654:         * has the ST_Q_ERASE_NOIMM quirk.  How long should we wait if we
                   1655:         * want to (eventually) to it synchronously?
1.57      thorpej  1656:         */
1.129     pk       1657:        if ((st->quirks & ST_Q_ERASE_NOIMM) == 0)
                   1658:                cmd.byte2 |= SE_IMMED;
                   1659:
1.134.2.1  nathanw  1660:        return (scsipi_command(st->sc_periph,
1.76      enami    1661:            (struct scsipi_generic *)&cmd, sizeof(cmd),
1.90      mjacob   1662:            0, 0, ST_RETRIES, tmo, NULL, flags));
1.1       cgd      1663: }
                   1664:
1.3       deraadt  1665: /*
                   1666:  * skip N blocks/filemarks/seq filemarks/eom
1.20      mycroft  1667:  */
1.51      mycroft  1668: int
1.20      mycroft  1669: st_space(st, number, what, flags)
1.44      mycroft  1670:        struct st_softc *st;
1.20      mycroft  1671:        u_int what;
1.27      mycroft  1672:        int flags;
1.20      mycroft  1673:        int number;
1.1       cgd      1674: {
1.28      mycroft  1675:        struct scsi_space cmd;
1.20      mycroft  1676:        int error;
1.1       cgd      1677:
1.20      mycroft  1678:        switch (what) {
                   1679:        case SP_BLKS:
                   1680:                if (st->flags & ST_PER_ACTION) {
                   1681:                        if (number > 0) {
                   1682:                                st->flags &= ~ST_PER_ACTION;
1.76      enami    1683:                                return (EIO);
1.20      mycroft  1684:                        } else if (number < 0) {
                   1685:                                if (st->flags & ST_AT_FILEMARK) {
                   1686:                                        /*
                   1687:                                         * Handling of ST_AT_FILEMARK
                   1688:                                         * in st_space will fill in the
                   1689:                                         * right file mark count.
                   1690:                                         */
                   1691:                                        error = st_space(st, 0, SP_FILEMARKS,
1.76      enami    1692:                                            flags);
1.20      mycroft  1693:                                        if (error)
1.76      enami    1694:                                                return (error);
1.20      mycroft  1695:                                }
                   1696:                                if (st->flags & ST_BLANK_READ) {
                   1697:                                        st->flags &= ~ST_BLANK_READ;
1.76      enami    1698:                                        return (EIO);
1.20      mycroft  1699:                                }
1.93      mjacob   1700:                                st->flags &= ~(ST_EIO_PENDING|ST_EOM_PENDING);
1.20      mycroft  1701:                        }
                   1702:                }
                   1703:                break;
                   1704:        case SP_FILEMARKS:
                   1705:                if (st->flags & ST_EIO_PENDING) {
                   1706:                        if (number > 0) {
1.22      mycroft  1707:                                /* pretend we just discovered the error */
1.20      mycroft  1708:                                st->flags &= ~ST_EIO_PENDING;
1.76      enami    1709:                                return (EIO);
1.20      mycroft  1710:                        } else if (number < 0) {
                   1711:                                /* back away from the error */
                   1712:                                st->flags &= ~ST_EIO_PENDING;
                   1713:                        }
                   1714:                }
                   1715:                if (st->flags & ST_AT_FILEMARK) {
                   1716:                        st->flags &= ~ST_AT_FILEMARK;
                   1717:                        number--;
                   1718:                }
                   1719:                if ((st->flags & ST_BLANK_READ) && (number < 0)) {
                   1720:                        /* back away from unwritten tape */
                   1721:                        st->flags &= ~ST_BLANK_READ;
                   1722:                        number++;       /* XXX dubious */
                   1723:                }
1.22      mycroft  1724:                break;
                   1725:        case SP_EOM:
1.93      mjacob   1726:                if (st->flags & ST_EOM_PENDING) {
                   1727:                        /* we're already there */
                   1728:                        st->flags &= ~ST_EOM_PENDING;
                   1729:                        return (0);
                   1730:                }
1.22      mycroft  1731:                if (st->flags & ST_EIO_PENDING) {
                   1732:                        /* pretend we just discovered the error */
                   1733:                        st->flags &= ~ST_EIO_PENDING;
1.76      enami    1734:                        return (EIO);
1.22      mycroft  1735:                }
                   1736:                if (st->flags & ST_AT_FILEMARK)
                   1737:                        st->flags &= ~ST_AT_FILEMARK;
                   1738:                break;
1.20      mycroft  1739:        }
                   1740:        if (number == 0)
1.76      enami    1741:                return (0);
1.28      mycroft  1742:
1.134.2.2  nathanw  1743:        memset(&cmd, 0, sizeof(cmd));
1.44      mycroft  1744:        cmd.opcode = SPACE;
1.28      mycroft  1745:        cmd.byte2 = what;
1.64      mycroft  1746:        _lto3b(number, cmd.number);
1.28      mycroft  1747:
1.134.2.6  nathanw  1748:        st->flags &= ~ST_POSUPDATED;
                   1749:        st->last_ctl_resid = 0;
                   1750:        error = scsipi_command(st->sc_periph,
1.76      enami    1751:            (struct scsipi_generic *)&cmd, sizeof(cmd),
1.134.2.6  nathanw  1752:            0, 0, 0, ST_SPC_TIME, NULL, flags);
                   1753:
                   1754:        if (error == 0 && (st->flags & ST_POSUPDATED) == 0) {
                   1755:                number = number - st->last_ctl_resid;
                   1756:                if (what == SP_BLKS) {
                   1757:                        if (st->blkno != -1) {
                   1758:                                st->blkno += number;
                   1759:                        }
                   1760:                } else if (what == SP_FILEMARKS) {
                   1761:                        if (st->fileno != -1) {
                   1762:                                st->fileno += number;
                   1763:                                if (number > 0) {
                   1764:                                        st->blkno = 0;
                   1765:                                } else if (number < 0) {
                   1766:                                        st->blkno = -1;
                   1767:                                }
                   1768:                        }
                   1769:                } else if (what == SP_EOM) {
                   1770:                        /*
                   1771:                         * This loses us relative position.
                   1772:                         */
                   1773:                        st->fileno = st->blkno = -1;
                   1774:                }
                   1775:        }
                   1776:        return (error);
1.1       cgd      1777: }
1.3       deraadt  1778:
                   1779: /*
                   1780:  * write N filemarks
1.20      mycroft  1781:  */
1.51      mycroft  1782: int
1.20      mycroft  1783: st_write_filemarks(st, number, flags)
1.44      mycroft  1784:        struct st_softc *st;
1.27      mycroft  1785:        int flags;
1.20      mycroft  1786:        int number;
1.1       cgd      1787: {
1.134.2.6  nathanw  1788:        int error;
1.28      mycroft  1789:        struct scsi_write_filemarks cmd;
1.1       cgd      1790:
1.20      mycroft  1791:        /*
                   1792:         * It's hard to write a negative number of file marks.
                   1793:         * Don't try.
                   1794:         */
                   1795:        if (number < 0)
1.76      enami    1796:                return (EINVAL);
1.20      mycroft  1797:        switch (number) {
                   1798:        case 0:         /* really a command to sync the drive's buffers */
                   1799:                break;
                   1800:        case 1:
                   1801:                if (st->flags & ST_FM_WRITTEN)  /* already have one down */
                   1802:                        st->flags &= ~ST_WRITTEN;
                   1803:                else
                   1804:                        st->flags |= ST_FM_WRITTEN;
                   1805:                st->flags &= ~ST_PER_ACTION;
                   1806:                break;
                   1807:        default:
                   1808:                st->flags &= ~(ST_PER_ACTION | ST_WRITTEN);
                   1809:        }
1.28      mycroft  1810:
1.134.2.2  nathanw  1811:        memset(&cmd, 0, sizeof(cmd));
1.44      mycroft  1812:        cmd.opcode = WRITE_FILEMARKS;
1.134.2.4  nathanw  1813:        if (scsipi_periph_bustype(st->sc_periph) == SCSIPI_BUSTYPE_ATAPI)
                   1814:                cmd.byte2 = SR_IMMED;
                   1815:        /*
                   1816:         * The ATAPI Onstream DI-30 doesn't support writing filemarks, but
                   1817:         * WRITE_FILEMARKS is still used to flush the buffer
                   1818:         */
                   1819:        if ((st->quirks & ST_Q_NOFILEMARKS) == 0)
                   1820:                _lto3b(number, cmd.number);
1.28      mycroft  1821:
1.134.2.6  nathanw  1822:        /* XXX WE NEED TO BE ABLE TO GET A RESIDIUAL XXX */
                   1823:        error = scsipi_command(st->sc_periph,
1.76      enami    1824:            (struct scsipi_generic *)&cmd, sizeof(cmd),
1.134.2.6  nathanw  1825:            0, 0, 0, ST_IO_TIME * 4, NULL, flags);
                   1826:        if (error == 0 && st->fileno != -1) {
                   1827:                st->fileno += number;
                   1828:        }
                   1829:        return (error);
1.1       cgd      1830: }
1.3       deraadt  1831:
                   1832: /*
1.20      mycroft  1833:  * Make sure the right number of file marks is on tape if the
                   1834:  * tape has been written.  If the position argument is true,
                   1835:  * leave the tape positioned where it was originally.
                   1836:  *
                   1837:  * nmarks returns the number of marks to skip (or, if position
                   1838:  * true, which were skipped) to get back original position.
                   1839:  */
1.51      mycroft  1840: int
1.28      mycroft  1841: st_check_eod(st, position, nmarks, flags)
1.44      mycroft  1842:        struct st_softc *st;
1.20      mycroft  1843:        boolean position;
                   1844:        int *nmarks;
1.27      mycroft  1845:        int flags;
1.1       cgd      1846: {
1.20      mycroft  1847:        int error;
1.1       cgd      1848:
1.20      mycroft  1849:        switch (st->flags & (ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD)) {
                   1850:        default:
                   1851:                *nmarks = 0;
1.76      enami    1852:                return (0);
1.20      mycroft  1853:        case ST_WRITTEN:
                   1854:        case ST_WRITTEN | ST_FM_WRITTEN | ST_2FM_AT_EOD:
                   1855:                *nmarks = 1;
                   1856:                break;
                   1857:        case ST_WRITTEN | ST_2FM_AT_EOD:
                   1858:                *nmarks = 2;
1.1       cgd      1859:        }
1.20      mycroft  1860:        error = st_write_filemarks(st, *nmarks, flags);
                   1861:        if (position && !error)
                   1862:                error = st_space(st, -*nmarks, SP_FILEMARKS, flags);
1.76      enami    1863:        return (error);
1.1       cgd      1864: }
1.3       deraadt  1865:
                   1866: /*
1.23      mycroft  1867:  * load/unload/retension
1.20      mycroft  1868:  */
1.51      mycroft  1869: int
1.20      mycroft  1870: st_load(st, type, flags)
1.44      mycroft  1871:        struct st_softc *st;
1.20      mycroft  1872:        u_int type;
1.27      mycroft  1873:        int flags;
1.1       cgd      1874: {
1.112     mjacob   1875:        int error;
1.28      mycroft  1876:        struct scsi_load cmd;
1.1       cgd      1877:
1.20      mycroft  1878:        if (type != LD_LOAD) {
                   1879:                int nmarks;
                   1880:
1.28      mycroft  1881:                error = st_check_eod(st, FALSE, &nmarks, flags);
1.112     mjacob   1882:                if (error) {
                   1883:                        printf("%s: failed to write closing filemarks at "
                   1884:                            "unload, errno=%d\n", st->sc_dev.dv_xname, error);
1.76      enami    1885:                        return (error);
1.112     mjacob   1886:                }
1.1       cgd      1887:        }
1.90      mjacob   1888:        if (st->quirks & ST_Q_IGNORE_LOADS) {
                   1889:                if (type == LD_LOAD) {
                   1890:                        /*
                   1891:                         * If we ignore loads, at least we should try a rewind.
                   1892:                         */
                   1893:                        return st_rewind(st, 0, flags);
                   1894:                }
1.112     mjacob   1895:                /* otherwise, we should do what's asked of us */
1.90      mjacob   1896:        }
1.28      mycroft  1897:
1.134.2.2  nathanw  1898:        memset(&cmd, 0, sizeof(cmd));
1.44      mycroft  1899:        cmd.opcode = LOAD;
1.134.2.4  nathanw  1900:        if (scsipi_periph_bustype(st->sc_periph) == SCSIPI_BUSTYPE_ATAPI)
                   1901:                cmd.byte2 = SR_IMMED;
1.28      mycroft  1902:        cmd.how = type;
                   1903:
1.134.2.1  nathanw  1904:        error = scsipi_command(st->sc_periph,
1.76      enami    1905:            (struct scsipi_generic *)&cmd, sizeof(cmd),
1.112     mjacob   1906:            0, 0, ST_RETRIES, ST_SPC_TIME, NULL, flags);
                   1907:        if (error) {
                   1908:                printf("%s: error %d in st_load (op %d)\n",
                   1909:                    st->sc_dev.dv_xname, error, type);
                   1910:        }
                   1911:        return (error);
1.1       cgd      1912: }
1.3       deraadt  1913:
                   1914: /*
                   1915:  *  Rewind the device
1.20      mycroft  1916:  */
1.51      mycroft  1917: int
1.28      mycroft  1918: st_rewind(st, immediate, flags)
1.44      mycroft  1919:        struct st_softc *st;
1.28      mycroft  1920:        u_int immediate;
1.27      mycroft  1921:        int flags;
1.1       cgd      1922: {
1.28      mycroft  1923:        struct scsi_rewind cmd;
1.20      mycroft  1924:        int error;
                   1925:        int nmarks;
                   1926:
1.28      mycroft  1927:        error = st_check_eod(st, FALSE, &nmarks, flags);
1.112     mjacob   1928:        if (error) {
                   1929:                printf("%s: failed to write closing filemarks at "
                   1930:                    "rewind, errno=%d\n", st->sc_dev.dv_xname, error);
1.76      enami    1931:                return (error);
1.112     mjacob   1932:        }
1.20      mycroft  1933:        st->flags &= ~ST_PER_ACTION;
1.28      mycroft  1934:
1.134.2.1  nathanw  1935:        /*
1.134.2.4  nathanw  1936:         * ATAPI tapes always need immediate to be set
1.134.2.1  nathanw  1937:         */
                   1938:        if (scsipi_periph_bustype(st->sc_periph) == SCSIPI_BUSTYPE_ATAPI)
                   1939:                immediate = SR_IMMED;
                   1940:
1.134.2.2  nathanw  1941:        memset(&cmd, 0, sizeof(cmd));
1.44      mycroft  1942:        cmd.opcode = REWIND;
1.28      mycroft  1943:        cmd.byte2 = immediate;
                   1944:
1.134.2.1  nathanw  1945:        error = scsipi_command(st->sc_periph,
1.90      mjacob   1946:            (struct scsipi_generic *)&cmd, sizeof(cmd), 0, 0, ST_RETRIES,
1.112     mjacob   1947:            immediate ? ST_CTL_TIME: ST_SPC_TIME, NULL, flags);
                   1948:        if (error) {
                   1949:                printf("%s: error %d trying to rewind\n",
                   1950:                    st->sc_dev.dv_xname, error);
1.134.2.6  nathanw  1951:                /* lost position */
                   1952:                st->fileno = st->blkno = -1;
                   1953:        } else {
                   1954:                st->fileno = st->blkno = 0;
1.112     mjacob   1955:        }
                   1956:        return (error);
1.1       cgd      1957: }
1.3       deraadt  1958:
1.75      mjacob   1959: int
                   1960: st_rdpos(st, hard, blkptr)
                   1961:        struct st_softc *st;
                   1962:        int hard;
                   1963:        u_int32_t *blkptr;
                   1964: {
                   1965:        int error;
                   1966:        u_int8_t posdata[20];
                   1967:        struct scsi_tape_read_position cmd;
                   1968:
                   1969:        /*
1.134.2.6  nathanw  1970:         * We try and flush any buffered writes here if we were writing
                   1971:         * and we're trying to get hardware block position. It eats
                   1972:         * up performance substantially, but I'm wary of drive firmware.
                   1973:         *
                   1974:         * I think that *logical* block position is probably okay-
                   1975:         * but hardware block position might have to wait for data
                   1976:         * to hit media to be valid. Caveat Emptor.
1.75      mjacob   1977:         */
1.77      mjacob   1978:
1.134.2.6  nathanw  1979:        if (hard && (st->flags & ST_WRITTEN)) {
                   1980:                /*
                   1981:                 * First flush any pending writes...
                   1982:                 */
                   1983:                error = st_write_filemarks(st, 0, XS_CTL_SILENT);
                   1984:                /*
                   1985:                 * The latter case is for 'write protected' tapes
                   1986:                 * which are too stupid to recognize a zero count
                   1987:                 * for writing filemarks as a no-op.
                   1988:                 */
                   1989:                if (error != 0 && error != EACCES && error != EROFS)
                   1990:                        return (error);
                   1991:        }
1.75      mjacob   1992:
1.134.2.2  nathanw  1993:        memset(&cmd, 0, sizeof(cmd));
                   1994:        memset(&posdata, 0, sizeof(posdata));
1.75      mjacob   1995:        cmd.opcode = READ_POSITION;
                   1996:        if (hard)
                   1997:                cmd.byte1 = 1;
                   1998:
1.134.2.1  nathanw  1999:        error = scsipi_command(st->sc_periph,
1.76      enami    2000:            (struct scsipi_generic *)&cmd, sizeof(cmd), (u_char *)&posdata,
1.90      mjacob   2001:            sizeof(posdata), ST_RETRIES, ST_CTL_TIME, NULL,
1.124     enami    2002:            XS_CTL_SILENT | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK);
1.75      mjacob   2003:
                   2004:        if (error == 0) {
                   2005: #if    0
                   2006:                printf("posdata:");
1.76      enami    2007:                for (hard = 0; hard < sizeof(posdata); hard++)
1.75      mjacob   2008:                        printf("%02x ", posdata[hard] & 0xff);
                   2009:                printf("\n");
                   2010: #endif
                   2011:                if (posdata[0] & 0x4)   /* Block Position Unknown */
                   2012:                        error = EINVAL;
1.79      enami    2013:                else
1.75      mjacob   2014:                        *blkptr = _4btol(&posdata[4]);
                   2015:        }
                   2016:        return (error);
                   2017: }
                   2018:
                   2019: int
                   2020: st_setpos(st, hard, blkptr)
                   2021:        struct st_softc *st;
                   2022:        int hard;
                   2023:        u_int32_t *blkptr;
                   2024: {
                   2025:        int error;
1.98      drochner 2026:        struct scsi_tape_locate cmd;
1.75      mjacob   2027:
                   2028:        /*
1.134.2.6  nathanw  2029:         * We used to try and flush any buffered writes here.
                   2030:         * Now we push this onto user applications to either
                   2031:         * flush the pending writes themselves (via a zero count
                   2032:         * WRITE FILEMARKS command) or they can trust their tape
                   2033:         * drive to do this correctly for them.
                   2034:         *
                   2035:         * There are very ugly performance limitations otherwise.
1.77      mjacob   2036:         */
1.75      mjacob   2037:
1.134.2.2  nathanw  2038:        memset(&cmd, 0, sizeof(cmd));
1.75      mjacob   2039:        cmd.opcode = LOCATE;
                   2040:        if (hard)
1.98      drochner 2041:                cmd.byte2 = 1 << 2;
                   2042:        _lto4b(*blkptr, cmd.blkaddr);
1.134.2.1  nathanw  2043:        error = scsipi_command(st->sc_periph,
1.98      drochner 2044:                (struct scsipi_generic *)&cmd, sizeof(cmd),
                   2045:                NULL, 0, ST_RETRIES, ST_SPC_TIME, NULL, 0);
1.75      mjacob   2046:        /*
1.134.2.6  nathanw  2047:         * Note file && block number position now unknown (if
                   2048:         * these things ever start being maintained in this driver)
1.75      mjacob   2049:         */
1.134.2.6  nathanw  2050:        st->fileno = st->blkno = -1;
1.75      mjacob   2051:        return (error);
                   2052: }
                   2053:
                   2054:
1.3       deraadt  2055: /*
1.91      mjacob   2056:  * Look at the returned sense and act on the error and determine
                   2057:  * the unix error number to pass back..., 0 (== report no error),
                   2058:  * -1 = retry the operation, -2 continue error processing.
1.20      mycroft  2059:  */
1.51      mycroft  2060: int
1.20      mycroft  2061: st_interpret_sense(xs)
1.73      bouyer   2062:        struct scsipi_xfer *xs;
1.1       cgd      2063: {
1.134.2.1  nathanw  2064:        struct scsipi_periph *periph = xs->xs_periph;
1.73      bouyer   2065:        struct scsipi_sense_data *sense = &xs->sense.scsi_sense;
1.20      mycroft  2066:        struct buf *bp = xs->bp;
1.134.2.1  nathanw  2067:        struct st_softc *st = (void *)periph->periph_dev;
                   2068:        int retval = EJUSTRETURN;
1.114     thorpej  2069:        int doprint = ((xs->xs_control & XS_CTL_SILENT) == 0);
1.44      mycroft  2070:        u_int8_t key;
1.56      pk       2071:        int32_t info;
1.3       deraadt  2072:
                   2073:        /*
1.90      mjacob   2074:         * If it isn't a extended or extended/deferred error, let
                   2075:         * the generic code handle it.
1.3       deraadt  2076:         */
1.90      mjacob   2077:        if ((sense->error_code & SSD_ERRCODE) != 0x70 &&
                   2078:            (sense->error_code & SSD_ERRCODE) != 0x71) {        /* DEFFERRED */
1.91      mjacob   2079:                return (retval);
1.90      mjacob   2080:        }
                   2081:
1.64      mycroft  2082:        if (sense->error_code & SSD_ERRCODE_VALID)
                   2083:                info = _4btol(sense->info);
                   2084:        else
1.134.2.5  nathanw  2085:                info = (st->flags & ST_FIXEDBLOCKS) ?
                   2086:                    xs->datalen / st->blksize : xs->datalen;
1.90      mjacob   2087:        key = sense->flags & SSD_KEY;
                   2088:        st->mt_erreg = key;
1.115     mjacob   2089:        st->asc = sense->add_sense_code;
                   2090:        st->ascq = sense->add_sense_code_qual;
1.90      mjacob   2091:        st->mt_resid = (short) info;
1.134.2.4  nathanw  2092:
                   2093:        if (key == SKEY_NOT_READY && st->asc == 0x4 && st->ascq == 0x1) {
                   2094:                /* Not Ready, Logical Unit Is in Process Of Becoming Ready */
1.134.2.7  nathanw  2095:                if (!callout_active(&periph->periph_callout))
                   2096:                        scsipi_periph_freeze(periph, 1);
1.134.2.4  nathanw  2097:                callout_reset(&periph->periph_callout,
                   2098:                    hz, scsipi_periph_timed_thaw, periph);
                   2099:                return (ERESTART);
                   2100:        }
1.96      mjacob   2101:
                   2102:        /*
                   2103:         * If the device is not open yet, let generic handle
                   2104:         */
1.134.2.1  nathanw  2105:        if ((periph->periph_flags & PERIPH_OPEN) == 0) {
1.96      mjacob   2106:                return (retval);
                   2107:        }
                   2108:
1.134.2.6  nathanw  2109:        xs->resid = info;
1.20      mycroft  2110:        if (st->flags & ST_FIXEDBLOCKS) {
1.134.2.6  nathanw  2111:                if (bp) {
                   2112:                        xs->resid *= st->blksize;
                   2113:                        st->last_io_resid = xs->resid;
                   2114:                } else {
                   2115:                        st->last_ctl_resid = xs->resid;
                   2116:                }
                   2117:                if (key == SKEY_VOLUME_OVERFLOW) {
                   2118:                        st->flags |= ST_EIO_PENDING;
                   2119:                        if (bp)
                   2120:                                bp->b_resid = xs->resid;
                   2121:                } else if (sense->flags & SSD_EOM) {
1.93      mjacob   2122:                        if ((st->flags & ST_EARLYWARN) == 0)
                   2123:                                st->flags |= ST_EIO_PENDING;
                   2124:                        st->flags |= ST_EOM_PENDING;
1.134.2.6  nathanw  2125:                        if (bp) {
                   2126: #if 0
1.20      mycroft  2127:                                bp->b_resid = xs->resid;
1.134.2.6  nathanw  2128: #else
                   2129:                                /*
                   2130:                                 * Grotesque as it seems, the few times
                   2131:                                 * I've actually seen a non-zero resid,
                   2132:                                 * the tape drive actually lied and had
                   2133:                                 * written all the data!
                   2134:                                 */
                   2135:                                bp->b_resid = 0;
                   2136: #endif
                   2137:                        }
1.20      mycroft  2138:                }
1.64      mycroft  2139:                if (sense->flags & SSD_FILEMARK) {
1.20      mycroft  2140:                        st->flags |= ST_AT_FILEMARK;
                   2141:                        if (bp)
                   2142:                                bp->b_resid = xs->resid;
1.134.2.6  nathanw  2143:                        if (st->fileno != (daddr_t) -1) {
                   2144:                                st->fileno++;
                   2145:                                st->blkno = 0;
                   2146:                                st->flags |= ST_POSUPDATED;
                   2147:                        }
1.20      mycroft  2148:                }
1.64      mycroft  2149:                if (sense->flags & SSD_ILI) {
1.20      mycroft  2150:                        st->flags |= ST_EIO_PENDING;
                   2151:                        if (bp)
                   2152:                                bp->b_resid = xs->resid;
1.44      mycroft  2153:                        if (sense->error_code & SSD_ERRCODE_VALID &&
1.114     thorpej  2154:                            (xs->xs_control & XS_CTL_SILENT) == 0)
1.90      mjacob   2155:                                printf("%s: block wrong size, %d blocks "
                   2156:                                    "residual\n", st->sc_dev.dv_xname, info);
1.3       deraadt  2157:
1.20      mycroft  2158:                        /*
                   2159:                         * This quirk code helps the drive read
                   2160:                         * the first tape block, regardless of
                   2161:                         * format.  That is required for these
                   2162:                         * drives to return proper MODE SENSE
                   2163:                         * information.
                   2164:                         */
1.28      mycroft  2165:                        if ((st->quirks & ST_Q_SENSE_HELP) &&
1.134.2.1  nathanw  2166:                            (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0)
1.44      mycroft  2167:                                st->blksize -= 512;
1.134.2.6  nathanw  2168:                        else if ((st->flags & ST_POSUPDATED) == 0) {
                   2169:                                if (st->blkno != (daddr_t) -1) {
                   2170:                                        st->blkno +=
                   2171:                                            (xs->datalen / st->blksize);
                   2172:                                        st->flags |= ST_POSUPDATED;
                   2173:                                }
                   2174:                        }
1.6       mycroft  2175:                }
1.3       deraadt  2176:                /*
1.134.2.2  nathanw  2177:                 * If data wanted and no data was transferred, do it immediately
1.3       deraadt  2178:                 */
1.85      mjacob   2179:                if (xs->datalen && xs->resid >= xs->datalen) {
1.20      mycroft  2180:                        if (st->flags & ST_EIO_PENDING)
1.76      enami    2181:                                return (EIO);
1.20      mycroft  2182:                        if (st->flags & ST_AT_FILEMARK) {
                   2183:                                if (bp)
                   2184:                                        bp->b_resid = xs->resid;
1.134.2.1  nathanw  2185:                                return (0);
1.20      mycroft  2186:                        }
                   2187:                }
                   2188:        } else {                /* must be variable mode */
1.134.2.6  nathanw  2189:                if (bp) {
                   2190:                        st->last_io_resid = xs->resid;
                   2191:                } else {
                   2192:                        st->last_ctl_resid = xs->resid;
                   2193:                }
1.90      mjacob   2194:                if (sense->flags & SSD_EOM) {
                   2195:                        /*
                   2196:                         * The current semantics of this
                   2197:                         * driver requires EOM detection
1.93      mjacob   2198:                         * to return EIO unless early
                   2199:                         * warning detection is enabled
                   2200:                         * for variable mode (this is always
                   2201:                         * on for fixed block mode).
1.90      mjacob   2202:                         */
1.93      mjacob   2203:                        if (st->flags & ST_EARLYWARN) {
                   2204:                                st->flags |= ST_EOM_PENDING;
1.134.2.1  nathanw  2205:                                retval = 0;
1.93      mjacob   2206:                        } else {
                   2207:                                retval = EIO;
                   2208:                        }
1.90      mjacob   2209:
                   2210:                        /*
                   2211:                         * If it's an unadorned EOM detection,
                   2212:                         * suppress printing an error.
                   2213:                         */
                   2214:                        if (key == SKEY_NO_SENSE) {
                   2215:                                doprint = 0;
                   2216:                        }
                   2217:                } else if (sense->flags & SSD_FILEMARK) {
1.134.2.1  nathanw  2218:                        retval = 0;
1.134.2.6  nathanw  2219:                        if (st->fileno != (daddr_t) -1) {
                   2220:                                st->fileno++;
                   2221:                                st->blkno = 0;
                   2222:                                st->flags |= ST_POSUPDATED;
                   2223:                        }
1.90      mjacob   2224:                } else if (sense->flags & SSD_ILI) {
1.20      mycroft  2225:                        if (info < 0) {
1.3       deraadt  2226:                                /*
1.90      mjacob   2227:                                 * The tape record was bigger than the read
                   2228:                                 * we issued.
1.3       deraadt  2229:                                 */
1.114     thorpej  2230:                                if ((xs->xs_control & XS_CTL_SILENT) == 0) {
1.90      mjacob   2231:                                        printf("%s: %d-byte tape record too big"
                   2232:                                            " for %d-byte user buffer\n",
1.20      mycroft  2233:                                            st->sc_dev.dv_xname,
1.90      mjacob   2234:                                            xs->datalen - info, xs->datalen);
                   2235:                                }
                   2236:                                retval = EIO;
                   2237:                        } else {
1.134.2.1  nathanw  2238:                                retval = 0;
1.134.2.6  nathanw  2239:                                if (st->blkno != (daddr_t) -1) {
                   2240:                                        st->blkno++;
                   2241:                                        st->flags |= ST_POSUPDATED;
                   2242:                                }
1.20      mycroft  2243:                        }
1.3       deraadt  2244:                }
1.90      mjacob   2245:                if (bp)
                   2246:                        bp->b_resid = info;
1.20      mycroft  2247:        }
1.1       cgd      2248:
1.134.2.1  nathanw  2249: #ifndef SCSIPI_DEBUG
                   2250:        if (retval == 0 && key == SKEY_NO_SENSE)
1.90      mjacob   2251:                doprint = 0;
                   2252: #endif
                   2253:        if (key == SKEY_BLANK_CHECK) {
1.20      mycroft  2254:                /*
                   2255:                 * This quirk code helps the drive read the
                   2256:                 * first tape block, regardless of format.  That
                   2257:                 * is required for these drives to return proper
                   2258:                 * MODE SENSE information.
                   2259:                 */
1.28      mycroft  2260:                if ((st->quirks & ST_Q_SENSE_HELP) &&
1.134.2.1  nathanw  2261:                    (periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
1.20      mycroft  2262:                        /* still starting */
1.44      mycroft  2263:                        st->blksize -= 512;
1.20      mycroft  2264:                } else if (!(st->flags & (ST_2FM_AT_EOD | ST_BLANK_READ))) {
                   2265:                        st->flags |= ST_BLANK_READ;
                   2266:                        xs->resid = xs->datalen;
                   2267:                        if (bp) {
                   2268:                                bp->b_resid = xs->resid;
                   2269:                                /* return an EOF */
1.1       cgd      2270:                        }
1.134.2.1  nathanw  2271:                        retval = 0;
1.134.2.6  nathanw  2272:                        /* lost position */
                   2273:                        st->fileno = st->blkno = -1;
1.1       cgd      2274:                }
                   2275:        }
1.128     pk       2276:
                   2277:        /*
                   2278:         * If generic sense processing will continue, we should not
                   2279:         * print sense info here.
                   2280:         */
1.134.2.1  nathanw  2281:        if (retval == EJUSTRETURN)
1.128     pk       2282:                doprint = 0;
                   2283:
                   2284:        if (doprint) {
1.90      mjacob   2285: #ifdef SCSIVERBOSE
1.105     bouyer   2286:                scsipi_print_sense(xs, 0);
1.90      mjacob   2287: #else
1.134.2.1  nathanw  2288:                scsipi_printaddr(periph);
1.103     mjacob   2289:                printf("Sense Key 0x%02x", key);
1.90      mjacob   2290:                if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
1.131     pk       2291:                        switch (key) {
1.90      mjacob   2292:                        case SKEY_NOT_READY:
                   2293:                        case SKEY_ILLEGAL_REQUEST:
                   2294:                        case SKEY_UNIT_ATTENTION:
                   2295:                        case SKEY_WRITE_PROTECT:
                   2296:                                break;
1.134.2.6  nathanw  2297:                        case SKEY_VOLUME_OVERFLOW:
1.90      mjacob   2298:                        case SKEY_BLANK_CHECK:
                   2299:                                printf(", requested size: %d (decimal)", info);
1.131     pk       2300:                                break;
1.90      mjacob   2301:                        case SKEY_ABORTED_COMMAND:
1.134.2.1  nathanw  2302:                                if (xs->xs_retries)
1.90      mjacob   2303:                                        printf(", retrying");
                   2304:                                printf(", cmd 0x%x, info 0x%x",
                   2305:                                    xs->cmd->opcode, info);
                   2306:                                break;
                   2307:                        default:
                   2308:                                printf(", info = %d (decimal)", info);
                   2309:                        }
1.131     pk       2310:                }
1.90      mjacob   2311:                if (sense->extra_len != 0) {
1.131     pk       2312:                        int n;
                   2313:                        printf(", data =");
1.90      mjacob   2314:                        for (n = 0; n < sense->extra_len; n++)
                   2315:                                printf(" %02x", sense->cmd_spec_info[n]);
1.131     pk       2316:                }
1.90      mjacob   2317:                printf("\n");
1.128     pk       2318: #endif
1.90      mjacob   2319:        }
                   2320:        return (retval);
1.20      mycroft  2321: }
                   2322:
                   2323: /*
                   2324:  * The quirk here is that the drive returns some value to st_mode_sense
                   2325:  * incorrectly until the tape has actually passed by the head.
                   2326:  *
                   2327:  * The method is to set the drive to large fixed-block state (user-specified
                   2328:  * density and 1024-byte blocks), then read and rewind to get it to sense the
                   2329:  * tape.  If that doesn't work, try 512-byte fixed blocks.  If that doesn't
                   2330:  * work, as a last resort, try variable- length blocks.  The result will be
                   2331:  * the ability to do an accurate st_mode_sense.
                   2332:  *
                   2333:  * We know we can do a rewind because we just did a load, which implies rewind.
                   2334:  * Rewind seems preferable to space backward if we have a virgin tape.
                   2335:  *
                   2336:  * The rest of the code for this quirk is in ILI processing and BLANK CHECK
                   2337:  * error processing, both part of st_interpret_sense.
                   2338:  */
                   2339: int
                   2340: st_touch_tape(st)
1.44      mycroft  2341:        struct st_softc *st;
1.20      mycroft  2342: {
1.44      mycroft  2343:        char *buf;
                   2344:        int readsize;
1.20      mycroft  2345:        int error;
                   2346:
                   2347:        buf = malloc(1024, M_TEMP, M_NOWAIT);
1.76      enami    2348:        if (buf == NULL)
                   2349:                return (ENOMEM);
1.20      mycroft  2350:
1.134.2.1  nathanw  2351:        if ((error = st->ops(st, ST_OPS_MODESENSE, 0)) != 0)
1.20      mycroft  2352:                goto bad;
1.131     pk       2353:
                   2354:        /*
                   2355:         * If the block size is already known from the
                   2356:         * sense data, use it. Else start probing at 1024.
                   2357:         */
                   2358:        if (st->media_blksize > 0)
                   2359:                st->blksize = st->media_blksize;
                   2360:        else
                   2361:                st->blksize = 1024;
                   2362:
1.20      mycroft  2363:        do {
1.44      mycroft  2364:                switch (st->blksize) {
1.20      mycroft  2365:                case 512:
                   2366:                case 1024:
1.44      mycroft  2367:                        readsize = st->blksize;
1.20      mycroft  2368:                        st->flags |= ST_FIXEDBLOCKS;
                   2369:                        break;
                   2370:                default:
1.44      mycroft  2371:                        readsize = 1;
1.20      mycroft  2372:                        st->flags &= ~ST_FIXEDBLOCKS;
                   2373:                }
1.134.2.1  nathanw  2374:                if ((error = st->ops(st, ST_OPS_MODESELECT, XS_CTL_SILENT))
                   2375:                    != 0) {
1.126     pk       2376:                        /*
                   2377:                         * The device did not agree with the proposed
                   2378:                         * block size. If we exhausted our options,
                   2379:                         * return failure, else try another.
                   2380:                         */
                   2381:                        if (readsize == 1)
                   2382:                                goto bad;
                   2383:                        st->blksize -= 512;
                   2384:                        continue;
                   2385:                }
1.114     thorpej  2386:                st_read(st, buf, readsize, XS_CTL_SILENT);      /* XXX */
1.59      christos 2387:                if ((error = st_rewind(st, 0, 0)) != 0) {
1.20      mycroft  2388: bad:                   free(buf, M_TEMP);
1.76      enami    2389:                        return (error);
1.20      mycroft  2390:                }
1.44      mycroft  2391:        } while (readsize != 1 && readsize > st->blksize);
                   2392:
1.20      mycroft  2393:        free(buf, M_TEMP);
1.76      enami    2394:        return (0);
1.31      mycroft  2395: }
                   2396:
                   2397: int
1.48      cgd      2398: stdump(dev, blkno, va, size)
                   2399:        dev_t dev;
                   2400:        daddr_t blkno;
                   2401:        caddr_t va;
                   2402:        size_t size;
1.31      mycroft  2403: {
                   2404:
                   2405:        /* Not implemented. */
1.76      enami    2406:        return (ENXIO);
1.1       cgd      2407: }

CVSweb <webmaster@jp.NetBSD.org>