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