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