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