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