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

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

CVSweb <webmaster@jp.NetBSD.org>