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