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

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

CVSweb <webmaster@jp.NetBSD.org>