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

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

CVSweb <webmaster@jp.NetBSD.org>