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