xref: /dragonfly/sys/bus/cam/scsi/scsi_sa.c (revision 857fcb57d0e5e7f20e3d0ef58163c718377e363e)
1 /*
2  * $FreeBSD: src/sys/cam/scsi/scsi_sa.c,v 1.45.2.13 2002/12/17 17:08:50 trhodes Exp $
3  *
4  * Implementation of SCSI Sequential Access Peripheral driver for CAM.
5  *
6  * Copyright (c) 1999, 2000 Matthew Jacob
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions, and the following disclaimer,
14  *    without modification, immediately at the beginning of the file.
15  * 2. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
22  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  *
30  */
31 
32 #include <sys/param.h>
33 #include <sys/queue.h>
34 #ifdef _KERNEL
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #endif
38 #include <sys/types.h>
39 #ifdef _KERNEL
40 #include <sys/buf.h>
41 #include <sys/malloc.h>
42 #endif
43 #include <sys/mtio.h>
44 #include <sys/conf.h>
45 #ifdef _KERNEL
46 #include <sys/proc.h>
47 #include <sys/buf2.h>
48 #endif
49 #include <sys/caps.h>
50 #include <sys/fcntl.h>
51 #include <sys/devicestat.h>
52 #include <machine/limits.h>
53 
54 #ifndef _KERNEL
55 #include <stdio.h>
56 #include <string.h>
57 #endif
58 
59 #include "../cam.h"
60 #include "../cam_ccb.h"
61 #include "../cam_extend.h"
62 #include "../cam_periph.h"
63 #include "../cam_xpt_periph.h"
64 #include "../cam_debug.h"
65 
66 #include "scsi_all.h"
67 #include "scsi_message.h"
68 #include "scsi_sa.h"
69 
70 #ifdef _KERNEL
71 
72 #include <opt_sa.h>
73 
74 #ifndef SA_IO_TIMEOUT
75 #define SA_IO_TIMEOUT                   4
76 #endif
77 #ifndef SA_SPACE_TIMEOUT
78 #define SA_SPACE_TIMEOUT      1 * 60
79 #endif
80 #ifndef SA_REWIND_TIMEOUT
81 #define SA_REWIND_TIMEOUT     2 * 60
82 #endif
83 #ifndef SA_ERASE_TIMEOUT
84 #define SA_ERASE_TIMEOUT      4 * 60
85 #endif
86 
87 #define   SCSIOP_TIMEOUT                (60 * 1000)         /* not an option */
88 
89 #define   IO_TIMEOUT                    (SA_IO_TIMEOUT * 60 * 1000)
90 #define   REWIND_TIMEOUT                (SA_REWIND_TIMEOUT * 60 * 1000)
91 #define   ERASE_TIMEOUT                 (SA_ERASE_TIMEOUT * 60 * 1000)
92 #define   SPACE_TIMEOUT                 (SA_SPACE_TIMEOUT * 60 * 1000)
93 
94 /*
95  * Additional options that can be set for config: SA_1FM_AT_EOT
96  */
97 
98 #define   QFRLS(ccb)          \
99           if (((ccb)->ccb_h.status & CAM_DEV_QFRZN) != 0)   \
100                     cam_release_devq((ccb)->ccb_h.path, 0, 0, 0, FALSE)
101 
102 /*
103  * Driver states
104  */
105 
106 MALLOC_DEFINE(M_SCSISA, "SCSI sa", "SCSI sequential access buffers");
107 
108 typedef enum {
109           SA_STATE_NORMAL, SA_STATE_ABNORMAL
110 } sa_state;
111 
112 #define ccb_pflags  ppriv_field0
113 #define ccb_bio               ppriv_ptr1
114 
115 #define   SA_CCB_POLLED                 0x00
116 #define   SA_CCB_BUFFER_IO    0x01
117 #define   SA_CCB_WAITING                0x02
118 #define   SA_CCB_TYPEMASK               0x0F
119 #define   SA_POSITION_UPDATED 0x10
120 
121 #define   Set_CCB_Type(x, type) do {                        \
122           x->ccb_h.ccb_pflags &= ~SA_CCB_TYPEMASK;          \
123           x->ccb_h.ccb_pflags |= type;                      \
124     } while (0)
125 
126 #define   CCB_Type(x)         (x->ccb_h.ccb_pflags & SA_CCB_TYPEMASK)
127 
128 
129 
130 typedef enum {
131           SA_FLAG_OPEN                  = 0x0001,
132           SA_FLAG_FIXED                 = 0x0002,
133           SA_FLAG_TAPE_LOCKED = 0x0004,
134           SA_FLAG_TAPE_MOUNTED          = 0x0008,
135           SA_FLAG_TAPE_WP               = 0x0010,
136           SA_FLAG_TAPE_WRITTEN          = 0x0020,
137           SA_FLAG_EOM_PENDING = 0x0040,
138           SA_FLAG_EIO_PENDING = 0x0080,
139           SA_FLAG_EOF_PENDING = 0x0100,
140           SA_FLAG_ERR_PENDING = (SA_FLAG_EOM_PENDING|SA_FLAG_EIO_PENDING|
141                                            SA_FLAG_EOF_PENDING),
142           SA_FLAG_INVALID               = 0x0200,
143           SA_FLAG_COMP_ENABLED          = 0x0400,
144           SA_FLAG_COMP_SUPP   = 0x0800,
145           SA_FLAG_COMP_UNSUPP = 0x1000,
146           SA_FLAG_TAPE_FROZEN = 0x2000
147 } sa_flags;
148 
149 typedef enum {
150           SA_MODE_REWIND                = 0x00,
151           SA_MODE_NOREWIND    = 0x01,
152           SA_MODE_OFFLINE               = 0x02
153 } sa_mode;
154 
155 typedef enum {
156           SA_PARAM_NONE                 = 0x00,
157           SA_PARAM_BLOCKSIZE  = 0x01,
158           SA_PARAM_DENSITY    = 0x02,
159           SA_PARAM_COMPRESSION          = 0x04,
160           SA_PARAM_BUFF_MODE  = 0x08,
161           SA_PARAM_NUMBLOCKS  = 0x10,
162           SA_PARAM_WP                   = 0x20,
163           SA_PARAM_SPEED                = 0x40,
164           SA_PARAM_ALL                  = 0x7f
165 } sa_params;
166 
167 typedef enum {
168           SA_QUIRK_NONE                 = 0x00,
169           SA_QUIRK_NOCOMP               = 0x01,   /* Can't deal with compression at all */
170           SA_QUIRK_FIXED                = 0x02,   /* Force fixed mode */
171           SA_QUIRK_VARIABLE   = 0x04,   /* Force variable mode */
172           SA_QUIRK_2FM                  = 0x08,   /* Needs Two File Marks at EOD */
173           SA_QUIRK_1FM                  = 0x10,   /* No more than 1 File Mark at EOD */
174           SA_QUIRK_NODREAD    = 0x20,   /* Don't try and dummy read density */
175           SA_QUIRK_NO_MODESEL = 0x40,   /* Don't do mode select at all */
176           SA_QUIRK_NO_CPAGE   = 0x80    /* Don't use DEVICE COMPRESSION page */
177 } sa_quirks;
178 
179 /* units are bits 4-7, 16-21 (1024 units) */
180 #define SAUNIT(DEV) \
181           (((minor(DEV) & 0xF0) >> 4) |  ((minor(DEV) & 0x3f0000) >> 16))
182 
183 #define SAMODE(z) ((minor(z) & 0x3))
184 #define SADENSITY(z) (((minor(z) >> 2) & 0x3))
185 #define   SA_IS_CTRL(z) (minor(z) & (1 << 29))
186 
187 #define SA_NOT_CTLDEV         0
188 #define SA_CTLDEV   1
189 
190 #define SA_ATYPE_R  0
191 #define SA_ATYPE_NR 1
192 #define SA_ATYPE_ER 2
193 
194 #define SAMINOR(ctl, unit, mode, access) \
195           ((ctl << 29) | ((unit & 0x3f0) << 16) | ((unit & 0xf) << 4) | \
196           (mode << 0x2) | (access & 0x3))
197 
198 #define SA_UNITMASK SAMINOR(0, -1, 0, 0)
199 #define SA_UNIT(unit)         SAMINOR(0, unit, 0, 0)
200 
201 #define SA_NUM_MODES          4
202 
203 struct sa_softc {
204           sa_state  state;
205           sa_flags  flags;
206           sa_quirks quirks;
207           struct              bio_queue_head bio_queue;
208           int                 queue_count;
209           struct              devstat device_stats;
210           int                 blk_gran;
211           int                 blk_mask;
212           int                 blk_shift;
213           u_int32_t max_blk;
214           u_int32_t min_blk;
215           u_int32_t comp_algorithm;
216           u_int32_t saved_comp_algorithm;
217           u_int32_t media_blksize;
218           u_int32_t last_media_blksize;
219           u_int32_t media_numblks;
220           u_int8_t  media_density;
221           u_int8_t  speed;
222           u_int8_t  scsi_rev;
223           u_int8_t  dsreg;              /* mtio mt_dsreg, redux */
224           int                 buffer_mode;
225           int                 filemarks;
226           union               ccb saved_ccb;
227           int                 last_resid_was_io;
228 
229           /*
230            * Relative to BOT Location.
231            */
232           daddr_t             fileno;
233           daddr_t             blkno;
234 
235           /*
236            * Latched Error Info
237            */
238           struct {
239                     struct scsi_sense_data _last_io_sense;
240                     u_int32_t _last_io_resid;
241                     u_int8_t _last_io_cdb[CAM_MAX_CDBLEN];
242                     struct scsi_sense_data _last_ctl_sense;
243                     u_int32_t _last_ctl_resid;
244                     u_int8_t _last_ctl_cdb[CAM_MAX_CDBLEN];
245 #define   last_io_sense       errinfo._last_io_sense
246 #define   last_io_resid       errinfo._last_io_resid
247 #define   last_io_cdb         errinfo._last_io_cdb
248 #define   last_ctl_sense      errinfo._last_ctl_sense
249 #define   last_ctl_resid      errinfo._last_ctl_resid
250 #define   last_ctl_cdb        errinfo._last_ctl_cdb
251           } errinfo;
252           /*
253            * Misc other flags/state
254            */
255           u_int32_t
256                                                   : 29,
257                     open_rdonly                   : 1,      /* open read-only */
258                     open_pending_mount  : 1,      /* open pending mount */
259                     ctrl_mode           : 1;      /* control device open */
260 };
261 
262 struct sa_quirk_entry {
263           struct scsi_inquiry_pattern inq_pat;    /* matching pattern */
264           sa_quirks quirks;   /* specific quirk type */
265           u_int32_t prefblk;  /* preferred blocksize when in fixed mode */
266 };
267 
268 static struct sa_quirk_entry sa_quirk_table[] =
269 {
270           {
271                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "OnStream",
272                       "ADR*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_NODREAD |
273                        SA_QUIRK_1FM|SA_QUIRK_NO_MODESEL, 32768
274           },
275           {
276                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
277                       "Python 06408*", "*"}, SA_QUIRK_NODREAD, 0
278           },
279           {
280                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
281                       "Python 25601*", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_NODREAD, 0
282           },
283           {
284                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
285                       "Python*", "*"}, SA_QUIRK_NODREAD, 0
286           },
287           {
288                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
289                       "VIPER 150*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
290           },
291           {
292                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
293                       "VIPER 2525 25462", "-011"},
294                       SA_QUIRK_NOCOMP|SA_QUIRK_1FM|SA_QUIRK_NODREAD, 0
295           },
296           {
297                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
298                       "VIPER 2525*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024
299           },
300 #if       0
301           {
302                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
303                       "C15*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_NO_CPAGE, 0,
304           },
305 #endif
306           {
307                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
308                       "C56*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
309           },
310           {
311                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
312                       "T20*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
313           },
314           {
315                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
316                       "T4000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
317           },
318           {
319                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
320                       "HP-88780*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
321           },
322           {
323                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY",
324                       "*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
325           },
326           {
327                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "M4 DATA",
328                       "123107 SCSI*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
329           },
330           {         /* jreynold@primenet.com */
331                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "Seagate",
332                     "STT8000N*", "*"}, SA_QUIRK_1FM, 0
333           },
334           {         /* mike@sentex.net */
335                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "Seagate",
336                     "STT20000*", "*"}, SA_QUIRK_1FM, 0
337           },
338           {
339                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
340                       " TDC 3600", "U07:"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
341           },
342           {
343                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
344                       " TDC 3800", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
345           },
346           {
347                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
348                       " TDC 4100", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
349           },
350           {
351                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
352                       " TDC 4200", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
353           },
354           {
355                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
356                       " SLR*", "*"}, SA_QUIRK_1FM, 0
357           },
358           {
359                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK",
360                       "5525ES*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
361           },
362           {
363                     { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK",
364                       "51000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024
365           }
366 };
367 
368 static    d_open_t  saopen;
369 static    d_close_t saclose;
370 static    d_strategy_t        sastrategy;
371 static    d_ioctl_t saioctl;
372 static    periph_init_t       sainit;
373 static    periph_ctor_t       saregister;
374 static    periph_oninv_t      saoninvalidate;
375 static    periph_dtor_t       sacleanup;
376 static    periph_start_t      sastart;
377 static    void                saasync(void *callback_arg, u_int32_t code,
378                                         struct cam_path *path, void *arg);
379 static    void                sadone(struct cam_periph *periph,
380                                      union ccb *start_ccb);
381 static  int                   saerror(union ccb *ccb, u_int32_t cam_flags,
382                                         u_int32_t sense_flags);
383 static int                    samarkswanted(struct cam_periph *);
384 static int                    sacheckeod(struct cam_periph *periph);
385 static int                    sagetparams(struct cam_periph *periph,
386                                             sa_params params_to_get,
387                                             u_int32_t *blocksize, u_int8_t *density,
388                                             u_int32_t *numblocks, int *buff_mode,
389                                             u_int8_t *write_protect, u_int8_t *speed,
390                                             int *comp_supported, int *comp_enabled,
391                                             u_int32_t *comp_algorithm,
392                                             sa_comp_t *comp_page);
393 static int                    sasetparams(struct cam_periph *periph,
394                                             sa_params params_to_set,
395                                             u_int32_t blocksize, u_int8_t density,
396                                             u_int32_t comp_algorithm,
397                                             u_int32_t sense_flags);
398 static void                   saprevent(struct cam_periph *periph, int action);
399 static int                    sarewind(struct cam_periph *periph);
400 static int                    saspace(struct cam_periph *periph, int count,
401                                         scsi_space_code code);
402 static int                    samount(struct cam_periph *, int, cdev_t);
403 static int                    saretension(struct cam_periph *periph);
404 static int                    sareservereleaseunit(struct cam_periph *periph,
405                                                        int reserve);
406 static int                    saloadunload(struct cam_periph *periph, int load);
407 static int                    saerase(struct cam_periph *periph, int longerase);
408 static int                    sawritefilemarks(struct cam_periph *periph,
409                                                    int nmarks, int setmarks);
410 static int                    sardpos(struct cam_periph *periph, int, u_int32_t *);
411 static int                    sasetpos(struct cam_periph *periph, int, u_int32_t *);
412 
413 
414 static struct periph_driver sadriver =
415 {
416           sainit, "sa",
417           TAILQ_HEAD_INITIALIZER(sadriver.units), /* generation */ 0
418 };
419 
420 PERIPHDRIVER_DECLARE(sa, sadriver);
421 
422 /* For 2.2-stable support */
423 #ifndef D_TAPE
424 #define D_TAPE 0
425 #endif
426 
427 static struct dev_ops sa_ops = {
428           { "sa", 0, D_TAPE },
429           .d_open = saopen,
430           .d_close =          saclose,
431           .d_read = physread,
432           .d_write =          physwrite,
433           .d_ioctl =          saioctl,
434           .d_strategy =       sastrategy,
435 };
436 
437 static struct extend_array *saperiphs;
438 
439 static int
saopen(struct dev_open_args * ap)440 saopen(struct dev_open_args *ap)
441 {
442           cdev_t dev = ap->a_head.a_dev;
443           struct cam_periph *periph;
444           struct sa_softc *softc;
445           int unit;
446           int error;
447 
448           /*
449            * Disallow CAM access if RESTRICTEDROOT
450            */
451           if (caps_priv_check_self(SYSCAP_RESTRICTEDROOT))
452                     return (EPERM);
453 
454           unit = SAUNIT(dev);
455 
456           periph = cam_extend_get(saperiphs, unit);
457           if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
458                     return (ENXIO);
459           }
460 
461           cam_periph_lock(periph);
462 
463           softc = (struct sa_softc *)periph->softc;
464 
465           CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO,
466               ("saopen(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags));
467 
468           if (SA_IS_CTRL(dev)) {
469                     softc->ctrl_mode = 1;
470                     cam_periph_unlock(periph);
471                     return (0);
472           }
473 
474           if ((error = cam_periph_hold(periph, PCATCH)) != 0) {
475                     cam_periph_unlock(periph);
476                     cam_periph_release(periph);
477                     return (error);
478           }
479 
480           if (softc->flags & SA_FLAG_OPEN) {
481                     error = EBUSY;
482           } else if (softc->flags & SA_FLAG_INVALID) {
483                     error = ENXIO;
484           } else {
485                     /*
486                      * Preserve whether this is a read_only open.
487                      */
488                     softc->open_rdonly = (ap->a_oflags & O_RDWR) == O_RDONLY;
489 
490                     /*
491                      * The function samount ensures media is loaded and ready.
492                      * It also does a device RESERVE if the tape isn't yet mounted.
493                      *
494                      * If the mount fails and this was a non-blocking open,
495                      * make this a 'open_pending_mount' action.
496                      */
497                     error = samount(periph, ap->a_oflags, dev);
498                     if (error && (ap->a_oflags & O_NONBLOCK)) {
499                               softc->flags |= SA_FLAG_OPEN;
500                               softc->open_pending_mount = 1;
501                               cam_periph_unhold(periph, 1);
502                               return (0);
503                     }
504           }
505 
506           if (error) {
507                     cam_periph_unhold(periph, 1);
508                     cam_periph_release(periph);
509                     return (error);
510           }
511 
512           saprevent(periph, PR_PREVENT);
513           softc->flags |= SA_FLAG_OPEN;
514 
515           cam_periph_unhold(periph, 1);
516           return (error);
517 }
518 
519 static int
saclose(struct dev_close_args * ap)520 saclose(struct dev_close_args *ap)
521 {
522           cdev_t dev = ap->a_head.a_dev;
523           struct    cam_periph *periph;
524           struct    sa_softc *softc;
525           int       unit, mode, error, writing, tmp;
526           int       closedbits = SA_FLAG_OPEN;
527 
528           unit = SAUNIT(dev);
529           mode = SAMODE(dev);
530           periph = cam_extend_get(saperiphs, unit);
531           if (periph == NULL)
532                     return (ENXIO);
533 
534           cam_periph_lock(periph);
535 
536           softc = (struct sa_softc *)periph->softc;
537 
538           CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO,
539               ("saclose(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags));
540 
541 
542           softc->open_rdonly = 0;
543           if (SA_IS_CTRL(dev)) {
544                     softc->ctrl_mode = 0;
545                     cam_periph_unlock(periph);
546                     cam_periph_release(periph);
547                     return (0);
548           }
549 
550           if (softc->open_pending_mount) {
551                     softc->flags &= ~SA_FLAG_OPEN;
552                     softc->open_pending_mount = 0;
553                     cam_periph_unlock(periph);
554                     cam_periph_release(periph);
555                     return (0);
556           }
557 
558           if ((error = cam_periph_hold(periph, 0)) != 0) {
559                     cam_periph_unlock(periph);
560                     return (error);
561           }
562 
563           /*
564            * Were we writing the tape?
565            */
566           writing = (softc->flags & SA_FLAG_TAPE_WRITTEN) != 0;
567 
568           /*
569            * See whether or not we need to write filemarks. If this
570            * fails, we probably have to assume we've lost tape
571            * position.
572            */
573           error = sacheckeod(periph);
574           if (error) {
575                     xpt_print(periph->path,
576                         "failed to write terminating filemark(s)\n");
577                     softc->flags |= SA_FLAG_TAPE_FROZEN;
578           }
579 
580           /*
581            * Whatever we end up doing, allow users to eject tapes from here on.
582            */
583           saprevent(periph, PR_ALLOW);
584 
585           /*
586            * Decide how to end...
587            */
588           if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) {
589                     closedbits |= SA_FLAG_TAPE_FROZEN;
590           } else switch (mode) {
591           case SA_MODE_OFFLINE:
592                     /*
593                      * An 'offline' close is an unconditional release of
594                      * frozen && mount conditions, irrespective of whether
595                      * these operations succeeded. The reason for this is
596                      * to allow at least some kind of programmatic way
597                      * around our state getting all fouled up. If somebody
598                      * issues an 'offline' command, that will be allowed
599                      * to clear state.
600                      */
601                     sarewind(periph);
602                     saloadunload(periph, FALSE);
603                     closedbits |= SA_FLAG_TAPE_MOUNTED|SA_FLAG_TAPE_FROZEN;
604                     break;
605           case SA_MODE_REWIND:
606                     /*
607                      * If the rewind fails, return an error- if anyone cares,
608                      * but not overwriting any previous error.
609                      *
610                      * We don't clear the notion of mounted here, but we do
611                      * clear the notion of frozen if we successfully rewound.
612                      */
613                     tmp = sarewind(periph);
614                     if (tmp) {
615                               if (error != 0)
616                                         error = tmp;
617                     } else {
618                               closedbits |= SA_FLAG_TAPE_FROZEN;
619                     }
620                     break;
621           case SA_MODE_NOREWIND:
622                     /*
623                      * If we're not rewinding/unloading the tape, find out
624                      * whether we need to back up over one of two filemarks
625                      * we wrote (if we wrote two filemarks) so that appends
626                      * from this point on will be sane.
627                      */
628                     if (error == 0 && writing && (softc->quirks & SA_QUIRK_2FM)) {
629                               tmp = saspace(periph, -1, SS_FILEMARKS);
630                               if (tmp) {
631                                         xpt_print(periph->path, "unable to backspace "
632                                             "over one of double filemarks at end of "
633                                             "tape\n");
634                                         xpt_print(periph->path, "it is possible that "
635                                             "this device needs a SA_QUIRK_1FM quirk set"
636                                             "for it\n");
637                                         softc->flags |= SA_FLAG_TAPE_FROZEN;
638                               }
639                     }
640                     break;
641           default:
642                     xpt_print(periph->path, "unknown mode 0x%x in saclose\n", mode);
643                     /* NOTREACHED */
644                     break;
645           }
646 
647           /*
648            * We wish to note here that there are no more filemarks to be written.
649            */
650           softc->filemarks = 0;
651           softc->flags &= ~SA_FLAG_TAPE_WRITTEN;
652 
653           /*
654            * And we are no longer open for business.
655            */
656           softc->flags &= ~closedbits;
657 
658           /*
659            * Inform users if tape state if frozen....
660            */
661           if (softc->flags & SA_FLAG_TAPE_FROZEN) {
662                     xpt_print(periph->path, "tape is now frozen- use an OFFLINE, "
663                         "REWIND or MTEOM command to clear this state.\n");
664           }
665 
666           /* release the device if it is no longer mounted */
667           if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0)
668                     sareservereleaseunit(periph, FALSE);
669 
670           cam_periph_unhold(periph, 1);
671           cam_periph_release(periph);
672 
673           return (error);
674 }
675 
676 /*
677  * Actually translate the requested transfer into one the physical driver
678  * can understand.  The transfer is described by a buf and will include
679  * only one physical transfer.
680  */
681 static int
sastrategy(struct dev_strategy_args * ap)682 sastrategy(struct dev_strategy_args *ap)
683 {
684           cdev_t dev = ap->a_head.a_dev;
685           struct bio *bio = ap->a_bio;
686           struct buf *bp = bio->bio_buf;
687           struct cam_periph *periph;
688           struct sa_softc *softc;
689           u_int  unit;
690 
691           if (SA_IS_CTRL(dev)) {
692                     bp->b_error = EINVAL;
693                     goto bad;
694           }
695           unit = SAUNIT(dev);
696           periph = cam_extend_get(saperiphs, unit);
697           if (periph == NULL) {
698                     bp->b_error = ENXIO;
699                     goto bad;
700           }
701           cam_periph_lock(periph);
702 
703           softc = (struct sa_softc *)periph->softc;
704 
705           if (softc->flags & SA_FLAG_INVALID) {
706                     cam_periph_unlock(periph);
707                     bp->b_error = ENXIO;
708                     goto bad;
709           }
710 
711           if (softc->flags & SA_FLAG_TAPE_FROZEN) {
712                     cam_periph_unlock(periph);
713                     bp->b_error = EPERM;
714                     goto bad;
715           }
716 
717           /*
718            * This should actually never occur as the write(2)
719            * system call traps attempts to write to a read-only
720            * file descriptor.
721            */
722           if (bp->b_cmd == BUF_CMD_WRITE && softc->open_rdonly) {
723                     cam_periph_unlock(periph);
724                     bp->b_error = EBADF;
725                     goto bad;
726           }
727 
728           if (softc->open_pending_mount) {
729                     int error = samount(periph, 0, dev);
730                     if (error) {
731                               cam_periph_unlock(periph);
732                               bp->b_error = ENXIO;
733                               goto bad;
734                     }
735                     saprevent(periph, PR_PREVENT);
736                     softc->open_pending_mount = 0;
737           }
738 
739           /*
740            * If it's a null transfer, return immediately
741            */
742           if (bp->b_bcount == 0) {
743                     cam_periph_unlock(periph);
744                     goto done;
745           }
746 
747           /* valid request?  */
748           if (softc->flags & SA_FLAG_FIXED) {
749                     /*
750                      * Fixed block device.  The byte count must
751                      * be a multiple of our block size.
752                      */
753                     if (((softc->blk_mask != ~0) &&
754                         ((bp->b_bcount & softc->blk_mask) != 0)) ||
755                         ((softc->blk_mask == ~0) &&
756                         ((bp->b_bcount % softc->min_blk) != 0))) {
757                               xpt_print(periph->path, "Invalid request.  Fixed block "
758                                   "device requests must be a multiple of %d bytes\n",
759                                   softc->min_blk);
760                               cam_periph_unlock(periph);
761                               bp->b_error = EINVAL;
762                               goto bad;
763                     }
764           } else if ((bp->b_bcount > softc->max_blk) ||
765                        (bp->b_bcount < softc->min_blk) ||
766                        (bp->b_bcount & softc->blk_mask) != 0) {
767 
768                     xpt_print_path(periph->path);
769                     kprintf("Invalid request.  Variable block "
770                         "device requests must be ");
771                     if (softc->blk_mask != 0) {
772                               kprintf("a multiple of %d ", (0x1 << softc->blk_gran));
773                     }
774                     kprintf("between %d and %d bytes\n", softc->min_blk,
775                         softc->max_blk);
776                     cam_periph_unlock(periph);
777                     bp->b_error = EINVAL;
778                     goto bad;
779         }
780 
781           /*
782            * Place it at the end of the queue.
783            */
784           bioq_insert_tail(&softc->bio_queue, bio);
785           softc->queue_count++;
786 #if       0
787           CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
788               ("sastrategy: queuing a %ld %s byte %s\n", bp->bio_bcount,
789               (softc->flags & SA_FLAG_FIXED)?  "fixed" : "variable",
790               (bp->bio_cmd == BIO_READ)? "read" : "write"));
791 #endif
792           if (softc->queue_count > 1) {
793                     CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
794                         ("sastrategy: queue count now %d\n", softc->queue_count));
795           }
796 
797           /*
798            * Schedule ourselves for performing the work.
799            */
800           xpt_schedule(periph, 1);
801           cam_periph_unlock(periph);
802 
803           return(0);
804 bad:
805           bp->b_flags |= B_ERROR;
806 done:
807 
808           /*
809            * Correctly set the buf to indicate a completed xfer
810            */
811           bp->b_resid = bp->b_bcount;
812           biodone(bio);
813           return(0);
814 }
815 
816 
817 #define   PENDING_MOUNT_CHECK(softc, periph, dev)           \
818           if (softc->open_pending_mount) {                  \
819                     error = samount(periph, 0, dev);        \
820                     if (error) {                                      \
821                               break;                                  \
822                     }                                                 \
823                     saprevent(periph, PR_PREVENT);                    \
824                     softc->open_pending_mount = 0;                    \
825           }
826 
827 static int
saioctl(struct dev_ioctl_args * ap)828 saioctl(struct dev_ioctl_args *ap)
829 {
830           cdev_t dev = ap->a_head.a_dev;
831           caddr_t addr = ap->a_data;
832           struct cam_periph *periph;
833           struct sa_softc *softc;
834           scsi_space_code spaceop;
835           int didholdperiph = 0;
836           int unit;
837           int mode;
838           int error = 0;
839 
840           unit = SAUNIT(dev);
841           mode = SAMODE(dev);
842           error = 0;                    /* shut up gcc */
843           spaceop = 0;                  /* shut up gcc */
844 
845           periph = cam_extend_get(saperiphs, unit);
846           if (periph == NULL)
847                     return (ENXIO);
848 
849           cam_periph_lock(periph);
850           softc = (struct sa_softc *)periph->softc;
851 
852           /*
853            * Check for control mode accesses. We allow MTIOCGET and
854            * MTIOCERRSTAT (but need to be the only one open in order
855            * to clear latched status), and MTSETBSIZE, MTSETDNSTY
856            * and MTCOMP (but need to be the only one accessing this
857            * device to run those).
858            */
859 
860           if (SA_IS_CTRL(dev)) {
861                     switch (ap->a_cmd) {
862                     case MTIOCGETEOTMODEL:
863                     case MTIOCGET:
864                               break;
865                     case MTIOCERRSTAT:
866                               /*
867                                * If the periph isn't already locked, lock it
868                                * so our MTIOCERRSTAT can reset latched error stats.
869                                *
870                                * If the periph is already locked, skip it because
871                                * we're just getting status and it'll be up to the
872                                * other thread that has this device open to do
873                                * an MTIOCERRSTAT that would clear latched status.
874                                */
875                               if ((periph->flags & CAM_PERIPH_LOCKED) == 0) {
876                                         error = cam_periph_hold(periph, PCATCH);
877                                         if (error != 0) {
878                                                   return (error);
879                                         }
880                                         didholdperiph = 1;
881                               }
882                               break;
883 
884                     case MTIOCTOP:
885                     {
886                               struct mtop *mt = (struct mtop *) addr;
887 
888                               /*
889                                * Check to make sure it's an OP we can perform
890                                * with no media inserted.
891                                */
892                               switch (mt->mt_op) {
893                               case MTSETBSIZ:
894                               case MTSETDNSTY:
895                               case MTCOMP:
896                                         mt = NULL;
897                                         /* FALLTHROUGH */
898                               default:
899                                         break;
900                               }
901                               if (mt != NULL) {
902                                         break;
903                               }
904                               /* FALLTHROUGH */
905                     }
906                     case MTIOCSETEOTMODEL:
907                               /*
908                                * We need to acquire the peripheral here rather
909                                * than at open time because we are sharing writable
910                                * access to data structures.
911                                */
912                               error = cam_periph_hold(periph, PCATCH);
913                               if (error != 0) {
914                                         return (error);
915                               }
916                               didholdperiph = 1;
917                               break;
918 
919                     default:
920                               return (EINVAL);
921                     }
922           }
923 
924           /*
925            * Find the device that the user is talking about
926            */
927           switch (ap->a_cmd) {
928           case MTIOCGET:
929           {
930                     struct mtget *g = (struct mtget *)addr;
931 
932                     /*
933                      * If this isn't the control mode device, actually go out
934                      * and ask the drive again what it's set to.
935                      */
936                     if (!SA_IS_CTRL(dev) && !softc->open_pending_mount) {
937                               u_int8_t write_protect = 0;   /* silence gcc */
938                               int comp_enabled = 0;                   /* silence gcc */
939                               int comp_supported = 0;                 /* silence gcc */
940 
941                               error = sagetparams(periph, SA_PARAM_ALL,
942                                   &softc->media_blksize, &softc->media_density,
943                                   &softc->media_numblks, &softc->buffer_mode,
944                                   &write_protect, &softc->speed, &comp_supported,
945                                   &comp_enabled, &softc->comp_algorithm, NULL);
946                               if (error)
947                                         break;
948                               if (write_protect)
949                                         softc->flags |= SA_FLAG_TAPE_WP;
950                               else
951                                         softc->flags &= ~SA_FLAG_TAPE_WP;
952                               softc->flags &= ~(SA_FLAG_COMP_SUPP|
953                                   SA_FLAG_COMP_ENABLED|SA_FLAG_COMP_UNSUPP);
954                               if (comp_supported) {
955                                         if (softc->saved_comp_algorithm == 0)
956                                                   softc->saved_comp_algorithm =
957                                                       softc->comp_algorithm;
958                                         softc->flags |= SA_FLAG_COMP_SUPP;
959                                         if (comp_enabled)
960                                                   softc->flags |= SA_FLAG_COMP_ENABLED;
961                               } else
962                                         softc->flags |= SA_FLAG_COMP_UNSUPP;
963                     }
964                     bzero(g, sizeof(struct mtget));
965                     g->mt_type = MT_ISAR;
966                     if (softc->flags & SA_FLAG_COMP_UNSUPP) {
967                               g->mt_comp = MT_COMP_UNSUPP;
968                               g->mt_comp0 = MT_COMP_UNSUPP;
969                               g->mt_comp1 = MT_COMP_UNSUPP;
970                               g->mt_comp2 = MT_COMP_UNSUPP;
971                               g->mt_comp3 = MT_COMP_UNSUPP;
972                     } else {
973                               if ((softc->flags & SA_FLAG_COMP_ENABLED) == 0) {
974                                         g->mt_comp = MT_COMP_DISABLED;
975                               } else {
976                                         g->mt_comp = softc->comp_algorithm;
977                               }
978                               g->mt_comp0 = softc->comp_algorithm;
979                               g->mt_comp1 = softc->comp_algorithm;
980                               g->mt_comp2 = softc->comp_algorithm;
981                               g->mt_comp3 = softc->comp_algorithm;
982                     }
983                     g->mt_density = softc->media_density;
984                     g->mt_density0 = softc->media_density;
985                     g->mt_density1 = softc->media_density;
986                     g->mt_density2 = softc->media_density;
987                     g->mt_density3 = softc->media_density;
988                     g->mt_blksiz = softc->media_blksize;
989                     g->mt_blksiz0 = softc->media_blksize;
990                     g->mt_blksiz1 = softc->media_blksize;
991                     g->mt_blksiz2 = softc->media_blksize;
992                     g->mt_blksiz3 = softc->media_blksize;
993                     g->mt_fileno = softc->fileno;
994                     g->mt_blkno = softc->blkno;
995                     g->mt_dsreg = (short) softc->dsreg;
996                     /*
997                      * Yes, we know that this is likely to overflow
998                      */
999                     if (softc->last_resid_was_io) {
1000                               if ((g->mt_resid = (short) softc->last_io_resid) != 0) {
1001                                         if (SA_IS_CTRL(dev) == 0 || didholdperiph) {
1002                                                   softc->last_io_resid = 0;
1003                                         }
1004                               }
1005                     } else {
1006                               if ((g->mt_resid = (short)softc->last_ctl_resid) != 0) {
1007                                         if (SA_IS_CTRL(dev) == 0 || didholdperiph) {
1008                                                   softc->last_ctl_resid = 0;
1009                                         }
1010                               }
1011                     }
1012                     error = 0;
1013                     break;
1014           }
1015           case MTIOCERRSTAT:
1016           {
1017                     struct scsi_tape_errors *sep =
1018                         &((union mterrstat *)addr)->scsi_errstat;
1019 
1020                     CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
1021                         ("saioctl: MTIOCERRSTAT\n"));
1022 
1023                     bzero(sep, sizeof(*sep));
1024                     sep->io_resid = softc->last_io_resid;
1025                     bcopy((caddr_t) &softc->last_io_sense, sep->io_sense,
1026                         sizeof (sep->io_sense));
1027                     bcopy((caddr_t) &softc->last_io_cdb, sep->io_cdb,
1028                         sizeof (sep->io_cdb));
1029                     sep->ctl_resid = softc->last_ctl_resid;
1030                     bcopy((caddr_t) &softc->last_ctl_sense, sep->ctl_sense,
1031                         sizeof (sep->ctl_sense));
1032                     bcopy((caddr_t) &softc->last_ctl_cdb, sep->ctl_cdb,
1033                         sizeof (sep->ctl_cdb));
1034 
1035                     if ((SA_IS_CTRL(dev) == 0 && softc->open_pending_mount) ||
1036                         didholdperiph)
1037                               bzero((caddr_t) &softc->errinfo,
1038                                   sizeof (softc->errinfo));
1039                     error = 0;
1040                     break;
1041           }
1042           case MTIOCTOP:
1043           {
1044                     struct mtop *mt;
1045                     int    count;
1046 
1047                     PENDING_MOUNT_CHECK(softc, periph, dev);
1048 
1049                     mt = (struct mtop *)addr;
1050 
1051                     CAM_DEBUG(periph->path, CAM_DEBUG_TRACE,
1052                                ("saioctl: op=0x%x count=0x%x\n",
1053                                 mt->mt_op, mt->mt_count));
1054 
1055                     count = mt->mt_count;
1056                     switch (mt->mt_op) {
1057                     case MTWEOF:        /* write an end-of-file marker */
1058                               /*
1059                                * We don't need to clear the SA_FLAG_TAPE_WRITTEN
1060                                * flag because by keeping track of filemarks
1061                                * we have last written we know ehether or not
1062                                * we need to write more when we close the device.
1063                                */
1064                               error = sawritefilemarks(periph, count, FALSE);
1065                               break;
1066                     case MTWSS:         /* write a setmark */
1067                               error = sawritefilemarks(periph, count, TRUE);
1068                               break;
1069                     case MTBSR:         /* backward space record */
1070                     case MTFSR:         /* forward space record */
1071                     case MTBSF:         /* backward space file */
1072                     case MTFSF:         /* forward space file */
1073                     case MTBSS:         /* backward space setmark */
1074                     case MTFSS:         /* forward space setmark */
1075                     case MTEOD:         /* space to end of recorded medium */
1076                     {
1077                               int nmarks;
1078 
1079                               spaceop = SS_FILEMARKS;
1080                               nmarks = softc->filemarks;
1081                               error = sacheckeod(periph);
1082                               if (error) {
1083                                         xpt_print(periph->path,
1084                                             "EOD check prior to spacing failed\n");
1085                                         softc->flags |= SA_FLAG_EIO_PENDING;
1086                                         break;
1087                               }
1088                               nmarks -= softc->filemarks;
1089                               switch(mt->mt_op) {
1090                               case MTBSR:
1091                                         count = -count;
1092                                         /* FALLTHROUGH */
1093                               case MTFSR:
1094                                         spaceop = SS_BLOCKS;
1095                                         break;
1096                               case MTBSF:
1097                                         count = -count;
1098                                         /* FALLTHROUGH */
1099                               case MTFSF:
1100                                         break;
1101                               case MTBSS:
1102                                         count = -count;
1103                                         /* FALLTHROUGH */
1104                               case MTFSS:
1105                                         spaceop = SS_SETMARKS;
1106                                         break;
1107                               case MTEOD:
1108                                         spaceop = SS_EOD;
1109                                         count = 0;
1110                                         nmarks = 0;
1111                                         break;
1112                               default:
1113                                         error = EINVAL;
1114                                         break;
1115                               }
1116                               if (error)
1117                                         break;
1118 
1119                               nmarks = softc->filemarks;
1120                               /*
1121                                * XXX: Why are we checking again?
1122                                */
1123                               error = sacheckeod(periph);
1124                               if (error)
1125                                         break;
1126                               nmarks -= softc->filemarks;
1127                               error = saspace(periph, count - nmarks, spaceop);
1128                               /*
1129                                * At this point, clear that we've written the tape
1130                                * and that we've written any filemarks. We really
1131                                * don't know what the applications wishes to do next-
1132                                * the sacheckeod's will make sure we terminated the
1133                                * tape correctly if we'd been writing, but the next
1134                                * action the user application takes will set again
1135                                * whether we need to write filemarks.
1136                                */
1137                               softc->flags &=
1138                                   ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN);
1139                               softc->filemarks = 0;
1140                               break;
1141                     }
1142                     case MTREW:         /* rewind */
1143                               PENDING_MOUNT_CHECK(softc, periph, dev);
1144                               sacheckeod(periph);
1145                               error = sarewind(periph);
1146                               /* see above */
1147                               softc->flags &=
1148                                   ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN);
1149                               softc->flags &= ~SA_FLAG_ERR_PENDING;
1150                               softc->filemarks = 0;
1151                               break;
1152                     case MTERASE:       /* erase */
1153                               PENDING_MOUNT_CHECK(softc, periph, dev);
1154                               error = saerase(periph, count);
1155                               softc->flags &=
1156                                   ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN);
1157                               softc->flags &= ~SA_FLAG_ERR_PENDING;
1158                               break;
1159                     case MTRETENS:      /* re-tension tape */
1160                               PENDING_MOUNT_CHECK(softc, periph, dev);
1161                               error = saretension(periph);
1162                               softc->flags &=
1163                                   ~(SA_FLAG_TAPE_WRITTEN|SA_FLAG_TAPE_FROZEN);
1164                               softc->flags &= ~SA_FLAG_ERR_PENDING;
1165                               break;
1166                     case MTOFFL:        /* rewind and put the drive offline */
1167 
1168                               PENDING_MOUNT_CHECK(softc, periph, dev);
1169 
1170                               sacheckeod(periph);
1171                               /* see above */
1172                               softc->flags &= ~SA_FLAG_TAPE_WRITTEN;
1173                               softc->filemarks = 0;
1174 
1175                               error = sarewind(periph);
1176                               /* clear the frozen flag anyway */
1177                               softc->flags &= ~SA_FLAG_TAPE_FROZEN;
1178 
1179                               /*
1180                                * Be sure to allow media removal before ejecting.
1181                                */
1182 
1183                               saprevent(periph, PR_ALLOW);
1184                               if (error == 0) {
1185                                         error = saloadunload(periph, FALSE);
1186                                         if (error == 0) {
1187                                                   softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
1188                                         }
1189                               }
1190                               break;
1191 
1192                     case MTNOP:         /* no operation, sets status only */
1193                     case MTCACHE:       /* enable controller cache */
1194                     case MTNOCACHE:     /* disable controller cache */
1195                               error = 0;
1196                               break;
1197 
1198                     case MTSETBSIZ:     /* Set block size for device */
1199 
1200                               PENDING_MOUNT_CHECK(softc, periph, dev);
1201 
1202                               error = sasetparams(periph, SA_PARAM_BLOCKSIZE, count,
1203                                                       0, 0, 0);
1204                               if (error == 0) {
1205                                         softc->last_media_blksize =
1206                                             softc->media_blksize;
1207                                         softc->media_blksize = count;
1208                                         if (count) {
1209                                                   softc->flags |= SA_FLAG_FIXED;
1210                                                   if (powerof2(count)) {
1211                                                             softc->blk_shift =
1212                                                                 ffs(count) - 1;
1213                                                             softc->blk_mask = count - 1;
1214                                                   } else {
1215                                                             softc->blk_mask = ~0;
1216                                                             softc->blk_shift = 0;
1217                                                   }
1218                                                   /*
1219                                                    * Make the user's desire 'persistent'.
1220                                                    */
1221                                                   softc->quirks &= ~SA_QUIRK_VARIABLE;
1222                                                   softc->quirks |= SA_QUIRK_FIXED;
1223                                         } else {
1224                                                   softc->flags &= ~SA_FLAG_FIXED;
1225                                                   if (softc->max_blk == 0) {
1226                                                             softc->max_blk = ~0;
1227                                                   }
1228                                                   softc->blk_shift = 0;
1229                                                   if (softc->blk_gran != 0) {
1230                                                             softc->blk_mask =
1231                                                                 softc->blk_gran - 1;
1232                                                   } else {
1233                                                             softc->blk_mask = 0;
1234                                                   }
1235                                                   /*
1236                                                    * Make the user's desire 'persistent'.
1237                                                    */
1238                                                   softc->quirks |= SA_QUIRK_VARIABLE;
1239                                                   softc->quirks &= ~SA_QUIRK_FIXED;
1240                                         }
1241                               }
1242                               break;
1243                     case MTSETDNSTY:    /* Set density for device and mode */
1244                               PENDING_MOUNT_CHECK(softc, periph, dev);
1245 
1246                               if (count > UCHAR_MAX) {
1247                                         error = EINVAL;
1248                                         break;
1249                               } else {
1250                                         error = sasetparams(periph, SA_PARAM_DENSITY,
1251                                                                 0, count, 0, 0);
1252                               }
1253                               break;
1254                     case MTCOMP:        /* enable compression */
1255                               PENDING_MOUNT_CHECK(softc, periph, dev);
1256                               /*
1257                                * Some devices don't support compression, and
1258                                * don't like it if you ask them for the
1259                                * compression page.
1260                                */
1261                               if ((softc->quirks & SA_QUIRK_NOCOMP) ||
1262                                   (softc->flags & SA_FLAG_COMP_UNSUPP)) {
1263                                         error = ENODEV;
1264                                         break;
1265                               }
1266                               error = sasetparams(periph, SA_PARAM_COMPRESSION,
1267                                   0, 0, count, SF_NO_PRINT);
1268                               break;
1269                     default:
1270                               error = EINVAL;
1271                     }
1272                     break;
1273           }
1274           case MTIOCIEOT:
1275           case MTIOCEEOT:
1276                     error = 0;
1277                     break;
1278           case MTIOCRDSPOS:
1279                     PENDING_MOUNT_CHECK(softc, periph, dev);
1280                     error = sardpos(periph, 0, (u_int32_t *) addr);
1281                     break;
1282           case MTIOCRDHPOS:
1283                     PENDING_MOUNT_CHECK(softc, periph, dev);
1284                     error = sardpos(periph, 1, (u_int32_t *) addr);
1285                     break;
1286           case MTIOCSLOCATE:
1287                     PENDING_MOUNT_CHECK(softc, periph, dev);
1288                     error = sasetpos(periph, 0, (u_int32_t *) addr);
1289                     break;
1290           case MTIOCHLOCATE:
1291                     PENDING_MOUNT_CHECK(softc, periph, dev);
1292                     error = sasetpos(periph, 1, (u_int32_t *) addr);
1293                     break;
1294           case MTIOCGETEOTMODEL:
1295                     error = 0;
1296                     if (softc->quirks & SA_QUIRK_1FM)
1297                               mode = 1;
1298                     else
1299                               mode = 2;
1300                     *((u_int32_t *) addr) = mode;
1301                     break;
1302           case MTIOCSETEOTMODEL:
1303                     error = 0;
1304                     switch (*((u_int32_t *) addr)) {
1305                     case 1:
1306                               softc->quirks &= ~SA_QUIRK_2FM;
1307                               softc->quirks |= SA_QUIRK_1FM;
1308                               break;
1309                     case 2:
1310                               softc->quirks &= ~SA_QUIRK_1FM;
1311                               softc->quirks |= SA_QUIRK_2FM;
1312                               break;
1313                     default:
1314                               error = EINVAL;
1315                               break;
1316                     }
1317                     break;
1318           default:
1319                     error = cam_periph_ioctl(periph, ap->a_cmd, addr, saerror);
1320                     break;
1321           }
1322 
1323           /*
1324            * Check to see if we cleared a frozen state
1325            */
1326           if (error == 0 && (softc->flags & SA_FLAG_TAPE_FROZEN)) {
1327                     switch(ap->a_cmd) {
1328                     case MTIOCRDSPOS:
1329                     case MTIOCRDHPOS:
1330                     case MTIOCSLOCATE:
1331                     case MTIOCHLOCATE:
1332                               softc->fileno = (daddr_t) -1;
1333                               softc->blkno = (daddr_t) -1;
1334                               softc->flags &= ~SA_FLAG_TAPE_FROZEN;
1335                               xpt_print(periph->path,
1336                                   "tape state now unfrozen.\n");
1337                               break;
1338                     default:
1339                               break;
1340                     }
1341           }
1342           if (didholdperiph)
1343                     cam_periph_unhold(periph, 1);
1344           else
1345                     cam_periph_unlock(periph);
1346           return (error);
1347 }
1348 
1349 static void
sainit(void)1350 sainit(void)
1351 {
1352           cam_status status;
1353 
1354           /*
1355            * Create our extend array for storing the devices we attach to.
1356            */
1357           saperiphs = cam_extend_new();
1358           if (saperiphs == NULL) {
1359                     kprintf("sa: Failed to alloc extend array!\n");
1360                     return;
1361           }
1362 
1363           /*
1364            * Install a global async callback.
1365            */
1366           status = xpt_register_async(AC_FOUND_DEVICE, saasync, NULL, NULL);
1367 
1368           if (status != CAM_REQ_CMP) {
1369                     kprintf("sa: Failed to attach master async callback "
1370                            "due to status 0x%x!\n", status);
1371           }
1372 }
1373 
1374 static void
saoninvalidate(struct cam_periph * periph)1375 saoninvalidate(struct cam_periph *periph)
1376 {
1377           struct sa_softc *softc;
1378           struct buf *q_bp;
1379           struct bio *q_bio;
1380 
1381           softc = (struct sa_softc *)periph->softc;
1382 
1383           /*
1384            * De-register any async callbacks.
1385            */
1386           xpt_register_async(0, saasync, periph, periph->path);
1387 
1388           softc->flags |= SA_FLAG_INVALID;
1389 
1390           /*
1391            * Return all queued I/O with ENXIO.
1392            * XXX Handle any transactions queued to the card
1393            *     with XPT_ABORT_CCB.
1394            */
1395           while ((q_bio = bioq_takefirst(&softc->bio_queue)) != NULL) {
1396                     q_bp = q_bio->bio_buf;
1397                     q_bp->b_resid = q_bp->b_bcount;
1398                     q_bp->b_error = ENXIO;
1399                     q_bp->b_flags |= B_ERROR;
1400                     biodone(q_bio);
1401           }
1402           softc->queue_count = 0;
1403 
1404           xpt_print(periph->path, "lost device\n");
1405 
1406 }
1407 
1408 static void
sacleanup(struct cam_periph * periph)1409 sacleanup(struct cam_periph *periph)
1410 {
1411           struct sa_softc *softc;
1412 
1413           softc = (struct sa_softc *)periph->softc;
1414 
1415           devstat_remove_entry(&softc->device_stats);
1416 
1417           cam_extend_release(saperiphs, periph->unit_number);
1418           xpt_print(periph->path, "removing device entry\n");
1419           dev_ops_remove_minor(&sa_ops, /*SA_UNITMASK,*/ SA_UNIT(periph->unit_number));
1420           kfree(softc, M_SCSISA);
1421 }
1422 
1423 static void
saasync(void * callback_arg,u_int32_t code,struct cam_path * path,void * arg)1424 saasync(void *callback_arg, u_int32_t code,
1425           struct cam_path *path, void *arg)
1426 {
1427           struct cam_periph *periph;
1428 
1429           periph = (struct cam_periph *)callback_arg;
1430           switch (code) {
1431           case AC_FOUND_DEVICE:
1432           {
1433                     struct ccb_getdev *cgd;
1434                     cam_status status;
1435 
1436                     cgd = (struct ccb_getdev *)arg;
1437                     if (cgd == NULL)
1438                               break;
1439 
1440                     if (SID_TYPE(&cgd->inq_data) != T_SEQUENTIAL)
1441                               break;
1442 
1443                     /*
1444                      * Allocate a peripheral instance for
1445                      * this device and start the probe
1446                      * process.
1447                      */
1448                     status = cam_periph_alloc(saregister, saoninvalidate,
1449                                                     sacleanup, sastart,
1450                                                     "sa", CAM_PERIPH_BIO, cgd->ccb_h.path,
1451                                                     saasync, AC_FOUND_DEVICE, cgd);
1452 
1453                     if (status != CAM_REQ_CMP
1454                      && status != CAM_REQ_INPROG)
1455                               kprintf("saasync: Unable to probe new device "
1456                                         "due to status 0x%x\n", status);
1457                     break;
1458           }
1459           default:
1460                     cam_periph_async(periph, code, path, arg);
1461                     break;
1462           }
1463 }
1464 
1465 static cam_status
saregister(struct cam_periph * periph,void * arg)1466 saregister(struct cam_periph *periph, void *arg)
1467 {
1468           struct sa_softc *softc;
1469           struct ccb_getdev *cgd;
1470           caddr_t match;
1471           int i;
1472 
1473           cgd = (struct ccb_getdev *)arg;
1474           if (periph == NULL) {
1475                     kprintf("saregister: periph was NULL!!\n");
1476                     return (CAM_REQ_CMP_ERR);
1477           }
1478 
1479           if (cgd == NULL) {
1480                     kprintf("saregister: no getdev CCB, can't register device\n");
1481                     return (CAM_REQ_CMP_ERR);
1482           }
1483 
1484           softc = kmalloc(sizeof (*softc), M_SCSISA, M_INTWAIT | M_ZERO);
1485           softc->scsi_rev = SID_ANSI_REV(&cgd->inq_data);
1486           softc->state = SA_STATE_NORMAL;
1487           softc->fileno = (daddr_t) -1;
1488           softc->blkno = (daddr_t) -1;
1489 
1490           bioq_init(&softc->bio_queue);
1491           periph->softc = softc;
1492           cam_extend_set(saperiphs, periph->unit_number, periph);
1493 
1494           /*
1495            * See if this device has any quirks.
1496            */
1497           match = cam_quirkmatch((caddr_t)&cgd->inq_data,
1498                                      (caddr_t)sa_quirk_table,
1499                                      NELEM(sa_quirk_table),
1500                                      sizeof(*sa_quirk_table), scsi_inquiry_match);
1501 
1502           if (match != NULL) {
1503                     softc->quirks = ((struct sa_quirk_entry *)match)->quirks;
1504                     softc->last_media_blksize =
1505                         ((struct sa_quirk_entry *)match)->prefblk;
1506 #ifdef    CAMDEBUG
1507                     xpt_print(periph->path, "found quirk entry %d\n",
1508                         (int) (((struct sa_quirk_entry *) match) - sa_quirk_table));
1509 #endif
1510           } else
1511                     softc->quirks = SA_QUIRK_NONE;
1512 
1513           /*
1514            * The SA driver supports a blocksize, but we don't know the
1515            * blocksize until we media is inserted.  So, set a flag to
1516            * indicate that the blocksize is unavailable right now.
1517            */
1518           cam_periph_unlock(periph);
1519           devstat_add_entry(&softc->device_stats, "sa", periph->unit_number, 0,
1520               DEVSTAT_BS_UNAVAILABLE, SID_TYPE(&cgd->inq_data) |
1521               DEVSTAT_TYPE_IF_SCSI, DEVSTAT_PRIORITY_TAPE);
1522 
1523           make_dev(&sa_ops, SAMINOR(SA_CTLDEV,
1524               periph->unit_number, 0, SA_ATYPE_R), UID_ROOT, GID_OPERATOR,
1525               0660, "%s%d.ctl", periph->periph_name, periph->unit_number);
1526 
1527           make_dev(&sa_ops, SAMINOR(SA_NOT_CTLDEV,
1528               periph->unit_number, 0, SA_ATYPE_R), UID_ROOT, GID_OPERATOR,
1529               0660, "%s%d", periph->periph_name, periph->unit_number);
1530 
1531           make_dev(&sa_ops, SAMINOR(SA_NOT_CTLDEV,
1532               periph->unit_number, 0, SA_ATYPE_NR), UID_ROOT, GID_OPERATOR,
1533               0660, "n%s%d", periph->periph_name, periph->unit_number);
1534 
1535           make_dev(&sa_ops, SAMINOR(SA_NOT_CTLDEV,
1536               periph->unit_number, 0, SA_ATYPE_ER), UID_ROOT, GID_OPERATOR,
1537               0660, "e%s%d", periph->periph_name, periph->unit_number);
1538 
1539           for (i = 0; i < SA_NUM_MODES; i++) {
1540 
1541                     make_dev(&sa_ops,
1542                         SAMINOR(SA_NOT_CTLDEV, periph->unit_number, i, SA_ATYPE_R),
1543                         UID_ROOT, GID_OPERATOR, 0660, "%s%d.%d",
1544                         periph->periph_name, periph->unit_number, i);
1545 
1546                     make_dev(&sa_ops,
1547                         SAMINOR(SA_NOT_CTLDEV, periph->unit_number, i, SA_ATYPE_NR),
1548                         UID_ROOT, GID_OPERATOR, 0660, "n%s%d.%d",
1549                         periph->periph_name, periph->unit_number, i);
1550 
1551 
1552                     make_dev(&sa_ops,
1553                         SAMINOR(SA_NOT_CTLDEV, periph->unit_number, i, SA_ATYPE_ER),
1554                         UID_ROOT, GID_OPERATOR, 0660, "e%s%d.%d",
1555                         periph->periph_name, periph->unit_number, i);
1556           }
1557           cam_periph_lock(periph);
1558 
1559           /*
1560            * Add an async callback so that we get
1561            * notified if this device goes away.
1562            */
1563           xpt_register_async(AC_LOST_DEVICE, saasync, periph, periph->path);
1564 
1565           xpt_announce_periph(periph, NULL);
1566 
1567           return (CAM_REQ_CMP);
1568 }
1569 
1570 static void
sastart(struct cam_periph * periph,union ccb * start_ccb)1571 sastart(struct cam_periph *periph, union ccb *start_ccb)
1572 {
1573           struct sa_softc *softc;
1574 
1575           softc = (struct sa_softc *)periph->softc;
1576 
1577           CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sastart\n"));
1578 
1579 
1580           switch (softc->state) {
1581           case SA_STATE_NORMAL:
1582           {
1583                     /* Pull a buffer from the queue and get going on it */
1584                     struct buf *bp;
1585                     struct bio *bio;
1586 
1587                     /*
1588                      * See if there is a buf with work for us to do..
1589                      */
1590                     bio = bioq_first(&softc->bio_queue);
1591                     if (periph->immediate_priority <= periph->pinfo.priority) {
1592                               CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
1593                                                   ("queuing for immediate ccb\n"));
1594                               Set_CCB_Type(start_ccb, SA_CCB_WAITING);
1595                               SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
1596                                                     periph_links.sle);
1597                               periph->immediate_priority = CAM_PRIORITY_NONE;
1598                               wakeup(&periph->ccb_list);
1599                     } else if (bio == NULL) {
1600                               xpt_release_ccb(start_ccb);
1601                     } else if ((softc->flags & SA_FLAG_ERR_PENDING) != 0) {
1602                               struct bio *done_bio;
1603 again:
1604                               softc->queue_count--;
1605                               bioq_remove(&softc->bio_queue, bio);
1606                               bp = bio->bio_buf;
1607                               bp->b_resid = bp->b_bcount;
1608                               done_bio = bio;
1609                               if ((softc->flags & SA_FLAG_EOM_PENDING) != 0) {
1610                                         /*
1611                                          * We now just clear errors in this case
1612                                          * and let the residual be the notifier.
1613                                          */
1614                                         bp->b_error = 0;
1615                               } else if ((softc->flags & SA_FLAG_EOF_PENDING) != 0) {
1616                                         /*
1617                                          * This can only happen if we're reading
1618                                          * in fixed length mode. In this case,
1619                                          * we dump the rest of the list the
1620                                          * same way.
1621                                          */
1622                                         bp->b_error = 0;
1623                                         if (bioq_first(&softc->bio_queue) != NULL) {
1624                                                   biodone(done_bio);
1625                                                   goto again;
1626                                         }
1627                               } else if ((softc->flags & SA_FLAG_EIO_PENDING) != 0) {
1628                                         bp->b_error = EIO;
1629                                         bp->b_flags |= B_ERROR;
1630                               }
1631                               bio = bioq_first(&softc->bio_queue);
1632                               /*
1633                                * Only if we have no other buffers queued up
1634                                * do we clear the pending error flag.
1635                                */
1636                               if (bio == NULL)
1637                                         softc->flags &= ~SA_FLAG_ERR_PENDING;
1638                               CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
1639                                   ("sastart- ERR_PENDING now 0x%x, bio is %sNULL, "
1640                                   "%d more buffers queued up\n",
1641                                   (softc->flags & SA_FLAG_ERR_PENDING),
1642                                   (bio != NULL)? "not " : " ", softc->queue_count));
1643                               xpt_release_ccb(start_ccb);
1644                               biodone(done_bio);
1645                     } else {
1646                               u_int32_t length;
1647 
1648                               bioq_remove(&softc->bio_queue, bio);
1649                               bp = bio->bio_buf;
1650                               softc->queue_count--;
1651 
1652                               if ((softc->flags & SA_FLAG_FIXED) != 0) {
1653                                         if (softc->blk_shift != 0) {
1654                                                   length =
1655                                                       bp->b_bcount >> softc->blk_shift;
1656                                         } else if (softc->media_blksize != 0) {
1657                                                   length =
1658                                                       bp->b_bcount / softc->media_blksize;
1659                                         } else {
1660                                                   bp->b_error = EIO;
1661                                                   xpt_print(periph->path, "zero blocksize"
1662                                                       " for FIXED length writes?\n");
1663                                                   biodone(bio);
1664                                                   break;
1665                                         }
1666 #if       0
1667                                         CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO,
1668                                             ("issuing a %d fixed record %s\n",
1669                                             length,  (bp->bio_cmd == BIO_READ)? "read" :
1670                                             "write"));
1671 #endif
1672                               } else {
1673                                         length = bp->b_bcount;
1674 #if       0
1675                                         CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO,
1676                                             ("issuing a %d variable byte %s\n",
1677                                             length,  (bp->bio_cmd == BIO_READ)? "read" :
1678                                             "write"));
1679 #endif
1680                               }
1681                               devstat_start_transaction(&softc->device_stats);
1682                               /*
1683                                * Some people have theorized that we should
1684                                * suppress illegal length indication if we are
1685                                * running in variable block mode so that we don't
1686                                * have to request sense every time our requested
1687                                * block size is larger than the written block.
1688                                * The residual information from the ccb allows
1689                                * us to identify this situation anyway.  The only
1690                                * problem with this is that we will not get
1691                                * information about blocks that are larger than
1692                                * our read buffer unless we set the block size
1693                                * in the mode page to something other than 0.
1694                                *
1695                                * I believe that this is a non-issue. If user apps
1696                                * don't adjust their read size to match our record
1697                                * size, that's just life. Anyway, the typical usage
1698                                * would be to issue, e.g., 64KB reads and occasionally
1699                                * have to do deal with 512 byte or 1KB intermediate
1700                                * records.
1701                                */
1702                               softc->dsreg = (bp->b_cmd == BUF_CMD_READ) ?
1703                                   MTIO_DSREG_RD : MTIO_DSREG_WR;
1704                               scsi_sa_read_write(&start_ccb->csio, 0, sadone,
1705                                   MSG_SIMPLE_Q_TAG, (bp->b_cmd == BUF_CMD_READ) != 0,
1706                                   FALSE, (softc->flags & SA_FLAG_FIXED) != 0,
1707                                   length, bp->b_data, bp->b_bcount, SSD_FULL_SIZE,
1708                                   IO_TIMEOUT);
1709                               start_ccb->ccb_h.ccb_pflags &= ~SA_POSITION_UPDATED;
1710                               Set_CCB_Type(start_ccb, SA_CCB_BUFFER_IO);
1711                               start_ccb->ccb_h.ccb_bio = bio;
1712                               bio = bioq_first(&softc->bio_queue);
1713                               xpt_action(start_ccb);
1714                     }
1715 
1716                     if (bio != NULL) {
1717                               /* Have more work to do, so ensure we stay scheduled */
1718                               xpt_schedule(periph, 1);
1719                     }
1720                     break;
1721           }
1722           case SA_STATE_ABNORMAL:
1723           default:
1724                     panic("state 0x%x in sastart", softc->state);
1725                     break;
1726           }
1727 }
1728 
1729 
1730 static void
sadone(struct cam_periph * periph,union ccb * done_ccb)1731 sadone(struct cam_periph *periph, union ccb *done_ccb)
1732 {
1733           struct sa_softc *softc;
1734           struct ccb_scsiio *csio;
1735 
1736           softc = (struct sa_softc *)periph->softc;
1737           csio = &done_ccb->csio;
1738 
1739           switch (CCB_Type(csio)) {
1740           case SA_CCB_BUFFER_IO:
1741           {
1742                     struct buf *bp;
1743                     struct bio *bio;
1744                     int error;
1745 
1746                     softc->dsreg = MTIO_DSREG_REST;
1747                     bio = (struct bio *)done_ccb->ccb_h.ccb_bio;
1748                     bp = bio->bio_buf;
1749                     error = 0;
1750                     if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
1751                               if ((error = saerror(done_ccb, 0, 0)) == ERESTART) {
1752                                         /*
1753                                          * A retry was scheduled, so just return.
1754                                          */
1755                                         return;
1756                               }
1757                     }
1758 
1759                     if (error == EIO) {
1760                               struct buf *q_bp;
1761                               struct bio *q_bio;
1762 
1763                               /*
1764                                * Catastrophic error. Mark the tape as frozen
1765                                * (we no longer know tape position).
1766                                *
1767                                * Return all queued I/O with EIO, and unfreeze
1768                                * our queue so that future transactions that
1769                                * attempt to fix this problem can get to the
1770                                * device.
1771                                *
1772                                */
1773 
1774                               softc->flags |= SA_FLAG_TAPE_FROZEN;
1775                               while ((q_bio = bioq_takefirst(&softc->bio_queue)) != NULL) {
1776                                         q_bp = q_bio->bio_buf;
1777                                         q_bp->b_resid = q_bp->b_bcount;
1778                                         q_bp->b_error = EIO;
1779                                         q_bp->b_flags |= B_ERROR;
1780                                         biodone(q_bio);
1781                               }
1782                     }
1783                     if (error != 0) {
1784                               bp->b_resid = bp->b_bcount;
1785                               bp->b_error = error;
1786                               bp->b_flags |= B_ERROR;
1787                               /*
1788                                * In the error case, position is updated in saerror.
1789                                */
1790                     } else {
1791                               bp->b_resid = csio->resid;
1792                               bp->b_error = 0;
1793                               if (csio->resid != 0) {
1794                                         bp->b_flags |= B_ERROR;
1795                               }
1796                               if (bp->b_cmd != BUF_CMD_READ) {
1797                                         softc->flags |= SA_FLAG_TAPE_WRITTEN;
1798                                         softc->filemarks = 0;
1799                               }
1800                               if (!(csio->ccb_h.ccb_pflags & SA_POSITION_UPDATED) &&
1801                                   (softc->blkno != (daddr_t) -1)) {
1802                                         if ((softc->flags & SA_FLAG_FIXED) != 0) {
1803                                                   u_int32_t l;
1804                                                   if (softc->blk_shift != 0) {
1805                                                             l = bp->b_bcount >>
1806                                                                       softc->blk_shift;
1807                                                   } else {
1808                                                             l = bp->b_bcount /
1809                                                                       softc->media_blksize;
1810                                                   }
1811                                                   softc->blkno += (daddr_t) l;
1812                                         } else {
1813                                                   softc->blkno++;
1814                                         }
1815                               }
1816                     }
1817                     /*
1818                      * If we had an error (immediate or pending),
1819                      * release the device queue now.
1820                      */
1821                     if (error || (softc->flags & SA_FLAG_ERR_PENDING))
1822                               cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0);
1823 #ifdef    CAMDEBUG
1824                     if (error || bp->b_resid) {
1825                               CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
1826                                           ("error %d resid %d count %d\n", error,
1827                                           bp->b_resid, bp->b_bcount));
1828                     }
1829 #endif
1830                     devstat_end_transaction_buf(&softc->device_stats, bp);
1831                     biodone(bio);
1832                     break;
1833           }
1834           case SA_CCB_WAITING:
1835           {
1836                     /* Caller will release the CCB */
1837                     wakeup(&done_ccb->ccb_h.cbfcnp);
1838                     return;
1839           }
1840           case SA_CCB_POLLED:
1841                     /* polled, caller releases ccb */
1842                     wakeup(&done_ccb->ccb_h.cbfcnp);
1843                     return;
1844           }
1845           xpt_release_ccb(done_ccb);
1846 }
1847 
1848 /*
1849  * Mount the tape (make sure it's ready for I/O).
1850  *
1851  * oflags can be checked for 'kind' of open (read-only check) - later
1852  * dev can be checked for a control-mode or compression open - later
1853  */
1854 static int
samount(struct cam_periph * periph,__unused int oflags,__unused cdev_t dev)1855 samount(struct cam_periph *periph, __unused int oflags, __unused cdev_t dev)
1856 {
1857           struct    sa_softc *softc;
1858           union     ccb *ccb;
1859           int       error;
1860 
1861           softc = (struct sa_softc *)periph->softc;
1862 
1863           /*
1864            * This should determine if something has happend since the last
1865            * open/mount that would invalidate the mount. We do *not* want
1866            * to retry this command- we just want the status. But we only
1867            * do this if we're mounted already- if we're not mounted,
1868            * we don't care about the unit read state and can instead use
1869            * this opportunity to attempt to reserve the tape unit.
1870            */
1871 
1872           if (softc->flags & SA_FLAG_TAPE_MOUNTED) {
1873                     ccb = cam_periph_getccb(periph, 1);
1874                     Set_CCB_Type(ccb, SA_CCB_POLLED);
1875 
1876                     scsi_test_unit_ready(&ccb->csio, 0, sadone,
1877                                              MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE,
1878                                              IO_TIMEOUT);
1879                     error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
1880                                                     &softc->device_stats);
1881                     QFRLS(ccb);
1882                     if (error == ENXIO) {
1883                               softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
1884                               scsi_test_unit_ready(&ccb->csio, 0, sadone,
1885                                   MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE, IO_TIMEOUT);
1886                               error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
1887                                   &softc->device_stats);
1888                               QFRLS(ccb);
1889                     } else if (error) {
1890                               /*
1891                                * We don't need to freeze the tape because we
1892                                * will now attempt to rewind/load it.
1893                                */
1894                               softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
1895                               if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) {
1896                                         xpt_print(periph->path,
1897                                             "error %d on TUR in samount\n", error);
1898                               }
1899                     }
1900           } else {
1901                     error = sareservereleaseunit(periph, TRUE);
1902                     if (error) {
1903                               return (error);
1904                     }
1905                     ccb = cam_periph_getccb(periph, 1);
1906                     Set_CCB_Type(ccb, SA_CCB_POLLED);
1907                     scsi_test_unit_ready(&ccb->csio, 0, sadone,
1908                                              MSG_SIMPLE_Q_TAG, SSD_FULL_SIZE,
1909                                              IO_TIMEOUT);
1910                     error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
1911                                                     &softc->device_stats);
1912                     QFRLS(ccb);
1913           }
1914 
1915           if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) {
1916                     struct scsi_read_block_limits_data *rblim = NULL;
1917                     int comp_enabled = 0;                   /* silence gcc */
1918                     int comp_supported = 0;                 /* silence gcc */
1919                     u_int8_t write_protect = 0;   /* silence gcc */
1920                     u_int8_t guessing = 0;
1921 
1922                     /*
1923                      * Clear out old state.
1924                      */
1925                     softc->flags &= ~(SA_FLAG_TAPE_WP|SA_FLAG_TAPE_WRITTEN|
1926                                           SA_FLAG_ERR_PENDING|SA_FLAG_COMP_ENABLED|
1927                                           SA_FLAG_COMP_SUPP|SA_FLAG_COMP_UNSUPP);
1928                     softc->filemarks = 0;
1929 
1930                     /*
1931                      * *Very* first off, make sure we're loaded to BOT.
1932                      */
1933                     scsi_load_unload(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, FALSE,
1934                         FALSE, FALSE, 1, SSD_FULL_SIZE, REWIND_TIMEOUT);
1935                     error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
1936                         &softc->device_stats);
1937                     QFRLS(ccb);
1938 
1939                     /*
1940                      * In case this doesn't work, do a REWIND instead
1941                      */
1942                     if (error) {
1943                               scsi_rewind(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG,
1944                                   FALSE, SSD_FULL_SIZE, REWIND_TIMEOUT);
1945                               error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
1946                                         &softc->device_stats);
1947                               QFRLS(ccb);
1948                     }
1949                     if (error) {
1950                               xpt_release_ccb(ccb);
1951                               goto exit;
1952                     }
1953 
1954                     /*
1955                      * Do a dummy test read to force access to the
1956                      * media so that the drive will really know what's
1957                      * there. We actually don't really care what the
1958                      * blocksize on tape is and don't expect to really
1959                      * read a full record.
1960                      */
1961                     rblim = kmalloc(8192, M_SCSISA, M_INTWAIT);
1962 
1963                     if ((softc->quirks & SA_QUIRK_NODREAD) == 0) {
1964                               scsi_sa_read_write(&ccb->csio, 0, sadone,
1965                                   MSG_SIMPLE_Q_TAG, 1, FALSE, 0, 8192,
1966                                   (void *) rblim, 8192, SSD_FULL_SIZE,
1967                                   IO_TIMEOUT);
1968                               cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
1969                                   &softc->device_stats);
1970                               QFRLS(ccb);
1971                               scsi_rewind(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG,
1972                                   FALSE, SSD_FULL_SIZE, REWIND_TIMEOUT);
1973                               error = cam_periph_runccb(ccb, saerror, CAM_RETRY_SELTO,
1974                                   SF_NO_PRINT | SF_RETRY_UA,
1975                                   &softc->device_stats);
1976                               QFRLS(ccb);
1977                               if (error) {
1978                                         xpt_print(periph->path,
1979                                             "unable to rewind after test read\n");
1980                                         xpt_release_ccb(ccb);
1981                                         goto exit;
1982                               }
1983                     }
1984 
1985                     /*
1986                      * Next off, determine block limits.
1987                      */
1988                     scsi_read_block_limits(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG,
1989                         rblim, SSD_FULL_SIZE, SCSIOP_TIMEOUT);
1990 
1991                     error = cam_periph_runccb(ccb, saerror, CAM_RETRY_SELTO,
1992                         SF_NO_PRINT | SF_RETRY_UA, &softc->device_stats);
1993 
1994                     QFRLS(ccb);
1995                     xpt_release_ccb(ccb);
1996 
1997                     if (error != 0) {
1998                               /*
1999                                * If it's less than SCSI-2, READ BLOCK LIMITS is not
2000                                * a MANDATORY command. Anyway- it doesn't matter-
2001                                * we can proceed anyway.
2002                                */
2003                               softc->blk_gran = 0;
2004                               softc->max_blk = ~0;
2005                               softc->min_blk = 0;
2006                     } else {
2007                               if (softc->scsi_rev >= SCSI_REV_SPC) {
2008                                         softc->blk_gran = RBL_GRAN(rblim);
2009                               } else {
2010                                         softc->blk_gran = 0;
2011                               }
2012                               /*
2013                                * We take max_blk == min_blk to mean a default to
2014                                * fixed mode- but note that whatever we get out of
2015                                * sagetparams below will actually determine whether
2016                                * we are actually *in* fixed mode.
2017                                */
2018                               softc->max_blk = scsi_3btoul(rblim->maximum);
2019                               softc->min_blk = scsi_2btoul(rblim->minimum);
2020 
2021 
2022                     }
2023                     /*
2024                      * Next, perform a mode sense to determine
2025                      * current density, blocksize, compression etc.
2026                      */
2027                     error = sagetparams(periph, SA_PARAM_ALL,
2028                                             &softc->media_blksize,
2029                                             &softc->media_density,
2030                                             &softc->media_numblks,
2031                                             &softc->buffer_mode, &write_protect,
2032                                             &softc->speed, &comp_supported,
2033                                             &comp_enabled, &softc->comp_algorithm,
2034                                             NULL);
2035 
2036                     if (error != 0) {
2037                               /*
2038                                * We could work a little harder here. We could
2039                                * adjust our attempts to get information. It
2040                                * might be an ancient tape drive. If someone
2041                                * nudges us, we'll do that.
2042                                */
2043                               goto exit;
2044                     }
2045 
2046                     /*
2047                      * If no quirk has determined that this is a device that is
2048                      * preferred to be in fixed or variable mode, now is the time
2049                      * to find out.
2050                      */
2051                     if ((softc->quirks & (SA_QUIRK_FIXED|SA_QUIRK_VARIABLE)) == 0) {
2052                               guessing = 1;
2053                               /*
2054                                * This could be expensive to find out. Luckily we
2055                                * only need to do this once. If we start out in
2056                                * 'default' mode, try and set ourselves to one
2057                                * of the densities that would determine a wad
2058                                * of other stuff. Go from highest to lowest.
2059                                */
2060                               if (softc->media_density == SCSI_DEFAULT_DENSITY) {
2061                                         int i;
2062                                         static u_int8_t ctry[] = {
2063                                                   SCSI_DENSITY_HALFINCH_PE,
2064                                                   SCSI_DENSITY_HALFINCH_6250C,
2065                                                   SCSI_DENSITY_HALFINCH_6250,
2066                                                   SCSI_DENSITY_HALFINCH_1600,
2067                                                   SCSI_DENSITY_HALFINCH_800,
2068                                                   SCSI_DENSITY_QIC_4GB,
2069                                                   SCSI_DENSITY_QIC_2GB,
2070                                                   SCSI_DENSITY_QIC_525_320,
2071                                                   SCSI_DENSITY_QIC_150,
2072                                                   SCSI_DENSITY_QIC_120,
2073                                                   SCSI_DENSITY_QIC_24,
2074                                                   SCSI_DENSITY_QIC_11_9TRK,
2075                                                   SCSI_DENSITY_QIC_11_4TRK,
2076                                                   SCSI_DENSITY_QIC_1320,
2077                                                   SCSI_DENSITY_QIC_3080,
2078                                                   0
2079                                         };
2080                                         for (i = 0; ctry[i]; i++) {
2081                                                   error = sasetparams(periph,
2082                                                       SA_PARAM_DENSITY, 0, ctry[i],
2083                                                       0, SF_NO_PRINT);
2084                                                   if (error == 0) {
2085                                                             softc->media_density = ctry[i];
2086                                                             break;
2087                                                   }
2088                                         }
2089                               }
2090                               switch (softc->media_density) {
2091                               case SCSI_DENSITY_QIC_11_4TRK:
2092                               case SCSI_DENSITY_QIC_11_9TRK:
2093                               case SCSI_DENSITY_QIC_24:
2094                               case SCSI_DENSITY_QIC_120:
2095                               case SCSI_DENSITY_QIC_150:
2096                               case SCSI_DENSITY_QIC_525_320:
2097                               case SCSI_DENSITY_QIC_1320:
2098                               case SCSI_DENSITY_QIC_3080:
2099                                         softc->quirks &= ~SA_QUIRK_2FM;
2100                                         softc->quirks |= SA_QUIRK_FIXED|SA_QUIRK_1FM;
2101                                         softc->last_media_blksize = 512;
2102                                         break;
2103                               case SCSI_DENSITY_QIC_4GB:
2104                               case SCSI_DENSITY_QIC_2GB:
2105                                         softc->quirks &= ~SA_QUIRK_2FM;
2106                                         softc->quirks |= SA_QUIRK_FIXED|SA_QUIRK_1FM;
2107                                         softc->last_media_blksize = 1024;
2108                                         break;
2109                               default:
2110                                         softc->last_media_blksize =
2111                                             softc->media_blksize;
2112                                         softc->quirks |= SA_QUIRK_VARIABLE;
2113                                         break;
2114                               }
2115                     }
2116 
2117                     /*
2118                      * If no quirk has determined that this is a device that needs
2119                      * to have 2 Filemarks at EOD, now is the time to find out.
2120                      */
2121 
2122                     if ((softc->quirks & SA_QUIRK_2FM) == 0) {
2123                               switch (softc->media_density) {
2124                               case SCSI_DENSITY_HALFINCH_800:
2125                               case SCSI_DENSITY_HALFINCH_1600:
2126                               case SCSI_DENSITY_HALFINCH_6250:
2127                               case SCSI_DENSITY_HALFINCH_6250C:
2128                               case SCSI_DENSITY_HALFINCH_PE:
2129                                         softc->quirks &= ~SA_QUIRK_1FM;
2130                                         softc->quirks |= SA_QUIRK_2FM;
2131                                         break;
2132                               default:
2133                                         break;
2134                               }
2135                     }
2136 
2137                     /*
2138                      * Now validate that some info we got makes sense.
2139                      */
2140                     if ((softc->max_blk < softc->media_blksize) ||
2141                         (softc->min_blk > softc->media_blksize &&
2142                         softc->media_blksize)) {
2143                               xpt_print(periph->path,
2144                                   "BLOCK LIMITS (%d..%d) could not match current "
2145                                   "block settings (%d)- adjusting\n", softc->min_blk,
2146                                   softc->max_blk, softc->media_blksize);
2147                               softc->max_blk = softc->min_blk =
2148                                   softc->media_blksize;
2149                     }
2150 
2151                     /*
2152                      * Now put ourselves into the right frame of mind based
2153                      * upon quirks...
2154                      */
2155 tryagain:
2156                     /*
2157                      * If we want to be in FIXED mode and our current blocksize
2158                      * is not equal to our last blocksize (if nonzero), try and
2159                      * set ourselves to this last blocksize (as the 'preferred'
2160                      * block size).  The initial quirkmatch at registry sets the
2161                      * initial 'last' blocksize. If, for whatever reason, this
2162                      * 'last' blocksize is zero, set the blocksize to 512,
2163                      * or min_blk if that's larger.
2164                      */
2165                     if ((softc->quirks & SA_QUIRK_FIXED) &&
2166                         (softc->quirks & SA_QUIRK_NO_MODESEL) == 0 &&
2167                         (softc->media_blksize != softc->last_media_blksize)) {
2168                               softc->media_blksize = softc->last_media_blksize;
2169                               if (softc->media_blksize == 0) {
2170                                         softc->media_blksize = 512;
2171                                         if (softc->media_blksize < softc->min_blk) {
2172                                                   softc->media_blksize = softc->min_blk;
2173                                         }
2174                               }
2175                               error = sasetparams(periph, SA_PARAM_BLOCKSIZE,
2176                                   softc->media_blksize, 0, 0, SF_NO_PRINT);
2177                               if (error) {
2178                                         xpt_print(periph->path,
2179                                             "unable to set fixed blocksize to %d\n",
2180                                             softc->media_blksize);
2181                                         goto exit;
2182                               }
2183                     }
2184 
2185                     if ((softc->quirks & SA_QUIRK_VARIABLE) &&
2186                         (softc->media_blksize != 0)) {
2187                               softc->last_media_blksize = softc->media_blksize;
2188                               softc->media_blksize = 0;
2189                               error = sasetparams(periph, SA_PARAM_BLOCKSIZE,
2190                                   0, 0, 0, SF_NO_PRINT);
2191                               if (error) {
2192                                         /*
2193                                          * If this fails and we were guessing, just
2194                                          * assume that we got it wrong and go try
2195                                          * fixed block mode. Don't even check against
2196                                          * density code at this point.
2197                                          */
2198                                         if (guessing) {
2199                                                   softc->quirks &= ~SA_QUIRK_VARIABLE;
2200                                                   softc->quirks |= SA_QUIRK_FIXED;
2201                                                   if (softc->last_media_blksize == 0)
2202                                                             softc->last_media_blksize = 512;
2203                                                   goto tryagain;
2204                                         }
2205                                         xpt_print(periph->path,
2206                                             "unable to set variable blocksize\n");
2207                                         goto exit;
2208                               }
2209                     }
2210 
2211                     /*
2212                      * Now that we have the current block size,
2213                      * set up some parameters for sastart's usage.
2214                      */
2215                     if (softc->media_blksize) {
2216                               softc->flags |= SA_FLAG_FIXED;
2217                               if (powerof2(softc->media_blksize)) {
2218                                         softc->blk_shift =
2219                                             ffs(softc->media_blksize) - 1;
2220                                         softc->blk_mask = softc->media_blksize - 1;
2221                               } else {
2222                                         softc->blk_mask = ~0;
2223                                         softc->blk_shift = 0;
2224                               }
2225                     } else {
2226                               /*
2227                                * The SCSI-3 spec allows 0 to mean "unspecified".
2228                                * The SCSI-1 spec allows 0 to mean 'infinite'.
2229                                *
2230                                * Either works here.
2231                                */
2232                               if (softc->max_blk == 0) {
2233                                         softc->max_blk = ~0;
2234                               }
2235                               softc->blk_shift = 0;
2236                               if (softc->blk_gran != 0) {
2237                                         softc->blk_mask = softc->blk_gran - 1;
2238                               } else {
2239                                         softc->blk_mask = 0;
2240                               }
2241                     }
2242 
2243                     if (write_protect)
2244                               softc->flags |= SA_FLAG_TAPE_WP;
2245 
2246                     if (comp_supported) {
2247                               if (softc->saved_comp_algorithm == 0)
2248                                         softc->saved_comp_algorithm =
2249                                             softc->comp_algorithm;
2250                               softc->flags |= SA_FLAG_COMP_SUPP;
2251                               if (comp_enabled)
2252                                         softc->flags |= SA_FLAG_COMP_ENABLED;
2253                     } else
2254                               softc->flags |= SA_FLAG_COMP_UNSUPP;
2255 
2256                     if ((softc->buffer_mode == SMH_SA_BUF_MODE_NOBUF) &&
2257                         (softc->quirks & SA_QUIRK_NO_MODESEL) == 0) {
2258                               error = sasetparams(periph, SA_PARAM_BUFF_MODE, 0,
2259                                   0, 0, SF_NO_PRINT);
2260                               if (error == 0) {
2261                                         softc->buffer_mode = SMH_SA_BUF_MODE_SIBUF;
2262                               } else {
2263                                         xpt_print(periph->path,
2264                                             "unable to set buffered mode\n");
2265                               }
2266                               error = 0;          /* not an error */
2267                     }
2268 
2269 
2270                     if (error == 0) {
2271                               softc->flags |= SA_FLAG_TAPE_MOUNTED;
2272                     }
2273 exit:
2274                     if (rblim != NULL)
2275                               kfree(rblim, M_SCSISA);
2276 
2277                     if (error != 0) {
2278                               softc->dsreg = MTIO_DSREG_NIL;
2279                     } else {
2280                               softc->fileno = softc->blkno = 0;
2281                               softc->dsreg = MTIO_DSREG_REST;
2282                     }
2283 #ifdef    SA_1FM_AT_EOD
2284                     if ((softc->quirks & SA_QUIRK_2FM) == 0)
2285                               softc->quirks |= SA_QUIRK_1FM;
2286 #else
2287                     if ((softc->quirks & SA_QUIRK_1FM) == 0)
2288                               softc->quirks |= SA_QUIRK_2FM;
2289 #endif
2290           } else
2291                     xpt_release_ccb(ccb);
2292 
2293           /*
2294            * If we return an error, we're not mounted any more,
2295            * so release any device reservation.
2296            */
2297           if (error != 0) {
2298                     sareservereleaseunit(periph, FALSE);
2299           } else {
2300                     /*
2301                      * Clear I/O residual.
2302                      */
2303                     softc->last_io_resid = 0;
2304                     softc->last_ctl_resid = 0;
2305           }
2306           return (error);
2307 }
2308 
2309 /*
2310  * How many filemarks do we need to write if we were to terminate the
2311  * tape session right now? Note that this can be a negative number
2312  */
2313 
2314 static int
samarkswanted(struct cam_periph * periph)2315 samarkswanted(struct cam_periph *periph)
2316 {
2317           int       markswanted;
2318           struct    sa_softc *softc;
2319 
2320           softc = (struct sa_softc *)periph->softc;
2321           markswanted = 0;
2322           if ((softc->flags & SA_FLAG_TAPE_WRITTEN) != 0) {
2323                     markswanted++;
2324                     if (softc->quirks & SA_QUIRK_2FM)
2325                               markswanted++;
2326           }
2327           markswanted -= softc->filemarks;
2328           return (markswanted);
2329 }
2330 
2331 static int
sacheckeod(struct cam_periph * periph)2332 sacheckeod(struct cam_periph *periph)
2333 {
2334           int       error;
2335           int       markswanted;
2336 
2337           markswanted = samarkswanted(periph);
2338 
2339           if (markswanted > 0) {
2340                     error = sawritefilemarks(periph, markswanted, FALSE);
2341           } else {
2342                     error = 0;
2343           }
2344           return (error);
2345 }
2346 
2347 static int
saerror(union ccb * ccb,u_int32_t cflgs,u_int32_t sflgs)2348 saerror(union ccb *ccb, u_int32_t cflgs, u_int32_t sflgs)
2349 {
2350           static const char *toobig =
2351               "%d-byte tape record bigger than supplied buffer\n";
2352           struct    cam_periph *periph;
2353           struct    sa_softc *softc;
2354           struct    ccb_scsiio *csio;
2355           struct    scsi_sense_data *sense;
2356           u_int32_t resid = 0;
2357           int32_t   info = 0;
2358           cam_status status;
2359           int error_code, sense_key, asc, ascq, error, aqvalid;
2360 
2361           periph = xpt_path_periph(ccb->ccb_h.path);
2362           softc = (struct sa_softc *)periph->softc;
2363           csio = &ccb->csio;
2364           sense = &csio->sense_data;
2365           scsi_extract_sense(sense, &error_code, &sense_key, &asc, &ascq);
2366           aqvalid = sense->extra_len >= 6;
2367           error = 0;
2368 
2369           status = csio->ccb_h.status & CAM_STATUS_MASK;
2370 
2371           /*
2372            * Calculate/latch up, any residuals... We do this in a funny 2-step
2373            * so we can print stuff here if we have CAM_DEBUG enabled for this
2374            * unit.
2375            */
2376           if (status == CAM_SCSI_STATUS_ERROR) {
2377                     if ((sense->error_code & SSD_ERRCODE_VALID) != 0) {
2378                               info = (int32_t) scsi_4btoul(sense->info);
2379                               resid = info;
2380                               if ((softc->flags & SA_FLAG_FIXED) != 0)
2381                                         resid *= softc->media_blksize;
2382                     } else {
2383                               resid = csio->dxfer_len;
2384                               info = resid;
2385                               if ((softc->flags & SA_FLAG_FIXED) != 0) {
2386                                         if (softc->media_blksize)
2387                                                   info /= softc->media_blksize;
2388                               }
2389                     }
2390                     if (CCB_Type(csio) == SA_CCB_BUFFER_IO) {
2391                               bcopy((caddr_t) sense, (caddr_t) &softc->last_io_sense,
2392                                   sizeof (struct scsi_sense_data));
2393                               bcopy(csio->cdb_io.cdb_bytes, softc->last_io_cdb,
2394                                   (int) csio->cdb_len);
2395                               softc->last_io_resid = resid;
2396                               softc->last_resid_was_io = 1;
2397                     } else {
2398                               bcopy((caddr_t) sense, (caddr_t) &softc->last_ctl_sense,
2399                                   sizeof (struct scsi_sense_data));
2400                               bcopy(csio->cdb_io.cdb_bytes, softc->last_ctl_cdb,
2401                                   (int) csio->cdb_len);
2402                               softc->last_ctl_resid = resid;
2403                               softc->last_resid_was_io = 0;
2404                     }
2405                     CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("CDB[0]=0x%x Key 0x%x "
2406                         "ASC/ASCQ 0x%x/0x%x CAM STATUS 0x%x flags 0x%x resid %d "
2407                         "dxfer_len %d\n", csio->cdb_io.cdb_bytes[0] & 0xff,
2408                         sense_key, asc, ascq, status,
2409                         sense->flags & ~SSD_KEY_RESERVED, resid, csio->dxfer_len));
2410           } else {
2411                     CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
2412                         ("Cam Status 0x%x\n", status));
2413           }
2414 
2415           switch (status) {
2416           case CAM_REQ_CMP:
2417                     return (0);
2418           case CAM_SCSI_STATUS_ERROR:
2419                     /*
2420                      * If a read/write command, we handle it here.
2421                      */
2422                     if (CCB_Type(csio) != SA_CCB_WAITING) {
2423                               break;
2424                     }
2425                     /*
2426                      * If this was just EOM/EOP, Filemark, Setmark or ILI detected
2427                      * on a non read/write command, we assume it's not an error
2428                      * and propagate the residule and return.
2429                      */
2430                     if ((aqvalid && asc == 0 && ascq > 0 && ascq <= 5) ||
2431                         (aqvalid == 0 && sense_key == SSD_KEY_NO_SENSE)) {
2432                               csio->resid = resid;
2433                               QFRLS(ccb);
2434                               return (0);
2435                     }
2436                     /*
2437                      * Otherwise, we let the common code handle this.
2438                      */
2439                     return (cam_periph_error(ccb, cflgs, sflgs, &softc->saved_ccb));
2440 
2441           /*
2442            * XXX: To Be Fixed
2443            * We cannot depend upon CAM honoring retry counts for these.
2444            */
2445           case CAM_SCSI_BUS_RESET:
2446           case CAM_BDR_SENT:
2447                     if (ccb->ccb_h.retry_count <= 0) {
2448                               return (EIO);
2449                     }
2450                     /* FALLTHROUGH */
2451           default:
2452                     return (cam_periph_error(ccb, cflgs, sflgs, &softc->saved_ccb));
2453           }
2454 
2455           /*
2456            * Handle filemark, end of tape, mismatched record sizes....
2457            * From this point out, we're only handling read/write cases.
2458            * Handle writes && reads differently.
2459            */
2460 
2461           if (csio->cdb_io.cdb_bytes[0] == SA_WRITE) {
2462                     if (sense_key == SSD_KEY_VOLUME_OVERFLOW) {
2463                               csio->resid = resid;
2464                               error = ENOSPC;
2465                     } else if (sense->flags & SSD_EOM) {
2466                               softc->flags |= SA_FLAG_EOM_PENDING;
2467                               /*
2468                                * Grotesque as it seems, the few times
2469                                * I've actually seen a non-zero resid,
2470                                * the tape drive actually lied and had
2471                                * written all the data!.
2472                                */
2473                               csio->resid = 0;
2474                     }
2475           } else {
2476                     csio->resid = resid;
2477                     if (sense_key == SSD_KEY_BLANK_CHECK) {
2478                               if (softc->quirks & SA_QUIRK_1FM) {
2479                                         error = 0;
2480                                         softc->flags |= SA_FLAG_EOM_PENDING;
2481                               } else {
2482                                         error = EIO;
2483                               }
2484                     } else if (sense->flags & SSD_FILEMARK) {
2485                               if (softc->flags & SA_FLAG_FIXED) {
2486                                         error = -1;
2487                                         softc->flags |= SA_FLAG_EOF_PENDING;
2488                               }
2489                               /*
2490                                * Unconditionally, if we detected a filemark on a read,
2491                                * mark that we've run moved a file ahead.
2492                                */
2493                               if (softc->fileno != (daddr_t) -1) {
2494                                         softc->fileno++;
2495                                         softc->blkno = 0;
2496                                         csio->ccb_h.ccb_pflags |= SA_POSITION_UPDATED;
2497                               }
2498                     }
2499           }
2500 
2501           /*
2502            * Incorrect Length usually applies to read, but can apply to writes.
2503            */
2504           if (error == 0 && (sense->flags & SSD_ILI)) {
2505                     if (info < 0) {
2506                               xpt_print(csio->ccb_h.path, toobig,
2507                                   csio->dxfer_len - info);
2508                               csio->resid = csio->dxfer_len;
2509                               error = EIO;
2510                     } else {
2511                               csio->resid = resid;
2512                               if (softc->flags & SA_FLAG_FIXED) {
2513                                         softc->flags |= SA_FLAG_EIO_PENDING;
2514                               }
2515                               /*
2516                                * Bump the block number if we hadn't seen a filemark.
2517                                * Do this independent of errors (we've moved anyway).
2518                                */
2519                               if ((sense->flags & SSD_FILEMARK) == 0) {
2520                                         if (softc->blkno != (daddr_t) -1) {
2521                                                   softc->blkno++;
2522                                                   csio->ccb_h.ccb_pflags |=
2523                                                      SA_POSITION_UPDATED;
2524                                         }
2525                               }
2526                     }
2527           }
2528 
2529           if (error <= 0) {
2530                     /*
2531                      * Unfreeze the queue if frozen as we're not returning anything
2532                      * to our waiters that would indicate an I/O error has occurred
2533                      * (yet).
2534                      */
2535                     QFRLS(ccb);
2536                     error = 0;
2537           }
2538           return (error);
2539 }
2540 
2541 static int
sagetparams(struct cam_periph * periph,sa_params params_to_get,u_int32_t * blocksize,u_int8_t * density,u_int32_t * numblocks,int * buff_mode,u_int8_t * write_protect,u_int8_t * speed,int * comp_supported,int * comp_enabled,u_int32_t * comp_algorithm,sa_comp_t * tcs)2542 sagetparams(struct cam_periph *periph, sa_params params_to_get,
2543               u_int32_t *blocksize, u_int8_t *density, u_int32_t *numblocks,
2544               int *buff_mode, u_int8_t *write_protect, u_int8_t *speed,
2545               int *comp_supported, int *comp_enabled, u_int32_t *comp_algorithm,
2546               sa_comp_t *tcs)
2547 {
2548           union ccb *ccb;
2549           void *mode_buffer;
2550           struct scsi_mode_header_6 *mode_hdr;
2551           struct scsi_mode_blk_desc *mode_blk;
2552           int mode_buffer_len;
2553           struct sa_softc *softc;
2554           u_int8_t cpage;
2555           int error;
2556           cam_status status;
2557 
2558           softc = (struct sa_softc *)periph->softc;
2559           ccb = cam_periph_getccb(periph, 1);
2560           Set_CCB_Type(ccb, SA_CCB_POLLED);
2561           if (softc->quirks & SA_QUIRK_NO_CPAGE)
2562                     cpage = SA_DEVICE_CONFIGURATION_PAGE;
2563           else
2564                     cpage = SA_DATA_COMPRESSION_PAGE;
2565 
2566 retry:
2567           mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk);
2568 
2569           if (params_to_get & SA_PARAM_COMPRESSION) {
2570                     if (softc->quirks & SA_QUIRK_NOCOMP) {
2571                               *comp_supported = FALSE;
2572                               params_to_get &= ~SA_PARAM_COMPRESSION;
2573                     } else
2574                               mode_buffer_len += sizeof (sa_comp_t);
2575           }
2576 
2577           mode_buffer = kmalloc(mode_buffer_len, M_SCSISA, M_INTWAIT | M_ZERO);
2578           mode_hdr = (struct scsi_mode_header_6 *)mode_buffer;
2579           mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
2580 
2581           /* it is safe to retry this */
2582           scsi_mode_sense(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, FALSE,
2583               SMS_PAGE_CTRL_CURRENT, (params_to_get & SA_PARAM_COMPRESSION) ?
2584               cpage : SMS_VENDOR_SPECIFIC_PAGE, mode_buffer, mode_buffer_len,
2585               SSD_FULL_SIZE, SCSIOP_TIMEOUT);
2586 
2587           error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
2588               &softc->device_stats);
2589           QFRLS(ccb);
2590 
2591           status = ccb->ccb_h.status & CAM_STATUS_MASK;
2592 
2593           if (error == EINVAL && (params_to_get & SA_PARAM_COMPRESSION) != 0) {
2594                     /*
2595                      * Hmm. Let's see if we can try another page...
2596                      * If we've already done that, give up on compression
2597                      * for this device and remember this for the future
2598                      * and attempt the request without asking for compression
2599                      * info.
2600                      */
2601                     if (cpage == SA_DATA_COMPRESSION_PAGE) {
2602                               cpage = SA_DEVICE_CONFIGURATION_PAGE;
2603                               goto retry;
2604                     }
2605                     softc->quirks |= SA_QUIRK_NOCOMP;
2606                     kfree(mode_buffer, M_SCSISA);
2607                     goto retry;
2608           } else if (status == CAM_SCSI_STATUS_ERROR) {
2609                     /* Tell the user about the fatal error. */
2610                     scsi_sense_print(&ccb->csio);
2611                     goto sagetparamsexit;
2612           }
2613 
2614           /*
2615            * If the user only wants the compression information, and
2616            * the device doesn't send back the block descriptor, it's
2617            * no big deal.  If the user wants more than just
2618            * compression, though, and the device doesn't pass back the
2619            * block descriptor, we need to send another mode sense to
2620            * get the block descriptor.
2621            */
2622           if ((mode_hdr->blk_desc_len == 0) &&
2623               (params_to_get & SA_PARAM_COMPRESSION) &&
2624               (params_to_get & ~(SA_PARAM_COMPRESSION))) {
2625 
2626                     /*
2627                      * Decrease the mode buffer length by the size of
2628                      * the compression page, to make sure the data
2629                      * there doesn't get overwritten.
2630                      */
2631                     mode_buffer_len -= sizeof (sa_comp_t);
2632 
2633                     /*
2634                      * Now move the compression page that we presumably
2635                      * got back down the memory chunk a little bit so
2636                      * it doesn't get spammed.
2637                      */
2638                     bcopy(&mode_hdr[0], &mode_hdr[1], sizeof (sa_comp_t));
2639                     bzero(&mode_hdr[0], sizeof (mode_hdr[0]));
2640 
2641                     /*
2642                      * Now, we issue another mode sense and just ask
2643                      * for the block descriptor, etc.
2644                      */
2645 
2646                     scsi_mode_sense(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, FALSE,
2647                         SMS_PAGE_CTRL_CURRENT, SMS_VENDOR_SPECIFIC_PAGE,
2648                         mode_buffer, mode_buffer_len, SSD_FULL_SIZE,
2649                         SCSIOP_TIMEOUT);
2650 
2651                     error = cam_periph_runccb(ccb, saerror, 0, SF_NO_PRINT,
2652                         &softc->device_stats);
2653                     QFRLS(ccb);
2654 
2655                     if (error != 0)
2656                               goto sagetparamsexit;
2657           }
2658 
2659           if (params_to_get & SA_PARAM_BLOCKSIZE)
2660                     *blocksize = scsi_3btoul(mode_blk->blklen);
2661 
2662           if (params_to_get & SA_PARAM_NUMBLOCKS)
2663                     *numblocks = scsi_3btoul(mode_blk->nblocks);
2664 
2665           if (params_to_get & SA_PARAM_BUFF_MODE)
2666                     *buff_mode = mode_hdr->dev_spec & SMH_SA_BUF_MODE_MASK;
2667 
2668           if (params_to_get & SA_PARAM_DENSITY)
2669                     *density = mode_blk->density;
2670 
2671           if (params_to_get & SA_PARAM_WP)
2672                     *write_protect = (mode_hdr->dev_spec & SMH_SA_WP)? TRUE : FALSE;
2673 
2674           if (params_to_get & SA_PARAM_SPEED)
2675                     *speed = mode_hdr->dev_spec & SMH_SA_SPEED_MASK;
2676 
2677           if (params_to_get & SA_PARAM_COMPRESSION) {
2678                     sa_comp_t *ntcs = (sa_comp_t *) &mode_blk[1];
2679                     if (cpage == SA_DATA_COMPRESSION_PAGE) {
2680                               struct scsi_data_compression_page *cp = &ntcs->dcomp;
2681                               *comp_supported =
2682                                   (cp->dce_and_dcc & SA_DCP_DCC)? TRUE : FALSE;
2683                               *comp_enabled =
2684                                   (cp->dce_and_dcc & SA_DCP_DCE)? TRUE : FALSE;
2685                               *comp_algorithm = scsi_4btoul(cp->comp_algorithm);
2686                     } else {
2687                               struct scsi_dev_conf_page *cp = &ntcs->dconf;
2688                               /*
2689                                * We don't really know whether this device supports
2690                                * Data Compression if the the algorithm field is
2691                                * zero. Just say we do.
2692                                */
2693                               *comp_supported = TRUE;
2694                               *comp_enabled =
2695                                   (cp->sel_comp_alg != SA_COMP_NONE)? TRUE : FALSE;
2696                               *comp_algorithm = cp->sel_comp_alg;
2697                     }
2698                     if (tcs != NULL)
2699                               bcopy(ntcs, tcs, sizeof (sa_comp_t));
2700           }
2701 
2702           if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) {
2703                     int idx;
2704                     char *xyz = mode_buffer;
2705                     xpt_print_path(periph->path);
2706                     kprintf("Mode Sense Data=");
2707                     for (idx = 0; idx < mode_buffer_len; idx++)
2708                               kprintf(" 0x%02x", xyz[idx] & 0xff);
2709                     kprintf("\n");
2710           }
2711 
2712 sagetparamsexit:
2713 
2714           xpt_release_ccb(ccb);
2715           kfree(mode_buffer, M_SCSISA);
2716           return (error);
2717 }
2718 
2719 /*
2720  * The purpose of this function is to set one of four different parameters
2721  * for a tape drive:
2722  *        - blocksize
2723  *        - density
2724  *        - compression / compression algorithm
2725  *        - buffering mode
2726  *
2727  * The assumption is that this will be called from saioctl(), and therefore
2728  * from a process context.  Thus the waiting malloc calls below.  If that
2729  * assumption ever changes, the malloc calls should be changed to be
2730  * NOWAIT mallocs.
2731  *
2732  * Any or all of the four parameters may be set when this function is
2733  * called.  It should handle setting more than one parameter at once.
2734  */
2735 static int
sasetparams(struct cam_periph * periph,sa_params params_to_set,u_int32_t blocksize,u_int8_t density,u_int32_t calg,u_int32_t sense_flags)2736 sasetparams(struct cam_periph *periph, sa_params params_to_set,
2737               u_int32_t blocksize, u_int8_t density, u_int32_t calg,
2738               u_int32_t sense_flags)
2739 {
2740           struct sa_softc *softc;
2741           u_int32_t current_blocksize = 0;/* silence gcc */
2742           u_int32_t current_calg;
2743           u_int8_t current_density = 0; /* silence gcc */
2744           u_int8_t current_speed = 0;   /* silence gcc */
2745           int comp_enabled, comp_supported;
2746           void *mode_buffer;
2747           int mode_buffer_len;
2748           struct scsi_mode_header_6 *mode_hdr;
2749           struct scsi_mode_blk_desc *mode_blk;
2750           sa_comp_t *ccomp, *cpage;
2751           int buff_mode;
2752           union ccb *ccb = NULL;
2753           int error;
2754 
2755           softc = (struct sa_softc *)periph->softc;
2756 
2757           ccomp = kmalloc(sizeof (sa_comp_t), M_SCSISA, M_INTWAIT);
2758 
2759           /*
2760            * Since it doesn't make sense to set the number of blocks, or
2761            * write protection, we won't try to get the current value.  We
2762            * always want to get the blocksize, so we can set it back to the
2763            * proper value.
2764            */
2765           error = sagetparams(periph,
2766               params_to_set | SA_PARAM_BLOCKSIZE | SA_PARAM_SPEED,
2767               &current_blocksize, &current_density, NULL, &buff_mode, NULL,
2768               &current_speed, &comp_supported, &comp_enabled,
2769               &current_calg, ccomp);
2770 
2771           if (error != 0) {
2772                     kfree(ccomp, M_SCSISA);
2773                     return (error);
2774           }
2775 
2776           mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk);
2777           if (params_to_set & SA_PARAM_COMPRESSION)
2778                     mode_buffer_len += sizeof (sa_comp_t);
2779 
2780           mode_buffer = kmalloc(mode_buffer_len, M_SCSISA, M_INTWAIT | M_ZERO);
2781 
2782           mode_hdr = (struct scsi_mode_header_6 *)mode_buffer;
2783           mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
2784 
2785           ccb = cam_periph_getccb(periph, 1);
2786           Set_CCB_Type(ccb, SA_CCB_POLLED);
2787 
2788 retry:
2789 
2790           if (params_to_set & SA_PARAM_COMPRESSION) {
2791                     if (mode_blk) {
2792                               cpage = (sa_comp_t *)&mode_blk[1];
2793                     } else {
2794                               cpage = (sa_comp_t *)&mode_hdr[1];
2795                     }
2796                     bcopy(ccomp, cpage, sizeof (sa_comp_t));
2797                     cpage->hdr.pagecode &= ~0x80;
2798           } else
2799                     cpage = NULL;
2800 
2801           /*
2802            * If the caller wants us to set the blocksize, use the one they
2803            * pass in.  Otherwise, use the blocksize we got back from the
2804            * mode select above.
2805            */
2806           if (mode_blk) {
2807                     if (params_to_set & SA_PARAM_BLOCKSIZE)
2808                               scsi_ulto3b(blocksize, mode_blk->blklen);
2809                     else
2810                               scsi_ulto3b(current_blocksize, mode_blk->blklen);
2811 
2812                     /*
2813                      * Set density if requested, else preserve old density.
2814                      * SCSI_SAME_DENSITY only applies to SCSI-2 or better
2815                      * devices, else density we've latched up in our softc.
2816                      */
2817                     if (params_to_set & SA_PARAM_DENSITY) {
2818                               mode_blk->density = density;
2819                     } else if (softc->scsi_rev > SCSI_REV_CCS) {
2820                               mode_blk->density = SCSI_SAME_DENSITY;
2821                     } else {
2822                               mode_blk->density = softc->media_density;
2823                     }
2824           }
2825 
2826           /*
2827            * For mode selects, these two fields must be zero.
2828            */
2829           mode_hdr->data_length = 0;
2830           mode_hdr->medium_type = 0;
2831 
2832           /* set the speed to the current value */
2833           mode_hdr->dev_spec = current_speed;
2834 
2835           /* if set, set single-initiator buffering mode */
2836           if (softc->buffer_mode == SMH_SA_BUF_MODE_SIBUF) {
2837                     mode_hdr->dev_spec |= SMH_SA_BUF_MODE_SIBUF;
2838           }
2839 
2840           if (mode_blk)
2841                     mode_hdr->blk_desc_len = sizeof(struct scsi_mode_blk_desc);
2842           else
2843                     mode_hdr->blk_desc_len = 0;
2844 
2845           /*
2846            * First, if the user wants us to set the compression algorithm or
2847            * just turn compression on, check to make sure that this drive
2848            * supports compression.
2849            */
2850           if (params_to_set & SA_PARAM_COMPRESSION) {
2851                     /*
2852                      * If the compression algorithm is 0, disable compression.
2853                      * If the compression algorithm is non-zero, enable
2854                      * compression and set the compression type to the
2855                      * specified compression algorithm, unless the algorithm is
2856                      * MT_COMP_ENABLE.  In that case, we look at the
2857                      * compression algorithm that is currently set and if it is
2858                      * non-zero, we leave it as-is.  If it is zero, and we have
2859                      * saved a compression algorithm from a time when
2860                      * compression was enabled before, set the compression to
2861                      * the saved value.
2862                      */
2863                     switch (ccomp->hdr.pagecode & ~0x80) {
2864                     case SA_DEVICE_CONFIGURATION_PAGE:
2865                     {
2866                               struct scsi_dev_conf_page *dcp = &cpage->dconf;
2867                               if (calg == 0) {
2868                                         dcp->sel_comp_alg = SA_COMP_NONE;
2869                                         break;
2870                               }
2871                               if (calg != MT_COMP_ENABLE) {
2872                                         dcp->sel_comp_alg = calg;
2873                               } else if (dcp->sel_comp_alg == SA_COMP_NONE &&
2874                                   softc->saved_comp_algorithm != 0) {
2875                                         dcp->sel_comp_alg = softc->saved_comp_algorithm;
2876                               }
2877                               break;
2878                     }
2879                     case SA_DATA_COMPRESSION_PAGE:
2880                     if (ccomp->dcomp.dce_and_dcc & SA_DCP_DCC) {
2881                               struct scsi_data_compression_page *dcp = &cpage->dcomp;
2882                               if (calg == 0) {
2883                                         /*
2884                                          * Disable compression, but leave the
2885                                          * decompression and the capability bit
2886                                          * alone.
2887                                          */
2888                                         dcp->dce_and_dcc = SA_DCP_DCC;
2889                                         dcp->dde_and_red |= SA_DCP_DDE;
2890                                         break;
2891                               }
2892                               /* enable compression && decompression */
2893                               dcp->dce_and_dcc = SA_DCP_DCE | SA_DCP_DCC;
2894                               dcp->dde_and_red |= SA_DCP_DDE;
2895                               /*
2896                                * If there, use compression algorithm from caller.
2897                                * Otherwise, if there's a saved compression algorithm
2898                                * and there is no current algorithm, use the saved
2899                                * algorithm. Else parrot back what we got and hope
2900                                * for the best.
2901                                */
2902                               if (calg != MT_COMP_ENABLE) {
2903                                         scsi_ulto4b(calg, dcp->comp_algorithm);
2904                                         scsi_ulto4b(calg, dcp->decomp_algorithm);
2905                               } else if (scsi_4btoul(dcp->comp_algorithm) == 0 &&
2906                                   softc->saved_comp_algorithm != 0) {
2907                                         scsi_ulto4b(softc->saved_comp_algorithm,
2908                                             dcp->comp_algorithm);
2909                                         scsi_ulto4b(softc->saved_comp_algorithm,
2910                                             dcp->decomp_algorithm);
2911                               }
2912                               break;
2913                     }
2914                     /*
2915                      * Compression does not appear to be supported-
2916                      * at least via the DATA COMPRESSION page. It
2917                      * would be too much to ask us to believe that
2918                      * the page itself is supported, but incorrectly
2919                      * reports an ability to manipulate data compression,
2920                      * so we'll assume that this device doesn't support
2921                      * compression. We can just fall through for that.
2922                      */
2923                     /* FALLTHROUGH */
2924                     default:
2925                               /*
2926                                * The drive doesn't seem to support compression,
2927                                * so turn off the set compression bit.
2928                                */
2929                               params_to_set &= ~SA_PARAM_COMPRESSION;
2930                               xpt_print(periph->path,
2931                                   "device does not seem to support compression\n");
2932 
2933                               /*
2934                                * If that was the only thing the user wanted us to set,
2935                                * clean up allocated resources and return with
2936                                * 'operation not supported'.
2937                                */
2938                               if (params_to_set == SA_PARAM_NONE) {
2939                                         kfree(mode_buffer, M_SCSISA);
2940                                         xpt_release_ccb(ccb);
2941                                         return (ENODEV);
2942                               }
2943 
2944                               /*
2945                                * That wasn't the only thing the user wanted us to set.
2946                                * So, decrease the stated mode buffer length by the
2947                                * size of the compression mode page.
2948                                */
2949                               mode_buffer_len -= sizeof(sa_comp_t);
2950                     }
2951           }
2952 
2953           /* It is safe to retry this operation */
2954           scsi_mode_select(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG,
2955               (params_to_set & SA_PARAM_COMPRESSION)? TRUE : FALSE,
2956               FALSE, mode_buffer, mode_buffer_len, SSD_FULL_SIZE, SCSIOP_TIMEOUT);
2957 
2958           error = cam_periph_runccb(ccb, saerror, 0,
2959               sense_flags, &softc->device_stats);
2960           QFRLS(ccb);
2961 
2962           if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) {
2963                     int idx;
2964                     char *xyz = mode_buffer;
2965                     xpt_print_path(periph->path);
2966                     kprintf("Err%d, Mode Select Data=", error);
2967                     for (idx = 0; idx < mode_buffer_len; idx++)
2968                               kprintf(" 0x%02x", xyz[idx] & 0xff);
2969                     kprintf("\n");
2970           }
2971 
2972 
2973           if (error) {
2974                     /*
2975                      * If we can, try without setting density/blocksize.
2976                      */
2977                     if (mode_blk) {
2978                               if ((params_to_set &
2979                                   (SA_PARAM_DENSITY|SA_PARAM_BLOCKSIZE)) == 0) {
2980                                         mode_blk = NULL;
2981                                         goto retry;
2982                               }
2983                     } else {
2984                               mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
2985                               cpage = (sa_comp_t *)&mode_blk[1];
2986                     }
2987 
2988                     /*
2989                      * If we were setting the blocksize, and that failed, we
2990                      * want to set it to its original value.  If we weren't
2991                      * setting the blocksize, we don't want to change it.
2992                      */
2993                     scsi_ulto3b(current_blocksize, mode_blk->blklen);
2994 
2995                     /*
2996                      * Set density if requested, else preserve old density.
2997                      * SCSI_SAME_DENSITY only applies to SCSI-2 or better
2998                      * devices, else density we've latched up in our softc.
2999                      */
3000                     if (params_to_set & SA_PARAM_DENSITY) {
3001                               mode_blk->density = current_density;
3002                     } else if (softc->scsi_rev > SCSI_REV_CCS) {
3003                               mode_blk->density = SCSI_SAME_DENSITY;
3004                     } else {
3005                               mode_blk->density = softc->media_density;
3006                     }
3007 
3008                     if (params_to_set & SA_PARAM_COMPRESSION)
3009                               bcopy(ccomp, cpage, sizeof (sa_comp_t));
3010 
3011                     /*
3012                      * The retry count is the only CCB field that might have been
3013                      * changed that we care about, so reset it back to 1.
3014                      */
3015                     ccb->ccb_h.retry_count = 1;
3016                     cam_periph_runccb(ccb, saerror, 0, sense_flags,
3017                         &softc->device_stats);
3018                     QFRLS(ccb);
3019           }
3020 
3021           xpt_release_ccb(ccb);
3022 
3023           if (ccomp != NULL)
3024                     kfree(ccomp, M_SCSISA);
3025 
3026           if (params_to_set & SA_PARAM_COMPRESSION) {
3027                     if (error) {
3028                               softc->flags &= ~SA_FLAG_COMP_ENABLED;
3029                               /*
3030                                * Even if we get an error setting compression,
3031                                * do not say that we don't support it. We could
3032                                * have been wrong, or it may be media specific.
3033                                *        softc->flags &= ~SA_FLAG_COMP_SUPP;
3034                                */
3035                               softc->saved_comp_algorithm = softc->comp_algorithm;
3036                               softc->comp_algorithm = 0;
3037                     } else {
3038                               softc->flags |= SA_FLAG_COMP_ENABLED;
3039                               softc->comp_algorithm = calg;
3040                     }
3041           }
3042 
3043           kfree(mode_buffer, M_SCSISA);
3044           return (error);
3045 }
3046 
3047 static void
saprevent(struct cam_periph * periph,int action)3048 saprevent(struct cam_periph *periph, int action)
3049 {
3050           struct    sa_softc *softc;
3051           union     ccb *ccb;
3052           int       error, sf;
3053 
3054           softc = (struct sa_softc *)periph->softc;
3055 
3056           if ((action == PR_ALLOW) && (softc->flags & SA_FLAG_TAPE_LOCKED) == 0)
3057                     return;
3058           if ((action == PR_PREVENT) && (softc->flags & SA_FLAG_TAPE_LOCKED) != 0)
3059                     return;
3060 
3061           /*
3062            * We can be quiet about illegal requests.
3063            */
3064           if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) {
3065                     sf = 0;
3066           } else
3067                     sf = SF_QUIET_IR;
3068 
3069           ccb = cam_periph_getccb(periph, 1);
3070           Set_CCB_Type(ccb, SA_CCB_POLLED);
3071 
3072           /* It is safe to retry this operation */
3073           scsi_prevent(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, action,
3074               SSD_FULL_SIZE, SCSIOP_TIMEOUT);
3075 
3076           error = cam_periph_runccb(ccb, saerror, 0, sf, &softc->device_stats);
3077           QFRLS(ccb);
3078           if (error == 0) {
3079                     if (action == PR_ALLOW)
3080                               softc->flags &= ~SA_FLAG_TAPE_LOCKED;
3081                     else
3082                               softc->flags |= SA_FLAG_TAPE_LOCKED;
3083           }
3084 
3085           xpt_release_ccb(ccb);
3086 }
3087 
3088 static int
sarewind(struct cam_periph * periph)3089 sarewind(struct cam_periph *periph)
3090 {
3091           union     ccb *ccb;
3092           struct    sa_softc *softc;
3093           int       error;
3094 
3095           softc = (struct sa_softc *)periph->softc;
3096 
3097           ccb = cam_periph_getccb(periph, 1);
3098           Set_CCB_Type(ccb, SA_CCB_POLLED);
3099 
3100           /* It is safe to retry this operation */
3101           scsi_rewind(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG, FALSE,
3102               SSD_FULL_SIZE, REWIND_TIMEOUT);
3103 
3104           softc->dsreg = MTIO_DSREG_REW;
3105           error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
3106           softc->dsreg = MTIO_DSREG_REST;
3107 
3108           if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
3109                     cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE);
3110 
3111           xpt_release_ccb(ccb);
3112           if (error == 0)
3113                     softc->fileno = softc->blkno = (daddr_t) 0;
3114           else
3115                     softc->fileno = softc->blkno = (daddr_t) -1;
3116           return (error);
3117 }
3118 
3119 static int
saspace(struct cam_periph * periph,int count,scsi_space_code code)3120 saspace(struct cam_periph *periph, int count, scsi_space_code code)
3121 {
3122           union     ccb *ccb;
3123           struct    sa_softc *softc;
3124           int       error;
3125 
3126           softc = (struct sa_softc *)periph->softc;
3127 
3128           ccb = cam_periph_getccb(periph, 1);
3129           Set_CCB_Type(ccb, SA_CCB_POLLED);
3130 
3131           /* This cannot be retried */
3132 
3133           scsi_space(&ccb->csio, 0, sadone, MSG_SIMPLE_Q_TAG, code, count,
3134               SSD_FULL_SIZE, SPACE_TIMEOUT);
3135 
3136           /*
3137            * Clear residual because we will be using it.
3138            */
3139           softc->last_ctl_resid = 0;
3140 
3141           softc->dsreg = (count < 0)? MTIO_DSREG_REV : MTIO_DSREG_FWD;
3142           error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
3143           softc->dsreg = MTIO_DSREG_REST;
3144 
3145           if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
3146                     cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE);
3147 
3148           xpt_release_ccb(ccb);
3149 
3150           /*
3151            * If a spacing operation has failed, we need to invalidate
3152            * this mount.
3153            *
3154            * If the spacing operation was setmarks or to end of recorded data,
3155            * we no longer know our relative position.
3156            *
3157            * If the spacing operations was spacing files in reverse, we
3158            * take account of the residual, but still check against less
3159            * than zero- if we've gone negative, we must have hit BOT.
3160            *
3161            * If the spacing operations was spacing records in reverse and
3162            * we have a residual, we've either hit BOT or hit a filemark.
3163            * In the former case, we know our new record number (0). In
3164            * the latter case, we have absolutely no idea what the real
3165            * record number is- we've stopped between the end of the last
3166            * record in the previous file and the filemark that stopped
3167            * our spacing backwards.
3168            */
3169           if (error) {
3170                     softc->fileno = softc->blkno = (daddr_t) -1;
3171           } else if (code == SS_SETMARKS || code == SS_EOD) {
3172                     softc->fileno = softc->blkno = (daddr_t) -1;
3173           } else if (code == SS_FILEMARKS && softc->fileno != (daddr_t) -1) {
3174                     softc->fileno += (count - softc->last_ctl_resid);
3175                     if (softc->fileno < 0)        /* we must of hit BOT */
3176                               softc->fileno = 0;
3177                     softc->blkno = 0;
3178           } else if (code == SS_BLOCKS && softc->blkno != (daddr_t) -1) {
3179                     softc->blkno += (count - softc->last_ctl_resid);
3180                     if (count < 0) {
3181                               if (softc->last_ctl_resid || softc->blkno < 0) {
3182                                         if (softc->fileno == 0) {
3183                                                   softc->blkno = 0;
3184                                         } else {
3185                                                   softc->blkno = (daddr_t) -1;
3186                                         }
3187                               }
3188                     }
3189           }
3190           return (error);
3191 }
3192 
3193 static int
sawritefilemarks(struct cam_periph * periph,int nmarks,int setmarks)3194 sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks)
3195 {
3196           union     ccb *ccb;
3197           struct    sa_softc *softc;
3198           int       error, nwm = 0;
3199 
3200           softc = (struct sa_softc *)periph->softc;
3201           if (softc->open_rdonly)
3202                     return (EBADF);
3203 
3204           ccb = cam_periph_getccb(periph, 1);
3205           Set_CCB_Type(ccb, SA_CCB_POLLED);
3206 
3207           /*
3208            * Clear residual because we will be using it.
3209            */
3210           softc->last_ctl_resid = 0;
3211 
3212           softc->dsreg = MTIO_DSREG_FMK;
3213           /* this *must* not be retried */
3214           scsi_write_filemarks(&ccb->csio, 0, sadone, MSG_SIMPLE_Q_TAG,
3215               FALSE, setmarks, nmarks, SSD_FULL_SIZE, IO_TIMEOUT);
3216           softc->dsreg = MTIO_DSREG_REST;
3217 
3218 
3219           error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
3220 
3221           if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
3222                     cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE);
3223 
3224           if (error == 0 && nmarks) {
3225                     struct sa_softc *softc = (struct sa_softc *)periph->softc;
3226                     nwm = nmarks - softc->last_ctl_resid;
3227                     softc->filemarks += nwm;
3228           }
3229 
3230           xpt_release_ccb(ccb);
3231 
3232           /*
3233            * Update relative positions (if we're doing that).
3234            */
3235           if (error) {
3236                     softc->fileno = softc->blkno = (daddr_t) -1;
3237           } else if (softc->fileno != (daddr_t) -1) {
3238                     softc->fileno += nwm;
3239                     softc->blkno = 0;
3240           }
3241           return (error);
3242 }
3243 
3244 static int
sardpos(struct cam_periph * periph,int hard,u_int32_t * blkptr)3245 sardpos(struct cam_periph *periph, int hard, u_int32_t *blkptr)
3246 {
3247           struct scsi_tape_position_data loc;
3248           union ccb *ccb;
3249           struct sa_softc *softc = (struct sa_softc *)periph->softc;
3250           int error;
3251 
3252           /*
3253            * We try and flush any buffered writes here if we were writing
3254            * and we're trying to get hardware block position. It eats
3255            * up performance substantially, but I'm wary of drive firmware.
3256            *
3257            * I think that *logical* block position is probably okay-
3258            * but hardware block position might have to wait for data
3259            * to hit media to be valid. Caveat Emptor.
3260            */
3261 
3262           if (hard && (softc->flags & SA_FLAG_TAPE_WRITTEN)) {
3263                     error = sawritefilemarks(periph, 0, 0);
3264                     if (error && error != EACCES)
3265                               return (error);
3266           }
3267 
3268           ccb = cam_periph_getccb(periph, 1);
3269           Set_CCB_Type(ccb, SA_CCB_POLLED);
3270           scsi_read_position(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG,
3271                                  hard, &loc, SSD_FULL_SIZE, SCSIOP_TIMEOUT);
3272           softc->dsreg = MTIO_DSREG_RBSY;
3273           error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
3274           softc->dsreg = MTIO_DSREG_REST;
3275           if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
3276                     cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
3277 
3278           if (error == 0) {
3279                     if (loc.flags & SA_RPOS_UNCERTAIN) {
3280                               error = EINVAL;               /* nothing is certain */
3281                     } else {
3282                               *blkptr = scsi_4btoul(loc.firstblk);
3283                     }
3284           }
3285 
3286           xpt_release_ccb(ccb);
3287           return (error);
3288 }
3289 
3290 static int
sasetpos(struct cam_periph * periph,int hard,u_int32_t * blkptr)3291 sasetpos(struct cam_periph *periph, int hard, u_int32_t *blkptr)
3292 {
3293           union ccb *ccb;
3294           struct sa_softc *softc;
3295           int error;
3296 
3297           /*
3298            * We used to try and flush any buffered writes here.
3299            * Now we push this onto user applications to either
3300            * flush the pending writes themselves (via a zero count
3301            * WRITE FILEMARKS command) or they can trust their tape
3302            * drive to do this correctly for them.
3303            */
3304 
3305           softc = (struct sa_softc *)periph->softc;
3306           ccb = cam_periph_getccb(periph, 1);
3307           Set_CCB_Type(ccb, SA_CCB_POLLED);
3308 
3309           scsi_set_position(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG,
3310               hard, *blkptr, SSD_FULL_SIZE, SPACE_TIMEOUT);
3311 
3312 
3313           softc->dsreg = MTIO_DSREG_POS;
3314           error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
3315           softc->dsreg = MTIO_DSREG_REST;
3316           if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
3317                     cam_release_devq(ccb->ccb_h.path, 0, 0, 0, 0);
3318           xpt_release_ccb(ccb);
3319           /*
3320            * Note relative file && block number position as now unknown.
3321            */
3322           softc->fileno = softc->blkno = (daddr_t) -1;
3323           return (error);
3324 }
3325 
3326 static int
saretension(struct cam_periph * periph)3327 saretension(struct cam_periph *periph)
3328 {
3329           union ccb *ccb;
3330           struct sa_softc *softc;
3331           int error;
3332 
3333           softc = (struct sa_softc *)periph->softc;
3334 
3335           ccb = cam_periph_getccb(periph, 1);
3336           Set_CCB_Type(ccb, SA_CCB_POLLED);
3337 
3338           /* It is safe to retry this operation */
3339           scsi_load_unload(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, FALSE,
3340               FALSE, TRUE,  TRUE, SSD_FULL_SIZE, ERASE_TIMEOUT);
3341 
3342           softc->dsreg = MTIO_DSREG_TEN;
3343           error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
3344           softc->dsreg = MTIO_DSREG_REST;
3345 
3346           if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
3347                     cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE);
3348           xpt_release_ccb(ccb);
3349           if (error == 0)
3350                     softc->fileno = softc->blkno = (daddr_t) 0;
3351           else
3352                     softc->fileno = softc->blkno = (daddr_t) -1;
3353           return (error);
3354 }
3355 
3356 static int
sareservereleaseunit(struct cam_periph * periph,int reserve)3357 sareservereleaseunit(struct cam_periph *periph, int reserve)
3358 {
3359           union ccb *ccb;
3360           struct sa_softc *softc;
3361           int error;
3362 
3363           softc = (struct sa_softc *)periph->softc;
3364           ccb = cam_periph_getccb(periph,  1);
3365           Set_CCB_Type(ccb, SA_CCB_POLLED);
3366 
3367           /* It is safe to retry this operation */
3368           scsi_reserve_release_unit(&ccb->csio, 2, sadone, MSG_SIMPLE_Q_TAG,
3369               FALSE,  0, SSD_FULL_SIZE,  SCSIOP_TIMEOUT, reserve);
3370           softc->dsreg = MTIO_DSREG_RBSY;
3371           error = cam_periph_runccb(ccb, saerror, 0,
3372               SF_RETRY_UA | SF_NO_PRINT, &softc->device_stats);
3373           softc->dsreg = MTIO_DSREG_REST;
3374           QFRLS(ccb);
3375           xpt_release_ccb(ccb);
3376 
3377           /*
3378            * If the error was Illegal Request, then the device doesn't support
3379            * RESERVE/RELEASE. This is not an error.
3380            */
3381           if (error == EINVAL) {
3382                     error = 0;
3383           }
3384 
3385           return (error);
3386 }
3387 
3388 static int
saloadunload(struct cam_periph * periph,int load)3389 saloadunload(struct cam_periph *periph, int load)
3390 {
3391           union     ccb *ccb;
3392           struct    sa_softc *softc;
3393           int       error;
3394 
3395           softc = (struct sa_softc *)periph->softc;
3396 
3397           ccb = cam_periph_getccb(periph, 1);
3398           Set_CCB_Type(ccb, SA_CCB_POLLED);
3399 
3400           /* It is safe to retry this operation */
3401           scsi_load_unload(&ccb->csio, 5, sadone, MSG_SIMPLE_Q_TAG, FALSE,
3402               FALSE, FALSE, load, SSD_FULL_SIZE, REWIND_TIMEOUT);
3403 
3404           softc->dsreg = (load)? MTIO_DSREG_LD : MTIO_DSREG_UNL;
3405           error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
3406           softc->dsreg = MTIO_DSREG_REST;
3407           QFRLS(ccb);
3408           xpt_release_ccb(ccb);
3409 
3410           if (error || load == 0)
3411                     softc->fileno = softc->blkno = (daddr_t) -1;
3412           else if (error == 0)
3413                     softc->fileno = softc->blkno = (daddr_t) 0;
3414           return (error);
3415 }
3416 
3417 static int
saerase(struct cam_periph * periph,int longerase)3418 saerase(struct cam_periph *periph, int longerase)
3419 {
3420 
3421           union     ccb *ccb;
3422           struct    sa_softc *softc;
3423           int error;
3424 
3425           softc = (struct sa_softc *)periph->softc;
3426           if (softc->open_rdonly)
3427                     return (EBADF);
3428 
3429           ccb = cam_periph_getccb(periph, 1);
3430           Set_CCB_Type(ccb, SA_CCB_POLLED);
3431 
3432           scsi_erase(&ccb->csio, 1, sadone, MSG_SIMPLE_Q_TAG, FALSE, longerase,
3433               SSD_FULL_SIZE, ERASE_TIMEOUT);
3434 
3435           softc->dsreg = MTIO_DSREG_ZER;
3436           error = cam_periph_runccb(ccb, saerror, 0, 0, &softc->device_stats);
3437           softc->dsreg = MTIO_DSREG_REST;
3438 
3439           if ((ccb->ccb_h.status & CAM_DEV_QFRZN) != 0)
3440                     cam_release_devq(ccb->ccb_h.path, 0, 0, 0, FALSE);
3441           xpt_release_ccb(ccb);
3442           return (error);
3443 }
3444 
3445 #endif /* _KERNEL */
3446 
3447 /*
3448  * Read tape block limits command.
3449  */
3450 void
scsi_read_block_limits(struct ccb_scsiio * csio,u_int32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),u_int8_t tag_action,struct scsi_read_block_limits_data * rlimit_buf,u_int8_t sense_len,u_int32_t timeout)3451 scsi_read_block_limits(struct ccb_scsiio *csio, u_int32_t retries,
3452                        void (*cbfcnp)(struct cam_periph *, union ccb *),
3453                        u_int8_t tag_action,
3454                        struct scsi_read_block_limits_data *rlimit_buf,
3455                        u_int8_t sense_len, u_int32_t timeout)
3456 {
3457           struct scsi_read_block_limits *scsi_cmd;
3458 
3459           cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action,
3460                (u_int8_t *)rlimit_buf, sizeof(*rlimit_buf), sense_len,
3461                sizeof(*scsi_cmd), timeout);
3462 
3463           scsi_cmd = (struct scsi_read_block_limits *)&csio->cdb_io.cdb_bytes;
3464           bzero(scsi_cmd, sizeof(*scsi_cmd));
3465           scsi_cmd->opcode = READ_BLOCK_LIMITS;
3466 }
3467 
3468 void
scsi_sa_read_write(struct ccb_scsiio * csio,u_int32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),u_int8_t tag_action,int readop,int sli,int fixed,u_int32_t length,u_int8_t * data_ptr,u_int32_t dxfer_len,u_int8_t sense_len,u_int32_t timeout)3469 scsi_sa_read_write(struct ccb_scsiio *csio, u_int32_t retries,
3470                        void (*cbfcnp)(struct cam_periph *, union ccb *),
3471                        u_int8_t tag_action, int readop, int sli,
3472                        int fixed, u_int32_t length, u_int8_t *data_ptr,
3473                        u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout)
3474 {
3475           struct scsi_sa_rw *scsi_cmd;
3476 
3477           scsi_cmd = (struct scsi_sa_rw *)&csio->cdb_io.cdb_bytes;
3478           scsi_cmd->opcode = readop ? SA_READ : SA_WRITE;
3479           scsi_cmd->sli_fixed = 0;
3480           if (sli && readop)
3481                     scsi_cmd->sli_fixed |= SAR_SLI;
3482           if (fixed)
3483                     scsi_cmd->sli_fixed |= SARW_FIXED;
3484           scsi_ulto3b(length, scsi_cmd->length);
3485           scsi_cmd->control = 0;
3486 
3487           cam_fill_csio(csio, retries, cbfcnp, readop ? CAM_DIR_IN : CAM_DIR_OUT,
3488               tag_action, data_ptr, dxfer_len, sense_len,
3489               sizeof(*scsi_cmd), timeout);
3490 }
3491 
3492 void
scsi_load_unload(struct ccb_scsiio * csio,u_int32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),u_int8_t tag_action,int immediate,int eot,int reten,int load,u_int8_t sense_len,u_int32_t timeout)3493 scsi_load_unload(struct ccb_scsiio *csio, u_int32_t retries,
3494                      void (*cbfcnp)(struct cam_periph *, union ccb *),
3495                      u_int8_t tag_action, int immediate, int eot,
3496                      int reten, int load, u_int8_t sense_len,
3497                      u_int32_t timeout)
3498 {
3499           struct scsi_load_unload *scsi_cmd;
3500 
3501           scsi_cmd = (struct scsi_load_unload *)&csio->cdb_io.cdb_bytes;
3502           bzero(scsi_cmd, sizeof(*scsi_cmd));
3503           scsi_cmd->opcode = LOAD_UNLOAD;
3504           if (immediate)
3505                     scsi_cmd->immediate = SLU_IMMED;
3506           if (eot)
3507                     scsi_cmd->eot_reten_load |= SLU_EOT;
3508           if (reten)
3509                     scsi_cmd->eot_reten_load |= SLU_RETEN;
3510           if (load)
3511                     scsi_cmd->eot_reten_load |= SLU_LOAD;
3512 
3513           cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action,
3514               NULL, 0, sense_len, sizeof(*scsi_cmd), timeout);
3515 }
3516 
3517 void
scsi_rewind(struct ccb_scsiio * csio,u_int32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),u_int8_t tag_action,int immediate,u_int8_t sense_len,u_int32_t timeout)3518 scsi_rewind(struct ccb_scsiio *csio, u_int32_t retries,
3519               void (*cbfcnp)(struct cam_periph *, union ccb *),
3520               u_int8_t tag_action, int immediate, u_int8_t sense_len,
3521               u_int32_t timeout)
3522 {
3523           struct scsi_rewind *scsi_cmd;
3524 
3525           scsi_cmd = (struct scsi_rewind *)&csio->cdb_io.cdb_bytes;
3526           bzero(scsi_cmd, sizeof(*scsi_cmd));
3527           scsi_cmd->opcode = REWIND;
3528           if (immediate)
3529                     scsi_cmd->immediate = SREW_IMMED;
3530 
3531           cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
3532               0, sense_len, sizeof(*scsi_cmd), timeout);
3533 }
3534 
3535 void
scsi_space(struct ccb_scsiio * csio,u_int32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),u_int8_t tag_action,scsi_space_code code,u_int32_t count,u_int8_t sense_len,u_int32_t timeout)3536 scsi_space(struct ccb_scsiio *csio, u_int32_t retries,
3537              void (*cbfcnp)(struct cam_periph *, union ccb *),
3538              u_int8_t tag_action, scsi_space_code code,
3539              u_int32_t count, u_int8_t sense_len, u_int32_t timeout)
3540 {
3541           struct scsi_space *scsi_cmd;
3542 
3543           scsi_cmd = (struct scsi_space *)&csio->cdb_io.cdb_bytes;
3544           scsi_cmd->opcode = SPACE;
3545           scsi_cmd->code = code;
3546           scsi_ulto3b(count, scsi_cmd->count);
3547           scsi_cmd->control = 0;
3548 
3549           cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
3550               0, sense_len, sizeof(*scsi_cmd), timeout);
3551 }
3552 
3553 void
scsi_write_filemarks(struct ccb_scsiio * csio,u_int32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),u_int8_t tag_action,int immediate,int setmark,u_int32_t num_marks,u_int8_t sense_len,u_int32_t timeout)3554 scsi_write_filemarks(struct ccb_scsiio *csio, u_int32_t retries,
3555                          void (*cbfcnp)(struct cam_periph *, union ccb *),
3556                          u_int8_t tag_action, int immediate, int setmark,
3557                          u_int32_t num_marks, u_int8_t sense_len,
3558                          u_int32_t timeout)
3559 {
3560           struct scsi_write_filemarks *scsi_cmd;
3561 
3562           scsi_cmd = (struct scsi_write_filemarks *)&csio->cdb_io.cdb_bytes;
3563           bzero(scsi_cmd, sizeof(*scsi_cmd));
3564           scsi_cmd->opcode = WRITE_FILEMARKS;
3565           if (immediate)
3566                     scsi_cmd->byte2 |= SWFMRK_IMMED;
3567           if (setmark)
3568                     scsi_cmd->byte2 |= SWFMRK_WSMK;
3569 
3570           scsi_ulto3b(num_marks, scsi_cmd->num_marks);
3571 
3572           cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
3573               0, sense_len, sizeof(*scsi_cmd), timeout);
3574 }
3575 
3576 /*
3577  * The reserve and release unit commands differ only by their opcodes.
3578  */
3579 void
scsi_reserve_release_unit(struct ccb_scsiio * csio,u_int32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),u_int8_t tag_action,int third_party,int third_party_id,u_int8_t sense_len,u_int32_t timeout,int reserve)3580 scsi_reserve_release_unit(struct ccb_scsiio *csio, u_int32_t retries,
3581                                 void (*cbfcnp)(struct cam_periph *, union ccb *),
3582                                 u_int8_t tag_action, int third_party,
3583                                 int third_party_id, u_int8_t sense_len,
3584                                 u_int32_t timeout, int reserve)
3585 {
3586           struct scsi_reserve_release_unit *scsi_cmd;
3587 
3588           scsi_cmd = (struct scsi_reserve_release_unit *)&csio->cdb_io.cdb_bytes;
3589           bzero(scsi_cmd, sizeof(*scsi_cmd));
3590 
3591           if (reserve)
3592                     scsi_cmd->opcode = RESERVE_UNIT;
3593           else
3594                     scsi_cmd->opcode = RELEASE_UNIT;
3595 
3596           if (third_party) {
3597                     scsi_cmd->lun_thirdparty |= SRRU_3RD_PARTY;
3598                     scsi_cmd->lun_thirdparty |=
3599                               ((third_party_id << SRRU_3RD_SHAMT) & SRRU_3RD_MASK);
3600           }
3601 
3602           cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
3603               0, sense_len, sizeof(*scsi_cmd), timeout);
3604 }
3605 
3606 void
scsi_erase(struct ccb_scsiio * csio,u_int32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),u_int8_t tag_action,int immediate,int long_erase,u_int8_t sense_len,u_int32_t timeout)3607 scsi_erase(struct ccb_scsiio *csio, u_int32_t retries,
3608              void (*cbfcnp)(struct cam_periph *, union ccb *),
3609              u_int8_t tag_action, int immediate, int long_erase,
3610              u_int8_t sense_len, u_int32_t timeout)
3611 {
3612           struct scsi_erase *scsi_cmd;
3613 
3614           scsi_cmd = (struct scsi_erase *)&csio->cdb_io.cdb_bytes;
3615           bzero(scsi_cmd, sizeof(*scsi_cmd));
3616 
3617           scsi_cmd->opcode = ERASE;
3618 
3619           if (immediate)
3620                     scsi_cmd->lun_imm_long |= SE_IMMED;
3621 
3622           if (long_erase)
3623                     scsi_cmd->lun_imm_long |= SE_LONG;
3624 
3625           cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
3626               0, sense_len, sizeof(*scsi_cmd), timeout);
3627 }
3628 
3629 /*
3630  * Read Tape Position command.
3631  */
3632 void
scsi_read_position(struct ccb_scsiio * csio,u_int32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),u_int8_t tag_action,int hardsoft,struct scsi_tape_position_data * sbp,u_int8_t sense_len,u_int32_t timeout)3633 scsi_read_position(struct ccb_scsiio *csio, u_int32_t retries,
3634                        void (*cbfcnp)(struct cam_periph *, union ccb *),
3635                        u_int8_t tag_action, int hardsoft,
3636                        struct scsi_tape_position_data *sbp,
3637                        u_int8_t sense_len, u_int32_t timeout)
3638 {
3639           struct scsi_tape_read_position *scmd;
3640 
3641           cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action,
3642               (u_int8_t *)sbp, sizeof (*sbp), sense_len, sizeof(*scmd), timeout);
3643           scmd = (struct scsi_tape_read_position *)&csio->cdb_io.cdb_bytes;
3644           bzero(scmd, sizeof(*scmd));
3645           scmd->opcode = READ_POSITION;
3646           scmd->byte1 = hardsoft;
3647 }
3648 
3649 /*
3650  * Set Tape Position command.
3651  */
3652 void
scsi_set_position(struct ccb_scsiio * csio,u_int32_t retries,void (* cbfcnp)(struct cam_periph *,union ccb *),u_int8_t tag_action,int hardsoft,u_int32_t blkno,u_int8_t sense_len,u_int32_t timeout)3653 scsi_set_position(struct ccb_scsiio *csio, u_int32_t retries,
3654                        void (*cbfcnp)(struct cam_periph *, union ccb *),
3655                        u_int8_t tag_action, int hardsoft, u_int32_t blkno,
3656                        u_int8_t sense_len, u_int32_t timeout)
3657 {
3658           struct scsi_tape_locate *scmd;
3659 
3660           cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action,
3661               NULL, 0, sense_len, sizeof(*scmd), timeout);
3662           scmd = (struct scsi_tape_locate *)&csio->cdb_io.cdb_bytes;
3663           bzero(scmd, sizeof(*scmd));
3664           scmd->opcode = LOCATE;
3665           if (hardsoft)
3666                     scmd->byte1 |= SA_SPOS_BT;
3667           scsi_ulto4b(blkno, scmd->blkaddr);
3668 }
3669