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

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

CVSweb <webmaster@jp.NetBSD.org>