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