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