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