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