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