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