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