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

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

CVSweb <webmaster@jp.NetBSD.org>