The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/cam/scsi/scsi_sa.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Implementation of SCSI Sequential Access Peripheral driver for CAM.
    3  *
    4  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    5  *
    6  * Copyright (c) 1999, 2000 Matthew Jacob
    7  * Copyright (c) 2013, 2014, 2015, 2021 Spectra Logic Corporation
    8  * All rights reserved.
    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  *    without modification, immediately at the beginning of the file.
   16  * 2. The name of the author may not be used to endorse or promote products
   17  *    derived from this software without specific prior written permission.
   18  *
   19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29  * SUCH DAMAGE.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __FBSDID("$FreeBSD$");
   34 
   35 #include <sys/param.h>
   36 #include <sys/queue.h>
   37 #ifdef _KERNEL
   38 #include <sys/systm.h>
   39 #include <sys/kernel.h>
   40 #endif
   41 #include <sys/types.h>
   42 #include <sys/time.h>
   43 #include <sys/bio.h>
   44 #include <sys/limits.h>
   45 #include <sys/malloc.h>
   46 #include <sys/mtio.h>
   47 #ifdef _KERNEL
   48 #include <sys/conf.h>
   49 #include <sys/sbuf.h>
   50 #include <sys/sysctl.h>
   51 #include <sys/taskqueue.h>
   52 #endif
   53 #include <sys/fcntl.h>
   54 #include <sys/devicestat.h>
   55 
   56 #ifndef _KERNEL
   57 #include <stdio.h>
   58 #include <string.h>
   59 #endif
   60 
   61 #include <cam/cam.h>
   62 #include <cam/cam_ccb.h>
   63 #include <cam/cam_periph.h>
   64 #include <cam/cam_xpt_periph.h>
   65 #include <cam/cam_debug.h>
   66 
   67 #include <cam/scsi/scsi_all.h>
   68 #include <cam/scsi/scsi_message.h>
   69 #include <cam/scsi/scsi_sa.h>
   70 
   71 #ifdef _KERNEL
   72 
   73 #include "opt_sa.h"
   74 
   75 #ifndef SA_IO_TIMEOUT
   76 #define SA_IO_TIMEOUT           32
   77 #endif
   78 #ifndef SA_SPACE_TIMEOUT
   79 #define SA_SPACE_TIMEOUT        1 * 60
   80 #endif
   81 #ifndef SA_REWIND_TIMEOUT
   82 #define SA_REWIND_TIMEOUT       2 * 60
   83 #endif
   84 #ifndef SA_ERASE_TIMEOUT
   85 #define SA_ERASE_TIMEOUT        4 * 60
   86 #endif
   87 #ifndef SA_REP_DENSITY_TIMEOUT
   88 #define SA_REP_DENSITY_TIMEOUT  1
   89 #endif
   90 
   91 #define SCSIOP_TIMEOUT          (60 * 1000)     /* not an option */
   92 
   93 #define IO_TIMEOUT              (SA_IO_TIMEOUT * 60 * 1000)
   94 #define REWIND_TIMEOUT          (SA_REWIND_TIMEOUT * 60 * 1000)
   95 #define ERASE_TIMEOUT           (SA_ERASE_TIMEOUT * 60 * 1000)
   96 #define SPACE_TIMEOUT           (SA_SPACE_TIMEOUT * 60 * 1000)
   97 #define REP_DENSITY_TIMEOUT     (SA_REP_DENSITY_TIMEOUT * 60 * 1000)
   98 
   99 /*
  100  * Additional options that can be set for config: SA_1FM_AT_EOT
  101  */
  102 
  103 #ifndef UNUSED_PARAMETER
  104 #define UNUSED_PARAMETER(x)     x = x
  105 #endif
  106 
  107 #define QFRLS(ccb)      \
  108         if (((ccb)->ccb_h.status & CAM_DEV_QFRZN) != 0) \
  109                 cam_release_devq((ccb)->ccb_h.path, 0, 0, 0, FALSE)
  110 
  111 /*
  112  * Driver states
  113  */
  114 
  115 static MALLOC_DEFINE(M_SCSISA, "SCSI sa", "SCSI sequential access buffers");
  116 
  117 typedef enum {
  118         SA_STATE_NORMAL, SA_STATE_PROBE, SA_STATE_ABNORMAL
  119 } sa_state;
  120 
  121 #define ccb_pflags      ppriv_field0
  122 #define ccb_bp          ppriv_ptr1
  123 
  124 /* bits in ccb_pflags */
  125 #define SA_POSITION_UPDATED     0x1
  126 
  127 typedef enum {
  128         SA_FLAG_OPEN            = 0x00001,
  129         SA_FLAG_FIXED           = 0x00002,
  130         SA_FLAG_TAPE_LOCKED     = 0x00004,
  131         SA_FLAG_TAPE_MOUNTED    = 0x00008,
  132         SA_FLAG_TAPE_WP         = 0x00010,
  133         SA_FLAG_TAPE_WRITTEN    = 0x00020,
  134         SA_FLAG_EOM_PENDING     = 0x00040,
  135         SA_FLAG_EIO_PENDING     = 0x00080,
  136         SA_FLAG_EOF_PENDING     = 0x00100,
  137         SA_FLAG_ERR_PENDING     = (SA_FLAG_EOM_PENDING|SA_FLAG_EIO_PENDING|
  138                                    SA_FLAG_EOF_PENDING),
  139         SA_FLAG_INVALID         = 0x00200,
  140         SA_FLAG_COMP_ENABLED    = 0x00400,
  141         SA_FLAG_COMP_SUPP       = 0x00800,
  142         SA_FLAG_COMP_UNSUPP     = 0x01000,
  143         SA_FLAG_TAPE_FROZEN     = 0x02000,
  144         SA_FLAG_PROTECT_SUPP    = 0x04000,
  145 
  146         SA_FLAG_COMPRESSION     = (SA_FLAG_COMP_SUPP|SA_FLAG_COMP_ENABLED|
  147                                    SA_FLAG_COMP_UNSUPP),
  148         SA_FLAG_SCTX_INIT       = 0x08000,
  149         SA_FLAG_RSOC_TO_TRY     = 0x10000,
  150 } sa_flags;
  151 
  152 typedef enum {
  153         SA_MODE_REWIND          = 0x00,
  154         SA_MODE_NOREWIND        = 0x01,
  155         SA_MODE_OFFLINE         = 0x02
  156 } sa_mode;
  157 
  158 typedef enum {
  159         SA_TIMEOUT_ERASE,
  160         SA_TIMEOUT_LOAD,
  161         SA_TIMEOUT_LOCATE,
  162         SA_TIMEOUT_MODE_SELECT,
  163         SA_TIMEOUT_MODE_SENSE,
  164         SA_TIMEOUT_PREVENT,
  165         SA_TIMEOUT_READ,
  166         SA_TIMEOUT_READ_BLOCK_LIMITS,
  167         SA_TIMEOUT_READ_POSITION,
  168         SA_TIMEOUT_REP_DENSITY,
  169         SA_TIMEOUT_RESERVE,
  170         SA_TIMEOUT_REWIND,
  171         SA_TIMEOUT_SPACE,
  172         SA_TIMEOUT_TUR,
  173         SA_TIMEOUT_WRITE,
  174         SA_TIMEOUT_WRITE_FILEMARKS,
  175         SA_TIMEOUT_TYPE_MAX
  176 } sa_timeout_types;
  177 
  178 /*
  179  * These are the default timeout values that apply to all tape drives.  
  180  *
  181  * We get timeouts from the following places in order of increasing
  182  * priority:
  183  * 1. Driver default timeouts. (Set in the structure below.)
  184  * 2. Timeouts loaded from the drive via REPORT SUPPORTED OPERATION
  185  *    CODES.  (If the drive supports it, SPC-4/LTO-5 and newer should.)
  186  * 3. Global loader tunables, used for all sa(4) driver instances on
  187  *    a machine.
  188  * 4. Instance-specific loader tunables, used for say sa5.
  189  * 5. On the fly user sysctl changes.
  190  * 
  191  * Each step will overwrite the timeout value set from the one
  192  * before, so you go from general to most specific.
  193  */
  194 static struct sa_timeout_desc {
  195         const char *desc;
  196         int value;
  197 } sa_default_timeouts[SA_TIMEOUT_TYPE_MAX] = {
  198         {"erase",               ERASE_TIMEOUT},
  199         {"load",                REWIND_TIMEOUT},
  200         {"locate",              SPACE_TIMEOUT},
  201         {"mode_select",         SCSIOP_TIMEOUT},
  202         {"mode_sense",          SCSIOP_TIMEOUT},
  203         {"prevent",             SCSIOP_TIMEOUT},
  204         {"read",                IO_TIMEOUT},
  205         {"read_block_limits",   SCSIOP_TIMEOUT},
  206         {"read_position",       SCSIOP_TIMEOUT},
  207         {"report_density",      REP_DENSITY_TIMEOUT},
  208         {"reserve",             SCSIOP_TIMEOUT},
  209         {"rewind",              REWIND_TIMEOUT},
  210         {"space",               SPACE_TIMEOUT},
  211         {"tur",                 SCSIOP_TIMEOUT},
  212         {"write",               IO_TIMEOUT},
  213         {"write_filemarks",     IO_TIMEOUT},
  214 };
  215 
  216 typedef enum {
  217         SA_PARAM_NONE           = 0x000,
  218         SA_PARAM_BLOCKSIZE      = 0x001,
  219         SA_PARAM_DENSITY        = 0x002,
  220         SA_PARAM_COMPRESSION    = 0x004,
  221         SA_PARAM_BUFF_MODE      = 0x008,
  222         SA_PARAM_NUMBLOCKS      = 0x010,
  223         SA_PARAM_WP             = 0x020,
  224         SA_PARAM_SPEED          = 0x040,
  225         SA_PARAM_DENSITY_EXT    = 0x080,
  226         SA_PARAM_LBP            = 0x100,
  227         SA_PARAM_ALL            = 0x1ff
  228 } sa_params;
  229 
  230 typedef enum {
  231         SA_QUIRK_NONE           = 0x000,
  232         SA_QUIRK_NOCOMP         = 0x001, /* Can't deal with compression at all*/
  233         SA_QUIRK_FIXED          = 0x002, /* Force fixed mode */
  234         SA_QUIRK_VARIABLE       = 0x004, /* Force variable mode */
  235         SA_QUIRK_2FM            = 0x008, /* Needs Two File Marks at EOD */
  236         SA_QUIRK_1FM            = 0x010, /* No more than 1 File Mark at EOD */
  237         SA_QUIRK_NODREAD        = 0x020, /* Don't try and dummy read density */
  238         SA_QUIRK_NO_MODESEL     = 0x040, /* Don't do mode select at all */
  239         SA_QUIRK_NO_CPAGE       = 0x080, /* Don't use DEVICE COMPRESSION page */
  240         SA_QUIRK_NO_LONG_POS    = 0x100  /* No long position information */
  241 } sa_quirks;
  242 
  243 #define SA_QUIRK_BIT_STRING     \
  244         "\020"                  \
  245         "\001NOCOMP"            \
  246         "\002FIXED"             \
  247         "\003VARIABLE"          \
  248         "\0042FM"               \
  249         "\0051FM"               \
  250         "\006NODREAD"           \
  251         "\007NO_MODESEL"        \
  252         "\010NO_CPAGE"          \
  253         "\011NO_LONG_POS"
  254 
  255 #define SAMODE(z)       (dev2unit(z) & 0x3)
  256 #define SA_IS_CTRL(z)   (dev2unit(z) & (1 << 4))
  257 
  258 #define SA_NOT_CTLDEV   0
  259 #define SA_CTLDEV       1
  260 
  261 #define SA_ATYPE_R      0
  262 #define SA_ATYPE_NR     1
  263 #define SA_ATYPE_ER     2
  264 #define SA_NUM_ATYPES   3
  265 
  266 #define SAMINOR(ctl, access) \
  267         ((ctl << 4) | (access & 0x3))
  268 
  269 struct sa_devs {
  270         struct cdev *ctl_dev;
  271         struct cdev *r_dev;
  272         struct cdev *nr_dev;
  273         struct cdev *er_dev;
  274 };
  275 
  276 #define SASBADDBASE(sb, indent, data, xfmt, name, type, xsize, desc)    \
  277         sbuf_printf(sb, "%*s<%s type=\"%s\" size=\"%zd\" "              \
  278             "fmt=\"%s\" desc=\"%s\">" #xfmt "</%s>\n", indent, "",      \
  279             #name, #type, xsize, #xfmt, desc ? desc : "", data, #name);
  280 
  281 #define SASBADDINT(sb, indent, data, fmt, name)                         \
  282         SASBADDBASE(sb, indent, data, fmt, name, int, sizeof(data),     \
  283                     NULL)
  284 
  285 #define SASBADDINTDESC(sb, indent, data, fmt, name, desc)               \
  286         SASBADDBASE(sb, indent, data, fmt, name, int, sizeof(data),     \
  287                     desc)
  288 
  289 #define SASBADDUINT(sb, indent, data, fmt, name)                        \
  290         SASBADDBASE(sb, indent, data, fmt, name, uint, sizeof(data),    \
  291                     NULL)
  292 
  293 #define SASBADDUINTDESC(sb, indent, data, fmt, name, desc)              \
  294         SASBADDBASE(sb, indent, data, fmt, name, uint, sizeof(data),    \
  295                     desc)
  296 
  297 #define SASBADDFIXEDSTR(sb, indent, data, fmt, name)                    \
  298         SASBADDBASE(sb, indent, data, fmt, name, str, sizeof(data),     \
  299                     NULL)
  300 
  301 #define SASBADDFIXEDSTRDESC(sb, indent, data, fmt, name, desc)          \
  302         SASBADDBASE(sb, indent, data, fmt, name, str, sizeof(data),     \
  303                     desc)
  304 
  305 #define SASBADDVARSTR(sb, indent, data, fmt, name, maxlen)              \
  306         SASBADDBASE(sb, indent, data, fmt, name, str, maxlen, NULL)
  307 
  308 #define SASBADDVARSTRDESC(sb, indent, data, fmt, name, maxlen, desc)    \
  309         SASBADDBASE(sb, indent, data, fmt, name, str, maxlen, desc)
  310 
  311 #define SASBADDNODE(sb, indent, name) {                                 \
  312         sbuf_printf(sb, "%*s<%s type=\"%s\">\n", indent, "", #name,     \
  313             "node");                                                    \
  314         indent += 2;                                                    \
  315 }
  316 
  317 #define SASBADDNODENUM(sb, indent, name, num) {                         \
  318         sbuf_printf(sb, "%*s<%s type=\"%s\" num=\"%d\">\n", indent, "", \
  319             #name, "node", num);                                        \
  320         indent += 2;                                                    \
  321 }
  322 
  323 #define SASBENDNODE(sb, indent, name) {                                 \
  324         indent -= 2;                                                    \
  325         sbuf_printf(sb, "%*s</%s>\n", indent, "", #name);               \
  326 }
  327 
  328 #define SA_DENSITY_TYPES        4
  329 
  330 struct sa_prot_state {
  331         int initialized;
  332         uint32_t prot_method;
  333         uint32_t pi_length;
  334         uint32_t lbp_w;
  335         uint32_t lbp_r;
  336         uint32_t rbdp;
  337 };
  338 
  339 struct sa_prot_info {
  340         struct sa_prot_state cur_prot_state;
  341         struct sa_prot_state pending_prot_state;
  342 };
  343 
  344 /*
  345  * A table mapping protection parameters to their types and values.
  346  */
  347 struct sa_prot_map {
  348         char *name;
  349         mt_param_set_type param_type;
  350         off_t offset;
  351         uint32_t min_val;
  352         uint32_t max_val;
  353         uint32_t *value;
  354 } sa_prot_table[] = {
  355         { "prot_method", MT_PARAM_SET_UNSIGNED,
  356           __offsetof(struct sa_prot_state, prot_method), 
  357           /*min_val*/ 0, /*max_val*/ 255, NULL },
  358         { "pi_length", MT_PARAM_SET_UNSIGNED, 
  359           __offsetof(struct sa_prot_state, pi_length),
  360           /*min_val*/ 0, /*max_val*/ SA_CTRL_DP_PI_LENGTH_MASK, NULL },
  361         { "lbp_w", MT_PARAM_SET_UNSIGNED,
  362           __offsetof(struct sa_prot_state, lbp_w),
  363           /*min_val*/ 0, /*max_val*/ 1, NULL },
  364         { "lbp_r", MT_PARAM_SET_UNSIGNED,
  365           __offsetof(struct sa_prot_state, lbp_r),
  366           /*min_val*/ 0, /*max_val*/ 1, NULL },
  367         { "rbdp", MT_PARAM_SET_UNSIGNED,
  368           __offsetof(struct sa_prot_state, rbdp),
  369           /*min_val*/ 0, /*max_val*/ 1, NULL }
  370 };
  371 
  372 #define SA_NUM_PROT_ENTS nitems(sa_prot_table)
  373 
  374 #define SA_PROT_ENABLED(softc) ((softc->flags & SA_FLAG_PROTECT_SUPP)   \
  375         && (softc->prot_info.cur_prot_state.initialized != 0)           \
  376         && (softc->prot_info.cur_prot_state.prot_method != 0))
  377 
  378 #define SA_PROT_LEN(softc)      softc->prot_info.cur_prot_state.pi_length
  379 
  380 struct sa_softc {
  381         sa_state        state;
  382         sa_flags        flags;
  383         sa_quirks       quirks;
  384         u_int           si_flags;
  385         struct cam_periph *periph;
  386         struct          bio_queue_head bio_queue;
  387         int             queue_count;
  388         struct          devstat *device_stats;
  389         struct sa_devs  devs;
  390         int             open_count;
  391         int             num_devs_to_destroy;
  392         int             blk_gran;
  393         int             blk_mask;
  394         int             blk_shift;
  395         u_int32_t       max_blk;
  396         u_int32_t       min_blk;
  397         u_int32_t       maxio;
  398         u_int32_t       cpi_maxio;
  399         int             allow_io_split;
  400         int             inject_eom;
  401         int             set_pews_status;
  402         u_int32_t       comp_algorithm;
  403         u_int32_t       saved_comp_algorithm;
  404         u_int32_t       media_blksize;
  405         u_int32_t       last_media_blksize;
  406         u_int32_t       media_numblks;
  407         u_int8_t        media_density;
  408         u_int8_t        speed;
  409         u_int8_t        scsi_rev;
  410         u_int8_t        dsreg;          /* mtio mt_dsreg, redux */
  411         int             buffer_mode;
  412         int             filemarks;
  413         int             last_resid_was_io;
  414         uint8_t         density_type_bits[SA_DENSITY_TYPES];
  415         int             density_info_valid[SA_DENSITY_TYPES];
  416         uint8_t         density_info[SA_DENSITY_TYPES][SRDS_MAX_LENGTH];
  417         int             timeout_info[SA_TIMEOUT_TYPE_MAX];
  418 
  419         struct sa_prot_info     prot_info;
  420 
  421         int             sili;
  422         int             eot_warn;
  423 
  424         /*
  425          * Current position information.  -1 means that the given value is
  426          * unknown.  fileno and blkno are always calculated.  blkno is
  427          * relative to the previous file mark.  rep_fileno and rep_blkno
  428          * are as reported by the drive, if it supports the long form
  429          * report for the READ POSITION command.  rep_blkno is relative to
  430          * the beginning of the partition.
  431          *
  432          * bop means that the drive is at the beginning of the partition.
  433          * eop means that the drive is between early warning and end of
  434          * partition, inside the current partition.
  435          * bpew means that the position is in a PEWZ (Programmable Early
  436          * Warning Zone)
  437          */
  438         daddr_t         partition;      /* Absolute from BOT */
  439         daddr_t         fileno;         /* Relative to beginning of partition */
  440         daddr_t         blkno;          /* Relative to last file mark */
  441         daddr_t         rep_blkno;      /* Relative to beginning of partition */
  442         daddr_t         rep_fileno;     /* Relative to beginning of partition */
  443         int             bop;            /* Beginning of Partition */
  444         int             eop;            /* End of Partition */
  445         int             bpew;           /* Beyond Programmable Early Warning */
  446 
  447         /*
  448          * Latched Error Info
  449          */
  450         struct {
  451                 struct scsi_sense_data _last_io_sense;
  452                 u_int64_t _last_io_resid;
  453                 u_int8_t _last_io_cdb[CAM_MAX_CDBLEN];
  454                 struct scsi_sense_data _last_ctl_sense;
  455                 u_int64_t _last_ctl_resid;
  456                 u_int8_t _last_ctl_cdb[CAM_MAX_CDBLEN];
  457 #define last_io_sense   errinfo._last_io_sense
  458 #define last_io_resid   errinfo._last_io_resid
  459 #define last_io_cdb     errinfo._last_io_cdb
  460 #define last_ctl_sense  errinfo._last_ctl_sense
  461 #define last_ctl_resid  errinfo._last_ctl_resid
  462 #define last_ctl_cdb    errinfo._last_ctl_cdb
  463         } errinfo;
  464         /*
  465          * Misc other flags/state
  466          */
  467         u_int32_t
  468                                         : 29,
  469                 open_rdonly             : 1,    /* open read-only */
  470                 open_pending_mount      : 1,    /* open pending mount */
  471                 ctrl_mode               : 1;    /* control device open */
  472 
  473         struct task             sysctl_task;
  474         struct sysctl_ctx_list  sysctl_ctx;
  475         struct sysctl_oid       *sysctl_tree;
  476         struct sysctl_ctx_list  sysctl_timeout_ctx;
  477         struct sysctl_oid       *sysctl_timeout_tree;
  478 };
  479 
  480 struct sa_quirk_entry {
  481         struct scsi_inquiry_pattern inq_pat;    /* matching pattern */
  482         sa_quirks quirks;       /* specific quirk type */
  483         u_int32_t prefblk;      /* preferred blocksize when in fixed mode */
  484 };
  485 
  486 static struct sa_quirk_entry sa_quirk_table[] =
  487 {
  488         {
  489                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "OnStream",
  490                   "ADR*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_NODREAD |
  491                    SA_QUIRK_1FM|SA_QUIRK_NO_MODESEL, 32768
  492         },
  493         {
  494                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
  495                   "Python 06408*", "*"}, SA_QUIRK_NODREAD, 0
  496         },
  497         {
  498                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
  499                   "Python 25601*", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_NODREAD, 0
  500         },
  501         {
  502                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
  503                   "Python*", "*"}, SA_QUIRK_NODREAD, 0
  504         },
  505         {
  506                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
  507                   "VIPER 150*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
  508         },
  509         {
  510                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
  511                   "VIPER 2525 25462", "-011"},
  512                   SA_QUIRK_NOCOMP|SA_QUIRK_1FM|SA_QUIRK_NODREAD, 0
  513         },
  514         {
  515                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
  516                   "VIPER 2525*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024
  517         },
  518 #if     0
  519         {
  520                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
  521                   "C15*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_NO_CPAGE, 0,
  522         },
  523 #endif
  524         {
  525                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
  526                   "C56*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
  527         },
  528         {
  529                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
  530                   "T20*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
  531         },
  532         {
  533                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
  534                   "T4000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
  535         },
  536         {
  537                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
  538                   "HP-88780*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
  539         },
  540         {
  541                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY",
  542                   "*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
  543         },
  544         {
  545                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "M4 DATA",
  546                   "123107 SCSI*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
  547         },
  548         {       /* jreynold@primenet.com */
  549                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "Seagate",
  550                 "STT8000N*", "*"}, SA_QUIRK_1FM, 0
  551         },
  552         {       /* mike@sentex.net */
  553                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "Seagate",
  554                 "STT20000*", "*"}, SA_QUIRK_1FM, 0
  555         },
  556         {
  557                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "SEAGATE",
  558                 "DAT    06241-XXX", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
  559         },
  560         {
  561                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
  562                   " TDC 3600", "U07:"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
  563         },
  564         {
  565                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
  566                   " TDC 3800", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
  567         },
  568         {
  569                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
  570                   " TDC 4100", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
  571         },
  572         {
  573                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
  574                   " TDC 4200", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
  575         },
  576         {
  577                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
  578                   " SLR*", "*"}, SA_QUIRK_1FM, 0
  579         },
  580         {
  581                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK",
  582                   "5525ES*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
  583         },
  584         {
  585                 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK",
  586                   "51000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024
  587         }
  588 };
  589 
  590 static  d_open_t        saopen;
  591 static  d_close_t       saclose;
  592 static  d_strategy_t    sastrategy;
  593 static  d_ioctl_t       saioctl;
  594 static  periph_init_t   sainit;
  595 static  periph_ctor_t   saregister;
  596 static  periph_oninv_t  saoninvalidate;
  597 static  periph_dtor_t   sacleanup;
  598 static  periph_start_t  sastart;
  599 static  void            saasync(void *callback_arg, u_int32_t code,
  600                                 struct cam_path *path, void *arg);
  601 static  void            sadone(struct cam_periph *periph,
  602                                union ccb *start_ccb);
  603 static  int             saerror(union ccb *ccb, u_int32_t cam_flags,
  604                                 u_int32_t sense_flags);
  605 static int              samarkswanted(struct cam_periph *);
  606 static int              sacheckeod(struct cam_periph *periph);
  607 static int              sagetparams(struct cam_periph *periph,
  608                                     sa_params params_to_get,
  609                                     u_int32_t *blocksize, u_int8_t *density,
  610                                     u_int32_t *numblocks, int *buff_mode,
  611                                     u_int8_t *write_protect, u_int8_t *speed,
  612                                     int *comp_supported, int *comp_enabled,
  613                                     u_int32_t *comp_algorithm,
  614                                     sa_comp_t *comp_page,
  615                                     struct scsi_control_data_prot_subpage
  616                                     *prot_page, int dp_size,
  617                                     int prot_changeable);
  618 static int              sasetprot(struct cam_periph *periph,
  619                                   struct sa_prot_state *new_prot);
  620 static int              sasetparams(struct cam_periph *periph,
  621                                     sa_params params_to_set,
  622                                     u_int32_t blocksize, u_int8_t density,
  623                                     u_int32_t comp_algorithm,
  624                                     u_int32_t sense_flags);
  625 static int              sasetsili(struct cam_periph *periph,
  626                                   struct mtparamset *ps, int num_params);
  627 static int              saseteotwarn(struct cam_periph *periph,
  628                                      struct mtparamset *ps, int num_params);
  629 static void             safillprot(struct sa_softc *softc, int *indent,
  630                                    struct sbuf *sb);
  631 static void             sapopulateprots(struct sa_prot_state *cur_state,
  632                                         struct sa_prot_map *new_table,
  633                                         int table_ents);
  634 static struct sa_prot_map *safindprotent(char *name, struct sa_prot_map *table,
  635                                          int table_ents);
  636 static int              sasetprotents(struct cam_periph *periph,
  637                                       struct mtparamset *ps, int num_params);
  638 static struct sa_param_ent *safindparament(struct mtparamset *ps);
  639 static int              saparamsetlist(struct cam_periph *periph,
  640                                        struct mtsetlist *list, int need_copy);
  641 static  int             saextget(struct cdev *dev, struct cam_periph *periph,
  642                                  struct sbuf *sb, struct mtextget *g);
  643 static  int             saparamget(struct sa_softc *softc, struct sbuf *sb);
  644 static void             saprevent(struct cam_periph *periph, int action);
  645 static int              sarewind(struct cam_periph *periph);
  646 static int              saspace(struct cam_periph *periph, int count,
  647                                 scsi_space_code code);
  648 static void             sadevgonecb(void *arg);
  649 static void             sasetupdev(struct sa_softc *softc, struct cdev *dev);
  650 static void             saloadtotunables(struct sa_softc *softc);
  651 static void             sasysctlinit(void *context, int pending);
  652 static int              samount(struct cam_periph *, int, struct cdev *);
  653 static int              saretension(struct cam_periph *periph);
  654 static int              sareservereleaseunit(struct cam_periph *periph,
  655                                              int reserve);
  656 static int              saloadunload(struct cam_periph *periph, int load);
  657 static int              saerase(struct cam_periph *periph, int longerase);
  658 static int              sawritefilemarks(struct cam_periph *periph,
  659                                          int nmarks, int setmarks, int immed);
  660 static int              sagetpos(struct cam_periph *periph);
  661 static int              sardpos(struct cam_periph *periph, int, u_int32_t *);
  662 static int              sasetpos(struct cam_periph *periph, int, 
  663                                  struct mtlocate *);
  664 static void             safilldenstypesb(struct sbuf *sb, int *indent,
  665                                          uint8_t *buf, int buf_len,
  666                                          int is_density);
  667 static void             safilldensitysb(struct sa_softc *softc, int *indent,
  668                                         struct sbuf *sb);
  669 static void             saloadtimeouts(struct sa_softc *softc, union ccb *ccb);
  670 
  671 #ifndef SA_DEFAULT_IO_SPLIT
  672 #define SA_DEFAULT_IO_SPLIT     0
  673 #endif
  674 
  675 static int sa_allow_io_split = SA_DEFAULT_IO_SPLIT;
  676 
  677 /*
  678  * Tunable to allow the user to set a global allow_io_split value.  Note
  679  * that this WILL GO AWAY in FreeBSD 11.0.  Silently splitting the I/O up
  680  * is bad behavior, because it hides the true tape block size from the
  681  * application.
  682  */
  683 static SYSCTL_NODE(_kern_cam, OID_AUTO, sa, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  684     "CAM Sequential Access Tape Driver");
  685 SYSCTL_INT(_kern_cam_sa, OID_AUTO, allow_io_split, CTLFLAG_RDTUN,
  686     &sa_allow_io_split, 0, "Default I/O split value");
  687 
  688 static struct periph_driver sadriver =
  689 {
  690         sainit, "sa",
  691         TAILQ_HEAD_INITIALIZER(sadriver.units), /* generation */ 0
  692 };
  693 
  694 PERIPHDRIVER_DECLARE(sa, sadriver);
  695 
  696 /* For 2.2-stable support */
  697 #ifndef D_TAPE
  698 #define D_TAPE 0
  699 #endif
  700 
  701 static struct cdevsw sa_cdevsw = {
  702         .d_version =    D_VERSION,
  703         .d_open =       saopen,
  704         .d_close =      saclose,
  705         .d_read =       physread,
  706         .d_write =      physwrite,
  707         .d_ioctl =      saioctl,
  708         .d_strategy =   sastrategy,
  709         .d_name =       "sa",
  710         .d_flags =      D_TAPE | D_TRACKCLOSE,
  711 };
  712 
  713 static int
  714 saopen(struct cdev *dev, int flags, int fmt, struct thread *td)
  715 {
  716         struct cam_periph *periph;
  717         struct sa_softc *softc;
  718         int error;
  719 
  720         periph = (struct cam_periph *)dev->si_drv1;
  721         if (cam_periph_acquire(periph) != 0) {
  722                 return (ENXIO);
  723         }
  724 
  725         cam_periph_lock(periph);
  726 
  727         softc = (struct sa_softc *)periph->softc;
  728 
  729         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO,
  730             ("saopen(%s): softc=0x%x\n", devtoname(dev), softc->flags));
  731 
  732         if (SA_IS_CTRL(dev)) {
  733                 softc->ctrl_mode = 1;
  734                 softc->open_count++;
  735                 cam_periph_unlock(periph);
  736                 return (0);
  737         }
  738 
  739         if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
  740                 cam_periph_unlock(periph);
  741                 cam_periph_release(periph);
  742                 return (error);
  743         }
  744 
  745         if (softc->flags & SA_FLAG_OPEN) {
  746                 error = EBUSY;
  747         } else if (softc->flags & SA_FLAG_INVALID) {
  748                 error = ENXIO;
  749         } else {
  750                 /*
  751                  * Preserve whether this is a read_only open.
  752                  */
  753                 softc->open_rdonly = (flags & O_RDWR) == O_RDONLY;
  754 
  755                 /*
  756                  * The function samount ensures media is loaded and ready.
  757                  * It also does a device RESERVE if the tape isn't yet mounted.
  758                  *
  759                  * If the mount fails and this was a non-blocking open,
  760                  * make this a 'open_pending_mount' action.
  761                  */
  762                 error = samount(periph, flags, dev);
  763                 if (error && (flags & O_NONBLOCK)) {
  764                         softc->flags |= SA_FLAG_OPEN;
  765                         softc->open_pending_mount = 1;
  766                         softc->open_count++;
  767                         cam_periph_unhold(periph);
  768                         cam_periph_unlock(periph);
  769                         return (0);
  770                 }
  771         }
  772 
  773         if (error) {
  774                 cam_periph_unhold(periph);
  775                 cam_periph_unlock(periph);
  776                 cam_periph_release(periph);
  777                 return (error);
  778         }
  779 
  780         saprevent(periph, PR_PREVENT);
  781         softc->flags |= SA_FLAG_OPEN;
  782         softc->open_count++;
  783 
  784         cam_periph_unhold(periph);
  785         cam_periph_unlock(periph);
  786         return (error);
  787 }
  788 
  789 static int
  790 saclose(struct cdev *dev, int flag, int fmt, struct thread *td)
  791 {
  792         struct  cam_periph *periph;
  793         struct  sa_softc *softc;
  794         int     mode, error, writing, tmp, i;
  795         int     closedbits = SA_FLAG_OPEN;
  796 
  797         mode = SAMODE(dev);
  798         periph = (struct cam_periph *)dev->si_drv1;
  799         cam_periph_lock(periph);
  800 
  801         softc = (struct sa_softc *)periph->softc;
  802 
  803         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO,
  804             ("saclose(%s): softc=0x%x\n", devtoname(dev), softc->flags));
  805 
  806         softc->open_rdonly = 0; 
  807         if (SA_IS_CTRL(dev)) {
  808                 softc->ctrl_mode = 0;
  809                 softc->open_count--;
  810                 cam_periph_unlock(periph);
  811                 cam_periph_release(periph);
  812                 return (0);
  813         }
  814 
  815         if (softc->open_pending_mount) {
  816                 softc->flags &= ~SA_FLAG_OPEN;
  817                 softc->open_pending_mount = 0; 
  818                 softc->open_count--;
  819                 cam_periph_unlock(periph);
  820                 cam_periph_release(periph);
  821                 return (0);
  822         }
  823 
  824         if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
  825                 cam_periph_unlock(periph);
  826                 return (error);
  827         }
  828 
  829         /*
  830          * Were we writing the tape?
  831          */
  832         writing = (softc->flags & SA_FLAG_TAPE_WRITTEN) != 0;
  833 
  834         /*
  835          * See whether or not we need to write filemarks. If this
  836          * fails, we probably have to assume we've lost tape
  837          * position.
  838          */
  839         error = sacheckeod(periph);
  840         if (error) {
  841                 xpt_print(periph->path,
  842                     "failed to write terminating filemark(s)\n");
  843                 softc->flags |= SA_FLAG_TAPE_FROZEN;
  844         }
  845 
  846         /*
  847          * Whatever we end up doing, allow users to eject tapes from here on.
  848          */
  849         saprevent(periph, PR_ALLOW);
  850 
  851         /*
  852          * Decide how to end...
  853          */
  854         if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) {
  855                 closedbits |= SA_FLAG_TAPE_FROZEN;
  856         } else switch (mode) {
  857         case SA_MODE_OFFLINE:
  858                 /*
  859                  * An 'offline' close is an unconditional release of
  860                  * frozen && mount conditions, irrespective of whether
  861                  * these operations succeeded. The reason for this is
  862                  * to allow at least some kind of programmatic way
  863                  * around our state getting all fouled up. If somebody
  864                  * issues an 'offline' command, that will be allowed
  865                  * to clear state.
  866                  */
  867                 (void) sarewind(periph);
  868                 (void) saloadunload(periph, FALSE);
  869                 closedbits |= SA_FLAG_TAPE_MOUNTED|SA_FLAG_TAPE_FROZEN;
  870                 break;
  871         case SA_MODE_REWIND:
  872                 /*
  873                  * If the rewind fails, return an error- if anyone cares,
  874                  * but not overwriting any previous error.
  875                  *
  876                  * We don't clear the notion of mounted here, but we do
  877                  * clear the notion of frozen if we successfully rewound.
  878                  */
  879                 tmp = sarewind(periph);
  880                 if (tmp) {
  881                         if (error != 0)
  882                                 error = tmp;
  883                 } else {
  884                         closedbits |= SA_FLAG_TAPE_FROZEN;
  885                 }
  886                 break;
  887         case SA_MODE_NOREWIND:
  888                 /*
  889                  * If we're not rewinding/unloading the tape, find out
  890                  * whether we need to back up over one of two filemarks
  891                  * we wrote (if we wrote two filemarks) so that appends
  892                  * from this point on will be sane.
  893                  */
  894                 if (error == 0 && writing && (softc->quirks & SA_QUIRK_2FM)) {
  895                         tmp = saspace(periph, -1, SS_FILEMARKS);
  896                         if (tmp) {
  897                                 xpt_print(periph->path, "unable to backspace "
  898                                     "over one of double filemarks at end of "
  899                                     "tape\n");
  900                                 xpt_print(periph->path, "it is possible that "
  901                                     "this device needs a SA_QUIRK_1FM quirk set"
  902                                     "for it\n");
  903                                 softc->flags |= SA_FLAG_TAPE_FROZEN;
  904                         }
  905                 }
  906                 break;
  907         default:
  908                 xpt_print(periph->path, "unknown mode 0x%x in saclose\n", mode);
  909                 /* NOTREACHED */
  910                 break;
  911         }
  912 
  913         /*
  914          * We wish to note here that there are no more filemarks to be written.
  915          */
  916         softc->filemarks = 0;
  917         softc->flags &= ~SA_FLAG_TAPE_WRITTEN;
  918 
  919         /*
  920          * And we are no longer open for business.
  921          */
  922         softc->flags &= ~closedbits;
  923         softc->open_count--;
  924 
  925         /*
  926          * Invalidate any density information that depends on having tape
  927          * media in the drive.
  928          */
  929         for (i = 0; i < SA_DENSITY_TYPES; i++) {
  930                 if (softc->density_type_bits[i] & SRDS_MEDIA)
  931                         softc->density_info_valid[i] = 0;
  932         }
  933 
  934         /*
  935          * Inform users if tape state if frozen....
  936          */
  937         if (softc->flags & SA_FLAG_TAPE_FROZEN) {
  938                 xpt_print(periph->path, "tape is now frozen- use an OFFLINE, "
  939                     "REWIND or MTEOM command to clear this state.\n");
  940         }
  941 
  942         /* release the device if it is no longer mounted */
  943         if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0)
  944                 sareservereleaseunit(periph, FALSE);
  945 
  946         cam_periph_unhold(periph);
  947         cam_periph_unlock(periph);
  948         cam_periph_release(periph);
  949 
  950         return (error); 
  951 }
  952 
  953 /*
  954  * Actually translate the requested transfer into one the physical driver
  955  * can understand.  The transfer is described by a buf and will include
  956  * only one physical transfer.
  957  */
  958 static void
  959 sastrategy(struct bio *bp)
  960 {
  961         struct cam_periph *periph;
  962         struct sa_softc *softc;
  963 
  964         bp->bio_resid = bp->bio_bcount;
  965         if (SA_IS_CTRL(bp->bio_dev)) {
  966                 biofinish(bp, NULL, EINVAL);
  967                 return;
  968         }
  969         periph = (struct cam_periph *)bp->bio_dev->si_drv1;
  970         cam_periph_lock(periph);
  971 
  972         softc = (struct sa_softc *)periph->softc;
  973 
  974         if (softc->flags & SA_FLAG_INVALID) {
  975                 cam_periph_unlock(periph);
  976                 biofinish(bp, NULL, ENXIO);
  977                 return;
  978         }
  979 
  980         if (softc->flags & SA_FLAG_TAPE_FROZEN) {
  981                 cam_periph_unlock(periph);
  982                 biofinish(bp, NULL, EPERM);
  983                 return;
  984         }
  985 
  986         /*
  987          * This should actually never occur as the write(2)
  988          * system call traps attempts to write to a read-only
  989          * file descriptor.
  990          */
  991         if (bp->bio_cmd == BIO_WRITE && softc->open_rdonly) {
  992                 cam_periph_unlock(periph);
  993                 biofinish(bp, NULL, EBADF);
  994                 return;
  995         }
  996 
  997         if (softc->open_pending_mount) {
  998                 int error = samount(periph, 0, bp->bio_dev);
  999                 if (error) {
 1000                         cam_periph_unlock(periph);
 1001                         biofinish(bp, NULL, ENXIO);
 1002                         return;
 1003                 }
 1004                 saprevent(periph, PR_PREVENT);
 1005                 softc->open_pending_mount = 0;
 1006         }
 1007 
 1008         /*
 1009          * If it's a null transfer, return immediately
 1010          */
 1011         if (bp->bio_bcount == 0) {
 1012                 cam_periph_unlock(periph);
 1013                 biodone(bp);
 1014                 return;
 1015         }
 1016 
 1017         /* valid request?  */
 1018         if (softc->flags & SA_FLAG_FIXED) {
 1019                 /*
 1020                  * Fixed block device.  The byte count must
 1021                  * be a multiple of our block size.
 1022                  */
 1023                 if (((softc->blk_mask != ~0) &&
 1024                     ((bp->bio_bcount & softc->blk_mask) != 0)) ||
 1025                     ((softc->blk_mask == ~0) &&
 1026                     ((bp->bio_bcount % softc->min_blk) != 0))) {
 1027                         xpt_print(periph->path, "Invalid request.  Fixed block "
 1028                             "device requests must be a multiple of %d bytes\n",
 1029                             softc->min_blk);
 1030                         cam_periph_unlock(periph);
 1031                         biofinish(bp, NULL, EINVAL);
 1032                         return;
 1033                 }
 1034         } else if ((bp->bio_bcount > softc->max_blk) ||
 1035                    (bp->bio_bcount < softc->min_blk) ||
 1036                    (bp->bio_bcount & softc->blk_mask) != 0) {
 1037                 xpt_print_path(periph->path);
 1038                 printf("Invalid request.  Variable block "
 1039                     "device requests must be ");
 1040                 if (softc->blk_mask != 0) {
 1041                         printf("a multiple of %d ", (0x1 << softc->blk_gran));
 1042                 }
 1043                 printf("between %d and %d bytes\n", softc->min_blk,
 1044                     softc->max_blk);
 1045                 cam_periph_unlock(periph);
 1046                 biofinish(bp, NULL, EINVAL);
 1047                 return;
 1048         }
 1049 
 1050         /*
 1051          * Place it at the end of the queue.
 1052          */
 1053         bioq_insert_tail(&softc->bio_queue, bp);
 1054         softc->queue_count++;
 1055 #if     0
 1056         CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
 1057             ("sastrategy: queuing a %ld %s byte %s\n", bp->bio_bcount,
 1058             (softc->flags & SA_FLAG_FIXED)?  "fixed" : "variable",
 1059             (bp->bio_cmd == BIO_READ)? "read" : "write"));
 1060 #endif
 1061         if (softc->queue_count > 1) {
 1062                 CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
 1063                     ("sastrategy: queue count now %d\n", softc->queue_count));
 1064         }
 1065 
 1066         /*
 1067          * Schedule ourselves for performing the work.
 1068          */
 1069         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 1070         cam_periph_unlock(periph);
 1071 
 1072         return;
 1073 }
 1074 
 1075 static int
 1076 sasetsili(struct cam_periph *periph, struct mtparamset *ps, int num_params)
 1077 {
 1078         uint32_t sili_blocksize;
 1079         struct sa_softc *softc;
 1080         int error;
 1081 
 1082         error = 0;
 1083         softc = (struct sa_softc *)periph->softc;
 1084 
 1085         if (ps->value_type != MT_PARAM_SET_SIGNED) {
 1086                 snprintf(ps->error_str, sizeof(ps->error_str),
 1087                     "sili is a signed parameter");
 1088                 goto bailout;
 1089         }
 1090         if ((ps->value.value_signed < 0)
 1091          || (ps->value.value_signed > 1)) {
 1092                 snprintf(ps->error_str, sizeof(ps->error_str),
 1093                     "invalid sili value %jd", (intmax_t)ps->value.value_signed);
 1094                 goto bailout_error;
 1095         }
 1096         /*
 1097          * We only set the SILI flag in variable block
 1098          * mode.  You'll get a check condition in fixed
 1099          * block mode if things don't line up in any case.
 1100          */
 1101         if (softc->flags & SA_FLAG_FIXED) {
 1102                 snprintf(ps->error_str, sizeof(ps->error_str),
 1103                     "can't set sili bit in fixed block mode");
 1104                 goto bailout_error;
 1105         }
 1106         if (softc->sili == ps->value.value_signed)
 1107                 goto bailout;
 1108 
 1109         if (ps->value.value_signed == 1)
 1110                 sili_blocksize = 4;
 1111         else
 1112                 sili_blocksize = 0;
 1113 
 1114         error = sasetparams(periph, SA_PARAM_BLOCKSIZE,
 1115                             sili_blocksize, 0, 0, SF_QUIET_IR);
 1116         if (error != 0) {
 1117                 snprintf(ps->error_str, sizeof(ps->error_str),
 1118                     "sasetparams() returned error %d", error);
 1119                 goto bailout_error;
 1120         }
 1121 
 1122         softc->sili = ps->value.value_signed;
 1123 
 1124 bailout:
 1125         ps->status = MT_PARAM_STATUS_OK;
 1126         return (error);
 1127 
 1128 bailout_error:
 1129         ps->status = MT_PARAM_STATUS_ERROR;
 1130         if (error == 0)
 1131                 error = EINVAL;
 1132 
 1133         return (error);
 1134 }
 1135 
 1136 static int
 1137 saseteotwarn(struct cam_periph *periph, struct mtparamset *ps, int num_params)
 1138 {
 1139         struct sa_softc *softc;
 1140         int error;
 1141 
 1142         error = 0;
 1143         softc = (struct sa_softc *)periph->softc;
 1144 
 1145         if (ps->value_type != MT_PARAM_SET_SIGNED) {
 1146                 snprintf(ps->error_str, sizeof(ps->error_str),
 1147                     "eot_warn is a signed parameter");
 1148                 ps->status = MT_PARAM_STATUS_ERROR;
 1149                 goto bailout;
 1150         }
 1151         if ((ps->value.value_signed < 0)
 1152          || (ps->value.value_signed > 1)) {
 1153                 snprintf(ps->error_str, sizeof(ps->error_str),
 1154                     "invalid eot_warn value %jd\n",
 1155                     (intmax_t)ps->value.value_signed);
 1156                 ps->status = MT_PARAM_STATUS_ERROR;
 1157                 goto bailout;
 1158         }
 1159         softc->eot_warn = ps->value.value_signed;
 1160         ps->status = MT_PARAM_STATUS_OK;
 1161 bailout:
 1162         if (ps->status != MT_PARAM_STATUS_OK)
 1163                 error = EINVAL;
 1164 
 1165         return (error);
 1166 }
 1167 
 1168 static void
 1169 safillprot(struct sa_softc *softc, int *indent, struct sbuf *sb)
 1170 {
 1171         int tmpint;
 1172 
 1173         SASBADDNODE(sb, *indent, protection);
 1174         if (softc->flags & SA_FLAG_PROTECT_SUPP)
 1175                 tmpint = 1;
 1176         else
 1177                 tmpint = 0;
 1178         SASBADDINTDESC(sb, *indent, tmpint, %d, protection_supported,
 1179             "Set to 1 if protection information is supported");
 1180 
 1181         if ((tmpint != 0)
 1182          && (softc->prot_info.cur_prot_state.initialized != 0)) {
 1183                 struct sa_prot_state *prot;
 1184 
 1185                 prot = &softc->prot_info.cur_prot_state;
 1186 
 1187                 SASBADDUINTDESC(sb, *indent, prot->prot_method, %u,
 1188                     prot_method, "Current Protection Method");
 1189                 SASBADDUINTDESC(sb, *indent, prot->pi_length, %u,
 1190                     pi_length, "Length of Protection Information");
 1191                 SASBADDUINTDESC(sb, *indent, prot->lbp_w, %u,
 1192                     lbp_w, "Check Protection on Writes");
 1193                 SASBADDUINTDESC(sb, *indent, prot->lbp_r, %u,
 1194                     lbp_r, "Check and Include Protection on Reads");
 1195                 SASBADDUINTDESC(sb, *indent, prot->rbdp, %u,
 1196                     rbdp, "Transfer Protection Information for RECOVER "
 1197                     "BUFFERED DATA command");
 1198         }
 1199         SASBENDNODE(sb, *indent, protection);
 1200 }
 1201 
 1202 static void
 1203 sapopulateprots(struct sa_prot_state *cur_state, struct sa_prot_map *new_table,
 1204     int table_ents)
 1205 {
 1206         int i;
 1207 
 1208         bcopy(sa_prot_table, new_table, min(table_ents * sizeof(*new_table),
 1209             sizeof(sa_prot_table)));
 1210 
 1211         table_ents = min(table_ents, SA_NUM_PROT_ENTS);
 1212 
 1213         for (i = 0; i < table_ents; i++)
 1214                 new_table[i].value = (uint32_t *)((uint8_t *)cur_state +
 1215                     new_table[i].offset);
 1216 
 1217         return;
 1218 }
 1219 
 1220 static struct sa_prot_map *
 1221 safindprotent(char *name, struct sa_prot_map *table, int table_ents)
 1222 {
 1223         char *prot_name = "protection.";
 1224         int i, prot_len;
 1225 
 1226         prot_len = strlen(prot_name);
 1227 
 1228         /*
 1229          * This shouldn't happen, but we check just in case.
 1230          */
 1231         if (strncmp(name, prot_name, prot_len) != 0)
 1232                 goto bailout;
 1233 
 1234         for (i = 0; i < table_ents; i++) {
 1235                 if (strcmp(&name[prot_len], table[i].name) != 0)
 1236                         continue;
 1237                 return (&table[i]);
 1238         }
 1239 bailout:
 1240         return (NULL);
 1241 }
 1242 
 1243 static int
 1244 sasetprotents(struct cam_periph *periph, struct mtparamset *ps, int num_params)
 1245 {
 1246         struct sa_softc *softc;
 1247         struct sa_prot_map prot_ents[SA_NUM_PROT_ENTS];
 1248         struct sa_prot_state new_state;
 1249         int error;
 1250         int i;
 1251 
 1252         softc = (struct sa_softc *)periph->softc;
 1253         error = 0;
 1254 
 1255         /*
 1256          * Make sure that this tape drive supports protection information.
 1257          * Otherwise we can't set anything.
 1258          */
 1259         if ((softc->flags & SA_FLAG_PROTECT_SUPP) == 0) {
 1260                 snprintf(ps[0].error_str, sizeof(ps[0].error_str),
 1261                     "Protection information is not supported for this device");
 1262                 ps[0].status = MT_PARAM_STATUS_ERROR;
 1263                 goto bailout;
 1264         }
 1265 
 1266         /*
 1267          * We can't operate with physio(9) splitting enabled, because there
 1268          * is no way to insure (especially in variable block mode) that
 1269          * what the user writes (with a checksum block at the end) will 
 1270          * make it into the sa(4) driver intact.
 1271          */
 1272         if ((softc->si_flags & SI_NOSPLIT) == 0) {
 1273                 snprintf(ps[0].error_str, sizeof(ps[0].error_str),
 1274                     "Protection information cannot be enabled with I/O "
 1275                     "splitting");
 1276                 ps[0].status = MT_PARAM_STATUS_ERROR;
 1277                 goto bailout;
 1278         }
 1279 
 1280         /*
 1281          * Take the current cached protection state and use that as the
 1282          * basis for our new entries.
 1283          */
 1284         bcopy(&softc->prot_info.cur_prot_state, &new_state, sizeof(new_state));
 1285 
 1286         /*
 1287          * Populate the table mapping property names to pointers into the
 1288          * state structure.
 1289          */
 1290         sapopulateprots(&new_state, prot_ents, SA_NUM_PROT_ENTS);
 1291 
 1292         /*
 1293          * For each parameter the user passed in, make sure the name, type
 1294          * and value are valid.
 1295          */
 1296         for (i = 0; i < num_params; i++) {
 1297                 struct sa_prot_map *ent;
 1298 
 1299                 ent = safindprotent(ps[i].value_name, prot_ents,
 1300                     SA_NUM_PROT_ENTS);
 1301                 if (ent == NULL) {
 1302                         ps[i].status = MT_PARAM_STATUS_ERROR;
 1303                         snprintf(ps[i].error_str, sizeof(ps[i].error_str),
 1304                             "Invalid protection entry name %s",
 1305                             ps[i].value_name);
 1306                         error = EINVAL;
 1307                         goto bailout;
 1308                 }
 1309                 if (ent->param_type != ps[i].value_type) {
 1310                         ps[i].status = MT_PARAM_STATUS_ERROR;
 1311                         snprintf(ps[i].error_str, sizeof(ps[i].error_str),
 1312                             "Supplied type %d does not match actual type %d",
 1313                             ps[i].value_type, ent->param_type);
 1314                         error = EINVAL;
 1315                         goto bailout;
 1316                 }
 1317                 if ((ps[i].value.value_unsigned < ent->min_val)
 1318                  || (ps[i].value.value_unsigned > ent->max_val)) {
 1319                         ps[i].status = MT_PARAM_STATUS_ERROR;
 1320                         snprintf(ps[i].error_str, sizeof(ps[i].error_str),
 1321                             "Value %ju is outside valid range %u - %u",
 1322                             (uintmax_t)ps[i].value.value_unsigned, ent->min_val,
 1323                             ent->max_val);
 1324                         error = EINVAL;
 1325                         goto bailout;
 1326                 }
 1327                 *(ent->value) = ps[i].value.value_unsigned;
 1328         }
 1329 
 1330         /*
 1331          * Actually send the protection settings to the drive.
 1332          */
 1333         error = sasetprot(periph, &new_state);
 1334         if (error != 0) {
 1335                 for (i = 0; i < num_params; i++) {
 1336                         ps[i].status = MT_PARAM_STATUS_ERROR;
 1337                         snprintf(ps[i].error_str, sizeof(ps[i].error_str),
 1338                             "Unable to set parameter, see dmesg(8)");
 1339                 }
 1340                 goto bailout;
 1341         }
 1342 
 1343         /*
 1344          * Let the user know that his settings were stored successfully.
 1345          */
 1346         for (i = 0; i < num_params; i++)
 1347                 ps[i].status = MT_PARAM_STATUS_OK;
 1348 
 1349 bailout:
 1350         return (error);
 1351 }
 1352 /*
 1353  * Entry handlers generally only handle a single entry.  Node handlers will
 1354  * handle a contiguous range of parameters to set in a single call.
 1355  */
 1356 typedef enum {
 1357         SA_PARAM_TYPE_ENTRY,
 1358         SA_PARAM_TYPE_NODE
 1359 } sa_param_type;
 1360 
 1361 struct sa_param_ent {
 1362         char *name;
 1363         sa_param_type param_type;
 1364         int (*set_func)(struct cam_periph *periph, struct mtparamset *ps,
 1365                         int num_params);
 1366 } sa_param_table[] = {
 1367         {"sili", SA_PARAM_TYPE_ENTRY, sasetsili },
 1368         {"eot_warn", SA_PARAM_TYPE_ENTRY, saseteotwarn },
 1369         {"protection.", SA_PARAM_TYPE_NODE, sasetprotents }
 1370 };
 1371 
 1372 static struct sa_param_ent *
 1373 safindparament(struct mtparamset *ps)
 1374 {
 1375         unsigned int i;
 1376 
 1377         for (i = 0; i < nitems(sa_param_table); i++){
 1378                 /*
 1379                  * For entries, we compare all of the characters.  For
 1380                  * nodes, we only compare the first N characters.  The node
 1381                  * handler will decode the rest.
 1382                  */
 1383                 if (sa_param_table[i].param_type == SA_PARAM_TYPE_ENTRY) {
 1384                         if (strcmp(ps->value_name, sa_param_table[i].name) != 0)
 1385                                 continue;
 1386                 } else {
 1387                         if (strncmp(ps->value_name, sa_param_table[i].name,
 1388                             strlen(sa_param_table[i].name)) != 0)
 1389                                 continue;
 1390                 }
 1391                 return (&sa_param_table[i]);
 1392         }
 1393 
 1394         return (NULL);
 1395 }
 1396 
 1397 /*
 1398  * Go through a list of parameters, coalescing contiguous parameters with
 1399  * the same parent node into a single call to a set_func.
 1400  */
 1401 static int
 1402 saparamsetlist(struct cam_periph *periph, struct mtsetlist *list,
 1403     int need_copy)
 1404 {
 1405         int i, contig_ents;
 1406         int error;
 1407         struct mtparamset *params, *first;
 1408         struct sa_param_ent *first_ent;
 1409 
 1410         error = 0;
 1411         params = NULL;
 1412 
 1413         if (list->num_params == 0)
 1414                 /* Nothing to do */
 1415                 goto bailout;
 1416 
 1417         /*
 1418          * Verify that the user has the correct structure size.
 1419          */
 1420         if ((list->num_params * sizeof(struct mtparamset)) !=
 1421              list->param_len) {
 1422                 xpt_print(periph->path, "%s: length of params %d != "
 1423                     "sizeof(struct mtparamset) %zd * num_params %d\n",
 1424                     __func__, list->param_len, sizeof(struct mtparamset),
 1425                     list->num_params);
 1426                 error = EINVAL;
 1427                 goto bailout;
 1428         }
 1429 
 1430         if (need_copy != 0) {
 1431                 /*
 1432                  * XXX KDM will dropping the lock cause an issue here?
 1433                  */
 1434                 cam_periph_unlock(periph);
 1435                 params = malloc(list->param_len, M_SCSISA, M_WAITOK | M_ZERO);
 1436                 error = copyin(list->params, params, list->param_len);
 1437                 cam_periph_lock(periph);
 1438 
 1439                 if (error != 0)
 1440                         goto bailout;
 1441         } else {
 1442                 params = list->params;
 1443         }
 1444 
 1445         contig_ents = 0;
 1446         first = NULL;
 1447         first_ent = NULL;
 1448         for (i = 0; i < list->num_params; i++) {
 1449                 struct sa_param_ent *ent;
 1450 
 1451                 ent = safindparament(&params[i]);
 1452                 if (ent == NULL) {
 1453                         snprintf(params[i].error_str,
 1454                             sizeof(params[i].error_str),
 1455                             "%s: cannot find parameter %s", __func__,
 1456                             params[i].value_name);
 1457                         params[i].status = MT_PARAM_STATUS_ERROR;
 1458                         break;
 1459                 }
 1460 
 1461                 if (first != NULL) {
 1462                         if (first_ent == ent) {
 1463                                 /*
 1464                                  * We're still in a contiguous list of
 1465                                  * parameters that can be handled by one
 1466                                  * node handler.
 1467                                  */
 1468                                 contig_ents++;
 1469                                 continue;
 1470                         } else {
 1471                                 error = first_ent->set_func(periph, first,
 1472                                     contig_ents);
 1473                                 first = NULL;
 1474                                 first_ent = NULL;
 1475                                 contig_ents = 0;
 1476                                 if (error != 0) {
 1477                                         error = 0;
 1478                                         break;
 1479                                 }
 1480                         }
 1481                 }
 1482                 if (ent->param_type == SA_PARAM_TYPE_NODE) {
 1483                         first = &params[i];
 1484                         first_ent = ent;
 1485                         contig_ents = 1;
 1486                 } else {
 1487                         error = ent->set_func(periph, &params[i], 1);
 1488                         if (error != 0) {
 1489                                 error = 0;
 1490                                 break;
 1491                         }
 1492                 }
 1493         }
 1494         if (first != NULL)
 1495                 first_ent->set_func(periph, first, contig_ents);
 1496 
 1497 bailout:
 1498         if (need_copy != 0) {
 1499                 if (error != EFAULT) {
 1500                         cam_periph_unlock(periph);
 1501                         copyout(params, list->params, list->param_len);
 1502                         cam_periph_lock(periph);
 1503                 }
 1504                 free(params, M_SCSISA);
 1505         }
 1506         return (error);
 1507 }
 1508 
 1509 static int
 1510 sagetparams_common(struct cdev *dev, struct cam_periph *periph)
 1511 {
 1512         struct sa_softc *softc;
 1513         u_int8_t write_protect;
 1514         int comp_enabled, comp_supported, error;
 1515 
 1516         softc = (struct sa_softc *)periph->softc;
 1517 
 1518         if (softc->open_pending_mount)
 1519                 return (0);
 1520 
 1521         /* The control device may issue getparams() if there are no opens. */
 1522         if (SA_IS_CTRL(dev) && (softc->flags & SA_FLAG_OPEN) != 0)
 1523                 return (0);
 1524 
 1525         error = sagetparams(periph, SA_PARAM_ALL, &softc->media_blksize,
 1526             &softc->media_density, &softc->media_numblks, &softc->buffer_mode,
 1527             &write_protect, &softc->speed, &comp_supported, &comp_enabled,
 1528             &softc->comp_algorithm, NULL, NULL, 0, 0);
 1529         if (error)
 1530                 return (error);
 1531         if (write_protect)
 1532                 softc->flags |= SA_FLAG_TAPE_WP;
 1533         else
 1534                 softc->flags &= ~SA_FLAG_TAPE_WP;
 1535         softc->flags &= ~SA_FLAG_COMPRESSION;
 1536         if (comp_supported) {
 1537                 if (softc->saved_comp_algorithm == 0)
 1538                         softc->saved_comp_algorithm =
 1539                             softc->comp_algorithm;
 1540                 softc->flags |= SA_FLAG_COMP_SUPP;
 1541                 if (comp_enabled)
 1542                         softc->flags |= SA_FLAG_COMP_ENABLED;
 1543         } else  
 1544                 softc->flags |= SA_FLAG_COMP_UNSUPP;
 1545 
 1546         return (0);
 1547 }
 1548 
 1549 #define PENDING_MOUNT_CHECK(softc, periph, dev)         \
 1550         if (softc->open_pending_mount) {                \
 1551                 error = samount(periph, 0, dev);        \
 1552                 if (error) {                            \
 1553                         break;                          \
 1554                 }                                       \
 1555                 saprevent(periph, PR_PREVENT);          \
 1556                 softc->open_pending_mount = 0;          \
 1557         }
 1558 
 1559 static int
 1560 saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
 1561 {
 1562         struct cam_periph *periph;
 1563         struct sa_softc *softc;
 1564         scsi_space_code spaceop;
 1565         int didlockperiph = 0;
 1566         int mode;
 1567         int error = 0;
 1568 
 1569         mode = SAMODE(dev);
 1570         error = 0;              /* shut up gcc */
 1571         spaceop = 0;            /* shut up gcc */
 1572 
 1573         periph = (struct cam_periph *)dev->si_drv1;
 1574         cam_periph_lock(periph);
 1575         softc = (struct sa_softc *)periph->softc;
 1576 
 1577         /*
 1578          * Check for control mode accesses. We allow MTIOCGET and
 1579          * MTIOCERRSTAT (but need to be the only one open in order
 1580          * to clear latched status), and MTSETBSIZE, MTSETDNSTY
 1581          * and MTCOMP (but need to be the only one accessing this
 1582          * device to run those).
 1583          */
 1584 
 1585         if (SA_IS_CTRL(dev)) {
 1586                 switch (cmd) {
 1587                 case MTIOCGETEOTMODEL:
 1588                 case MTIOCGET:
 1589                 case MTIOCEXTGET:
 1590                 case MTIOCPARAMGET:
 1591                 case MTIOCRBLIM:
 1592                         break;
 1593                 case MTIOCERRSTAT:
 1594                         /*
 1595                          * If the periph isn't already locked, lock it
 1596                          * so our MTIOCERRSTAT can reset latched error stats.
 1597                          *
 1598                          * If the periph is already locked, skip it because
 1599                          * we're just getting status and it'll be up to the
 1600                          * other thread that has this device open to do
 1601                          * an MTIOCERRSTAT that would clear latched status.
 1602                          */
 1603                         if ((periph->flags & CAM_PERIPH_LOCKED) == 0) {
 1604                                 error = cam_periph_hold(periph, PRIBIO|PCATCH);
 1605                                 if (error != 0) {
 1606                                         cam_periph_unlock(periph);
 1607                                         return (error);
 1608                                 }
 1609                                 didlockperiph = 1;
 1610                         }
 1611                         break;
 1612 
 1613                 case MTIOCTOP:
 1614                 {
 1615                         struct mtop *mt = (struct mtop *) arg;
 1616 
 1617                         /*
 1618                          * Check to make sure it's an OP we can perform
 1619                          * with no media inserted.
 1620                          */
 1621                         switch (mt->mt_op) {
 1622                         case MTSETBSIZ:
 1623                         case MTSETDNSTY:
 1624                         case MTCOMP:
 1625                                 mt = NULL;
 1626                                 /* FALLTHROUGH */
 1627                         default:
 1628                                 break;
 1629                         }
 1630                         if (mt != NULL) {
 1631                                 break;
 1632                         }
 1633                         /* FALLTHROUGH */
 1634                 }
 1635                 case MTIOCSETEOTMODEL:
 1636                         /*
 1637                          * We need to acquire the peripheral here rather
 1638                          * than at open time because we are sharing writable
 1639                          * access to data structures.
 1640                          */
 1641                         error = cam_periph_hold(periph, PRIBIO|PCATCH);
 1642                         if (error != 0) {
 1643                                 cam_periph_unlock(periph);
 1644                                 return (error);
 1645                         }
 1646                         didlockperiph = 1;
 1647                         break;
 1648 
 1649                 default:
 1650                         cam_periph_unlock(periph);
 1651                         return (EINVAL);
 1652                 }
 1653         }
 1654 
 1655         /*
 1656          * Find the device that the user is talking about
 1657          */
 1658         switch (cmd) {
 1659         case MTIOCGET:
 1660         {
 1661                 struct mtget *g = (struct mtget *)arg;
 1662 
 1663                 error = sagetparams_common(dev, periph);
 1664                 if (error)
 1665                         break;
 1666                 bzero(g, sizeof(struct mtget));
 1667                 g->mt_type = MT_ISAR;
 1668                 if (softc->flags & SA_FLAG_COMP_UNSUPP) {
 1669                         g->mt_comp = MT_COMP_UNSUPP;
 1670                         g->mt_comp0 = MT_COMP_UNSUPP;
 1671                         g->mt_comp1 = MT_COMP_UNSUPP;
 1672                         g->mt_comp2 = MT_COMP_UNSUPP;
 1673                         g->mt_comp3 = MT_COMP_UNSUPP;
 1674                 } else {
 1675                         if ((softc->flags & SA_FLAG_COMP_ENABLED) == 0) {
 1676                                 g->mt_comp = MT_COMP_DISABLED;
 1677                         } else {
 1678                                 g->mt_comp = softc->comp_algorithm;
 1679                         }
 1680                         g->mt_comp0 = softc->comp_algorithm;
 1681                         g->mt_comp1 = softc->comp_algorithm;
 1682                         g->mt_comp2 = softc->comp_algorithm;
 1683                         g->mt_comp3 = softc->comp_algorithm;
 1684                 }
 1685                 g->mt_density = softc->media_density;
 1686                 g->mt_density0 = softc->media_density;
 1687                 g->mt_density1 = softc->media_density;
 1688                 g->mt_density2 = softc->media_density;
 1689                 g->mt_density3 = softc->media_density;
 1690                 g->mt_blksiz = softc->media_blksize;
 1691                 g->mt_blksiz0 = softc->media_blksize;
 1692                 g->mt_blksiz1 = softc->media_blksize;
 1693                 g->mt_blksiz2 = softc->media_blksize;
 1694                 g->mt_blksiz3 = softc->media_blksize;
 1695                 g->mt_fileno = softc->fileno;
 1696                 g->mt_blkno = softc->blkno;
 1697                 g->mt_dsreg = (short) softc->dsreg;
 1698                 /*
 1699                  * Yes, we know that this is likely to overflow
 1700                  */
 1701                 if (softc->last_resid_was_io) {
 1702                         if ((g->mt_resid = (short) softc->last_io_resid) != 0) {
 1703                                 if (SA_IS_CTRL(dev) == 0 || didlockperiph) {
 1704                                         softc->last_io_resid = 0;
 1705                                 }
 1706                         }
 1707                 } else {
 1708                         if ((g->mt_resid = (short)softc->last_ctl_resid) != 0) {
 1709                                 if (SA_IS_CTRL(dev) == 0 || didlockperiph) {
 1710                                         softc->last_ctl_resid = 0;
 1711                                 }
 1712                         }
 1713                 }
 1714                 error = 0;
 1715                 break;
 1716         }
 1717         case MTIOCEXTGET:
 1718         case MTIOCPARAMGET:
 1719         {
 1720                 struct mtextget *g = (struct mtextget *)arg;
 1721                 char *tmpstr2;
 1722                 struct sbuf *sb;
 1723 
 1724                 /*
 1725                  * Report drive status using an XML format.
 1726                  */
 1727 
 1728                 /*
 1729                  * XXX KDM will dropping the lock cause any problems here?
 1730                  */
 1731                 cam_periph_unlock(periph);
 1732                 sb = sbuf_new(NULL, NULL, g->alloc_len, SBUF_FIXEDLEN);
 1733                 if (sb == NULL) {
 1734                         g->status = MT_EXT_GET_ERROR;
 1735                         snprintf(g->error_str, sizeof(g->error_str),
 1736                                  "Unable to allocate %d bytes for status info",
 1737                                  g->alloc_len);
 1738                         cam_periph_lock(periph);
 1739                         goto extget_bailout;
 1740                 }
 1741                 cam_periph_lock(periph);
 1742 
 1743                 if (cmd == MTIOCEXTGET)
 1744                         error = saextget(dev, periph, sb, g);
 1745                 else
 1746                         error = saparamget(softc, sb);
 1747 
 1748                 if (error != 0)
 1749                         goto extget_bailout;
 1750 
 1751                 error = sbuf_finish(sb);
 1752                 if (error == ENOMEM) {
 1753                         g->status = MT_EXT_GET_NEED_MORE_SPACE;
 1754                         error = 0;
 1755                 } else if (error != 0) {
 1756                         g->status = MT_EXT_GET_ERROR;
 1757                         snprintf(g->error_str, sizeof(g->error_str),
 1758                             "Error %d returned from sbuf_finish()", error);
 1759                 } else
 1760                         g->status = MT_EXT_GET_OK;
 1761 
 1762                 error = 0;
 1763                 tmpstr2 = sbuf_data(sb);
 1764                 g->fill_len = strlen(tmpstr2) + 1;
 1765                 cam_periph_unlock(periph);
 1766 
 1767                 error = copyout(tmpstr2, g->status_xml, g->fill_len);
 1768 
 1769                 cam_periph_lock(periph);
 1770 
 1771 extget_bailout:
 1772                 sbuf_delete(sb);
 1773                 break;
 1774         }
 1775         case MTIOCPARAMSET:
 1776         {
 1777                 struct mtsetlist list;
 1778                 struct mtparamset *ps = (struct mtparamset *)arg;
 1779                 
 1780                 bzero(&list, sizeof(list));
 1781                 list.num_params = 1;
 1782                 list.param_len = sizeof(*ps);
 1783                 list.params = ps;
 1784 
 1785                 error = saparamsetlist(periph, &list, /*need_copy*/ 0);
 1786                 break;
 1787         }
 1788         case MTIOCSETLIST:
 1789         {
 1790                 struct mtsetlist *list = (struct mtsetlist *)arg;
 1791 
 1792                 error = saparamsetlist(periph, list, /*need_copy*/ 1);
 1793                 break;
 1794         }
 1795         case MTIOCERRSTAT:
 1796         {
 1797                 struct scsi_tape_errors *sep =
 1798                     &((union mterrstat *)arg)->scsi_errstat;
 1799 
 1800                 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
 1801                     ("saioctl: MTIOCERRSTAT\n"));
 1802 
 1803                 bzero(sep, sizeof(*sep));
 1804                 sep->io_resid = softc->last_io_resid;
 1805                 bcopy((caddr_t) &softc->last_io_sense, sep->io_sense,
 1806                     sizeof (sep->io_sense));
 1807                 bcopy((caddr_t) &softc->last_io_cdb, sep->io_cdb,
 1808                     sizeof (sep->io_cdb));
 1809                 sep->ctl_resid = softc->last_ctl_resid;
 1810                 bcopy((caddr_t) &softc->last_ctl_sense, sep->ctl_sense,
 1811                     sizeof (sep->ctl_sense));
 1812                 bcopy((caddr_t) &softc->last_ctl_cdb, sep->ctl_cdb,
 1813                     sizeof (sep->ctl_cdb));
 1814 
 1815                 if ((SA_IS_CTRL(dev) == 0 && !softc->open_pending_mount) ||
 1816                     didlockperiph)
 1817                         bzero((caddr_t) &softc->errinfo,
 1818                             sizeof (softc->errinfo));
 1819                 error = 0;
 1820                 break;
 1821         }
 1822         case MTIOCTOP:
 1823         {
 1824                 struct mtop *mt;
 1825                 int    count;
 1826 
 1827                 PENDING_MOUNT_CHECK(softc, periph, dev);
 1828 
 1829                 mt = (struct mtop *)arg;
 1830 
 1831                 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
 1832                          ("saioctl: op=0x%x count=0x%x\n",
 1833                           mt->mt_op, mt->mt_count));
 1834 
 1835                 count = mt->mt_count;
 1836                 switch (mt->mt_op) {
 1837                 case MTWEOF:    /* write an end-of-file marker */
 1838                         /*
 1839                          * We don't need to clear the SA_FLAG_TAPE_WRITTEN
 1840                          * flag because by keeping track of filemarks
 1841                          * we have last written we know whether or not
 1842                          * we need to write more when we close the device.
 1843                          */
 1844                         error = sawritefilemarks(periph, count, FALSE, FALSE);
 1845                         break;
 1846                 case MTWEOFI:
 1847                         /* write an end-of-file marker without waiting */
 1848                         error = sawritefilemarks(periph, count, FALSE, TRUE);
 1849                         break;
 1850                 case MTWSS:     /* write a setmark */
 1851                         error = sawritefilemarks(periph, count, TRUE, FALSE);
 1852                         break;
 1853                 case MTBSR:     /* backward space record */
 1854                 case MTFSR:     /* forward space record */
 1855                 case MTBSF:     /* backward space file */
 1856                 case MTFSF:     /* forward space file */
 1857                 case MTBSS:     /* backward space setmark */
 1858                 case MTFSS:     /* forward space setmark */
 1859                 case MTEOD:     /* space to end of recorded medium */
 1860                 {
 1861                         int nmarks;
 1862 
 1863                         spaceop = SS_FILEMARKS;
 1864                         nmarks = softc->filemarks;
 1865                         error = sacheckeod(periph);
 1866                         if (error) {
 1867                                 xpt_print(periph->path,
 1868                                     "EOD check prior to spacing failed\n");
 1869                                 softc->flags |= SA_FLAG_EIO_PENDING;
 1870                                 break;
 1871                         }
 1872                         nmarks -= softc->filemarks;
 1873                         switch(mt->mt_op) {
 1874                         case MTBSR:
 1875                                 count = -count;
 1876                                 /* FALLTHROUGH */
 1877                         case MTFSR:
 1878                                 spaceop = SS_BLOCKS;
 1879                                 break;
 1880                         case MTBSF:
 1881                                 count = -count;
 1882                                 /* FALLTHROUGH */
 1883                         case MTFSF:
 1884                                 break;
 1885                         case MTBSS:
 1886                                 count = -count;
 1887                                 /* FALLTHROUGH */
 1888                         case MTFSS:
 1889                                 spaceop = SS_SETMARKS;
 1890                                 break;
 1891                         case MTEOD:
 1892                                 spaceop = SS_EOD;
 1893                                 count = 0;
 1894                                 nmarks = 0;
 1895                                 break;
 1896                         default:
 1897                                 error = EINVAL;
 1898                                 break;
 1899                         }
 1900                         if (error)
 1901                                 break;
 1902 
 1903                         nmarks = softc->filemarks;
 1904                         /*
 1905                          * XXX: Why are we checking again?
 1906                          */
 1907                         error = sacheckeod(periph);
 1908                         if (error)
 1909                                 break;
 1910                         nmarks -= softc->filemarks;
 1911                         error = saspace(periph, count - nmarks, spaceop);
 1912                         /*
 1913                          * At this point, clear that we've written the tape
 1914                          * and that we've written any filemarks. We really
 1915                          * don't know what the applications wishes to do next-
 1916                          * the sacheckeod's will make sure we terminated the
 1917                          * tape correctly if we'd been writing, but the next
 1918                          * action the user application takes will set again
 1919                          * whether we need to write filemarks.
 1920                          */
 1921                         softc->flags &=
 1922                             ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN);
 1923                         softc->filemarks = 0;
 1924                         break;
 1925                 }
 1926                 case MTREW:     /* rewind */
 1927                         PENDING_MOUNT_CHECK(softc, periph, dev);
 1928                         (void) sacheckeod(periph);
 1929                         error = sarewind(periph);
 1930                         /* see above */
 1931                         softc->flags &=
 1932                             ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN);
 1933                         softc->flags &= ~SA_FLAG_ERR_PENDING;
 1934                         softc->filemarks = 0;
 1935                         break;
 1936                 case MTERASE:   /* erase */
 1937                         PENDING_MOUNT_CHECK(softc, periph, dev);
 1938                         error = saerase(periph, count);
 1939                         softc->flags &=
 1940                             ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN);
 1941                         softc->flags &= ~SA_FLAG_ERR_PENDING;
 1942                         break;
 1943                 case MTRETENS:  /* re-tension tape */
 1944                         PENDING_MOUNT_CHECK(softc, periph, dev);
 1945                         error = saretension(periph);            
 1946                         softc->flags &=
 1947                             ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN);
 1948                         softc->flags &= ~SA_FLAG_ERR_PENDING;
 1949                         break;
 1950                 case MTOFFL:    /* rewind and put the drive offline */
 1951 
 1952                         PENDING_MOUNT_CHECK(softc, periph, dev);
 1953 
 1954                         (void) sacheckeod(periph);
 1955                         /* see above */
 1956                         softc->flags &= ~SA_FLAG_TAPE_WRITTEN;
 1957                         softc->filemarks = 0;
 1958 
 1959                         error = sarewind(periph);
 1960                         /* clear the frozen flag anyway */
 1961                         softc->flags &= ~SA_FLAG_TAPE_FROZEN;
 1962 
 1963                         /*
 1964                          * Be sure to allow media removal before ejecting.
 1965                          */
 1966 
 1967                         saprevent(periph, PR_ALLOW);
 1968                         if (error == 0) {
 1969                                 error = saloadunload(periph, FALSE);
 1970                                 if (error == 0) {
 1971                                         softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
 1972                                 }
 1973                         }
 1974                         break;
 1975 
 1976                 case MTLOAD:
 1977                         error = saloadunload(periph, TRUE);
 1978                         break;
 1979                 case MTNOP:     /* no operation, sets status only */
 1980                 case MTCACHE:   /* enable controller cache */
 1981                 case MTNOCACHE: /* disable controller cache */
 1982                         error = 0;
 1983                         break;
 1984 
 1985                 case MTSETBSIZ: /* Set block size for device */
 1986 
 1987                         PENDING_MOUNT_CHECK(softc, periph, dev);
 1988 
 1989                         if ((softc->sili != 0)
 1990                          && (count != 0)) {
 1991                                 xpt_print(periph->path, "Can't enter fixed "
 1992                                     "block mode with SILI enabled\n");
 1993                                 error = EINVAL;
 1994                                 break;
 1995                         }
 1996                         error = sasetparams(periph, SA_PARAM_BLOCKSIZE, count,
 1997                                             0, 0, 0);
 1998                         if (error == 0) {
 1999                                 softc->last_media_blksize =
 2000                                     softc->media_blksize;
 2001                                 softc->media_blksize = count;
 2002                                 if (count) {
 2003                                         softc->flags |= SA_FLAG_FIXED;
 2004                                         if (powerof2(count)) {
 2005                                                 softc->blk_shift =
 2006                                                     ffs(count) - 1;
 2007                                                 softc->blk_mask = count - 1;
 2008                                         } else {
 2009                                                 softc->blk_mask = ~0;
 2010                                                 softc->blk_shift = 0;
 2011                                         }
 2012                                         /*
 2013                                          * Make the user's desire 'persistent'.
 2014                                          */
 2015                                         softc->quirks &= ~SA_QUIRK_VARIABLE;
 2016                                         softc->quirks |= SA_QUIRK_FIXED;
 2017                                 } else {
 2018                                         softc->flags &= ~SA_FLAG_FIXED;
 2019                                         if (softc->max_blk == 0) {
 2020                                                 softc->max_blk = ~0;
 2021                                         }
 2022                                         softc->blk_shift = 0;
 2023                                         if (softc->blk_gran != 0) {
 2024                                                 softc->blk_mask =
 2025                                                     softc->blk_gran - 1;
 2026                                         } else {
 2027                                                 softc->blk_mask = 0;
 2028                                         }
 2029                                         /*
 2030                                          * Make the user's desire 'persistent'.
 2031                                          */
 2032                                         softc->quirks |= SA_QUIRK_VARIABLE;
 2033                                         softc->quirks &= ~SA_QUIRK_FIXED;
 2034                                 }
 2035                         }
 2036                         break;
 2037                 case MTSETDNSTY:        /* Set density for device and mode */
 2038                         PENDING_MOUNT_CHECK(softc, periph, dev);
 2039 
 2040                         if (count > UCHAR_MAX) {
 2041                                 error = EINVAL; 
 2042                                 break;
 2043                         } else {
 2044                                 error = sasetparams(periph, SA_PARAM_DENSITY,
 2045                                                     0, count, 0, 0);
 2046                         }
 2047                         break;
 2048                 case MTCOMP:    /* enable compression */
 2049                         PENDING_MOUNT_CHECK(softc, periph, dev);
 2050                         /*
 2051                          * Some devices don't support compression, and
 2052                          * don't like it if you ask them for the
 2053                          * compression page.
 2054                          */
 2055                         if ((softc->quirks & SA_QUIRK_NOCOMP) ||
 2056                             (softc->flags & SA_FLAG_COMP_UNSUPP)) {
 2057                                 error = ENODEV;
 2058                                 break;
 2059                         }
 2060                         error = sasetparams(periph, SA_PARAM_COMPRESSION,
 2061                             0, 0, count, SF_NO_PRINT);
 2062                         break;
 2063                 default:
 2064                         error = EINVAL;
 2065                 }
 2066                 break;
 2067         }
 2068         case MTIOCIEOT:
 2069         case MTIOCEEOT:
 2070                 error = 0;
 2071                 break;
 2072         case MTIOCRDSPOS:
 2073                 PENDING_MOUNT_CHECK(softc, periph, dev);
 2074                 error = sardpos(periph, 0, (u_int32_t *) arg);
 2075                 break;
 2076         case MTIOCRDHPOS:
 2077                 PENDING_MOUNT_CHECK(softc, periph, dev);
 2078                 error = sardpos(periph, 1, (u_int32_t *) arg);
 2079                 break;
 2080         case MTIOCSLOCATE:
 2081         case MTIOCHLOCATE: {
 2082                 struct mtlocate locate_info;
 2083                 int hard;
 2084 
 2085                 bzero(&locate_info, sizeof(locate_info));
 2086                 locate_info.logical_id = *((uint32_t *)arg);
 2087                 if (cmd == MTIOCSLOCATE)
 2088                         hard = 0;
 2089                 else
 2090                         hard = 1;
 2091 
 2092                 PENDING_MOUNT_CHECK(softc, periph, dev);
 2093 
 2094                 error = sasetpos(periph, hard, &locate_info);
 2095                 break;
 2096         }
 2097         case MTIOCEXTLOCATE:
 2098                 PENDING_MOUNT_CHECK(softc, periph, dev);
 2099                 error = sasetpos(periph, /*hard*/ 0, (struct mtlocate *)arg);
 2100                 softc->flags &=
 2101                     ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN);
 2102                 softc->flags &= ~SA_FLAG_ERR_PENDING;
 2103                 softc->filemarks = 0;
 2104                 break;
 2105         case MTIOCGETEOTMODEL:
 2106                 error = 0;
 2107                 if (softc->quirks & SA_QUIRK_1FM)
 2108                         mode = 1;
 2109                 else
 2110                         mode = 2;
 2111                 *((u_int32_t *) arg) = mode;
 2112                 break;
 2113         case MTIOCSETEOTMODEL:
 2114                 error = 0;
 2115                 switch (*((u_int32_t *) arg)) {
 2116                 case 1:
 2117                         softc->quirks &= ~SA_QUIRK_2FM;
 2118                         softc->quirks |= SA_QUIRK_1FM;
 2119                         break;
 2120                 case 2:
 2121                         softc->quirks &= ~SA_QUIRK_1FM;
 2122                         softc->quirks |= SA_QUIRK_2FM;
 2123                         break;
 2124                 default:
 2125                         error = EINVAL;
 2126                         break;
 2127                 }
 2128                 break;
 2129         case MTIOCRBLIM: {
 2130                 struct mtrblim *rblim;
 2131 
 2132                 rblim = (struct mtrblim *)arg;
 2133 
 2134                 rblim->granularity = softc->blk_gran;
 2135                 rblim->min_block_length = softc->min_blk;
 2136                 rblim->max_block_length = softc->max_blk;
 2137                 break;
 2138         }
 2139         default:
 2140                 error = cam_periph_ioctl(periph, cmd, arg, saerror);
 2141                 break;
 2142         }
 2143 
 2144         /*
 2145          * Check to see if we cleared a frozen state
 2146          */
 2147         if (error == 0 && (softc->flags & SA_FLAG_TAPE_FROZEN)) {
 2148                 switch(cmd) {
 2149                 case MTIOCRDSPOS:
 2150                 case MTIOCRDHPOS:
 2151                 case MTIOCSLOCATE:
 2152                 case MTIOCHLOCATE:
 2153                         /*
 2154                          * XXX KDM look at this.
 2155                          */
 2156                         softc->fileno = (daddr_t) -1;
 2157                         softc->blkno = (daddr_t) -1;
 2158                         softc->rep_blkno = (daddr_t) -1;
 2159                         softc->rep_fileno = (daddr_t) -1;
 2160                         softc->partition = (daddr_t) -1;
 2161                         softc->flags &= ~SA_FLAG_TAPE_FROZEN;
 2162                         xpt_print(periph->path,
 2163                             "tape state now unfrozen.\n");
 2164                         break;
 2165                 default:
 2166                         break;
 2167                 }
 2168         }
 2169         if (didlockperiph) {
 2170                 cam_periph_unhold(periph);
 2171         }
 2172         cam_periph_unlock(periph);
 2173         return (error);
 2174 }
 2175 
 2176 static void
 2177 sainit(void)
 2178 {
 2179         cam_status status;
 2180 
 2181         /*
 2182          * Install a global async callback.
 2183          */
 2184         status = xpt_register_async(AC_FOUND_DEVICE, saasync, NULL, NULL);
 2185 
 2186         if (status != CAM_REQ_CMP) {
 2187                 printf("sa: Failed to attach master async callback "
 2188                        "due to status 0x%x!\n", status);
 2189         }
 2190 }
 2191 
 2192 static void
 2193 sadevgonecb(void *arg)
 2194 {
 2195         struct cam_periph *periph;
 2196         struct mtx *mtx;
 2197         struct sa_softc *softc;
 2198 
 2199         periph = (struct cam_periph *)arg;
 2200         softc = (struct sa_softc *)periph->softc;
 2201 
 2202         mtx = cam_periph_mtx(periph);
 2203         mtx_lock(mtx);
 2204 
 2205         softc->num_devs_to_destroy--;
 2206         if (softc->num_devs_to_destroy == 0) {
 2207                 int i;
 2208 
 2209                 /*
 2210                  * When we have gotten all of our callbacks, we will get
 2211                  * no more close calls from devfs.  So if we have any
 2212                  * dangling opens, we need to release the reference held
 2213                  * for that particular context.
 2214                  */
 2215                 for (i = 0; i < softc->open_count; i++)
 2216                         cam_periph_release_locked(periph);
 2217 
 2218                 softc->open_count = 0;
 2219 
 2220                 /*
 2221                  * Release the reference held for devfs, all of our
 2222                  * instances are gone now.
 2223                  */
 2224                 cam_periph_release_locked(periph);
 2225         }
 2226 
 2227         /*
 2228          * We reference the lock directly here, instead of using
 2229          * cam_periph_unlock().  The reason is that the final call to
 2230          * cam_periph_release_locked() above could result in the periph
 2231          * getting freed.  If that is the case, dereferencing the periph
 2232          * with a cam_periph_unlock() call would cause a page fault.
 2233          */
 2234         mtx_unlock(mtx);
 2235 }
 2236 
 2237 static void
 2238 saoninvalidate(struct cam_periph *periph)
 2239 {
 2240         struct sa_softc *softc;
 2241 
 2242         softc = (struct sa_softc *)periph->softc;
 2243 
 2244         /*
 2245          * De-register any async callbacks.
 2246          */
 2247         xpt_register_async(0, saasync, periph, periph->path);
 2248 
 2249         softc->flags |= SA_FLAG_INVALID;
 2250 
 2251         /*
 2252          * Return all queued I/O with ENXIO.
 2253          * XXX Handle any transactions queued to the card
 2254          *     with XPT_ABORT_CCB.
 2255          */
 2256         bioq_flush(&softc->bio_queue, NULL, ENXIO);
 2257         softc->queue_count = 0;
 2258 
 2259         /*
 2260          * Tell devfs that all of our devices have gone away, and ask for a
 2261          * callback when it has cleaned up its state.
 2262          */
 2263         destroy_dev_sched_cb(softc->devs.ctl_dev, sadevgonecb, periph);
 2264         destroy_dev_sched_cb(softc->devs.r_dev, sadevgonecb, periph);
 2265         destroy_dev_sched_cb(softc->devs.nr_dev, sadevgonecb, periph);
 2266         destroy_dev_sched_cb(softc->devs.er_dev, sadevgonecb, periph);
 2267 }
 2268 
 2269 static void
 2270 sacleanup(struct cam_periph *periph)
 2271 {
 2272         struct sa_softc *softc;
 2273 
 2274         softc = (struct sa_softc *)periph->softc;
 2275 
 2276         cam_periph_unlock(periph);
 2277 
 2278         if ((softc->flags & SA_FLAG_SCTX_INIT) != 0
 2279          && (((softc->sysctl_timeout_tree != NULL)
 2280            && (sysctl_ctx_free(&softc->sysctl_timeout_ctx) != 0))
 2281           || sysctl_ctx_free(&softc->sysctl_ctx) != 0))
 2282                 xpt_print(periph->path, "can't remove sysctl context\n");
 2283 
 2284         cam_periph_lock(periph);
 2285 
 2286         devstat_remove_entry(softc->device_stats);
 2287 
 2288         free(softc, M_SCSISA);
 2289 }
 2290 
 2291 static void
 2292 saasync(void *callback_arg, u_int32_t code,
 2293         struct cam_path *path, void *arg)
 2294 {
 2295         struct cam_periph *periph;
 2296 
 2297         periph = (struct cam_periph *)callback_arg;
 2298         switch (code) {
 2299         case AC_FOUND_DEVICE:
 2300         {
 2301                 struct ccb_getdev *cgd;
 2302                 cam_status status;
 2303 
 2304                 cgd = (struct ccb_getdev *)arg;
 2305                 if (cgd == NULL)
 2306                         break;
 2307 
 2308                 if (cgd->protocol != PROTO_SCSI)
 2309                         break;
 2310                 if (SID_QUAL(&cgd->inq_data) != SID_QUAL_LU_CONNECTED)
 2311                         break;
 2312                 if (SID_TYPE(&cgd->inq_data) != T_SEQUENTIAL)
 2313                         break;
 2314 
 2315                 /*
 2316                  * Allocate a peripheral instance for
 2317                  * this device and start the probe
 2318                  * process.
 2319                  */
 2320                 status = cam_periph_alloc(saregister, saoninvalidate,
 2321                                           sacleanup, sastart,
 2322                                           "sa", CAM_PERIPH_BIO, path,
 2323                                           saasync, AC_FOUND_DEVICE, cgd);
 2324 
 2325                 if (status != CAM_REQ_CMP
 2326                  && status != CAM_REQ_INPROG)
 2327                         printf("saasync: Unable to probe new device "
 2328                                 "due to status 0x%x\n", status);
 2329                 break;
 2330         }
 2331         default:
 2332                 cam_periph_async(periph, code, path, arg);
 2333                 break;
 2334         }
 2335 }
 2336 
 2337 static void
 2338 sasetupdev(struct sa_softc *softc, struct cdev *dev)
 2339 {
 2340 
 2341         dev->si_iosize_max = softc->maxio;
 2342         dev->si_flags |= softc->si_flags;
 2343         /*
 2344          * Keep a count of how many non-alias devices we have created,
 2345          * so we can make sure we clean them all up on shutdown.  Aliases
 2346          * are cleaned up when we destroy the device they're an alias for.
 2347          */
 2348         if ((dev->si_flags & SI_ALIAS) == 0)
 2349                 softc->num_devs_to_destroy++;
 2350 }
 2351 
 2352 /*
 2353  * Load the global (for all sa(4) instances) and per-instance tunable
 2354  * values for timeouts for various sa(4) commands.  This should be run
 2355  * after the default timeouts are fetched from the drive, so the user's
 2356  * preference will override the drive's defaults.
 2357  */
 2358 static void
 2359 saloadtotunables(struct sa_softc *softc)
 2360 {
 2361         int i;
 2362         char tmpstr[80];
 2363 
 2364         for (i = 0; i < SA_TIMEOUT_TYPE_MAX; i++) {
 2365                 int tmpval, retval;
 2366 
 2367                 /* First grab any global timeout setting */
 2368                 snprintf(tmpstr, sizeof(tmpstr), "kern.cam.sa.timeout.%s",
 2369                     sa_default_timeouts[i].desc);
 2370                 retval = TUNABLE_INT_FETCH(tmpstr, &tmpval);
 2371                 if (retval != 0)
 2372                         softc->timeout_info[i] = tmpval;
 2373 
 2374                 /*
 2375                  * Then overwrite any global timeout settings with
 2376                  * per-instance timeout settings.
 2377                  */
 2378                 snprintf(tmpstr, sizeof(tmpstr), "kern.cam.sa.%u.timeout.%s",
 2379                     softc->periph->unit_number, sa_default_timeouts[i].desc);
 2380                 retval = TUNABLE_INT_FETCH(tmpstr, &tmpval);
 2381                 if (retval != 0)
 2382                         softc->timeout_info[i] = tmpval;
 2383         }
 2384 }
 2385 
 2386 static void
 2387 sasysctlinit(void *context, int pending)
 2388 {
 2389         struct cam_periph *periph;
 2390         struct sa_softc *softc;
 2391         char tmpstr[64], tmpstr2[16];
 2392         int i;
 2393 
 2394         periph = (struct cam_periph *)context;
 2395         /*
 2396          * If the periph is invalid, no need to setup the sysctls.
 2397          */
 2398         if (periph->flags & CAM_PERIPH_INVALID)
 2399                 goto bailout;
 2400 
 2401         softc = (struct sa_softc *)periph->softc;
 2402 
 2403         snprintf(tmpstr, sizeof(tmpstr), "CAM SA unit %d", periph->unit_number);
 2404         snprintf(tmpstr2, sizeof(tmpstr2), "%u", periph->unit_number);
 2405 
 2406         sysctl_ctx_init(&softc->sysctl_ctx);
 2407         softc->flags |= SA_FLAG_SCTX_INIT;
 2408         softc->sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&softc->sysctl_ctx,
 2409             SYSCTL_STATIC_CHILDREN(_kern_cam_sa), OID_AUTO, tmpstr2,
 2410             CTLFLAG_RD | CTLFLAG_MPSAFE, 0, tmpstr, "device_index");
 2411         if (softc->sysctl_tree == NULL)
 2412                 goto bailout;
 2413 
 2414         SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
 2415             OID_AUTO, "allow_io_split", CTLFLAG_RDTUN | CTLFLAG_NOFETCH, 
 2416             &softc->allow_io_split, 0, "Allow Splitting I/O");
 2417         SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
 2418             OID_AUTO, "maxio", CTLFLAG_RD, 
 2419             &softc->maxio, 0, "Maximum I/O size");
 2420         SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
 2421             OID_AUTO, "cpi_maxio", CTLFLAG_RD, 
 2422             &softc->cpi_maxio, 0, "Maximum Controller I/O size");
 2423         SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
 2424             OID_AUTO, "inject_eom", CTLFLAG_RW, 
 2425             &softc->inject_eom, 0, "Queue EOM for the next write/read");
 2426 
 2427         sysctl_ctx_init(&softc->sysctl_timeout_ctx);
 2428         softc->sysctl_timeout_tree = SYSCTL_ADD_NODE(&softc->sysctl_timeout_ctx,
 2429             SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO, "timeout",
 2430             CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Timeouts");
 2431         if (softc->sysctl_timeout_tree == NULL)
 2432                 goto bailout;
 2433 
 2434         for (i = 0; i < SA_TIMEOUT_TYPE_MAX; i++) {
 2435                 snprintf(tmpstr, sizeof(tmpstr), "%s timeout",
 2436                     sa_default_timeouts[i].desc);
 2437 
 2438                 /*
 2439                  * Do NOT change this sysctl declaration to also load any
 2440                  * tunable values for this sa(4) instance.  In other words,
 2441                  * do not change this to CTLFLAG_RWTUN.  This function is
 2442                  * run in parallel with the probe routine that fetches
 2443                  * recommended timeout values from the tape drive, and we
 2444                  * don't want the values from the drive to override the
 2445                  * user's preference.
 2446                  */
 2447                 SYSCTL_ADD_INT(&softc->sysctl_timeout_ctx,
 2448                     SYSCTL_CHILDREN(softc->sysctl_timeout_tree),
 2449                     OID_AUTO, sa_default_timeouts[i].desc, CTLFLAG_RW, 
 2450                     &softc->timeout_info[i], 0, tmpstr);
 2451         }
 2452 
 2453 bailout:
 2454         /*
 2455          * Release the reference that was held when this task was enqueued.
 2456          */
 2457         cam_periph_release(periph);
 2458 }
 2459 
 2460 static cam_status
 2461 saregister(struct cam_periph *periph, void *arg)
 2462 {
 2463         struct sa_softc *softc;
 2464         struct ccb_getdev *cgd;
 2465         struct ccb_pathinq cpi;
 2466         struct make_dev_args args;
 2467         caddr_t match;
 2468         char tmpstr[80];
 2469         int error;
 2470         int i;
 2471 
 2472         cgd = (struct ccb_getdev *)arg;
 2473         if (cgd == NULL) {
 2474                 printf("saregister: no getdev CCB, can't register device\n");
 2475                 return (CAM_REQ_CMP_ERR);
 2476         }
 2477 
 2478         softc = (struct sa_softc *)
 2479             malloc(sizeof (*softc), M_SCSISA, M_NOWAIT | M_ZERO);
 2480         if (softc == NULL) {
 2481                 printf("saregister: Unable to probe new device. "
 2482                        "Unable to allocate softc\n");                           
 2483                 return (CAM_REQ_CMP_ERR);
 2484         }
 2485         softc->scsi_rev = SID_ANSI_REV(&cgd->inq_data);
 2486         softc->state = SA_STATE_NORMAL;
 2487         softc->fileno = (daddr_t) -1;
 2488         softc->blkno = (daddr_t) -1;
 2489         softc->rep_fileno = (daddr_t) -1;
 2490         softc->rep_blkno = (daddr_t) -1;
 2491         softc->partition = (daddr_t) -1;
 2492         softc->bop = -1;
 2493         softc->eop = -1;
 2494         softc->bpew = -1;
 2495 
 2496         bioq_init(&softc->bio_queue);
 2497         softc->periph = periph;
 2498         periph->softc = softc;
 2499 
 2500         /*
 2501          * See if this device has any quirks.
 2502          */
 2503         match = cam_quirkmatch((caddr_t)&cgd->inq_data,
 2504                                (caddr_t)sa_quirk_table,
 2505                                nitems(sa_quirk_table),
 2506                                sizeof(*sa_quirk_table), scsi_inquiry_match);
 2507 
 2508         if (match != NULL) {
 2509                 softc->quirks = ((struct sa_quirk_entry *)match)->quirks;
 2510                 softc->last_media_blksize =
 2511                     ((struct sa_quirk_entry *)match)->prefblk;
 2512         } else
 2513                 softc->quirks = SA_QUIRK_NONE;
 2514 
 2515 
 2516         /*
 2517          * Initialize the default timeouts.  If this drive supports
 2518          * timeout descriptors we'll overwrite these values with the
 2519          * recommended timeouts from the drive.
 2520          */
 2521         for (i = 0; i < SA_TIMEOUT_TYPE_MAX; i++)
 2522                 softc->timeout_info[i] = sa_default_timeouts[i].value;
 2523 
 2524         /*
 2525          * Long format data for READ POSITION was introduced in SSC, which
 2526          * was after SCSI-2.  (Roughly equivalent to SCSI-3.)  If the drive
 2527          * reports that it is SCSI-2 or older, it is unlikely to support
 2528          * long position data, but it might.  Some drives from that era
 2529          * claim to be SCSI-2, but do support long position information.
 2530          * So, instead of immediately disabling long position information
 2531          * for SCSI-2 devices, we'll try one pass through sagetpos(), and 
 2532          * then disable long position information if we get an error.   
 2533          */
 2534         if (cgd->inq_data.version <= SCSI_REV_CCS)
 2535                 softc->quirks |= SA_QUIRK_NO_LONG_POS;
 2536 
 2537         /*
 2538          * The SCSI REPORT SUPPORTED OPERATION CODES command was added in
 2539          * SPC-4.  That command optionally includes timeout data for
 2540          * different commands.  Timeout values can vary wildly among
 2541          * different drives, so if the drive itself has recommended values,
 2542          * we will try to use them.  Set this flag to indicate we're going
 2543          * to ask the drive for timeout data.  This flag also tells us to
 2544          * wait on loading timeout tunables so we can properly override
 2545          * timeouts with any user-specified values.
 2546          */
 2547         if (SID_ANSI_REV(&cgd->inq_data) >= SCSI_REV_SPC4)
 2548                 softc->flags |= SA_FLAG_RSOC_TO_TRY;
 2549 
 2550         if (cgd->inq_data.spc3_flags & SPC3_SID_PROTECT) {
 2551                 struct ccb_dev_advinfo cdai;
 2552                 struct scsi_vpd_extended_inquiry_data ext_inq;
 2553 
 2554                 bzero(&ext_inq, sizeof(ext_inq));
 2555 
 2556                 memset(&cdai, 0, sizeof(cdai));
 2557                 xpt_setup_ccb(&cdai.ccb_h, periph->path, CAM_PRIORITY_NORMAL);
 2558 
 2559                 cdai.ccb_h.func_code = XPT_DEV_ADVINFO;
 2560                 cdai.flags = CDAI_FLAG_NONE;
 2561                 cdai.buftype = CDAI_TYPE_EXT_INQ;
 2562                 cdai.bufsiz = sizeof(ext_inq);
 2563                 cdai.buf = (uint8_t *)&ext_inq;
 2564                 xpt_action((union ccb *)&cdai);
 2565 
 2566                 if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
 2567                         cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
 2568                 if ((cdai.ccb_h.status == CAM_REQ_CMP)
 2569                  && (ext_inq.flags1 & SVPD_EID_SA_SPT_LBP))
 2570                         softc->flags |= SA_FLAG_PROTECT_SUPP;
 2571         }
 2572 
 2573         xpt_path_inq(&cpi, periph->path);
 2574 
 2575         /*
 2576          * The SA driver supports a blocksize, but we don't know the
 2577          * blocksize until we media is inserted.  So, set a flag to
 2578          * indicate that the blocksize is unavailable right now.
 2579          */
 2580         cam_periph_unlock(periph);
 2581         softc->device_stats = devstat_new_entry("sa", periph->unit_number, 0,
 2582             DEVSTAT_BS_UNAVAILABLE, SID_TYPE(&cgd->inq_data) |
 2583             XPORT_DEVSTAT_TYPE(cpi.transport), DEVSTAT_PRIORITY_TAPE);
 2584 
 2585         /*
 2586          * Load the default value that is either compiled in, or loaded 
 2587          * in the global kern.cam.sa.allow_io_split tunable.
 2588          */
 2589         softc->allow_io_split = sa_allow_io_split;
 2590 
 2591         /*
 2592          * Load a per-instance tunable, if it exists.  NOTE that this
 2593          * tunable WILL GO AWAY in FreeBSD 11.0.
 2594          */ 
 2595         snprintf(tmpstr, sizeof(tmpstr), "kern.cam.sa.%u.allow_io_split",
 2596                  periph->unit_number);
 2597         TUNABLE_INT_FETCH(tmpstr, &softc->allow_io_split);
 2598 
 2599         /*
 2600          * If maxio isn't set, we fall back to DFLTPHYS.  Otherwise we take
 2601          * the smaller of cpi.maxio or maxphys.
 2602          */
 2603         if (cpi.maxio == 0)
 2604                 softc->maxio = DFLTPHYS;
 2605         else if (cpi.maxio > maxphys)
 2606                 softc->maxio = maxphys;
 2607         else
 2608                 softc->maxio = cpi.maxio;
 2609 
 2610         /*
 2611          * Record the controller's maximum I/O size so we can report it to
 2612          * the user later.
 2613          */
 2614         softc->cpi_maxio = cpi.maxio;
 2615 
 2616         /*
 2617          * By default we tell physio that we do not want our I/O split.
 2618          * The user needs to have a 1:1 mapping between the size of his
 2619          * write to a tape character device and the size of the write
 2620          * that actually goes down to the drive.
 2621          */
 2622         if (softc->allow_io_split == 0)
 2623                 softc->si_flags = SI_NOSPLIT;
 2624         else
 2625                 softc->si_flags = 0;
 2626 
 2627         TASK_INIT(&softc->sysctl_task, 0, sasysctlinit, periph);
 2628 
 2629         /*
 2630          * If the SIM supports unmapped I/O, let physio know that we can
 2631          * handle unmapped buffers.
 2632          */
 2633         if (cpi.hba_misc & PIM_UNMAPPED)
 2634                 softc->si_flags |= SI_UNMAPPED;
 2635 
 2636         /*
 2637          * Acquire a reference to the periph before we create the devfs
 2638          * instances for it.  We'll release this reference once the devfs
 2639          * instances have been freed.
 2640          */
 2641         if (cam_periph_acquire(periph) != 0) {
 2642                 xpt_print(periph->path, "%s: lost periph during "
 2643                           "registration!\n", __func__);
 2644                 cam_periph_lock(periph);
 2645                 return (CAM_REQ_CMP_ERR);
 2646         }
 2647 
 2648         make_dev_args_init(&args);
 2649         args.mda_devsw = &sa_cdevsw;
 2650         args.mda_si_drv1 = softc->periph;
 2651         args.mda_uid = UID_ROOT;
 2652         args.mda_gid = GID_OPERATOR;
 2653         args.mda_mode = 0660;
 2654 
 2655         args.mda_unit = SAMINOR(SA_CTLDEV, SA_ATYPE_R);
 2656         error = make_dev_s(&args, &softc->devs.ctl_dev, "%s%d.ctl",
 2657             periph->periph_name, periph->unit_number);
 2658         if (error != 0) {
 2659                 cam_periph_lock(periph);
 2660                 return (CAM_REQ_CMP_ERR);
 2661         }
 2662         sasetupdev(softc, softc->devs.ctl_dev);
 2663 
 2664         args.mda_unit = SAMINOR(SA_NOT_CTLDEV, SA_ATYPE_R);
 2665         error = make_dev_s(&args, &softc->devs.r_dev, "%s%d",
 2666             periph->periph_name, periph->unit_number);
 2667         if (error != 0) {
 2668                 cam_periph_lock(periph);
 2669                 return (CAM_REQ_CMP_ERR);
 2670         }
 2671         sasetupdev(softc, softc->devs.r_dev);
 2672 
 2673         args.mda_unit = SAMINOR(SA_NOT_CTLDEV, SA_ATYPE_NR);
 2674         error = make_dev_s(&args, &softc->devs.nr_dev, "n%s%d",
 2675             periph->periph_name, periph->unit_number);
 2676         if (error != 0) {
 2677                 cam_periph_lock(periph);
 2678                 return (CAM_REQ_CMP_ERR);
 2679         }
 2680         sasetupdev(softc, softc->devs.nr_dev);
 2681 
 2682         args.mda_unit = SAMINOR(SA_NOT_CTLDEV, SA_ATYPE_ER);
 2683         error = make_dev_s(&args, &softc->devs.er_dev, "e%s%d",
 2684             periph->periph_name, periph->unit_number);
 2685         if (error != 0) {
 2686                 cam_periph_lock(periph);
 2687                 return (CAM_REQ_CMP_ERR);
 2688         }
 2689         sasetupdev(softc, softc->devs.er_dev);
 2690 
 2691         cam_periph_lock(periph);
 2692 
 2693         softc->density_type_bits[0] = 0;
 2694         softc->density_type_bits[1] = SRDS_MEDIA;
 2695         softc->density_type_bits[2] = SRDS_MEDIUM_TYPE;
 2696         softc->density_type_bits[3] = SRDS_MEDIUM_TYPE | SRDS_MEDIA;
 2697         /*
 2698          * Bump the peripheral refcount for the sysctl thread, in case we
 2699          * get invalidated before the thread has a chance to run.  Note
 2700          * that this runs in parallel with the probe for the timeout
 2701          * values.
 2702          */
 2703         cam_periph_acquire(periph);
 2704         taskqueue_enqueue(taskqueue_thread, &softc->sysctl_task);
 2705 
 2706         /*
 2707          * Add an async callback so that we get
 2708          * notified if this device goes away.
 2709          */
 2710         xpt_register_async(AC_LOST_DEVICE, saasync, periph, periph->path);
 2711 
 2712         /*
 2713          * See comment above, try fetching timeout values for drives that
 2714          * might support it.  Otherwise, use the defaults.  
 2715          *
 2716          * We get timeouts from the following places in order of increasing
 2717          * priority:
 2718          * 1. Driver default timeouts.
 2719          * 2. Timeouts loaded from the drive via REPORT SUPPORTED OPERATION
 2720          *    CODES. (We kick that off here if SA_FLAG_RSOC_TO_TRY is set.)
 2721          * 3. Global loader tunables, used for all sa(4) driver instances on
 2722          *    a machine.
 2723          * 4. Instance-specific loader tunables, used for say sa5.
 2724          * 5. On the fly user sysctl changes.
 2725          * 
 2726          * Each step will overwrite the timeout value set from the one
 2727          * before, so you go from general to most specific.
 2728          */
 2729         if (softc->flags & SA_FLAG_RSOC_TO_TRY) {
 2730                 /*
 2731                  * Bump the peripheral refcount while we are probing.
 2732                  */
 2733                 cam_periph_acquire(periph);
 2734                 softc->state = SA_STATE_PROBE;
 2735                 xpt_schedule(periph, CAM_PRIORITY_DEV);
 2736         } else {
 2737                 /*
 2738                  * This drive doesn't support Report Supported Operation
 2739                  * Codes, so we load the tunables at this point to bring
 2740                  * in any user preferences.
 2741                  */
 2742                 saloadtotunables(softc);
 2743 
 2744                 xpt_announce_periph(periph, NULL);
 2745                 xpt_announce_quirks(periph, softc->quirks, SA_QUIRK_BIT_STRING);
 2746         }
 2747 
 2748         return (CAM_REQ_CMP);
 2749 }
 2750 
 2751 static void
 2752 sastart(struct cam_periph *periph, union ccb *start_ccb)
 2753 {
 2754         struct sa_softc *softc;
 2755 
 2756         softc = (struct sa_softc *)periph->softc;
 2757 
 2758         CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sastart\n"));
 2759 
 2760         switch (softc->state) {
 2761         case SA_STATE_NORMAL:
 2762         {
 2763                 /* Pull a buffer from the queue and get going on it */          
 2764                 struct bio *bp;
 2765 
 2766                 /*
 2767                  * See if there is a buf with work for us to do..
 2768                  */
 2769                 bp = bioq_first(&softc->bio_queue);
 2770                 if (bp == NULL) {
 2771                         xpt_release_ccb(start_ccb);
 2772                 } else if (((softc->flags & SA_FLAG_ERR_PENDING) != 0)
 2773                         || (softc->inject_eom != 0)) {
 2774                         struct bio *done_bp;
 2775 
 2776                         if (softc->inject_eom != 0) {
 2777                                 softc->flags |= SA_FLAG_EOM_PENDING;
 2778                                 softc->inject_eom = 0;
 2779                                 /*
 2780                                  * If we're injecting EOM for writes, we
 2781                                  * need to keep PEWS set for 3 queries
 2782                                  * to cover 2 position requests from the
 2783                                  * kernel via sagetpos(), and then allow
 2784                                  * for one for the user to see the BPEW
 2785                                  * flag (e.g. via mt status).  After that,
 2786                                  * it will be cleared.
 2787                                  */
 2788                                 if (bp->bio_cmd == BIO_WRITE)
 2789                                         softc->set_pews_status = 3;
 2790                                 else
 2791                                         softc->set_pews_status = 1;
 2792                         }
 2793 again:
 2794                         softc->queue_count--;
 2795                         bioq_remove(&softc->bio_queue, bp);
 2796                         bp->bio_resid = bp->bio_bcount;
 2797                         done_bp = bp;
 2798                         if ((softc->flags & SA_FLAG_EOM_PENDING) != 0) {
 2799                                 /*
 2800                                  * We have two different behaviors for
 2801                                  * writes when we hit either Early Warning
 2802                                  * or the PEWZ (Programmable Early Warning
 2803                                  * Zone).  The default behavior is that
 2804                                  * for all writes that are currently
 2805                                  * queued after the write where we saw the
 2806                                  * early warning, we will return the write
 2807                                  * with the residual equal to the count.
 2808                                  * i.e. tell the application that 0 bytes
 2809                                  * were written.
 2810                                  * 
 2811                                  * The alternate behavior, which is enabled
 2812                                  * when eot_warn is set, is that in
 2813                                  * addition to setting the residual equal
 2814                                  * to the count, we will set the error
 2815                                  * to ENOSPC.
 2816                                  *
 2817                                  * In either case, once queued writes are
 2818                                  * cleared out, we clear the error flag
 2819                                  * (see below) and the application is free to
 2820                                  * attempt to write more.
 2821                                  */
 2822                                 if (softc->eot_warn != 0) {
 2823                                         bp->bio_flags |= BIO_ERROR;
 2824                                         bp->bio_error = ENOSPC;
 2825                                 } else
 2826                                         bp->bio_error = 0;
 2827                         } else if ((softc->flags & SA_FLAG_EOF_PENDING) != 0) {
 2828                                 /*
 2829                                  * This can only happen if we're reading
 2830                                  * in fixed length mode. In this case,
 2831                                  * we dump the rest of the list the
 2832                                  * same way.
 2833                                  */
 2834                                 bp->bio_error = 0;
 2835                                 if (bioq_first(&softc->bio_queue) != NULL) {
 2836                                         biodone(done_bp);
 2837                                         goto again;
 2838                                 }
 2839                         } else if ((softc->flags & SA_FLAG_EIO_PENDING) != 0) {
 2840                                 bp->bio_error = EIO;
 2841                                 bp->bio_flags |= BIO_ERROR;
 2842                         }
 2843                         bp = bioq_first(&softc->bio_queue);
 2844                         /*
 2845                          * Only if we have no other buffers queued up
 2846                          * do we clear the pending error flag.
 2847                          */
 2848                         if (bp == NULL)
 2849                                 softc->flags &= ~SA_FLAG_ERR_PENDING;
 2850                         CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
 2851                             ("sastart- ERR_PENDING now 0x%x, bp is %sNULL, "
 2852                             "%d more buffers queued up\n",
 2853                             (softc->flags & SA_FLAG_ERR_PENDING),
 2854                             (bp != NULL)? "not " : " ", softc->queue_count));
 2855                         xpt_release_ccb(start_ccb);
 2856                         biodone(done_bp);
 2857                 } else {
 2858                         u_int32_t length;
 2859 
 2860                         bioq_remove(&softc->bio_queue, bp);
 2861                         softc->queue_count--;
 2862 
 2863                         if ((bp->bio_cmd != BIO_READ) &&
 2864                             (bp->bio_cmd != BIO_WRITE)) {
 2865                                 biofinish(bp, NULL, EOPNOTSUPP);
 2866                                 xpt_release_ccb(start_ccb);
 2867                                 return;
 2868                         }
 2869                         length = bp->bio_bcount;
 2870 
 2871                         if ((softc->flags & SA_FLAG_FIXED) != 0) {
 2872                                 if (softc->blk_shift != 0) {
 2873                                         length = length >> softc->blk_shift;
 2874                                 } else if (softc->media_blksize != 0) {
 2875                                         length = length / softc->media_blksize;
 2876                                 } else {
 2877                                         bp->bio_error = EIO;
 2878                                         xpt_print(periph->path, "zero blocksize"
 2879                                             " for FIXED length writes?\n");
 2880                                         biodone(bp);
 2881                                         break;
 2882                                 }
 2883 #if     0
 2884                                 CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO,
 2885                                     ("issuing a %d fixed record %s\n",
 2886                                     length,  (bp->bio_cmd == BIO_READ)? "read" :
 2887                                     "write"));
 2888 #endif
 2889                         } else {
 2890 #if     0
 2891                                 CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO,
 2892                                     ("issuing a %d variable byte %s\n",
 2893                                     length,  (bp->bio_cmd == BIO_READ)? "read" :
 2894                                     "write"));
 2895 #endif
 2896                         }
 2897                         devstat_start_transaction_bio(softc->device_stats, bp);
 2898                         /*
 2899                          * Some people have theorized that we should
 2900                          * suppress illegal length indication if we are
 2901                          * running in variable block mode so that we don't
 2902                          * have to request sense every time our requested
 2903                          * block size is larger than the written block.
 2904                          * The residual information from the ccb allows
 2905                          * us to identify this situation anyway.  The only
 2906                          * problem with this is that we will not get
 2907                          * information about blocks that are larger than
 2908                          * our read buffer unless we set the block size
 2909                          * in the mode page to something other than 0.
 2910                          *
 2911                          * I believe that this is a non-issue. If user apps
 2912                          * don't adjust their read size to match our record
 2913                          * size, that's just life. Anyway, the typical usage
 2914                          * would be to issue, e.g., 64KB reads and occasionally
 2915                          * have to do deal with 512 byte or 1KB intermediate
 2916                          * records.
 2917                          *
 2918                          * That said, though, we now support setting the
 2919                          * SILI bit on reads, and we set the blocksize to 4
 2920                          * bytes when we do that.  This gives us
 2921                          * compatibility with software that wants this,
 2922                          * although the only real difference between that
 2923                          * and not setting the SILI bit on reads is that we
 2924                          * won't get a check condition on reads where our
 2925                          * request size is larger than the block on tape.
 2926                          * That probably only makes a real difference in
 2927                          * non-packetized SCSI, where you have to go back
 2928                          * to the drive to request sense and thus incur
 2929                          * more latency.
 2930                          */
 2931                         softc->dsreg = (bp->bio_cmd == BIO_READ)?
 2932                             MTIO_DSREG_RD : MTIO_DSREG_WR;
 2933                         scsi_sa_read_write(&start_ccb->csio, 0, sadone,
 2934                             MSG_SIMPLE_Q_TAG, (bp->bio_cmd == BIO_READ ? 
 2935                             SCSI_RW_READ : SCSI_RW_WRITE) |
 2936                             ((bp->bio_flags & BIO_UNMAPPED) != 0 ?
 2937                             SCSI_RW_BIO : 0), softc->sili,
 2938                             (softc->flags & SA_FLAG_FIXED) != 0, length,
 2939                             (bp->bio_flags & BIO_UNMAPPED) != 0 ? (void *)bp :
 2940                             bp->bio_data, bp->bio_bcount, SSD_FULL_SIZE,
 2941                             (bp->bio_cmd == BIO_READ) ? 
 2942                             softc->timeout_info[SA_TIMEOUT_READ] :
 2943                             softc->timeout_info[SA_TIMEOUT_WRITE]);
 2944                         start_ccb->ccb_h.ccb_pflags &= ~SA_POSITION_UPDATED;
 2945                         start_ccb->ccb_h.ccb_bp = bp;
 2946                         bp = bioq_first(&softc->bio_queue);
 2947                         xpt_action(start_ccb);
 2948                 }
 2949                 
 2950                 if (bp != NULL) {
 2951                         /* Have more work to do, so ensure we stay scheduled */
 2952                         xpt_schedule(periph, CAM_PRIORITY_NORMAL);
 2953                 }
 2954                 break;
 2955         }
 2956         case SA_STATE_PROBE: {
 2957                 int num_opcodes;
 2958                 size_t alloc_len;
 2959                 uint8_t *params;
 2960 
 2961                 /*
 2962                  * This is an arbitrary number.  An IBM LTO-6 drive reports
 2963                  * 67 entries, and an IBM LTO-9 drive reports 71 entries.
 2964                  * There can theoretically be more than 256 because
 2965                  * service actions of a particular opcode are reported
 2966                  * separately, but we're far enough ahead of the practical
 2967                  * number here that we don't need to implement logic to
 2968                  * retry if we don't get all the timeout descriptors.
 2969                  */
 2970                 num_opcodes = 256;
 2971 
 2972                 alloc_len = num_opcodes *
 2973                     (sizeof(struct scsi_report_supported_opcodes_descr) +
 2974                      sizeof(struct scsi_report_supported_opcodes_timeout));
 2975 
 2976                 params = malloc(alloc_len, M_SCSISA, M_NOWAIT| M_ZERO);
 2977                 if (params == NULL) {
 2978                         /*
 2979                          * If this happens, go with default
 2980                          * timeouts and announce the drive.
 2981                          */
 2982                         saloadtotunables(softc);
 2983 
 2984                         softc->state = SA_STATE_NORMAL;
 2985 
 2986                         xpt_announce_periph(periph, NULL);
 2987                         xpt_announce_quirks(periph, softc->quirks,
 2988                                             SA_QUIRK_BIT_STRING);
 2989                         xpt_release_ccb(start_ccb);
 2990                         cam_periph_release_locked(periph);
 2991                         return;
 2992                 }
 2993 
 2994                 scsi_report_supported_opcodes(&start_ccb->csio,
 2995                     /*retries*/ 3,
 2996                     /*cbfcnp*/ sadone,
 2997                     /*tag_action*/ MSG_SIMPLE_Q_TAG,
 2998                     /*options*/ RSO_RCTD,
 2999                     /*req_opcode*/ 0,
 3000                     /*req_service_action*/ 0,
 3001                     /*data_ptr*/ params,
 3002                     /*dxfer_len*/ alloc_len,
 3003                     /*sense_len*/ SSD_FULL_SIZE,
 3004                     /*timeout*/ softc->timeout_info[SA_TIMEOUT_TUR]);
 3005 
 3006                 xpt_action(start_ccb);
 3007                 break;
 3008         }
 3009         case SA_STATE_ABNORMAL:
 3010         default:
 3011                 panic("state 0x%x in sastart", softc->state);
 3012                 break;
 3013         }
 3014 }
 3015 
 3016 static void
 3017 sadone(struct cam_periph *periph, union ccb *done_ccb)
 3018 {
 3019         struct sa_softc *softc;
 3020         struct ccb_scsiio *csio;
 3021         struct bio *bp;
 3022         int error;
 3023 
 3024         softc = (struct sa_softc *)periph->softc;
 3025         csio = &done_ccb->csio;
 3026         error = 0;
 3027 
 3028         if (softc->state == SA_STATE_NORMAL) {
 3029                 softc->dsreg = MTIO_DSREG_REST;
 3030                 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
 3031 
 3032                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 3033                         if ((error = saerror(done_ccb, 0, 0)) == ERESTART) {
 3034                                 /*
 3035                                  * A retry was scheduled, so just return.
 3036                                  */
 3037                                 return;
 3038                         }
 3039                 }
 3040         } else if (softc->state == SA_STATE_PROBE) {
 3041                 bp = NULL;
 3042                 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 3043                         /*
 3044                          * Note that on probe, we just run through
 3045                          * cam_periph_error(), since saerror() has a lot of
 3046                          * special handling for I/O errors.  We don't need
 3047                          * that to get the opcodes.  We either succeed
 3048                          * after a retry or two, or give up.  We don't
 3049                          * print sense, we don't need to worry the user if
 3050                          * this drive doesn't support timeout descriptors.
 3051                          */
 3052                         if ((error = cam_periph_error(done_ccb, 0,
 3053                              SF_NO_PRINT)) == ERESTART) {
 3054                                 /*
 3055                                  * A retry was scheduled, so just return.
 3056                                  */
 3057                                 return;
 3058                         } else if (error != 0) {
 3059                                 /* We failed to get opcodes.  Give up. */
 3060 
 3061                                 saloadtotunables(softc);
 3062 
 3063                                 softc->state = SA_STATE_NORMAL;
 3064 
 3065                                 xpt_release_ccb(done_ccb);
 3066 
 3067                                 xpt_announce_periph(periph, NULL);
 3068                                 xpt_announce_quirks(periph, softc->quirks,
 3069                                                     SA_QUIRK_BIT_STRING);
 3070                                 cam_periph_release_locked(periph);
 3071                                 return;
 3072                         }
 3073                 }
 3074                 /*
 3075                  * At this point, we have succeeded, so load the timeouts
 3076                  * and go into the normal state.
 3077                  */
 3078                 softc->state = SA_STATE_NORMAL;
 3079 
 3080                 /*
 3081                  * First, load the timeouts we got from the drive.
 3082                  */
 3083                 saloadtimeouts(softc, done_ccb);
 3084 
 3085                 /*
 3086                  * Next, overwrite the timeouts from the drive with any
 3087                  * loader tunables that the user set.
 3088                  */
 3089                 saloadtotunables(softc);
 3090 
 3091                 xpt_release_ccb(done_ccb);
 3092                 xpt_announce_periph(periph, NULL);
 3093                 xpt_announce_quirks(periph, softc->quirks,
 3094                                     SA_QUIRK_BIT_STRING);
 3095                 cam_periph_release_locked(periph);
 3096                 return;
 3097         } else {
 3098                 panic("state 0x%x in sadone", softc->state);
 3099         }
 3100 
 3101         if (error == EIO) {
 3102                 /*
 3103                  * Catastrophic error. Mark the tape as frozen
 3104                  * (we no longer know tape position).
 3105                  *
 3106                  * Return all queued I/O with EIO, and unfreeze
 3107                  * our queue so that future transactions that
 3108                  * attempt to fix this problem can get to the
 3109                  * device.
 3110                  *
 3111                  */
 3112 
 3113                 softc->flags |= SA_FLAG_TAPE_FROZEN;
 3114                 bioq_flush(&softc->bio_queue, NULL, EIO);
 3115         }
 3116         if (error != 0) {
 3117                 bp->bio_resid = bp->bio_bcount;
 3118                 bp->bio_error = error;
 3119                 bp->bio_flags |= BIO_ERROR;
 3120                 /*
 3121                  * In the error case, position is updated in saerror.
 3122                  */
 3123         } else {
 3124                 bp->bio_resid = csio->resid;
 3125                 bp->bio_error = 0;
 3126                 if (csio->resid != 0) {
 3127                         bp->bio_flags |= BIO_ERROR;
 3128                 }
 3129                 if (bp->bio_cmd == BIO_WRITE) {
 3130                         softc->flags |= SA_FLAG_TAPE_WRITTEN;
 3131                         softc->filemarks = 0;
 3132                 }
 3133                 if (!(csio->ccb_h.ccb_pflags & SA_POSITION_UPDATED) &&
 3134                     (softc->blkno != (daddr_t) -1)) {
 3135                         if ((softc->flags & SA_FLAG_FIXED) != 0) {
 3136                                 u_int32_t l;
 3137                                 if (softc->blk_shift != 0) {
 3138                                         l = bp->bio_bcount >>
 3139                                                 softc->blk_shift;
 3140                                 } else {
 3141                                         l = bp->bio_bcount /
 3142                                                 softc->media_blksize;
 3143                                 }
 3144                                 softc->blkno += (daddr_t) l;
 3145                         } else {
 3146                                 softc->blkno++;
 3147                         }
 3148                 }
 3149         }
 3150         /*
 3151          * If we had an error (immediate or pending),
 3152          * release the device queue now.
 3153          */
 3154         if (error || (softc->flags & SA_FLAG_ERR_PENDING))
 3155                 cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0);
 3156         if (error || bp->bio_resid) {
 3157                 CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
 3158                           ("error %d resid %ld count %ld\n", error,
 3159                           bp->bio_resid, bp->bio_bcount));
 3160         }
 3161         biofinish(bp, softc->device_stats, 0);
 3162         xpt_release_ccb(done_ccb);
 3163 }
 3164 
 3165 /*
 3166  * Mount the tape (make sure it's ready for I/O).
 3167  */
 3168 static int
 3169 samount(struct cam_periph *periph, int oflags, struct cdev *dev)
 3170 {
 3171         struct  sa_softc *softc;
 3172         union   ccb *ccb;
 3173         int     error;
 3174 
 3175         /*
 3176          * oflags can be checked for 'kind' of open (read-only check) - later
 3177          * dev can be checked for a control-mode or compression open - later
 3178          */
 3179         UNUSED_PARAMETER(oflags);
 3180         UNUSED_PARAMETER(dev);
 3181 
 3182         softc = (struct sa_softc *)periph->softc;
 3183 
 3184         /*
 3185          * This should determine if something has happened since the last
 3186          * open/mount that would invalidate the mount. We do *not* want
 3187          * to retry this command- we just want the status. But we only
 3188          * do this if we're mounted already- if we're not mounted,
 3189          * we don't care about the unit read state and can instead use
 3190          * this opportunity to attempt to reserve the tape unit.
 3191          */
 3192 
 3193         if (softc->flags & SA_FLAG_TAPE_MOUNTED) {
 3194                 ccb = cam_periph_getccb(periph, 1);
 3195                 scsi_test_unit_ready(&ccb->csio, 0, NULL,
 3196                     MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE,
 3197                     softc->timeout_info[SA_TIMEOUT_TUR]);
 3198                 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
 3199                     softc->device_stats);
 3200                 if (error == ENXIO) {
 3201                         softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
 3202                         scsi_test_unit_ready(&ccb->csio, 0, NULL,
 3203                             MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE,
 3204                             softc->timeout_info[SA_TIMEOUT_TUR]);
 3205                         error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
 3206                             softc->device_stats);
 3207                 } else if (error) {
 3208                         /*
 3209                          * We don't need to freeze the tape because we
 3210                          * will now attempt to rewind/load it.
 3211                          */
 3212                         softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
 3213                         if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) {
 3214                                 xpt_print(periph->path,
 3215                                     "error %d on TUR in samount\n", error);
 3216                         }
 3217                 }
 3218         } else {
 3219                 error = sareservereleaseunit(periph, TRUE);
 3220                 if (error) {
 3221                         return (error);
 3222                 }
 3223                 ccb = cam_periph_getccb(periph, 1);
 3224                 scsi_test_unit_ready(&ccb->csio, 0, NULL,
 3225                     MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE,
 3226                     softc->timeout_info[SA_TIMEOUT_TUR]);
 3227                 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
 3228                     softc->device_stats);
 3229         }
 3230 
 3231         if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) {
 3232                 struct scsi_read_block_limits_data *rblim = NULL;
 3233                 int comp_enabled, comp_supported;
 3234                 u_int8_t write_protect, guessing = 0;
 3235 
 3236                 /*
 3237                  * Clear out old state.
 3238                  */
 3239                 softc->flags &= ~(SA_FLAG_TAPE_WP|SA_FLAG_TAPE_WRITTEN|
 3240                                   SA_FLAG_ERR_PENDING|SA_FLAG_COMPRESSION);
 3241                 softc->filemarks = 0;
 3242 
 3243                 /*
 3244                  * *Very* first off, make sure we're loaded to BOT.
 3245                  */
 3246                 scsi_load_unload(&ccb->csio, 2, NULL, MSG_SIMPLE_Q_TAG, FALSE,
 3247                     FALSE, FALSE, 1, SSD_FULL_SIZE,
 3248                     softc->timeout_info[SA_TIMEOUT_LOAD]);
 3249                 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
 3250                     softc->device_stats);
 3251 
 3252                 /*
 3253                  * In case this doesn't work, do a REWIND instead
 3254                  */
 3255                 if (error) {
 3256                         scsi_rewind(&ccb->csio, 2, NULL, MSG_SIMPLE_Q_TAG,
 3257                             FALSE, SSD_FULL_SIZE,
 3258                             softc->timeout_info[SA_TIMEOUT_REWIND]);
 3259                         error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
 3260                                 softc->device_stats);
 3261                 }
 3262                 if (error) {
 3263                         xpt_release_ccb(ccb);
 3264                         goto exit;
 3265                 }
 3266 
 3267                 /*
 3268                  * Do a dummy test read to force access to the
 3269                  * media so that the drive will really know what's
 3270                  * there. We actually don't really care what the
 3271                  * blocksize on tape is and don't expect to really
 3272                  * read a full record.
 3273                  */
 3274                 rblim = (struct  scsi_read_block_limits_data *)
 3275                     malloc(8192, M_SCSISA, M_NOWAIT);
 3276                 if (rblim == NULL) {
 3277                         xpt_print(periph->path, "no memory for test read\n");
 3278                         xpt_release_ccb(ccb);
 3279                         error = ENOMEM;
 3280                         goto exit;
 3281                 }
 3282 
 3283                 if ((softc->quirks & SA_QUIRK_NODREAD) == 0) {
 3284                         scsi_sa_read_write(&ccb->csio, 0, NULL,
 3285                             MSG_SIMPLE_Q_TAG, 1, FALSE, 0, 8192,
 3286                             (void *) rblim, 8192, SSD_FULL_SIZE,
 3287                             softc->timeout_info[SA_TIMEOUT_READ]);
 3288                         (void) cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
 3289                             softc->device_stats);
 3290                         scsi_rewind(&ccb->csio, 1, NULL, MSG_SIMPLE_Q_TAG,
 3291                             FALSE, SSD_FULL_SIZE,
 3292                             softc->timeout_info[SA_TIMEOUT_REWIND]);
 3293                         error = cam_periph_runccb(ccb, saerror, CAM_RETRY_SELTO,
 3294                             SF_NO_PRINT | SF_RETRY_UA,
 3295                             softc->device_stats);
 3296                         if (error) {
 3297                                 xpt_print(periph->path,
 3298                                     "unable to rewind after test read\n");
 3299                                 xpt_release_ccb(ccb);
 3300                                 goto exit;
 3301                         }
 3302                 }
 3303 
 3304                 /*
 3305                  * Next off, determine block limits.
 3306                  */
 3307                 scsi_read_block_limits(&ccb->csio, 5, NULL, MSG_SIMPLE_Q_TAG,
 3308                     rblim, SSD_FULL_SIZE,
 3309                     softc->timeout_info[SA_TIMEOUT_READ_BLOCK_LIMITS]);
 3310 
 3311                 error = cam_periph_runccb(ccb, saerror, CAM_RETRY_SELTO,
 3312                     SF_NO_PRINT | SF_RETRY_UA, softc->device_stats);
 3313 
 3314                 xpt_release_ccb(ccb);
 3315 
 3316                 if (error != 0) {
 3317                         /*
 3318                          * If it's less than SCSI-2, READ BLOCK LIMITS is not
 3319                          * a MANDATORY command. Anyway- it doesn't matter-
 3320                          * we can proceed anyway.
 3321                          */
 3322                         softc->blk_gran = 0;
 3323                         softc->max_blk = ~0;
 3324                         softc->min_blk = 0;
 3325                 } else {
 3326                         if (softc->scsi_rev >= SCSI_REV_SPC) {
 3327                                 softc->blk_gran = RBL_GRAN(rblim);
 3328                         } else {
 3329                                 softc->blk_gran = 0;
 3330                         }
 3331                         /*
 3332                          * We take max_blk == min_blk to mean a default to
 3333                          * fixed mode- but note that whatever we get out of
 3334                          * sagetparams below will actually determine whether
 3335                          * we are actually *in* fixed mode.
 3336                          */
 3337                         softc->max_blk = scsi_3btoul(rblim->maximum);
 3338                         softc->min_blk = scsi_2btoul(rblim->minimum);
 3339                 }
 3340                 /*
 3341                  * Next, perform a mode sense to determine
 3342                  * current density, blocksize, compression etc.
 3343                  */
 3344                 error = sagetparams(periph, SA_PARAM_ALL,
 3345                                     &softc->media_blksize,
 3346                                     &softc->media_density,
 3347                                     &softc->media_numblks,
 3348                                     &softc->buffer_mode, &write_protect,
 3349                                     &softc->speed, &comp_supported,
 3350                                     &comp_enabled, &softc->comp_algorithm,
 3351                                     NULL, NULL, 0, 0);
 3352 
 3353                 if (error != 0) {
 3354                         /*
 3355                          * We could work a little harder here. We could
 3356                          * adjust our attempts to get information. It
 3357                          * might be an ancient tape drive. If someone
 3358                          * nudges us, we'll do that.
 3359                          */
 3360                         goto exit;
 3361                 }
 3362 
 3363                 /*
 3364                  * If no quirk has determined that this is a device that is
 3365                  * preferred to be in fixed or variable mode, now is the time
 3366                  * to find out.
 3367                  */
 3368                 if ((softc->quirks & (SA_QUIRK_FIXED|SA_QUIRK_VARIABLE)) == 0) {
 3369                         guessing = 1;
 3370                         /*
 3371                          * This could be expensive to find out. Luckily we
 3372                          * only need to do this once. If we start out in
 3373                          * 'default' mode, try and set ourselves to one
 3374                          * of the densities that would determine a wad
 3375                          * of other stuff. Go from highest to lowest.
 3376                          */
 3377                         if (softc->media_density == SCSI_DEFAULT_DENSITY) {
 3378                                 int i;
 3379                                 static u_int8_t ctry[] = {
 3380                                         SCSI_DENSITY_HALFINCH_PE,
 3381                                         SCSI_DENSITY_HALFINCH_6250C,
 3382                                         SCSI_DENSITY_HALFINCH_6250,
 3383                                         SCSI_DENSITY_HALFINCH_1600,
 3384                                         SCSI_DENSITY_HALFINCH_800,
 3385                                         SCSI_DENSITY_QIC_4GB,
 3386                                         SCSI_DENSITY_QIC_2GB,
 3387                                         SCSI_DENSITY_QIC_525_320,
 3388                                         SCSI_DENSITY_QIC_150,
 3389                                         SCSI_DENSITY_QIC_120,
 3390                                         SCSI_DENSITY_QIC_24,
 3391                                         SCSI_DENSITY_QIC_11_9TRK,
 3392                                         SCSI_DENSITY_QIC_11_4TRK,
 3393                                         SCSI_DENSITY_QIC_1320,
 3394                                         SCSI_DENSITY_QIC_3080,
 3395                                         0
 3396                                 };
 3397                                 for (i = 0; ctry[i]; i++) {
 3398                                         error = sasetparams(periph,
 3399                                             SA_PARAM_DENSITY, 0, ctry[i],
 3400                                             0, SF_NO_PRINT);
 3401                                         if (error == 0) {
 3402                                                 softc->media_density = ctry[i];
 3403                                                 break;
 3404                                         }
 3405                                 }
 3406                         }
 3407                         switch (softc->media_density) {
 3408                         case SCSI_DENSITY_QIC_11_4TRK:
 3409                         case SCSI_DENSITY_QIC_11_9TRK:
 3410                         case SCSI_DENSITY_QIC_24:
 3411                         case SCSI_DENSITY_QIC_120:
 3412                         case SCSI_DENSITY_QIC_150:
 3413                         case SCSI_DENSITY_QIC_525_320:
 3414                         case SCSI_DENSITY_QIC_1320:
 3415                         case SCSI_DENSITY_QIC_3080:
 3416                                 softc->quirks &= ~SA_QUIRK_2FM;
 3417                                 softc->quirks |= SA_QUIRK_FIXED|SA_QUIRK_1FM;
 3418                                 softc->last_media_blksize = 512;
 3419                                 break;
 3420                         case SCSI_DENSITY_QIC_4GB:
 3421                         case SCSI_DENSITY_QIC_2GB:
 3422                                 softc->quirks &= ~SA_QUIRK_2FM;
 3423                                 softc->quirks |= SA_QUIRK_FIXED|SA_QUIRK_1FM;
 3424                                 softc->last_media_blksize = 1024;
 3425                                 break;
 3426                         default:
 3427                                 softc->last_media_blksize =
 3428                                     softc->media_blksize;
 3429                                 softc->quirks |= SA_QUIRK_VARIABLE;
 3430                                 break;
 3431                         }
 3432                 }
 3433 
 3434                 /*
 3435                  * If no quirk has determined that this is a device that needs
 3436                  * to have 2 Filemarks at EOD, now is the time to find out.
 3437                  */
 3438 
 3439                 if ((softc->quirks & SA_QUIRK_2FM) == 0) {
 3440                         switch (softc->media_density) {
 3441                         case SCSI_DENSITY_HALFINCH_800:
 3442                         case SCSI_DENSITY_HALFINCH_1600:
 3443                         case SCSI_DENSITY_HALFINCH_6250:
 3444                         case SCSI_DENSITY_HALFINCH_6250C:
 3445                         case SCSI_DENSITY_HALFINCH_PE:
 3446                                 softc->quirks &= ~SA_QUIRK_1FM;
 3447                                 softc->quirks |= SA_QUIRK_2FM;
 3448                                 break;
 3449                         default:
 3450                                 break;
 3451                         }
 3452                 }
 3453 
 3454                 /*
 3455                  * Now validate that some info we got makes sense.
 3456                  */
 3457                 if ((softc->max_blk < softc->media_blksize) ||
 3458                     (softc->min_blk > softc->media_blksize &&
 3459                     softc->media_blksize)) {
 3460                         xpt_print(periph->path,
 3461                             "BLOCK LIMITS (%d..%d) could not match current "
 3462                             "block settings (%d)- adjusting\n", softc->min_blk,
 3463                             softc->max_blk, softc->media_blksize);
 3464                         softc->max_blk = softc->min_blk =
 3465                             softc->media_blksize;
 3466                 }
 3467 
 3468                 /*
 3469                  * Now put ourselves into the right frame of mind based
 3470                  * upon quirks...
 3471                  */
 3472 tryagain:
 3473                 /*
 3474                  * If we want to be in FIXED mode and our current blocksize
 3475                  * is not equal to our last blocksize (if nonzero), try and
 3476                  * set ourselves to this last blocksize (as the 'preferred'
 3477                  * block size).  The initial quirkmatch at registry sets the
 3478                  * initial 'last' blocksize. If, for whatever reason, this
 3479                  * 'last' blocksize is zero, set the blocksize to 512,
 3480                  * or min_blk if that's larger.
 3481                  */
 3482                 if ((softc->quirks & SA_QUIRK_FIXED) &&
 3483                     (softc->quirks & SA_QUIRK_NO_MODESEL) == 0 &&
 3484                     (softc->media_blksize != softc->last_media_blksize)) {
 3485                         softc->media_blksize = softc->last_media_blksize;
 3486                         if (softc->media_blksize == 0) {
 3487                                 softc->media_blksize = 512;
 3488                                 if (softc->media_blksize < softc->min_blk) {
 3489                                         softc->media_blksize = softc->min_blk;
 3490                                 }
 3491                         }
 3492                         error = sasetparams(periph, SA_PARAM_BLOCKSIZE,
 3493                             softc->media_blksize, 0, 0, SF_NO_PRINT);
 3494                         if (error) {
 3495                                 xpt_print(periph->path,
 3496                                     "unable to set fixed blocksize to %d\n",
 3497                                     softc->media_blksize);
 3498                                 goto exit;
 3499                         }
 3500                 }
 3501 
 3502                 if ((softc->quirks & SA_QUIRK_VARIABLE) && 
 3503                     (softc->media_blksize != 0)) {
 3504                         softc->last_media_blksize = softc->media_blksize;
 3505                         softc->media_blksize = 0;
 3506                         error = sasetparams(periph, SA_PARAM_BLOCKSIZE,
 3507                             0, 0, 0, SF_NO_PRINT);
 3508                         if (error) {
 3509                                 /*
 3510                                  * If this fails and we were guessing, just
 3511                                  * assume that we got it wrong and go try
 3512                                  * fixed block mode. Don't even check against
 3513                                  * density code at this point.
 3514                                  */
 3515                                 if (guessing) {
 3516                                         softc->quirks &= ~SA_QUIRK_VARIABLE;
 3517                                         softc->quirks |= SA_QUIRK_FIXED;
 3518                                         if (softc->last_media_blksize == 0)
 3519                                                 softc->last_media_blksize = 512;
 3520                                         goto tryagain;
 3521                                 }
 3522                                 xpt_print(periph->path,
 3523                                     "unable to set variable blocksize\n");
 3524                                 goto exit;
 3525                         }
 3526                 }
 3527 
 3528                 /*
 3529                  * Now that we have the current block size,
 3530                  * set up some parameters for sastart's usage.
 3531                  */
 3532                 if (softc->media_blksize) {
 3533                         softc->flags |= SA_FLAG_FIXED;
 3534                         if (powerof2(softc->media_blksize)) {
 3535                                 softc->blk_shift =
 3536                                     ffs(softc->media_blksize) - 1;
 3537                                 softc->blk_mask = softc->media_blksize - 1;
 3538                         } else {
 3539                                 softc->blk_mask = ~0;
 3540                                 softc->blk_shift = 0;
 3541                         }
 3542                 } else {
 3543                         /*
 3544                          * The SCSI-3 spec allows 0 to mean "unspecified".
 3545                          * The SCSI-1 spec allows 0 to mean 'infinite'.
 3546                          *
 3547                          * Either works here.
 3548                          */
 3549                         if (softc->max_blk == 0) {
 3550                                 softc->max_blk = ~0;
 3551                         }
 3552                         softc->blk_shift = 0;
 3553                         if (softc->blk_gran != 0) {
 3554                                 softc->blk_mask = softc->blk_gran - 1;
 3555                         } else {
 3556                                 softc->blk_mask = 0;
 3557                         }
 3558                 }
 3559 
 3560                 if (write_protect) 
 3561                         softc->flags |= SA_FLAG_TAPE_WP;
 3562 
 3563                 if (comp_supported) {
 3564                         if (softc->saved_comp_algorithm == 0)
 3565                                 softc->saved_comp_algorithm =
 3566                                     softc->comp_algorithm;
 3567                         softc->flags |= SA_FLAG_COMP_SUPP;
 3568                         if (comp_enabled)
 3569                                 softc->flags |= SA_FLAG_COMP_ENABLED;
 3570                 } else
 3571                         softc->flags |= SA_FLAG_COMP_UNSUPP;
 3572 
 3573                 if ((softc->buffer_mode == SMH_SA_BUF_MODE_NOBUF) &&
 3574                     (softc->quirks & SA_QUIRK_NO_MODESEL) == 0) {
 3575                         error = sasetparams(periph, SA_PARAM_BUFF_MODE, 0,
 3576                             0, 0, SF_NO_PRINT);
 3577                         if (error == 0) {
 3578                                 softc->buffer_mode = SMH_SA_BUF_MODE_SIBUF;
 3579                         } else {
 3580                                 xpt_print(periph->path,
 3581                                     "unable to set buffered mode\n");
 3582                         }
 3583                         error = 0;      /* not an error */
 3584                 }
 3585 
 3586                 if (error == 0) {
 3587                         softc->flags |= SA_FLAG_TAPE_MOUNTED;
 3588                 }
 3589 exit:
 3590                 if (rblim != NULL)
 3591                         free(rblim, M_SCSISA);
 3592 
 3593                 if (error != 0) {
 3594                         softc->dsreg = MTIO_DSREG_NIL;
 3595                 } else {
 3596                         softc->fileno = softc->blkno = 0;
 3597                         softc->rep_fileno = softc->rep_blkno = -1;
 3598                         softc->partition = 0;
 3599                         softc->dsreg = MTIO_DSREG_REST;
 3600                 }
 3601 #ifdef  SA_1FM_AT_EOD
 3602                 if ((softc->quirks & SA_QUIRK_2FM) == 0)
 3603                         softc->quirks |= SA_QUIRK_1FM;
 3604 #else
 3605                 if ((softc->quirks & SA_QUIRK_1FM) == 0)
 3606                         softc->quirks |= SA_QUIRK_2FM;
 3607 #endif
 3608         } else
 3609                 xpt_release_ccb(ccb);
 3610 
 3611         /*
 3612          * If we return an error, we're not mounted any more,
 3613          * so release any device reservation.
 3614          */
 3615         if (error != 0) {
 3616                 (void) sareservereleaseunit(periph, FALSE);
 3617         } else {
 3618                 /*
 3619                  * Clear I/O residual.
 3620                  */
 3621                 softc->last_io_resid = 0;
 3622                 softc->last_ctl_resid = 0;
 3623         }
 3624         return (error);
 3625 }
 3626 
 3627 /*
 3628  * How many filemarks do we need to write if we were to terminate the
 3629  * tape session right now? Note that this can be a negative number
 3630  */
 3631 
 3632 static int
 3633 samarkswanted(struct cam_periph *periph)
 3634 {
 3635         int     markswanted;
 3636         struct  sa_softc *softc;
 3637 
 3638         softc = (struct sa_softc *)periph->softc;
 3639         markswanted = 0;
 3640         if ((softc->flags & SA_FLAG_TAPE_WRITTEN) != 0) {
 3641                 markswanted++;
 3642                 if (softc->quirks & SA_QUIRK_2FM)
 3643                         markswanted++;
 3644         }
 3645         markswanted -= softc->filemarks;
 3646         return (markswanted);
 3647 }
 3648 
 3649 static int
 3650 sacheckeod(struct cam_periph *periph)
 3651 {
 3652         int     error;
 3653         int     markswanted;
 3654 
 3655         markswanted = samarkswanted(periph);
 3656 
 3657         if (markswanted > 0) {
 3658                 error = sawritefilemarks(periph, markswanted, FALSE, FALSE);
 3659         } else {
 3660                 error = 0;
 3661         }
 3662         return (error);
 3663 }
 3664 
 3665 static int
 3666 saerror(union ccb *ccb, u_int32_t cflgs, u_int32_t sflgs)
 3667 {
 3668         static const char *toobig =
 3669             "%d-byte tape record bigger than supplied buffer\n";
 3670         struct  cam_periph *periph;
 3671         struct  sa_softc *softc;
 3672         struct  ccb_scsiio *csio;
 3673         struct  scsi_sense_data *sense;
 3674         uint64_t resid = 0;
 3675         int64_t info = 0;
 3676         cam_status status;
 3677         int error_code, sense_key, asc, ascq, error, aqvalid, stream_valid;
 3678         int sense_len;
 3679         uint8_t stream_bits;
 3680 
 3681         periph = xpt_path_periph(ccb->ccb_h.path);
 3682         softc = (struct sa_softc *)periph->softc;
 3683         csio = &ccb->csio;
 3684         sense = &csio->sense_data;
 3685         sense_len = csio->sense_len - csio->sense_resid;
 3686         scsi_extract_sense_len(sense, sense_len, &error_code, &sense_key,
 3687             &asc, &ascq, /*show_errors*/ 1);
 3688         if (asc != -1 && ascq != -1)
 3689                 aqvalid = 1;
 3690         else
 3691                 aqvalid = 0;
 3692         if (scsi_get_stream_info(sense, sense_len, NULL, &stream_bits) == 0)
 3693                 stream_valid = 1;
 3694         else
 3695                 stream_valid = 0;
 3696         error = 0;
 3697 
 3698         status = csio->ccb_h.status & CAM_STATUS_MASK;
 3699 
 3700         /*
 3701          * Calculate/latch up, any residuals... We do this in a funny 2-step
 3702          * so we can print stuff here if we have CAM_DEBUG enabled for this
 3703          * unit.
 3704          */
 3705         if (status == CAM_SCSI_STATUS_ERROR) {
 3706                 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &resid,
 3707                                         &info) == 0) {
 3708                         if ((softc->flags & SA_FLAG_FIXED) != 0)
 3709                                 resid *= softc->media_blksize;
 3710                 } else {
 3711                         resid = csio->dxfer_len;
 3712                         info = resid;
 3713                         if ((softc->flags & SA_FLAG_FIXED) != 0) {
 3714                                 if (softc->media_blksize)
 3715                                         info /= softc->media_blksize;
 3716                         }
 3717                 }
 3718                 if (csio->cdb_io.cdb_bytes[0] == SA_READ ||
 3719                     csio->cdb_io.cdb_bytes[0] == SA_WRITE) {
 3720                         bcopy((caddr_t) sense, (caddr_t) &softc->last_io_sense,
 3721                             sizeof (struct scsi_sense_data));
 3722                         bcopy(csio->cdb_io.cdb_bytes, softc->last_io_cdb,
 3723                             (int) csio->cdb_len);
 3724                         softc->last_io_resid = resid;
 3725                         softc->last_resid_was_io = 1;
 3726                 } else {
 3727                         bcopy((caddr_t) sense, (caddr_t) &softc->last_ctl_sense,
 3728                             sizeof (struct scsi_sense_data));
 3729                         bcopy(csio->cdb_io.cdb_bytes, softc->last_ctl_cdb,
 3730                             (int) csio->cdb_len);
 3731                         softc->last_ctl_resid = resid;
 3732                         softc->last_resid_was_io = 0;
 3733                 }
 3734                 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("CDB[0]=0x%x Key 0x%x "
 3735                     "ASC/ASCQ 0x%x/0x%x CAM STATUS 0x%x flags 0x%x resid %jd "
 3736                     "dxfer_len %d\n", csio->cdb_io.cdb_bytes[0] & 0xff,
 3737                     sense_key, asc, ascq, status,
 3738                     (stream_valid) ? stream_bits : 0, (intmax_t)resid,
 3739                     csio->dxfer_len));
 3740         } else {
 3741                 CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
 3742                     ("Cam Status 0x%x\n", status));
 3743         }
 3744 
 3745         switch (status) {
 3746         case CAM_REQ_CMP:
 3747                 return (0);
 3748         case CAM_SCSI_STATUS_ERROR:
 3749                 /*
 3750                  * If a read/write command, we handle it here.
 3751                  */
 3752                 if (csio->cdb_io.cdb_bytes[0] == SA_READ ||
 3753                     csio->cdb_io.cdb_bytes[0] == SA_WRITE) {
 3754                         break;
 3755                 }
 3756                 /*
 3757                  * If this was just EOM/EOP, Filemark, Setmark, ILI or
 3758                  * PEW detected on a non read/write command, we assume
 3759                  * it's not an error and propagate the residual and return.
 3760                  */
 3761                 if ((aqvalid && asc == 0 && ((ascq > 0 && ascq <= 5)
 3762                   || (ascq == 0x07)))
 3763                  || (aqvalid == 0 && sense_key == SSD_KEY_NO_SENSE)) {
 3764                         csio->resid = resid;
 3765                         QFRLS(ccb);
 3766                         return (0);
 3767                 }
 3768                 /*
 3769                  * Otherwise, we let the common code handle this.
 3770                  */
 3771                 return (cam_periph_error(ccb, cflgs, sflgs));
 3772 
 3773         /*
 3774          * XXX: To Be Fixed
 3775          * We cannot depend upon CAM honoring retry counts for these.
 3776          */
 3777         case CAM_SCSI_BUS_RESET:
 3778         case CAM_BDR_SENT:
 3779                 if (ccb->ccb_h.retry_count <= 0) {
 3780                         return (EIO);
 3781                 }
 3782                 /* FALLTHROUGH */
 3783         default:
 3784                 return (cam_periph_error(ccb, cflgs, sflgs));
 3785         }
 3786 
 3787         /*
 3788          * Handle filemark, end of tape, mismatched record sizes....
 3789          * From this point out, we're only handling read/write cases.
 3790          * Handle writes && reads differently.
 3791          */
 3792 
 3793         if (csio->cdb_io.cdb_bytes[0] == SA_WRITE) {
 3794                 if (sense_key == SSD_KEY_VOLUME_OVERFLOW) {
 3795                         csio->resid = resid;
 3796                         error = ENOSPC;
 3797                 } else if ((stream_valid != 0) && (stream_bits & SSD_EOM)) {
 3798                         softc->flags |= SA_FLAG_EOM_PENDING;
 3799                         /*
 3800                          * Grotesque as it seems, the few times
 3801                          * I've actually seen a non-zero resid,
 3802                          * the tape drive actually lied and had
 3803                          * written all the data!.
 3804                          */
 3805                         csio->resid = 0;
 3806                 }
 3807         } else {
 3808                 csio->resid = resid;
 3809                 if (sense_key == SSD_KEY_BLANK_CHECK) {
 3810                         if (softc->quirks & SA_QUIRK_1FM) {
 3811                                 error = 0;
 3812                                 softc->flags |= SA_FLAG_EOM_PENDING;
 3813                         } else {
 3814                                 error = EIO;
 3815                         }
 3816                 } else if ((stream_valid != 0) && (stream_bits & SSD_FILEMARK)){
 3817                         if (softc->flags & SA_FLAG_FIXED) {
 3818                                 error = -1;
 3819                                 softc->flags |= SA_FLAG_EOF_PENDING;
 3820                         }
 3821                         /*
 3822                          * Unconditionally, if we detected a filemark on a read,
 3823                          * mark that we've run moved a file ahead.
 3824                          */
 3825                         if (softc->fileno != (daddr_t) -1) {
 3826                                 softc->fileno++;
 3827                                 softc->blkno = 0;
 3828                                 csio->ccb_h.ccb_pflags |= SA_POSITION_UPDATED;
 3829                         }
 3830                 }
 3831         }
 3832 
 3833         /*
 3834          * Incorrect Length usually applies to read, but can apply to writes.
 3835          */
 3836         if (error == 0 && (stream_valid != 0) && (stream_bits & SSD_ILI)) {
 3837                 if (info < 0) {
 3838                         xpt_print(csio->ccb_h.path, toobig,
 3839                             csio->dxfer_len - info);
 3840                         csio->resid = csio->dxfer_len;
 3841                         error = EIO;
 3842                 } else {
 3843                         csio->resid = resid;
 3844                         if (softc->flags & SA_FLAG_FIXED) {
 3845                                 softc->flags |= SA_FLAG_EIO_PENDING;
 3846                         }
 3847                         /*
 3848                          * Bump the block number if we hadn't seen a filemark.
 3849                          * Do this independent of errors (we've moved anyway).
 3850                          */
 3851                         if ((stream_valid == 0) ||
 3852                             (stream_bits & SSD_FILEMARK) == 0) {
 3853                                 if (softc->blkno != (daddr_t) -1) {
 3854                                         softc->blkno++;
 3855                                         csio->ccb_h.ccb_pflags |=
 3856                                            SA_POSITION_UPDATED;
 3857                                 }
 3858                         }
 3859                 }
 3860         }
 3861 
 3862         if (error <= 0) {
 3863                 /*
 3864                  * Unfreeze the queue if frozen as we're not returning anything
 3865                  * to our waiters that would indicate an I/O error has occurred
 3866                  * (yet).
 3867                  */
 3868                 QFRLS(ccb);
 3869                 error = 0;
 3870         }
 3871         return (error);
 3872 }
 3873 
 3874 static int
 3875 sagetparams(struct cam_periph *periph, sa_params params_to_get,
 3876             u_int32_t *blocksize, u_int8_t *density, u_int32_t *numblocks,
 3877             int *buff_mode, u_int8_t *write_protect, u_int8_t *speed,
 3878             int *comp_supported, int *comp_enabled, u_int32_t *comp_algorithm,
 3879             sa_comp_t *tcs, struct scsi_control_data_prot_subpage *prot_page,
 3880             int dp_size, int prot_changeable)
 3881 {
 3882         union ccb *ccb;
 3883         void *mode_buffer;
 3884         struct scsi_mode_header_6 *mode_hdr;
 3885         struct scsi_mode_blk_desc *mode_blk;
 3886         int mode_buffer_len;
 3887         struct sa_softc *softc;
 3888         u_int8_t cpage;
 3889         int error;
 3890         cam_status status;
 3891 
 3892         softc = (struct sa_softc *)periph->softc;
 3893         ccb = cam_periph_getccb(periph, 1);
 3894         if (softc->quirks & SA_QUIRK_NO_CPAGE)
 3895                 cpage = SA_DEVICE_CONFIGURATION_PAGE;
 3896         else
 3897                 cpage = SA_DATA_COMPRESSION_PAGE;
 3898 
 3899 retry:
 3900         mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk);
 3901 
 3902         if (params_to_get & SA_PARAM_COMPRESSION) {
 3903                 if (softc->quirks & SA_QUIRK_NOCOMP) {
 3904                         *comp_supported = FALSE;
 3905                         params_to_get &= ~SA_PARAM_COMPRESSION;
 3906                 } else
 3907                         mode_buffer_len += sizeof (sa_comp_t);
 3908         }
 3909 
 3910         /* XXX Fix M_NOWAIT */
 3911         mode_buffer = malloc(mode_buffer_len, M_SCSISA, M_NOWAIT | M_ZERO);
 3912         if (mode_buffer == NULL) {
 3913                 xpt_release_ccb(ccb);
 3914                 return (ENOMEM);
 3915         }
 3916         mode_hdr = (struct scsi_mode_header_6 *)mode_buffer;
 3917         mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
 3918 
 3919         /* it is safe to retry this */
 3920         scsi_mode_sense(&ccb->csio, 5, NULL, MSG_SIMPLE_Q_TAG, FALSE,
 3921             SMS_PAGE_CTRL_CURRENT, (params_to_get & SA_PARAM_COMPRESSION) ?
 3922             cpage : SMS_VENDOR_SPECIFIC_PAGE, mode_buffer, mode_buffer_len,
 3923             SSD_FULL_SIZE, softc->timeout_info[SA_TIMEOUT_MODE_SENSE]);
 3924 
 3925         error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
 3926             softc->device_stats);
 3927 
 3928         status = ccb->ccb_h.status & CAM_STATUS_MASK;
 3929 
 3930         if (error == EINVAL && (params_to_get & SA_PARAM_COMPRESSION) != 0) {
 3931                 /*
 3932                  * Hmm. Let's see if we can try another page...
 3933                  * If we've already done that, give up on compression
 3934                  * for this device and remember this for the future
 3935                  * and attempt the request without asking for compression
 3936                  * info.
 3937                  */
 3938                 if (cpage == SA_DATA_COMPRESSION_PAGE) {
 3939                         cpage = SA_DEVICE_CONFIGURATION_PAGE;
 3940                         goto retry;
 3941                 }
 3942                 softc->quirks |= SA_QUIRK_NOCOMP;
 3943                 free(mode_buffer, M_SCSISA);
 3944                 goto retry;
 3945         } else if (status == CAM_SCSI_STATUS_ERROR) {
 3946                 /* Tell the user about the fatal error. */
 3947                 scsi_sense_print(&ccb->csio);
 3948                 goto sagetparamsexit;
 3949         }
 3950 
 3951         /*
 3952          * If the user only wants the compression information, and
 3953          * the device doesn't send back the block descriptor, it's
 3954          * no big deal.  If the user wants more than just
 3955          * compression, though, and the device doesn't pass back the
 3956          * block descriptor, we need to send another mode sense to
 3957          * get the block descriptor.
 3958          */
 3959         if ((mode_hdr->blk_desc_len == 0) &&
 3960             (params_to_get & SA_PARAM_COMPRESSION) &&
 3961             (params_to_get & ~(SA_PARAM_COMPRESSION))) {
 3962                 /*
 3963                  * Decrease the mode buffer length by the size of
 3964                  * the compression page, to make sure the data
 3965                  * there doesn't get overwritten.
 3966                  */
 3967                 mode_buffer_len -= sizeof (sa_comp_t);
 3968 
 3969                 /*
 3970                  * Now move the compression page that we presumably
 3971                  * got back down the memory chunk a little bit so
 3972                  * it doesn't get spammed.
 3973                  */
 3974                 bcopy(&mode_hdr[0], &mode_hdr[1], sizeof (sa_comp_t));
 3975                 bzero(&mode_hdr[0], sizeof (mode_hdr[0]));
 3976 
 3977                 /*
 3978                  * Now, we issue another mode sense and just ask
 3979                  * for the block descriptor, etc.
 3980                  */
 3981 
 3982                 scsi_mode_sense(&ccb->csio, 2, NULL, MSG_SIMPLE_Q_TAG, FALSE,
 3983                     SMS_PAGE_CTRL_CURRENT, SMS_VENDOR_SPECIFIC_PAGE,
 3984                     mode_buffer, mode_buffer_len, SSD_FULL_SIZE,
 3985                     softc->timeout_info[SA_TIMEOUT_MODE_SENSE]);
 3986 
 3987                 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
 3988                     softc->device_stats);
 3989 
 3990                 if (error != 0)
 3991                         goto sagetparamsexit;
 3992         }
 3993 
 3994         if (params_to_get & SA_PARAM_BLOCKSIZE)
 3995                 *blocksize = scsi_3btoul(mode_blk->blklen);
 3996 
 3997         if (params_to_get & SA_PARAM_NUMBLOCKS)
 3998                 *numblocks = scsi_3btoul(mode_blk->nblocks);
 3999 
 4000         if (params_to_get & SA_PARAM_BUFF_MODE)
 4001                 *buff_mode = mode_hdr->dev_spec & SMH_SA_BUF_MODE_MASK;
 4002 
 4003         if (params_to_get & SA_PARAM_DENSITY)
 4004                 *density = mode_blk->density;
 4005 
 4006         if (params_to_get & SA_PARAM_WP)
 4007                 *write_protect = (mode_hdr->dev_spec & SMH_SA_WP)? TRUE : FALSE;
 4008 
 4009         if (params_to_get & SA_PARAM_SPEED)
 4010                 *speed = mode_hdr->dev_spec & SMH_SA_SPEED_MASK;
 4011 
 4012         if (params_to_get & SA_PARAM_COMPRESSION) {
 4013                 sa_comp_t *ntcs = (sa_comp_t *) &mode_blk[1];
 4014                 if (cpage == SA_DATA_COMPRESSION_PAGE) {
 4015                         struct scsi_data_compression_page *cp = &ntcs->dcomp;
 4016                         *comp_supported =
 4017                             (cp->dce_and_dcc & SA_DCP_DCC)? TRUE : FALSE;
 4018                         *comp_enabled =
 4019                             (cp->dce_and_dcc & SA_DCP_DCE)? TRUE : FALSE;
 4020                         *comp_algorithm = scsi_4btoul(cp->comp_algorithm);
 4021                 } else {
 4022                         struct scsi_dev_conf_page *cp = &ntcs->dconf;
 4023                         /*
 4024                          * We don't really know whether this device supports
 4025                          * Data Compression if the algorithm field is
 4026                          * zero. Just say we do.
 4027                          */
 4028                         *comp_supported = TRUE;
 4029                         *comp_enabled =
 4030                             (cp->sel_comp_alg != SA_COMP_NONE)? TRUE : FALSE;
 4031                         *comp_algorithm = cp->sel_comp_alg;
 4032                 }
 4033                 if (tcs != NULL)
 4034                         bcopy(ntcs, tcs, sizeof (sa_comp_t));
 4035         }
 4036 
 4037         if ((params_to_get & SA_PARAM_DENSITY_EXT)
 4038          && (softc->scsi_rev >= SCSI_REV_SPC)) {
 4039                 int i;
 4040 
 4041                 for (i = 0; i < SA_DENSITY_TYPES; i++) {
 4042                         scsi_report_density_support(&ccb->csio,
 4043                             /*retries*/ 1,
 4044                             /*cbfcnp*/ NULL,
 4045                             /*tag_action*/ MSG_SIMPLE_Q_TAG,
 4046                             /*media*/ softc->density_type_bits[i] & SRDS_MEDIA,
 4047                             /*medium_type*/ softc->density_type_bits[i] &
 4048                                             SRDS_MEDIUM_TYPE,
 4049                             /*data_ptr*/ softc->density_info[i],
 4050                             /*length*/ sizeof(softc->density_info[i]),
 4051                             /*sense_len*/ SSD_FULL_SIZE,
 4052                             /*timeout*/
 4053                                 softc->timeout_info[SA_TIMEOUT_REP_DENSITY]);
 4054                         error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
 4055                             softc->device_stats);
 4056                         status = ccb->ccb_h.status & CAM_STATUS_MASK;
 4057 
 4058                         /*
 4059                          * Some tape drives won't support this command at
 4060                          * all, but hopefully we'll minimize that with the
 4061                          * check for SPC or greater support above.  If they
 4062                          * don't support the default report (neither the
 4063                          * MEDIA or MEDIUM_TYPE bits set), then there is
 4064                          * really no point in continuing on to look for
 4065                          * other reports.
 4066                          */
 4067                         if ((error != 0)
 4068                          || (status != CAM_REQ_CMP)) {
 4069                                 error = 0;
 4070                                 softc->density_info_valid[i] = 0;
 4071                                 if (softc->density_type_bits[i] == 0)
 4072                                         break;
 4073                                 else
 4074                                         continue;
 4075                         }
 4076                         softc->density_info_valid[i] = ccb->csio.dxfer_len -
 4077                             ccb->csio.resid;
 4078                 }
 4079         }
 4080 
 4081         /*
 4082          * Get logical block protection parameters if the drive supports it.
 4083          */
 4084         if ((params_to_get & SA_PARAM_LBP)
 4085          && (softc->flags & SA_FLAG_PROTECT_SUPP)) {
 4086                 struct scsi_mode_header_10 *mode10_hdr;
 4087                 struct scsi_control_data_prot_subpage *dp_page;
 4088                 struct scsi_mode_sense_10 *cdb;
 4089                 struct sa_prot_state *prot;
 4090                 int dp_len, returned_len;
 4091 
 4092                 if (dp_size == 0)
 4093                         dp_size = sizeof(*dp_page);
 4094 
 4095                 dp_len = sizeof(*mode10_hdr) + dp_size;
 4096                 mode10_hdr = malloc(dp_len, M_SCSISA, M_NOWAIT | M_ZERO);
 4097                 if (mode10_hdr == NULL) {
 4098                         error = ENOMEM;
 4099                         goto sagetparamsexit;
 4100                 }
 4101 
 4102                 scsi_mode_sense_len(&ccb->csio,
 4103                                     /*retries*/ 5,
 4104                                     /*cbfcnp*/ NULL,
 4105                                     /*tag_action*/ MSG_SIMPLE_Q_TAG,
 4106                                     /*dbd*/ TRUE,
 4107                                     /*page_code*/ (prot_changeable == 0) ?
 4108                                                   SMS_PAGE_CTRL_CURRENT :
 4109                                                   SMS_PAGE_CTRL_CHANGEABLE,
 4110                                     /*page*/ SMS_CONTROL_MODE_PAGE,
 4111                                     /*param_buf*/ (uint8_t *)mode10_hdr,
 4112                                     /*param_len*/ dp_len,
 4113                                     /*minimum_cmd_size*/ 10,
 4114                                     /*sense_len*/ SSD_FULL_SIZE,
 4115                                     /*timeout*/
 4116                                     softc->timeout_info[SA_TIMEOUT_MODE_SENSE]);
 4117                 /*
 4118                  * XXX KDM we need to be able to set the subpage in the
 4119                  * fill function.
 4120                  */
 4121                 cdb = (struct scsi_mode_sense_10 *)ccb->csio.cdb_io.cdb_bytes;
 4122                 cdb->subpage = SA_CTRL_DP_SUBPAGE_CODE;
 4123 
 4124                 error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
 4125                     softc->device_stats);
 4126                 if (error != 0) {
 4127                         free(mode10_hdr, M_SCSISA);
 4128                         goto sagetparamsexit;
 4129                 }
 4130 
 4131                 status = ccb->ccb_h.status & CAM_STATUS_MASK;
 4132                 if (status != CAM_REQ_CMP) {
 4133                         error = EINVAL;
 4134                         free(mode10_hdr, M_SCSISA);
 4135                         goto sagetparamsexit;
 4136                 }
 4137 
 4138                 /*
 4139                  * The returned data length at least has to be long enough
 4140                  * for us to look at length in the mode page header.
 4141                  */
 4142                 returned_len = ccb->csio.dxfer_len - ccb->csio.resid;
 4143                 if (returned_len < sizeof(mode10_hdr->data_length)) {
 4144                         error = EINVAL;
 4145                         free(mode10_hdr, M_SCSISA);
 4146                         goto sagetparamsexit;
 4147                 }
 4148 
 4149                 returned_len = min(returned_len, 
 4150                     sizeof(mode10_hdr->data_length) +
 4151                     scsi_2btoul(mode10_hdr->data_length));
 4152 
 4153                 dp_page = (struct scsi_control_data_prot_subpage *)
 4154                     &mode10_hdr[1];
 4155 
 4156                 /*
 4157                  * We also have to have enough data to include the prot_bits
 4158                  * in the subpage.
 4159                  */
 4160                 if (returned_len < (sizeof(*mode10_hdr) +
 4161                     __offsetof(struct scsi_control_data_prot_subpage, prot_bits)
 4162                     + sizeof(dp_page->prot_bits))) {
 4163                         error = EINVAL;
 4164                         free(mode10_hdr, M_SCSISA);
 4165                         goto sagetparamsexit;
 4166                 }
 4167 
 4168                 prot = &softc->prot_info.cur_prot_state;
 4169                 prot->prot_method = dp_page->prot_method;
 4170                 prot->pi_length = dp_page->pi_length &
 4171                     SA_CTRL_DP_PI_LENGTH_MASK;
 4172                 prot->lbp_w = (dp_page->prot_bits & SA_CTRL_DP_LBP_W) ? 1 :0;
 4173                 prot->lbp_r = (dp_page->prot_bits & SA_CTRL_DP_LBP_R) ? 1 :0;
 4174                 prot->rbdp = (dp_page->prot_bits & SA_CTRL_DP_RBDP) ? 1 :0;
 4175                 prot->initialized = 1;
 4176 
 4177                 if (prot_page != NULL)
 4178                         bcopy(dp_page, prot_page, min(sizeof(*prot_page),
 4179                             sizeof(*dp_page)));
 4180 
 4181                 free(mode10_hdr, M_SCSISA);
 4182         }
 4183 
 4184         if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) {
 4185                 int idx;
 4186                 char *xyz = mode_buffer;
 4187                 xpt_print_path(periph->path);
 4188                 printf("Mode Sense Data=");
 4189                 for (idx = 0; idx < mode_buffer_len; idx++)
 4190                         printf(" 0x%02x", xyz[idx] & 0xff);
 4191                 printf("\n");
 4192         }
 4193 
 4194 sagetparamsexit:
 4195 
 4196         xpt_release_ccb(ccb);
 4197         free(mode_buffer, M_SCSISA);
 4198         return (error);
 4199 }
 4200 
 4201 /*
 4202  * Set protection information to the pending protection information stored
 4203  * in the softc.
 4204  */
 4205 static int
 4206 sasetprot(struct cam_periph *periph, struct sa_prot_state *new_prot)
 4207 {
 4208         struct sa_softc *softc;
 4209         struct scsi_control_data_prot_subpage *dp_page, *dp_changeable;
 4210         struct scsi_mode_header_10 *mode10_hdr, *mode10_changeable;
 4211         union ccb *ccb;
 4212         uint8_t current_speed;
 4213         size_t dp_size, dp_page_length;
 4214         int dp_len, buff_mode;
 4215         int error;
 4216 
 4217         softc = (struct sa_softc *)periph->softc;
 4218         mode10_hdr = NULL;
 4219         mode10_changeable = NULL;
 4220         ccb = NULL;
 4221 
 4222         /*
 4223          * Start off with the size set to the actual length of the page
 4224          * that we have defined.
 4225          */
 4226         dp_size = sizeof(*dp_changeable);
 4227         dp_page_length = dp_size -
 4228             __offsetof(struct scsi_control_data_prot_subpage, prot_method);
 4229 
 4230 retry_length:
 4231 
 4232         dp_len = sizeof(*mode10_changeable) + dp_size;
 4233         mode10_changeable = malloc(dp_len, M_SCSISA, M_NOWAIT | M_ZERO);
 4234         if (mode10_changeable == NULL) {
 4235                 error = ENOMEM;
 4236                 goto bailout;
 4237         }
 4238 
 4239         dp_changeable =
 4240             (struct scsi_control_data_prot_subpage *)&mode10_changeable[1];
 4241 
 4242         /*
 4243          * First get the data protection page changeable parameters mask.
 4244          * We need to know which parameters the drive supports changing.
 4245          * We also need to know what the drive claims that its page length
 4246          * is.  The reason is that IBM drives in particular are very picky
 4247          * about the page length.  They want it (the length set in the
 4248          * page structure itself) to be 28 bytes, and they want the
 4249          * parameter list length specified in the mode select header to be
 4250          * 40 bytes.  So, to work with IBM drives as well as any other tape
 4251          * drive, find out what the drive claims the page length is, and
 4252          * make sure that we match that.
 4253          */
 4254         error = sagetparams(periph, SA_PARAM_SPEED | SA_PARAM_LBP,  
 4255             NULL, NULL, NULL, &buff_mode, NULL, &current_speed, NULL, NULL,
 4256             NULL, NULL, dp_changeable, dp_size, /*prot_changeable*/ 1);
 4257         if (error != 0)
 4258                 goto bailout;
 4259 
 4260         if (scsi_2btoul(dp_changeable->length) > dp_page_length) {
 4261                 dp_page_length = scsi_2btoul(dp_changeable->length);
 4262                 dp_size = dp_page_length +
 4263                     __offsetof(struct scsi_control_data_prot_subpage,
 4264                     prot_method);
 4265                 free(mode10_changeable, M_SCSISA);
 4266                 mode10_changeable = NULL;
 4267                 goto retry_length;
 4268         }
 4269 
 4270         mode10_hdr = malloc(dp_len, M_SCSISA, M_NOWAIT | M_ZERO);
 4271         if (mode10_hdr == NULL) {
 4272                 error = ENOMEM;
 4273                 goto bailout;
 4274         }
 4275 
 4276         dp_page = (struct scsi_control_data_prot_subpage *)&mode10_hdr[1];
 4277 
 4278         /*
 4279          * Now grab the actual current settings in the page.
 4280          */
 4281         error = sagetparams(periph, SA_PARAM_SPEED | SA_PARAM_LBP,  
 4282             NULL, NULL, NULL, &buff_mode, NULL, &current_speed, NULL, NULL,
 4283             NULL, NULL, dp_page, dp_size, /*prot_changeable*/ 0);
 4284         if (error != 0)
 4285                 goto bailout;
 4286 
 4287         /* These two fields need to be 0 for MODE SELECT */
 4288         scsi_ulto2b(0, mode10_hdr->data_length);
 4289         mode10_hdr->medium_type = 0;
 4290         /* We are not including a block descriptor */
 4291         scsi_ulto2b(0, mode10_hdr->blk_desc_len);
 4292 
 4293         mode10_hdr->dev_spec = current_speed;
 4294         /* if set, set single-initiator buffering mode */
 4295         if (softc->buffer_mode == SMH_SA_BUF_MODE_SIBUF) {
 4296                 mode10_hdr->dev_spec |= SMH_SA_BUF_MODE_SIBUF;
 4297         }
 4298 
 4299         /*
 4300          * For each field, make sure that the drive allows changing it
 4301          * before bringing in the user's setting.
 4302          */
 4303         if (dp_changeable->prot_method != 0)
 4304                 dp_page->prot_method = new_prot->prot_method;
 4305 
 4306         if (dp_changeable->pi_length & SA_CTRL_DP_PI_LENGTH_MASK) {
 4307                 dp_page->pi_length &= ~SA_CTRL_DP_PI_LENGTH_MASK;
 4308                 dp_page->pi_length |= (new_prot->pi_length &
 4309                     SA_CTRL_DP_PI_LENGTH_MASK);
 4310         }
 4311         if (dp_changeable->prot_bits & SA_CTRL_DP_LBP_W) {
 4312                 if (new_prot->lbp_w)
 4313                         dp_page->prot_bits |= SA_CTRL_DP_LBP_W;
 4314                 else
 4315                         dp_page->prot_bits &= ~SA_CTRL_DP_LBP_W;
 4316         }
 4317 
 4318         if (dp_changeable->prot_bits & SA_CTRL_DP_LBP_R) {
 4319                 if (new_prot->lbp_r)
 4320                         dp_page->prot_bits |= SA_CTRL_DP_LBP_R;
 4321                 else
 4322                         dp_page->prot_bits &= ~SA_CTRL_DP_LBP_R;
 4323         }
 4324 
 4325         if (dp_changeable->prot_bits & SA_CTRL_DP_RBDP) {
 4326                 if (new_prot->rbdp)
 4327                         dp_page->prot_bits |= SA_CTRL_DP_RBDP;
 4328                 else
 4329                         dp_page->prot_bits &= ~SA_CTRL_DP_RBDP;
 4330         }
 4331 
 4332         ccb = cam_periph_getccb(periph, 1);
 4333 
 4334         scsi_mode_select_len(&ccb->csio,
 4335                              /*retries*/ 5,
 4336                              /*cbfcnp*/ NULL,
 4337                              /*tag_action*/ MSG_SIMPLE_Q_TAG,
 4338                              /*scsi_page_fmt*/ TRUE,
 4339                              /*save_pages*/ FALSE,
 4340                              /*param_buf*/ (uint8_t *)mode10_hdr,
 4341                              /*param_len*/ dp_len,
 4342                              /*minimum_cmd_size*/ 10,
 4343                              /*sense_len*/ SSD_FULL_SIZE,
 4344                              /*timeout*/
 4345                                    softc->timeout_info[SA_TIMEOUT_MODE_SELECT]);
 4346 
 4347         error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
 4348         if (error != 0)
 4349                 goto bailout;
 4350 
 4351         if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 4352                 error = EINVAL;
 4353                 goto bailout;
 4354         }
 4355 
 4356         /*
 4357          * The operation was successful.  We could just copy the settings
 4358          * the user requested, but just in case the drive ignored some of
 4359          * our settings, let's ask for status again.
 4360          */
 4361         error = sagetparams(periph, SA_PARAM_SPEED | SA_PARAM_LBP,  
 4362             NULL, NULL, NULL, &buff_mode, NULL, &current_speed, NULL, NULL,
 4363             NULL, NULL, dp_page, dp_size, 0);
 4364 
 4365 bailout:
 4366         if (ccb != NULL)
 4367                 xpt_release_ccb(ccb);
 4368         free(mode10_hdr, M_SCSISA);
 4369         free(mode10_changeable, M_SCSISA);
 4370         return (error);
 4371 }
 4372 
 4373 /*
 4374  * The purpose of this function is to set one of four different parameters
 4375  * for a tape drive:
 4376  *      - blocksize
 4377  *      - density
 4378  *      - compression / compression algorithm
 4379  *      - buffering mode
 4380  *
 4381  * The assumption is that this will be called from saioctl(), and therefore
 4382  * from a process context.  Thus the waiting malloc calls below.  If that
 4383  * assumption ever changes, the malloc calls should be changed to be
 4384  * NOWAIT mallocs.
 4385  *
 4386  * Any or all of the four parameters may be set when this function is
 4387  * called.  It should handle setting more than one parameter at once.
 4388  */
 4389 static int
 4390 sasetparams(struct cam_periph *periph, sa_params params_to_set,
 4391             u_int32_t blocksize, u_int8_t density, u_int32_t calg,
 4392             u_int32_t sense_flags)
 4393 {
 4394         struct sa_softc *softc;
 4395         u_int32_t current_blocksize;
 4396         u_int32_t current_calg;
 4397         u_int8_t current_density;
 4398         u_int8_t current_speed;
 4399         int comp_enabled, comp_supported;
 4400         void *mode_buffer;
 4401         int mode_buffer_len;
 4402         struct scsi_mode_header_6 *mode_hdr;
 4403         struct scsi_mode_blk_desc *mode_blk;
 4404         sa_comp_t *ccomp, *cpage;
 4405         int buff_mode;
 4406         union ccb *ccb = NULL;
 4407         int error;
 4408 
 4409         softc = (struct sa_softc *)periph->softc;
 4410 
 4411         ccomp = malloc(sizeof (sa_comp_t), M_SCSISA, M_NOWAIT);
 4412         if (ccomp == NULL)
 4413                 return (ENOMEM);
 4414 
 4415         /*
 4416          * Since it doesn't make sense to set the number of blocks, or
 4417          * write protection, we won't try to get the current value.  We
 4418          * always want to get the blocksize, so we can set it back to the
 4419          * proper value.
 4420          */
 4421         error = sagetparams(periph,
 4422             params_to_set | SA_PARAM_BLOCKSIZE | SA_PARAM_SPEED,
 4423             &current_blocksize, &current_density, NULL, &buff_mode, NULL,
 4424             &current_speed, &comp_supported, &comp_enabled,
 4425             &current_calg, ccomp, NULL, 0, 0);
 4426 
 4427         if (error != 0) {
 4428                 free(ccomp, M_SCSISA);
 4429                 return (error);
 4430         }
 4431 
 4432         mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk);
 4433         if (params_to_set & SA_PARAM_COMPRESSION)
 4434                 mode_buffer_len += sizeof (sa_comp_t);
 4435 
 4436         mode_buffer = malloc(mode_buffer_len, M_SCSISA, M_NOWAIT | M_ZERO);
 4437         if (mode_buffer == NULL) {
 4438                 free(ccomp, M_SCSISA);
 4439                 return (ENOMEM);
 4440         }
 4441 
 4442         mode_hdr = (struct scsi_mode_header_6 *)mode_buffer;
 4443         mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
 4444 
 4445         ccb = cam_periph_getccb(periph, 1);
 4446 
 4447 retry:
 4448 
 4449         if (params_to_set & SA_PARAM_COMPRESSION) {
 4450                 if (mode_blk) {
 4451                         cpage = (sa_comp_t *)&mode_blk[1];
 4452                 } else {
 4453                         cpage = (sa_comp_t *)&mode_hdr[1];
 4454                 }
 4455                 bcopy(ccomp, cpage, sizeof (sa_comp_t));
 4456                 cpage->hdr.pagecode &= ~0x80;
 4457         } else
 4458                 cpage = NULL;
 4459 
 4460         /*
 4461          * If the caller wants us to set the blocksize, use the one they
 4462          * pass in.  Otherwise, use the blocksize we got back from the
 4463          * mode select above.
 4464          */
 4465         if (mode_blk) {
 4466                 if (params_to_set & SA_PARAM_BLOCKSIZE)
 4467                         scsi_ulto3b(blocksize, mode_blk->blklen);
 4468                 else
 4469                         scsi_ulto3b(current_blocksize, mode_blk->blklen);
 4470 
 4471                 /*
 4472                  * Set density if requested, else preserve old density.
 4473                  * SCSI_SAME_DENSITY only applies to SCSI-2 or better
 4474                  * devices, else density we've latched up in our softc.
 4475                  */
 4476                 if (params_to_set & SA_PARAM_DENSITY) {
 4477                         mode_blk->density = density;
 4478                 } else if (softc->scsi_rev > SCSI_REV_CCS) {
 4479                         mode_blk->density = SCSI_SAME_DENSITY;
 4480                 } else {
 4481                         mode_blk->density = softc->media_density;
 4482                 }
 4483         }
 4484 
 4485         /*
 4486          * For mode selects, these two fields must be zero.
 4487          */
 4488         mode_hdr->data_length = 0;
 4489         mode_hdr->medium_type = 0;
 4490 
 4491         /* set the speed to the current value */
 4492         mode_hdr->dev_spec = current_speed;
 4493 
 4494         /* if set, set single-initiator buffering mode */
 4495         if (softc->buffer_mode == SMH_SA_BUF_MODE_SIBUF) {
 4496                 mode_hdr->dev_spec |= SMH_SA_BUF_MODE_SIBUF;
 4497         }
 4498 
 4499         if (mode_blk)
 4500                 mode_hdr->blk_desc_len = sizeof(struct scsi_mode_blk_desc);
 4501         else
 4502                 mode_hdr->blk_desc_len = 0;
 4503 
 4504         /*
 4505          * First, if the user wants us to set the compression algorithm or
 4506          * just turn compression on, check to make sure that this drive
 4507          * supports compression.
 4508          */
 4509         if (params_to_set & SA_PARAM_COMPRESSION) {
 4510                 /*
 4511                  * If the compression algorithm is 0, disable compression.
 4512                  * If the compression algorithm is non-zero, enable
 4513                  * compression and set the compression type to the
 4514                  * specified compression algorithm, unless the algorithm is
 4515                  * MT_COMP_ENABLE.  In that case, we look at the
 4516                  * compression algorithm that is currently set and if it is
 4517                  * non-zero, we leave it as-is.  If it is zero, and we have
 4518                  * saved a compression algorithm from a time when
 4519                  * compression was enabled before, set the compression to
 4520                  * the saved value.
 4521                  */
 4522                 switch (ccomp->hdr.pagecode & ~0x80) {
 4523                 case SA_DEVICE_CONFIGURATION_PAGE:
 4524                 {
 4525                         struct scsi_dev_conf_page *dcp = &cpage->dconf;
 4526                         if (calg == 0) {
 4527                                 dcp->sel_comp_alg = SA_COMP_NONE;
 4528                                 break;
 4529                         }
 4530                         if (calg != MT_COMP_ENABLE) {
 4531                                 dcp->sel_comp_alg = calg;
 4532                         } else if (dcp->sel_comp_alg == SA_COMP_NONE &&
 4533                             softc->saved_comp_algorithm != 0) {
 4534                                 dcp->sel_comp_alg = softc->saved_comp_algorithm;
 4535                         }
 4536                         break;
 4537                 }
 4538                 case SA_DATA_COMPRESSION_PAGE:
 4539                 if (ccomp->dcomp.dce_and_dcc & SA_DCP_DCC) {
 4540                         struct scsi_data_compression_page *dcp = &cpage->dcomp;
 4541                         if (calg == 0) {
 4542                                 /*
 4543                                  * Disable compression, but leave the
 4544                                  * decompression and the capability bit
 4545                                  * alone.
 4546                                  */
 4547                                 dcp->dce_and_dcc = SA_DCP_DCC;
 4548                                 dcp->dde_and_red |= SA_DCP_DDE;
 4549                                 break;
 4550                         }
 4551                         /* enable compression && decompression */
 4552                         dcp->dce_and_dcc = SA_DCP_DCE | SA_DCP_DCC;
 4553                         dcp->dde_and_red |= SA_DCP_DDE;
 4554                         /*
 4555                          * If there, use compression algorithm from caller.
 4556                          * Otherwise, if there's a saved compression algorithm
 4557                          * and there is no current algorithm, use the saved
 4558                          * algorithm. Else parrot back what we got and hope
 4559                          * for the best.
 4560                          */
 4561                         if (calg != MT_COMP_ENABLE) {
 4562                                 scsi_ulto4b(calg, dcp->comp_algorithm);
 4563                                 scsi_ulto4b(calg, dcp->decomp_algorithm);
 4564                         } else if (scsi_4btoul(dcp->comp_algorithm) == 0 &&
 4565                             softc->saved_comp_algorithm != 0) {
 4566                                 scsi_ulto4b(softc->saved_comp_algorithm,
 4567                                     dcp->comp_algorithm);
 4568                                 scsi_ulto4b(softc->saved_comp_algorithm,
 4569                                     dcp->decomp_algorithm);
 4570                         }
 4571                         break;
 4572                 }
 4573                 /*
 4574                  * Compression does not appear to be supported-
 4575                  * at least via the DATA COMPRESSION page. It
 4576                  * would be too much to ask us to believe that
 4577                  * the page itself is supported, but incorrectly
 4578                  * reports an ability to manipulate data compression,
 4579                  * so we'll assume that this device doesn't support
 4580                  * compression. We can just fall through for that.
 4581                  */
 4582                 /* FALLTHROUGH */
 4583                 default:
 4584                         /*
 4585                          * The drive doesn't seem to support compression,
 4586                          * so turn off the set compression bit.
 4587                          */
 4588                         params_to_set &= ~SA_PARAM_COMPRESSION;
 4589                         xpt_print(periph->path,
 4590                             "device does not seem to support compression\n");
 4591 
 4592                         /*
 4593                          * If that was the only thing the user wanted us to set,
 4594                          * clean up allocated resources and return with
 4595                          * 'operation not supported'.
 4596                          */
 4597                         if (params_to_set == SA_PARAM_NONE) {
 4598                                 free(mode_buffer, M_SCSISA);
 4599                                 xpt_release_ccb(ccb);
 4600                                 return (ENODEV);
 4601                         }
 4602                 
 4603                         /*
 4604                          * That wasn't the only thing the user wanted us to set.
 4605                          * So, decrease the stated mode buffer length by the
 4606                          * size of the compression mode page.
 4607                          */
 4608                         mode_buffer_len -= sizeof(sa_comp_t);
 4609                 }
 4610         }
 4611 
 4612         /* It is safe to retry this operation */
 4613         scsi_mode_select(&ccb->csio, 5, NULL, MSG_SIMPLE_Q_TAG,
 4614             (params_to_set & SA_PARAM_COMPRESSION)? TRUE : FALSE,
 4615             FALSE, mode_buffer, mode_buffer_len, SSD_FULL_SIZE,
 4616             softc->timeout_info[SA_TIMEOUT_MODE_SELECT]);
 4617 
 4618         error = cam_periph_runccb(ccb, saerror, 0,
 4619             sense_flags, softc->device_stats);
 4620 
 4621         if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) {
 4622                 int idx;
 4623                 char *xyz = mode_buffer;
 4624                 xpt_print_path(periph->path);
 4625                 printf("Err%d, Mode Select Data=", error);
 4626                 for (idx = 0; idx < mode_buffer_len; idx++)
 4627                         printf(" 0x%02x", xyz[idx] & 0xff);
 4628                 printf("\n");
 4629         }
 4630 
 4631         if (error) {
 4632                 /*
 4633                  * If we can, try without setting density/blocksize.
 4634                  */
 4635                 if (mode_blk) {
 4636                         if ((params_to_set &
 4637                             (SA_PARAM_DENSITY|SA_PARAM_BLOCKSIZE)) == 0) {
 4638                                 mode_blk = NULL;
 4639                                 goto retry;
 4640                         }
 4641                 } else {
 4642                         mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
 4643                         cpage = (sa_comp_t *)&mode_blk[1];
 4644                 }
 4645 
 4646                 /*
 4647                  * If we were setting the blocksize, and that failed, we
 4648                  * want to set it to its original value.  If we weren't
 4649                  * setting the blocksize, we don't want to change it.
 4650                  */
 4651                 scsi_ulto3b(current_blocksize, mode_blk->blklen);
 4652 
 4653                 /*
 4654                  * Set density if requested, else preserve old density.
 4655                  * SCSI_SAME_DENSITY only applies to SCSI-2 or better
 4656                  * devices, else density we've latched up in our softc.
 4657                  */
 4658                 if (params_to_set & SA_PARAM_DENSITY) {
 4659                         mode_blk->density = current_density;
 4660                 } else if (softc->scsi_rev > SCSI_REV_CCS) {
 4661                         mode_blk->density = SCSI_SAME_DENSITY;
 4662                 } else {
 4663                         mode_blk->density = softc->media_density;
 4664                 }
 4665 
 4666                 if (params_to_set & SA_PARAM_COMPRESSION)
 4667                         bcopy(ccomp, cpage, sizeof (sa_comp_t));
 4668 
 4669                 /*
 4670                  * The retry count is the only CCB field that might have been
 4671                  * changed that we care about, so reset it back to 1.
 4672                  */
 4673                 ccb->ccb_h.retry_count = 1;
 4674                 cam_periph_runccb(ccb, saerror, 0, sense_flags,
 4675                     softc->device_stats);
 4676         }
 4677 
 4678         xpt_release_ccb(ccb);
 4679 
 4680         if (ccomp != NULL)
 4681                 free(ccomp, M_SCSISA);
 4682 
 4683         if (params_to_set & SA_PARAM_COMPRESSION) {
 4684                 if (error) {
 4685                         softc->flags &= ~SA_FLAG_COMP_ENABLED;
 4686                         /*
 4687                          * Even if we get an error setting compression,
 4688                          * do not say that we don't support it. We could
 4689                          * have been wrong, or it may be media specific.
 4690                          *      softc->flags &= ~SA_FLAG_COMP_SUPP;
 4691                          */
 4692                         softc->saved_comp_algorithm = softc->comp_algorithm;
 4693                         softc->comp_algorithm = 0;
 4694                 } else {
 4695                         softc->flags |= SA_FLAG_COMP_ENABLED;
 4696                         softc->comp_algorithm = calg;
 4697                 }
 4698         }
 4699 
 4700         free(mode_buffer, M_SCSISA);
 4701         return (error);
 4702 }
 4703 
 4704 static int
 4705 saextget(struct cdev *dev, struct cam_periph *periph, struct sbuf *sb,
 4706     struct mtextget *g)
 4707 {
 4708         int indent, error;
 4709         char tmpstr[80];
 4710         struct sa_softc *softc;
 4711         int tmpint;
 4712         uint32_t maxio_tmp;
 4713         struct ccb_getdev cgd;
 4714 
 4715         softc = (struct sa_softc *)periph->softc;
 4716 
 4717         error = 0;
 4718 
 4719         error = sagetparams_common(dev, periph);
 4720         if (error)
 4721                 goto extget_bailout;
 4722         if (!SA_IS_CTRL(dev) && !softc->open_pending_mount)
 4723                 sagetpos(periph);
 4724 
 4725         indent = 0;
 4726         SASBADDNODE(sb, indent, mtextget);
 4727         /*
 4728          * Basic CAM peripheral information.
 4729          */
 4730         SASBADDVARSTR(sb, indent, periph->periph_name, %s, periph_name,
 4731             strlen(periph->periph_name) + 1);
 4732         SASBADDUINT(sb, indent, periph->unit_number, %u, unit_number);
 4733         memset(&cgd, 0, sizeof(cgd));
 4734         xpt_setup_ccb(&cgd.ccb_h,
 4735                       periph->path,
 4736                       CAM_PRIORITY_NORMAL);
 4737         cgd.ccb_h.func_code = XPT_GDEV_TYPE;
 4738         xpt_action((union ccb *)&cgd);
 4739         if ((cgd.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
 4740                 g->status = MT_EXT_GET_ERROR;
 4741                 snprintf(g->error_str, sizeof(g->error_str),
 4742                     "Error %#x returned for XPT_GDEV_TYPE CCB",
 4743                     cgd.ccb_h.status);
 4744                 goto extget_bailout;
 4745         }
 4746 
 4747         cam_strvis(tmpstr, cgd.inq_data.vendor,
 4748             sizeof(cgd.inq_data.vendor), sizeof(tmpstr));
 4749         SASBADDVARSTRDESC(sb, indent, tmpstr, %s, vendor,
 4750             sizeof(cgd.inq_data.vendor) + 1, "SCSI Vendor ID");
 4751 
 4752         cam_strvis(tmpstr, cgd.inq_data.product,
 4753             sizeof(cgd.inq_data.product), sizeof(tmpstr));
 4754         SASBADDVARSTRDESC(sb, indent, tmpstr, %s, product,
 4755             sizeof(cgd.inq_data.product) + 1, "SCSI Product ID");
 4756 
 4757         cam_strvis(tmpstr, cgd.inq_data.revision,
 4758             sizeof(cgd.inq_data.revision), sizeof(tmpstr));
 4759         SASBADDVARSTRDESC(sb, indent, tmpstr, %s, revision,
 4760             sizeof(cgd.inq_data.revision) + 1, "SCSI Revision");
 4761 
 4762         if (cgd.serial_num_len > 0) {
 4763                 char *tmpstr2;
 4764                 size_t ts2_len;
 4765                 int ts2_malloc;
 4766 
 4767                 ts2_len = 0;
 4768 
 4769                 if (cgd.serial_num_len > sizeof(tmpstr)) {
 4770                         ts2_len = cgd.serial_num_len + 1;
 4771                         ts2_malloc = 1;
 4772                         tmpstr2 = malloc(ts2_len, M_SCSISA, M_NOWAIT | M_ZERO);
 4773                         /*
 4774                          * The 80 characters allocated on the stack above
 4775                          * will handle the vast majority of serial numbers.
 4776                          * If we run into one that is larger than that, and
 4777                          * we can't malloc the length without blocking,
 4778                          * bail out with an out of memory error.
 4779                          */
 4780                         if (tmpstr2 == NULL) {
 4781                                 error = ENOMEM;
 4782                                 goto extget_bailout;
 4783                         }
 4784                 } else {
 4785                         ts2_len = sizeof(tmpstr);
 4786                         ts2_malloc = 0;
 4787                         tmpstr2 = tmpstr;
 4788                 }
 4789 
 4790                 cam_strvis(tmpstr2, cgd.serial_num, cgd.serial_num_len,
 4791                     ts2_len);
 4792 
 4793                 SASBADDVARSTRDESC(sb, indent, tmpstr2, %s, serial_num,
 4794                     (ssize_t)cgd.serial_num_len + 1, "Serial Number");
 4795                 if (ts2_malloc != 0)
 4796                         free(tmpstr2, M_SCSISA);
 4797         } else {
 4798                 /*
 4799                  * We return a serial_num element in any case, but it will
 4800                  * be empty if the device has no serial number.
 4801                  */
 4802                 tmpstr[0] = '\0';
 4803                 SASBADDVARSTRDESC(sb, indent, tmpstr, %s, serial_num,
 4804                     (ssize_t)0, "Serial Number");
 4805         }
 4806 
 4807         SASBADDUINTDESC(sb, indent, softc->maxio, %u, maxio, 
 4808             "Maximum I/O size allowed by driver and controller");
 4809 
 4810         SASBADDUINTDESC(sb, indent, softc->cpi_maxio, %u, cpi_maxio, 
 4811             "Maximum I/O size reported by controller");
 4812 
 4813         SASBADDUINTDESC(sb, indent, softc->max_blk, %u, max_blk, 
 4814             "Maximum block size supported by tape drive and media");
 4815 
 4816         SASBADDUINTDESC(sb, indent, softc->min_blk, %u, min_blk, 
 4817             "Minimum block size supported by tape drive and media");
 4818 
 4819         SASBADDUINTDESC(sb, indent, softc->blk_gran, %u, blk_gran, 
 4820             "Block granularity supported by tape drive and media");
 4821 
 4822         maxio_tmp = min(softc->max_blk, softc->maxio);
 4823 
 4824         SASBADDUINTDESC(sb, indent, maxio_tmp, %u, max_effective_iosize, 
 4825             "Maximum possible I/O size");
 4826 
 4827         SASBADDINTDESC(sb, indent, softc->flags & SA_FLAG_FIXED ? 1 : 0, %d, 
 4828             fixed_mode, "Set to 1 for fixed block mode, 0 for variable block");
 4829 
 4830         /*
 4831          * XXX KDM include SIM, bus, target, LUN?
 4832          */
 4833         if (softc->flags & SA_FLAG_COMP_UNSUPP)
 4834                 tmpint = 0;
 4835         else
 4836                 tmpint = 1;
 4837         SASBADDINTDESC(sb, indent, tmpint, %d, compression_supported,
 4838             "Set to 1 if compression is supported, 0 if not");
 4839         if (softc->flags & SA_FLAG_COMP_ENABLED)
 4840                 tmpint = 1;
 4841         else
 4842                 tmpint = 0;
 4843         SASBADDINTDESC(sb, indent, tmpint, %d, compression_enabled,
 4844             "Set to 1 if compression is enabled, 0 if not");
 4845         SASBADDUINTDESC(sb, indent, softc->comp_algorithm, %u,
 4846             compression_algorithm, "Numeric compression algorithm");
 4847 
 4848         safillprot(softc, &indent, sb);
 4849 
 4850         SASBADDUINTDESC(sb, indent, softc->media_blksize, %u,
 4851             media_blocksize, "Block size reported by drive or set by user");
 4852         SASBADDINTDESC(sb, indent, (intmax_t)softc->fileno, %jd,
 4853             calculated_fileno, "Calculated file number, -1 if unknown");
 4854         SASBADDINTDESC(sb, indent, (intmax_t)softc->blkno, %jd,
 4855             calculated_rel_blkno, "Calculated block number relative to file, "
 4856             "set to -1 if unknown");
 4857         SASBADDINTDESC(sb, indent, (intmax_t)softc->rep_fileno, %jd,
 4858             reported_fileno, "File number reported by drive, -1 if unknown");
 4859         SASBADDINTDESC(sb, indent, (intmax_t)softc->rep_blkno, %jd,
 4860             reported_blkno, "Block number relative to BOP/BOT reported by "
 4861             "drive, -1 if unknown");
 4862         SASBADDINTDESC(sb, indent, (intmax_t)softc->partition, %jd,
 4863             partition, "Current partition number, 0 is the default");
 4864         SASBADDINTDESC(sb, indent, softc->bop, %d, bop,
 4865             "Set to 1 if drive is at the beginning of partition/tape, 0 if "
 4866             "not, -1 if unknown");
 4867         SASBADDINTDESC(sb, indent, softc->eop, %d, eop,
 4868             "Set to 1 if drive is past early warning, 0 if not, -1 if unknown");
 4869         SASBADDINTDESC(sb, indent, softc->bpew, %d, bpew,
 4870             "Set to 1 if drive is past programmable early warning, 0 if not, "
 4871             "-1 if unknown");
 4872         SASBADDINTDESC(sb, indent, (intmax_t)softc->last_io_resid, %jd,
 4873             residual, "Residual for the last I/O");
 4874         /*
 4875          * XXX KDM should we send a string with the current driver
 4876          * status already decoded instead of a numeric value?
 4877          */
 4878         SASBADDINTDESC(sb, indent, softc->dsreg, %d, dsreg, 
 4879             "Current state of the driver");
 4880 
 4881         safilldensitysb(softc, &indent, sb);
 4882 
 4883         SASBENDNODE(sb, indent, mtextget);
 4884 
 4885 extget_bailout:
 4886 
 4887         return (error);
 4888 }
 4889 
 4890 static int
 4891 saparamget(struct sa_softc *softc, struct sbuf *sb)
 4892 {
 4893         int indent;
 4894 
 4895         indent = 0;
 4896         SASBADDNODE(sb, indent, mtparamget);
 4897         SASBADDINTDESC(sb, indent, softc->sili, %d, sili, 
 4898             "Suppress an error on underlength variable reads");
 4899         SASBADDINTDESC(sb, indent, softc->eot_warn, %d, eot_warn, 
 4900             "Return an error to warn that end of tape is approaching");
 4901         safillprot(softc, &indent, sb);
 4902         SASBENDNODE(sb, indent, mtparamget);
 4903 
 4904         return (0);
 4905 }
 4906 
 4907 static void
 4908 saprevent(struct cam_periph *periph, int action)
 4909 {
 4910         struct  sa_softc *softc;
 4911         union   ccb *ccb;               
 4912         int     error, sf;
 4913                 
 4914         softc = (struct sa_softc *)periph->softc;
 4915 
 4916         if ((action == PR_ALLOW) && (softc->flags & SA_FLAG_TAPE_LOCKED) == 0)
 4917                 return;
 4918         if ((action == PR_PREVENT) && (softc->flags & SA_FLAG_TAPE_LOCKED) != 0)
 4919                 return;
 4920 
 4921         /*
 4922          * We can be quiet about illegal requests.
 4923          */
 4924         if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) {
 4925                 sf = 0;
 4926         } else
 4927                 sf = SF_QUIET_IR;
 4928 
 4929         ccb = cam_periph_getccb(periph, 1);
 4930 
 4931         /* It is safe to retry this operation */
 4932         scsi_prevent(&ccb->csio, 5, NULL, MSG_SIMPLE_Q_TAG, action,
 4933             SSD_FULL_SIZE, softc->timeout_info[SA_TIMEOUT_PREVENT]);
 4934 
 4935         error = cam_periph_runccb(ccb, saerror, 0, sf, softc->device_stats);
 4936         if (error == 0) {
 4937                 if (action == PR_ALLOW)
 4938                         softc->flags &= ~SA_FLAG_TAPE_LOCKED;
 4939                 else
 4940                         softc->flags |= SA_FLAG_TAPE_LOCKED;
 4941         }
 4942 
 4943         xpt_release_ccb(ccb);
 4944 }
 4945 
 4946 static int
 4947 sarewind(struct cam_periph *periph)
 4948 {
 4949         union   ccb *ccb;
 4950         struct  sa_softc *softc;
 4951         int     error;
 4952                 
 4953         softc = (struct sa_softc *)periph->softc;
 4954 
 4955         ccb = cam_periph_getccb(periph, 1);
 4956 
 4957         /* It is safe to retry this operation */
 4958         scsi_rewind(&ccb->csio, 2, NULL, MSG_SIMPLE_Q_TAG, FALSE,
 4959             SSD_FULL_SIZE, softc->timeout_info[SA_TIMEOUT_REWIND]);
 4960 
 4961         softc->dsreg = MTIO_DSREG_REW;
 4962         error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
 4963         softc->dsreg = MTIO_DSREG_REST;
 4964 
 4965         xpt_release_ccb(ccb);
 4966         if (error == 0) {
 4967                 softc->partition = softc->fileno = softc->blkno = (daddr_t) 0;
 4968                 softc->rep_fileno = softc->rep_blkno = (daddr_t) 0;
 4969         } else {
 4970                 softc->fileno = softc->blkno = (daddr_t) -1;
 4971                 softc->partition = (daddr_t) -1; 
 4972                 softc->rep_fileno = softc->rep_blkno = (daddr_t) -1;
 4973         }
 4974         return (error);
 4975 }
 4976 
 4977 static int
 4978 saspace(struct cam_periph *periph, int count, scsi_space_code code)
 4979 {
 4980         union   ccb *ccb;
 4981         struct  sa_softc *softc;
 4982         int     error;
 4983                 
 4984         softc = (struct sa_softc *)periph->softc;
 4985 
 4986         ccb = cam_periph_getccb(periph, 1);
 4987 
 4988         /* This cannot be retried */
 4989 
 4990         scsi_space(&ccb->csio, 0, NULL, MSG_SIMPLE_Q_TAG, code, count,
 4991             SSD_FULL_SIZE, softc->timeout_info[SA_TIMEOUT_SPACE]);
 4992 
 4993         /*
 4994          * Clear residual because we will be using it.
 4995          */
 4996         softc->last_ctl_resid = 0;
 4997 
 4998         softc->dsreg = (count < 0)? MTIO_DSREG_REV : MTIO_DSREG_FWD;
 4999         error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
 5000         softc->dsreg = MTIO_DSREG_REST;
 5001 
 5002         xpt_release_ccb(ccb);
 5003 
 5004         /*
 5005          * If a spacing operation has failed, we need to invalidate
 5006          * this mount.
 5007          *
 5008          * If the spacing operation was setmarks or to end of recorded data,
 5009          * we no longer know our relative position.
 5010          *
 5011          * If the spacing operations was spacing files in reverse, we
 5012          * take account of the residual, but still check against less
 5013          * than zero- if we've gone negative, we must have hit BOT.
 5014          *
 5015          * If the spacing operations was spacing records in reverse and
 5016          * we have a residual, we've either hit BOT or hit a filemark.
 5017          * In the former case, we know our new record number (0). In
 5018          * the latter case, we have absolutely no idea what the real
 5019          * record number is- we've stopped between the end of the last
 5020          * record in the previous file and the filemark that stopped
 5021          * our spacing backwards.
 5022          */
 5023         if (error) {
 5024                 softc->fileno = softc->blkno = (daddr_t) -1;
 5025                 softc->rep_blkno = softc->partition = (daddr_t) -1;
 5026                 softc->rep_fileno = (daddr_t) -1;
 5027         } else if (code == SS_SETMARKS || code == SS_EOD) {
 5028                 softc->fileno = softc->blkno = (daddr_t) -1;
 5029         } else if (code == SS_FILEMARKS && softc->fileno != (daddr_t) -1) {
 5030                 softc->fileno += (count - softc->last_ctl_resid);
 5031                 if (softc->fileno < 0)  /* we must of hit BOT */
 5032                         softc->fileno = 0;
 5033                 softc->blkno = 0;
 5034         } else if (code == SS_BLOCKS && softc->blkno != (daddr_t) -1) {
 5035                 softc->blkno += (count - softc->last_ctl_resid);
 5036                 if (count < 0) {
 5037                         if (softc->last_ctl_resid || softc->blkno < 0) {
 5038                                 if (softc->fileno == 0) {
 5039                                         softc->blkno = 0;
 5040                                 } else {
 5041                                         softc->blkno = (daddr_t) -1;
 5042                                 }
 5043                         }
 5044                 }
 5045         }
 5046         if (error == 0)
 5047                 sagetpos(periph);
 5048 
 5049         return (error);
 5050 }
 5051 
 5052 static int
 5053 sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks, int immed)
 5054 {
 5055         union   ccb *ccb;
 5056         struct  sa_softc *softc;
 5057         int     error, nwm = 0;
 5058 
 5059         softc = (struct sa_softc *)periph->softc;
 5060         if (softc->open_rdonly)
 5061                 return (EBADF);
 5062 
 5063         ccb = cam_periph_getccb(periph, 1);
 5064         /*
 5065          * Clear residual because we will be using it.
 5066          */
 5067         softc->last_ctl_resid = 0;
 5068 
 5069         softc->dsreg = MTIO_DSREG_FMK;
 5070         /* this *must* not be retried */
 5071         scsi_write_filemarks(&ccb->csio, 0, NULL, MSG_SIMPLE_Q_TAG,
 5072             immed, setmarks, nmarks, SSD_FULL_SIZE,
 5073             softc->timeout_info[SA_TIMEOUT_WRITE_FILEMARKS]);
 5074         softc->dsreg = MTIO_DSREG_REST;
 5075 
 5076         error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
 5077 
 5078         if (error == 0 && nmarks) {
 5079                 struct sa_softc *softc = (struct sa_softc *)periph->softc;
 5080                 nwm = nmarks - softc->last_ctl_resid;
 5081                 softc->filemarks += nwm;
 5082         }
 5083 
 5084         xpt_release_ccb(ccb);
 5085 
 5086         /*
 5087          * Update relative positions (if we're doing that).
 5088          */
 5089         if (error) {
 5090                 softc->fileno = softc->blkno = softc->partition = (daddr_t) -1;
 5091         } else if (softc->fileno != (daddr_t) -1) {
 5092                 softc->fileno += nwm;
 5093                 softc->blkno = 0;
 5094         }
 5095 
 5096         /*
 5097          * Ask the tape drive for position information.
 5098          */
 5099         sagetpos(periph);
 5100 
 5101         /*
 5102          * If we got valid position information, since we just wrote a file
 5103          * mark, we know we're at the file mark and block 0 after that
 5104          * filemark.
 5105          */
 5106         if (softc->rep_fileno != (daddr_t) -1) {
 5107                 softc->fileno = softc->rep_fileno;
 5108                 softc->blkno = 0;
 5109         }
 5110 
 5111         return (error);
 5112 }
 5113 
 5114 static int
 5115 sagetpos(struct cam_periph *periph)
 5116 {
 5117         union ccb *ccb;
 5118         struct scsi_tape_position_long_data long_pos;
 5119         struct sa_softc *softc = (struct sa_softc *)periph->softc;
 5120         int error;
 5121 
 5122         if (softc->quirks & SA_QUIRK_NO_LONG_POS) {
 5123                 softc->rep_fileno = (daddr_t) -1;
 5124                 softc->rep_blkno = (daddr_t) -1;
 5125                 softc->bop = softc->eop = softc->bpew = -1;
 5126                 return (EOPNOTSUPP);
 5127         }
 5128 
 5129         bzero(&long_pos, sizeof(long_pos));
 5130 
 5131         ccb = cam_periph_getccb(periph, CAM_PRIORITY_NORMAL);
 5132         scsi_read_position_10(&ccb->csio,
 5133                               /*retries*/ 1,
 5134                               /*cbfcnp*/ NULL,
 5135                               /*tag_action*/ MSG_SIMPLE_Q_TAG,
 5136                               /*service_action*/ SA_RPOS_LONG_FORM,
 5137                               /*data_ptr*/ (uint8_t *)&long_pos,
 5138                               /*length*/ sizeof(long_pos),
 5139                               /*sense_len*/ SSD_FULL_SIZE,
 5140                               /*timeout*/
 5141                                  softc->timeout_info[SA_TIMEOUT_READ_POSITION]);
 5142 
 5143         softc->dsreg = MTIO_DSREG_RBSY;
 5144         error = cam_periph_runccb(ccb, saerror, 0, SF_QUIET_IR,
 5145                                   softc->device_stats);
 5146         softc->dsreg = MTIO_DSREG_REST;
 5147 
 5148         if (error == 0) {
 5149                 if (long_pos.flags & SA_RPOS_LONG_MPU) {
 5150                         /*
 5151                          * If the drive doesn't know what file mark it is
 5152                          * on, our calculated filemark isn't going to be
 5153                          * accurate either.
 5154                          */
 5155                         softc->fileno = (daddr_t) -1;
 5156                         softc->rep_fileno = (daddr_t) -1;
 5157                 } else {
 5158                         softc->fileno = softc->rep_fileno =
 5159                             scsi_8btou64(long_pos.logical_file_num);
 5160                 }
 5161 
 5162                 if (long_pos.flags & SA_RPOS_LONG_LONU) {
 5163                         softc->partition = (daddr_t) -1;
 5164                         softc->rep_blkno = (daddr_t) -1;
 5165                         /*
 5166                          * If the tape drive doesn't know its block
 5167                          * position, we can't claim to know it either.
 5168                          */
 5169                         softc->blkno = (daddr_t) -1;
 5170                 } else {
 5171                         softc->partition = scsi_4btoul(long_pos.partition);
 5172                         softc->rep_blkno =
 5173                             scsi_8btou64(long_pos.logical_object_num);
 5174                 }
 5175                 if (long_pos.flags & SA_RPOS_LONG_BOP)
 5176                         softc->bop = 1;
 5177                 else
 5178                         softc->bop = 0;
 5179 
 5180                 if (long_pos.flags & SA_RPOS_LONG_EOP)
 5181                         softc->eop = 1;
 5182                 else
 5183                         softc->eop = 0;
 5184 
 5185                 if ((long_pos.flags & SA_RPOS_LONG_BPEW)
 5186                  || (softc->set_pews_status != 0)) {
 5187                         softc->bpew = 1;
 5188                         if (softc->set_pews_status > 0)
 5189                                 softc->set_pews_status--;
 5190                 } else
 5191                         softc->bpew = 0;
 5192         } else if (error == EINVAL) {
 5193                 /*
 5194                  * If this drive returned an invalid-request type error,
 5195                  * then it likely doesn't support the long form report.
 5196                  */
 5197                 softc->quirks |= SA_QUIRK_NO_LONG_POS;
 5198         }
 5199 
 5200         if (error != 0) {
 5201                 softc->rep_fileno = softc->rep_blkno = (daddr_t) -1;
 5202                 softc->partition = (daddr_t) -1;
 5203                 softc->bop = softc->eop = softc->bpew = -1;
 5204         }
 5205 
 5206         xpt_release_ccb(ccb);
 5207 
 5208         return (error);
 5209 }
 5210 
 5211 static int
 5212 sardpos(struct cam_periph *periph, int hard, u_int32_t *blkptr)
 5213 {
 5214         struct scsi_tape_position_data loc;
 5215         union ccb *ccb;
 5216         struct sa_softc *softc = (struct sa_softc *)periph->softc;
 5217         int error;
 5218 
 5219         /*
 5220          * We try and flush any buffered writes here if we were writing
 5221          * and we're trying to get hardware block position. It eats
 5222          * up performance substantially, but I'm wary of drive firmware.
 5223          *
 5224          * I think that *logical* block position is probably okay-
 5225          * but hardware block position might have to wait for data
 5226          * to hit media to be valid. Caveat Emptor.
 5227          */
 5228 
 5229         if (hard && (softc->flags & SA_FLAG_TAPE_WRITTEN)) {
 5230                 error = sawritefilemarks(periph, 0, 0, 0);
 5231                 if (error && error != EACCES)
 5232                         return (error);
 5233         }
 5234 
 5235         ccb = cam_periph_getccb(periph, 1);
 5236         scsi_read_position(&ccb->csio, 1, NULL, MSG_SIMPLE_Q_TAG,
 5237             hard, &loc, SSD_FULL_SIZE,
 5238             softc->timeout_info[SA_TIMEOUT_READ_POSITION]);
 5239         softc->dsreg = MTIO_DSREG_RBSY;
 5240         error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
 5241         softc->dsreg = MTIO_DSREG_REST;
 5242 
 5243         if (error == 0) {
 5244                 if (loc.flags & SA_RPOS_UNCERTAIN) {
 5245                         error = EINVAL;         /* nothing is certain */
 5246                 } else {
 5247                         *blkptr = scsi_4btoul(loc.firstblk);
 5248                 }
 5249         }
 5250 
 5251         xpt_release_ccb(ccb);
 5252         return (error);
 5253 }
 5254 
 5255 static int
 5256 sasetpos(struct cam_periph *periph, int hard, struct mtlocate *locate_info)
 5257 {
 5258         union ccb *ccb;
 5259         struct sa_softc *softc;
 5260         int locate16;
 5261         int immed, cp;
 5262         int error;
 5263 
 5264         /*
 5265          * We used to try and flush any buffered writes here.
 5266          * Now we push this onto user applications to either
 5267          * flush the pending writes themselves (via a zero count
 5268          * WRITE FILEMARKS command) or they can trust their tape
 5269          * drive to do this correctly for them.
 5270          */
 5271 
 5272         softc = (struct sa_softc *)periph->softc;
 5273         ccb = cam_periph_getccb(periph, 1);
 5274 
 5275         cp = locate_info->flags & MT_LOCATE_FLAG_CHANGE_PART ? 1 : 0;
 5276         immed = locate_info->flags & MT_LOCATE_FLAG_IMMED ? 1 : 0;
 5277 
 5278         /*
 5279          * Determine whether we have to use LOCATE or LOCATE16.  The hard
 5280          * bit is only possible with LOCATE, but the new ioctls do not
 5281          * allow setting that bit.  So we can't get into the situation of
 5282          * having the hard bit set with a block address that is larger than
 5283          * 32-bits.
 5284          */
 5285         if (hard != 0)
 5286                 locate16 = 0;
 5287         else if ((locate_info->dest_type != MT_LOCATE_DEST_OBJECT)
 5288               || (locate_info->block_address_mode != MT_LOCATE_BAM_IMPLICIT)
 5289               || (locate_info->logical_id > SA_SPOS_MAX_BLK))
 5290                 locate16 = 1;
 5291         else
 5292                 locate16 = 0;
 5293 
 5294         if (locate16 != 0) {
 5295                 scsi_locate_16(&ccb->csio,
 5296                                /*retries*/ 1,
 5297                                /*cbfcnp*/ NULL,
 5298                                /*tag_action*/ MSG_SIMPLE_Q_TAG,
 5299                                /*immed*/ immed,
 5300                                /*cp*/ cp,
 5301                                /*dest_type*/ locate_info->dest_type,
 5302                                /*bam*/ locate_info->block_address_mode,
 5303                                /*partition*/ locate_info->partition,
 5304                                /*logical_id*/ locate_info->logical_id,
 5305                                /*sense_len*/ SSD_FULL_SIZE,
 5306                                /*timeout*/
 5307                                    softc->timeout_info[SA_TIMEOUT_LOCATE]);
 5308         } else {
 5309                 scsi_locate_10(&ccb->csio,
 5310                                /*retries*/ 1,
 5311                                /*cbfcnp*/ NULL,
 5312                                /*tag_action*/ MSG_SIMPLE_Q_TAG,
 5313                                /*immed*/ immed,
 5314                                /*cp*/ cp,
 5315                                /*hard*/ hard,
 5316                                /*partition*/ locate_info->partition,
 5317                                /*block_address*/ locate_info->logical_id,
 5318                                /*sense_len*/ SSD_FULL_SIZE,
 5319                                /*timeout*/
 5320                                    softc->timeout_info[SA_TIMEOUT_LOCATE]);
 5321         }
 5322 
 5323         softc->dsreg = MTIO_DSREG_POS;
 5324         error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
 5325         softc->dsreg = MTIO_DSREG_REST;
 5326         xpt_release_ccb(ccb);
 5327 
 5328         /*
 5329          * We assume the calculated file and block numbers are unknown
 5330          * unless we have enough information to populate them.
 5331          */
 5332         softc->fileno = softc->blkno = (daddr_t) -1;
 5333 
 5334         /*
 5335          * If the user requested changing the partition and the request
 5336          * succeeded, note the partition.
 5337          */
 5338         if ((error == 0)
 5339          && (cp != 0))
 5340                 softc->partition = locate_info->partition;
 5341         else
 5342                 softc->partition = (daddr_t) -1;
 5343 
 5344         if (error == 0) {
 5345                 switch (locate_info->dest_type) {
 5346                 case MT_LOCATE_DEST_FILE:
 5347                         /*
 5348                          * This is the only case where we can reliably
 5349                          * calculate the file and block numbers.
 5350                          */
 5351                         softc->fileno = locate_info->logical_id;
 5352                         softc->blkno = 0;
 5353                         break;
 5354                 case MT_LOCATE_DEST_OBJECT:
 5355                 case MT_LOCATE_DEST_SET:
 5356                 case MT_LOCATE_DEST_EOD:
 5357                 default:
 5358                         break;
 5359                 }
 5360         }
 5361 
 5362         /*
 5363          * Ask the drive for current position information.
 5364          */
 5365         sagetpos(periph);
 5366 
 5367         return (error);
 5368 }
 5369 
 5370 static int
 5371 saretension(struct cam_periph *periph)
 5372 {
 5373         union ccb *ccb;
 5374         struct sa_softc *softc;
 5375         int error;
 5376 
 5377         softc = (struct sa_softc *)periph->softc;
 5378 
 5379         ccb = cam_periph_getccb(periph, 1);
 5380 
 5381         /* It is safe to retry this operation */
 5382         scsi_load_unload(&ccb->csio, 5, NULL, MSG_SIMPLE_Q_TAG, FALSE,
 5383             FALSE, TRUE,  TRUE, SSD_FULL_SIZE,
 5384             softc->timeout_info[SA_TIMEOUT_LOAD]);
 5385 
 5386         softc->dsreg = MTIO_DSREG_TEN;
 5387         error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
 5388         softc->dsreg = MTIO_DSREG_REST;
 5389 
 5390         xpt_release_ccb(ccb);
 5391         if (error == 0) {
 5392                 softc->partition = softc->fileno = softc->blkno = (daddr_t) 0;
 5393                 sagetpos(periph);
 5394         } else
 5395                 softc->partition = softc->fileno = softc->blkno = (daddr_t) -1;
 5396         return (error);
 5397 }
 5398 
 5399 static int
 5400 sareservereleaseunit(struct cam_periph *periph, int reserve)
 5401 {
 5402         union ccb *ccb;
 5403         struct sa_softc *softc;
 5404         int error;
 5405 
 5406         softc = (struct sa_softc *)periph->softc;
 5407         ccb = cam_periph_getccb(periph,  1);
 5408 
 5409         /* It is safe to retry this operation */
 5410         scsi_reserve_release_unit(&ccb->csio, 2, NULL, MSG_SIMPLE_Q_TAG,
 5411             FALSE,  0, SSD_FULL_SIZE,  softc->timeout_info[SA_TIMEOUT_RESERVE],
 5412             reserve);
 5413         softc->dsreg = MTIO_DSREG_RBSY;
 5414         error = cam_periph_runccb(ccb, saerror, 0,
 5415             SF_RETRY_UA | SF_NO_PRINT, softc->device_stats);
 5416         softc->dsreg = MTIO_DSREG_REST;
 5417         xpt_release_ccb(ccb);
 5418 
 5419         /*
 5420          * If the error was Illegal Request, then the device doesn't support
 5421          * RESERVE/RELEASE. This is not an error.
 5422          */
 5423         if (error == EINVAL) {
 5424                 error = 0;
 5425         }
 5426 
 5427         return (error);
 5428 }
 5429 
 5430 static int
 5431 saloadunload(struct cam_periph *periph, int load)
 5432 {
 5433         union   ccb *ccb;
 5434         struct  sa_softc *softc;
 5435         int     error;
 5436 
 5437         softc = (struct sa_softc *)periph->softc;
 5438 
 5439         ccb = cam_periph_getccb(periph, 1);
 5440 
 5441         /* It is safe to retry this operation */
 5442         scsi_load_unload(&ccb->csio, 5, NULL, MSG_SIMPLE_Q_TAG, FALSE,
 5443             FALSE, FALSE, load, SSD_FULL_SIZE,
 5444             softc->timeout_info[SA_TIMEOUT_LOAD]);
 5445 
 5446         softc->dsreg = (load)? MTIO_DSREG_LD : MTIO_DSREG_UNL;
 5447         error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
 5448         softc->dsreg = MTIO_DSREG_REST;
 5449         xpt_release_ccb(ccb);
 5450 
 5451         if (error || load == 0) {
 5452                 softc->partition = softc->fileno = softc->blkno = (daddr_t) -1;
 5453                 softc->rep_fileno = softc->rep_blkno = (daddr_t) -1;
 5454         } else if (error == 0) {
 5455                 softc->partition = softc->fileno = softc->blkno = (daddr_t) 0;
 5456                 sagetpos(periph);
 5457         }
 5458         return (error);
 5459 }
 5460 
 5461 static int
 5462 saerase(struct cam_periph *periph, int longerase)
 5463 {
 5464 
 5465         union   ccb *ccb;
 5466         struct  sa_softc *softc;
 5467         int error;
 5468 
 5469         softc = (struct sa_softc *)periph->softc;
 5470         if (softc->open_rdonly)
 5471                 return (EBADF);
 5472 
 5473         ccb = cam_periph_getccb(periph, 1);
 5474 
 5475         scsi_erase(&ccb->csio, 1, NULL, MSG_SIMPLE_Q_TAG, FALSE, longerase,
 5476             SSD_FULL_SIZE, softc->timeout_info[SA_TIMEOUT_ERASE]);
 5477 
 5478         softc->dsreg = MTIO_DSREG_ZER;
 5479         error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
 5480         softc->dsreg = MTIO_DSREG_REST;
 5481 
 5482         xpt_release_ccb(ccb);
 5483         return (error);
 5484 }
 5485 
 5486 /*
 5487  * Fill an sbuf with density data in XML format.  This particular macro
 5488  * works for multi-byte integer fields.
 5489  *
 5490  * Note that 1 byte fields aren't supported here.  The reason is that the
 5491  * compiler does not evaluate the sizeof(), and assumes that any of the
 5492  * sizes are possible for a given field.  So passing in a multi-byte
 5493  * field will result in a warning that the assignment makes an integer
 5494  * from a pointer without a cast, if there is an assignment in the 1 byte
 5495  * case.
 5496  */
 5497 #define SAFILLDENSSB(dens_data, sb, indent, field, desc_remain,         \
 5498                      len_to_go, cur_offset, desc){                      \
 5499         size_t cur_field_len;                                           \
 5500                                                                         \
 5501         cur_field_len = sizeof(dens_data->field);                       \
 5502         if (desc_remain < cur_field_len) {                              \
 5503                 len_to_go -= desc_remain;                               \
 5504                 cur_offset += desc_remain;                              \
 5505                 continue;                                               \
 5506         }                                                               \
 5507         len_to_go -= cur_field_len;                                     \
 5508         cur_offset += cur_field_len;                                    \
 5509         desc_remain -= cur_field_len;                                   \
 5510                                                                         \
 5511         switch (sizeof(dens_data->field)) {                             \
 5512         case 1:                                                         \
 5513                 KASSERT(1 == 0, ("Programmer error, invalid 1 byte "    \
 5514                         "field width for SAFILLDENSFIELD"));            \
 5515                 break;                                                  \
 5516         case 2:                                                         \
 5517                 SASBADDUINTDESC(sb, indent,                             \
 5518                     scsi_2btoul(dens_data->field), %u, field, desc);    \
 5519                 break;                                                  \
 5520         case 3:                                                         \
 5521                 SASBADDUINTDESC(sb, indent,                             \
 5522                     scsi_3btoul(dens_data->field), %u, field, desc);    \
 5523                 break;                                                  \
 5524         case 4:                                                         \
 5525                 SASBADDUINTDESC(sb, indent,                             \
 5526                     scsi_4btoul(dens_data->field), %u, field, desc);    \
 5527                 break;                                                  \
 5528         case 8:                                                         \
 5529                 SASBADDUINTDESC(sb, indent,                             \
 5530                     (uintmax_t)scsi_8btou64(dens_data->field),  %ju,    \
 5531                     field, desc);                                       \
 5532                 break;                                                  \
 5533         default:                                                        \
 5534                 break;                                                  \
 5535         }                                                               \
 5536 };
 5537 /*
 5538  * Fill an sbuf with density data in XML format.  This particular macro
 5539  * works for strings.
 5540  */
 5541 #define SAFILLDENSSBSTR(dens_data, sb, indent, field, desc_remain,      \
 5542                         len_to_go, cur_offset, desc){                   \
 5543         size_t cur_field_len;                                           \
 5544         char tmpstr[32];                                                \
 5545                                                                         \
 5546         cur_field_len = sizeof(dens_data->field);                       \
 5547         if (desc_remain < cur_field_len) {                              \
 5548                 len_to_go -= desc_remain;                               \
 5549                 cur_offset += desc_remain;                              \
 5550                 continue;                                               \
 5551         }                                                               \
 5552         len_to_go -= cur_field_len;                                     \
 5553         cur_offset += cur_field_len;                                    \
 5554         desc_remain -= cur_field_len;                                   \
 5555                                                                         \
 5556         cam_strvis(tmpstr, dens_data->field,                            \
 5557             sizeof(dens_data->field), sizeof(tmpstr));                  \
 5558         SASBADDVARSTRDESC(sb, indent, tmpstr, %s, field,                \
 5559             strlen(tmpstr) + 1, desc);                                  \
 5560 };
 5561 
 5562 /*
 5563  * Fill an sbuf with density data descriptors.
 5564  */
 5565 static void
 5566 safilldenstypesb(struct sbuf *sb, int *indent, uint8_t *buf, int buf_len,
 5567     int is_density)
 5568 {
 5569         struct scsi_density_hdr *hdr;
 5570         uint32_t hdr_len;
 5571         int len_to_go, cur_offset;
 5572         int length_offset;
 5573         int num_reports, need_close;
 5574 
 5575         /*
 5576          * We need at least the header length.  Note that this isn't an
 5577          * error, not all tape drives will have every data type.
 5578          */
 5579         if (buf_len < sizeof(*hdr))
 5580                 goto bailout;
 5581 
 5582         hdr = (struct scsi_density_hdr *)buf;
 5583         hdr_len = scsi_2btoul(hdr->length);
 5584         len_to_go = min(buf_len - sizeof(*hdr), hdr_len);
 5585         if (is_density) {
 5586                 length_offset = __offsetof(struct scsi_density_data,
 5587                     bits_per_mm);
 5588         } else {
 5589                 length_offset = __offsetof(struct scsi_medium_type_data,
 5590                     num_density_codes);
 5591         }
 5592         cur_offset = sizeof(*hdr);
 5593 
 5594         num_reports = 0;
 5595         need_close = 0;
 5596 
 5597         while (len_to_go > length_offset) {
 5598                 struct scsi_density_data *dens_data;
 5599                 struct scsi_medium_type_data *type_data;
 5600                 int desc_remain;
 5601                 size_t cur_field_len;
 5602 
 5603                 dens_data = NULL;
 5604                 type_data = NULL;
 5605 
 5606                 if (is_density) {
 5607                         dens_data =(struct scsi_density_data *)&buf[cur_offset];
 5608                         if (dens_data->byte2 & SDD_DLV)
 5609                                 desc_remain = scsi_2btoul(dens_data->length);
 5610                         else
 5611                                 desc_remain = SDD_DEFAULT_LENGTH -
 5612                                     length_offset;
 5613                 } else {
 5614                         type_data = (struct scsi_medium_type_data *)
 5615                             &buf[cur_offset];
 5616                         desc_remain = scsi_2btoul(type_data->length);
 5617                 }
 5618 
 5619                 len_to_go -= length_offset;
 5620                 desc_remain = min(desc_remain, len_to_go);
 5621                 cur_offset += length_offset;
 5622 
 5623                 if (need_close != 0) {
 5624                         SASBENDNODE(sb, *indent, density_entry);
 5625                 }
 5626 
 5627                 SASBADDNODENUM(sb, *indent, density_entry, num_reports);
 5628                 num_reports++;
 5629                 need_close = 1;
 5630 
 5631                 if (is_density) {
 5632                         SASBADDUINTDESC(sb, *indent,
 5633                             dens_data->primary_density_code, %u,
 5634                             primary_density_code, "Primary Density Code");
 5635                         SASBADDUINTDESC(sb, *indent,
 5636                             dens_data->secondary_density_code, %u,
 5637                             secondary_density_code, "Secondary Density Code");
 5638                         SASBADDUINTDESC(sb, *indent,
 5639                             dens_data->byte2 & ~SDD_DLV, %#x, density_flags,
 5640                             "Density Flags");
 5641 
 5642                         SAFILLDENSSB(dens_data, sb, *indent, bits_per_mm,
 5643                             desc_remain, len_to_go, cur_offset, "Bits per mm");
 5644                         SAFILLDENSSB(dens_data, sb, *indent, media_width,
 5645                             desc_remain, len_to_go, cur_offset, "Media width");
 5646                         SAFILLDENSSB(dens_data, sb, *indent, tracks,
 5647                             desc_remain, len_to_go, cur_offset,
 5648                             "Number of Tracks");
 5649                         SAFILLDENSSB(dens_data, sb, *indent, capacity,
 5650                             desc_remain, len_to_go, cur_offset, "Capacity");
 5651 
 5652                         SAFILLDENSSBSTR(dens_data, sb, *indent, assigning_org,
 5653                             desc_remain, len_to_go, cur_offset,
 5654                             "Assigning Organization");
 5655 
 5656                         SAFILLDENSSBSTR(dens_data, sb, *indent, density_name,
 5657                             desc_remain, len_to_go, cur_offset, "Density Name");
 5658 
 5659                         SAFILLDENSSBSTR(dens_data, sb, *indent, description,
 5660                             desc_remain, len_to_go, cur_offset, "Description");
 5661                 } else {
 5662                         int i;
 5663 
 5664                         SASBADDUINTDESC(sb, *indent, type_data->medium_type,
 5665                             %u, medium_type, "Medium Type");
 5666 
 5667                         cur_field_len =
 5668                             __offsetof(struct scsi_medium_type_data,
 5669                                        media_width) -
 5670                             __offsetof(struct scsi_medium_type_data,
 5671                                        num_density_codes);
 5672 
 5673                         if (desc_remain < cur_field_len) {
 5674                                 len_to_go -= desc_remain;
 5675                                 cur_offset += desc_remain;
 5676                                 continue;
 5677                         }
 5678                         len_to_go -= cur_field_len;
 5679                         cur_offset += cur_field_len;
 5680                         desc_remain -= cur_field_len;
 5681 
 5682                         SASBADDINTDESC(sb, *indent,
 5683                             type_data->num_density_codes, %d,
 5684                             num_density_codes, "Number of Density Codes");
 5685                         SASBADDNODE(sb, *indent, density_code_list);
 5686                         for (i = 0; i < type_data->num_density_codes;
 5687                              i++) {
 5688                                 SASBADDUINTDESC(sb, *indent,
 5689                                     type_data->primary_density_codes[i], %u,
 5690                                     density_code, "Density Code");
 5691                         }
 5692                         SASBENDNODE(sb, *indent, density_code_list);
 5693 
 5694                         SAFILLDENSSB(type_data, sb, *indent, media_width,
 5695                             desc_remain, len_to_go, cur_offset,
 5696                             "Media width");
 5697                         SAFILLDENSSB(type_data, sb, *indent, medium_length,
 5698                             desc_remain, len_to_go, cur_offset,
 5699                             "Medium length");
 5700 
 5701                         /*
 5702                          * Account for the two reserved bytes.
 5703                          */
 5704                         cur_field_len = sizeof(type_data->reserved2);
 5705                         if (desc_remain < cur_field_len) {
 5706                                 len_to_go -= desc_remain;
 5707                                 cur_offset += desc_remain;
 5708                                 continue;
 5709                         }
 5710                         len_to_go -= cur_field_len;
 5711                         cur_offset += cur_field_len;
 5712                         desc_remain -= cur_field_len;
 5713                         
 5714                         SAFILLDENSSBSTR(type_data, sb, *indent, assigning_org,
 5715                             desc_remain, len_to_go, cur_offset,
 5716                             "Assigning Organization");
 5717                         SAFILLDENSSBSTR(type_data, sb, *indent,
 5718                             medium_type_name, desc_remain, len_to_go,
 5719                             cur_offset, "Medium type name");
 5720                         SAFILLDENSSBSTR(type_data, sb, *indent, description,
 5721                             desc_remain, len_to_go, cur_offset, "Description");
 5722                 }
 5723         }
 5724         if (need_close != 0) {
 5725                 SASBENDNODE(sb, *indent, density_entry);
 5726         }
 5727 
 5728 bailout:
 5729         return;
 5730 }
 5731 
 5732 /*
 5733  * Fill an sbuf with density data information
 5734  */
 5735 static void
 5736 safilldensitysb(struct sa_softc *softc, int *indent, struct sbuf *sb)
 5737 {
 5738         int i, is_density;
 5739 
 5740         SASBADDNODE(sb, *indent, mtdensity);
 5741         SASBADDUINTDESC(sb, *indent, softc->media_density, %u, media_density,
 5742             "Current Medium Density");
 5743         is_density = 0;
 5744         for (i = 0; i < SA_DENSITY_TYPES; i++) {
 5745                 int tmpint;
 5746 
 5747                 if (softc->density_info_valid[i] == 0)
 5748                         continue;
 5749 
 5750                 SASBADDNODE(sb, *indent, density_report);
 5751                 if (softc->density_type_bits[i] & SRDS_MEDIUM_TYPE) {
 5752                         tmpint = 1;
 5753                         is_density = 0;
 5754                 } else {
 5755                         tmpint = 0;
 5756                         is_density = 1;
 5757                 }
 5758                 SASBADDINTDESC(sb, *indent, tmpint, %d, medium_type_report,
 5759                     "Medium type report");
 5760 
 5761                 if (softc->density_type_bits[i] & SRDS_MEDIA)
 5762                         tmpint = 1;
 5763                 else
 5764                         tmpint = 0;
 5765                 SASBADDINTDESC(sb, *indent, tmpint, %d, media_report, 
 5766                     "Media report");
 5767 
 5768                 safilldenstypesb(sb, indent, softc->density_info[i],
 5769                     softc->density_info_valid[i], is_density);
 5770                 SASBENDNODE(sb, *indent, density_report);
 5771         }
 5772         SASBENDNODE(sb, *indent, mtdensity);
 5773 }
 5774 
 5775 /*
 5776  * Given a completed REPORT SUPPORTED OPERATION CODES command with timeout
 5777  * descriptors, go through the descriptors and set the sa(4) driver
 5778  * timeouts to the recommended values.
 5779  */
 5780 static void
 5781 saloadtimeouts(struct sa_softc *softc, union ccb *ccb)
 5782 {
 5783         uint32_t valid_len, avail_len = 0, used_len = 0;
 5784         struct scsi_report_supported_opcodes_all *hdr;
 5785         struct scsi_report_supported_opcodes_descr *desc;
 5786         uint8_t *buf;
 5787 
 5788         hdr = (struct scsi_report_supported_opcodes_all *)ccb->csio.data_ptr;
 5789         valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
 5790 
 5791         if (valid_len < sizeof(*hdr))
 5792                 return;
 5793 
 5794         avail_len = scsi_4btoul(hdr->length) + sizeof(hdr->length);
 5795         if ((avail_len != 0)
 5796          && (avail_len > valid_len)) {
 5797                 xpt_print(softc->periph->path, "WARNING: available timeout "
 5798                     "descriptor len %zu > valid len %u\n", avail_len,valid_len);
 5799         }
 5800 
 5801         used_len = sizeof(hdr->length);
 5802         avail_len = MIN(avail_len, valid_len - sizeof(*hdr));
 5803         buf = ccb->csio.data_ptr;
 5804         while ((avail_len - used_len) > sizeof(*desc)) {
 5805                 struct scsi_report_supported_opcodes_timeout *td;
 5806                 uint32_t td_len;
 5807                 uint32_t rec_time;
 5808                 uint8_t *cur_ptr;
 5809 
 5810                 cur_ptr = &buf[used_len];
 5811                 desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
 5812 
 5813                 used_len += sizeof(*desc);
 5814                 /* If there's no timeout descriptor, keep going */
 5815                 if ((desc->flags & RSO_CTDP) == 0)
 5816                         continue;
 5817 
 5818                 /*
 5819                  * If we don't have enough space to fit a timeout
 5820                  * descriptor then we're done.
 5821                  */
 5822                 if ((avail_len - used_len) < sizeof(*td)) {
 5823                         used_len = avail_len;
 5824                         continue;
 5825                 }
 5826 
 5827                 cur_ptr = &buf[used_len];
 5828                 td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
 5829                 td_len = scsi_2btoul(td->length);
 5830                 td_len += sizeof(td->length);
 5831                 used_len += td_len;
 5832 
 5833                 if (td_len < sizeof(*td))
 5834                         continue;
 5835 
 5836                 /*
 5837                  * Use the recommended timeout.  The nominal time is the
 5838                  * time to wait before querying for status.
 5839                  */
 5840                 rec_time = scsi_4btoul(td->recommended_time);
 5841 
 5842                 /*
 5843                  * Our timeouts are set in thousandths of a seconds.
 5844                  */
 5845                 rec_time *= 1000;
 5846 
 5847                 switch(desc->opcode) {
 5848                 case ERASE:
 5849                         softc->timeout_info[SA_TIMEOUT_ERASE] = rec_time;
 5850                         break;
 5851                 case LOAD_UNLOAD:
 5852                         softc->timeout_info[SA_TIMEOUT_LOAD] = rec_time;
 5853                         break;
 5854                 case LOCATE:
 5855                 case LOCATE_16:
 5856                         /*
 5857                          * We are assuming these are the same timeout.
 5858                          */
 5859                         softc->timeout_info[SA_TIMEOUT_LOCATE] = rec_time;
 5860                         break;
 5861                 case MODE_SELECT_6:
 5862                 case MODE_SELECT_10:
 5863                         /*
 5864                          * We are assuming these are the same timeout.
 5865                          */
 5866                         softc->timeout_info[SA_TIMEOUT_MODE_SELECT] = rec_time;
 5867                         break;
 5868                 case MODE_SENSE_6:
 5869                 case MODE_SENSE_10:
 5870                         /*
 5871                          * We are assuming these are the same timeout.
 5872                          */
 5873                         softc->timeout_info[SA_TIMEOUT_MODE_SENSE] = rec_time;
 5874                         break;
 5875                 case PREVENT_ALLOW:
 5876                         softc->timeout_info[SA_TIMEOUT_PREVENT] = rec_time;
 5877                         break;
 5878                 case SA_READ:
 5879                         softc->timeout_info[SA_TIMEOUT_READ] = rec_time;
 5880                         break;
 5881                 case READ_BLOCK_LIMITS:
 5882                         softc->timeout_info[SA_TIMEOUT_READ_BLOCK_LIMITS] =
 5883                             rec_time;
 5884                         break;
 5885                 case READ_POSITION:
 5886                         /*
 5887                          * Note that this may show up multiple times for
 5888                          * the short form, long form and extended form
 5889                          * service actions.  We're assuming they are all
 5890                          * the same.
 5891                          */
 5892                         softc->timeout_info[SA_TIMEOUT_READ_POSITION] =rec_time;
 5893                         break;
 5894                 case REPORT_DENSITY_SUPPORT:
 5895                         softc->timeout_info[SA_TIMEOUT_REP_DENSITY] = rec_time;
 5896                         break;
 5897                 case RESERVE_UNIT:
 5898                 case RELEASE_UNIT:
 5899                         /* We are assuming these are the same timeout.*/
 5900                         softc->timeout_info[SA_TIMEOUT_RESERVE] = rec_time;
 5901                         break;
 5902                 case REWIND:
 5903                         softc->timeout_info[SA_TIMEOUT_REWIND] = rec_time;
 5904                         break;
 5905                 case SPACE:
 5906                         softc->timeout_info[SA_TIMEOUT_SPACE] = rec_time;
 5907                         break;
 5908                 case TEST_UNIT_READY:
 5909                         softc->timeout_info[SA_TIMEOUT_TUR] = rec_time;
 5910                         break;
 5911                 case SA_WRITE:
 5912                         softc->timeout_info[SA_TIMEOUT_WRITE] = rec_time;
 5913                         break;
 5914                 case WRITE_FILEMARKS:
 5915                         softc->timeout_info[SA_TIMEOUT_WRITE_FILEMARKS] =
 5916                             rec_time;
 5917                         break;
 5918                 default:
 5919                         /*
 5920                          * We have explicit cases for all of the timeouts
 5921                          * we use.
 5922                          */
 5923                         break;
 5924                 }
 5925         }
 5926 }
 5927 
 5928 #endif /* _KERNEL */
 5929 
 5930 /*
 5931  * Read tape block limits command.
 5932  */
 5933 void
 5934 scsi_read_block_limits(struct ccb_scsiio *csio, u_int32_t retries,
 5935                    void (*cbfcnp)(struct cam_periph *, union ccb *),
 5936                    u_int8_t tag_action,
 5937                    struct scsi_read_block_limits_data *rlimit_buf,
 5938                    u_int8_t sense_len, u_int32_t timeout)
 5939 {
 5940         struct scsi_read_block_limits *scsi_cmd;
 5941 
 5942         cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action,
 5943              (u_int8_t *)rlimit_buf, sizeof(*rlimit_buf), sense_len,
 5944              sizeof(*scsi_cmd), timeout);
 5945 
 5946         scsi_cmd = (struct scsi_read_block_limits *)&csio->cdb_io.cdb_bytes;
 5947         bzero(scsi_cmd, sizeof(*scsi_cmd));
 5948         scsi_cmd->opcode = READ_BLOCK_LIMITS;
 5949 }
 5950 
 5951 void
 5952 scsi_sa_read_write(struct ccb_scsiio *csio, u_int32_t retries,
 5953                    void (*cbfcnp)(struct cam_periph *, union ccb *),
 5954                    u_int8_t tag_action, int readop, int sli,
 5955                    int fixed, u_int32_t length, u_int8_t *data_ptr,
 5956                    u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout)
 5957 {
 5958         struct scsi_sa_rw *scsi_cmd;
 5959         int read;
 5960 
 5961         read = (readop & SCSI_RW_DIRMASK) == SCSI_RW_READ;
 5962 
 5963         scsi_cmd = (struct scsi_sa_rw *)&csio->cdb_io.cdb_bytes;
 5964         scsi_cmd->opcode = read ? SA_READ : SA_WRITE;
 5965         scsi_cmd->sli_fixed = 0;
 5966         if (sli && read)
 5967                 scsi_cmd->sli_fixed |= SAR_SLI;
 5968         if (fixed)
 5969                 scsi_cmd->sli_fixed |= SARW_FIXED;
 5970         scsi_ulto3b(length, scsi_cmd->length);
 5971         scsi_cmd->control = 0;
 5972 
 5973         cam_fill_csio(csio, retries, cbfcnp, (read ? CAM_DIR_IN : CAM_DIR_OUT) |
 5974             ((readop & SCSI_RW_BIO) != 0 ? CAM_DATA_BIO : 0),
 5975             tag_action, data_ptr, dxfer_len, sense_len,
 5976             sizeof(*scsi_cmd), timeout);
 5977 }
 5978 
 5979 void
 5980 scsi_load_unload(struct ccb_scsiio *csio, u_int32_t retries,         
 5981                  void (*cbfcnp)(struct cam_periph *, union ccb *),   
 5982                  u_int8_t tag_action, int immediate, int eot,
 5983                  int reten, int load, u_int8_t sense_len,
 5984                  u_int32_t timeout)
 5985 {
 5986         struct scsi_load_unload *scsi_cmd;
 5987 
 5988         scsi_cmd = (struct scsi_load_unload *)&csio->cdb_io.cdb_bytes;
 5989         bzero(scsi_cmd, sizeof(*scsi_cmd));
 5990         scsi_cmd->opcode = LOAD_UNLOAD;
 5991         if (immediate)
 5992                 scsi_cmd->immediate = SLU_IMMED;
 5993         if (eot)
 5994                 scsi_cmd->eot_reten_load |= SLU_EOT;
 5995         if (reten)
 5996                 scsi_cmd->eot_reten_load |= SLU_RETEN;
 5997         if (load)
 5998                 scsi_cmd->eot_reten_load |= SLU_LOAD;
 5999 
 6000         cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action,
 6001             NULL, 0, sense_len, sizeof(*scsi_cmd), timeout);    
 6002 }
 6003 
 6004 void
 6005 scsi_rewind(struct ccb_scsiio *csio, u_int32_t retries,         
 6006             void (*cbfcnp)(struct cam_periph *, union ccb *),   
 6007             u_int8_t tag_action, int immediate, u_int8_t sense_len,     
 6008             u_int32_t timeout)
 6009 {
 6010         struct scsi_rewind *scsi_cmd;
 6011 
 6012         scsi_cmd = (struct scsi_rewind *)&csio->cdb_io.cdb_bytes;
 6013         bzero(scsi_cmd, sizeof(*scsi_cmd));
 6014         scsi_cmd->opcode = REWIND;
 6015         if (immediate)
 6016                 scsi_cmd->immediate = SREW_IMMED;
 6017 
 6018         cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
 6019             0, sense_len, sizeof(*scsi_cmd), timeout);
 6020 }
 6021 
 6022 void
 6023 scsi_space(struct ccb_scsiio *csio, u_int32_t retries,
 6024            void (*cbfcnp)(struct cam_periph *, union ccb *),
 6025            u_int8_t tag_action, scsi_space_code code,
 6026            u_int32_t count, u_int8_t sense_len, u_int32_t timeout)
 6027 {
 6028         struct scsi_space *scsi_cmd;
 6029 
 6030         scsi_cmd = (struct scsi_space *)&csio->cdb_io.cdb_bytes;
 6031         scsi_cmd->opcode = SPACE;
 6032         scsi_cmd->code = code;
 6033         scsi_ulto3b(count, scsi_cmd->count);
 6034         scsi_cmd->control = 0;
 6035 
 6036         cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
 6037             0, sense_len, sizeof(*scsi_cmd), timeout);
 6038 }
 6039 
 6040 void
 6041 scsi_write_filemarks(struct ccb_scsiio *csio, u_int32_t retries,
 6042                      void (*cbfcnp)(struct cam_periph *, union ccb *),
 6043                      u_int8_t tag_action, int immediate, int setmark,
 6044                      u_int32_t num_marks, u_int8_t sense_len,
 6045                      u_int32_t timeout)
 6046 {
 6047         struct scsi_write_filemarks *scsi_cmd;
 6048 
 6049         scsi_cmd = (struct scsi_write_filemarks *)&csio->cdb_io.cdb_bytes;
 6050         bzero(scsi_cmd, sizeof(*scsi_cmd));
 6051         scsi_cmd->opcode = WRITE_FILEMARKS;
 6052         if (immediate)
 6053                 scsi_cmd->byte2 |= SWFMRK_IMMED;
 6054         if (setmark)
 6055                 scsi_cmd->byte2 |= SWFMRK_WSMK;
 6056 
 6057         scsi_ulto3b(num_marks, scsi_cmd->num_marks);
 6058 
 6059         cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
 6060             0, sense_len, sizeof(*scsi_cmd), timeout);
 6061 }
 6062 
 6063 /*
 6064  * The reserve and release unit commands differ only by their opcodes.
 6065  */
 6066 void
 6067 scsi_reserve_release_unit(struct ccb_scsiio *csio, u_int32_t retries,
 6068                           void (*cbfcnp)(struct cam_periph *, union ccb *),
 6069                           u_int8_t tag_action, int third_party,
 6070                           int third_party_id, u_int8_t sense_len,
 6071                           u_int32_t timeout, int reserve)
 6072 {
 6073         struct scsi_reserve_release_unit *scsi_cmd;
 6074 
 6075         scsi_cmd = (struct scsi_reserve_release_unit *)&csio->cdb_io.cdb_bytes;
 6076         bzero(scsi_cmd, sizeof(*scsi_cmd));
 6077 
 6078         if (reserve)
 6079                 scsi_cmd->opcode = RESERVE_UNIT;
 6080         else
 6081                 scsi_cmd->opcode = RELEASE_UNIT;
 6082 
 6083         if (third_party) {
 6084                 scsi_cmd->lun_thirdparty |= SRRU_3RD_PARTY;
 6085                 scsi_cmd->lun_thirdparty |=
 6086                         ((third_party_id << SRRU_3RD_SHAMT) & SRRU_3RD_MASK);
 6087         }
 6088 
 6089         cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
 6090             0, sense_len, sizeof(*scsi_cmd), timeout);
 6091 }
 6092 
 6093 void
 6094 scsi_erase(struct ccb_scsiio *csio, u_int32_t retries,
 6095            void (*cbfcnp)(struct cam_periph *, union ccb *),
 6096            u_int8_t tag_action, int immediate, int long_erase,
 6097            u_int8_t sense_len, u_int32_t timeout)
 6098 {
 6099         struct scsi_erase *scsi_cmd;
 6100 
 6101         scsi_cmd = (struct scsi_erase *)&csio->cdb_io.cdb_bytes;
 6102         bzero(scsi_cmd, sizeof(*scsi_cmd));
 6103 
 6104         scsi_cmd->opcode = ERASE;
 6105 
 6106         if (immediate)
 6107                 scsi_cmd->lun_imm_long |= SE_IMMED;
 6108 
 6109         if (long_erase)
 6110                 scsi_cmd->lun_imm_long |= SE_LONG;
 6111 
 6112         cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
 6113             0, sense_len, sizeof(*scsi_cmd), timeout);
 6114 }
 6115 
 6116 /*
 6117  * Read Tape Position command.
 6118  */
 6119 void
 6120 scsi_read_position(struct ccb_scsiio *csio, u_int32_t retries,
 6121                    void (*cbfcnp)(struct cam_periph *, union ccb *),
 6122                    u_int8_t tag_action, int hardsoft,
 6123                    struct scsi_tape_position_data *sbp,
 6124                    u_int8_t sense_len, u_int32_t timeout)
 6125 {
 6126         struct scsi_tape_read_position *scmd;
 6127 
 6128         cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action,
 6129             (u_int8_t *)sbp, sizeof (*sbp), sense_len, sizeof(*scmd), timeout);
 6130         scmd = (struct scsi_tape_read_position *)&csio->cdb_io.cdb_bytes;
 6131         bzero(scmd, sizeof(*scmd));
 6132         scmd->opcode = READ_POSITION;
 6133         scmd->byte1 = hardsoft;
 6134 }
 6135 
 6136 /*
 6137  * Read Tape Position command.
 6138  */
 6139 void
 6140 scsi_read_position_10(struct ccb_scsiio *csio, u_int32_t retries,
 6141                       void (*cbfcnp)(struct cam_periph *, union ccb *),
 6142                       u_int8_t tag_action, int service_action,
 6143                       u_int8_t *data_ptr, u_int32_t length,
 6144                       u_int32_t sense_len, u_int32_t timeout)
 6145 {
 6146         struct scsi_tape_read_position *scmd;
 6147 
 6148         cam_fill_csio(csio,
 6149                       retries,
 6150                       cbfcnp,
 6151                       /*flags*/CAM_DIR_IN,
 6152                       tag_action,
 6153                       /*data_ptr*/data_ptr,
 6154                       /*dxfer_len*/length,
 6155                       sense_len,
 6156                       sizeof(*scmd),
 6157                       timeout);
 6158 
 6159         scmd = (struct scsi_tape_read_position *)&csio->cdb_io.cdb_bytes;
 6160         bzero(scmd, sizeof(*scmd));
 6161         scmd->opcode = READ_POSITION;
 6162         scmd->byte1 = service_action;
 6163         /*
 6164          * The length is only currently set (as of SSC4r03) if the extended
 6165          * form is specified.  The other forms have fixed lengths.
 6166          */
 6167         if (service_action == SA_RPOS_EXTENDED_FORM)
 6168                 scsi_ulto2b(length, scmd->length);
 6169 }
 6170 
 6171 /*
 6172  * Set Tape Position command.
 6173  */
 6174 void
 6175 scsi_set_position(struct ccb_scsiio *csio, u_int32_t retries,
 6176                    void (*cbfcnp)(struct cam_periph *, union ccb *),
 6177                    u_int8_t tag_action, int hardsoft, u_int32_t blkno,
 6178                    u_int8_t sense_len, u_int32_t timeout)
 6179 {
 6180         struct scsi_tape_locate *scmd;
 6181 
 6182         cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action,
 6183             (u_int8_t *)NULL, 0, sense_len, sizeof(*scmd), timeout);
 6184         scmd = (struct scsi_tape_locate *)&csio->cdb_io.cdb_bytes;
 6185         bzero(scmd, sizeof(*scmd));
 6186         scmd->opcode = LOCATE;
 6187         if (hardsoft)
 6188                 scmd->byte1 |= SA_SPOS_BT;
 6189         scsi_ulto4b(blkno, scmd->blkaddr);
 6190 }
 6191 
 6192 /*
 6193  * XXX KDM figure out how to make a compatibility function.
 6194  */
 6195 void
 6196 scsi_locate_10(struct ccb_scsiio *csio, u_int32_t retries,
 6197                void (*cbfcnp)(struct cam_periph *, union ccb *),
 6198                u_int8_t tag_action, int immed, int cp, int hard,
 6199                int64_t partition, u_int32_t block_address,
 6200                int sense_len, u_int32_t timeout)
 6201 {
 6202         struct scsi_tape_locate *scmd;
 6203 
 6204         cam_fill_csio(csio,
 6205                       retries,
 6206                       cbfcnp,
 6207                       CAM_DIR_NONE,
 6208                       tag_action,
 6209                       /*data_ptr*/ NULL,
 6210                       /*dxfer_len*/ 0,
 6211                       sense_len,
 6212                       sizeof(*scmd),
 6213                       timeout);
 6214         scmd = (struct scsi_tape_locate *)&csio->cdb_io.cdb_bytes;
 6215         bzero(scmd, sizeof(*scmd));
 6216         scmd->opcode = LOCATE;
 6217         if (immed)
 6218                 scmd->byte1 |= SA_SPOS_IMMED;
 6219         if (cp)
 6220                 scmd->byte1 |= SA_SPOS_CP;
 6221         if (hard)
 6222                 scmd->byte1 |= SA_SPOS_BT;
 6223         scsi_ulto4b(block_address, scmd->blkaddr);
 6224         scmd->partition = partition;
 6225 }
 6226 
 6227 void
 6228 scsi_locate_16(struct ccb_scsiio *csio, u_int32_t retries,
 6229                void (*cbfcnp)(struct cam_periph *, union ccb *),
 6230                u_int8_t tag_action, int immed, int cp, u_int8_t dest_type,
 6231                int bam, int64_t partition, u_int64_t logical_id,
 6232                int sense_len, u_int32_t timeout)
 6233 {
 6234 
 6235         struct scsi_locate_16 *scsi_cmd;
 6236 
 6237         cam_fill_csio(csio,
 6238                       retries,
 6239                       cbfcnp,
 6240                       /*flags*/CAM_DIR_NONE,
 6241                       tag_action,
 6242                       /*data_ptr*/NULL,
 6243                       /*dxfer_len*/0,
 6244                       sense_len,
 6245                       sizeof(*scsi_cmd),
 6246                       timeout);
 6247 
 6248         scsi_cmd = (struct scsi_locate_16 *)&csio->cdb_io.cdb_bytes;
 6249         bzero(scsi_cmd, sizeof(*scsi_cmd));
 6250         scsi_cmd->opcode = LOCATE_16;
 6251         if (immed)
 6252                 scsi_cmd->byte1 |= SA_LC_IMMEDIATE;
 6253         if (cp)
 6254                 scsi_cmd->byte1 |= SA_LC_CP;
 6255         scsi_cmd->byte1 |= (dest_type << SA_LC_DEST_TYPE_SHIFT);
 6256 
 6257         scsi_cmd->byte2 |= bam;
 6258         scsi_cmd->partition = partition;
 6259         scsi_u64to8b(logical_id, scsi_cmd->logical_id);
 6260 }
 6261 
 6262 void
 6263 scsi_report_density_support(struct ccb_scsiio *csio, u_int32_t retries,
 6264                             void (*cbfcnp)(struct cam_periph *, union ccb *),
 6265                             u_int8_t tag_action, int media, int medium_type,
 6266                             u_int8_t *data_ptr, u_int32_t length,
 6267                             u_int32_t sense_len, u_int32_t timeout)
 6268 {
 6269         struct scsi_report_density_support *scsi_cmd;
 6270 
 6271         scsi_cmd =(struct scsi_report_density_support *)&csio->cdb_io.cdb_bytes;
 6272         bzero(scsi_cmd, sizeof(*scsi_cmd));
 6273 
 6274         scsi_cmd->opcode = REPORT_DENSITY_SUPPORT;
 6275         if (media != 0)
 6276                 scsi_cmd->byte1 |= SRDS_MEDIA;
 6277         if (medium_type != 0)
 6278                 scsi_cmd->byte1 |= SRDS_MEDIUM_TYPE;
 6279 
 6280         scsi_ulto2b(length, scsi_cmd->length);
 6281 
 6282         cam_fill_csio(csio,
 6283                       retries,
 6284                       cbfcnp,
 6285                       /*flags*/CAM_DIR_IN,
 6286                       tag_action,
 6287                       /*data_ptr*/data_ptr,
 6288                       /*dxfer_len*/length,
 6289                       sense_len,
 6290                       sizeof(*scsi_cmd),
 6291                       timeout);
 6292 }
 6293 
 6294 void
 6295 scsi_set_capacity(struct ccb_scsiio *csio, u_int32_t retries,
 6296                   void (*cbfcnp)(struct cam_periph *, union ccb *),
 6297                   u_int8_t tag_action, int byte1, u_int32_t proportion,
 6298                   u_int32_t sense_len, u_int32_t timeout)
 6299 {
 6300         struct scsi_set_capacity *scsi_cmd;
 6301 
 6302         scsi_cmd = (struct scsi_set_capacity *)&csio->cdb_io.cdb_bytes;
 6303         bzero(scsi_cmd, sizeof(*scsi_cmd));
 6304 
 6305         scsi_cmd->opcode = SET_CAPACITY;
 6306 
 6307         scsi_cmd->byte1 = byte1;
 6308         scsi_ulto2b(proportion, scsi_cmd->cap_proportion);
 6309 
 6310         cam_fill_csio(csio,
 6311                       retries,
 6312                       cbfcnp,
 6313                       /*flags*/CAM_DIR_NONE,
 6314                       tag_action,
 6315                       /*data_ptr*/NULL,
 6316                       /*dxfer_len*/0,
 6317                       sense_len,
 6318                       sizeof(*scsi_cmd),
 6319                       timeout);
 6320 }
 6321 
 6322 void
 6323 scsi_format_medium(struct ccb_scsiio *csio, u_int32_t retries,
 6324                    void (*cbfcnp)(struct cam_periph *, union ccb *),
 6325                    u_int8_t tag_action, int byte1, int byte2, 
 6326                    u_int8_t *data_ptr, u_int32_t dxfer_len,
 6327                    u_int32_t sense_len, u_int32_t timeout)
 6328 {
 6329         struct scsi_format_medium *scsi_cmd;
 6330 
 6331         scsi_cmd = (struct scsi_format_medium*)&csio->cdb_io.cdb_bytes;
 6332         bzero(scsi_cmd, sizeof(*scsi_cmd));
 6333 
 6334         scsi_cmd->opcode = FORMAT_MEDIUM;
 6335 
 6336         scsi_cmd->byte1 = byte1;
 6337         scsi_cmd->byte2 = byte2;
 6338 
 6339         scsi_ulto2b(dxfer_len, scsi_cmd->length);
 6340 
 6341         cam_fill_csio(csio,
 6342                       retries,
 6343                       cbfcnp,
 6344                       /*flags*/(dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE,
 6345                       tag_action,
 6346                       /*data_ptr*/ data_ptr,
 6347                       /*dxfer_len*/ dxfer_len,
 6348                       sense_len,
 6349                       sizeof(*scsi_cmd),
 6350                       timeout);
 6351 }
 6352 
 6353 void
 6354 scsi_allow_overwrite(struct ccb_scsiio *csio, u_int32_t retries,
 6355                    void (*cbfcnp)(struct cam_periph *, union ccb *),
 6356                    u_int8_t tag_action, int allow_overwrite, int partition, 
 6357                    u_int64_t logical_id, u_int32_t sense_len, u_int32_t timeout)
 6358 {
 6359         struct scsi_allow_overwrite *scsi_cmd;
 6360 
 6361         scsi_cmd = (struct scsi_allow_overwrite *)&csio->cdb_io.cdb_bytes;
 6362         bzero(scsi_cmd, sizeof(*scsi_cmd));
 6363 
 6364         scsi_cmd->opcode = ALLOW_OVERWRITE;
 6365 
 6366         scsi_cmd->allow_overwrite = allow_overwrite;
 6367         scsi_cmd->partition = partition;
 6368         scsi_u64to8b(logical_id, scsi_cmd->logical_id);
 6369 
 6370         cam_fill_csio(csio,
 6371                       retries,
 6372                       cbfcnp,
 6373                       CAM_DIR_NONE,
 6374                       tag_action,
 6375                       /*data_ptr*/ NULL,
 6376                       /*dxfer_len*/ 0,
 6377                       sense_len,
 6378                       sizeof(*scsi_cmd),
 6379                       timeout);
 6380 }

Cache object: 32777d38d8f6777a3efef1756fa86059


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.