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