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