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: src/sys/cam/scsi/scsi_sa.c,v 1.114 2008/09/27 08:51:18 ed Exp $");
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/fcntl.h>
48 #include <sys/devicestat.h>
49
50 #ifndef _KERNEL
51 #include <stdio.h>
52 #include <string.h>
53 #endif
54
55 #include <cam/cam.h>
56 #include <cam/cam_ccb.h>
57 #include <cam/cam_periph.h>
58 #include <cam/cam_xpt_periph.h>
59 #include <cam/cam_debug.h>
60
61 #include <cam/scsi/scsi_all.h>
62 #include <cam/scsi/scsi_message.h>
63 #include <cam/scsi/scsi_sa.h>
64
65 #ifdef _KERNEL
66
67 #include <opt_sa.h>
68
69 #ifndef SA_IO_TIMEOUT
70 #define SA_IO_TIMEOUT 4
71 #endif
72 #ifndef SA_SPACE_TIMEOUT
73 #define SA_SPACE_TIMEOUT 1 * 60
74 #endif
75 #ifndef SA_REWIND_TIMEOUT
76 #define SA_REWIND_TIMEOUT 2 * 60
77 #endif
78 #ifndef SA_ERASE_TIMEOUT
79 #define SA_ERASE_TIMEOUT 4 * 60
80 #endif
81
82 #define SCSIOP_TIMEOUT (60 * 1000) /* not an option */
83
84 #define IO_TIMEOUT (SA_IO_TIMEOUT * 60 * 1000)
85 #define REWIND_TIMEOUT (SA_REWIND_TIMEOUT * 60 * 1000)
86 #define ERASE_TIMEOUT (SA_ERASE_TIMEOUT * 60 * 1000)
87 #define SPACE_TIMEOUT (SA_SPACE_TIMEOUT * 60 * 1000)
88
89 /*
90 * Additional options that can be set for config: SA_1FM_AT_EOT
91 */
92
93 #ifndef UNUSED_PARAMETER
94 #define UNUSED_PARAMETER(x) x = x
95 #endif
96
97 #define QFRLS(ccb) \
98 if (((ccb)->ccb_h.status & CAM_DEV_QFRZN) != 0) \
99 cam_release_devq((ccb)->ccb_h.path, 0, 0, 0, FALSE)
100
101 /*
102 * Driver states
103 */
104
105 MALLOC_DEFINE(M_SCSISA, "SCSI sa", "SCSI sequential access buffers");
106
107 typedef enum {
108 SA_STATE_NORMAL, SA_STATE_ABNORMAL
109 } sa_state;
110
111 #define ccb_pflags ppriv_field0
112 #define ccb_bp ppriv_ptr1
113
114 #define SA_CCB_BUFFER_IO 0x0
115 #define SA_CCB_WAITING 0x1
116 #define SA_CCB_TYPEMASK 0x1
117 #define SA_POSITION_UPDATED 0x2
118
119 #define Set_CCB_Type(x, type) \
120 x->ccb_h.ccb_pflags &= ~SA_CCB_TYPEMASK; \
121 x->ccb_h.ccb_pflags |= type
122
123 #define CCB_Type(x) (x->ccb_h.ccb_pflags & SA_CCB_TYPEMASK)
124
125
126
127 typedef enum {
128 SA_FLAG_OPEN = 0x0001,
129 SA_FLAG_FIXED = 0x0002,
130 SA_FLAG_TAPE_LOCKED = 0x0004,
131 SA_FLAG_TAPE_MOUNTED = 0x0008,
132 SA_FLAG_TAPE_WP = 0x0010,
133 SA_FLAG_TAPE_WRITTEN = 0x0020,
134 SA_FLAG_EOM_PENDING = 0x0040,
135 SA_FLAG_EIO_PENDING = 0x0080,
136 SA_FLAG_EOF_PENDING = 0x0100,
137 SA_FLAG_ERR_PENDING = (SA_FLAG_EOM_PENDING|SA_FLAG_EIO_PENDING|
138 SA_FLAG_EOF_PENDING),
139 SA_FLAG_INVALID = 0x0200,
140 SA_FLAG_COMP_ENABLED = 0x0400,
141 SA_FLAG_COMP_SUPP = 0x0800,
142 SA_FLAG_COMP_UNSUPP = 0x1000,
143 SA_FLAG_TAPE_FROZEN = 0x2000
144 } sa_flags;
145
146 typedef enum {
147 SA_MODE_REWIND = 0x00,
148 SA_MODE_NOREWIND = 0x01,
149 SA_MODE_OFFLINE = 0x02
150 } sa_mode;
151
152 typedef enum {
153 SA_PARAM_NONE = 0x00,
154 SA_PARAM_BLOCKSIZE = 0x01,
155 SA_PARAM_DENSITY = 0x02,
156 SA_PARAM_COMPRESSION = 0x04,
157 SA_PARAM_BUFF_MODE = 0x08,
158 SA_PARAM_NUMBLOCKS = 0x10,
159 SA_PARAM_WP = 0x20,
160 SA_PARAM_SPEED = 0x40,
161 SA_PARAM_ALL = 0x7f
162 } sa_params;
163
164 typedef enum {
165 SA_QUIRK_NONE = 0x00,
166 SA_QUIRK_NOCOMP = 0x01, /* Can't deal with compression at all */
167 SA_QUIRK_FIXED = 0x02, /* Force fixed mode */
168 SA_QUIRK_VARIABLE = 0x04, /* Force variable mode */
169 SA_QUIRK_2FM = 0x08, /* Needs Two File Marks at EOD */
170 SA_QUIRK_1FM = 0x10, /* No more than 1 File Mark at EOD */
171 SA_QUIRK_NODREAD = 0x20, /* Don't try and dummy read density */
172 SA_QUIRK_NO_MODESEL = 0x40, /* Don't do mode select at all */
173 SA_QUIRK_NO_CPAGE = 0x80 /* Don't use DEVICE COMPRESSION page */
174 } sa_quirks;
175
176 /* units are bits 4-7, 16-21 (1024 units) */
177 #define SAUNIT(DEV) \
178 (((dev2unit(DEV) & 0xF0) >> 4) | ((dev2unit(DEV) & 0x3f0000) >> 16))
179
180 #define SAMODE(z) ((dev2unit(z) & 0x3))
181 #define SADENSITY(z) (((dev2unit(z) >> 2) & 0x3))
182 #define SA_IS_CTRL(z) (dev2unit(z) & (1 << 29))
183
184 #define SA_NOT_CTLDEV 0
185 #define SA_CTLDEV 1
186
187 #define SA_ATYPE_R 0
188 #define SA_ATYPE_NR 1
189 #define SA_ATYPE_ER 2
190
191 #define SAMINOR(ctl, unit, mode, access) \
192 ((ctl << 29) | ((unit & 0x3f0) << 16) | ((unit & 0xf) << 4) | \
193 (mode << 0x2) | (access & 0x3))
194
195 #define SA_NUM_MODES 4
196 struct sa_devs {
197 struct cdev *ctl_dev;
198 struct sa_mode_devs {
199 struct cdev *r_dev;
200 struct cdev *nr_dev;
201 struct cdev *er_dev;
202 } mode_devs[SA_NUM_MODES];
203 };
204
205 struct sa_softc {
206 sa_state state;
207 sa_flags flags;
208 sa_quirks quirks;
209 struct bio_queue_head bio_queue;
210 int queue_count;
211 struct devstat *device_stats;
212 struct sa_devs devs;
213 int blk_gran;
214 int blk_mask;
215 int blk_shift;
216 u_int32_t max_blk;
217 u_int32_t min_blk;
218 u_int32_t comp_algorithm;
219 u_int32_t saved_comp_algorithm;
220 u_int32_t media_blksize;
221 u_int32_t last_media_blksize;
222 u_int32_t media_numblks;
223 u_int8_t media_density;
224 u_int8_t speed;
225 u_int8_t scsi_rev;
226 u_int8_t dsreg; /* mtio mt_dsreg, redux */
227 int buffer_mode;
228 int filemarks;
229 union ccb saved_ccb;
230 int last_resid_was_io;
231
232 /*
233 * Relative to BOT Location.
234 */
235 daddr_t fileno;
236 daddr_t blkno;
237
238 /*
239 * Latched Error Info
240 */
241 struct {
242 struct scsi_sense_data _last_io_sense;
243 u_int32_t _last_io_resid;
244 u_int8_t _last_io_cdb[CAM_MAX_CDBLEN];
245 struct scsi_sense_data _last_ctl_sense;
246 u_int32_t _last_ctl_resid;
247 u_int8_t _last_ctl_cdb[CAM_MAX_CDBLEN];
248 #define last_io_sense errinfo._last_io_sense
249 #define last_io_resid errinfo._last_io_resid
250 #define last_io_cdb errinfo._last_io_cdb
251 #define last_ctl_sense errinfo._last_ctl_sense
252 #define last_ctl_resid errinfo._last_ctl_resid
253 #define last_ctl_cdb errinfo._last_ctl_cdb
254 } errinfo;
255 /*
256 * Misc other flags/state
257 */
258 u_int32_t
259 : 29,
260 open_rdonly : 1, /* open read-only */
261 open_pending_mount : 1, /* open pending mount */
262 ctrl_mode : 1; /* control device open */
263 };
264
265 struct sa_quirk_entry {
266 struct scsi_inquiry_pattern inq_pat; /* matching pattern */
267 sa_quirks quirks; /* specific quirk type */
268 u_int32_t prefblk; /* preferred blocksize when in fixed mode */
269 };
270
271 static struct sa_quirk_entry sa_quirk_table[] =
272 {
273 {
274 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "OnStream",
275 "ADR*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_NODREAD |
276 SA_QUIRK_1FM|SA_QUIRK_NO_MODESEL, 32768
277 },
278 {
279 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
280 "Python 06408*", "*"}, SA_QUIRK_NODREAD, 0
281 },
282 {
283 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
284 "Python 25601*", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_NODREAD, 0
285 },
286 {
287 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
288 "Python*", "*"}, SA_QUIRK_NODREAD, 0
289 },
290 {
291 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
292 "VIPER 150*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
293 },
294 {
295 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
296 "VIPER 2525 25462", "-011"},
297 SA_QUIRK_NOCOMP|SA_QUIRK_1FM|SA_QUIRK_NODREAD, 0
298 },
299 {
300 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
301 "VIPER 2525*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024
302 },
303 #if 0
304 {
305 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
306 "C15*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_NO_CPAGE, 0,
307 },
308 #endif
309 {
310 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
311 "C56*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
312 },
313 {
314 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
315 "T20*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
316 },
317 {
318 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
319 "T4000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
320 },
321 {
322 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "HP",
323 "HP-88780*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
324 },
325 {
326 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY",
327 "*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
328 },
329 {
330 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "M4 DATA",
331 "123107 SCSI*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
332 },
333 { /* jreynold@primenet.com */
334 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "Seagate",
335 "STT8000N*", "*"}, SA_QUIRK_1FM, 0
336 },
337 { /* mike@sentex.net */
338 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "Seagate",
339 "STT20000*", "*"}, SA_QUIRK_1FM, 0
340 },
341 {
342 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
343 " TDC 3600", "U07:"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
344 },
345 {
346 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
347 " TDC 3800", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
348 },
349 {
350 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
351 " TDC 4100", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
352 },
353 {
354 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
355 " TDC 4200", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
356 },
357 {
358 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
359 " SLR*", "*"}, SA_QUIRK_1FM, 0
360 },
361 {
362 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK",
363 "5525ES*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
364 },
365 {
366 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK",
367 "51000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024
368 }
369 };
370
371 static d_open_t saopen;
372 static d_close_t saclose;
373 static d_strategy_t sastrategy;
374 static d_ioctl_t saioctl;
375 static periph_init_t sainit;
376 static periph_ctor_t saregister;
377 static periph_oninv_t saoninvalidate;
378 static periph_dtor_t sacleanup;
379 static periph_start_t sastart;
380 static void saasync(void *callback_arg, u_int32_t code,
381 struct cam_path *path, void *arg);
382 static void sadone(struct cam_periph *periph,
383 union ccb *start_ccb);
384 static int saerror(union ccb *ccb, u_int32_t cam_flags,
385 u_int32_t sense_flags);
386 static int samarkswanted(struct cam_periph *);
387 static int sacheckeod(struct cam_periph *periph);
388 static int sagetparams(struct cam_periph *periph,
389 sa_params params_to_get,
390 u_int32_t *blocksize, u_int8_t *density,
391 u_int32_t *numblocks, int *buff_mode,
392 u_int8_t *write_protect, u_int8_t *speed,
393 int *comp_supported, int *comp_enabled,
394 u_int32_t *comp_algorithm,
395 sa_comp_t *comp_page);
396 static int sasetparams(struct cam_periph *periph,
397 sa_params params_to_set,
398 u_int32_t blocksize, u_int8_t density,
399 u_int32_t comp_algorithm,
400 u_int32_t sense_flags);
401 static void saprevent(struct cam_periph *periph, int action);
402 static int sarewind(struct cam_periph *periph);
403 static int saspace(struct cam_periph *periph, int count,
404 scsi_space_code code);
405 static int samount(struct cam_periph *, int, struct cdev *);
406 static int saretension(struct cam_periph *periph);
407 static int sareservereleaseunit(struct cam_periph *periph,
408 int reserve);
409 static int saloadunload(struct cam_periph *periph, int load);
410 static int saerase(struct cam_periph *periph, int longerase);
411 static int sawritefilemarks(struct cam_periph *periph,
412 int nmarks, int setmarks);
413 static int sardpos(struct cam_periph *periph, int, u_int32_t *);
414 static int sasetpos(struct cam_periph *periph, int, u_int32_t *);
415
416
417 static struct periph_driver sadriver =
418 {
419 sainit, "sa",
420 TAILQ_HEAD_INITIALIZER(sadriver.units), /* generation */ 0
421 };
422
423 PERIPHDRIVER_DECLARE(sa, sadriver);
424
425 /* For 2.2-stable support */
426 #ifndef D_TAPE
427 #define D_TAPE 0
428 #endif
429
430
431 static struct cdevsw sa_cdevsw = {
432 .d_version = D_VERSION,
433 .d_open = saopen,
434 .d_close = saclose,
435 .d_read = physread,
436 .d_write = physwrite,
437 .d_ioctl = saioctl,
438 .d_strategy = sastrategy,
439 .d_name = "sa",
440 .d_flags = D_TAPE | D_NEEDGIANT,
441 };
442
443 static int
444 saopen(struct cdev *dev, int flags, int fmt, struct thread *td)
445 {
446 struct cam_periph *periph;
447 struct sa_softc *softc;
448 int unit;
449 int error;
450
451 unit = SAUNIT(dev);
452
453 periph = (struct cam_periph *)dev->si_drv1;
454 if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
455 return (ENXIO);
456 }
457
458 cam_periph_lock(periph);
459
460 softc = (struct sa_softc *)periph->softc;
461
462 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO,
463 ("saopen(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags));
464
465 if (SA_IS_CTRL(dev)) {
466 softc->ctrl_mode = 1;
467 cam_periph_unlock(periph);
468 return (0);
469 }
470
471 if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
472 cam_periph_unlock(periph);
473 cam_periph_release(periph);
474 return (error);
475 }
476
477 if (softc->flags & SA_FLAG_OPEN) {
478 error = EBUSY;
479 } else if (softc->flags & SA_FLAG_INVALID) {
480 error = ENXIO;
481 } else {
482 /*
483 * Preserve whether this is a read_only open.
484 */
485 softc->open_rdonly = (flags & O_RDWR) == O_RDONLY;
486
487 /*
488 * The function samount ensures media is loaded and ready.
489 * It also does a device RESERVE if the tape isn't yet mounted.
490 *
491 * If the mount fails and this was a non-blocking open,
492 * make this a 'open_pending_mount' action.
493 */
494 error = samount(periph, flags, dev);
495 if (error && (flags & O_NONBLOCK)) {
496 softc->flags |= SA_FLAG_OPEN;
497 softc->open_pending_mount = 1;
498 cam_periph_unhold(periph);
499 cam_periph_unlock(periph);
500 return (0);
501 }
502 }
503
504 if (error) {
505 cam_periph_unhold(periph);
506 cam_periph_unlock(periph);
507 cam_periph_release(periph);
508 return (error);
509 }
510
511 saprevent(periph, PR_PREVENT);
512 softc->flags |= SA_FLAG_OPEN;
513
514 cam_periph_unhold(periph);
515 cam_periph_unlock(periph);
516 return (error);
517 }
518
519 static int
520 saclose(struct cdev *dev, int flag, int fmt, struct thread *td)
521 {
522 struct cam_periph *periph;
523 struct sa_softc *softc;
524 int unit, mode, error, writing, tmp;
525 int closedbits = SA_FLAG_OPEN;
526
527 unit = SAUNIT(dev);
528 mode = SAMODE(dev);
529 periph = (struct cam_periph *)dev->si_drv1;
530 if (periph == NULL)
531 return (ENXIO);
532
533 cam_periph_lock(periph);
534
535 softc = (struct sa_softc *)periph->softc;
536
537 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO,
538 ("saclose(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags));
539
540
541 softc->open_rdonly = 0;
542 if (SA_IS_CTRL(dev)) {
543 softc->ctrl_mode = 0;
544 cam_periph_unlock(periph);
545 cam_periph_release(periph);
546 return (0);
547 }
548
549 if (softc->open_pending_mount) {
550 softc->flags &= ~SA_FLAG_OPEN;
551 softc->open_pending_mount = 0;
552 cam_periph_unlock(periph);
553 cam_periph_release(periph);
554 return (0);
555 }
556
557 if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
558 cam_periph_unlock(periph);
559 return (error);
560 }
561
562 /*
563 * Were we writing the tape?
564 */
565 writing = (softc->flags & SA_FLAG_TAPE_WRITTEN) != 0;
566
567 /*
568 * See whether or not we need to write filemarks. If this
569 * fails, we probably have to assume we've lost tape
570 * position.
571 */
572 error = sacheckeod(periph);
573 if (error) {
574 xpt_print(periph->path,
575 "failed to write terminating filemark(s)\n");
576 softc->flags |= SA_FLAG_TAPE_FROZEN;
577 }
578
579 /*
580 * Whatever we end up doing, allow users to eject tapes from here on.
581 */
582 saprevent(periph, PR_ALLOW);
583
584 /*
585 * Decide how to end...
586 */
587 if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) {
588 closedbits |= SA_FLAG_TAPE_FROZEN;
589 } else switch (mode) {
590 case SA_MODE_OFFLINE:
591 /*
592 * An 'offline' close is an unconditional release of
593 * frozen && mount conditions, irrespective of whether
594 * these operations succeeded. The reason for this is
595 * to allow at least some kind of programmatic way
596 * around our state getting all fouled up. If somebody
597 * issues an 'offline' command, that will be allowed
598 * to clear state.
599 */
600 (void) sarewind(periph);
601 (void) saloadunload(periph, FALSE);
602 closedbits |= SA_FLAG_TAPE_MOUNTED|SA_FLAG_TAPE_FROZEN;
603 break;
604 case SA_MODE_REWIND:
605 /*
606 * If the rewind fails, return an error- if anyone cares,
607 * but not overwriting any previous error.
608 *
609 * We don't clear the notion of mounted here, but we do
610 * clear the notion of frozen if we successfully rewound.
611 */
612 tmp = sarewind(periph);
613 if (tmp) {
614 if (error != 0)
615 error = tmp;
616 } else {
617 closedbits |= SA_FLAG_TAPE_FROZEN;
618 }
619 break;
620 case SA_MODE_NOREWIND:
621 /*
622 * If we're not rewinding/unloading the tape, find out
623 * whether we need to back up over one of two filemarks
624 * we wrote (if we wrote two filemarks) so that appends
625 * from this point on will be sane.
626 */
627 if (error == 0 && writing && (softc->quirks & SA_QUIRK_2FM)) {
628 tmp = saspace(periph, -1, SS_FILEMARKS);
629 if (tmp) {
630 xpt_print(periph->path, "unable to backspace "
631 "over one of double filemarks at end of "
632 "tape\n");
633 xpt_print(periph->path, "it is possible that "
634 "this device needs a SA_QUIRK_1FM quirk set"
635 "for it\n");
636 softc->flags |= SA_FLAG_TAPE_FROZEN;
637 }
638 }
639 break;
640 default:
641 xpt_print(periph->path, "unknown mode 0x%x in saclose\n", mode);
642 /* NOTREACHED */
643 break;
644 }
645
646 /*
647 * We wish to note here that there are no more filemarks to be written.
648 */
649 softc->filemarks = 0;
650 softc->flags &= ~SA_FLAG_TAPE_WRITTEN;
651
652 /*
653 * And we are no longer open for business.
654 */
655 softc->flags &= ~closedbits;
656
657 /*
658 * Inform users if tape state if frozen....
659 */
660 if (softc->flags & SA_FLAG_TAPE_FROZEN) {
661 xpt_print(periph->path, "tape is now frozen- use an OFFLINE, "
662 "REWIND or MTEOM command to clear this state.\n");
663 }
664
665 /* release the device if it is no longer mounted */
666 if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0)
667 sareservereleaseunit(periph, FALSE);
668
669 cam_periph_unhold(periph);
670 cam_periph_unlock(periph);
671 cam_periph_release(periph);
672
673 return (error);
674 }
675
676 /*
677 * Actually translate the requested transfer into one the physical driver
678 * can understand. The transfer is described by a buf and will include
679 * only one physical transfer.
680 */
681 static void
682 sastrategy(struct bio *bp)
683 {
684 struct cam_periph *periph;
685 struct sa_softc *softc;
686
687 bp->bio_resid = bp->bio_bcount;
688 if (SA_IS_CTRL(bp->bio_dev)) {
689 biofinish(bp, NULL, EINVAL);
690 return;
691 }
692 periph = (struct cam_periph *)bp->bio_dev->si_drv1;
693 if (periph == NULL) {
694 biofinish(bp, NULL, ENXIO);
695 return;
696 }
697 cam_periph_lock(periph);
698
699 softc = (struct sa_softc *)periph->softc;
700
701 if (softc->flags & SA_FLAG_INVALID) {
702 cam_periph_unlock(periph);
703 biofinish(bp, NULL, ENXIO);
704 return;
705 }
706
707 if (softc->flags & SA_FLAG_TAPE_FROZEN) {
708 cam_periph_unlock(periph);
709 biofinish(bp, NULL, EPERM);
710 return;
711 }
712
713 /*
714 * This should actually never occur as the write(2)
715 * system call traps attempts to write to a read-only
716 * file descriptor.
717 */
718 if (bp->bio_cmd == BIO_WRITE && softc->open_rdonly) {
719 cam_periph_unlock(periph);
720 biofinish(bp, NULL, EBADF);
721 return;
722 }
723
724 if (softc->open_pending_mount) {
725 int error = samount(periph, 0, bp->bio_dev);
726 if (error) {
727 cam_periph_unlock(periph);
728 biofinish(bp, NULL, ENXIO);
729 return;
730 }
731 saprevent(periph, PR_PREVENT);
732 softc->open_pending_mount = 0;
733 }
734
735
736 /*
737 * If it's a null transfer, return immediately
738 */
739 if (bp->bio_bcount == 0) {
740 cam_periph_unlock(periph);
741 biodone(bp);
742 return;
743 }
744
745 /* valid request? */
746 if (softc->flags & SA_FLAG_FIXED) {
747 /*
748 * Fixed block device. The byte count must
749 * be a multiple of our block size.
750 */
751 if (((softc->blk_mask != ~0) &&
752 ((bp->bio_bcount & softc->blk_mask) != 0)) ||
753 ((softc->blk_mask == ~0) &&
754 ((bp->bio_bcount % softc->min_blk) != 0))) {
755 xpt_print(periph->path, "Invalid request. Fixed block "
756 "device requests must be a multiple of %d bytes\n",
757 softc->min_blk);
758 cam_periph_unlock(periph);
759 biofinish(bp, NULL, EINVAL);
760 return;
761 }
762 } else if ((bp->bio_bcount > softc->max_blk) ||
763 (bp->bio_bcount < softc->min_blk) ||
764 (bp->bio_bcount & softc->blk_mask) != 0) {
765
766 xpt_print_path(periph->path);
767 printf("Invalid request. Variable block "
768 "device requests must be ");
769 if (softc->blk_mask != 0) {
770 printf("a multiple of %d ", (0x1 << softc->blk_gran));
771 }
772 printf("between %d and %d bytes\n", softc->min_blk,
773 softc->max_blk);
774 cam_periph_unlock(periph);
775 biofinish(bp, NULL, EINVAL);
776 return;
777 }
778
779 /*
780 * Place it at the end of the queue.
781 */
782 bioq_insert_tail(&softc->bio_queue, bp);
783 softc->queue_count++;
784 #if 0
785 CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
786 ("sastrategy: queuing a %ld %s byte %s\n", bp->bio_bcount,
787 (softc->flags & SA_FLAG_FIXED)? "fixed" : "variable",
788 (bp->bio_cmd == BIO_READ)? "read" : "write"));
789 #endif
790 if (softc->queue_count > 1) {
791 CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
792 ("sastrategy: queue count now %d\n", softc->queue_count));
793 }
794
795 /*
796 * Schedule ourselves for performing the work.
797 */
798 xpt_schedule(periph, 1);
799 cam_periph_unlock(periph);
800
801 return;
802 }
803
804
805 #define PENDING_MOUNT_CHECK(softc, periph, dev) \
806 if (softc->open_pending_mount) { \
807 error = samount(periph, 0, dev); \
808 if (error) { \
809 break; \
810 } \
811 saprevent(periph, PR_PREVENT); \
812 softc->open_pending_mount = 0; \
813 }
814
815 static int
816 saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
817 {
818 struct cam_periph *periph;
819 struct sa_softc *softc;
820 scsi_space_code spaceop;
821 int didlockperiph = 0;
822 int mode;
823 int error = 0;
824
825 mode = SAMODE(dev);
826 error = 0; /* shut up gcc */
827 spaceop = 0; /* shut up gcc */
828
829 periph = (struct cam_periph *)dev->si_drv1;
830 if (periph == NULL)
831 return (ENXIO);
832
833 cam_periph_lock(periph);
834 softc = (struct sa_softc *)periph->softc;
835
836 /*
837 * Check for control mode accesses. We allow MTIOCGET and
838 * MTIOCERRSTAT (but need to be the only one open in order
839 * to clear latched status), and MTSETBSIZE, MTSETDNSTY
840 * and MTCOMP (but need to be the only one accessing this
841 * device to run those).
842 */
843
844 if (SA_IS_CTRL(dev)) {
845 switch (cmd) {
846 case MTIOCGETEOTMODEL:
847 case MTIOCGET:
848 break;
849 case MTIOCERRSTAT:
850 /*
851 * If the periph isn't already locked, lock it
852 * so our MTIOCERRSTAT can reset latched error stats.
853 *
854 * If the periph is already locked, skip it because
855 * we're just getting status and it'll be up to the
856 * other thread that has this device open to do
857 * an MTIOCERRSTAT that would clear latched status.
858 */
859 if ((periph->flags & CAM_PERIPH_LOCKED) == 0) {
860 error = cam_periph_hold(periph, PRIBIO|PCATCH);
861 if (error != 0)
862 return (error);
863 didlockperiph = 1;
864 }
865 break;
866
867 case MTIOCTOP:
868 {
869 struct mtop *mt = (struct mtop *) arg;
870
871 /*
872 * Check to make sure it's an OP we can perform
873 * with no media inserted.
874 */
875 switch (mt->mt_op) {
876 case MTSETBSIZ:
877 case MTSETDNSTY:
878 case MTCOMP:
879 mt = NULL;
880 /* FALLTHROUGH */
881 default:
882 break;
883 }
884 if (mt != NULL) {
885 break;
886 }
887 /* FALLTHROUGH */
888 }
889 case MTIOCSETEOTMODEL:
890 /*
891 * We need to acquire the peripheral here rather
892 * than at open time because we are sharing writable
893 * access to data structures.
894 */
895 error = cam_periph_hold(periph, PRIBIO|PCATCH);
896 if (error != 0)
897 return (error);
898 didlockperiph = 1;
899 break;
900
901 default:
902 return (EINVAL);
903 }
904 }
905
906 /*
907 * Find the device that the user is talking about
908 */
909 switch (cmd) {
910 case MTIOCGET:
911 {
912 struct mtget *g = (struct mtget *)arg;
913
914 /*
915 * If this isn't the control mode device, actually go out
916 * and ask the drive again what it's set to.
917 */
918 if (!SA_IS_CTRL(dev) && !softc->open_pending_mount) {
919 u_int8_t write_protect;
920 int comp_enabled, comp_supported;
921 error = sagetparams(periph, SA_PARAM_ALL,
922 &softc->media_blksize, &softc->media_density,
923 &softc->media_numblks, &softc->buffer_mode,
924 &write_protect, &softc->speed, &comp_supported,
925 &comp_enabled, &softc->comp_algorithm, NULL);
926 if (error)
927 break;
928 if (write_protect)
929 softc->flags |= SA_FLAG_TAPE_WP;
930 else
931 softc->flags &= ~SA_FLAG_TAPE_WP;
932 softc->flags &= ~(SA_FLAG_COMP_SUPP|
933 SA_FLAG_COMP_ENABLED|SA_FLAG_COMP_UNSUPP);
934 if (comp_supported) {
935 if (softc->saved_comp_algorithm == 0)
936 softc->saved_comp_algorithm =
937 softc->comp_algorithm;
938 softc->flags |= SA_FLAG_COMP_SUPP;
939 if (comp_enabled)
940 softc->flags |= SA_FLAG_COMP_ENABLED;
941 } else
942 softc->flags |= SA_FLAG_COMP_UNSUPP;
943 }
944 bzero(g, sizeof(struct mtget));
945 g->mt_type = MT_ISAR;
946 if (softc->flags & SA_FLAG_COMP_UNSUPP) {
947 g->mt_comp = MT_COMP_UNSUPP;
948 g->mt_comp0 = MT_COMP_UNSUPP;
949 g->mt_comp1 = MT_COMP_UNSUPP;
950 g->mt_comp2 = MT_COMP_UNSUPP;
951 g->mt_comp3 = MT_COMP_UNSUPP;
952 } else {
953 if ((softc->flags & SA_FLAG_COMP_ENABLED) == 0) {
954 g->mt_comp = MT_COMP_DISABLED;
955 } else {
956 g->mt_comp = softc->comp_algorithm;
957 }
958 g->mt_comp0 = softc->comp_algorithm;
959 g->mt_comp1 = softc->comp_algorithm;
960 g->mt_comp2 = softc->comp_algorithm;
961 g->mt_comp3 = softc->comp_algorithm;
962 }
963 g->mt_density = softc->media_density;
964 g->mt_density0 = softc->media_density;
965 g->mt_density1 = softc->media_density;
966 g->mt_density2 = softc->media_density;
967 g->mt_density3 = softc->media_density;
968 g->mt_blksiz = softc->media_blksize;
969 g->mt_blksiz0 = softc->media_blksize;
970 g->mt_blksiz1 = softc->media_blksize;
971 g->mt_blksiz2 = softc->media_blksize;
972 g->mt_blksiz3 = softc->media_blksize;
973 g->mt_fileno = softc->fileno;
974 g->mt_blkno = softc->blkno;
975 g->mt_dsreg = (short) softc->dsreg;
976 /*
977 * Yes, we know that this is likely to overflow
978 */
979 if (softc->last_resid_was_io) {
980 if ((g->mt_resid = (short) softc->last_io_resid) != 0) {
981 if (SA_IS_CTRL(dev) == 0 || didlockperiph) {
982 softc->last_io_resid = 0;
983 }
984 }
985 } else {
986 if ((g->mt_resid = (short)softc->last_ctl_resid) != 0) {
987 if (SA_IS_CTRL(dev) == 0 || didlockperiph) {
988 softc->last_ctl_resid = 0;
989 }
990 }
991 }
992 |