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