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