FreeBSD kernel CAM code
scsi_sa.c
Go to the documentation of this file.
1/*-
2 * Implementation of SCSI Sequential Access Peripheral driver for CAM.
3 *
4 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
5 *
6 * Copyright (c) 1999, 2000 Matthew Jacob
7 * Copyright (c) 2013, 2014, 2015, 2021 Spectra Logic Corporation
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions, and the following disclaimer,
15 * without modification, immediately at the beginning of the file.
16 * 2. The name of the author may not be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD$");
34
35#include <sys/param.h>
36#include <sys/queue.h>
37#ifdef _KERNEL
38#include <sys/systm.h>
39#include <sys/kernel.h>
40#endif
41#include <sys/types.h>
42#include <sys/time.h>
43#include <sys/bio.h>
44#include <sys/limits.h>
45#include <sys/malloc.h>
46#include <sys/mtio.h>
47#ifdef _KERNEL
48#include <sys/conf.h>
49#include <sys/sbuf.h>
50#include <sys/sysctl.h>
51#include <sys/taskqueue.h>
52#endif
53#include <sys/fcntl.h>
54#include <sys/devicestat.h>
55
56#ifndef _KERNEL
57#include <stdio.h>
58#include <string.h>
59#endif
60
61#include <cam/cam.h>
62#include <cam/cam_ccb.h>
63#include <cam/cam_periph.h>
64#include <cam/cam_xpt_periph.h>
65#include <cam/cam_debug.h>
66
67#include <cam/scsi/scsi_all.h>
69#include <cam/scsi/scsi_sa.h>
70
71#ifdef _KERNEL
72
73#include "opt_sa.h"
74
75#ifndef SA_IO_TIMEOUT
76#define SA_IO_TIMEOUT 32
77#endif
78#ifndef SA_SPACE_TIMEOUT
79#define SA_SPACE_TIMEOUT 1 * 60
80#endif
81#ifndef SA_REWIND_TIMEOUT
82#define SA_REWIND_TIMEOUT 2 * 60
83#endif
84#ifndef SA_ERASE_TIMEOUT
85#define SA_ERASE_TIMEOUT 4 * 60
86#endif
87#ifndef SA_REP_DENSITY_TIMEOUT
88#define SA_REP_DENSITY_TIMEOUT 1
89#endif
90
91#define SCSIOP_TIMEOUT (60 * 1000) /* not an option */
92
93#define IO_TIMEOUT (SA_IO_TIMEOUT * 60 * 1000)
94#define REWIND_TIMEOUT (SA_REWIND_TIMEOUT * 60 * 1000)
95#define ERASE_TIMEOUT (SA_ERASE_TIMEOUT * 60 * 1000)
96#define SPACE_TIMEOUT (SA_SPACE_TIMEOUT * 60 * 1000)
97#define REP_DENSITY_TIMEOUT (SA_REP_DENSITY_TIMEOUT * 60 * 1000)
98
99/*
100 * Additional options that can be set for config: SA_1FM_AT_EOT
101 */
102
103#ifndef UNUSED_PARAMETER
104#define UNUSED_PARAMETER(x) x = x
105#endif
106
107#define QFRLS(ccb) \
108 if (((ccb)->ccb_h.status & CAM_DEV_QFRZN) != 0) \
109 cam_release_devq((ccb)->ccb_h.path, 0, 0, 0, FALSE)
110
111/*
112 * Driver states
113 */
114
115static MALLOC_DEFINE(M_SCSISA, "SCSI sa", "SCSI sequential access buffers");
116
117typedef enum {
120
121#define ccb_pflags ppriv_field0
122#define ccb_bp ppriv_ptr1
123
124/* bits in ccb_pflags */
125#define SA_POSITION_UPDATED 0x1
126
127typedef enum {
128 SA_FLAG_OPEN = 0x00001,
129 SA_FLAG_FIXED = 0x00002,
145
150} sa_flags;
151
152typedef enum {
155 SA_MODE_OFFLINE = 0x02
157
158typedef enum {
177
178/*
179 * These are the default timeout values that apply to all tape drives.
180 *
181 * We get timeouts from the following places in order of increasing
182 * priority:
183 * 1. Driver default timeouts. (Set in the structure below.)
184 * 2. Timeouts loaded from the drive via REPORT SUPPORTED OPERATION
185 * CODES. (If the drive supports it, SPC-4/LTO-5 and newer should.)
186 * 3. Global loader tunables, used for all sa(4) driver instances on
187 * a machine.
188 * 4. Instance-specific loader tunables, used for say sa5.
189 * 5. On the fly user sysctl changes.
190 *
191 * Each step will overwrite the timeout value set from the one
192 * before, so you go from general to most specific.
193 */
194static struct sa_timeout_desc {
195 const char *desc;
196 int value;
198 {"erase", ERASE_TIMEOUT},
199 {"load", REWIND_TIMEOUT},
200 {"locate", SPACE_TIMEOUT},
201 {"mode_select", SCSIOP_TIMEOUT},
202 {"mode_sense", SCSIOP_TIMEOUT},
203 {"prevent", SCSIOP_TIMEOUT},
204 {"read", IO_TIMEOUT},
205 {"read_block_limits", SCSIOP_TIMEOUT},
206 {"read_position", SCSIOP_TIMEOUT},
207 {"report_density", REP_DENSITY_TIMEOUT},
208 {"reserve", SCSIOP_TIMEOUT},
209 {"rewind", REWIND_TIMEOUT},
210 {"space", SPACE_TIMEOUT},
211 {"tur", SCSIOP_TIMEOUT},
212 {"write", IO_TIMEOUT},
213 {"write_filemarks", IO_TIMEOUT},
215
216typedef enum {
223 SA_PARAM_WP = 0x020,
227 SA_PARAM_ALL = 0x1ff
229
230typedef enum {
232 SA_QUIRK_NOCOMP = 0x001, /* Can't deal with compression at all*/
233 SA_QUIRK_FIXED = 0x002, /* Force fixed mode */
234 SA_QUIRK_VARIABLE = 0x004, /* Force variable mode */
235 SA_QUIRK_2FM = 0x008, /* Needs Two File Marks at EOD */
236 SA_QUIRK_1FM = 0x010, /* No more than 1 File Mark at EOD */
237 SA_QUIRK_NODREAD = 0x020, /* Don't try and dummy read density */
238 SA_QUIRK_NO_MODESEL = 0x040, /* Don't do mode select at all */
239 SA_QUIRK_NO_CPAGE = 0x080, /* Don't use DEVICE COMPRESSION page */
240 SA_QUIRK_NO_LONG_POS = 0x100 /* No long position information */
242
243#define SA_QUIRK_BIT_STRING \
244 "\020" \
245 "\001NOCOMP" \
246 "\002FIXED" \
247 "\003VARIABLE" \
248 "\0042FM" \
249 "\0051FM" \
250 "\006NODREAD" \
251 "\007NO_MODESEL" \
252 "\010NO_CPAGE" \
253 "\011NO_LONG_POS"
254
255#define SAMODE(z) (dev2unit(z) & 0x3)
256#define SA_IS_CTRL(z) (dev2unit(z) & (1 << 4))
257
258#define SA_NOT_CTLDEV 0
259#define SA_CTLDEV 1
260
261#define SA_ATYPE_R 0
262#define SA_ATYPE_NR 1
263#define SA_ATYPE_ER 2
264#define SA_NUM_ATYPES 3
265
266#define SAMINOR(ctl, access) \
267 ((ctl << 4) | (access & 0x3))
268
269struct sa_devs {
270 struct cdev *ctl_dev;
271 struct cdev *r_dev;
272 struct cdev *nr_dev;
273 struct cdev *er_dev;
274};
275
276#define SASBADDBASE(sb, indent, data, xfmt, name, type, xsize, desc) \
277 sbuf_printf(sb, "%*s<%s type=\"%s\" size=\"%zd\" " \
278 "fmt=\"%s\" desc=\"%s\">" #xfmt "</%s>\n", indent, "", \
279 #name, #type, xsize, #xfmt, desc ? desc : "", data, #name);
280
281#define SASBADDINT(sb, indent, data, fmt, name) \
282 SASBADDBASE(sb, indent, data, fmt, name, int, sizeof(data), \
283 NULL)
284
285#define SASBADDINTDESC(sb, indent, data, fmt, name, desc) \
286 SASBADDBASE(sb, indent, data, fmt, name, int, sizeof(data), \
287 desc)
288
289#define SASBADDUINT(sb, indent, data, fmt, name) \
290 SASBADDBASE(sb, indent, data, fmt, name, uint, sizeof(data), \
291 NULL)
292
293#define SASBADDUINTDESC(sb, indent, data, fmt, name, desc) \
294 SASBADDBASE(sb, indent, data, fmt, name, uint, sizeof(data), \
295 desc)
296
297#define SASBADDFIXEDSTR(sb, indent, data, fmt, name) \
298 SASBADDBASE(sb, indent, data, fmt, name, str, sizeof(data), \
299 NULL)
300
301#define SASBADDFIXEDSTRDESC(sb, indent, data, fmt, name, desc) \
302 SASBADDBASE(sb, indent, data, fmt, name, str, sizeof(data), \
303 desc)
304
305#define SASBADDVARSTR(sb, indent, data, fmt, name, maxlen) \
306 SASBADDBASE(sb, indent, data, fmt, name, str, maxlen, NULL)
307
308#define SASBADDVARSTRDESC(sb, indent, data, fmt, name, maxlen, desc) \
309 SASBADDBASE(sb, indent, data, fmt, name, str, maxlen, desc)
310
311#define SASBADDNODE(sb, indent, name) { \
312 sbuf_printf(sb, "%*s<%s type=\"%s\">\n", indent, "", #name, \
313 "node"); \
314 indent += 2; \
315}
316
317#define SASBADDNODENUM(sb, indent, name, num) { \
318 sbuf_printf(sb, "%*s<%s type=\"%s\" num=\"%d\">\n", indent, "", \
319 #name, "node", num); \
320 indent += 2; \
321}
322
323#define SASBENDNODE(sb, indent, name) { \
324 indent -= 2; \
325 sbuf_printf(sb, "%*s</%s>\n", indent, "", #name); \
326}
327
328#define SA_DENSITY_TYPES 4
329
332 uint32_t prot_method;
333 uint32_t pi_length;
334 uint32_t lbp_w;
335 uint32_t lbp_r;
336 uint32_t rbdp;
337};
338
342};
343
344/*
345 * A table mapping protection parameters to their types and values.
346 */
348 char *name;
349 mt_param_set_type param_type;
350 off_t offset;
351 uint32_t min_val;
352 uint32_t max_val;
353 uint32_t *value;
354} sa_prot_table[] = {
355 { "prot_method", MT_PARAM_SET_UNSIGNED,
356 __offsetof(struct sa_prot_state, prot_method),
357 /*min_val*/ 0, /*max_val*/ 255, NULL },
358 { "pi_length", MT_PARAM_SET_UNSIGNED,
359 __offsetof(struct sa_prot_state, pi_length),
360 /*min_val*/ 0, /*max_val*/ SA_CTRL_DP_PI_LENGTH_MASK, NULL },
361 { "lbp_w", MT_PARAM_SET_UNSIGNED,
362 __offsetof(struct sa_prot_state, lbp_w),
363 /*min_val*/ 0, /*max_val*/ 1, NULL },
364 { "lbp_r", MT_PARAM_SET_UNSIGNED,
365 __offsetof(struct sa_prot_state, lbp_r),
366 /*min_val*/ 0, /*max_val*/ 1, NULL },
367 { "rbdp", MT_PARAM_SET_UNSIGNED,
368 __offsetof(struct sa_prot_state, rbdp),
369 /*min_val*/ 0, /*max_val*/ 1, NULL }
371
372#define SA_NUM_PROT_ENTS nitems(sa_prot_table)
373
374#define SA_PROT_ENABLED(softc) ((softc->flags & SA_FLAG_PROTECT_SUPP) \
375 && (softc->prot_info.cur_prot_state.initialized != 0) \
376 && (softc->prot_info.cur_prot_state.prot_method != 0))
377
378#define SA_PROT_LEN(softc) softc->prot_info.cur_prot_state.pi_length
379
380struct sa_softc {
384 u_int si_flags;
386 struct bio_queue_head bio_queue;
388 struct devstat *device_stats;
389 struct sa_devs devs;
395 u_int32_t max_blk;
396 u_int32_t min_blk;
397 u_int32_t maxio;
398 u_int32_t cpi_maxio;
402 u_int32_t comp_algorithm;
404 u_int32_t media_blksize;
406 u_int32_t media_numblks;
408 u_int8_t speed;
409 u_int8_t scsi_rev;
410 u_int8_t dsreg; /* mtio mt_dsreg, redux */
418
420
421 int sili;
423
424 /*
425 * Current position information. -1 means that the given value is
426 * unknown. fileno and blkno are always calculated. blkno is
427 * relative to the previous file mark. rep_fileno and rep_blkno
428 * are as reported by the drive, if it supports the long form
429 * report for the READ POSITION command. rep_blkno is relative to
430 * the beginning of the partition.
431 *
432 * bop means that the drive is at the beginning of the partition.
433 * eop means that the drive is between early warning and end of
434 * partition, inside the current partition.
435 * bpew means that the position is in a PEWZ (Programmable Early
436 * Warning Zone)
437 */
438 daddr_t partition; /* Absolute from BOT */
439 daddr_t fileno; /* Relative to beginning of partition */
440 daddr_t blkno; /* Relative to last file mark */
441 daddr_t rep_blkno; /* Relative to beginning of partition */
442 daddr_t rep_fileno; /* Relative to beginning of partition */
443 int bop; /* Beginning of Partition */
444 int eop; /* End of Partition */
445 int bpew; /* Beyond Programmable Early Warning */
446
447 /*
448 * Latched Error Info
449 */
450 struct {
452 u_int64_t _last_io_resid;
457#define last_io_sense errinfo._last_io_sense
458#define last_io_resid errinfo._last_io_resid
459#define last_io_cdb errinfo._last_io_cdb
460#define last_ctl_sense errinfo._last_ctl_sense
461#define last_ctl_resid errinfo._last_ctl_resid
462#define last_ctl_cdb errinfo._last_ctl_cdb
464 /*
465 * Misc other flags/state
466 */
467 u_int32_t
468 : 29,
469 open_rdonly : 1, /* open read-only */
470 open_pending_mount : 1, /* open pending mount */
471 ctrl_mode : 1; /* control device open */
472
473 struct task sysctl_task;
474 struct sysctl_ctx_list sysctl_ctx;
475 struct sysctl_oid *sysctl_tree;
476 struct sysctl_ctx_list sysctl_timeout_ctx;
477 struct sysctl_oid *sysctl_timeout_tree;
478};
479
481 struct scsi_inquiry_pattern inq_pat; /* matching pattern */
482 sa_quirks quirks; /* specific quirk type */
483 u_int32_t prefblk; /* preferred blocksize when in fixed mode */
484};
485
487{
488 {
489 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "OnStream",
490 "ADR*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_NODREAD |
492 },
493 {
494 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
495 "Python 06408*", "*"}, SA_QUIRK_NODREAD, 0
496 },
497 {
498 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
499 "Python 25601*", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_NODREAD, 0
500 },
501 {
502 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
503 "Python*", "*"}, SA_QUIRK_NODREAD, 0
504 },
505 {
506 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
507 "VIPER 150*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
508 },
509 {
510 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
511 "VIPER 2525 25462", "-011"},
513 },
514 {
515 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "ARCHIVE",
516 "VIPER 2525*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024
517 },
518#if 0
519 {
521 "C15*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_NO_CPAGE, 0,
522 },
523#endif
524 {
526 "C56*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
527 },
528 {
530 "T20*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
531 },
532 {
534 "T4000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
535 },
536 {
538 "HP-88780*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
539 },
540 {
541 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "KENNEDY",
542 "*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
543 },
544 {
545 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "M4 DATA",
546 "123107 SCSI*", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
547 },
548 { /* jreynold@primenet.com */
549 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "Seagate",
550 "STT8000N*", "*"}, SA_QUIRK_1FM, 0
551 },
552 { /* mike@sentex.net */
553 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "Seagate",
554 "STT20000*", "*"}, SA_QUIRK_1FM, 0
555 },
556 {
557 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "SEAGATE",
558 "DAT 06241-XXX", "*"}, SA_QUIRK_VARIABLE|SA_QUIRK_2FM, 0
559 },
560 {
561 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
562 " TDC 3600", "U07:"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
563 },
564 {
565 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
566 " TDC 3800", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
567 },
568 {
569 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
570 " TDC 4100", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
571 },
572 {
573 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
574 " TDC 4200", "*"}, SA_QUIRK_NOCOMP|SA_QUIRK_1FM, 512
575 },
576 {
577 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "TANDBERG",
578 " SLR*", "*"}, SA_QUIRK_1FM, 0
579 },
580 {
581 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK",
582 "5525ES*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 512
583 },
584 {
585 { T_SEQUENTIAL, SIP_MEDIA_REMOVABLE, "WANGTEK",
586 "51000*", "*"}, SA_QUIRK_FIXED|SA_QUIRK_1FM, 1024
587 }
588};
589
590static d_open_t saopen;
591static d_close_t saclose;
592static d_strategy_t sastrategy;
593static d_ioctl_t saioctl;
599static void saasync(void *callback_arg, u_int32_t code,
600 struct cam_path *path, void *arg);
601static void sadone(struct cam_periph *periph,
602 union ccb *start_ccb);
603static int saerror(union ccb *ccb, u_int32_t cam_flags,
604 u_int32_t sense_flags);
605static int samarkswanted(struct cam_periph *);
606static int sacheckeod(struct cam_periph *periph);
607static int sagetparams(struct cam_periph *periph,
608 sa_params params_to_get,
609 u_int32_t *blocksize, u_int8_t *density,
610 u_int32_t *numblocks, int *buff_mode,
611 u_int8_t *write_protect, u_int8_t *speed,
612 int *comp_supported, int *comp_enabled,
613 u_int32_t *comp_algorithm,
614 sa_comp_t *comp_page,
616 *prot_page, int dp_size,
617 int prot_changeable);
618static int sasetprot(struct cam_periph *periph,
619 struct sa_prot_state *new_prot);
620static int sasetparams(struct cam_periph *periph,
621 sa_params params_to_set,
622 u_int32_t blocksize, u_int8_t density,
623 u_int32_t comp_algorithm,
624 u_int32_t sense_flags);
625static int sasetsili(struct cam_periph *periph,
626 struct mtparamset *ps, int num_params);
627static int saseteotwarn(struct cam_periph *periph,
628 struct mtparamset *ps, int num_params);
629static void safillprot(struct sa_softc *softc, int *indent,
630 struct sbuf *sb);
631static void sapopulateprots(struct sa_prot_state *cur_state,
632 struct sa_prot_map *new_table,
633 int table_ents);
634static struct sa_prot_map *safindprotent(char *name, struct sa_prot_map *table,
635 int table_ents);
636static int sasetprotents(struct cam_periph *periph,
637 struct mtparamset *ps, int num_params);
638static struct sa_param_ent *safindparament(struct mtparamset *ps);
639static int saparamsetlist(struct cam_periph *periph,
640 struct mtsetlist *list, int need_copy);
641static int saextget(struct cdev *dev, struct cam_periph *periph,
642 struct sbuf *sb, struct mtextget *g);
643static int saparamget(struct sa_softc *softc, struct sbuf *sb);
644static void saprevent(struct cam_periph *periph, int action);
645static int sarewind(struct cam_periph *periph);
646static int saspace(struct cam_periph *periph, int count,
647 scsi_space_code code);
648static void sadevgonecb(void *arg);
649static void sasetupdev(struct sa_softc *softc, struct cdev *dev);
650static void saloadtotunables(struct sa_softc *softc);
651static void sasysctlinit(void *context, int pending);
652static int samount(struct cam_periph *, int, struct cdev *);
653static int saretension(struct cam_periph *periph);
654static int sareservereleaseunit(struct cam_periph *periph,
655 int reserve);
656static int saloadunload(struct cam_periph *periph, int load);
657static int saerase(struct cam_periph *periph, int longerase);
658static int sawritefilemarks(struct cam_periph *periph,
659 int nmarks, int setmarks, int immed);
660static int sagetpos(struct cam_periph *periph);
661static int sardpos(struct cam_periph *periph, int, u_int32_t *);
662static int sasetpos(struct cam_periph *periph, int,
663 struct mtlocate *);
664static void safilldenstypesb(struct sbuf *sb, int *indent,
665 uint8_t *buf, int buf_len,
666 int is_density);
667static void safilldensitysb(struct sa_softc *softc, int *indent,
668 struct sbuf *sb);
669static void saloadtimeouts(struct sa_softc *softc, union ccb *ccb);
670
671#ifndef SA_DEFAULT_IO_SPLIT
672#define SA_DEFAULT_IO_SPLIT 0
673#endif
674
676
677/*
678 * Tunable to allow the user to set a global allow_io_split value. Note
679 * that this WILL GO AWAY in FreeBSD 11.0. Silently splitting the I/O up
680 * is bad behavior, because it hides the true tape block size from the
681 * application.
682 */
683static SYSCTL_NODE(_kern_cam, OID_AUTO, sa, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
684 "CAM Sequential Access Tape Driver");
685SYSCTL_INT(_kern_cam_sa, OID_AUTO, allow_io_split, CTLFLAG_RDTUN,
686 &sa_allow_io_split, 0, "Default I/O split value");
687
688static struct periph_driver sadriver =
689{
690 sainit, "sa",
691 TAILQ_HEAD_INITIALIZER(sadriver.units), /* generation */ 0
692};
693
695
696/* For 2.2-stable support */
697#ifndef D_TAPE
698#define D_TAPE 0
699#endif
700
701static struct cdevsw sa_cdevsw = {
702 .d_version = D_VERSION,
703 .d_open = saopen,
704 .d_close = saclose,
705 .d_read = physread,
706 .d_write = physwrite,
707 .d_ioctl = saioctl,
708 .d_strategy = sastrategy,
709 .d_name = "sa",
710 .d_flags = D_TAPE | D_TRACKCLOSE,
711};
712
713static int
714saopen(struct cdev *dev, int flags, int fmt, struct thread *td)
715{
716 struct cam_periph *periph;
717 struct sa_softc *softc;
718 int error;
719
720 periph = (struct cam_periph *)dev->si_drv1;
721 if (cam_periph_acquire(periph) != 0) {
722 return (ENXIO);
723 }
724
725 cam_periph_lock(periph);
726
727 softc = (struct sa_softc *)periph->softc;
728
730 ("saopen(%s): softc=0x%x\n", devtoname(dev), softc->flags));
731
732 if (SA_IS_CTRL(dev)) {
733 softc->ctrl_mode = 1;
734 softc->open_count++;
736 return (0);
737 }
738
739 if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
742 return (error);
743 }
744
745 if (softc->flags & SA_FLAG_OPEN) {
746 error = EBUSY;
747 } else if (softc->flags & SA_FLAG_INVALID) {
748 error = ENXIO;
749 } else {
750 /*
751 * Preserve whether this is a read_only open.
752 */
753 softc->open_rdonly = (flags & O_RDWR) == O_RDONLY;
754
755 /*
756 * The function samount ensures media is loaded and ready.
757 * It also does a device RESERVE if the tape isn't yet mounted.
758 *
759 * If the mount fails and this was a non-blocking open,
760 * make this a 'open_pending_mount' action.
761 */
762 error = samount(periph, flags, dev);
763 if (error && (flags & O_NONBLOCK)) {
764 softc->flags |= SA_FLAG_OPEN;
765 softc->open_pending_mount = 1;
766 softc->open_count++;
769 return (0);
770 }
771 }
772
773 if (error) {
777 return (error);
778 }
779
781 softc->flags |= SA_FLAG_OPEN;
782 softc->open_count++;
783
786 return (error);
787}
788
789static int
790saclose(struct cdev *dev, int flag, int fmt, struct thread *td)
791{
792 struct cam_periph *periph;
793 struct sa_softc *softc;
794 int mode, error, writing, tmp, i;
795 int closedbits = SA_FLAG_OPEN;
796
797 mode = SAMODE(dev);
798 periph = (struct cam_periph *)dev->si_drv1;
799 cam_periph_lock(periph);
800
801 softc = (struct sa_softc *)periph->softc;
802
804 ("saclose(%s): softc=0x%x\n", devtoname(dev), softc->flags));
805
806 softc->open_rdonly = 0;
807 if (SA_IS_CTRL(dev)) {
808 softc->ctrl_mode = 0;
809 softc->open_count--;
812 return (0);
813 }
814
815 if (softc->open_pending_mount) {
816 softc->flags &= ~SA_FLAG_OPEN;
817 softc->open_pending_mount = 0;
818 softc->open_count--;
821 return (0);
822 }
823
824 if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
826 return (error);
827 }
828
829 /*
830 * Were we writing the tape?
831 */
832 writing = (softc->flags & SA_FLAG_TAPE_WRITTEN) != 0;
833
834 /*
835 * See whether or not we need to write filemarks. If this
836 * fails, we probably have to assume we've lost tape
837 * position.
838 */
839 error = sacheckeod(periph);
840 if (error) {
842 "failed to write terminating filemark(s)\n");
843 softc->flags |= SA_FLAG_TAPE_FROZEN;
844 }
845
846 /*
847 * Whatever we end up doing, allow users to eject tapes from here on.
848 */
850
851 /*
852 * Decide how to end...
853 */
854 if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) {
855 closedbits |= SA_FLAG_TAPE_FROZEN;
856 } else switch (mode) {
857 case SA_MODE_OFFLINE:
858 /*
859 * An 'offline' close is an unconditional release of
860 * frozen && mount conditions, irrespective of whether
861 * these operations succeeded. The reason for this is
862 * to allow at least some kind of programmatic way
863 * around our state getting all fouled up. If somebody
864 * issues an 'offline' command, that will be allowed
865 * to clear state.
866 */
867 (void) sarewind(periph);
868 (void) saloadunload(periph, FALSE);
870 break;
871 case SA_MODE_REWIND:
872 /*
873 * If the rewind fails, return an error- if anyone cares,
874 * but not overwriting any previous error.
875 *
876 * We don't clear the notion of mounted here, but we do
877 * clear the notion of frozen if we successfully rewound.
878 */
879 tmp = sarewind(periph);
880 if (tmp) {
881 if (error != 0)
882 error = tmp;
883 } else {
884 closedbits |= SA_FLAG_TAPE_FROZEN;
885 }
886 break;
887 case SA_MODE_NOREWIND:
888 /*
889 * If we're not rewinding/unloading the tape, find out
890 * whether we need to back up over one of two filemarks
891 * we wrote (if we wrote two filemarks) so that appends
892 * from this point on will be sane.
893 */
894 if (error == 0 && writing && (softc->quirks & SA_QUIRK_2FM)) {
895 tmp = saspace(periph, -1, SS_FILEMARKS);
896 if (tmp) {
897 xpt_print(periph->path, "unable to backspace "
898 "over one of double filemarks at end of "
899 "tape\n");
900 xpt_print(periph->path, "it is possible that "
901 "this device needs a SA_QUIRK_1FM quirk set"
902 "for it\n");
903 softc->flags |= SA_FLAG_TAPE_FROZEN;
904 }
905 }
906 break;
907 default:
908 xpt_print(periph->path, "unknown mode 0x%x in saclose\n", mode);
909 /* NOTREACHED */
910 break;
911 }
912
913 /*
914 * We wish to note here that there are no more filemarks to be written.
915 */
916 softc->filemarks = 0;
917 softc->flags &= ~SA_FLAG_TAPE_WRITTEN;
918
919 /*
920 * And we are no longer open for business.
921 */
922 softc->flags &= ~closedbits;
923 softc->open_count--;
924
925 /*
926 * Invalidate any density information that depends on having tape
927 * media in the drive.
928 */
929 for (i = 0; i < SA_DENSITY_TYPES; i++) {
930 if (softc->density_type_bits[i] & SRDS_MEDIA)
931 softc->density_info_valid[i] = 0;
932 }
933
934 /*
935 * Inform users if tape state if frozen....
936 */
937 if (softc->flags & SA_FLAG_TAPE_FROZEN) {
938 xpt_print(periph->path, "tape is now frozen- use an OFFLINE, "
939 "REWIND or MTEOM command to clear this state.\n");
940 }
941
942 /* release the device if it is no longer mounted */
943 if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0)
945
949
950 return (error);
951}
952
953/*
954 * Actually translate the requested transfer into one the physical driver
955 * can understand. The transfer is described by a buf and will include
956 * only one physical transfer.
957 */
958static void
959sastrategy(struct bio *bp)
960{
961 struct cam_periph *periph;
962 struct sa_softc *softc;
963
964 bp->bio_resid = bp->bio_bcount;
965 if (SA_IS_CTRL(bp->bio_dev)) {
966 biofinish(bp, NULL, EINVAL);
967 return;
968 }
969 periph = (struct cam_periph *)bp->bio_dev->si_drv1;
970 cam_periph_lock(periph);
971
972 softc = (struct sa_softc *)periph->softc;
973
974 if (softc->flags & SA_FLAG_INVALID) {
976 biofinish(bp, NULL, ENXIO);
977 return;
978 }
979
980 if (softc->flags & SA_FLAG_TAPE_FROZEN) {
982 biofinish(bp, NULL, EPERM);
983 return;
984 }
985
986 /*
987 * This should actually never occur as the write(2)
988 * system call traps attempts to write to a read-only
989 * file descriptor.
990 */
991 if (bp->bio_cmd == BIO_WRITE && softc->open_rdonly) {
993 biofinish(bp, NULL, EBADF);
994 return;
995 }
996
997 if (softc->open_pending_mount) {
998 int error = samount(periph, 0, bp->bio_dev);
999 if (error) {
1001 biofinish(bp, NULL, ENXIO);
1002 return;
1003 }
1005 softc->open_pending_mount = 0;
1006 }
1007
1008 /*
1009 * If it's a null transfer, return immediately
1010 */
1011 if (bp->bio_bcount == 0) {
1013 biodone(bp);
1014 return;
1015 }
1016
1017 /* valid request? */
1018 if (softc->flags & SA_FLAG_FIXED) {
1019 /*
1020 * Fixed block device. The byte count must
1021 * be a multiple of our block size.
1022 */
1023 if (((softc->blk_mask != ~0) &&
1024 ((bp->bio_bcount & softc->blk_mask) != 0)) ||
1025 ((softc->blk_mask == ~0) &&
1026 ((bp->bio_bcount % softc->min_blk) != 0))) {
1027 xpt_print(periph->path, "Invalid request. Fixed block "
1028 "device requests must be a multiple of %d bytes\n",
1029 softc->min_blk);
1031 biofinish(bp, NULL, EINVAL);
1032 return;
1033 }
1034 } else if ((bp->bio_bcount > softc->max_blk) ||
1035 (bp->bio_bcount < softc->min_blk) ||
1036 (bp->bio_bcount & softc->blk_mask) != 0) {
1038 printf("Invalid request. Variable block "
1039 "device requests must be ");
1040 if (softc->blk_mask != 0) {
1041 printf("a multiple of %d ", (0x1 << softc->blk_gran));
1042 }
1043 printf("between %d and %d bytes\n", softc->min_blk,
1044 softc->max_blk);
1046 biofinish(bp, NULL, EINVAL);
1047 return;
1048 }
1049
1050 /*
1051 * Place it at the end of the queue.
1052 */
1053 bioq_insert_tail(&softc->bio_queue, bp);
1054 softc->queue_count++;
1055#if 0
1057 ("sastrategy: queuing a %ld %s byte %s\n", bp->bio_bcount,
1058 (softc->flags & SA_FLAG_FIXED)? "fixed" : "variable",
1059 (bp->bio_cmd == BIO_READ)? "read" : "write"));
1060#endif
1061 if (softc->queue_count > 1) {
1063 ("sastrategy: queue count now %d\n", softc->queue_count));
1064 }
1065
1066 /*
1067 * Schedule ourselves for performing the work.
1068 */
1071
1072 return;
1073}
1074
1075static int
1076sasetsili(struct cam_periph *periph, struct mtparamset *ps, int num_params)
1077{
1078 uint32_t sili_blocksize;
1079 struct sa_softc *softc;
1080 int error;
1081
1082 error = 0;
1083 softc = (struct sa_softc *)periph->softc;
1084
1085 if (ps->value_type != MT_PARAM_SET_SIGNED) {
1086 snprintf(ps->error_str, sizeof(ps->error_str),
1087 "sili is a signed parameter");
1088 goto bailout;
1089 }
1090 if ((ps->value.value_signed < 0)
1091 || (ps->value.value_signed > 1)) {
1092 snprintf(ps->error_str, sizeof(ps->error_str),
1093 "invalid sili value %jd", (intmax_t)ps->value.value_signed);
1094 goto bailout_error;
1095 }
1096 /*
1097 * We only set the SILI flag in variable block
1098 * mode. You'll get a check condition in fixed
1099 * block mode if things don't line up in any case.
1100 */
1101 if (softc->flags & SA_FLAG_FIXED) {
1102 snprintf(ps->error_str, sizeof(ps->error_str),
1103 "can't set sili bit in fixed block mode");
1104 goto bailout_error;
1105 }
1106 if (softc->sili == ps->value.value_signed)
1107 goto bailout;
1108
1109 if (ps->value.value_signed == 1)
1110 sili_blocksize = 4;
1111 else
1112 sili_blocksize = 0;
1113
1115 sili_blocksize, 0, 0, SF_QUIET_IR);
1116 if (error != 0) {
1117 snprintf(ps->error_str, sizeof(ps->error_str),
1118 "sasetparams() returned error %d", error);
1119 goto bailout_error;
1120 }
1121
1122 softc->sili = ps->value.value_signed;
1123
1124bailout:
1125 ps->status = MT_PARAM_STATUS_OK;
1126 return (error);
1127
1128bailout_error:
1129 ps->status = MT_PARAM_STATUS_ERROR;
1130 if (error == 0)
1131 error = EINVAL;
1132
1133 return (error);
1134}
1135
1136static int
1137saseteotwarn(struct cam_periph *periph, struct mtparamset *ps, int num_params)
1138{
1139 struct sa_softc *softc;
1140 int error;
1141
1142 error = 0;
1143 softc = (struct sa_softc *)periph->softc;
1144
1145 if (ps->value_type != MT_PARAM_SET_SIGNED) {
1146 snprintf(ps->error_str, sizeof(ps->error_str),
1147 "eot_warn is a signed parameter");
1148 ps->status = MT_PARAM_STATUS_ERROR;
1149 goto bailout;
1150 }
1151 if ((ps->value.value_signed < 0)
1152 || (ps->value.value_signed > 1)) {
1153 snprintf(ps->error_str, sizeof(ps->error_str),
1154 "invalid eot_warn value %jd\n",
1155 (intmax_t)ps->value.value_signed);
1156 ps->status = MT_PARAM_STATUS_ERROR;
1157 goto bailout;
1158 }
1159 softc->eot_warn = ps->value.value_signed;
1160 ps->status = MT_PARAM_STATUS_OK;
1161bailout:
1162 if (ps->status != MT_PARAM_STATUS_OK)
1163 error = EINVAL;
1164
1165 return (error);
1166}
1167
1168static void
1169safillprot(struct sa_softc *softc, int *indent, struct sbuf *sb)
1170{
1171 int tmpint;
1172
1173 SASBADDNODE(sb, *indent, protection);
1174 if (softc->flags & SA_FLAG_PROTECT_SUPP)
1175 tmpint = 1;
1176 else
1177 tmpint = 0;
1178 SASBADDINTDESC(sb, *indent, tmpint, %d, protection_supported,
1179 "Set to 1 if protection information is supported");
1180
1181 if ((tmpint != 0)
1182 && (softc->prot_info.cur_prot_state.initialized != 0)) {
1183 struct sa_prot_state *prot;
1184
1185 prot = &softc->prot_info.cur_prot_state;
1186
1187 SASBADDUINTDESC(sb, *indent, prot->prot_method, %u,
1188 prot_method, "Current Protection Method");
1189 SASBADDUINTDESC(sb, *indent, prot->pi_length, %u,
1190 pi_length, "Length of Protection Information");
1191 SASBADDUINTDESC(sb, *indent, prot->lbp_w, %u,
1192 lbp_w, "Check Protection on Writes");
1193 SASBADDUINTDESC(sb, *indent, prot->lbp_r, %u,
1194 lbp_r, "Check and Include Protection on Reads");
1195 SASBADDUINTDESC(sb, *indent, prot->rbdp, %u,
1196 rbdp, "Transfer Protection Information for RECOVER "
1197 "BUFFERED DATA command");
1198 }
1199 SASBENDNODE(sb, *indent, protection);
1200}
1201
1202static void
1203sapopulateprots(struct sa_prot_state *cur_state, struct sa_prot_map *new_table,
1204 int table_ents)
1205{
1206 int i;
1207
1208 bcopy(sa_prot_table, new_table, min(table_ents * sizeof(*new_table),
1209 sizeof(sa_prot_table)));
1210
1211 table_ents = min(table_ents, SA_NUM_PROT_ENTS);
1212
1213 for (i = 0; i < table_ents; i++)
1214 new_table[i].value = (uint32_t *)((uint8_t *)cur_state +
1215 new_table[i].offset);
1216
1217 return;
1218}
1219
1220static struct sa_prot_map *
1221safindprotent(char *name, struct sa_prot_map *table, int table_ents)
1222{
1223 char *prot_name = "protection.";
1224 int i, prot_len;
1225
1226 prot_len = strlen(prot_name);
1227
1228 /*
1229 * This shouldn't happen, but we check just in case.
1230 */
1231 if (strncmp(name, prot_name, prot_len) != 0)
1232 goto bailout;
1233
1234 for (i = 0; i < table_ents; i++) {
1235 if (strcmp(&name[prot_len], table[i].name) != 0)
1236 continue;
1237 return (&table[i]);
1238 }
1239bailout:
1240 return (NULL);
1241}
1242
1243static int
1244sasetprotents(struct cam_periph *periph, struct mtparamset *ps, int num_params)
1245{
1246 struct sa_softc *softc;
1247 struct sa_prot_map prot_ents[SA_NUM_PROT_ENTS];
1248 struct sa_prot_state new_state;
1249 int error;
1250 int i;
1251
1252 softc = (struct sa_softc *)periph->softc;
1253 error = 0;
1254
1255 /*
1256 * Make sure that this tape drive supports protection information.
1257 * Otherwise we can't set anything.
1258 */
1259 if ((softc->flags & SA_FLAG_PROTECT_SUPP) == 0) {
1260 snprintf(ps[0].error_str, sizeof(ps[0].error_str),
1261 "Protection information is not supported for this device");
1262 ps[0].status = MT_PARAM_STATUS_ERROR;
1263 goto bailout;
1264 }
1265
1266 /*
1267 * We can't operate with physio(9) splitting enabled, because there
1268 * is no way to insure (especially in variable block mode) that
1269 * what the user writes (with a checksum block at the end) will
1270 * make it into the sa(4) driver intact.
1271 */
1272 if ((softc->si_flags & SI_NOSPLIT) == 0) {
1273 snprintf(ps[0].error_str, sizeof(ps[0].error_str),
1274 "Protection information cannot be enabled with I/O "
1275 "splitting");
1276 ps[0].status = MT_PARAM_STATUS_ERROR;
1277 goto bailout;
1278 }
1279
1280 /*
1281 * Take the current cached protection state and use that as the
1282 * basis for our new entries.
1283 */
1284 bcopy(&softc->prot_info.cur_prot_state, &new_state, sizeof(new_state));
1285
1286 /*
1287 * Populate the table mapping property names to pointers into the
1288 * state structure.
1289 */
1290 sapopulateprots(&new_state, prot_ents, SA_NUM_PROT_ENTS);
1291
1292 /*
1293 * For each parameter the user passed in, make sure the name, type
1294 * and value are valid.
1295 */
1296 for (i = 0; i < num_params; i++) {
1297 struct sa_prot_map *ent;
1298
1299 ent = safindprotent(ps[i].value_name, prot_ents,
1301 if (ent == NULL) {
1302 ps[i].status = MT_PARAM_STATUS_ERROR;
1303 snprintf(ps[i].error_str, sizeof(ps[i].error_str),
1304 "Invalid protection entry name %s",
1305 ps[i].value_name);
1306 error = EINVAL;
1307 goto bailout;
1308 }
1309 if (ent->param_type != ps[i].value_type) {
1310 ps[i].status = MT_PARAM_STATUS_ERROR;
1311 snprintf(ps[i].error_str, sizeof(ps[i].error_str),
1312 "Supplied type %d does not match actual type %d",
1313 ps[i].value_type, ent->param_type);
1314 error = EINVAL;
1315 goto bailout;
1316 }
1317 if ((ps[i].value.value_unsigned < ent->min_val)
1318 || (ps[i].value.value_unsigned > ent->max_val)) {
1319 ps[i].status = MT_PARAM_STATUS_ERROR;
1320 snprintf(ps[i].error_str, sizeof(ps[i].error_str),
1321 "Value %ju is outside valid range %u - %u",
1322 (uintmax_t)ps[i].value.value_unsigned, ent->min_val,
1323 ent->max_val);
1324 error = EINVAL;
1325 goto bailout;
1326 }
1327 *(ent->value) = ps[i].value.value_unsigned;
1328 }
1329
1330 /*
1331 * Actually send the protection settings to the drive.
1332 */
1333 error = sasetprot(periph, &new_state);
1334 if (error != 0) {
1335 for (i = 0; i < num_params; i++) {
1336 ps[i].status = MT_PARAM_STATUS_ERROR;
1337 snprintf(ps[i].error_str, sizeof(ps[i].error_str),
1338 "Unable to set parameter, see dmesg(8)");
1339 }
1340 goto bailout;
1341 }
1342
1343 /*
1344 * Let the user know that his settings were stored successfully.
1345 */
1346 for (i = 0; i < num_params; i++)
1347 ps[i].status = MT_PARAM_STATUS_OK;
1348
1349bailout:
1350 return (error);
1351}
1352/*
1353 * Entry handlers generally only handle a single entry. Node handlers will
1354 * handle a contiguous range of parameters to set in a single call.
1355 */
1356typedef enum {
1360
1362 char *name;
1364 int (*set_func)(struct cam_periph *periph, struct mtparamset *ps,
1365 int num_params);
1366} sa_param_table[] = {
1367 {"sili", SA_PARAM_TYPE_ENTRY, sasetsili },
1368 {"eot_warn", SA_PARAM_TYPE_ENTRY, saseteotwarn },
1369 {"protection.", SA_PARAM_TYPE_NODE, sasetprotents }
1371
1372static struct sa_param_ent *
1373safindparament(struct mtparamset *ps)
1374{
1375 unsigned int i;
1376
1377 for (i = 0; i < nitems(sa_param_table); i++){
1378 /*
1379 * For entries, we compare all of the characters. For
1380 * nodes, we only compare the first N characters. The node
1381 * handler will decode the rest.
1382 */
1384 if (strcmp(ps->value_name, sa_param_table[i].name) != 0)
1385 continue;
1386 } else {
1387 if (strncmp(ps->value_name, sa_param_table[i].name,
1388 strlen(sa_param_table[i].name)) != 0)
1389 continue;
1390 }
1391 return (&sa_param_table[i]);
1392 }
1393
1394 return (NULL);
1395}
1396
1397/*
1398 * Go through a list of parameters, coalescing contiguous parameters with
1399 * the same parent node into a single call to a set_func.
1400 */
1401static int
1402saparamsetlist(struct cam_periph *periph, struct mtsetlist *list,
1403 int need_copy)
1404{
1405 int i, contig_ents;
1406 int error;
1407 struct mtparamset *params, *first;
1408 struct sa_param_ent *first_ent;
1409
1410 error = 0;
1411 params = NULL;
1412
1413 if (list->num_params == 0)
1414 /* Nothing to do */
1415 goto bailout;
1416
1417 /*
1418 * Verify that the user has the correct structure size.
1419 */
1420 if ((list->num_params * sizeof(struct mtparamset)) !=
1421 list->param_len) {
1422 xpt_print(periph->path, "%s: length of params %d != "
1423 "sizeof(struct mtparamset) %zd * num_params %d\n",
1424 __func__, list->param_len, sizeof(struct mtparamset),
1425 list->num_params);
1426 error = EINVAL;
1427 goto bailout;
1428 }
1429
1430 if (need_copy != 0) {
1431 /*
1432 * XXX KDM will dropping the lock cause an issue here?
1433 */
1434 cam_periph_unlock(periph);
1435 params = malloc(list->param_len, M_SCSISA, M_WAITOK | M_ZERO);
1436 error = copyin(list->params, params, list->param_len);
1437 cam_periph_lock(periph);
1438
1439 if (error != 0)
1440 goto bailout;
1441 } else {
1442 params = list->params;
1443 }
1444
1445 contig_ents = 0;
1446 first = NULL;
1447 first_ent = NULL;
1448 for (i = 0; i < list->num_params; i++) {
1449 struct sa_param_ent *ent;
1450
1451 ent = safindparament(&params[i]);
1452 if (ent == NULL) {
1453 snprintf(params[i].error_str,
1454 sizeof(params[i].error_str),
1455 "%s: cannot find parameter %s", __func__,
1456 params[i].value_name);
1457 params[i].status = MT_PARAM_STATUS_ERROR;
1458 break;
1459 }
1460
1461 if (first != NULL) {
1462 if (first_ent == ent) {
1463 /*
1464 * We're still in a contiguous list of
1465 * parameters that can be handled by one
1466 * node handler.
1467 */
1468 contig_ents++;
1469 continue;
1470 } else {
1471 error = first_ent->set_func(periph, first,
1472 contig_ents);
1473 first = NULL;
1474 first_ent = NULL;
1475 contig_ents = 0;
1476 if (error != 0) {
1477 error = 0;
1478 break;
1479 }
1480 }
1481 }
1482 if (ent->param_type == SA_PARAM_TYPE_NODE) {
1483 first = &params[i];
1484 first_ent = ent;
1485 contig_ents = 1;
1486 } else {
1487 error = ent->set_func(periph, &params[i], 1);
1488 if (error != 0) {
1489 error = 0;
1490 break;
1491 }
1492 }
1493 }
1494 if (first != NULL)
1495 first_ent->set_func(periph, first, contig_ents);
1496
1497bailout:
1498 if (need_copy != 0) {
1499 if (error != EFAULT) {
1500 cam_periph_unlock(periph);
1501 copyout(params, list->params, list->param_len);
1502 cam_periph_lock(periph);
1503 }
1504 free(params, M_SCSISA);
1505 }
1506 return (error);
1507}
1508
1509static int
1510sagetparams_common(struct cdev *dev, struct cam_periph *periph)
1511{
1512 struct sa_softc *softc;
1513 u_int8_t write_protect;
1514 int comp_enabled, comp_supported, error;
1515
1516 softc = (struct sa_softc *)periph->softc;
1517
1518 if (softc->open_pending_mount)
1519 return (0);
1520
1521 /* The control device may issue getparams() if there are no opens. */
1522 if (SA_IS_CTRL(dev) && (softc->flags & SA_FLAG_OPEN) != 0)
1523 return (0);
1524
1525 error = sagetparams(periph, SA_PARAM_ALL, &softc->media_blksize,
1526 &softc->media_density, &softc->media_numblks, &softc->buffer_mode,
1527 &write_protect, &softc->speed, &comp_supported, &comp_enabled,
1528 &softc->comp_algorithm, NULL, NULL, 0, 0);
1529 if (error)
1530 return (error);
1531 if (write_protect)
1532 softc->flags |= SA_FLAG_TAPE_WP;
1533 else
1534 softc->flags &= ~SA_FLAG_TAPE_WP;
1535 softc->flags &= ~SA_FLAG_COMPRESSION;
1536 if (comp_supported) {
1537 if (softc->saved_comp_algorithm == 0)
1538 softc->saved_comp_algorithm =
1539 softc->comp_algorithm;
1540 softc->flags |= SA_FLAG_COMP_SUPP;
1541 if (comp_enabled)
1542 softc->flags |= SA_FLAG_COMP_ENABLED;
1543 } else
1544 softc->flags |= SA_FLAG_COMP_UNSUPP;
1545
1546 return (0);
1547}
1548
1549#define PENDING_MOUNT_CHECK(softc, periph, dev) \
1550 if (softc->open_pending_mount) { \
1551 error = samount(periph, 0, dev); \
1552 if (error) { \
1553 break; \
1554 } \
1555 saprevent(periph, PR_PREVENT); \
1556 softc->open_pending_mount = 0; \
1557 }
1558
1559static int
1560saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
1561{
1562 struct cam_periph *periph;
1563 struct sa_softc *softc;
1564 scsi_space_code spaceop;
1565 int didlockperiph = 0;
1566 int mode;
1567 int error = 0;
1568
1569 mode = SAMODE(dev);
1570 error = 0; /* shut up gcc */
1571 spaceop = 0; /* shut up gcc */
1572
1573 periph = (struct cam_periph *)dev->si_drv1;
1574 cam_periph_lock(periph);
1575 softc = (struct sa_softc *)periph->softc;
1576
1577 /*
1578 * Check for control mode accesses. We allow MTIOCGET and
1579 * MTIOCERRSTAT (but need to be the only one open in order
1580 * to clear latched status), and MTSETBSIZE, MTSETDNSTY
1581 * and MTCOMP (but need to be the only one accessing this
1582 * device to run those).
1583 */
1584
1585 if (SA_IS_CTRL(dev)) {
1586 switch (cmd) {
1587 case MTIOCGETEOTMODEL:
1588 case MTIOCGET:
1589 case MTIOCEXTGET:
1590 case MTIOCPARAMGET:
1591 case MTIOCRBLIM:
1592 break;
1593 case MTIOCERRSTAT:
1594 /*
1595 * If the periph isn't already locked, lock it
1596 * so our MTIOCERRSTAT can reset latched error stats.
1597 *
1598 * If the periph is already locked, skip it because
1599 * we're just getting status and it'll be up to the
1600 * other thread that has this device open to do
1601 * an MTIOCERRSTAT that would clear latched status.
1602 */
1603 if ((periph->flags & CAM_PERIPH_LOCKED) == 0) {
1604 error = cam_periph_hold(periph, PRIBIO|PCATCH);
1605 if (error != 0) {
1607 return (error);
1608 }
1609 didlockperiph = 1;
1610 }
1611 break;
1612
1613 case MTIOCTOP:
1614 {
1615 struct mtop *mt = (struct mtop *) arg;
1616
1617 /*
1618 * Check to make sure it's an OP we can perform
1619 * with no media inserted.
1620 */
1621 switch (mt->mt_op) {
1622 case MTSETBSIZ:
1623 case MTSETDNSTY:
1624 case MTCOMP:
1625 mt = NULL;
1626 /* FALLTHROUGH */
1627 default:
1628 break;
1629 }
1630 if (mt != NULL) {
1631 break;
1632 }
1633 /* FALLTHROUGH */
1634 }
1635 case MTIOCSETEOTMODEL:
1636 /*
1637 * We need to acquire the peripheral here rather
1638 * than at open time because we are sharing writable
1639 * access to data structures.
1640 */
1641 error = cam_periph_hold(periph, PRIBIO|PCATCH);
1642 if (error != 0) {
1643 cam_periph_unlock(periph);
1644 return (error);
1645 }
1646 didlockperiph = 1;
1647 break;
1648
1649 default:
1650 cam_periph_unlock(periph);
1651 return (EINVAL);
1652 }
1653 }
1654
1655 /*
1656 * Find the device that the user is talking about
1657 */
1658 switch (cmd) {
1659 case MTIOCGET:
1660 {
1661 struct mtget *g = (struct mtget *)arg;
1662
1663 error = sagetparams_common(dev, periph);
1664 if (error)
1665 break;
1666 bzero(g, sizeof(struct mtget));
1667 g->mt_type = MT_ISAR;
1668 if (softc->flags & SA_FLAG_COMP_UNSUPP) {
1669 g->mt_comp = MT_COMP_UNSUPP;
1670 g->mt_comp0 = MT_COMP_UNSUPP;
1671 g->mt_comp1 = MT_COMP_UNSUPP;
1672 g->mt_comp2 = MT_COMP_UNSUPP;
1673 g->mt_comp3 = MT_COMP_UNSUPP;
1674 } else {
1675 if ((softc->flags & SA_FLAG_COMP_ENABLED) == 0) {
1676 g->mt_comp = MT_COMP_DISABLED;
1677 } else {
1678 g->mt_comp = softc->comp_algorithm;
1679 }
1680 g->mt_comp0 = softc->comp_algorithm;
1681 g->mt_comp1 = softc->comp_algorithm;
1682 g->mt_comp2 = softc->comp_algorithm;
1683 g->mt_comp3 = softc->comp_algorithm;
1684 }
1685 g->mt_density = softc->media_density;
1686 g->mt_density0 = softc->media_density;
1687 g->mt_density1 = softc->media_density;
1688 g->mt_density2 = softc->media_density;
1689 g->mt_density3 = softc->media_density;
1690 g->mt_blksiz = softc->media_blksize;
1691 g->mt_blksiz0 = softc->media_blksize;
1692 g->mt_blksiz1 = softc->media_blksize;
1693 g->mt_blksiz2 = softc->media_blksize;
1694 g->mt_blksiz3 = softc->media_blksize;
1695 g->mt_fileno = softc->fileno;
1696 g->mt_blkno = softc->blkno;
1697 g->mt_dsreg = (short) softc->dsreg;
1698 /*
1699 * Yes, we know that this is likely to overflow
1700 */
1701 if (softc->last_resid_was_io) {
1702 if ((g->mt_resid = (short) softc->last_io_resid) != 0) {
1703 if (SA_IS_CTRL(dev) == 0 || didlockperiph) {
1704 softc->last_io_resid = 0;
1705 }
1706 }
1707 } else {
1708 if ((g->mt_resid = (short)softc->last_ctl_resid) != 0) {
1709 if (SA_IS_CTRL(dev) == 0 || didlockperiph) {
1710 softc->last_ctl_resid = 0;
1711 }
1712 }
1713 }
1714 error = 0;
1715 break;
1716 }
1717 case MTIOCEXTGET:
1718 case MTIOCPARAMGET:
1719 {
1720 struct mtextget *g = (struct mtextget *)arg;
1721 char *tmpstr2;
1722 struct sbuf *sb;
1723
1724 /*
1725 * Report drive status using an XML format.
1726 */
1727
1728 /*
1729 * XXX KDM will dropping the lock cause any problems here?
1730 */
1731 cam_periph_unlock(periph);
1732 sb = sbuf_new(NULL, NULL, g->alloc_len, SBUF_FIXEDLEN);
1733 if (sb == NULL) {
1734 g->status = MT_EXT_GET_ERROR;
1735 snprintf(g->error_str, sizeof(g->error_str),
1736 "Unable to allocate %d bytes for status info",
1737 g->alloc_len);
1738 cam_periph_lock(periph);
1739 goto extget_bailout;
1740 }
1741 cam_periph_lock(periph);
1742
1743 if (cmd == MTIOCEXTGET)
1744 error = saextget(dev, periph, sb, g);
1745 else
1746 error = saparamget(softc, sb);
1747
1748 if (error != 0)
1749 goto extget_bailout;
1750
1751 error = sbuf_finish(sb);
1752 if (error == ENOMEM) {
1753 g->status = MT_EXT_GET_NEED_MORE_SPACE;
1754 error = 0;
1755 } else if (error != 0) {
1756 g->status = MT_EXT_GET_ERROR;
1757 snprintf(g->error_str, sizeof(g->error_str),
1758 "Error %d returned from sbuf_finish()", error);
1759 } else
1760 g->status = MT_EXT_GET_OK;
1761
1762 error = 0;
1763 tmpstr2 = sbuf_data(sb);
1764 g->fill_len = strlen(tmpstr2) + 1;
1765 cam_periph_unlock(periph);
1766
1767 error = copyout(tmpstr2, g->status_xml, g->fill_len);
1768
1769 cam_periph_lock(periph);
1770
1771extget_bailout:
1772 sbuf_delete(sb);
1773 break;
1774 }
1775 case MTIOCPARAMSET:
1776 {
1777 struct mtsetlist list;
1778 struct mtparamset *ps = (struct mtparamset *)arg;
1779
1780 bzero(&list, sizeof(list));
1781 list.num_params = 1;
1782 list.param_len = sizeof(*ps);
1783 list.params = ps;
1784
1785 error = saparamsetlist(periph, &list, /*need_copy*/ 0);
1786 break;
1787 }
1788 case MTIOCSETLIST:
1789 {
1790 struct mtsetlist *list = (struct mtsetlist *)arg;
1791
1792 error = saparamsetlist(periph, list, /*need_copy*/ 1);
1793 break;
1794 }
1795 case MTIOCERRSTAT:
1796 {
1797 struct scsi_tape_errors *sep =
1798 &((union mterrstat *)arg)->scsi_errstat;
1799
1801 ("saioctl: MTIOCERRSTAT\n"));
1802
1803 bzero(sep, sizeof(*sep));
1804 sep->io_resid = softc->last_io_resid;
1805 bcopy((caddr_t) &softc->last_io_sense, sep->io_sense,
1806 sizeof (sep->io_sense));
1807 bcopy((caddr_t) &softc->last_io_cdb, sep->io_cdb,
1808 sizeof (sep->io_cdb));
1809 sep->ctl_resid = softc->last_ctl_resid;
1810 bcopy((caddr_t) &softc->last_ctl_sense, sep->ctl_sense,
1811 sizeof (sep->ctl_sense));
1812 bcopy((caddr_t) &softc->last_ctl_cdb, sep->ctl_cdb,
1813 sizeof (sep->ctl_cdb));
1814
1815 if ((SA_IS_CTRL(dev) == 0 && !softc->open_pending_mount) ||
1816 didlockperiph)
1817 bzero((caddr_t) &softc->errinfo,
1818 sizeof (softc->errinfo));
1819 error = 0;
1820 break;
1821 }
1822 case MTIOCTOP:
1823 {
1824 struct mtop *mt;
1825 int count;
1826
1827 PENDING_MOUNT_CHECK(softc, periph, dev);
1828
1829 mt = (struct mtop *)arg;
1830
1832 ("saioctl: op=0x%x count=0x%x\n",
1833 mt->mt_op, mt->mt_count));
1834
1835 count = mt->mt_count;
1836 switch (mt->mt_op) {
1837 case MTWEOF: /* write an end-of-file marker */
1838 /*
1839 * We don't need to clear the SA_FLAG_TAPE_WRITTEN
1840 * flag because by keeping track of filemarks
1841 * we have last written we know whether or not
1842 * we need to write more when we close the device.
1843 */
1844 error = sawritefilemarks(periph, count, FALSE, FALSE);
1845 break;
1846 case MTWEOFI:
1847 /* write an end-of-file marker without waiting */
1848 error = sawritefilemarks(periph, count, FALSE, TRUE);
1849 break;
1850 case MTWSS: /* write a setmark */
1851 error = sawritefilemarks(periph, count, TRUE, FALSE);
1852 break;
1853 case MTBSR: /* backward space record */
1854 case MTFSR: /* forward space record */
1855 case MTBSF: /* backward space file */
1856 case MTFSF: /* forward space file */
1857 case MTBSS: /* backward space setmark */
1858 case MTFSS: /* forward space setmark */
1859 case MTEOD: /* space to end of recorded medium */
1860 {
1861 int nmarks;
1862
1863 spaceop = SS_FILEMARKS;
1864 nmarks = softc->filemarks;
1865 error = sacheckeod(periph);
1866 if (error) {
1867 xpt_print(periph->path,
1868 "EOD check prior to spacing failed\n");
1869 softc->flags |= SA_FLAG_EIO_PENDING;
1870 break;
1871 }
1872 nmarks -= softc->filemarks;
1873 switch(mt->mt_op) {
1874 case MTBSR:
1875 count = -count;
1876 /* FALLTHROUGH */
1877 case MTFSR:
1878 spaceop = SS_BLOCKS;
1879 break;
1880 case MTBSF:
1881 count = -count;
1882 /* FALLTHROUGH */
1883 case MTFSF:
1884 break;
1885 case MTBSS:
1886 count = -count;
1887 /* FALLTHROUGH */
1888 case MTFSS:
1889 spaceop = SS_SETMARKS;
1890 break;
1891 case MTEOD:
1892 spaceop = SS_EOD;
1893 count = 0;
1894 nmarks = 0;
1895 break;
1896 default:
1897 error = EINVAL;
1898 break;
1899 }
1900 if (error)
1901 break;
1902
1903 nmarks = softc->filemarks;
1904 /*
1905 * XXX: Why are we checking again?
1906 */
1907 error = sacheckeod(periph);
1908 if (error)
1909 break;
1910 nmarks -= softc->filemarks;
1911 error = saspace(periph, count - nmarks, spaceop);
1912 /*
1913 * At this point, clear that we've written the tape
1914 * and that we've written any filemarks. We really
1915 * don't know what the applications wishes to do next-
1916 * the sacheckeod's will make sure we terminated the
1917 * tape correctly if we'd been writing, but the next
1918 * action the user application takes will set again
1919 * whether we need to write filemarks.
1920 */
1921 softc->flags &=
1923 softc->filemarks = 0;
1924 break;
1925 }
1926 case MTREW: /* rewind */
1927 PENDING_MOUNT_CHECK(softc, periph, dev);
1928 (void) sacheckeod(periph);
1929 error = sarewind(periph);
1930 /* see above */
1931 softc->flags &=
1933 softc->flags &= ~SA_FLAG_ERR_PENDING;
1934 softc->filemarks = 0;
1935 break;
1936 case MTERASE: /* erase */
1937 PENDING_MOUNT_CHECK(softc, periph, dev);
1938 error = saerase(periph, count);
1939 softc->flags &=
1941 softc->flags &= ~SA_FLAG_ERR_PENDING;
1942 break;
1943 case MTRETENS: /* re-tension tape */
1944 PENDING_MOUNT_CHECK(softc, periph, dev);
1945 error = saretension(periph);
1946 softc->flags &=
1948 softc->flags &= ~SA_FLAG_ERR_PENDING;
1949 break;
1950 case MTOFFL: /* rewind and put the drive offline */
1951
1952 PENDING_MOUNT_CHECK(softc, periph, dev);
1953
1954 (void) sacheckeod(periph);
1955 /* see above */
1956 softc->flags &= ~SA_FLAG_TAPE_WRITTEN;
1957 softc->filemarks = 0;
1958
1959 error = sarewind(periph);
1960 /* clear the frozen flag anyway */
1961 softc->flags &= ~SA_FLAG_TAPE_FROZEN;
1962
1963 /*
1964 * Be sure to allow media removal before ejecting.
1965 */
1966
1967 saprevent(periph, PR_ALLOW);
1968 if (error == 0) {
1969 error = saloadunload(periph, FALSE);
1970 if (error == 0) {
1971 softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
1972 }
1973 }
1974 break;
1975
1976 case MTLOAD:
1977 error = saloadunload(periph, TRUE);
1978 break;
1979 case MTNOP: /* no operation, sets status only */
1980 case MTCACHE: /* enable controller cache */
1981 case MTNOCACHE: /* disable controller cache */
1982 error = 0;
1983 break;
1984
1985 case MTSETBSIZ: /* Set block size for device */
1986
1987 PENDING_MOUNT_CHECK(softc, periph, dev);
1988
1989 if ((softc->sili != 0)
1990 && (count != 0)) {
1991 xpt_print(periph->path, "Can't enter fixed "
1992 "block mode with SILI enabled\n");
1993 error = EINVAL;
1994 break;
1995 }
1996 error = sasetparams(periph, SA_PARAM_BLOCKSIZE, count,
1997 0, 0, 0);
1998 if (error == 0) {
1999 softc->last_media_blksize =
2000 softc->media_blksize;
2001 softc->media_blksize = count;
2002 if (count) {
2003 softc->flags |= SA_FLAG_FIXED;
2004 if (powerof2(count)) {
2005 softc->blk_shift =
2006 ffs(count) - 1;
2007 softc->blk_mask = count - 1;
2008 } else {
2009 softc->blk_mask = ~0;
2010 softc->blk_shift = 0;
2011 }
2012 /*
2013 * Make the user's desire 'persistent'.
2014 */
2015 softc->quirks &= ~SA_QUIRK_VARIABLE;
2016 softc->quirks |= SA_QUIRK_FIXED;
2017 } else {
2018 softc->flags &= ~SA_FLAG_FIXED;
2019 if (softc->max_blk == 0) {
2020 softc->max_blk = ~0;
2021 }
2022 softc->blk_shift = 0;
2023 if (softc->blk_gran != 0) {
2024 softc->blk_mask =
2025 softc->blk_gran - 1;
2026 } else {
2027 softc->blk_mask = 0;
2028 }
2029 /*
2030 * Make the user's desire 'persistent'.
2031 */
2032 softc->quirks |= SA_QUIRK_VARIABLE;
2033 softc->quirks &= ~SA_QUIRK_FIXED;
2034 }
2035 }
2036 break;
2037 case MTSETDNSTY: /* Set density for device and mode */
2038 PENDING_MOUNT_CHECK(softc, periph, dev);
2039
2040 if (count > UCHAR_MAX) {
2041 error = EINVAL;
2042 break;
2043 } else {
2044 error = sasetparams(periph, SA_PARAM_DENSITY,
2045 0, count, 0, 0);
2046 }
2047 break;
2048 case MTCOMP: /* enable compression */
2049 PENDING_MOUNT_CHECK(softc, periph, dev);
2050 /*
2051 * Some devices don't support compression, and
2052 * don't like it if you ask them for the
2053 * compression page.
2054 */
2055 if ((softc->quirks & SA_QUIRK_NOCOMP) ||
2056 (softc->flags & SA_FLAG_COMP_UNSUPP)) {
2057 error = ENODEV;
2058 break;
2059 }
2060 error = sasetparams(periph, SA_PARAM_COMPRESSION,
2061 0, 0, count, SF_NO_PRINT);
2062 break;
2063 default:
2064 error = EINVAL;
2065 }
2066 break;
2067 }
2068 case MTIOCIEOT:
2069 case MTIOCEEOT:
2070 error = 0;
2071 break;
2072 case MTIOCRDSPOS:
2073 PENDING_MOUNT_CHECK(softc, periph, dev);
2074 error = sardpos(periph, 0, (u_int32_t *) arg);
2075 break;
2076 case MTIOCRDHPOS:
2077 PENDING_MOUNT_CHECK(softc, periph, dev);
2078 error = sardpos(periph, 1, (u_int32_t *) arg);
2079 break;
2080 case MTIOCSLOCATE:
2081 case MTIOCHLOCATE: {
2082 struct mtlocate locate_info;
2083 int hard;
2084
2085 bzero(&locate_info, sizeof(locate_info));
2086 locate_info.logical_id = *((uint32_t *)arg);
2087 if (cmd == MTIOCSLOCATE)
2088 hard = 0;
2089 else
2090 hard = 1;
2091
2092 PENDING_MOUNT_CHECK(softc, periph, dev);
2093
2094 error = sasetpos(periph, hard, &locate_info);
2095 break;
2096 }
2097 case MTIOCEXTLOCATE:
2098 PENDING_MOUNT_CHECK(softc, periph, dev);
2099 error = sasetpos(periph, /*hard*/ 0, (struct mtlocate *)arg);
2100 softc->flags &=
2102 softc->flags &= ~SA_FLAG_ERR_PENDING;
2103 softc->filemarks = 0;
2104 break;
2105 case MTIOCGETEOTMODEL:
2106 error = 0;
2107 if (softc->quirks & SA_QUIRK_1FM)
2108 mode = 1;
2109 else
2110 mode = 2;
2111 *((u_int32_t *) arg) = mode;
2112 break;
2113 case MTIOCSETEOTMODEL:
2114 error = 0;
2115 switch (*((u_int32_t *) arg)) {
2116 case 1:
2117 softc->quirks &= ~SA_QUIRK_2FM;
2118 softc->quirks |= SA_QUIRK_1FM;
2119 break;
2120 case 2:
2121 softc->quirks &= ~SA_QUIRK_1FM;
2122 softc->quirks |= SA_QUIRK_2FM;
2123 break;
2124 default:
2125 error = EINVAL;
2126 break;
2127 }
2128 break;
2129 case MTIOCRBLIM: {
2130 struct mtrblim *rblim;
2131
2132 rblim = (struct mtrblim *)arg;
2133
2134 rblim->granularity = softc->blk_gran;
2135 rblim->min_block_length = softc->min_blk;
2136 rblim->max_block_length = softc->max_blk;
2137 break;
2138 }
2139 default:
2140 error = cam_periph_ioctl(periph, cmd, arg, saerror);
2141 break;
2142 }
2143
2144 /*
2145 * Check to see if we cleared a frozen state
2146 */
2147 if (error == 0 && (softc->flags & SA_FLAG_TAPE_FROZEN)) {
2148 switch(cmd) {
2149 case MTIOCRDSPOS:
2150 case MTIOCRDHPOS:
2151 case MTIOCSLOCATE:
2152 case MTIOCHLOCATE:
2153 /*
2154 * XXX KDM look at this.
2155 */
2156 softc->fileno = (daddr_t) -1;
2157 softc->blkno = (daddr_t) -1;
2158 softc->rep_blkno = (daddr_t) -1;
2159 softc->rep_fileno = (daddr_t) -1;
2160 softc->partition = (daddr_t) -1;
2161 softc->flags &= ~SA_FLAG_TAPE_FROZEN;
2162 xpt_print(periph->path,
2163 "tape state now unfrozen.\n");
2164 break;
2165 default:
2166 break;
2167 }
2168 }
2169 if (didlockperiph) {
2170 cam_periph_unhold(periph);
2171 }
2172 cam_periph_unlock(periph);
2173 return (error);
2174}
2175
2176static void
2177sainit(void)
2178{
2179 cam_status status;
2180
2181 /*
2182 * Install a global async callback.
2183 */
2184 status = xpt_register_async(AC_FOUND_DEVICE, saasync, NULL, NULL);
2185
2186 if (status != CAM_REQ_CMP) {
2187 printf("sa: Failed to attach master async callback "
2188 "due to status 0x%x!\n", status);
2189 }
2190}
2191
2192static void
2193sadevgonecb(void *arg)
2194{
2195 struct cam_periph *periph;
2196 struct mtx *mtx;
2197 struct sa_softc *softc;
2198
2199 periph = (struct cam_periph *)arg;
2200 softc = (struct sa_softc *)periph->softc;
2201
2202 mtx = cam_periph_mtx(periph);
2203 mtx_lock(mtx);
2204
2205 softc->num_devs_to_destroy--;
2206 if (softc->num_devs_to_destroy == 0) {
2207 int i;
2208
2209 /*
2210 * When we have gotten all of our callbacks, we will get
2211 * no more close calls from devfs. So if we have any
2212 * dangling opens, we need to release the reference held
2213 * for that particular context.
2214 */
2215 for (i = 0; i < softc->open_count; i++)
2217
2218 softc->open_count = 0;
2219
2220 /*
2221 * Release the reference held for devfs, all of our
2222 * instances are gone now.
2223 */
2225 }
2226
2227 /*
2228 * We reference the lock directly here, instead of using
2229 * cam_periph_unlock(). The reason is that the final call to
2230 * cam_periph_release_locked() above could result in the periph
2231 * getting freed. If that is the case, dereferencing the periph
2232 * with a cam_periph_unlock() call would cause a page fault.
2233 */
2234 mtx_unlock(mtx);
2235}
2236
2237static void
2239{
2240 struct sa_softc *softc;
2241
2242 softc = (struct sa_softc *)periph->softc;
2243
2244 /*
2245 * De-register any async callbacks.
2246 */
2248
2249 softc->flags |= SA_FLAG_INVALID;
2250
2251 /*
2252 * Return all queued I/O with ENXIO.
2253 * XXX Handle any transactions queued to the card
2254 * with XPT_ABORT_CCB.
2255 */
2256 bioq_flush(&softc->bio_queue, NULL, ENXIO);
2257 softc->queue_count = 0;
2258
2259 /*
2260 * Tell devfs that all of our devices have gone away, and ask for a
2261 * callback when it has cleaned up its state.
2262 */
2263 destroy_dev_sched_cb(softc->devs.ctl_dev, sadevgonecb, periph);
2264 destroy_dev_sched_cb(softc->devs.r_dev, sadevgonecb, periph);
2265 destroy_dev_sched_cb(softc->devs.nr_dev, sadevgonecb, periph);
2266 destroy_dev_sched_cb(softc->devs.er_dev, sadevgonecb, periph);
2267}
2268
2269static void
2271{
2272 struct sa_softc *softc;
2273
2274 softc = (struct sa_softc *)periph->softc;
2275
2277
2278 if ((softc->flags & SA_FLAG_SCTX_INIT) != 0
2279 && (((softc->sysctl_timeout_tree != NULL)
2280 && (sysctl_ctx_free(&softc->sysctl_timeout_ctx) != 0))
2281 || sysctl_ctx_free(&softc->sysctl_ctx) != 0))
2282 xpt_print(periph->path, "can't remove sysctl context\n");
2283
2285
2286 devstat_remove_entry(softc->device_stats);
2287
2288 free(softc, M_SCSISA);
2289}
2290
2291static void
2292saasync(void *callback_arg, u_int32_t code,
2293 struct cam_path *path, void *arg)
2294{
2295 struct cam_periph *periph;
2296
2297 periph = (struct cam_periph *)callback_arg;
2298 switch (code) {
2299 case AC_FOUND_DEVICE:
2300 {
2301 struct ccb_getdev *cgd;
2302 cam_status status;
2303
2304 cgd = (struct ccb_getdev *)arg;
2305 if (cgd == NULL)
2306 break;
2307
2308 if (cgd->protocol != PROTO_SCSI)
2309 break;
2311 break;
2312 if (SID_TYPE(&cgd->inq_data) != T_SEQUENTIAL)
2313 break;
2314
2315 /*
2316 * Allocate a peripheral instance for
2317 * this device and start the probe
2318 * process.
2319 */
2322 "sa", CAM_PERIPH_BIO, path,
2323 saasync, AC_FOUND_DEVICE, cgd);
2324
2325 if (status != CAM_REQ_CMP
2326 && status != CAM_REQ_INPROG)
2327 printf("saasync: Unable to probe new device "
2328 "due to status 0x%x\n", status);
2329 break;
2330 }
2331 default:
2332 cam_periph_async(periph, code, path, arg);
2333 break;
2334 }
2335}
2336
2337static void
2338sasetupdev(struct sa_softc *softc, struct cdev *dev)
2339{
2340
2341 dev->si_iosize_max = softc->maxio;
2342 dev->si_flags |= softc->si_flags;
2343 /*
2344 * Keep a count of how many non-alias devices we have created,
2345 * so we can make sure we clean them all up on shutdown. Aliases
2346 * are cleaned up when we destroy the device they're an alias for.
2347 */
2348 if ((dev->si_flags & SI_ALIAS) == 0)
2349 softc->num_devs_to_destroy++;
2350}
2351
2352/*
2353 * Load the global (for all sa(4) instances) and per-instance tunable
2354 * values for timeouts for various sa(4) commands. This should be run
2355 * after the default timeouts are fetched from the drive, so the user's
2356 * preference will override the drive's defaults.
2357 */
2358static void
2360{
2361 int i;
2362 char tmpstr[80];
2363
2364 for (i = 0; i < SA_TIMEOUT_TYPE_MAX; i++) {
2365 int tmpval, retval;
2366
2367 /* First grab any global timeout setting */
2368 snprintf(tmpstr, sizeof(tmpstr), "kern.cam.sa.timeout.%s",
2369 sa_default_timeouts[i].desc);
2370 retval = TUNABLE_INT_FETCH(tmpstr, &tmpval);
2371 if (retval != 0)
2372 softc->timeout_info[i] = tmpval;
2373
2374 /*
2375 * Then overwrite any global timeout settings with
2376 * per-instance timeout settings.
2377 */
2378 snprintf(tmpstr, sizeof(tmpstr), "kern.cam.sa.%u.timeout.%s",
2380 retval = TUNABLE_INT_FETCH(tmpstr, &tmpval);
2381 if (retval != 0)
2382 softc->timeout_info[i] = tmpval;
2383 }
2384}
2385
2386static void
2387sasysctlinit(void *context, int pending)
2388{
2389 struct cam_periph *periph;
2390 struct sa_softc *softc;
2391 char tmpstr[64], tmpstr2[16];
2392 int i;
2393
2394 periph = (struct cam_periph *)context;
2395 /*
2396 * If the periph is invalid, no need to setup the sysctls.
2397 */
2398 if (periph->flags & CAM_PERIPH_INVALID)
2399 goto bailout;
2400
2401 softc = (struct sa_softc *)periph->softc;
2402
2403 snprintf(tmpstr, sizeof(tmpstr), "CAM SA unit %d", periph->unit_number);
2404 snprintf(tmpstr2, sizeof(tmpstr2), "%u", periph->unit_number);
2405
2406 sysctl_ctx_init(&softc->sysctl_ctx);
2407 softc->flags |= SA_FLAG_SCTX_INIT;
2408 softc->sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&softc->sysctl_ctx,
2409 SYSCTL_STATIC_CHILDREN(_kern_cam_sa), OID_AUTO, tmpstr2,
2410 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, tmpstr, "device_index");
2411 if (softc->sysctl_tree == NULL)
2412 goto bailout;
2413
2414 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2415 OID_AUTO, "allow_io_split", CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
2416 &softc->allow_io_split, 0, "Allow Splitting I/O");
2417 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2418 OID_AUTO, "maxio", CTLFLAG_RD,
2419 &softc->maxio, 0, "Maximum I/O size");
2420 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2421 OID_AUTO, "cpi_maxio", CTLFLAG_RD,
2422 &softc->cpi_maxio, 0, "Maximum Controller I/O size");
2423 SYSCTL_ADD_INT(&softc->sysctl_ctx, SYSCTL_CHILDREN(softc->sysctl_tree),
2424 OID_AUTO, "inject_eom", CTLFLAG_RW,
2425 &softc->inject_eom, 0, "Queue EOM for the next write/read");
2426
2427 sysctl_ctx_init(&softc->sysctl_timeout_ctx);
2428 softc->sysctl_timeout_tree = SYSCTL_ADD_NODE(&softc->sysctl_timeout_ctx,
2429 SYSCTL_CHILDREN(softc->sysctl_tree), OID_AUTO, "timeout",
2430 CTLFLAG_RD | CTLFLAG_MPSAFE, 0, "Timeouts");
2431 if (softc->sysctl_timeout_tree == NULL)
2432 goto bailout;
2433
2434 for (i = 0; i < SA_TIMEOUT_TYPE_MAX; i++) {
2435 snprintf(tmpstr, sizeof(tmpstr), "%s timeout",
2436 sa_default_timeouts[i].desc);
2437
2438 /*
2439 * Do NOT change this sysctl declaration to also load any
2440 * tunable values for this sa(4) instance. In other words,
2441 * do not change this to CTLFLAG_RWTUN. This function is
2442 * run in parallel with the probe routine that fetches
2443 * recommended timeout values from the tape drive, and we
2444 * don't want the values from the drive to override the
2445 * user's preference.
2446 */
2447 SYSCTL_ADD_INT(&softc->sysctl_timeout_ctx,
2448 SYSCTL_CHILDREN(softc->sysctl_timeout_tree),
2449 OID_AUTO, sa_default_timeouts[i].desc, CTLFLAG_RW,
2450 &softc->timeout_info[i], 0, tmpstr);
2451 }
2452
2453bailout:
2454 /*
2455 * Release the reference that was held when this task was enqueued.
2456 */
2458}
2459
2460static cam_status
2461saregister(struct cam_periph *periph, void *arg)
2462{
2463 struct sa_softc *softc;
2464 struct ccb_getdev *cgd;
2465 struct ccb_pathinq cpi;
2466 struct make_dev_args args;
2467 caddr_t match;
2468 char tmpstr[80];
2469 int error;
2470 int i;
2471
2472 cgd = (struct ccb_getdev *)arg;
2473 if (cgd == NULL) {
2474 printf("saregister: no getdev CCB, can't register device\n");
2475 return (CAM_REQ_CMP_ERR);
2476 }
2477
2478 softc = (struct sa_softc *)
2479 malloc(sizeof (*softc), M_SCSISA, M_NOWAIT | M_ZERO);
2480 if (softc == NULL) {
2481 printf("saregister: Unable to probe new device. "
2482 "Unable to allocate softc\n");
2483 return (CAM_REQ_CMP_ERR);
2484 }
2485 softc->scsi_rev = SID_ANSI_REV(&cgd->inq_data);
2486 softc->state = SA_STATE_NORMAL;
2487 softc->fileno = (daddr_t) -1;
2488 softc->blkno = (daddr_t) -1;
2489 softc->rep_fileno = (daddr_t) -1;
2490 softc->rep_blkno = (daddr_t) -1;
2491 softc->partition = (daddr_t) -1;
2492 softc->bop = -1;
2493 softc->eop = -1;
2494 softc->bpew = -1;
2495
2496 bioq_init(&softc->bio_queue);
2497 softc->periph = periph;
2498 periph->softc = softc;
2499
2500 /*
2501 * See if this device has any quirks.
2502 */
2503 match = cam_quirkmatch((caddr_t)&cgd->inq_data,
2504 (caddr_t)sa_quirk_table,
2505 nitems(sa_quirk_table),
2507
2508 if (match != NULL) {
2509 softc->quirks = ((struct sa_quirk_entry *)match)->quirks;
2510 softc->last_media_blksize =
2511 ((struct sa_quirk_entry *)match)->prefblk;
2512 } else
2513 softc->quirks = SA_QUIRK_NONE;
2514
2515
2516 /*
2517 * Initialize the default timeouts. If this drive supports
2518 * timeout descriptors we'll overwrite these values with the
2519 * recommended timeouts from the drive.
2520 */
2521 for (i = 0; i < SA_TIMEOUT_TYPE_MAX; i++)
2522 softc->timeout_info[i] = sa_default_timeouts[i].value;
2523
2524 /*
2525 * Long format data for READ POSITION was introduced in SSC, which
2526 * was after SCSI-2. (Roughly equivalent to SCSI-3.) If the drive
2527 * reports that it is SCSI-2 or older, it is unlikely to support
2528 * long position data, but it might. Some drives from that era
2529 * claim to be SCSI-2, but do support long position information.
2530 * So, instead of immediately disabling long position information
2531 * for SCSI-2 devices, we'll try one pass through sagetpos(), and
2532 * then disable long position information if we get an error.
2533 */
2534 if (cgd->inq_data.version <= SCSI_REV_CCS)
2535 softc->quirks |= SA_QUIRK_NO_LONG_POS;
2536
2537 /*
2538 * The SCSI REPORT SUPPORTED OPERATION CODES command was added in
2539 * SPC-4. That command optionally includes timeout data for
2540 * different commands. Timeout values can vary wildly among
2541 * different drives, so if the drive itself has recommended values,
2542 * we will try to use them. Set this flag to indicate we're going
2543 * to ask the drive for timeout data. This flag also tells us to
2544 * wait on loading timeout tunables so we can properly override
2545 * timeouts with any user-specified values.
2546 */
2547 if (SID_ANSI_REV(&cgd->inq_data) >= SCSI_REV_SPC4)
2548 softc->flags |= SA_FLAG_RSOC_TO_TRY;
2549
2551 struct ccb_dev_advinfo cdai;
2552 struct scsi_vpd_extended_inquiry_data ext_inq;
2553
2554 bzero(&ext_inq, sizeof(ext_inq));
2555
2556 memset(&cdai, 0, sizeof(cdai));
2558
2560 cdai.flags = CDAI_FLAG_NONE;
2562 cdai.bufsiz = sizeof(ext_inq);
2563 cdai.buf = (uint8_t *)&ext_inq;
2564 xpt_action((union ccb *)&cdai);
2565
2566 if ((cdai.ccb_h.status & CAM_DEV_QFRZN) != 0)
2567 cam_release_devq(cdai.ccb_h.path, 0, 0, 0, FALSE);
2568 if ((cdai.ccb_h.status == CAM_REQ_CMP)
2569 && (ext_inq.flags1 & SVPD_EID_SA_SPT_LBP))
2570 softc->flags |= SA_FLAG_PROTECT_SUPP;
2571 }
2572
2573 xpt_path_inq(&cpi, periph->path);
2574
2575 /*
2576 * The SA driver supports a blocksize, but we don't know the
2577 * blocksize until we media is inserted. So, set a flag to
2578 * indicate that the blocksize is unavailable right now.
2579 */
2580 cam_periph_unlock(periph);
2581 softc->device_stats = devstat_new_entry("sa", periph->unit_number, 0,
2582 DEVSTAT_BS_UNAVAILABLE, SID_TYPE(&cgd->inq_data) |
2583 XPORT_DEVSTAT_TYPE(cpi.transport), DEVSTAT_PRIORITY_TAPE);
2584
2585 /*
2586 * Load the default value that is either compiled in, or loaded
2587 * in the global kern.cam.sa.allow_io_split tunable.
2588 */
2590
2591 /*
2592 * Load a per-instance tunable, if it exists. NOTE that this
2593 * tunable WILL GO AWAY in FreeBSD 11.0.
2594 */
2595 snprintf(tmpstr, sizeof(tmpstr), "kern.cam.sa.%u.allow_io_split",
2596 periph->unit_number);
2597 TUNABLE_INT_FETCH(tmpstr, &softc->allow_io_split);
2598
2599 /*
2600 * If maxio isn't set, we fall back to DFLTPHYS. Otherwise we take
2601 * the smaller of cpi.maxio or maxphys.
2602 */
2603 if (cpi.maxio == 0)
2604 softc->maxio = DFLTPHYS;
2605 else if (cpi.maxio > maxphys)
2606 softc->maxio = maxphys;
2607 else
2608 softc->maxio = cpi.maxio;
2609
2610 /*
2611 * Record the controller's maximum I/O size so we can report it to
2612 * the user later.
2613 */
2614 softc->cpi_maxio = cpi.maxio;
2615
2616 /*
2617 * By default we tell physio that we do not want our I/O split.
2618 * The user needs to have a 1:1 mapping between the size of his
2619 * write to a tape character device and the size of the write
2620 * that actually goes down to the drive.
2621 */
2622 if (softc->allow_io_split == 0)
2623 softc->si_flags = SI_NOSPLIT;
2624 else
2625 softc->si_flags = 0;
2626
2627 TASK_INIT(&softc->sysctl_task, 0, sasysctlinit, periph);
2628
2629 /*
2630 * If the SIM supports unmapped I/O, let physio know that we can
2631 * handle unmapped buffers.
2632 */
2633 if (cpi.hba_misc & PIM_UNMAPPED)
2634 softc->si_flags |= SI_UNMAPPED;
2635
2636 /*
2637 * Acquire a reference to the periph before we create the devfs
2638 * instances for it. We'll release this reference once the devfs
2639 * instances have been freed.
2640 */
2641 if (cam_periph_acquire(periph) != 0) {
2642 xpt_print(periph->path, "%s: lost periph during "
2643 "registration!\n", __func__);
2644 cam_periph_lock(periph);
2645 return (CAM_REQ_CMP_ERR);
2646 }
2647
2648 make_dev_args_init(&args);
2649 args.mda_devsw = &sa_cdevsw;
2650 args.mda_si_drv1 = softc->periph;
2651 args.mda_uid = UID_ROOT;
2652 args.mda_gid = GID_OPERATOR;
2653 args.mda_mode = 0660;
2654
2655 args.mda_unit = SAMINOR(SA_CTLDEV, SA_ATYPE_R);
2656 error = make_dev_s(&args, &softc->devs.ctl_dev, "%s%d.ctl",
2657 periph->periph_name, periph->unit_number);
2658 if (error != 0) {
2659 cam_periph_lock(periph);
2660 return (CAM_REQ_CMP_ERR);
2661 }
2662 sasetupdev(softc, softc->devs.ctl_dev);
2663
2664 args.mda_unit = SAMINOR(SA_NOT_CTLDEV, SA_ATYPE_R);
2665 error = make_dev_s(&args, &softc->devs.r_dev, "%s%d",
2666 periph->periph_name, periph->unit_number);
2667 if (error != 0) {
2668 cam_periph_lock(periph);
2669 return (CAM_REQ_CMP_ERR);
2670 }
2671 sasetupdev(softc, softc->devs.r_dev);
2672
2673 args.mda_unit = SAMINOR(SA_NOT_CTLDEV, SA_ATYPE_NR);
2674 error = make_dev_s(&args, &softc->devs.nr_dev, "n%s%d",
2675 periph->periph_name, periph->unit_number);
2676 if (error != 0) {
2677 cam_periph_lock(periph);
2678 return (CAM_REQ_CMP_ERR);
2679 }
2680 sasetupdev(softc, softc->devs.nr_dev);
2681
2682 args.mda_unit = SAMINOR(SA_NOT_CTLDEV, SA_ATYPE_ER);
2683 error = make_dev_s(&args, &softc->devs.er_dev, "e%s%d",
2684 periph->periph_name, periph->unit_number);
2685 if (error != 0) {
2686 cam_periph_lock(periph);
2687 return (CAM_REQ_CMP_ERR);
2688 }
2689 sasetupdev(softc, softc->devs.er_dev);
2690
2691 cam_periph_lock(periph);
2692
2693 softc->density_type_bits[0] = 0;
2694 softc->density_type_bits[1] = SRDS_MEDIA;
2697 /*
2698 * Bump the peripheral refcount for the sysctl thread, in case we
2699 * get invalidated before the thread has a chance to run. Note
2700 * that this runs in parallel with the probe for the timeout
2701 * values.
2702 */
2703 cam_periph_acquire(periph);
2704 taskqueue_enqueue(taskqueue_thread, &softc->sysctl_task);
2705
2706 /*
2707 * Add an async callback so that we get
2708 * notified if this device goes away.
2709 */
2710 xpt_register_async(AC_LOST_DEVICE, saasync, periph, periph->path);
2711
2712 /*
2713 * See comment above, try fetching timeout values for drives that
2714 * might support it. Otherwise, use the defaults.
2715 *
2716 * We get timeouts from the following places in order of increasing
2717 * priority:
2718 * 1. Driver default timeouts.
2719 * 2. Timeouts loaded from the drive via REPORT SUPPORTED OPERATION
2720 * CODES. (We kick that off here if SA_FLAG_RSOC_TO_TRY is set.)
2721 * 3. Global loader tunables, used for all sa(4) driver instances on
2722 * a machine.
2723 * 4. Instance-specific loader tunables, used for say sa5.
2724 * 5. On the fly user sysctl changes.
2725 *
2726 * Each step will overwrite the timeout value set from the one
2727 * before, so you go from general to most specific.
2728 */
2729 if (softc->flags & SA_FLAG_RSOC_TO_TRY) {
2730 /*
2731 * Bump the peripheral refcount while we are probing.
2732 */
2733 cam_periph_acquire(periph);
2734 softc->state = SA_STATE_PROBE;
2736 } else {
2737 /*
2738 * This drive doesn't support Report Supported Operation
2739 * Codes, so we load the tunables at this point to bring
2740 * in any user preferences.
2741 */
2742 saloadtotunables(softc);
2743
2744 xpt_announce_periph(periph, NULL);
2746 }
2747
2748 return (CAM_REQ_CMP);
2749}
2750
2751static void
2752sastart(struct cam_periph *periph, union ccb *start_ccb)
2753{
2754 struct sa_softc *softc;
2755
2756 softc = (struct sa_softc *)periph->softc;
2757
2758 CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("sastart\n"));
2759
2760 switch (softc->state) {
2761 case SA_STATE_NORMAL:
2762 {
2763 /* Pull a buffer from the queue and get going on it */
2764 struct bio *bp;
2765
2766 /*
2767 * See if there is a buf with work for us to do..
2768 */
2769 bp = bioq_first(&softc->bio_queue);
2770 if (bp == NULL) {
2771 xpt_release_ccb(start_ccb);
2772 } else if (((softc->flags & SA_FLAG_ERR_PENDING) != 0)
2773 || (softc->inject_eom != 0)) {
2774 struct bio *done_bp;
2775
2776 if (softc->inject_eom != 0) {
2777 softc->flags |= SA_FLAG_EOM_PENDING;
2778 softc->inject_eom = 0;
2779 /*
2780 * If we're injecting EOM for writes, we
2781 * need to keep PEWS set for 3 queries
2782 * to cover 2 position requests from the
2783 * kernel via sagetpos(), and then allow
2784 * for one for the user to see the BPEW
2785 * flag (e.g. via mt status). After that,
2786 * it will be cleared.
2787 */
2788 if (bp->bio_cmd == BIO_WRITE)
2789 softc->set_pews_status = 3;
2790 else
2791 softc->set_pews_status = 1;
2792 }
2793again:
2794 softc->queue_count--;
2795 bioq_remove(&softc->bio_queue, bp);
2796 bp->bio_resid = bp->bio_bcount;
2797 done_bp = bp;
2798 if ((softc->flags & SA_FLAG_EOM_PENDING) != 0) {
2799 /*
2800 * We have two different behaviors for
2801 * writes when we hit either Early Warning
2802 * or the PEWZ (Programmable Early Warning
2803 * Zone). The default behavior is that
2804 * for all writes that are currently
2805 * queued after the write where we saw the
2806 * early warning, we will return the write
2807 * with the residual equal to the count.
2808 * i.e. tell the application that 0 bytes
2809 * were written.
2810 *
2811 * The alternate behavior, which is enabled
2812 * when eot_warn is set, is that in
2813 * addition to setting the residual equal
2814 * to the count, we will set the error
2815 * to ENOSPC.
2816 *
2817 * In either case, once queued writes are
2818 * cleared out, we clear the error flag
2819 * (see below) and the application is free to
2820 * attempt to write more.
2821 */
2822 if (softc->eot_warn != 0) {
2823 bp->bio_flags |= BIO_ERROR;
2824 bp->bio_error = ENOSPC;
2825 } else
2826 bp->bio_error = 0;
2827 } else if ((softc->flags & SA_FLAG_EOF_PENDING) != 0) {
2828 /*
2829 * This can only happen if we're reading
2830 * in fixed length mode. In this case,
2831 * we dump the rest of the list the
2832 * same way.
2833 */
2834 bp->bio_error = 0;
2835 if (bioq_first(&softc->bio_queue) != NULL) {
2836 biodone(done_bp);
2837 goto again;
2838 }
2839 } else if ((softc->flags & SA_FLAG_EIO_PENDING) != 0) {
2840 bp->bio_error = EIO;
2841 bp->bio_flags |= BIO_ERROR;
2842 }
2843 bp = bioq_first(&softc->bio_queue);
2844 /*
2845 * Only if we have no other buffers queued up
2846 * do we clear the pending error flag.
2847 */
2848 if (bp == NULL)
2849 softc->flags &= ~SA_FLAG_ERR_PENDING;
2850 CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
2851 ("sastart- ERR_PENDING now 0x%x, bp is %sNULL, "
2852 "%d more buffers queued up\n",
2853 (softc->flags & SA_FLAG_ERR_PENDING),
2854 (bp != NULL)? "not " : " ", softc->queue_count));
2855 xpt_release_ccb(start_ccb);
2856 biodone(done_bp);
2857 } else {
2858 u_int32_t length;
2859
2860 bioq_remove(&softc->bio_queue, bp);
2861 softc->queue_count--;
2862
2863 if ((bp->bio_cmd != BIO_READ) &&
2864 (bp->bio_cmd != BIO_WRITE)) {
2865 biofinish(bp, NULL, EOPNOTSUPP);
2866 xpt_release_ccb(start_ccb);
2867 return;
2868 }
2869 length = bp->bio_bcount;
2870
2871 if ((softc->flags & SA_FLAG_FIXED) != 0) {
2872 if (softc->blk_shift != 0) {
2873 length = length >> softc->blk_shift;
2874 } else if (softc->media_blksize != 0) {
2875 length = length / softc->media_blksize;
2876 } else {
2877 bp->bio_error = EIO;
2878 xpt_print(periph->path, "zero blocksize"
2879 " for FIXED length writes?\n");
2880 biodone(bp);
2881 break;
2882 }
2883#if 0
2884 CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO,
2885 ("issuing a %d fixed record %s\n",
2886 length, (bp->bio_cmd == BIO_READ)? "read" :
2887 "write"));
2888#endif
2889 } else {
2890#if 0
2891 CAM_DEBUG(start_ccb->ccb_h.path, CAM_DEBUG_INFO,
2892 ("issuing a %d variable byte %s\n",
2893 length, (bp->bio_cmd == BIO_READ)? "read" :
2894 "write"));
2895#endif
2896 }
2897 devstat_start_transaction_bio(softc->device_stats, bp);
2898 /*
2899 * Some people have theorized that we should
2900 * suppress illegal length indication if we are
2901 * running in variable block mode so that we don't
2902 * have to request sense every time our requested
2903 * block size is larger than the written block.
2904 * The residual information from the ccb allows
2905 * us to identify this situation anyway. The only
2906 * problem with this is that we will not get
2907 * information about blocks that are larger than
2908 * our read buffer unless we set the block size
2909 * in the mode page to something other than 0.
2910 *
2911 * I believe that this is a non-issue. If user apps
2912 * don't adjust their read size to match our record
2913 * size, that's just life. Anyway, the typical usage
2914 * would be to issue, e.g., 64KB reads and occasionally
2915 * have to do deal with 512 byte or 1KB intermediate
2916 * records.
2917 *
2918 * That said, though, we now support setting the
2919 * SILI bit on reads, and we set the blocksize to 4
2920 * bytes when we do that. This gives us
2921 * compatibility with software that wants this,
2922 * although the only real difference between that
2923 * and not setting the SILI bit on reads is that we
2924 * won't get a check condition on reads where our
2925 * request size is larger than the block on tape.
2926 * That probably only makes a real difference in
2927 * non-packetized SCSI, where you have to go back
2928 * to the drive to request sense and thus incur
2929 * more latency.
2930 */
2931 softc->dsreg = (bp->bio_cmd == BIO_READ)?
2932 MTIO_DSREG_RD : MTIO_DSREG_WR;
2933 scsi_sa_read_write(&start_ccb->csio, 0, sadone,
2934 MSG_SIMPLE_Q_TAG, (bp->bio_cmd == BIO_READ ?
2936 ((bp->bio_flags & BIO_UNMAPPED) != 0 ?
2937 SCSI_RW_BIO : 0), softc->sili,
2938 (softc->flags & SA_FLAG_FIXED) != 0, length,
2939 (bp->bio_flags & BIO_UNMAPPED) != 0 ? (void *)bp :
2940 bp->bio_data, bp->bio_bcount, SSD_FULL_SIZE,
2941 (bp->bio_cmd == BIO_READ) ?
2944 start_ccb->ccb_h.ccb_pflags &= ~SA_POSITION_UPDATED;
2945 start_ccb->ccb_h.ccb_bp = bp;
2946 bp = bioq_first(&softc->bio_queue);
2947 xpt_action(start_ccb);
2948 }
2949
2950 if (bp != NULL) {
2951 /* Have more work to do, so ensure we stay scheduled */
2953 }
2954 break;
2955 }
2956 case SA_STATE_PROBE: {
2957 int num_opcodes;
2958 size_t alloc_len;
2959 uint8_t *params;
2960
2961 /*
2962 * This is an arbitrary number. An IBM LTO-6 drive reports
2963 * 67 entries, and an IBM LTO-9 drive reports 71 entries.
2964 * There can theoretically be more than 256 because
2965 * service actions of a particular opcode are reported
2966 * separately, but we're far enough ahead of the practical
2967 * number here that we don't need to implement logic to
2968 * retry if we don't get all the timeout descriptors.
2969 */
2970 num_opcodes = 256;
2971
2972 alloc_len = num_opcodes *
2973 (sizeof(struct scsi_report_supported_opcodes_descr) +
2975
2976 params = malloc(alloc_len, M_SCSISA, M_NOWAIT| M_ZERO);
2977 if (params == NULL) {
2978 /*
2979 * If this happens, go with default
2980 * timeouts and announce the drive.
2981 */
2982 saloadtotunables(softc);
2983
2984 softc->state = SA_STATE_NORMAL;
2985
2986 xpt_announce_periph(periph, NULL);
2987 xpt_announce_quirks(periph, softc->quirks,
2989 xpt_release_ccb(start_ccb);
2991 return;
2992 }
2993
2995 /*retries*/ 3,
2996 /*cbfcnp*/ sadone,
2997 /*tag_action*/ MSG_SIMPLE_Q_TAG,
2998 /*options*/ RSO_RCTD,
2999 /*req_opcode*/ 0,
3000 /*req_service_action*/ 0,
3001 /*data_ptr*/ params,
3002 /*dxfer_len*/ alloc_len,
3003 /*sense_len*/ SSD_FULL_SIZE,
3004 /*timeout*/ softc->timeout_info[SA_TIMEOUT_TUR]);
3005
3006 xpt_action(start_ccb);
3007 break;
3008 }
3009 case SA_STATE_ABNORMAL:
3010 default:
3011 panic("state 0x%x in sastart", softc->state);
3012 break;
3013 }
3014}
3015
3016static void
3017sadone(struct cam_periph *periph, union ccb *done_ccb)
3018{
3019 struct sa_softc *softc;
3020 struct ccb_scsiio *csio;
3021 struct bio *bp;
3022 int error;
3023
3024 softc = (struct sa_softc *)periph->softc;
3025 csio = &done_ccb->csio;
3026 error = 0;
3027
3028 if (softc->state == SA_STATE_NORMAL) {
3029 softc->dsreg = MTIO_DSREG_REST;
3030 bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
3031
3032 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3033 if ((error = saerror(done_ccb, 0, 0)) == ERESTART) {
3034 /*
3035 * A retry was scheduled, so just return.
3036 */
3037 return;
3038 }
3039 }
3040 } else if (softc->state == SA_STATE_PROBE) {
3041 bp = NULL;
3042 if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
3043 /*
3044 * Note that on probe, we just run through
3045 * cam_periph_error(), since saerror() has a lot of
3046 * special handling for I/O errors. We don't need
3047 * that to get the opcodes. We either succeed
3048 * after a retry or two, or give up. We don't
3049 * print sense, we don't need to worry the user if
3050 * this drive doesn't support timeout descriptors.
3051 */
3052 if ((error = cam_periph_error(done_ccb, 0,
3053 SF_NO_PRINT)) == ERESTART) {
3054 /*
3055 * A retry was scheduled, so just return.
3056 */
3057 return;
3058 } else if (error != 0) {
3059 /* We failed to get opcodes. Give up. */
3060
3061 saloadtotunables(softc);
3062
3063 softc->state = SA_STATE_NORMAL;
3064
3065 xpt_release_ccb(done_ccb);
3066
3067 xpt_announce_periph(periph, NULL);
3068 xpt_announce_quirks(periph, softc->quirks,
3071 return;
3072 }
3073 }
3074 /*
3075 * At this point, we have succeeded, so load the timeouts
3076 * and go into the normal state.
3077 */
3078 softc->state = SA_STATE_NORMAL;
3079
3080 /*
3081 * First, load the timeouts we got from the drive.
3082 */
3083 saloadtimeouts(softc, done_ccb);
3084
3085 /*
3086 * Next, overwrite the timeouts from the drive with any
3087 * loader tunables that the user set.
3088 */
3089 saloadtotunables(softc);
3090
3091 xpt_release_ccb(done_ccb);
3092 xpt_announce_periph(periph, NULL);
3093 xpt_announce_quirks(periph, softc->quirks,
3096 return;
3097 } else {
3098 panic("state 0x%x in sadone", softc->state);
3099 }
3100
3101 if (error == EIO) {
3102 /*
3103 * Catastrophic error. Mark the tape as frozen
3104 * (we no longer know tape position).
3105 *
3106 * Return all queued I/O with EIO, and unfreeze
3107 * our queue so that future transactions that
3108 * attempt to fix this problem can get to the
3109 * device.
3110 *
3111 */
3112
3113 softc->flags |= SA_FLAG_TAPE_FROZEN;
3114 bioq_flush(&softc->bio_queue, NULL, EIO);
3115 }
3116 if (error != 0) {
3117 bp->bio_resid = bp->bio_bcount;
3118 bp->bio_error = error;
3119 bp->bio_flags |= BIO_ERROR;
3120 /*
3121 * In the error case, position is updated in saerror.
3122 */
3123 } else {
3124 bp->bio_resid = csio->resid;
3125 bp->bio_error = 0;
3126 if (csio->resid != 0) {
3127 bp->bio_flags |= BIO_ERROR;
3128 }
3129 if (bp->bio_cmd == BIO_WRITE) {
3130 softc->flags |= SA_FLAG_TAPE_WRITTEN;
3131 softc->filemarks = 0;
3132 }
3133 if (!(csio->ccb_h.ccb_pflags & SA_POSITION_UPDATED) &&
3134 (softc->blkno != (daddr_t) -1)) {
3135 if ((softc->flags & SA_FLAG_FIXED) != 0) {
3136 u_int32_t l;
3137 if (softc->blk_shift != 0) {
3138 l = bp->bio_bcount >>
3139 softc->blk_shift;
3140 } else {
3141 l = bp->bio_bcount /
3142 softc->media_blksize;
3143 }
3144 softc->blkno += (daddr_t) l;
3145 } else {
3146 softc->blkno++;
3147 }
3148 }
3149 }
3150 /*
3151 * If we had an error (immediate or pending),
3152 * release the device queue now.
3153 */
3154 if (error || (softc->flags & SA_FLAG_ERR_PENDING))
3155 cam_release_devq(done_ccb->ccb_h.path, 0, 0, 0, 0);
3156 if (error || bp->bio_resid) {
3157 CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
3158 ("error %d resid %ld count %ld\n", error,
3159 bp->bio_resid, bp->bio_bcount));
3160 }
3161 biofinish(bp, softc->device_stats, 0);
3162 xpt_release_ccb(done_ccb);
3163}
3164
3165/*
3166 * Mount the tape (make sure it's ready for I/O).
3167 */
3168static int
3169samount(struct cam_periph *periph, int oflags, struct cdev *dev)
3170{
3171 struct sa_softc *softc;
3172 union ccb *ccb;
3173 int error;
3174
3175 /*
3176 * oflags can be checked for 'kind' of open (read-only check) - later
3177 * dev can be checked for a control-mode or compression open - later
3178 */
3179 UNUSED_PARAMETER(oflags);
3180 UNUSED_PARAMETER(dev);
3181
3182 softc = (struct sa_softc *)periph->softc;
3183
3184 /*
3185 * This should determine if something has happened since the last
3186 * open/mount that would invalidate the mount. We do *not* want
3187 * to retry this command- we just want the status. But we only
3188 * do this if we're mounted already- if we're not mounted,
3189 * we don't care about the unit read state and can instead use
3190 * this opportunity to attempt to reserve the tape unit.
3191 */
3192
3193 if (softc->flags & SA_FLAG_TAPE_MOUNTED) {
3195 scsi_test_unit_ready(&ccb->csio, 0, NULL,
3199 softc->device_stats);
3200 if (error == ENXIO) {
3201 softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
3202 scsi_test_unit_ready(&ccb->csio, 0, NULL,
3206 softc->device_stats);
3207 } else if (error) {
3208 /*
3209 * We don't need to freeze the tape because we
3210 * will now attempt to rewind/load it.
3211 */
3212 softc->flags &= ~SA_FLAG_TAPE_MOUNTED;
3215 "error %d on TUR in samount\n", error);
3216 }
3217 }
3218 } else {
3219 error = sareservereleaseunit(periph, TRUE);
3220 if (error) {
3221 return (error);
3222 }
3224 scsi_test_unit_ready(&ccb->csio, 0, NULL,
3228 softc->device_stats);
3229 }
3230
3231 if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) {
3232 struct scsi_read_block_limits_data *rblim = NULL;
3233 int comp_enabled, comp_supported;
3234 u_int8_t write_protect, guessing = 0;
3235
3236 /*
3237 * Clear out old state.
3238 */
3241 softc->filemarks = 0;
3242
3243 /*
3244 * *Very* first off, make sure we're loaded to BOT.
3245 */
3246 scsi_load_unload(&ccb->csio, 2, NULL, MSG_SIMPLE_Q_TAG, FALSE,
3247 FALSE, FALSE, 1, SSD_FULL_SIZE,
3250 softc->device_stats);
3251
3252 /*
3253 * In case this doesn't work, do a REWIND instead
3254 */
3255 if (error) {
3257 FALSE, SSD_FULL_SIZE,
3260 softc->device_stats);
3261 }
3262 if (error) {
3264 goto exit;
3265 }
3266
3267 /*
3268 * Do a dummy test read to force access to the
3269 * media so that the drive will really know what's
3270 * there. We actually don't really care what the
3271 * blocksize on tape is and don't expect to really
3272 * read a full record.
3273 */
3274 rblim = (struct scsi_read_block_limits_data *)
3275 malloc(8192, M_SCSISA, M_NOWAIT);
3276 if (rblim == NULL) {
3277 xpt_print(periph->path, "no memory for test read\n");
3279 error = ENOMEM;
3280 goto exit;
3281 }
3282
3283 if ((softc->quirks & SA_QUIRK_NODREAD) == 0) {
3284 scsi_sa_read_write(&ccb->csio, 0, NULL,
3285 MSG_SIMPLE_Q_TAG, 1, FALSE, 0, 8192,
3286 (void *) rblim, 8192, SSD_FULL_SIZE,
3289 softc->device_stats);
3291 FALSE, SSD_FULL_SIZE,
3295 softc->device_stats);
3296 if (error) {
3297 xpt_print(periph->path,
3298 "unable to rewind after test read\n");
3300 goto exit;
3301 }
3302 }
3303
3304 /*
3305 * Next off, determine block limits.
3306 */
3308 rblim, SSD_FULL_SIZE,
3310
3313
3315
3316 if (error != 0) {
3317 /*
3318 * If it's less than SCSI-2, READ BLOCK LIMITS is not
3319 * a MANDATORY command. Anyway- it doesn't matter-
3320 * we can proceed anyway.
3321 */
3322 softc->blk_gran = 0;
3323 softc->max_blk = ~0;
3324 softc->min_blk = 0;
3325 } else {
3326 if (softc->scsi_rev >= SCSI_REV_SPC) {
3327 softc->blk_gran = RBL_GRAN(rblim);
3328 } else {
3329 softc->blk_gran = 0;
3330 }
3331 /*
3332 * We take max_blk == min_blk to mean a default to
3333 * fixed mode- but note that whatever we get out of
3334 * sagetparams below will actually determine whether
3335 * we are actually *in* fixed mode.
3336 */
3337 softc->max_blk = scsi_3btoul(rblim->maximum);
3338 softc->min_blk = scsi_2btoul(rblim->minimum);
3339 }
3340 /*
3341 * Next, perform a mode sense to determine
3342 * current density, blocksize, compression etc.
3343 */
3344 error = sagetparams(periph, SA_PARAM_ALL,
3345 &softc->media_blksize,
3346 &softc->media_density,
3347 &softc->media_numblks,
3348 &softc->buffer_mode, &write_protect,
3349 &softc->speed, &comp_supported,
3350 &comp_enabled, &softc->comp_algorithm,
3351 NULL, NULL, 0, 0);
3352
3353 if (error != 0) {
3354 /*
3355 * We could work a little harder here. We could
3356 * adjust our attempts to get information. It
3357 * might be an ancient tape drive. If someone
3358 * nudges us, we'll do that.
3359 */
3360 goto exit;
3361 }
3362
3363 /*
3364 * If no quirk has determined that this is a device that is
3365 * preferred to be in fixed or variable mode, now is the time
3366 * to find out.
3367 */
3368 if ((softc->quirks & (SA_QUIRK_FIXED|SA_QUIRK_VARIABLE)) == 0) {
3369 guessing = 1;
3370 /*
3371 * This could be expensive to find out. Luckily we
3372 * only need to do this once. If we start out in
3373 * 'default' mode, try and set ourselves to one
3374 * of the densities that would determine a wad
3375 * of other stuff. Go from highest to lowest.
3376 */
3377 if (softc->media_density == SCSI_DEFAULT_DENSITY) {
3378 int i;
3379 static u_int8_t ctry[] = {
3395 0
3396 };
3397 for (i = 0; ctry[i]; i++) {
3398 error = sasetparams(periph,
3399 SA_PARAM_DENSITY, 0, ctry[i],
3400 0, SF_NO_PRINT);
3401 if (error == 0) {
3402 softc->media_density = ctry[i];
3403 break;
3404 }
3405 }
3406 }
3407 switch (softc->media_density) {
3416 softc->quirks &= ~SA_QUIRK_2FM;
3418 softc->last_media_blksize = 512;
3419 break;
3422 softc->quirks &= ~SA_QUIRK_2FM;
3424 softc->last_media_blksize = 1024;
3425 break;
3426 default:
3427 softc->last_media_blksize =
3428 softc->media_blksize;
3429 softc->quirks |= SA_QUIRK_VARIABLE;
3430 break;
3431 }
3432 }
3433
3434 /*
3435 * If no quirk has determined that this is a device that needs
3436 * to have 2 Filemarks at EOD, now is the time to find out.
3437 */
3438
3439 if ((softc->quirks & SA_QUIRK_2FM) == 0) {
3440 switch (softc->media_density) {
3446 softc->quirks &= ~SA_QUIRK_1FM;
3447 softc->quirks |= SA_QUIRK_2FM;
3448 break;
3449 default:
3450 break;
3451 }
3452 }
3453
3454 /*
3455 * Now validate that some info we got makes sense.
3456 */
3457 if ((softc->max_blk < softc->media_blksize) ||
3458 (softc->min_blk > softc->media_blksize &&
3459 softc->media_blksize)) {
3460 xpt_print(periph->path,
3461 "BLOCK LIMITS (%d..%d) could not match current "
3462 "block settings (%d)- adjusting\n", softc->min_blk,
3463 softc->max_blk, softc->media_blksize);
3464 softc->max_blk = softc->min_blk =
3465 softc->media_blksize;
3466 }
3467
3468 /*
3469 * Now put ourselves into the right frame of mind based
3470 * upon quirks...
3471 */
3472tryagain:
3473 /*
3474 * If we want to be in FIXED mode and our current blocksize
3475 * is not equal to our last blocksize (if nonzero), try and
3476 * set ourselves to this last blocksize (as the 'preferred'
3477 * block size). The initial quirkmatch at registry sets the
3478 * initial 'last' blocksize. If, for whatever reason, this
3479 * 'last' blocksize is zero, set the blocksize to 512,
3480 * or min_blk if that's larger.
3481 */
3482 if ((softc->quirks & SA_QUIRK_FIXED) &&
3483 (softc->quirks & SA_QUIRK_NO_MODESEL) == 0 &&
3484 (softc->media_blksize != softc->last_media_blksize)) {
3485 softc->media_blksize = softc->last_media_blksize;
3486 if (softc->media_blksize == 0) {
3487 softc->media_blksize = 512;
3488 if (softc->media_blksize < softc->min_blk) {
3489 softc->media_blksize = softc->min_blk;
3490 }
3491 }
3492 error = sasetparams(periph, SA_PARAM_BLOCKSIZE,
3493 softc->media_blksize, 0, 0, SF_NO_PRINT);
3494 if (error) {
3495 xpt_print(periph->path,
3496 "unable to set fixed blocksize to %d\n",
3497 softc->media_blksize);
3498 goto exit;
3499 }
3500 }
3501
3502 if ((softc->quirks & SA_QUIRK_VARIABLE) &&
3503 (softc->media_blksize != 0)) {
3504 softc->last_media_blksize = softc->media_blksize;
3505 softc->media_blksize = 0;
3506 error = sasetparams(periph, SA_PARAM_BLOCKSIZE,
3507 0, 0, 0, SF_NO_PRINT);
3508 if (error) {
3509 /*
3510 * If this fails and we were guessing, just
3511 * assume that we got it wrong and go try
3512 * fixed block mode. Don't even check against
3513 * density code at this point.
3514 */
3515 if (guessing) {
3516 softc->quirks &= ~SA_QUIRK_VARIABLE;
3517 softc->quirks |= SA_QUIRK_FIXED;
3518 if (softc->last_media_blksize == 0)
3519 softc->last_media_blksize = 512;
3520 goto tryagain;
3521 }
3522 xpt_print(periph->path,
3523 "unable to set variable blocksize\n");
3524 goto exit;
3525 }
3526 }
3527
3528 /*
3529 * Now that we have the current block size,
3530 * set up some parameters for sastart's usage.
3531 */
3532 if (softc->media_blksize) {
3533 softc->flags |= SA_FLAG_FIXED;
3534 if (powerof2(softc->media_blksize)) {
3535 softc->blk_shift =
3536 ffs(softc->media_blksize) - 1;
3537 softc->blk_mask = softc->media_blksize - 1;
3538 } else {
3539 softc->blk_mask = ~0;
3540 softc->blk_shift = 0;
3541 }
3542 } else {
3543 /*
3544 * The SCSI-3 spec allows 0 to mean "unspecified".
3545 * The SCSI-1 spec allows 0 to mean 'infinite'.
3546 *
3547 * Either works here.
3548 */
3549 if (softc->max_blk == 0) {
3550 softc->max_blk = ~0;
3551 }
3552 softc->blk_shift = 0;
3553 if (softc->blk_gran != 0) {
3554 softc->blk_mask = softc->blk_gran - 1;
3555 } else {
3556 softc->blk_mask = 0;
3557 }
3558 }
3559
3560 if (write_protect)
3561 softc->flags |= SA_FLAG_TAPE_WP;
3562
3563 if (comp_supported) {
3564 if (softc->saved_comp_algorithm == 0)
3565 softc->saved_comp_algorithm =
3566 softc->comp_algorithm;
3567 softc->flags |= SA_FLAG_COMP_SUPP;
3568 if (comp_enabled)
3569 softc->flags |= SA_FLAG_COMP_ENABLED;
3570 } else
3571 softc->flags |= SA_FLAG_COMP_UNSUPP;
3572
3573 if ((softc->buffer_mode == SMH_SA_BUF_MODE_NOBUF) &&
3574 (softc->quirks & SA_QUIRK_NO_MODESEL) == 0) {
3575 error = sasetparams(periph, SA_PARAM_BUFF_MODE, 0,
3576 0, 0, SF_NO_PRINT);
3577 if (error == 0) {
3579 } else {
3580 xpt_print(periph->path,
3581 "unable to set buffered mode\n");
3582 }
3583 error = 0; /* not an error */
3584 }
3585
3586 if (error == 0) {
3587 softc->flags |= SA_FLAG_TAPE_MOUNTED;
3588 }
3589exit:
3590 if (rblim != NULL)
3591 free(rblim, M_SCSISA);
3592
3593 if (error != 0) {
3594 softc->dsreg = MTIO_DSREG_NIL;
3595 } else {
3596 softc->fileno = softc->blkno = 0;
3597 softc->rep_fileno = softc->rep_blkno = -1;
3598 softc->partition = 0;
3599 softc->dsreg = MTIO_DSREG_REST;
3600 }
3601#ifdef SA_1FM_AT_EOD
3602 if ((softc->quirks & SA_QUIRK_2FM) == 0)
3603 softc->quirks |= SA_QUIRK_1FM;
3604#else
3605 if ((softc->quirks & SA_QUIRK_1FM) == 0)
3606 softc->quirks |= SA_QUIRK_2FM;
3607#endif
3608 } else
3610
3611 /*
3612 * If we return an error, we're not mounted any more,
3613 * so release any device reservation.
3614 */
3615 if (error != 0) {
3616 (void) sareservereleaseunit(periph, FALSE);
3617 } else {
3618 /*
3619 * Clear I/O residual.
3620 */
3621 softc->last_io_resid = 0;
3622 softc->last_ctl_resid = 0;
3623 }
3624 return (error);
3625}
3626
3627/*
3628 * How many filemarks do we need to write if we were to terminate the
3629 * tape session right now? Note that this can be a negative number
3630 */
3631
3632static int
3634{
3635 int markswanted;
3636 struct sa_softc *softc;
3637
3638 softc = (struct sa_softc *)periph->softc;
3639 markswanted = 0;
3640 if ((softc->flags & SA_FLAG_TAPE_WRITTEN) != 0) {
3641 markswanted++;
3642 if (softc->quirks & SA_QUIRK_2FM)
3643 markswanted++;
3644 }
3645 markswanted -= softc->filemarks;
3646 return (markswanted);
3647}
3648
3649static int
3651{
3652 int error;
3653 int markswanted;
3654
3655 markswanted = samarkswanted(periph);
3656
3657 if (markswanted > 0) {
3658 error = sawritefilemarks(periph, markswanted, FALSE, FALSE);
3659 } else {
3660 error = 0;
3661 }
3662 return (error);
3663}
3664
3665static int
3666saerror(union ccb *ccb, u_int32_t cflgs, u_int32_t sflgs)
3667{
3668 static const char *toobig =
3669 "%d-byte tape record bigger than supplied buffer\n";
3670 struct cam_periph *periph;
3671 struct sa_softc *softc;
3672 struct ccb_scsiio *csio;
3673 struct scsi_sense_data *sense;
3674 uint64_t resid = 0;
3675 int64_t info = 0;
3676 cam_status status;
3677 int error_code, sense_key, asc, ascq, error, aqvalid, stream_valid;
3678 int sense_len;
3679 uint8_t stream_bits;
3680
3681 periph = xpt_path_periph(ccb->ccb_h.path);
3682 softc = (struct sa_softc *)periph->softc;
3683 csio = &ccb->csio;
3684 sense = &csio->sense_data;
3685 sense_len = csio->sense_len - csio->sense_resid;
3686 scsi_extract_sense_len(sense, sense_len, &error_code, &sense_key,
3687 &asc, &ascq, /*show_errors*/ 1);
3688 if (asc != -1 && ascq != -1)
3689 aqvalid = 1;
3690 else
3691 aqvalid = 0;
3692 if (scsi_get_stream_info(sense, sense_len, NULL, &stream_bits) == 0)
3693 stream_valid = 1;
3694 else
3695 stream_valid = 0;
3696 error = 0;
3697
3698 status = csio->ccb_h.status & CAM_STATUS_MASK;
3699
3700 /*
3701 * Calculate/latch up, any residuals... We do this in a funny 2-step
3702 * so we can print stuff here if we have CAM_DEBUG enabled for this
3703 * unit.
3704 */
3705 if (status == CAM_SCSI_STATUS_ERROR) {
3706 if (scsi_get_sense_info(sense, sense_len, SSD_DESC_INFO, &resid,
3707 &info) == 0) {
3708 if ((softc->flags & SA_FLAG_FIXED) != 0)
3709 resid *= softc->media_blksize;
3710 } else {
3711 resid = csio->dxfer_len;
3712 info = resid;
3713 if ((softc->flags & SA_FLAG_FIXED) != 0) {
3714 if (softc->media_blksize)
3715 info /= softc->media_blksize;
3716 }
3717 }
3718 if (csio->cdb_io.cdb_bytes[0] == SA_READ ||
3719 csio->cdb_io.cdb_bytes[0] == SA_WRITE) {
3720 bcopy((caddr_t) sense, (caddr_t) &softc->last_io_sense,
3721 sizeof (struct scsi_sense_data));
3722 bcopy(csio->cdb_io.cdb_bytes, softc->last_io_cdb,
3723 (int) csio->cdb_len);
3724 softc->last_io_resid = resid;
3725 softc->last_resid_was_io = 1;
3726 } else {
3727 bcopy((caddr_t) sense, (caddr_t) &softc->last_ctl_sense,
3728 sizeof (struct scsi_sense_data));
3729 bcopy(csio->cdb_io.cdb_bytes, softc->last_ctl_cdb,
3730 (int) csio->cdb_len);
3731 softc->last_ctl_resid = resid;
3732 softc->last_resid_was_io = 0;
3733 }
3734 CAM_DEBUG(periph->path, CAM_DEBUG_INFO, ("CDB[0]=0x%x Key 0x%x "
3735 "ASC/ASCQ 0x%x/0x%x CAM STATUS 0x%x flags 0x%x resid %jd "
3736 "dxfer_len %d\n", csio->cdb_io.cdb_bytes[0] & 0xff,
3737 sense_key, asc, ascq, status,
3738 (stream_valid) ? stream_bits : 0, (intmax_t)resid,
3739 csio->dxfer_len));
3740 } else {
3742 ("Cam Status 0x%x\n", status));
3743 }
3744
3745 switch (status) {
3746 case CAM_REQ_CMP:
3747 return (0);
3749 /*
3750 * If a read/write command, we handle it here.
3751 */
3752 if (csio->cdb_io.cdb_bytes[0] == SA_READ ||
3753 csio->cdb_io.cdb_bytes[0] == SA_WRITE) {
3754 break;
3755 }
3756 /*
3757 * If this was just EOM/EOP, Filemark, Setmark, ILI or
3758 * PEW detected on a non read/write command, we assume
3759 * it's not an error and propagate the residual and return.
3760 */
3761 if ((aqvalid && asc == 0 && ((ascq > 0 && ascq <= 5)
3762 || (ascq == 0x07)))
3763 || (aqvalid == 0 && sense_key == SSD_KEY_NO_SENSE)) {
3764 csio->resid = resid;
3765 QFRLS(ccb);
3766 return (0);
3767 }
3768 /*
3769 * Otherwise, we let the common code handle this.
3770 */
3771 return (cam_periph_error(ccb, cflgs, sflgs));
3772
3773 /*
3774 * XXX: To Be Fixed
3775 * We cannot depend upon CAM honoring retry counts for these.
3776 */
3777 case CAM_SCSI_BUS_RESET:
3778 case CAM_BDR_SENT:
3779 if (ccb->ccb_h.retry_count <= 0) {
3780 return (EIO);
3781 }
3782 /* FALLTHROUGH */
3783 default:
3784 return (cam_periph_error(ccb, cflgs, sflgs));
3785 }
3786
3787 /*
3788 * Handle filemark, end of tape, mismatched record sizes....
3789 * From this point out, we're only handling read/write cases.
3790 * Handle writes && reads differently.
3791 */
3792
3793 if (csio->cdb_io.cdb_bytes[0] == SA_WRITE) {
3794 if (sense_key == SSD_KEY_VOLUME_OVERFLOW) {
3795 csio->resid = resid;
3796 error = ENOSPC;
3797 } else if ((stream_valid != 0) && (stream_bits & SSD_EOM)) {
3798 softc->flags |= SA_FLAG_EOM_PENDING;
3799 /*
3800 * Grotesque as it seems, the few times
3801 * I've actually seen a non-zero resid,
3802 * the tape drive actually lied and had
3803 * written all the data!.
3804 */
3805 csio->resid = 0;
3806 }
3807 } else {
3808 csio->resid = resid;
3809 if (sense_key == SSD_KEY_BLANK_CHECK) {
3810 if (softc->quirks & SA_QUIRK_1FM) {
3811 error = 0;
3812 softc->flags |= SA_FLAG_EOM_PENDING;
3813 } else {
3814 error = EIO;
3815 }
3816 } else if ((stream_valid != 0) && (stream_bits & SSD_FILEMARK)){
3817 if (softc->flags & SA_FLAG_FIXED) {
3818 error = -1;
3819 softc->flags |= SA_FLAG_EOF_PENDING;
3820 }
3821 /*
3822 * Unconditionally, if we detected a filemark on a read,
3823 * mark that we've run moved a file ahead.
3824 */
3825 if (softc->fileno != (daddr_t) -1) {
3826 softc->fileno++;
3827 softc->blkno = 0;
3828 csio->ccb_h.ccb_pflags |= SA_POSITION_UPDATED;
3829 }
3830 }
3831 }
3832
3833 /*
3834 * Incorrect Length usually applies to read, but can apply to writes.
3835 */
3836 if (error == 0 && (stream_valid != 0) && (stream_bits & SSD_ILI)) {
3837 if (info < 0) {
3838 xpt_print(csio->ccb_h.path, toobig,
3839 csio->dxfer_len - info);
3840 csio->resid = csio->dxfer_len;
3841 error = EIO;
3842 } else {
3843 csio->resid = resid;
3844 if (softc->flags & SA_FLAG_FIXED) {
3845 softc->flags |= SA_FLAG_EIO_PENDING;
3846 }
3847 /*
3848 * Bump the block number if we hadn't seen a filemark.
3849 * Do this independent of errors (we've moved anyway).
3850 */
3851 if ((stream_valid == 0) ||
3852 (stream_bits & SSD_FILEMARK) == 0) {
3853 if (softc->blkno != (daddr_t) -1) {
3854 softc->blkno++;
3855 csio->ccb_h.ccb_pflags |=
3857 }
3858 }
3859 }
3860 }
3861
3862 if (error <= 0) {
3863 /*
3864 * Unfreeze the queue if frozen as we're not returning anything
3865 * to our waiters that would indicate an I/O error has occurred
3866 * (yet).
3867 */
3868 QFRLS(ccb);
3869 error = 0;
3870 }
3871 return (error);
3872}
3873
3874static int
3876 u_int32_t *blocksize, u_int8_t *density, u_int32_t *numblocks,
3877 int *buff_mode, u_int8_t *write_protect, u_int8_t *speed,
3878 int *comp_supported, int *comp_enabled, u_int32_t *comp_algorithm,
3879 sa_comp_t *tcs, struct scsi_control_data_prot_subpage *prot_page,
3880 int dp_size, int prot_changeable)
3881{
3882 union ccb *ccb;
3883 void *mode_buffer;
3884 struct scsi_mode_header_6 *mode_hdr;
3885 struct scsi_mode_blk_desc *mode_blk;
3886 int mode_buffer_len;
3887 struct sa_softc *softc;
3888 u_int8_t cpage;
3889 int error;
3890 cam_status status;
3891
3892 softc = (struct sa_softc *)periph->softc;
3894 if (softc->quirks & SA_QUIRK_NO_CPAGE)
3896 else
3898
3899retry:
3900 mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk);
3901
3902 if (params_to_get & SA_PARAM_COMPRESSION) {
3903 if (softc->quirks & SA_QUIRK_NOCOMP) {
3904 *comp_supported = FALSE;
3905 params_to_get &= ~SA_PARAM_COMPRESSION;
3906 } else
3907 mode_buffer_len += sizeof (sa_comp_t);
3908 }
3909
3910 /* XXX Fix M_NOWAIT */
3911 mode_buffer = malloc(mode_buffer_len, M_SCSISA, M_NOWAIT | M_ZERO);
3912 if (mode_buffer == NULL) {
3914 return (ENOMEM);
3915 }
3916 mode_hdr = (struct scsi_mode_header_6 *)mode_buffer;
3917 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
3918
3919 /* it is safe to retry this */
3920 scsi_mode_sense(&ccb->csio, 5, NULL, MSG_SIMPLE_Q_TAG, FALSE,
3921 SMS_PAGE_CTRL_CURRENT, (params_to_get & SA_PARAM_COMPRESSION) ?
3922 cpage : SMS_VENDOR_SPECIFIC_PAGE, mode_buffer, mode_buffer_len,
3924
3926 softc->device_stats);
3927
3928 status = ccb->ccb_h.status & CAM_STATUS_MASK;
3929
3930 if (error == EINVAL && (params_to_get & SA_PARAM_COMPRESSION) != 0) {
3931 /*
3932 * Hmm. Let's see if we can try another page...
3933 * If we've already done that, give up on compression
3934 * for this device and remember this for the future
3935 * and attempt the request without asking for compression
3936 * info.
3937 */
3938 if (cpage == SA_DATA_COMPRESSION_PAGE) {
3940 goto retry;
3941 }
3942 softc->quirks |= SA_QUIRK_NOCOMP;
3943 free(mode_buffer, M_SCSISA);
3944 goto retry;
3945 } else if (status == CAM_SCSI_STATUS_ERROR) {
3946 /* Tell the user about the fatal error. */
3948 goto sagetparamsexit;
3949 }
3950
3951 /*
3952 * If the user only wants the compression information, and
3953 * the device doesn't send back the block descriptor, it's
3954 * no big deal. If the user wants more than just
3955 * compression, though, and the device doesn't pass back the
3956 * block descriptor, we need to send another mode sense to
3957 * get the block descriptor.
3958 */
3959 if ((mode_hdr->blk_desc_len == 0) &&
3960 (params_to_get & SA_PARAM_COMPRESSION) &&
3961 (params_to_get & ~(SA_PARAM_COMPRESSION))) {
3962 /*
3963 * Decrease the mode buffer length by the size of
3964 * the compression page, to make sure the data
3965 * there doesn't get overwritten.
3966 */
3967 mode_buffer_len -= sizeof (sa_comp_t);
3968
3969 /*
3970 * Now move the compression page that we presumably
3971 * got back down the memory chunk a little bit so
3972 * it doesn't get spammed.
3973 */
3974 bcopy(&mode_hdr[0], &mode_hdr[1], sizeof (sa_comp_t));
3975 bzero(&mode_hdr[0], sizeof (mode_hdr[0]));
3976
3977 /*
3978 * Now, we issue another mode sense and just ask
3979 * for the block descriptor, etc.
3980 */
3981
3982 scsi_mode_sense(&ccb->csio, 2, NULL, MSG_SIMPLE_Q_TAG, FALSE,
3984 mode_buffer, mode_buffer_len, SSD_FULL_SIZE,
3986
3988 softc->device_stats);
3989
3990 if (error != 0)
3991 goto sagetparamsexit;
3992 }
3993
3994 if (params_to_get & SA_PARAM_BLOCKSIZE)
3995 *blocksize = scsi_3btoul(mode_blk->blklen);
3996
3997 if (params_to_get & SA_PARAM_NUMBLOCKS)
3998 *numblocks = scsi_3btoul(mode_blk->nblocks);
3999
4000 if (params_to_get & SA_PARAM_BUFF_MODE)
4001 *buff_mode = mode_hdr->dev_spec & SMH_SA_BUF_MODE_MASK;
4002
4003 if (params_to_get & SA_PARAM_DENSITY)
4004 *density = mode_blk->density;
4005
4006 if (params_to_get & SA_PARAM_WP)
4007 *write_protect = (mode_hdr->dev_spec & SMH_SA_WP)? TRUE : FALSE;
4008
4009 if (params_to_get & SA_PARAM_SPEED)
4010 *speed = mode_hdr->dev_spec & SMH_SA_SPEED_MASK;
4011
4012 if (params_to_get & SA_PARAM_COMPRESSION) {
4013 sa_comp_t *ntcs = (sa_comp_t *) &mode_blk[1];
4014 if (cpage == SA_DATA_COMPRESSION_PAGE) {
4015 struct scsi_data_compression_page *cp = &ntcs->dcomp;
4016 *comp_supported =
4017 (cp->dce_and_dcc & SA_DCP_DCC)? TRUE : FALSE;
4018 *comp_enabled =
4019 (cp->dce_and_dcc & SA_DCP_DCE)? TRUE : FALSE;
4021 } else {
4022 struct scsi_dev_conf_page *cp = &ntcs->dconf;
4023 /*
4024 * We don't really know whether this device supports
4025 * Data Compression if the algorithm field is
4026 * zero. Just say we do.
4027 */
4028 *comp_supported = TRUE;
4029 *comp_enabled =
4030 (cp->sel_comp_alg != SA_COMP_NONE)? TRUE : FALSE;
4031 *comp_algorithm = cp->sel_comp_alg;
4032 }
4033 if (tcs != NULL)
4034 bcopy(ntcs, tcs, sizeof (sa_comp_t));
4035 }
4036
4037 if ((params_to_get & SA_PARAM_DENSITY_EXT)
4038 && (softc->scsi_rev >= SCSI_REV_SPC)) {
4039 int i;
4040
4041 for (i = 0; i < SA_DENSITY_TYPES; i++) {
4043 /*retries*/ 1,
4044 /*cbfcnp*/ NULL,
4045 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4046 /*media*/ softc->density_type_bits[i] & SRDS_MEDIA,
4047 /*medium_type*/ softc->density_type_bits[i] &
4049 /*data_ptr*/ softc->density_info[i],
4050 /*length*/ sizeof(softc->density_info[i]),
4051 /*sense_len*/ SSD_FULL_SIZE,
4052 /*timeout*/
4055 softc->device_stats);
4056 status = ccb->ccb_h.status & CAM_STATUS_MASK;
4057
4058 /*
4059 * Some tape drives won't support this command at
4060 * all, but hopefully we'll minimize that with the
4061 * check for SPC or greater support above. If they
4062 * don't support the default report (neither the
4063 * MEDIA or MEDIUM_TYPE bits set), then there is
4064 * really no point in continuing on to look for
4065 * other reports.
4066 */
4067 if ((error != 0)
4068 || (status != CAM_REQ_CMP)) {
4069 error = 0;
4070 softc->density_info_valid[i] = 0;
4071 if (softc->density_type_bits[i] == 0)
4072 break;
4073 else
4074 continue;
4075 }
4076 softc->density_info_valid[i] = ccb->csio.dxfer_len -
4077 ccb->csio.resid;
4078 }
4079 }
4080
4081 /*
4082 * Get logical block protection parameters if the drive supports it.
4083 */
4084 if ((params_to_get & SA_PARAM_LBP)
4085 && (softc->flags & SA_FLAG_PROTECT_SUPP)) {
4086 struct scsi_mode_header_10 *mode10_hdr;
4087 struct scsi_control_data_prot_subpage *dp_page;
4088 struct scsi_mode_sense_10 *cdb;
4089 struct sa_prot_state *prot;
4090 int dp_len, returned_len;
4091
4092 if (dp_size == 0)
4093 dp_size = sizeof(*dp_page);
4094
4095 dp_len = sizeof(*mode10_hdr) + dp_size;
4096 mode10_hdr = malloc(dp_len, M_SCSISA, M_NOWAIT | M_ZERO);
4097 if (mode10_hdr == NULL) {
4098 error = ENOMEM;
4099 goto sagetparamsexit;
4100 }
4101
4103 /*retries*/ 5,
4104 /*cbfcnp*/ NULL,
4105 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4106 /*dbd*/ TRUE,
4107 /*page_code*/ (prot_changeable == 0) ?
4110 /*page*/ SMS_CONTROL_MODE_PAGE,
4111 /*param_buf*/ (uint8_t *)mode10_hdr,
4112 /*param_len*/ dp_len,
4113 /*minimum_cmd_size*/ 10,
4114 /*sense_len*/ SSD_FULL_SIZE,
4115 /*timeout*/
4117 /*
4118 * XXX KDM we need to be able to set the subpage in the
4119 * fill function.
4120 */
4121 cdb = (struct scsi_mode_sense_10 *)ccb->csio.cdb_io.cdb_bytes;
4123
4125 softc->device_stats);
4126 if (error != 0) {
4127 free(mode10_hdr, M_SCSISA);
4128 goto sagetparamsexit;
4129 }
4130
4131 status = ccb->ccb_h.status & CAM_STATUS_MASK;
4132 if (status != CAM_REQ_CMP) {
4133 error = EINVAL;
4134 free(mode10_hdr, M_SCSISA);
4135 goto sagetparamsexit;
4136 }
4137
4138 /*
4139 * The returned data length at least has to be long enough
4140 * for us to look at length in the mode page header.
4141 */
4142 returned_len = ccb->csio.dxfer_len - ccb->csio.resid;
4143 if (returned_len < sizeof(mode10_hdr->data_length)) {
4144 error = EINVAL;
4145 free(mode10_hdr, M_SCSISA);
4146 goto sagetparamsexit;
4147 }
4148
4149 returned_len = min(returned_len,
4150 sizeof(mode10_hdr->data_length) +
4151 scsi_2btoul(mode10_hdr->data_length));
4152
4153 dp_page = (struct scsi_control_data_prot_subpage *)
4154 &mode10_hdr[1];
4155
4156 /*
4157 * We also have to have enough data to include the prot_bits
4158 * in the subpage.
4159 */
4160 if (returned_len < (sizeof(*mode10_hdr) +
4161 __offsetof(struct scsi_control_data_prot_subpage, prot_bits)
4162 + sizeof(dp_page->prot_bits))) {
4163 error = EINVAL;
4164 free(mode10_hdr, M_SCSISA);
4165 goto sagetparamsexit;
4166 }
4167
4168 prot = &softc->prot_info.cur_prot_state;
4169 prot->prot_method = dp_page->prot_method;
4170 prot->pi_length = dp_page->pi_length &
4172 prot->lbp_w = (dp_page->prot_bits & SA_CTRL_DP_LBP_W) ? 1 :0;
4173 prot->lbp_r = (dp_page->prot_bits & SA_CTRL_DP_LBP_R) ? 1 :0;
4174 prot->rbdp = (dp_page->prot_bits & SA_CTRL_DP_RBDP) ? 1 :0;
4175 prot->initialized = 1;
4176
4177 if (prot_page != NULL)
4178 bcopy(dp_page, prot_page, min(sizeof(*prot_page),
4179 sizeof(*dp_page)));
4180
4181 free(mode10_hdr, M_SCSISA);
4182 }
4183
4184 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) {
4185 int idx;
4186 char *xyz = mode_buffer;
4187 xpt_print_path(periph->path);
4188 printf("Mode Sense Data=");
4189 for (idx = 0; idx < mode_buffer_len; idx++)
4190 printf(" 0x%02x", xyz[idx] & 0xff);
4191 printf("\n");
4192 }
4193
4194sagetparamsexit:
4195
4197 free(mode_buffer, M_SCSISA);
4198 return (error);
4199}
4200
4201/*
4202 * Set protection information to the pending protection information stored
4203 * in the softc.
4204 */
4205static int
4206sasetprot(struct cam_periph *periph, struct sa_prot_state *new_prot)
4207{
4208 struct sa_softc *softc;
4209 struct scsi_control_data_prot_subpage *dp_page, *dp_changeable;
4210 struct scsi_mode_header_10 *mode10_hdr, *mode10_changeable;
4211 union ccb *ccb;
4212 uint8_t current_speed;
4213 size_t dp_size, dp_page_length;
4214 int dp_len, buff_mode;
4215 int error;
4216
4217 softc = (struct sa_softc *)periph->softc;
4218 mode10_hdr = NULL;
4219 mode10_changeable = NULL;
4220 ccb = NULL;
4221
4222 /*
4223 * Start off with the size set to the actual length of the page
4224 * that we have defined.
4225 */
4226 dp_size = sizeof(*dp_changeable);
4227 dp_page_length = dp_size -
4228 __offsetof(struct scsi_control_data_prot_subpage, prot_method);
4229
4230retry_length:
4231
4232 dp_len = sizeof(*mode10_changeable) + dp_size;
4233 mode10_changeable = malloc(dp_len, M_SCSISA, M_NOWAIT | M_ZERO);
4234 if (mode10_changeable == NULL) {
4235 error = ENOMEM;
4236 goto bailout;
4237 }
4238
4239 dp_changeable =
4240 (struct scsi_control_data_prot_subpage *)&mode10_changeable[1];
4241
4242 /*
4243 * First get the data protection page changeable parameters mask.
4244 * We need to know which parameters the drive supports changing.
4245 * We also need to know what the drive claims that its page length
4246 * is. The reason is that IBM drives in particular are very picky
4247 * about the page length. They want it (the length set in the
4248 * page structure itself) to be 28 bytes, and they want the
4249 * parameter list length specified in the mode select header to be
4250 * 40 bytes. So, to work with IBM drives as well as any other tape
4251 * drive, find out what the drive claims the page length is, and
4252 * make sure that we match that.
4253 */
4254 error = sagetparams(periph, SA_PARAM_SPEED | SA_PARAM_LBP,
4255 NULL, NULL, NULL, &buff_mode, NULL, &current_speed, NULL, NULL,
4256 NULL, NULL, dp_changeable, dp_size, /*prot_changeable*/ 1);
4257 if (error != 0)
4258 goto bailout;
4259
4260 if (scsi_2btoul(dp_changeable->length) > dp_page_length) {
4261 dp_page_length = scsi_2btoul(dp_changeable->length);
4262 dp_size = dp_page_length +
4263 __offsetof(struct scsi_control_data_prot_subpage,
4264 prot_method);
4265 free(mode10_changeable, M_SCSISA);
4266 mode10_changeable = NULL;
4267 goto retry_length;
4268 }
4269
4270 mode10_hdr = malloc(dp_len, M_SCSISA, M_NOWAIT | M_ZERO);
4271 if (mode10_hdr == NULL) {
4272 error = ENOMEM;
4273 goto bailout;
4274 }
4275
4276 dp_page = (struct scsi_control_data_prot_subpage *)&mode10_hdr[1];
4277
4278 /*
4279 * Now grab the actual current settings in the page.
4280 */
4281 error = sagetparams(periph, SA_PARAM_SPEED | SA_PARAM_LBP,
4282 NULL, NULL, NULL, &buff_mode, NULL, &current_speed, NULL, NULL,
4283 NULL, NULL, dp_page, dp_size, /*prot_changeable*/ 0);
4284 if (error != 0)
4285 goto bailout;
4286
4287 /* These two fields need to be 0 for MODE SELECT */
4288 scsi_ulto2b(0, mode10_hdr->data_length);
4289 mode10_hdr->medium_type = 0;
4290 /* We are not including a block descriptor */
4291 scsi_ulto2b(0, mode10_hdr->blk_desc_len);
4292
4293 mode10_hdr->dev_spec = current_speed;
4294 /* if set, set single-initiator buffering mode */
4295 if (softc->buffer_mode == SMH_SA_BUF_MODE_SIBUF) {
4296 mode10_hdr->dev_spec |= SMH_SA_BUF_MODE_SIBUF;
4297 }
4298
4299 /*
4300 * For each field, make sure that the drive allows changing it
4301 * before bringing in the user's setting.
4302 */
4303 if (dp_changeable->prot_method != 0)
4304 dp_page->prot_method = new_prot->prot_method;
4305
4306 if (dp_changeable->pi_length & SA_CTRL_DP_PI_LENGTH_MASK) {
4307 dp_page->pi_length &= ~SA_CTRL_DP_PI_LENGTH_MASK;
4308 dp_page->pi_length |= (new_prot->pi_length &
4310 }
4311 if (dp_changeable->prot_bits & SA_CTRL_DP_LBP_W) {
4312 if (new_prot->lbp_w)
4313 dp_page->prot_bits |= SA_CTRL_DP_LBP_W;
4314 else
4315 dp_page->prot_bits &= ~SA_CTRL_DP_LBP_W;
4316 }
4317
4318 if (dp_changeable->prot_bits & SA_CTRL_DP_LBP_R) {
4319 if (new_prot->lbp_r)
4320 dp_page->prot_bits |= SA_CTRL_DP_LBP_R;
4321 else
4322 dp_page->prot_bits &= ~SA_CTRL_DP_LBP_R;
4323 }
4324
4325 if (dp_changeable->prot_bits & SA_CTRL_DP_RBDP) {
4326 if (new_prot->rbdp)
4327 dp_page->prot_bits |= SA_CTRL_DP_RBDP;
4328 else
4329 dp_page->prot_bits &= ~SA_CTRL_DP_RBDP;
4330 }
4331
4332 ccb = cam_periph_getccb(periph, 1);
4333
4335 /*retries*/ 5,
4336 /*cbfcnp*/ NULL,
4337 /*tag_action*/ MSG_SIMPLE_Q_TAG,
4338 /*scsi_page_fmt*/ TRUE,
4339 /*save_pages*/ FALSE,
4340 /*param_buf*/ (uint8_t *)mode10_hdr,
4341 /*param_len*/ dp_len,
4342 /*minimum_cmd_size*/ 10,
4343 /*sense_len*/ SSD_FULL_SIZE,
4344 /*timeout*/
4346
4347 error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
4348 if (error != 0)
4349 goto bailout;
4350
4352 error = EINVAL;
4353 goto bailout;
4354 }
4355
4356 /*
4357 * The operation was successful. We could just copy the settings
4358 * the user requested, but just in case the drive ignored some of
4359 * our settings, let's ask for status again.
4360 */
4361 error = sagetparams(periph, SA_PARAM_SPEED | SA_PARAM_LBP,
4362 NULL, NULL, NULL, &buff_mode, NULL, &current_speed, NULL, NULL,
4363 NULL, NULL, dp_page, dp_size, 0);
4364
4365bailout:
4366 if (ccb != NULL)
4368 free(mode10_hdr, M_SCSISA);
4369 free(mode10_changeable, M_SCSISA);
4370 return (error);
4371}
4372
4373/*
4374 * The purpose of this function is to set one of four different parameters
4375 * for a tape drive:
4376 * - blocksize
4377 * - density
4378 * - compression / compression algorithm
4379 * - buffering mode
4380 *
4381 * The assumption is that this will be called from saioctl(), and therefore
4382 * from a process context. Thus the waiting malloc calls below. If that
4383 * assumption ever changes, the malloc calls should be changed to be
4384 * NOWAIT mallocs.
4385 *
4386 * Any or all of the four parameters may be set when this function is
4387 * called. It should handle setting more than one parameter at once.
4388 */
4389static int
4390sasetparams(struct cam_periph *periph, sa_params params_to_set,
4391 u_int32_t blocksize, u_int8_t density, u_int32_t calg,
4392 u_int32_t sense_flags)
4393{
4394 struct sa_softc *softc;
4395 u_int32_t current_blocksize;
4396 u_int32_t current_calg;
4397 u_int8_t current_density;
4398 u_int8_t current_speed;
4399 int comp_enabled, comp_supported;
4400 void *mode_buffer;
4401 int mode_buffer_len;
4402 struct scsi_mode_header_6 *mode_hdr;
4403 struct scsi_mode_blk_desc *mode_blk;
4404 sa_comp_t *ccomp, *cpage;
4405 int buff_mode;
4406 union ccb *ccb = NULL;
4407 int error;
4408
4409 softc = (struct sa_softc *)periph->softc;
4410
4411 ccomp = malloc(sizeof (sa_comp_t), M_SCSISA, M_NOWAIT);
4412 if (ccomp == NULL)
4413 return (ENOMEM);
4414
4415 /*
4416 * Since it doesn't make sense to set the number of blocks, or
4417 * write protection, we won't try to get the current value. We
4418 * always want to get the blocksize, so we can set it back to the
4419 * proper value.
4420 */
4421 error = sagetparams(periph,
4422 params_to_set | SA_PARAM_BLOCKSIZE | SA_PARAM_SPEED,
4423 &current_blocksize, &current_density, NULL, &buff_mode, NULL,
4424 &current_speed, &comp_supported, &comp_enabled,
4425 &current_calg, ccomp, NULL, 0, 0);
4426
4427 if (error != 0) {
4428 free(ccomp, M_SCSISA);
4429 return (error);
4430 }
4431
4432 mode_buffer_len = sizeof(*mode_hdr) + sizeof(*mode_blk);
4433 if (params_to_set & SA_PARAM_COMPRESSION)
4434 mode_buffer_len += sizeof (sa_comp_t);
4435
4436 mode_buffer = malloc(mode_buffer_len, M_SCSISA, M_NOWAIT | M_ZERO);
4437 if (mode_buffer == NULL) {
4438 free(ccomp, M_SCSISA);
4439 return (ENOMEM);
4440 }
4441
4442 mode_hdr = (struct scsi_mode_header_6 *)mode_buffer;
4443 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
4444
4445 ccb = cam_periph_getccb(periph, 1);
4446
4447retry:
4448
4449 if (params_to_set & SA_PARAM_COMPRESSION) {
4450 if (mode_blk) {
4451 cpage = (sa_comp_t *)&mode_blk[1];
4452 } else {
4453 cpage = (sa_comp_t *)&mode_hdr[1];
4454 }
4455 bcopy(ccomp, cpage, sizeof (sa_comp_t));
4456 cpage->hdr.pagecode &= ~0x80;
4457 } else
4458 cpage = NULL;
4459
4460 /*
4461 * If the caller wants us to set the blocksize, use the one they
4462 * pass in. Otherwise, use the blocksize we got back from the
4463 * mode select above.
4464 */
4465 if (mode_blk) {
4466 if (params_to_set & SA_PARAM_BLOCKSIZE)
4467 scsi_ulto3b(blocksize, mode_blk->blklen);
4468 else
4469 scsi_ulto3b(current_blocksize, mode_blk->blklen);
4470
4471 /*
4472 * Set density if requested, else preserve old density.
4473 * SCSI_SAME_DENSITY only applies to SCSI-2 or better
4474 * devices, else density we've latched up in our softc.
4475 */
4476 if (params_to_set & SA_PARAM_DENSITY) {
4477 mode_blk->density = density;
4478 } else if (softc->scsi_rev > SCSI_REV_CCS) {
4479 mode_blk->density = SCSI_SAME_DENSITY;
4480 } else {
4481 mode_blk->density = softc->media_density;
4482 }
4483 }
4484
4485 /*
4486 * For mode selects, these two fields must be zero.
4487 */
4488 mode_hdr->data_length = 0;
4489 mode_hdr->medium_type = 0;
4490
4491 /* set the speed to the current value */
4492 mode_hdr->dev_spec = current_speed;
4493
4494 /* if set, set single-initiator buffering mode */
4495 if (softc->buffer_mode == SMH_SA_BUF_MODE_SIBUF) {
4496 mode_hdr->dev_spec |= SMH_SA_BUF_MODE_SIBUF;
4497 }
4498
4499 if (mode_blk)
4500 mode_hdr->blk_desc_len = sizeof(struct scsi_mode_blk_desc);
4501 else
4502 mode_hdr->blk_desc_len = 0;
4503
4504 /*
4505 * First, if the user wants us to set the compression algorithm or
4506 * just turn compression on, check to make sure that this drive
4507 * supports compression.
4508 */
4509 if (params_to_set & SA_PARAM_COMPRESSION) {
4510 /*
4511 * If the compression algorithm is 0, disable compression.
4512 * If the compression algorithm is non-zero, enable
4513 * compression and set the compression type to the
4514 * specified compression algorithm, unless the algorithm is
4515 * MT_COMP_ENABLE. In that case, we look at the
4516 * compression algorithm that is currently set and if it is
4517 * non-zero, we leave it as-is. If it is zero, and we have
4518 * saved a compression algorithm from a time when
4519 * compression was enabled before, set the compression to
4520 * the saved value.
4521 */
4522 switch (ccomp->hdr.pagecode & ~0x80) {
4524 {
4525 struct scsi_dev_conf_page *dcp = &cpage->dconf;
4526 if (calg == 0) {
4528 break;
4529 }
4530 if (calg != MT_COMP_ENABLE) {
4531 dcp->sel_comp_alg = calg;
4532 } else if (dcp->sel_comp_alg == SA_COMP_NONE &&
4533 softc->saved_comp_algorithm != 0) {
4534 dcp->sel_comp_alg = softc->saved_comp_algorithm;
4535 }
4536 break;
4537 }
4539 if (ccomp->dcomp.dce_and_dcc & SA_DCP_DCC) {
4540 struct scsi_data_compression_page *dcp = &cpage->dcomp;
4541 if (calg == 0) {
4542 /*
4543 * Disable compression, but leave the
4544 * decompression and the capability bit
4545 * alone.
4546 */
4547 dcp->dce_and_dcc = SA_DCP_DCC;
4548 dcp->dde_and_red |= SA_DCP_DDE;
4549 break;
4550 }
4551 /* enable compression && decompression */
4553 dcp->dde_and_red |= SA_DCP_DDE;
4554 /*
4555 * If there, use compression algorithm from caller.
4556 * Otherwise, if there's a saved compression algorithm
4557 * and there is no current algorithm, use the saved
4558 * algorithm. Else parrot back what we got and hope
4559 * for the best.
4560 */
4561 if (calg != MT_COMP_ENABLE) {
4562 scsi_ulto4b(calg, dcp->comp_algorithm);
4563 scsi_ulto4b(calg, dcp->decomp_algorithm);
4564 } else if (scsi_4btoul(dcp->comp_algorithm) == 0 &&
4565 softc->saved_comp_algorithm != 0) {
4567 dcp->comp_algorithm);
4569 dcp->decomp_algorithm);
4570 }
4571 break;
4572 }
4573 /*
4574 * Compression does not appear to be supported-
4575 * at least via the DATA COMPRESSION page. It
4576 * would be too much to ask us to believe that
4577 * the page itself is supported, but incorrectly
4578 * reports an ability to manipulate data compression,
4579 * so we'll assume that this device doesn't support
4580 * compression. We can just fall through for that.
4581 */
4582 /* FALLTHROUGH */
4583 default:
4584 /*
4585 * The drive doesn't seem to support compression,
4586 * so turn off the set compression bit.
4587 */
4588 params_to_set &= ~SA_PARAM_COMPRESSION;
4589 xpt_print(periph->path,
4590 "device does not seem to support compression\n");
4591
4592 /*
4593 * If that was the only thing the user wanted us to set,
4594 * clean up allocated resources and return with
4595 * 'operation not supported'.
4596 */
4597 if (params_to_set == SA_PARAM_NONE) {
4598 free(mode_buffer, M_SCSISA);
4600 return (ENODEV);
4601 }
4602
4603 /*
4604 * That wasn't the only thing the user wanted us to set.
4605 * So, decrease the stated mode buffer length by the
4606 * size of the compression mode page.
4607 */
4608 mode_buffer_len -= sizeof(sa_comp_t);
4609 }
4610 }
4611
4612 /* It is safe to retry this operation */
4614 (params_to_set & SA_PARAM_COMPRESSION)? TRUE : FALSE,
4615 FALSE, mode_buffer, mode_buffer_len, SSD_FULL_SIZE,
4617
4618 error = cam_periph_runccb(ccb, saerror, 0,
4619 sense_flags, softc->device_stats);
4620
4621 if (CAM_DEBUGGED(periph->path, CAM_DEBUG_INFO)) {
4622 int idx;
4623 char *xyz = mode_buffer;
4624 xpt_print_path(periph->path);
4625 printf("Err%d, Mode Select Data=", error);
4626 for (idx = 0; idx < mode_buffer_len; idx++)
4627 printf(" 0x%02x", xyz[idx] & 0xff);
4628 printf("\n");
4629 }
4630
4631 if (error) {
4632 /*
4633 * If we can, try without setting density/blocksize.
4634 */
4635 if (mode_blk) {
4636 if ((params_to_set &
4638 mode_blk = NULL;
4639 goto retry;
4640 }
4641 } else {
4642 mode_blk = (struct scsi_mode_blk_desc *)&mode_hdr[1];
4643 cpage = (sa_comp_t *)&mode_blk[1];
4644 }
4645
4646 /*
4647 * If we were setting the blocksize, and that failed, we
4648 * want to set it to its original value. If we weren't
4649 * setting the blocksize, we don't want to change it.
4650 */
4651 scsi_ulto3b(current_blocksize, mode_blk->blklen);
4652
4653 /*
4654 * Set density if requested, else preserve old density.
4655 * SCSI_SAME_DENSITY only applies to SCSI-2 or better
4656 * devices, else density we've latched up in our softc.
4657 */
4658 if (params_to_set & SA_PARAM_DENSITY) {
4659 mode_blk->density = current_density;
4660 } else if (softc->scsi_rev > SCSI_REV_CCS) {
4661 mode_blk->density = SCSI_SAME_DENSITY;
4662 } else {
4663 mode_blk->density = softc->media_density;
4664 }
4665
4666 if (params_to_set & SA_PARAM_COMPRESSION)
4667 bcopy(ccomp, cpage, sizeof (sa_comp_t));
4668
4669 /*
4670 * The retry count is the only CCB field that might have been
4671 * changed that we care about, so reset it back to 1.
4672 */
4673 ccb->ccb_h.retry_count = 1;
4674 cam_periph_runccb(ccb, saerror, 0, sense_flags,
4675 softc->device_stats);
4676 }
4677
4679
4680 if (ccomp != NULL)
4681 free(ccomp, M_SCSISA);
4682
4683 if (params_to_set & SA_PARAM_COMPRESSION) {
4684 if (error) {
4685 softc->flags &= ~SA_FLAG_COMP_ENABLED;
4686 /*
4687 * Even if we get an error setting compression,
4688 * do not say that we don't support it. We could
4689 * have been wrong, or it may be media specific.
4690 * softc->flags &= ~SA_FLAG_COMP_SUPP;
4691 */
4692 softc->saved_comp_algorithm = softc->comp_algorithm;
4693 softc->comp_algorithm = 0;
4694 } else {
4695 softc->flags |= SA_FLAG_COMP_ENABLED;
4696 softc->comp_algorithm = calg;
4697 }
4698 }
4699
4700 free(mode_buffer, M_SCSISA);
4701 return (error);
4702}
4703
4704static int
4705saextget(struct cdev *dev, struct cam_periph *periph, struct sbuf *sb,
4706 struct mtextget *g)
4707{
4708 int indent, error;
4709 char tmpstr[80];
4710 struct sa_softc *softc;
4711 int tmpint;
4712 uint32_t maxio_tmp;
4713 struct ccb_getdev cgd;
4714
4715 softc = (struct sa_softc *)periph->softc;
4716
4717 error = 0;
4718
4719 error = sagetparams_common(dev, periph);
4720 if (error)
4721 goto extget_bailout;
4722 if (!SA_IS_CTRL(dev) && !softc->open_pending_mount)
4724
4725 indent = 0;
4726 SASBADDNODE(sb, indent, mtextget);
4727 /*
4728 * Basic CAM peripheral information.
4729 */
4730 SASBADDVARSTR(sb, indent, periph->periph_name, %s, periph_name,
4731 strlen(periph->periph_name) + 1);
4732 SASBADDUINT(sb, indent, periph->unit_number, %u, unit_number);
4733 memset(&cgd, 0, sizeof(cgd));
4734 xpt_setup_ccb(&cgd.ccb_h,
4735 periph->path,
4738 xpt_action((union ccb *)&cgd);
4739 if ((cgd.ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
4740 g->status = MT_EXT_GET_ERROR;
4741 snprintf(g->error_str, sizeof(g->error_str),
4742 "Error %#x returned for XPT_GDEV_TYPE CCB",
4743 cgd.ccb_h.status);
4744 goto extget_bailout;
4745 }
4746
4747 cam_strvis(tmpstr, cgd.inq_data.vendor,
4748 sizeof(cgd.inq_data.vendor), sizeof(tmpstr));
4749 SASBADDVARSTRDESC(sb, indent, tmpstr, %s, vendor,
4750 sizeof(cgd.inq_data.vendor) + 1, "SCSI Vendor ID");
4751
4752 cam_strvis(tmpstr, cgd.inq_data.product,
4753 sizeof(cgd.inq_data.product), sizeof(tmpstr));
4754 SASBADDVARSTRDESC(sb, indent, tmpstr, %s, product,
4755 sizeof(cgd.inq_data.product) + 1, "SCSI Product ID");
4756
4757 cam_strvis(tmpstr, cgd.inq_data.revision,
4758 sizeof(cgd.inq_data.revision), sizeof(tmpstr));
4759 SASBADDVARSTRDESC(sb, indent, tmpstr, %s, revision,
4760 sizeof(cgd.inq_data.revision) + 1, "SCSI Revision");
4761
4762 if (cgd.serial_num_len > 0) {
4763 char *tmpstr2;
4764 size_t ts2_len;
4765 int ts2_malloc;
4766
4767 ts2_len = 0;
4768
4769 if (cgd.serial_num_len > sizeof(tmpstr)) {
4770 ts2_len = cgd.serial_num_len + 1;
4771 ts2_malloc = 1;
4772 tmpstr2 = malloc(ts2_len, M_SCSISA, M_NOWAIT | M_ZERO);
4773 /*
4774 * The 80 characters allocated on the stack above
4775 * will handle the vast majority of serial numbers.
4776 * If we run into one that is larger than that, and
4777 * we can't malloc the length without blocking,
4778 * bail out with an out of memory error.
4779 */
4780 if (tmpstr2 == NULL) {
4781 error = ENOMEM;
4782 goto extget_bailout;
4783 }
4784 } else {
4785 ts2_len = sizeof(tmpstr);
4786 ts2_malloc = 0;
4787 tmpstr2 = tmpstr;
4788 }
4789
4790 cam_strvis(tmpstr2, cgd.serial_num, cgd.serial_num_len,
4791 ts2_len);
4792
4793 SASBADDVARSTRDESC(sb, indent, tmpstr2, %s, serial_num,
4794 (ssize_t)cgd.serial_num_len + 1, "Serial Number");
4795 if (ts2_malloc != 0)
4796 free(tmpstr2, M_SCSISA);
4797 } else {
4798 /*
4799 * We return a serial_num element in any case, but it will
4800 * be empty if the device has no serial number.
4801 */
4802 tmpstr[0] = '\0';
4803 SASBADDVARSTRDESC(sb, indent, tmpstr, %s, serial_num,
4804 (ssize_t)0, "Serial Number");
4805 }
4806
4807 SASBADDUINTDESC(sb, indent, softc->maxio, %u, maxio,
4808 "Maximum I/O size allowed by driver and controller");
4809
4810 SASBADDUINTDESC(sb, indent, softc->cpi_maxio, %u, cpi_maxio,
4811 "Maximum I/O size reported by controller");
4812
4813 SASBADDUINTDESC(sb, indent, softc->max_blk, %u, max_blk,
4814 "Maximum block size supported by tape drive and media");
4815
4816 SASBADDUINTDESC(sb, indent, softc->min_blk, %u, min_blk,
4817 "Minimum block size supported by tape drive and media");
4818
4819 SASBADDUINTDESC(sb, indent, softc->blk_gran, %u, blk_gran,
4820 "Block granularity supported by tape drive and media");
4821
4822 maxio_tmp = min(softc->max_blk, softc->maxio);
4823
4824 SASBADDUINTDESC(sb, indent, maxio_tmp, %u, max_effective_iosize,
4825 "Maximum possible I/O size");
4826
4827 SASBADDINTDESC(sb, indent, softc->flags & SA_FLAG_FIXED ? 1 : 0, %d,
4828 fixed_mode, "Set to 1 for fixed block mode, 0 for variable block");
4829
4830 /*
4831 * XXX KDM include SIM, bus, target, LUN?
4832 */
4833 if (softc->flags & SA_FLAG_COMP_UNSUPP)
4834 tmpint = 0;
4835 else
4836 tmpint = 1;
4837 SASBADDINTDESC(sb, indent, tmpint, %d, compression_supported,
4838 "Set to 1 if compression is supported, 0 if not");
4839 if (softc->flags & SA_FLAG_COMP_ENABLED)
4840 tmpint = 1;
4841 else
4842 tmpint = 0;
4843 SASBADDINTDESC(sb, indent, tmpint, %d, compression_enabled,
4844 "Set to 1 if compression is enabled, 0 if not");
4845 SASBADDUINTDESC(sb, indent, softc->comp_algorithm, %u,
4846 compression_algorithm, "Numeric compression algorithm");
4847
4848 safillprot(softc, &indent, sb);
4849
4850 SASBADDUINTDESC(sb, indent, softc->media_blksize, %u,
4851 media_blocksize, "Block size reported by drive or set by user");
4852 SASBADDINTDESC(sb, indent, (intmax_t)softc->fileno, %jd,
4853 calculated_fileno, "Calculated file number, -1 if unknown");
4854 SASBADDINTDESC(sb, indent, (intmax_t)softc->blkno, %jd,
4855 calculated_rel_blkno, "Calculated block number relative to file, "
4856 "set to -1 if unknown");
4857 SASBADDINTDESC(sb, indent, (intmax_t)softc->rep_fileno, %jd,
4858 reported_fileno, "File number reported by drive, -1 if unknown");
4859 SASBADDINTDESC(sb, indent, (intmax_t)softc->rep_blkno, %jd,
4860 reported_blkno, "Block number relative to BOP/BOT reported by "
4861 "drive, -1 if unknown");
4862 SASBADDINTDESC(sb, indent, (intmax_t)softc->partition, %jd,
4863 partition, "Current partition number, 0 is the default");
4864 SASBADDINTDESC(sb, indent, softc->bop, %d, bop,
4865 "Set to 1 if drive is at the beginning of partition/tape, 0 if "
4866 "not, -1 if unknown");
4867 SASBADDINTDESC(sb, indent, softc->eop, %d, eop,
4868 "Set to 1 if drive is past early warning, 0 if not, -1 if unknown");
4869 SASBADDINTDESC(sb, indent, softc->bpew, %d, bpew,
4870 "Set to 1 if drive is past programmable early warning, 0 if not, "
4871 "-1 if unknown");
4872 SASBADDINTDESC(sb, indent, (intmax_t)softc->last_io_resid, %jd,
4873 residual, "Residual for the last I/O");
4874 /*
4875 * XXX KDM should we send a string with the current driver
4876 * status already decoded instead of a numeric value?
4877 */
4878 SASBADDINTDESC(sb, indent, softc->dsreg, %d, dsreg,
4879 "Current state of the driver");
4880
4881 safilldensitysb(softc, &indent, sb);
4882
4883 SASBENDNODE(sb, indent, mtextget);
4884
4885extget_bailout:
4886
4887 return (error);
4888}
4889
4890static int
4891saparamget(struct sa_softc *softc, struct sbuf *sb)
4892{
4893 int indent;
4894
4895 indent = 0;
4896 SASBADDNODE(sb, indent, mtparamget);
4897 SASBADDINTDESC(sb, indent, softc->sili, %d, sili,
4898 "Suppress an error on underlength variable reads");
4899 SASBADDINTDESC(sb, indent, softc->eot_warn, %d, eot_warn,
4900 "Return an error to warn that end of tape is approaching");
4901 safillprot(softc, &indent, sb);
4902 SASBENDNODE(sb, indent, mtparamget);
4903
4904 return (0);
4905}
4906
4907static void
4908saprevent(struct cam_periph *periph, int action)
4909{
4910 struct sa_softc *softc;
4911 union ccb *ccb;
4912 int error, sf;
4913
4914 softc = (struct sa_softc *)periph->softc;
4915
4916 if ((action == PR_ALLOW) && (softc->flags & SA_FLAG_TAPE_LOCKED) == 0)
4917 return;
4918 if ((action == PR_PREVENT) && (softc->flags & SA_FLAG_TAPE_LOCKED) != 0)
4919 return;
4920
4921 /*
4922 * We can be quiet about illegal requests.
4923 */
4925 sf = 0;
4926 } else
4927 sf = SF_QUIET_IR;
4928
4930
4931 /* It is safe to retry this operation */
4932 scsi_prevent(&ccb->csio, 5, NULL, MSG_SIMPLE_Q_TAG, action,
4934
4935 error = cam_periph_runccb(ccb, saerror, 0, sf, softc->device_stats);
4936 if (error == 0) {
4937 if (action == PR_ALLOW)
4938 softc->flags &= ~SA_FLAG_TAPE_LOCKED;
4939 else
4940 softc->flags |= SA_FLAG_TAPE_LOCKED;
4941 }
4942
4944}
4945
4946static int
4948{
4949 union ccb *ccb;
4950 struct sa_softc *softc;
4951 int error;
4952
4953 softc = (struct sa_softc *)periph->softc;
4954
4956
4957 /* It is safe to retry this operation */
4958 scsi_rewind(&ccb->csio, 2, NULL, MSG_SIMPLE_Q_TAG, FALSE,
4960
4961 softc->dsreg = MTIO_DSREG_REW;
4962 error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
4963 softc->dsreg = MTIO_DSREG_REST;
4964
4966 if (error == 0) {
4967 softc->partition = softc->fileno = softc->blkno = (daddr_t) 0;
4968 softc->rep_fileno = softc->rep_blkno = (daddr_t) 0;
4969 } else {
4970 softc->fileno = softc->blkno = (daddr_t) -1;
4971 softc->partition = (daddr_t) -1;
4972 softc->rep_fileno = softc->rep_blkno = (daddr_t) -1;
4973 }
4974 return (error);
4975}
4976
4977static int
4978saspace(struct cam_periph *periph, int count, scsi_space_code code)
4979{
4980 union ccb *ccb;
4981 struct sa_softc *softc;
4982 int error;
4983
4984 softc = (struct sa_softc *)periph->softc;
4985
4987
4988 /* This cannot be retried */
4989
4990 scsi_space(&ccb->csio, 0, NULL, MSG_SIMPLE_Q_TAG, code, count,
4992
4993 /*
4994 * Clear residual because we will be using it.
4995 */
4996 softc->last_ctl_resid = 0;
4997
4998 softc->dsreg = (count < 0)? MTIO_DSREG_REV : MTIO_DSREG_FWD;
4999 error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
5000 softc->dsreg = MTIO_DSREG_REST;
5001
5003
5004 /*
5005 * If a spacing operation has failed, we need to invalidate
5006 * this mount.
5007 *
5008 * If the spacing operation was setmarks or to end of recorded data,
5009 * we no longer know our relative position.
5010 *
5011 * If the spacing operations was spacing files in reverse, we
5012 * take account of the residual, but still check against less
5013 * than zero- if we've gone negative, we must have hit BOT.
5014 *
5015 * If the spacing operations was spacing records in reverse and
5016 * we have a residual, we've either hit BOT or hit a filemark.
5017 * In the former case, we know our new record number (0). In
5018 * the latter case, we have absolutely no idea what the real
5019 * record number is- we've stopped between the end of the last
5020 * record in the previous file and the filemark that stopped
5021 * our spacing backwards.
5022 */
5023 if (error) {
5024 softc->fileno = softc->blkno = (daddr_t) -1;
5025 softc->rep_blkno = softc->partition = (daddr_t) -1;
5026 softc->rep_fileno = (daddr_t) -1;
5027 } else if (code == SS_SETMARKS || code == SS_EOD) {
5028 softc->fileno = softc->blkno = (daddr_t) -1;
5029 } else if (code == SS_FILEMARKS && softc->fileno != (daddr_t) -1) {
5030 softc->fileno += (count - softc->last_ctl_resid);
5031 if (softc->fileno < 0) /* we must of hit BOT */
5032 softc->fileno = 0;
5033 softc->blkno = 0;
5034 } else if (code == SS_BLOCKS && softc->blkno != (daddr_t) -1) {
5035 softc->blkno += (count - softc->last_ctl_resid);
5036 if (count < 0) {
5037 if (softc->last_ctl_resid || softc->blkno < 0) {
5038 if (softc->fileno == 0) {
5039 softc->blkno = 0;
5040 } else {
5041 softc->blkno = (daddr_t) -1;
5042 }
5043 }
5044 }
5045 }
5046 if (error == 0)
5048
5049 return (error);
5050}
5051
5052static int
5053sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks, int immed)
5054{
5055 union ccb *ccb;
5056 struct sa_softc *softc;
5057 int error, nwm = 0;
5058
5059 softc = (struct sa_softc *)periph->softc;
5060 if (softc->open_rdonly)
5061 return (EBADF);
5062
5064 /*
5065 * Clear residual because we will be using it.
5066 */
5067 softc->last_ctl_resid = 0;
5068
5069 softc->dsreg = MTIO_DSREG_FMK;
5070 /* this *must* not be retried */
5072 immed, setmarks, nmarks, SSD_FULL_SIZE,
5074 softc->dsreg = MTIO_DSREG_REST;
5075
5076 error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
5077
5078 if (error == 0 && nmarks) {
5079 struct sa_softc *softc = (struct sa_softc *)periph->softc;
5080 nwm = nmarks - softc->last_ctl_resid;
5081 softc->filemarks += nwm;
5082 }
5083
5085
5086 /*
5087 * Update relative positions (if we're doing that).
5088 */
5089 if (error) {
5090 softc->fileno = softc->blkno = softc->partition = (daddr_t) -1;
5091 } else if (softc->fileno != (daddr_t) -1) {
5092 softc->fileno += nwm;
5093 softc->blkno = 0;
5094 }
5095
5096 /*
5097 * Ask the tape drive for position information.
5098 */
5100
5101 /*
5102 * If we got valid position information, since we just wrote a file
5103 * mark, we know we're at the file mark and block 0 after that
5104 * filemark.
5105 */
5106 if (softc->rep_fileno != (daddr_t) -1) {
5107 softc->fileno = softc->rep_fileno;
5108 softc->blkno = 0;
5109 }
5110
5111 return (error);
5112}
5113
5114static int
5116{
5117 union ccb *ccb;
5118 struct scsi_tape_position_long_data long_pos;
5119 struct sa_softc *softc = (struct sa_softc *)periph->softc;
5120 int error;
5121
5122 if (softc->quirks & SA_QUIRK_NO_LONG_POS) {
5123 softc->rep_fileno = (daddr_t) -1;
5124 softc->rep_blkno = (daddr_t) -1;
5125 softc->bop = softc->eop = softc->bpew = -1;
5126 return (EOPNOTSUPP);
5127 }
5128
5129 bzero(&long_pos, sizeof(long_pos));
5130
5133 /*retries*/ 1,
5134 /*cbfcnp*/ NULL,
5135 /*tag_action*/ MSG_SIMPLE_Q_TAG,
5136 /*service_action*/ SA_RPOS_LONG_FORM,
5137 /*data_ptr*/ (uint8_t *)&long_pos,
5138 /*length*/ sizeof(long_pos),
5139 /*sense_len*/ SSD_FULL_SIZE,
5140 /*timeout*/
5142
5143 softc->dsreg = MTIO_DSREG_RBSY;
5145 softc->device_stats);
5146 softc->dsreg = MTIO_DSREG_REST;
5147
5148 if (error == 0) {
5149 if (long_pos.flags & SA_RPOS_LONG_MPU) {
5150 /*
5151 * If the drive doesn't know what file mark it is
5152 * on, our calculated filemark isn't going to be
5153 * accurate either.
5154 */
5155 softc->fileno = (daddr_t) -1;
5156 softc->rep_fileno = (daddr_t) -1;
5157 } else {
5158 softc->fileno = softc->rep_fileno =
5160 }
5161
5162 if (long_pos.flags & SA_RPOS_LONG_LONU) {
5163 softc->partition = (daddr_t) -1;
5164 softc->rep_blkno = (daddr_t) -1;
5165 /*
5166 * If the tape drive doesn't know its block
5167 * position, we can't claim to know it either.
5168 */
5169 softc->blkno = (daddr_t) -1;
5170 } else {
5171 softc->partition = scsi_4btoul(long_pos.partition);
5172 softc->rep_blkno =
5174 }
5175 if (long_pos.flags & SA_RPOS_LONG_BOP)
5176 softc->bop = 1;
5177 else
5178 softc->bop = 0;
5179
5180 if (long_pos.flags & SA_RPOS_LONG_EOP)
5181 softc->eop = 1;
5182 else
5183 softc->eop = 0;
5184
5185 if ((long_pos.flags & SA_RPOS_LONG_BPEW)
5186 || (softc->set_pews_status != 0)) {
5187 softc->bpew = 1;
5188 if (softc->set_pews_status > 0)
5189 softc->set_pews_status--;
5190 } else
5191 softc->bpew = 0;
5192 } else if (error == EINVAL) {
5193 /*
5194 * If this drive returned an invalid-request type error,
5195 * then it likely doesn't support the long form report.
5196 */
5197 softc->quirks |= SA_QUIRK_NO_LONG_POS;
5198 }
5199
5200 if (error != 0) {
5201 softc->rep_fileno = softc->rep_blkno = (daddr_t) -1;
5202 softc->partition = (daddr_t) -1;
5203 softc->bop = softc->eop = softc->bpew = -1;
5204 }
5205
5207
5208 return (error);
5209}
5210
5211static int
5212sardpos(struct cam_periph *periph, int hard, u_int32_t *blkptr)
5213{
5214 struct scsi_tape_position_data loc;
5215 union ccb *ccb;
5216 struct sa_softc *softc = (struct sa_softc *)periph->softc;
5217 int error;
5218
5219 /*
5220 * We try and flush any buffered writes here if we were writing
5221 * and we're trying to get hardware block position. It eats
5222 * up performance substantially, but I'm wary of drive firmware.
5223 *
5224 * I think that *logical* block position is probably okay-
5225 * but hardware block position might have to wait for data
5226 * to hit media to be valid. Caveat Emptor.
5227 */
5228
5229 if (hard && (softc->flags & SA_FLAG_TAPE_WRITTEN)) {
5230 error = sawritefilemarks(periph, 0, 0, 0);
5231 if (error && error != EACCES)
5232 return (error);
5233 }
5234
5237 hard, &loc, SSD_FULL_SIZE,
5239 softc->dsreg = MTIO_DSREG_RBSY;
5240 error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
5241 softc->dsreg = MTIO_DSREG_REST;
5242
5243 if (error == 0) {
5244 if (loc.flags & SA_RPOS_UNCERTAIN) {
5245 error = EINVAL; /* nothing is certain */
5246 } else {
5247 *blkptr = scsi_4btoul(loc.firstblk);
5248 }
5249 }
5250
5252 return (error);
5253}
5254
5255static int
5256sasetpos(struct cam_periph *periph, int hard, struct mtlocate *locate_info)
5257{
5258 union ccb *ccb;
5259 struct sa_softc *softc;
5260 int locate16;
5261 int immed, cp;
5262 int error;
5263
5264 /*
5265 * We used to try and flush any buffered writes here.
5266 * Now we push this onto user applications to either
5267 * flush the pending writes themselves (via a zero count
5268 * WRITE FILEMARKS command) or they can trust their tape
5269 * drive to do this correctly for them.
5270 */
5271
5272 softc = (struct sa_softc *)periph->softc;
5274
5275 cp = locate_info->flags & MT_LOCATE_FLAG_CHANGE_PART ? 1 : 0;
5276 immed = locate_info->flags & MT_LOCATE_FLAG_IMMED ? 1 : 0;
5277
5278 /*
5279 * Determine whether we have to use LOCATE or LOCATE16. The hard
5280 * bit is only possible with LOCATE, but the new ioctls do not
5281 * allow setting that bit. So we can't get into the situation of
5282 * having the hard bit set with a block address that is larger than
5283 * 32-bits.
5284 */
5285 if (hard != 0)
5286 locate16 = 0;
5287 else if ((locate_info->dest_type != MT_LOCATE_DEST_OBJECT)
5288 || (locate_info->block_address_mode != MT_LOCATE_BAM_IMPLICIT)
5289 || (locate_info->logical_id > SA_SPOS_MAX_BLK))
5290 locate16 = 1;
5291 else
5292 locate16 = 0;
5293
5294 if (locate16 != 0) {
5296 /*retries*/ 1,
5297 /*cbfcnp*/ NULL,
5298 /*tag_action*/ MSG_SIMPLE_Q_TAG,
5299 /*immed*/ immed,
5300 /*cp*/ cp,
5301 /*dest_type*/ locate_info->dest_type,
5302 /*bam*/ locate_info->block_address_mode,
5303 /*partition*/ locate_info->partition,
5304 /*logical_id*/ locate_info->logical_id,
5305 /*sense_len*/ SSD_FULL_SIZE,
5306 /*timeout*/
5308 } else {
5310 /*retries*/ 1,
5311 /*cbfcnp*/ NULL,
5312 /*tag_action*/ MSG_SIMPLE_Q_TAG,
5313 /*immed*/ immed,
5314 /*cp*/ cp,
5315 /*hard*/ hard,
5316 /*partition*/ locate_info->partition,
5317 /*block_address*/ locate_info->logical_id,
5318 /*sense_len*/ SSD_FULL_SIZE,
5319 /*timeout*/
5321 }
5322
5323 softc->dsreg = MTIO_DSREG_POS;
5324 error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
5325 softc->dsreg = MTIO_DSREG_REST;
5327
5328 /*
5329 * We assume the calculated file and block numbers are unknown
5330 * unless we have enough information to populate them.
5331 */
5332 softc->fileno = softc->blkno = (daddr_t) -1;
5333
5334 /*
5335 * If the user requested changing the partition and the request
5336 * succeeded, note the partition.
5337 */
5338 if ((error == 0)
5339 && (cp != 0))
5340 softc->partition = locate_info->partition;
5341 else
5342 softc->partition = (daddr_t) -1;
5343
5344 if (error == 0) {
5345 switch (locate_info->dest_type) {
5346 case MT_LOCATE_DEST_FILE:
5347 /*
5348 * This is the only case where we can reliably
5349 * calculate the file and block numbers.
5350 */
5351 softc->fileno = locate_info->logical_id;
5352 softc->blkno = 0;
5353 break;
5354 case MT_LOCATE_DEST_OBJECT:
5355 case MT_LOCATE_DEST_SET:
5356 case MT_LOCATE_DEST_EOD:
5357 default:
5358 break;
5359 }
5360 }
5361
5362 /*
5363 * Ask the drive for current position information.
5364 */
5366
5367 return (error);
5368}
5369
5370static int
5372{
5373 union ccb *ccb;
5374 struct sa_softc *softc;
5375 int error;
5376
5377 softc = (struct sa_softc *)periph->softc;
5378
5380
5381 /* It is safe to retry this operation */
5382 scsi_load_unload(&ccb->csio, 5, NULL, MSG_SIMPLE_Q_TAG, FALSE,
5383 FALSE, TRUE, TRUE, SSD_FULL_SIZE,
5385
5386 softc->dsreg = MTIO_DSREG_TEN;
5387 error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
5388 softc->dsreg = MTIO_DSREG_REST;
5389
5391 if (error == 0) {
5392 softc->partition = softc->fileno = softc->blkno = (daddr_t) 0;
5394 } else
5395 softc->partition = softc->fileno = softc->blkno = (daddr_t) -1;
5396 return (error);
5397}
5398
5399static int
5401{
5402 union ccb *ccb;
5403 struct sa_softc *softc;
5404 int error;
5405
5406 softc = (struct sa_softc *)periph->softc;
5408
5409 /* It is safe to retry this operation */
5412 reserve);
5413 softc->dsreg = MTIO_DSREG_RBSY;
5414 error = cam_periph_runccb(ccb, saerror, 0,
5416 softc->dsreg = MTIO_DSREG_REST;
5418
5419 /*
5420 * If the error was Illegal Request, then the device doesn't support
5421 * RESERVE/RELEASE. This is not an error.
5422 */
5423 if (error == EINVAL) {
5424 error = 0;
5425 }
5426
5427 return (error);
5428}
5429
5430static int
5432{
5433 union ccb *ccb;
5434 struct sa_softc *softc;
5435 int error;
5436
5437 softc = (struct sa_softc *)periph->softc;
5438
5440
5441 /* It is safe to retry this operation */
5442 scsi_load_unload(&ccb->csio, 5, NULL, MSG_SIMPLE_Q_TAG, FALSE,
5443 FALSE, FALSE, load, SSD_FULL_SIZE,
5445
5446 softc->dsreg = (load)? MTIO_DSREG_LD : MTIO_DSREG_UNL;
5447 error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
5448 softc->dsreg = MTIO_DSREG_REST;
5450
5451 if (error || load == 0) {
5452 softc->partition = softc->fileno = softc->blkno = (daddr_t) -1;
5453 softc->rep_fileno = softc->rep_blkno = (daddr_t) -1;
5454 } else if (error == 0) {
5455 softc->partition = softc->fileno = softc->blkno = (daddr_t) 0;
5457 }
5458 return (error);
5459}
5460
5461static int
5462saerase(struct cam_periph *periph, int longerase)
5463{
5464
5465 union ccb *ccb;
5466 struct sa_softc *softc;
5467 int error;
5468
5469 softc = (struct sa_softc *)periph->softc;
5470 if (softc->open_rdonly)
5471 return (EBADF);
5472
5474
5475 scsi_erase(&ccb->csio, 1, NULL, MSG_SIMPLE_Q_TAG, FALSE, longerase,
5477
5478 softc->dsreg = MTIO_DSREG_ZER;
5479 error = cam_periph_runccb(ccb, saerror, 0, 0, softc->device_stats);
5480 softc->dsreg = MTIO_DSREG_REST;
5481
5483 return (error);
5484}
5485
5486/*
5487 * Fill an sbuf with density data in XML format. This particular macro
5488 * works for multi-byte integer fields.
5489 *
5490 * Note that 1 byte fields aren't supported here. The reason is that the
5491 * compiler does not evaluate the sizeof(), and assumes that any of the
5492 * sizes are possible for a given field. So passing in a multi-byte
5493 * field will result in a warning that the assignment makes an integer
5494 * from a pointer without a cast, if there is an assignment in the 1 byte
5495 * case.
5496 */
5497#define SAFILLDENSSB(dens_data, sb, indent, field, desc_remain, \
5498 len_to_go, cur_offset, desc){ \
5499 size_t cur_field_len; \
5500 \
5501 cur_field_len = sizeof(dens_data->field); \
5502 if (desc_remain < cur_field_len) { \
5503 len_to_go -= desc_remain; \
5504 cur_offset += desc_remain; \
5505 continue; \
5506 } \
5507 len_to_go -= cur_field_len; \
5508 cur_offset += cur_field_len; \
5509 desc_remain -= cur_field_len; \
5510 \
5511 switch (sizeof(dens_data->field)) { \
5512 case 1: \
5513 KASSERT(1 == 0, ("Programmer error, invalid 1 byte " \
5514 "field width for SAFILLDENSFIELD")); \
5515 break; \
5516 case 2: \
5517 SASBADDUINTDESC(sb, indent, \
5518 scsi_2btoul(dens_data->field), %u, field, desc); \
5519 break; \
5520 case 3: \
5521 SASBADDUINTDESC(sb, indent, \
5522 scsi_3btoul(dens_data->field), %u, field, desc); \
5523 break; \
5524 case 4: \
5525 SASBADDUINTDESC(sb, indent, \
5526 scsi_4btoul(dens_data->field), %u, field, desc); \
5527 break; \
5528 case 8: \
5529 SASBADDUINTDESC(sb, indent, \
5530 (uintmax_t)scsi_8btou64(dens_data->field), %ju, \
5531 field, desc); \
5532 break; \
5533 default: \
5534 break; \
5535 } \
5536};
5537/*
5538 * Fill an sbuf with density data in XML format. This particular macro
5539 * works for strings.
5540 */
5541#define SAFILLDENSSBSTR(dens_data, sb, indent, field, desc_remain, \
5542 len_to_go, cur_offset, desc){ \
5543 size_t cur_field_len; \
5544 char tmpstr[32]; \
5545 \
5546 cur_field_len = sizeof(dens_data->field); \
5547 if (desc_remain < cur_field_len) { \
5548 len_to_go -= desc_remain; \
5549 cur_offset += desc_remain; \
5550 continue; \
5551 } \
5552 len_to_go -= cur_field_len; \
5553 cur_offset += cur_field_len; \
5554 desc_remain -= cur_field_len; \
5555 \
5556 cam_strvis(tmpstr, dens_data->field, \
5557 sizeof(dens_data->field), sizeof(tmpstr)); \
5558 SASBADDVARSTRDESC(sb, indent, tmpstr, %s, field, \
5559 strlen(tmpstr) + 1, desc); \
5560};
5561
5562/*
5563 * Fill an sbuf with density data descriptors.
5564 */
5565static void
5566safilldenstypesb(struct sbuf *sb, int *indent, uint8_t *buf, int buf_len,
5567 int is_density)
5568{
5569 struct scsi_density_hdr *hdr;
5570 uint32_t hdr_len;
5571 int len_to_go, cur_offset;
5572 int length_offset;
5573 int num_reports, need_close;
5574
5575 /*
5576 * We need at least the header length. Note that this isn't an
5577 * error, not all tape drives will have every data type.
5578 */
5579 if (buf_len < sizeof(*hdr))
5580 goto bailout;
5581
5582 hdr = (struct scsi_density_hdr *)buf;
5583 hdr_len = scsi_2btoul(hdr->length);
5584 len_to_go = min(buf_len - sizeof(*hdr), hdr_len);
5585 if (is_density) {
5586 length_offset = __offsetof(struct scsi_density_data,
5587 bits_per_mm);
5588 } else {
5589 length_offset = __offsetof(struct scsi_medium_type_data,
5590 num_density_codes);
5591 }
5592 cur_offset = sizeof(*hdr);
5593
5594 num_reports = 0;
5595 need_close = 0;
5596
5597 while (len_to_go > length_offset) {
5598 struct scsi_density_data *dens_data;
5599 struct scsi_medium_type_data *type_data;
5600 int desc_remain;
5601 size_t cur_field_len;
5602
5603 dens_data = NULL;
5604 type_data = NULL;
5605
5606 if (is_density) {
5607 dens_data =(struct scsi_density_data *)&buf[cur_offset];
5608 if (dens_data->byte2 & SDD_DLV)
5609 desc_remain = scsi_2btoul(dens_data->length);
5610 else
5611 desc_remain = SDD_DEFAULT_LENGTH -
5612 length_offset;
5613 } else {
5614 type_data = (struct scsi_medium_type_data *)
5615 &buf[cur_offset];
5616 desc_remain = scsi_2btoul(type_data->length);
5617 }
5618
5619 len_to_go -= length_offset;
5620 desc_remain = min(desc_remain, len_to_go);
5621 cur_offset += length_offset;
5622
5623 if (need_close != 0) {
5624 SASBENDNODE(sb, *indent, density_entry);
5625 }
5626
5627 SASBADDNODENUM(sb, *indent, density_entry, num_reports);
5628 num_reports++;
5629 need_close = 1;
5630
5631 if (is_density) {
5632 SASBADDUINTDESC(sb, *indent,
5633 dens_data->primary_density_code, %u,
5634 primary_density_code, "Primary Density Code");
5635 SASBADDUINTDESC(sb, *indent,
5636 dens_data->secondary_density_code, %u,
5637 secondary_density_code, "Secondary Density Code");
5638 SASBADDUINTDESC(sb, *indent,
5639 dens_data->byte2 & ~SDD_DLV, %#x, density_flags,
5640 "Density Flags");
5641
5642 SAFILLDENSSB(dens_data, sb, *indent, bits_per_mm,
5643 desc_remain, len_to_go, cur_offset, "Bits per mm");
5644 SAFILLDENSSB(dens_data, sb, *indent, media_width,
5645 desc_remain, len_to_go, cur_offset, "Media width");
5646 SAFILLDENSSB(dens_data, sb, *indent, tracks,
5647 desc_remain, len_to_go, cur_offset,
5648 "Number of Tracks");
5649 SAFILLDENSSB(dens_data, sb, *indent, capacity,
5650 desc_remain, len_to_go, cur_offset, "Capacity");
5651
5652 SAFILLDENSSBSTR(dens_data, sb, *indent, assigning_org,
5653 desc_remain, len_to_go, cur_offset,
5654 "Assigning Organization");
5655
5656 SAFILLDENSSBSTR(dens_data, sb, *indent, density_name,
5657 desc_remain, len_to_go, cur_offset, "Density Name");
5658
5659 SAFILLDENSSBSTR(dens_data, sb, *indent, description,
5660 desc_remain, len_to_go, cur_offset, "Description");
5661 } else {
5662 int i;
5663
5664 SASBADDUINTDESC(sb, *indent, type_data->medium_type,
5665 %u, medium_type, "Medium Type");
5666
5667 cur_field_len =
5668 __offsetof(struct scsi_medium_type_data,
5669 media_width) -
5670 __offsetof(struct scsi_medium_type_data,
5672
5673 if (desc_remain < cur_field_len) {
5674 len_to_go -= desc_remain;
5675 cur_offset += desc_remain;
5676 continue;
5677 }
5678 len_to_go -= cur_field_len;
5679 cur_offset += cur_field_len;
5680 desc_remain -= cur_field_len;
5681
5682 SASBADDINTDESC(sb, *indent,
5683 type_data->num_density_codes, %d,
5684 num_density_codes, "Number of Density Codes");
5685 SASBADDNODE(sb, *indent, density_code_list);
5686 for (i = 0; i < type_data->num_density_codes;
5687 i++) {
5688 SASBADDUINTDESC(sb, *indent,
5689 type_data->primary_density_codes[i], %u,
5690 density_code, "Density Code");
5691 }
5692 SASBENDNODE(sb, *indent, density_code_list);
5693
5694 SAFILLDENSSB(type_data, sb, *indent, media_width,
5695 desc_remain, len_to_go, cur_offset,
5696 "Media width");
5697 SAFILLDENSSB(type_data, sb, *indent, medium_length,
5698 desc_remain, len_to_go, cur_offset,
5699 "Medium length");
5700
5701 /*
5702 * Account for the two reserved bytes.
5703 */
5704 cur_field_len = sizeof(type_data->reserved2);
5705 if (desc_remain < cur_field_len) {
5706 len_to_go -= desc_remain;
5707 cur_offset += desc_remain;
5708 continue;
5709 }
5710 len_to_go -= cur_field_len;
5711 cur_offset += cur_field_len;
5712 desc_remain -= cur_field_len;
5713
5714 SAFILLDENSSBSTR(type_data, sb, *indent, assigning_org,
5715 desc_remain, len_to_go, cur_offset,
5716 "Assigning Organization");
5717 SAFILLDENSSBSTR(type_data, sb, *indent,
5718 medium_type_name, desc_remain, len_to_go,
5719 cur_offset, "Medium type name");
5720 SAFILLDENSSBSTR(type_data, sb, *indent, description,
5721 desc_remain, len_to_go, cur_offset, "Description");
5722 }
5723 }
5724 if (need_close != 0) {
5725 SASBENDNODE(sb, *indent, density_entry);
5726 }
5727
5728bailout:
5729 return;
5730}
5731
5732/*
5733 * Fill an sbuf with density data information
5734 */
5735static void
5736safilldensitysb(struct sa_softc *softc, int *indent, struct sbuf *sb)
5737{
5738 int i, is_density;
5739
5740 SASBADDNODE(sb, *indent, mtdensity);
5741 SASBADDUINTDESC(sb, *indent, softc->media_density, %u, media_density,
5742 "Current Medium Density");
5743 is_density = 0;
5744 for (i = 0; i < SA_DENSITY_TYPES; i++) {
5745 int tmpint;
5746
5747 if (softc->density_info_valid[i] == 0)
5748 continue;
5749
5750 SASBADDNODE(sb, *indent, density_report);
5751 if (softc->density_type_bits[i] & SRDS_MEDIUM_TYPE) {
5752 tmpint = 1;
5753 is_density = 0;
5754 } else {
5755 tmpint = 0;
5756 is_density = 1;
5757 }
5758 SASBADDINTDESC(sb, *indent, tmpint, %d, medium_type_report,
5759 "Medium type report");
5760
5761 if (softc->density_type_bits[i] & SRDS_MEDIA)
5762 tmpint = 1;
5763 else
5764 tmpint = 0;
5765 SASBADDINTDESC(sb, *indent, tmpint, %d, media_report,
5766 "Media report");
5767
5768 safilldenstypesb(sb, indent, softc->density_info[i],
5769 softc->density_info_valid[i], is_density);
5770 SASBENDNODE(sb, *indent, density_report);
5771 }
5772 SASBENDNODE(sb, *indent, mtdensity);
5773}
5774
5775/*
5776 * Given a completed REPORT SUPPORTED OPERATION CODES command with timeout
5777 * descriptors, go through the descriptors and set the sa(4) driver
5778 * timeouts to the recommended values.
5779 */
5780static void
5781saloadtimeouts(struct sa_softc *softc, union ccb *ccb)
5782{
5783 uint32_t valid_len, avail_len = 0, used_len = 0;
5786 uint8_t *buf;
5787
5789 valid_len = ccb->csio.dxfer_len - ccb->csio.resid;
5790
5791 if (valid_len < sizeof(*hdr))
5792 return;
5793
5794 avail_len = scsi_4btoul(hdr->length) + sizeof(hdr->length);
5795 if ((avail_len != 0)
5796 && (avail_len > valid_len)) {
5797 xpt_print(softc->periph->path, "WARNING: available timeout "
5798 "descriptor len %zu > valid len %u\n", avail_len,valid_len);
5799 }
5800
5801 used_len = sizeof(hdr->length);
5802 avail_len = MIN(avail_len, valid_len - sizeof(*hdr));
5803 buf = ccb->csio.data_ptr;
5804 while ((avail_len - used_len) > sizeof(*desc)) {
5806 uint32_t td_len;
5807 uint32_t rec_time;
5808 uint8_t *cur_ptr;
5809
5810 cur_ptr = &buf[used_len];
5811 desc = (struct scsi_report_supported_opcodes_descr *)cur_ptr;
5812
5813 used_len += sizeof(*desc);
5814 /* If there's no timeout descriptor, keep going */
5815 if ((desc->flags & RSO_CTDP) == 0)
5816 continue;
5817
5818 /*
5819 * If we don't have enough space to fit a timeout
5820 * descriptor then we're done.
5821 */
5822 if ((avail_len - used_len) < sizeof(*td)) {
5823 used_len = avail_len;
5824 continue;
5825 }
5826
5827 cur_ptr = &buf[used_len];
5828 td = (struct scsi_report_supported_opcodes_timeout *)cur_ptr;
5829 td_len = scsi_2btoul(td->length);
5830 td_len += sizeof(td->length);
5831 used_len += td_len;
5832
5833 if (td_len < sizeof(*td))
5834 continue;
5835
5836 /*
5837 * Use the recommended timeout. The nominal time is the
5838 * time to wait before querying for status.
5839 */
5840 rec_time = scsi_4btoul(td->recommended_time);
5841
5842 /*
5843 * Our timeouts are set in thousandths of a seconds.
5844 */
5845 rec_time *= 1000;
5846
5847 switch(desc->opcode) {
5848 case ERASE:
5849 softc->timeout_info[SA_TIMEOUT_ERASE] = rec_time;
5850 break;
5851 case LOAD_UNLOAD:
5852 softc->timeout_info[SA_TIMEOUT_LOAD] = rec_time;
5853 break;
5854 case LOCATE:
5855 case LOCATE_16:
5856 /*
5857 * We are assuming these are the same timeout.
5858 */
5859 softc->timeout_info[SA_TIMEOUT_LOCATE] = rec_time;
5860 break;
5861 case MODE_SELECT_6:
5862 case MODE_SELECT_10:
5863 /*
5864 * We are assuming these are the same timeout.
5865 */
5866 softc->timeout_info[SA_TIMEOUT_MODE_SELECT] = rec_time;
5867 break;
5868 case MODE_SENSE_6:
5869 case MODE_SENSE_10:
5870 /*
5871 * We are assuming these are the same timeout.
5872 */
5873 softc->timeout_info[SA_TIMEOUT_MODE_SENSE] = rec_time;
5874 break;
5875 case PREVENT_ALLOW:
5876 softc->timeout_info[SA_TIMEOUT_PREVENT] = rec_time;
5877 break;
5878 case SA_READ:
5879 softc->timeout_info[SA_TIMEOUT_READ] = rec_time;
5880 break;
5881 case READ_BLOCK_LIMITS:
5883 rec_time;
5884 break;
5885 case READ_POSITION:
5886 /*
5887 * Note that this may show up multiple times for
5888 * the short form, long form and extended form
5889 * service actions. We're assuming they are all
5890 * the same.
5891 */
5892 softc->timeout_info[SA_TIMEOUT_READ_POSITION] =rec_time;
5893 break;
5895 softc->timeout_info[SA_TIMEOUT_REP_DENSITY] = rec_time;
5896 break;
5897 case RESERVE_UNIT:
5898 case RELEASE_UNIT:
5899 /* We are assuming these are the same timeout.*/
5900 softc->timeout_info[SA_TIMEOUT_RESERVE] = rec_time;
5901 break;
5902 case REWIND:
5903 softc->timeout_info[SA_TIMEOUT_REWIND] = rec_time;
5904 break;
5905 case SPACE:
5906 softc->timeout_info[SA_TIMEOUT_SPACE] = rec_time;
5907 break;
5908 case TEST_UNIT_READY:
5909 softc->timeout_info[SA_TIMEOUT_TUR] = rec_time;
5910 break;
5911 case SA_WRITE:
5912 softc->timeout_info[SA_TIMEOUT_WRITE] = rec_time;
5913 break;
5914 case WRITE_FILEMARKS:
5916 rec_time;
5917 break;
5918 default:
5919 /*
5920 * We have explicit cases for all of the timeouts
5921 * we use.
5922 */
5923 break;
5924 }
5925 }
5926}
5927
5928#endif /* _KERNEL */
5929
5930/*
5931 * Read tape block limits command.
5932 */
5933void
5934scsi_read_block_limits(struct ccb_scsiio *csio, u_int32_t retries,
5935 void (*cbfcnp)(struct cam_periph *, union ccb *),
5936 u_int8_t tag_action,
5937 struct scsi_read_block_limits_data *rlimit_buf,
5938 u_int8_t sense_len, u_int32_t timeout)
5939{
5940 struct scsi_read_block_limits *scsi_cmd;
5941
5942 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action,
5943 (u_int8_t *)rlimit_buf, sizeof(*rlimit_buf), sense_len,
5944 sizeof(*scsi_cmd), timeout);
5945
5946 scsi_cmd = (struct scsi_read_block_limits *)&csio->cdb_io.cdb_bytes;
5947 bzero(scsi_cmd, sizeof(*scsi_cmd));
5948 scsi_cmd->opcode = READ_BLOCK_LIMITS;
5949}
5950
5951void
5952scsi_sa_read_write(struct ccb_scsiio *csio, u_int32_t retries,
5953 void (*cbfcnp)(struct cam_periph *, union ccb *),
5954 u_int8_t tag_action, int readop, int sli,
5955 int fixed, u_int32_t length, u_int8_t *data_ptr,
5956 u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout)
5957{
5958 struct scsi_sa_rw *scsi_cmd;
5959 int read;
5960
5961 read = (readop & SCSI_RW_DIRMASK) == SCSI_RW_READ;
5962
5963 scsi_cmd = (struct scsi_sa_rw *)&csio->cdb_io.cdb_bytes;
5964 scsi_cmd->opcode = read ? SA_READ : SA_WRITE;
5965 scsi_cmd->sli_fixed = 0;
5966 if (sli && read)
5967 scsi_cmd->sli_fixed |= SAR_SLI;
5968 if (fixed)
5969 scsi_cmd->sli_fixed |= SARW_FIXED;
5970 scsi_ulto3b(length, scsi_cmd->length);
5971 scsi_cmd->control = 0;
5972
5973 cam_fill_csio(csio, retries, cbfcnp, (read ? CAM_DIR_IN : CAM_DIR_OUT) |
5974 ((readop & SCSI_RW_BIO) != 0 ? CAM_DATA_BIO : 0),
5975 tag_action, data_ptr, dxfer_len, sense_len,
5976 sizeof(*scsi_cmd), timeout);
5977}
5978
5979void
5980scsi_load_unload(struct ccb_scsiio *csio, u_int32_t retries,
5981 void (*cbfcnp)(struct cam_periph *, union ccb *),
5982 u_int8_t tag_action, int immediate, int eot,
5983 int reten, int load, u_int8_t sense_len,
5984 u_int32_t timeout)
5985{
5986 struct scsi_load_unload *scsi_cmd;
5987
5988 scsi_cmd = (struct scsi_load_unload *)&csio->cdb_io.cdb_bytes;
5989 bzero(scsi_cmd, sizeof(*scsi_cmd));
5990 scsi_cmd->opcode = LOAD_UNLOAD;
5991 if (immediate)
5992 scsi_cmd->immediate = SLU_IMMED;
5993 if (eot)
5994 scsi_cmd->eot_reten_load |= SLU_EOT;
5995 if (reten)
5996 scsi_cmd->eot_reten_load |= SLU_RETEN;
5997 if (load)
5998 scsi_cmd->eot_reten_load |= SLU_LOAD;
5999
6000 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action,
6001 NULL, 0, sense_len, sizeof(*scsi_cmd), timeout);
6002}
6003
6004void
6005scsi_rewind(struct ccb_scsiio *csio, u_int32_t retries,
6006 void (*cbfcnp)(struct cam_periph *, union ccb *),
6007 u_int8_t tag_action, int immediate, u_int8_t sense_len,
6008 u_int32_t timeout)
6009{
6010 struct scsi_rewind *scsi_cmd;
6011
6012 scsi_cmd = (struct scsi_rewind *)&csio->cdb_io.cdb_bytes;
6013 bzero(scsi_cmd, sizeof(*scsi_cmd));
6014 scsi_cmd->opcode = REWIND;
6015 if (immediate)
6016 scsi_cmd->immediate = SREW_IMMED;
6017
6018 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
6019 0, sense_len, sizeof(*scsi_cmd), timeout);
6020}
6021
6022void
6023scsi_space(struct ccb_scsiio *csio, u_int32_t retries,
6024 void (*cbfcnp)(struct cam_periph *, union ccb *),
6025 u_int8_t tag_action, scsi_space_code code,
6026 u_int32_t count, u_int8_t sense_len, u_int32_t timeout)
6027{
6028 struct scsi_space *scsi_cmd;
6029
6030 scsi_cmd = (struct scsi_space *)&csio->cdb_io.cdb_bytes;
6031 scsi_cmd->opcode = SPACE;
6032 scsi_cmd->code = code;
6033 scsi_ulto3b(count, scsi_cmd->count);
6034 scsi_cmd->control = 0;
6035
6036 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
6037 0, sense_len, sizeof(*scsi_cmd), timeout);
6038}
6039
6040void
6041scsi_write_filemarks(struct ccb_scsiio *csio, u_int32_t retries,
6042 void (*cbfcnp)(struct cam_periph *, union ccb *),
6043 u_int8_t tag_action, int immediate, int setmark,
6044 u_int32_t num_marks, u_int8_t sense_len,
6045 u_int32_t timeout)
6046{
6047 struct scsi_write_filemarks *scsi_cmd;
6048
6049 scsi_cmd = (struct scsi_write_filemarks *)&csio->cdb_io.cdb_bytes;
6050 bzero(scsi_cmd, sizeof(*scsi_cmd));
6051 scsi_cmd->opcode = WRITE_FILEMARKS;
6052 if (immediate)
6053 scsi_cmd->byte2 |= SWFMRK_IMMED;
6054 if (setmark)
6055 scsi_cmd->byte2 |= SWFMRK_WSMK;
6056
6057 scsi_ulto3b(num_marks, scsi_cmd->num_marks);
6058
6059 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
6060 0, sense_len, sizeof(*scsi_cmd), timeout);
6061}
6062
6063/*
6064 * The reserve and release unit commands differ only by their opcodes.
6065 */
6066void
6067scsi_reserve_release_unit(struct ccb_scsiio *csio, u_int32_t retries,
6068 void (*cbfcnp)(struct cam_periph *, union ccb *),
6069 u_int8_t tag_action, int third_party,
6070 int third_party_id, u_int8_t sense_len,
6071 u_int32_t timeout, int reserve)
6072{
6073 struct scsi_reserve_release_unit *scsi_cmd;
6074
6075 scsi_cmd = (struct scsi_reserve_release_unit *)&csio->cdb_io.cdb_bytes;
6076 bzero(scsi_cmd, sizeof(*scsi_cmd));
6077
6078 if (reserve)
6079 scsi_cmd->opcode = RESERVE_UNIT;
6080 else
6081 scsi_cmd->opcode = RELEASE_UNIT;
6082
6083 if (third_party) {
6084 scsi_cmd->lun_thirdparty |= SRRU_3RD_PARTY;
6085 scsi_cmd->lun_thirdparty |=
6086 ((third_party_id << SRRU_3RD_SHAMT) & SRRU_3RD_MASK);
6087 }
6088
6089 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
6090 0, sense_len, sizeof(*scsi_cmd), timeout);
6091}
6092
6093void
6094scsi_erase(struct ccb_scsiio *csio, u_int32_t retries,
6095 void (*cbfcnp)(struct cam_periph *, union ccb *),
6096 u_int8_t tag_action, int immediate, int long_erase,
6097 u_int8_t sense_len, u_int32_t timeout)
6098{
6099 struct scsi_erase *scsi_cmd;
6100
6101 scsi_cmd = (struct scsi_erase *)&csio->cdb_io.cdb_bytes;
6102 bzero(scsi_cmd, sizeof(*scsi_cmd));
6103
6104 scsi_cmd->opcode = ERASE;
6105
6106 if (immediate)
6107 scsi_cmd->lun_imm_long |= SE_IMMED;
6108
6109 if (long_erase)
6110 scsi_cmd->lun_imm_long |= SE_LONG;
6111
6112 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action, NULL,
6113 0, sense_len, sizeof(*scsi_cmd), timeout);
6114}
6115
6116/*
6117 * Read Tape Position command.
6118 */
6119void
6120scsi_read_position(struct ccb_scsiio *csio, u_int32_t retries,
6121 void (*cbfcnp)(struct cam_periph *, union ccb *),
6122 u_int8_t tag_action, int hardsoft,
6123 struct scsi_tape_position_data *sbp,
6124 u_int8_t sense_len, u_int32_t timeout)
6125{
6126 struct scsi_tape_read_position *scmd;
6127
6128 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_IN, tag_action,
6129 (u_int8_t *)sbp, sizeof (*sbp), sense_len, sizeof(*scmd), timeout);
6130 scmd = (struct scsi_tape_read_position *)&csio->cdb_io.cdb_bytes;
6131 bzero(scmd, sizeof(*scmd));
6132 scmd->opcode = READ_POSITION;
6133 scmd->byte1 = hardsoft;
6134}
6135
6136/*
6137 * Read Tape Position command.
6138 */
6139void
6140scsi_read_position_10(struct ccb_scsiio *csio, u_int32_t retries,
6141 void (*cbfcnp)(struct cam_periph *, union ccb *),
6142 u_int8_t tag_action, int service_action,
6143 u_int8_t *data_ptr, u_int32_t length,
6144 u_int32_t sense_len, u_int32_t timeout)
6145{
6146 struct scsi_tape_read_position *scmd;
6147
6148 cam_fill_csio(csio,
6149 retries,
6150 cbfcnp,
6151 /*flags*/CAM_DIR_IN,
6152 tag_action,
6153 /*data_ptr*/data_ptr,
6154 /*dxfer_len*/length,
6155 sense_len,
6156 sizeof(*scmd),
6157 timeout);
6158
6159 scmd = (struct scsi_tape_read_position *)&csio->cdb_io.cdb_bytes;
6160 bzero(scmd, sizeof(*scmd));
6161 scmd->opcode = READ_POSITION;
6162 scmd->byte1 = service_action;
6163 /*
6164 * The length is only currently set (as of SSC4r03) if the extended
6165 * form is specified. The other forms have fixed lengths.
6166 */
6167 if (service_action == SA_RPOS_EXTENDED_FORM)
6168 scsi_ulto2b(length, scmd->length);
6169}
6170
6171/*
6172 * Set Tape Position command.
6173 */
6174void
6175scsi_set_position(struct ccb_scsiio *csio, u_int32_t retries,
6176 void (*cbfcnp)(struct cam_periph *, union ccb *),
6177 u_int8_t tag_action, int hardsoft, u_int32_t blkno,
6178 u_int8_t sense_len, u_int32_t timeout)
6179{
6180 struct scsi_tape_locate *scmd;
6181
6182 cam_fill_csio(csio, retries, cbfcnp, CAM_DIR_NONE, tag_action,
6183 (u_int8_t *)NULL, 0, sense_len, sizeof(*scmd), timeout);
6184 scmd = (struct scsi_tape_locate *)&csio->cdb_io.cdb_bytes;
6185 bzero(scmd, sizeof(*scmd));
6186 scmd->opcode = LOCATE;
6187 if (hardsoft)
6188 scmd->byte1 |= SA_SPOS_BT;
6189 scsi_ulto4b(blkno, scmd->blkaddr);
6190}
6191
6192/*
6193 * XXX KDM figure out how to make a compatibility function.
6194 */
6195void
6196scsi_locate_10(struct ccb_scsiio *csio, u_int32_t retries,
6197 void (*cbfcnp)(struct cam_periph *, union ccb *),
6198 u_int8_t tag_action, int immed, int cp, int hard,
6199 int64_t partition, u_int32_t block_address,
6200 int sense_len, u_int32_t timeout)
6201{
6202 struct scsi_tape_locate *scmd;
6203
6204 cam_fill_csio(csio,
6205 retries,
6206 cbfcnp,
6208 tag_action,
6209 /*data_ptr*/ NULL,
6210 /*dxfer_len*/ 0,
6211 sense_len,
6212 sizeof(*scmd),
6213 timeout);
6214 scmd = (struct scsi_tape_locate *)&csio->cdb_io.cdb_bytes;
6215 bzero(scmd, sizeof(*scmd));
6216 scmd->opcode = LOCATE;
6217 if (immed)
6218 scmd->byte1 |= SA_SPOS_IMMED;
6219 if (cp)
6220 scmd->byte1 |= SA_SPOS_CP;
6221 if (hard)
6222 scmd->byte1 |= SA_SPOS_BT;
6223 scsi_ulto4b(block_address, scmd->blkaddr);
6224 scmd->partition = partition;
6225}
6226
6227void
6228scsi_locate_16(struct ccb_scsiio *csio, u_int32_t retries,
6229 void (*cbfcnp)(struct cam_periph *, union ccb *),
6230 u_int8_t tag_action, int immed, int cp, u_int8_t dest_type,
6231 int bam, int64_t partition, u_int64_t logical_id,
6232 int sense_len, u_int32_t timeout)
6233{
6234
6235 struct scsi_locate_16 *scsi_cmd;
6236
6237 cam_fill_csio(csio,
6238 retries,
6239 cbfcnp,
6240 /*flags*/CAM_DIR_NONE,
6241 tag_action,
6242 /*data_ptr*/NULL,
6243 /*dxfer_len*/0,
6244 sense_len,
6245 sizeof(*scsi_cmd),
6246 timeout);
6247
6248 scsi_cmd = (struct scsi_locate_16 *)&csio->cdb_io.cdb_bytes;
6249 bzero(scsi_cmd, sizeof(*scsi_cmd));
6250 scsi_cmd->opcode = LOCATE_16;
6251 if (immed)
6252 scsi_cmd->byte1 |= SA_LC_IMMEDIATE;
6253 if (cp)
6254 scsi_cmd->byte1 |= SA_LC_CP;
6255 scsi_cmd->byte1 |= (dest_type << SA_LC_DEST_TYPE_SHIFT);
6256
6257 scsi_cmd->byte2 |= bam;
6258 scsi_cmd->partition = partition;
6260}
6261
6262void
6263scsi_report_density_support(struct ccb_scsiio *csio, u_int32_t retries,
6264 void (*cbfcnp)(struct cam_periph *, union ccb *),
6265 u_int8_t tag_action, int media, int medium_type,
6266 u_int8_t *data_ptr, u_int32_t length,
6267 u_int32_t sense_len, u_int32_t timeout)
6268{
6269 struct scsi_report_density_support *scsi_cmd;
6270
6271 scsi_cmd =(struct scsi_report_density_support *)&csio->cdb_io.cdb_bytes;
6272 bzero(scsi_cmd, sizeof(*scsi_cmd));
6273
6274 scsi_cmd->opcode = REPORT_DENSITY_SUPPORT;
6275 if (media != 0)
6276 scsi_cmd->byte1 |= SRDS_MEDIA;
6277 if (medium_type != 0)
6278 scsi_cmd->byte1 |= SRDS_MEDIUM_TYPE;
6279
6280 scsi_ulto2b(length, scsi_cmd->length);
6281
6282 cam_fill_csio(csio,
6283 retries,
6284 cbfcnp,
6285 /*flags*/CAM_DIR_IN,
6286 tag_action,
6287 /*data_ptr*/data_ptr,
6288 /*dxfer_len*/length,
6289 sense_len,
6290 sizeof(*scsi_cmd),
6291 timeout);
6292}
6293
6294void
6295scsi_set_capacity(struct ccb_scsiio *csio, u_int32_t retries,
6296 void (*cbfcnp)(struct cam_periph *, union ccb *),
6297 u_int8_t tag_action, int byte1, u_int32_t proportion,
6298 u_int32_t sense_len, u_int32_t timeout)
6299{
6300 struct scsi_set_capacity *scsi_cmd;
6301
6302 scsi_cmd = (struct scsi_set_capacity *)&csio->cdb_io.cdb_bytes;
6303 bzero(scsi_cmd, sizeof(*scsi_cmd));
6304
6305 scsi_cmd->opcode = SET_CAPACITY;
6306
6307 scsi_cmd->byte1 = byte1;
6308 scsi_ulto2b(proportion, scsi_cmd->cap_proportion);
6309
6310 cam_fill_csio(csio,
6311 retries,
6312 cbfcnp,
6313 /*flags*/CAM_DIR_NONE,
6314 tag_action,
6315 /*data_ptr*/NULL,
6316 /*dxfer_len*/0,
6317 sense_len,
6318 sizeof(*scsi_cmd),
6319 timeout);
6320}
6321
6322void
6323scsi_format_medium(struct ccb_scsiio *csio, u_int32_t retries,
6324 void (*cbfcnp)(struct cam_periph *, union ccb *),
6325 u_int8_t tag_action, int byte1, int byte2,
6326 u_int8_t *data_ptr, u_int32_t dxfer_len,
6327 u_int32_t sense_len, u_int32_t timeout)
6328{
6329 struct scsi_format_medium *scsi_cmd;
6330
6331 scsi_cmd = (struct scsi_format_medium*)&csio->cdb_io.cdb_bytes;
6332 bzero(scsi_cmd, sizeof(*scsi_cmd));
6333
6334 scsi_cmd->opcode = FORMAT_MEDIUM;
6335
6336 scsi_cmd->byte1 = byte1;
6337 scsi_cmd->byte2 = byte2;
6338
6339 scsi_ulto2b(dxfer_len, scsi_cmd->length);
6340
6341 cam_fill_csio(csio,
6342 retries,
6343 cbfcnp,
6344 /*flags*/(dxfer_len > 0) ? CAM_DIR_OUT : CAM_DIR_NONE,
6345 tag_action,
6346 /*data_ptr*/ data_ptr,
6347 /*dxfer_len*/ dxfer_len,
6348 sense_len,
6349 sizeof(*scsi_cmd),
6350 timeout);
6351}
6352
6353void
6354scsi_allow_overwrite(struct ccb_scsiio *csio, u_int32_t retries,
6355 void (*cbfcnp)(struct cam_periph *, union ccb *),
6356 u_int8_t tag_action, int allow_overwrite, int partition,
6357 u_int64_t logical_id, u_int32_t sense_len, u_int32_t timeout)
6358{
6359 struct scsi_allow_overwrite *scsi_cmd;
6360
6361 scsi_cmd = (struct scsi_allow_overwrite *)&csio->cdb_io.cdb_bytes;
6362 bzero(scsi_cmd, sizeof(*scsi_cmd));
6363
6364 scsi_cmd->opcode = ALLOW_OVERWRITE;
6365
6366 scsi_cmd->allow_overwrite = allow_overwrite;
6367 scsi_cmd->partition = partition;
6369
6370 cam_fill_csio(csio,
6371 retries,
6372 cbfcnp,
6374 tag_action,
6375 /*data_ptr*/ NULL,
6376 /*dxfer_len*/ 0,
6377 sense_len,
6378 sizeof(*scsi_cmd),
6379 timeout);
6380}
caddr_t cam_quirkmatch(caddr_t target, caddr_t quirk_table, int num_entries, int entry_size, cam_quirkmatch_t *comp_func)
Definition: cam.c:281
void cam_strvis(u_int8_t *dst, const u_int8_t *src, int srclen, int dstlen)
Definition: cam.c:124
@ SF_QUIET_IR
Definition: cam.h:124
@ SF_RETRY_UA
Definition: cam.h:122
@ SF_NO_PRINT
Definition: cam.h:123
cam_flags
Definition: cam.h:115
@ CAM_RETRY_SELTO
Definition: cam.h:118
#define CAM_PRIORITY_NORMAL
Definition: cam.h:92
cam_status
Definition: cam.h:132
@ CAM_SCSI_BUS_RESET
Definition: cam.h:176
@ CAM_REQ_INPROG
Definition: cam.h:134
@ CAM_REQ_CMP
Definition: cam.h:137
@ CAM_REQ_CMP_ERR
Definition: cam.h:146
@ CAM_STATUS_MASK
Definition: cam.h:302
@ CAM_SCSI_STATUS_ERROR
Definition: cam.h:170
@ CAM_BDR_SENT
Definition: cam.h:203
@ CAM_DEV_QFRZN
Definition: cam.h:287
#define CAM_MAX_CDBLEN
Definition: cam.h:60
#define CAM_PRIORITY_DEV
Definition: cam.h:90
@ AC_FOUND_DEVICE
Definition: cam_ccb.h:874
@ AC_LOST_DEVICE
Definition: cam_ccb.h:873
@ PROTO_SCSI
Definition: cam_ccb.h:279
@ PIM_UNMAPPED
Definition: cam_ccb.h:625
@ CAM_DIR_IN
Definition: cam_ccb.h:79
@ CAM_DIR_NONE
Definition: cam_ccb.h:81
@ CAM_DATA_BIO
Definition: cam_ccb.h:87
@ CAM_DIR_OUT
Definition: cam_ccb.h:80
#define CDAI_TYPE_EXT_INQ
Definition: cam_ccb.h:1319
static __BEGIN_DECLS __inline void cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int32_t flags, u_int8_t tag_action, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int8_t cdb_len, u_int32_t timeout)
Definition: cam_ccb.h:1389
@ XPT_DEV_ADVINFO
Definition: cam_ccb.h:166
@ XPT_GDEV_TYPE
Definition: cam_ccb.h:143
#define XPORT_DEVSTAT_TYPE(t)
Definition: cam_ccb.h:310
#define CDAI_FLAG_NONE
Definition: cam_ccb.h:1311
@ CAM_DEBUG_TRACE
Definition: cam_debug.h:41
@ CAM_DEBUG_INFO
Definition: cam_debug.h:40
#define CAM_DEBUG(path, flag, printfargs)
Definition: cam_debug.h:93
#define CAM_DEBUGGED(path, flag)
Definition: cam_debug.h:87
void cam_periph_release_locked(struct cam_periph *periph)
Definition: cam_periph.c:453
u_int32_t cam_release_devq(struct cam_path *path, u_int32_t relsim_flags, u_int32_t openings, u_int32_t arg, int getcount_only)
Definition: cam_periph.c:1342
int cam_periph_acquire(struct cam_periph *periph)
Definition: cam_periph.c:413
void cam_periph_async(struct cam_periph *periph, u_int32_t code, struct cam_path *path, void *arg)
Definition: cam_periph.c:1471
void cam_periph_release(struct cam_periph *periph)
Definition: cam_periph.c:465
void cam_periph_unhold(struct cam_periph *periph)
Definition: cam_periph.c:519
int cam_periph_hold(struct cam_periph *periph, int priority)
Definition: cam_periph.c:486
int cam_periph_runccb(union ccb *ccb, int(*error_routine)(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags), cam_flags camflags, u_int32_t sense_flags, struct devstat *ds)
Definition: cam_periph.c:1207
int cam_periph_error(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags)
Definition: cam_periph.c:1864
int cam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr, int(*error_routine)(union ccb *ccb, cam_flags camflags, u_int32_t sense_flags))
Definition: cam_periph.c:1109
cam_status cam_periph_alloc(periph_ctor_t *periph_ctor, periph_oninv_t *periph_oninvalidate, periph_dtor_t *periph_dtor, periph_start_t *periph_start, char *name, cam_periph_type type, struct cam_path *path, ac_callback_t *ac_callback, ac_code code, void *arg)
Definition: cam_periph.c:197
cam_status periph_ctor_t(struct cam_periph *periph, void *arg)
Definition: cam_periph.h:115
#define CAM_PERIPH_INVALID
Definition: cam_periph.h:133
void periph_oninv_t(struct cam_periph *periph)
Definition: cam_periph.h:117
#define cam_periph_lock(periph)
Definition: cam_periph.h:224
union ccb * cam_periph_getccb(struct cam_periph *periph, u_int32_t priority)
Definition: cam_xpt.c:4695
#define cam_periph_unlock(periph)
Definition: cam_periph.h:227
static __inline struct mtx * cam_periph_mtx(struct cam_periph *periph)
Definition: cam_periph.h:213
#define CAM_PERIPH_LOCKED
Definition: cam_periph.h:131
void periph_dtor_t(struct cam_periph *periph)
Definition: cam_periph.h:118
void periph_start_t(struct cam_periph *periph, union ccb *start_ccb)
Definition: cam_periph.h:113
@ CAM_PERIPH_BIO
Definition: cam_periph.h:104
void() periph_init_t(void)
Definition: cam_periph.h:85
void xpt_print_path(struct cam_path *path)
Definition: cam_xpt.c:3786
void xpt_schedule(struct cam_periph *periph, u_int32_t new_priority)
Definition: cam_xpt.c:3243
void xpt_print(struct cam_path *path, const char *fmt,...)
Definition: cam_xpt.c:3814
void xpt_announce_periph(struct cam_periph *periph, char *announce_string)
Definition: cam_xpt.c:1049
void xpt_setup_ccb(struct ccb_hdr *ccb_h, struct cam_path *path, u_int32_t priority)
Definition: cam_xpt.c:3520
void xpt_action(union ccb *start_ccb)
Definition: cam_xpt.c:2601
cam_status xpt_register_async(int event, ac_callback_t *cbfunc, void *cbarg, struct cam_path *path)
Definition: cam_xpt.c:5213
struct cam_periph * xpt_path_periph(struct cam_path *path)
Definition: cam_xpt.c:3911
void xpt_release_ccb(union ccb *free_ccb)
Definition: cam_xpt.c:3924
void xpt_announce_quirks(struct cam_periph *periph, int quirks, char *bit_string)
Definition: cam_xpt.c:1151
static void xpt_path_inq(struct ccb_pathinq *cpi, struct cam_path *path)
Definition: cam_xpt.h:156
union ccb * ccb
Definition: mmc_sim_if.m:53
void scsi_mode_sense(struct ccb_scsiio *csio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, int dbd, uint8_t pc, uint8_t page, uint8_t *param_buf, uint32_t param_len, uint8_t sense_len, uint32_t timeout)
Definition: scsi_all.c:7625
void scsi_report_supported_opcodes(struct ccb_scsiio *csio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, int options, int req_opcode, int req_service_action, uint8_t *data_ptr, uint32_t dxfer_len, int sense_len, int timeout)
Definition: scsi_all.c:9127
void scsi_mode_select_len(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int scsi_page_fmt, int save_pages, u_int8_t *param_buf, u_int32_t param_len, int minimum_cmd_size, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_all.c:7716
void scsi_sense_print(struct ccb_scsiio *csio)
Definition: scsi_all.c:5161
void scsi_mode_select(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int scsi_page_fmt, int save_pages, u_int8_t *param_buf, u_int32_t param_len, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_all.c:7704
void scsi_prevent(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, u_int8_t action, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_all.c:7845
int scsi_inquiry_match(caddr_t inqbuffer, caddr_t table_entry)
Definition: scsi_all.c:9163
void scsi_extract_sense_len(struct scsi_sense_data *sense_data, u_int sense_len, int *error_code, int *sense_key, int *asc, int *ascq, int show_errors)
Definition: scsi_all.c:5245
void scsi_mode_sense_len(struct ccb_scsiio *csio, uint32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), uint8_t tag_action, int dbd, uint8_t pc, uint8_t page, uint8_t *param_buf, uint32_t param_len, int minimum_cmd_size, uint8_t sense_len, uint32_t timeout)
Definition: scsi_all.c:7636
int scsi_get_sense_info(struct scsi_sense_data *sense_data, u_int sense_len, uint8_t info_type, uint64_t *info, int64_t *signed_info)
Definition: scsi_all.c:4061
void scsi_test_unit_ready(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_all.c:7547
int scsi_get_stream_info(struct scsi_sense_data *sense_data, u_int sense_len, struct scsi_inquiry_data *inq_data, uint8_t *stream_bits)
Definition: scsi_all.c:4306
#define SCSI_REV_CCS
Definition: scsi_all.h:2221
#define SSD_KEY_BLANK_CHECK
Definition: scsi_all.h:3284
#define PR_ALLOW
Definition: scsi_all.h:946
#define SCSI_RW_BIO
Definition: scsi_all.h:4234
#define MODE_SENSE_6
Definition: scsi_all.h:2087
#define RSO_CTDP
Definition: scsi_all.h:1540
#define RSO_RCTD
Definition: scsi_all.h:1510
static __inline uint32_t scsi_3btoul(const uint8_t *bytes)
Definition: scsi_all.h:4425
static __inline uint64_t scsi_8btou64(const uint8_t *bytes)
Definition: scsi_all.h:4459
#define SSD_FILEMARK
Definition: scsi_all.h:3295
static __inline uint32_t scsi_2btoul(const uint8_t *bytes)
Definition: scsi_all.h:4415
#define SSD_DESC_INFO
Definition: scsi_all.h:3362
#define SIP_MEDIA_REMOVABLE
Definition: scsi_all.h:3706
#define SMS_PAGE_CTRL_CHANGEABLE
Definition: scsi_all.h:205
#define SCSI_REV_SPC
Definition: scsi_all.h:2223
#define SVPD_EID_SA_SPT_LBP
Definition: scsi_all.h:2528
#define SCSI_RW_READ
Definition: scsi_all.h:4231
static __inline void scsi_ulto2b(u_int32_t val, u_int8_t *bytes)
Definition: scsi_all.h:4374
#define MODE_SELECT_10
Definition: scsi_all.h:2110
#define MODE_SELECT_6
Definition: scsi_all.h:2086
static __inline uint32_t scsi_4btoul(const uint8_t *bytes)
Definition: scsi_all.h:4447
#define SSD_KEY_VOLUME_OVERFLOW
Definition: scsi_all.h:3289
#define SID_QUAL_LU_CONNECTED
Definition: scsi_all.h:2208
#define SMS_PAGE_CTRL_CURRENT
Definition: scsi_all.h:204
#define PREVENT_ALLOW
Definition: scsi_all.h:2094
#define SCSI_DEFAULT_DENSITY
Definition: scsi_all.h:3685
#define SSD_ILI
Definition: scsi_all.h:3293
#define SSD_EOM
Definition: scsi_all.h:3294
#define SMS_CONTROL_MODE_PAGE
Definition: scsi_all.h:199
#define MODE_SENSE_10
Definition: scsi_all.h:2113
#define SMS_VENDOR_SPECIFIC_PAGE
Definition: scsi_all.h:193
static __inline void scsi_ulto4b(u_int32_t val, u_int8_t *bytes)
Definition: scsi_all.h:4391
#define SPC3_SID_PROTECT
Definition: scsi_all.h:2241
static __inline void scsi_u64to8b(u_int64_t val, u_int8_t *bytes)
Definition: scsi_all.h:4401
#define SCSI_RW_DIRMASK
Definition: scsi_all.h:4233
#define SID_TYPE(inq_data)
Definition: scsi_all.h:2206
#define SCSI_RW_WRITE
Definition: scsi_all.h:4232
#define TEST_UNIT_READY
Definition: scsi_all.h:2081
#define SCSI_REV_SPC4
Definition: scsi_all.h:2226
#define T_SEQUENTIAL
Definition: scsi_all.h:2171
#define PR_PREVENT
Definition: scsi_all.h:945
#define SID_ANSI_REV(inq_data)
Definition: scsi_all.h:2219
#define SID_QUAL(inq_data)
Definition: scsi_all.h:2207
static __inline void scsi_ulto3b(u_int32_t val, u_int8_t *bytes)
Definition: scsi_all.h:4382
#define SCSI_SAME_DENSITY
Definition: scsi_all.h:3686
#define SSD_FULL_SIZE
Definition: scsi_all.h:3251
#define SSD_KEY_NO_SENSE
Definition: scsi_all.h:3276
#define MSG_SIMPLE_Q_TAG
Definition: scsi_message.h:35
void scsi_read_position(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int hardsoft, struct scsi_tape_position_data *sbp, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6120
static int saerase(struct cam_periph *periph, int longerase)
Definition: scsi_sa.c:5462
static MALLOC_DEFINE(M_SCSISA, "SCSI sa", "SCSI sequential access buffers")
static int sasetparams(struct cam_periph *periph, sa_params params_to_set, u_int32_t blocksize, u_int8_t density, u_int32_t comp_algorithm, u_int32_t sense_flags)
Definition: scsi_sa.c:4390
static struct sa_quirk_entry sa_quirk_table[]
Definition: scsi_sa.c:486
static void saloadtotunables(struct sa_softc *softc)
Definition: scsi_sa.c:2359
static int sacheckeod(struct cam_periph *periph)
Definition: scsi_sa.c:3650
#define SA_NOT_CTLDEV
Definition: scsi_sa.c:258
static d_strategy_t sastrategy
Definition: scsi_sa.c:592
sa_quirks
Definition: scsi_sa.c:230
@ SA_QUIRK_NODREAD
Definition: scsi_sa.c:237
@ SA_QUIRK_2FM
Definition: scsi_sa.c:235
@ SA_QUIRK_1FM
Definition: scsi_sa.c:236
@ SA_QUIRK_NONE
Definition: scsi_sa.c:231
@ SA_QUIRK_NOCOMP
Definition: scsi_sa.c:232
@ SA_QUIRK_VARIABLE
Definition: scsi_sa.c:234
@ SA_QUIRK_NO_MODESEL
Definition: scsi_sa.c:238
@ SA_QUIRK_FIXED
Definition: scsi_sa.c:233
@ SA_QUIRK_NO_CPAGE
Definition: scsi_sa.c:239
@ SA_QUIRK_NO_LONG_POS
Definition: scsi_sa.c:240
#define D_TAPE
Definition: scsi_sa.c:698
#define SASBADDVARSTRDESC(sb, indent, data, fmt, name, maxlen, desc)
Definition: scsi_sa.c:308
void scsi_allow_overwrite(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int allow_overwrite, int partition, u_int64_t logical_id, u_int32_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6354
static int saparamget(struct sa_softc *softc, struct sbuf *sb)
Definition: scsi_sa.c:4891
static int sawritefilemarks(struct cam_periph *periph, int nmarks, int setmarks, int immed)
Definition: scsi_sa.c:5053
static SYSCTL_NODE(_kern_cam, OID_AUTO, sa, CTLFLAG_RD|CTLFLAG_MPSAFE, 0, "CAM Sequential Access Tape Driver")
#define SASBENDNODE(sb, indent, name)
Definition: scsi_sa.c:323
static int sasetpos(struct cam_periph *periph, int, struct mtlocate *)
Definition: scsi_sa.c:5256
static void safilldenstypesb(struct sbuf *sb, int *indent, uint8_t *buf, int buf_len, int is_density)
Definition: scsi_sa.c:5566
struct sa_param_ent sa_param_table[]
static int sasetprotents(struct cam_periph *periph, struct mtparamset *ps, int num_params)
Definition: scsi_sa.c:1244
void scsi_read_block_limits(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, struct scsi_read_block_limits_data *rlimit_buf, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:5934
void scsi_space(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, scsi_space_code code, u_int32_t count, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6023
static int saretension(struct cam_periph *periph)
Definition: scsi_sa.c:5371
static d_ioctl_t saioctl
Definition: scsi_sa.c:593
#define REP_DENSITY_TIMEOUT
Definition: scsi_sa.c:97
static d_close_t saclose
Definition: scsi_sa.c:591
#define UNUSED_PARAMETER(x)
Definition: scsi_sa.c:104
void scsi_rewind(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int immediate, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6005
#define REWIND_TIMEOUT
Definition: scsi_sa.c:94
static void saasync(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg)
Definition: scsi_sa.c:2292
sa_timeout_types
Definition: scsi_sa.c:158
@ SA_TIMEOUT_READ_BLOCK_LIMITS
Definition: scsi_sa.c:166
@ SA_TIMEOUT_READ
Definition: scsi_sa.c:165
@ SA_TIMEOUT_MODE_SELECT
Definition: scsi_sa.c:162
@ SA_TIMEOUT_TYPE_MAX
Definition: scsi_sa.c:175
@ SA_TIMEOUT_SPACE
Definition: scsi_sa.c:171
@ SA_TIMEOUT_MODE_SENSE
Definition: scsi_sa.c:163
@ SA_TIMEOUT_RESERVE
Definition: scsi_sa.c:169
@ SA_TIMEOUT_WRITE
Definition: scsi_sa.c:173
@ SA_TIMEOUT_PREVENT
Definition: scsi_sa.c:164
@ SA_TIMEOUT_LOCATE
Definition: scsi_sa.c:161
@ SA_TIMEOUT_TUR
Definition: scsi_sa.c:172
@ SA_TIMEOUT_ERASE
Definition: scsi_sa.c:159
@ SA_TIMEOUT_REP_DENSITY
Definition: scsi_sa.c:168
@ SA_TIMEOUT_READ_POSITION
Definition: scsi_sa.c:167
@ SA_TIMEOUT_LOAD
Definition: scsi_sa.c:160
@ SA_TIMEOUT_REWIND
Definition: scsi_sa.c:170
@ SA_TIMEOUT_WRITE_FILEMARKS
Definition: scsi_sa.c:174
#define SAFILLDENSSBSTR(dens_data, sb, indent, field, desc_remain, len_to_go, cur_offset, desc)
Definition: scsi_sa.c:5541
static void saloadtimeouts(struct sa_softc *softc, union ccb *ccb)
Definition: scsi_sa.c:5781
static periph_init_t sainit
Definition: scsi_sa.c:594
static int sa_allow_io_split
Definition: scsi_sa.c:675
#define SCSIOP_TIMEOUT
Definition: scsi_sa.c:91
#define SA_CTLDEV
Definition: scsi_sa.c:259
static int sarewind(struct cam_periph *periph)
Definition: scsi_sa.c:4947
static void sadone(struct cam_periph *periph, union ccb *start_ccb)
Definition: scsi_sa.c:3017
void scsi_read_position_10(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int service_action, u_int8_t *data_ptr, u_int32_t length, u_int32_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6140
#define SA_ATYPE_R
Definition: scsi_sa.c:261
#define SASBADDNODENUM(sb, indent, name, num)
Definition: scsi_sa.c:317
static int sasetsili(struct cam_periph *periph, struct mtparamset *ps, int num_params)
Definition: scsi_sa.c:1076
#define SA_IS_CTRL(z)
Definition: scsi_sa.c:256
#define SAMINOR(ctl, access)
Definition: scsi_sa.c:266
#define SAMODE(z)
Definition: scsi_sa.c:255
#define SA_DEFAULT_IO_SPLIT
Definition: scsi_sa.c:672
void scsi_write_filemarks(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int immediate, int setmark, u_int32_t num_marks, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6041
static int saextget(struct cdev *dev, struct cam_periph *periph, struct sbuf *sb, struct mtextget *g)
Definition: scsi_sa.c:4705
#define QFRLS(ccb)
Definition: scsi_sa.c:107
static d_open_t saopen
Definition: scsi_sa.c:590
SYSCTL_INT(_kern_cam_sa, OID_AUTO, allow_io_split, CTLFLAG_RDTUN, &sa_allow_io_split, 0, "Default I/O split value")
void scsi_locate_16(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int immed, int cp, u_int8_t dest_type, int bam, int64_t partition, u_int64_t logical_id, int sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6228
void scsi_set_capacity(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int byte1, u_int32_t proportion, u_int32_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6295
void scsi_set_position(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int hardsoft, u_int32_t blkno, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6175
static int sagetparams_common(struct cdev *dev, struct cam_periph *periph)
Definition: scsi_sa.c:1510
void scsi_load_unload(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int immediate, int eot, int reten, int load, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:5980
void scsi_report_density_support(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int media, int medium_type, u_int8_t *data_ptr, u_int32_t length, u_int32_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6263
static int sasetprot(struct cam_periph *periph, struct sa_prot_state *new_prot)
Definition: scsi_sa.c:4206
struct sa_prot_map sa_prot_table[]
#define PENDING_MOUNT_CHECK(softc, periph, dev)
Definition: scsi_sa.c:1549
sa_flags
Definition: scsi_sa.c:127
@ SA_FLAG_SCTX_INIT
Definition: scsi_sa.c:148
@ SA_FLAG_TAPE_MOUNTED
Definition: scsi_sa.c:131
@ SA_FLAG_OPEN
Definition: scsi_sa.c:128
@ SA_FLAG_COMP_UNSUPP
Definition: scsi_sa.c:142
@ SA_FLAG_COMP_ENABLED
Definition: scsi_sa.c:140
@ SA_FLAG_PROTECT_SUPP
Definition: scsi_sa.c:144
@ SA_FLAG_TAPE_WRITTEN
Definition: scsi_sa.c:133
@ SA_FLAG_EIO_PENDING
Definition: scsi_sa.c:135
@ SA_FLAG_RSOC_TO_TRY
Definition: scsi_sa.c:149
@ SA_FLAG_COMP_SUPP
Definition: scsi_sa.c:141
@ SA_FLAG_TAPE_FROZEN
Definition: scsi_sa.c:143
@ SA_FLAG_INVALID
Definition: scsi_sa.c:139
@ SA_FLAG_TAPE_LOCKED
Definition: scsi_sa.c:130
@ SA_FLAG_EOF_PENDING
Definition: scsi_sa.c:136
@ SA_FLAG_ERR_PENDING
Definition: scsi_sa.c:137
@ SA_FLAG_TAPE_WP
Definition: scsi_sa.c:132
@ SA_FLAG_COMPRESSION
Definition: scsi_sa.c:146
@ SA_FLAG_FIXED
Definition: scsi_sa.c:129
@ SA_FLAG_EOM_PENDING
Definition: scsi_sa.c:134
static struct sa_prot_map * safindprotent(char *name, struct sa_prot_map *table, int table_ents)
Definition: scsi_sa.c:1221
static int sagetparams(struct cam_periph *periph, sa_params params_to_get, u_int32_t *blocksize, u_int8_t *density, u_int32_t *numblocks, int *buff_mode, u_int8_t *write_protect, u_int8_t *speed, int *comp_supported, int *comp_enabled, u_int32_t *comp_algorithm, sa_comp_t *comp_page, struct scsi_control_data_prot_subpage *prot_page, int dp_size, int prot_changeable)
Definition: scsi_sa.c:3875
void scsi_format_medium(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int byte1, int byte2, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int32_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6323
static struct sa_timeout_desc sa_default_timeouts[SA_TIMEOUT_TYPE_MAX]
#define SASBADDUINTDESC(sb, indent, data, fmt, name, desc)
Definition: scsi_sa.c:293
void scsi_reserve_release_unit(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int third_party, int third_party_id, u_int8_t sense_len, u_int32_t timeout, int reserve)
Definition: scsi_sa.c:6067
#define SASBADDVARSTR(sb, indent, data, fmt, name, maxlen)
Definition: scsi_sa.c:305
__FBSDID("$FreeBSD$")
static void sasetupdev(struct sa_softc *softc, struct cdev *dev)
Definition: scsi_sa.c:2338
#define SA_NUM_PROT_ENTS
Definition: scsi_sa.c:372
#define ERASE_TIMEOUT
Definition: scsi_sa.c:95
static int sardpos(struct cam_periph *periph, int, u_int32_t *)
Definition: scsi_sa.c:5212
static void safilldensitysb(struct sa_softc *softc, int *indent, struct sbuf *sb)
Definition: scsi_sa.c:5736
static periph_oninv_t saoninvalidate
Definition: scsi_sa.c:596
static int saseteotwarn(struct cam_periph *periph, struct mtparamset *ps, int num_params)
Definition: scsi_sa.c:1137
static struct sa_param_ent * safindparament(struct mtparamset *ps)
Definition: scsi_sa.c:1373
sa_state
Definition: scsi_sa.c:117
@ SA_STATE_NORMAL
Definition: scsi_sa.c:118
@ SA_STATE_PROBE
Definition: scsi_sa.c:118
@ SA_STATE_ABNORMAL
Definition: scsi_sa.c:118
static void sadevgonecb(void *arg)
Definition: scsi_sa.c:2193
sa_mode
Definition: scsi_sa.c:152
@ SA_MODE_NOREWIND
Definition: scsi_sa.c:154
@ SA_MODE_OFFLINE
Definition: scsi_sa.c:155
@ SA_MODE_REWIND
Definition: scsi_sa.c:153
#define IO_TIMEOUT
Definition: scsi_sa.c:93
static void safillprot(struct sa_softc *softc, int *indent, struct sbuf *sb)
Definition: scsi_sa.c:1169
#define SA_DENSITY_TYPES
Definition: scsi_sa.c:328
static void saprevent(struct cam_periph *periph, int action)
Definition: scsi_sa.c:4908
static int saparamsetlist(struct cam_periph *periph, struct mtsetlist *list, int need_copy)
Definition: scsi_sa.c:1402
PERIPHDRIVER_DECLARE(sa, sadriver)
#define SASBADDUINT(sb, indent, data, fmt, name)
Definition: scsi_sa.c:289
static int sagetpos(struct cam_periph *periph)
Definition: scsi_sa.c:5115
static void sasysctlinit(void *context, int pending)
Definition: scsi_sa.c:2387
static int saloadunload(struct cam_periph *periph, int load)
Definition: scsi_sa.c:5431
#define SA_ATYPE_ER
Definition: scsi_sa.c:263
#define SPACE_TIMEOUT
Definition: scsi_sa.c:96
void scsi_erase(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int immediate, int long_erase, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6094
static periph_ctor_t saregister
Definition: scsi_sa.c:595
static void sapopulateprots(struct sa_prot_state *cur_state, struct sa_prot_map *new_table, int table_ents)
Definition: scsi_sa.c:1203
void scsi_locate_10(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int immed, int cp, int hard, int64_t partition, u_int32_t block_address, int sense_len, u_int32_t timeout)
Definition: scsi_sa.c:6196
#define SASBADDNODE(sb, indent, name)
Definition: scsi_sa.c:311
#define SA_POSITION_UPDATED
Definition: scsi_sa.c:125
static periph_start_t sastart
Definition: scsi_sa.c:598
sa_param_type
Definition: scsi_sa.c:1356
@ SA_PARAM_TYPE_ENTRY
Definition: scsi_sa.c:1357
@ SA_PARAM_TYPE_NODE
Definition: scsi_sa.c:1358
static struct cdevsw sa_cdevsw
Definition: scsi_sa.c:701
static int saspace(struct cam_periph *periph, int count, scsi_space_code code)
Definition: scsi_sa.c:4978
void scsi_sa_read_write(struct ccb_scsiio *csio, u_int32_t retries, void(*cbfcnp)(struct cam_periph *, union ccb *), u_int8_t tag_action, int readop, int sli, int fixed, u_int32_t length, u_int8_t *data_ptr, u_int32_t dxfer_len, u_int8_t sense_len, u_int32_t timeout)
Definition: scsi_sa.c:5952
#define SASBADDINTDESC(sb, indent, data, fmt, name, desc)
Definition: scsi_sa.c:285
#define SA_QUIRK_BIT_STRING
Definition: scsi_sa.c:243
static int samount(struct cam_periph *, int, struct cdev *)
Definition: scsi_sa.c:3169
static periph_dtor_t sacleanup
Definition: scsi_sa.c:597
#define SAFILLDENSSB(dens_data, sb, indent, field, desc_remain, len_to_go, cur_offset, desc)
Definition: scsi_sa.c:5497
static struct periph_driver sadriver
Definition: scsi_sa.c:688
sa_params
Definition: scsi_sa.c:216
@ SA_PARAM_ALL
Definition: scsi_sa.c:227
@ SA_PARAM_LBP
Definition: scsi_sa.c:226
@ SA_PARAM_NONE
Definition: scsi_sa.c:217
@ SA_PARAM_COMPRESSION
Definition: scsi_sa.c:220
@ SA_PARAM_DENSITY_EXT
Definition: scsi_sa.c:225
@ SA_PARAM_BUFF_MODE
Definition: scsi_sa.c:221
@ SA_PARAM_DENSITY
Definition: scsi_sa.c:219
@ SA_PARAM_NUMBLOCKS
Definition: scsi_sa.c:222
@ SA_PARAM_BLOCKSIZE
Definition: scsi_sa.c:218
@ SA_PARAM_WP
Definition: scsi_sa.c:223
@ SA_PARAM_SPEED
Definition: scsi_sa.c:224
static int sareservereleaseunit(struct cam_periph *periph, int reserve)
Definition: scsi_sa.c:5400
static int saerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
Definition: scsi_sa.c:3666
static int samarkswanted(struct cam_periph *)
Definition: scsi_sa.c:3633
#define SA_ATYPE_NR
Definition: scsi_sa.c:262
#define SA_SPOS_MAX_BLK
Definition: scsi_sa.h:414
#define SE_LONG
Definition: scsi_sa.h:141
#define READ_BLOCK_LIMITS
Definition: scsi_sa.h:938
#define SARW_FIXED
Definition: scsi_sa.h:62
#define SA_CTRL_DP_LBP_R
Definition: scsi_sa.h:299
#define ERASE
Definition: scsi_sa.h:946
#define SMH_SA_BUF_MODE_SIBUF
Definition: scsi_sa.h:200
#define SRDS_MAX_LENGTH
Definition: scsi_sa.h:447
#define SLU_EOT
Definition: scsi_sa.h:74
#define SCSI_DENSITY_HALFINCH_PE
Definition: scsi_sa.h:966
#define SE_IMMED
Definition: scsi_sa.h:142
#define SCSI_DENSITY_QIC_24
Definition: scsi_sa.h:965
#define SRRU_3RD_SHAMT
Definition: scsi_sa.h:127
#define SRRU_3RD_MASK
Definition: scsi_sa.h:128
#define SCSI_DENSITY_HALFINCH_800
Definition: scsi_sa.h:959
#define SCSI_DENSITY_QIC_3080
Definition: scsi_sa.h:973
#define WRITE_FILEMARKS
Definition: scsi_sa.h:942
#define SA_WRITE
Definition: scsi_sa.h:940
#define ALLOW_OVERWRITE
Definition: scsi_sa.h:951
#define SA_SPOS_IMMED
Definition: scsi_sa.h:409
#define SA_CTRL_DP_PI_LENGTH_MASK
Definition: scsi_sa.h:295
scsi_space_code
Definition: scsi_sa.h:89
@ SS_BLOCKS
Definition: scsi_sa.h:90
@ SS_EOD
Definition: scsi_sa.h:93
@ SS_SETMARKS
Definition: scsi_sa.h:94
@ SS_FILEMARKS
Definition: scsi_sa.h:91
#define SCSI_DENSITY_QIC_2GB
Definition: scsi_sa.h:971
#define SCSI_DENSITY_QIC_525_320
Definition: scsi_sa.h:969
#define SMH_SA_BUF_MODE_NOBUF
Definition: scsi_sa.h:199
#define SMH_SA_BUF_MODE_MASK
Definition: scsi_sa.h:198
#define SWFMRK_WSMK
Definition: scsi_sa.h:112
#define SA_RPOS_LONG_FORM
Definition: scsi_sa.h:348
#define SA_DCP_DCE
Definition: scsi_sa.h:261
#define LOCATE
Definition: scsi_sa.h:948
#define SA_RPOS_LONG_BOP
Definition: scsi_sa.h:376
#define SCSI_DENSITY_QIC_120
Definition: scsi_sa.h:967
#define SA_COMP_NONE
Definition: scsi_sa.h:247
#define SCSI_DENSITY_HALFINCH_1600
Definition: scsi_sa.h:960
#define SRRU_3RD_PARTY
Definition: scsi_sa.h:126
#define LOCATE_16
Definition: scsi_sa.h:952
#define SLU_LOAD
Definition: scsi_sa.h:76
#define SA_LC_CP
Definition: scsi_sa.h:424
#define SPACE
Definition: scsi_sa.h:943
#define SREW_IMMED
Definition: scsi_sa.h:102
#define SA_SPOS_BT
Definition: scsi_sa.h:411
#define SA_LC_DEST_TYPE_SHIFT
Definition: scsi_sa.h:426
#define SCSI_DENSITY_QIC_150
Definition: scsi_sa.h:968
#define SCSI_DENSITY_QIC_4GB
Definition: scsi_sa.h:972
#define SDD_DLV
Definition: scsi_sa.h:461
#define SA_DATA_COMPRESSION_PAGE
Definition: scsi_sa.h:213
#define SWFMRK_IMMED
Definition: scsi_sa.h:111
#define SCSI_DENSITY_QIC_11_4TRK
Definition: scsi_sa.h:963
#define RELEASE_UNIT
Definition: scsi_sa.h:945
#define RESERVE_UNIT
Definition: scsi_sa.h:944
#define SA_RPOS_UNCERTAIN
Definition: scsi_sa.h:364
#define SA_RPOS_LONG_EOP
Definition: scsi_sa.h:377
#define READ_POSITION
Definition: scsi_sa.h:949
#define SCSI_DENSITY_HALFINCH_6250
Definition: scsi_sa.h:961
#define SA_RPOS_LONG_MPU
Definition: scsi_sa.h:378
#define SA_RPOS_LONG_LONU
Definition: scsi_sa.h:379
#define FORMAT_MEDIUM
Definition: scsi_sa.h:937
#define SCSI_DENSITY_HALFINCH_6250C
Definition: scsi_sa.h:962
#define SA_READ
Definition: scsi_sa.h:939
#define SDD_DEFAULT_LENGTH
Definition: scsi_sa.h:466
#define SLU_IMMED
Definition: scsi_sa.h:71
#define RBL_GRAN(rblim)
Definition: scsi_sa.h:52
#define SMH_SA_WP
Definition: scsi_sa.h:197
#define SA_LC_IMMEDIATE
Definition: scsi_sa.h:423
#define REWIND
Definition: scsi_sa.h:936
#define SA_SPOS_CP
Definition: scsi_sa.h:410
#define SAR_SLI
Definition: scsi_sa.h:61
#define SET_CAPACITY
Definition: scsi_sa.h:941
#define SMH_SA_SPEED_MASK
Definition: scsi_sa.h:202
#define SLU_RETEN
Definition: scsi_sa.h:75
#define SRDS_MEDIA
Definition: scsi_sa.h:443
#define SCSI_DENSITY_QIC_11_9TRK
Definition: scsi_sa.h:964
#define SCSI_DENSITY_QIC_1320
Definition: scsi_sa.h:970
#define SA_DEVICE_CONFIGURATION_PAGE
Definition: scsi_sa.h:208
#define SRDS_MEDIUM_TYPE
Definition: scsi_sa.h:444
#define SA_CTRL_DP_LBP_W
Definition: scsi_sa.h:298
#define REPORT_DENSITY_SUPPORT
Definition: scsi_sa.h:950
#define SA_DCP_DCC
Definition: scsi_sa.h:262
#define SA_DCP_DDE
Definition: scsi_sa.h:264
#define SA_RPOS_EXTENDED_FORM
Definition: scsi_sa.h:349
#define LOAD_UNLOAD
Definition: scsi_sa.h:947
#define SA_CTRL_DP_RBDP
Definition: scsi_sa.h:300
#define SA_RPOS_LONG_BPEW
Definition: scsi_sa.h:380
#define SA_CTRL_DP_SUBPAGE_CODE
Definition: scsi_sa.h:288
char * periph_name
Definition: cam_periph.h:123
u_int32_t unit_number
Definition: cam_periph.h:127
void * softc
Definition: cam_periph.h:125
struct cam_path * path
Definition: cam_periph.h:124
u_int32_t flags
Definition: cam_periph.h:129
struct ccb_hdr ccb_h
Definition: cam_ccb.h:1309
uint32_t buftype
Definition: cam_ccb.h:1313
uint8_t * buf
Definition: cam_ccb.h:1326
uint32_t flags
Definition: cam_ccb.h:1310
cam_proto protocol
Definition: cam_ccb.h:380
u_int8_t serial_num_len
Definition: cam_ccb.h:385
u_int8_t serial_num[252]
Definition: cam_ccb.h:383
struct ccb_hdr ccb_h
Definition: cam_ccb.h:379
struct scsi_inquiry_data inq_data
Definition: cam_ccb.h:381
struct cam_path * path
Definition: cam_ccb.h:364
xpt_opcode func_code
Definition: cam_ccb.h:362
u_int32_t status
Definition: cam_ccb.h:363
u_int16_t retry_count
Definition: cam_ccb.h:354
u_int32_t hba_misc
Definition: cam_ccb.h:665
cam_xport transport
Definition: cam_ccb.h:682
u_int maxio
Definition: cam_ccb.h:691
cdb_t cdb_io
Definition: cam_ccb.h:763
struct ccb_hdr ccb_h
Definition: cam_ccb.h:750
struct scsi_sense_data sense_data
Definition: cam_ccb.h:756
u_int8_t * data_ptr
Definition: cam_ccb.h:753
u_int8_t sense_len
Definition: cam_ccb.h:757
u_int8_t sense_resid
Definition: cam_ccb.h:761
u_int32_t dxfer_len
Definition: cam_ccb.h:754
u_int8_t cdb_len
Definition: cam_ccb.h:758
u_int32_t resid
Definition: cam_ccb.h:762
struct cdev * r_dev
Definition: scsi_sa.c:271
struct cdev * nr_dev
Definition: scsi_sa.c:272
struct cdev * er_dev
Definition: scsi_sa.c:273
struct cdev * ctl_dev
Definition: scsi_sa.c:270
sa_param_type param_type
Definition: scsi_sa.c:1363
char * name
Definition: scsi_sa.c:1362
int(* set_func)(struct cam_periph *periph, struct mtparamset *ps, int num_params)
Definition: scsi_sa.c:1364
struct sa_prot_state pending_prot_state
Definition: scsi_sa.c:341
struct sa_prot_state cur_prot_state
Definition: scsi_sa.c:340
uint32_t max_val
Definition: scsi_sa.c:352
uint32_t * value
Definition: scsi_sa.c:353
off_t offset
Definition: scsi_sa.c:350
mt_param_set_type param_type
Definition: scsi_sa.c:349
uint32_t min_val
Definition: scsi_sa.c:351
char * name
Definition: scsi_sa.c:348
uint32_t prot_method
Definition: scsi_sa.c:332
int initialized
Definition: scsi_sa.c:331
uint32_t lbp_w
Definition: scsi_sa.c:334
uint32_t rbdp
Definition: scsi_sa.c:336
uint32_t lbp_r
Definition: scsi_sa.c:335
uint32_t pi_length
Definition: scsi_sa.c:333
Definition: scsi_sa.c:480
struct scsi_inquiry_pattern inq_pat
Definition: scsi_sa.c:481
sa_quirks quirks
Definition: scsi_sa.c:482
u_int32_t prefblk
Definition: scsi_sa.c:483
int blk_mask
Definition: scsi_sa.c:393
daddr_t fileno
Definition: scsi_sa.c:439
int open_count
Definition: scsi_sa.c:390
struct scsi_sense_data _last_ctl_sense
Definition: scsi_sa.c:454
int last_resid_was_io
Definition: scsi_sa.c:413
struct sa_softc::@25 errinfo
u_int32_t saved_comp_algorithm
Definition: scsi_sa.c:403
uint8_t density_info[SA_DENSITY_TYPES][SRDS_MAX_LENGTH]
Definition: scsi_sa.c:416
u_int32_t maxio
Definition: scsi_sa.c:397
struct sysctl_oid * sysctl_tree
Definition: scsi_sa.c:475
u_int32_t ctrl_mode
Definition: scsi_sa.c:471
struct cam_periph * periph
Definition: scsi_sa.c:385
int filemarks
Definition: scsi_sa.c:412
struct sa_prot_info prot_info
Definition: scsi_sa.c:419
int eot_warn
Definition: scsi_sa.c:422
u_int64_t _last_ctl_resid
Definition: scsi_sa.c:455
int bop
Definition: scsi_sa.c:443
int timeout_info[SA_TIMEOUT_TYPE_MAX]
Definition: scsi_sa.c:417
u_int si_flags
Definition: scsi_sa.c:384
u_int32_t cpi_maxio
Definition: scsi_sa.c:398
int sili
Definition: scsi_sa.c:421
int eop
Definition: scsi_sa.c:444
u_int8_t _last_ctl_cdb[CAM_MAX_CDBLEN]
Definition: scsi_sa.c:456
u_int32_t open_rdonly
Definition: scsi_sa.c:469
u_int32_t open_pending_mount
Definition: scsi_sa.c:470
struct sysctl_oid * sysctl_timeout_tree
Definition: scsi_sa.c:477
sa_state state
Definition: scsi_sa.c:381
sa_flags flags
Definition: scsi_sa.c:382
u_int8_t dsreg
Definition: scsi_sa.c:410
u_int8_t speed
Definition: scsi_sa.c:408
u_int32_t comp_algorithm
Definition: scsi_sa.c:402
u_int64_t _last_io_resid
Definition: scsi_sa.c:452
uint8_t density_type_bits[SA_DENSITY_TYPES]
Definition: scsi_sa.c:414
int queue_count
Definition: scsi_sa.c:387
struct sa_devs devs
Definition: scsi_sa.c:389
struct sysctl_ctx_list sysctl_ctx
Definition: scsi_sa.c:474
int buffer_mode
Definition: scsi_sa.c:411
u_int32_t max_blk
Definition: scsi_sa.c:395
struct sysctl_ctx_list sysctl_timeout_ctx
Definition: scsi_sa.c:476
int blk_shift
Definition: scsi_sa.c:394
int num_devs_to_destroy
Definition: scsi_sa.c:391
u_int32_t media_blksize
Definition: scsi_sa.c:404
int inject_eom
Definition: scsi_sa.c:400
daddr_t rep_blkno
Definition: scsi_sa.c:441
struct task sysctl_task
Definition: scsi_sa.c:473
daddr_t partition
Definition: scsi_sa.c:438
int allow_io_split
Definition: scsi_sa.c:399
int bpew
Definition: scsi_sa.c:445
u_int32_t min_blk
Definition: scsi_sa.c:396
u_int8_t _last_io_cdb[CAM_MAX_CDBLEN]
Definition: scsi_sa.c:453
struct devstat * device_stats
Definition: scsi_sa.c:388
u_int32_t last_media_blksize
Definition: scsi_sa.c:405
int set_pews_status
Definition: scsi_sa.c:401
u_int32_t media_numblks
Definition: scsi_sa.c:406
int density_info_valid[SA_DENSITY_TYPES]
Definition: scsi_sa.c:415
sa_quirks quirks
Definition: scsi_sa.c:383
daddr_t rep_fileno
Definition: scsi_sa.c:442
u_int8_t scsi_rev
Definition: scsi_sa.c:409
daddr_t blkno
Definition: scsi_sa.c:440
int blk_gran
Definition: scsi_sa.c:392
struct bio_queue_head bio_queue
Definition: scsi_sa.c:386
u_int8_t media_density
Definition: scsi_sa.c:407
struct scsi_sense_data _last_io_sense
Definition: scsi_sa.c:451
const char * desc
Definition: scsi_sa.c:195
u_int8_t partition
Definition: scsi_sa.h:188
u_int8_t logical_id[8]
Definition: scsi_sa.h:189
u_int8_t allow_overwrite
Definition: scsi_sa.h:184
u_int8_t comp_algorithm[4]
Definition: scsi_sa.h:270
u_int8_t decomp_algorithm[4]
Definition: scsi_sa.h:271
u_int8_t primary_density_code
Definition: scsi_sa.h:458
u_int8_t length[2]
Definition: scsi_sa.h:465
u_int8_t byte2
Definition: scsi_sa.h:460
u_int8_t secondary_density_code
Definition: scsi_sa.h:459
u_int8_t length[2]
Definition: scsi_sa.h:452
u_int8_t sel_comp_alg
Definition: scsi_sa.h:246
u_int8_t opcode
Definition: scsi_sa.h:138
u_int8_t lun_imm_long
Definition: scsi_sa.h:139
u_int8_t byte2
Definition: scsi_sa.h:171
u_int8_t length[2]
Definition: scsi_sa.h:176
u_int8_t byte1
Definition: scsi_sa.h:168
u_int8_t opcode
Definition: scsi_sa.h:167
char vendor[SID_VENDOR_SIZE]
Definition: scsi_all.h:2269
char product[SID_PRODUCT_SIZE]
Definition: scsi_all.h:2271
u_int8_t spc3_flags
Definition: scsi_all.h:2240
u_int8_t version
Definition: scsi_all.h:2218
char revision[SID_REVISION_SIZE]
Definition: scsi_all.h:2273
u_int8_t eot_reten_load
Definition: scsi_sa.h:73
u_int8_t opcode
Definition: scsi_sa.h:69
u_int8_t immediate
Definition: scsi_sa.h:70
u_int8_t logical_id[8]
Definition: scsi_sa.h:435
u_int8_t opcode
Definition: scsi_sa.h:421
u_int8_t byte2
Definition: scsi_sa.h:431
u_int8_t byte1
Definition: scsi_sa.h:422
u_int8_t partition
Definition: scsi_sa.h:434
u_int8_t length[2]
Definition: scsi_sa.h:479
u_int8_t description[20]
Definition: scsi_sa.h:488
u_int8_t media_width[2]
Definition: scsi_sa.h:483
u_int8_t reserved2[2]
Definition: scsi_sa.h:485
u_int8_t medium_type
Definition: scsi_sa.h:477
u_int8_t medium_length[2]
Definition: scsi_sa.h:484
u_int8_t medium_type_name[8]
Definition: scsi_sa.h:487
u_int8_t assigning_org[8]
Definition: scsi_sa.h:486
u_int8_t num_density_codes
Definition: scsi_sa.h:481
u_int8_t primary_density_codes[9]
Definition: scsi_sa.h:482
u_int8_t blklen[3]
Definition: scsi_all.h:3682
u_int8_t density
Definition: scsi_all.h:3679
u_int8_t nblocks[3]
Definition: scsi_all.h:3680
u_int8_t data_length[2]
Definition: scsi_all.h:3652
u_int8_t medium_type
Definition: scsi_all.h:3653
u_int8_t blk_desc_len[2]
Definition: scsi_all.h:3658
u_int8_t dev_spec
Definition: scsi_all.h:3646
u_int8_t medium_type
Definition: scsi_all.h:3645
u_int8_t blk_desc_len
Definition: scsi_all.h:3647
u_int8_t data_length
Definition: scsi_all.h:3644
u_int8_t subpage
Definition: scsi_all.h:221
u_int8_t immediate
Definition: scsi_sa.h:83
u_int8_t opcode
Definition: scsi_sa.h:82
u_int8_t sli_fixed
Definition: scsi_sa.h:60
u_int8_t opcode
Definition: scsi_sa.h:59
u_int8_t length[3]
Definition: scsi_sa.h:63
u_int8_t control
Definition: scsi_sa.h:64
uint8_t error_code
Definition: scsi_all.h:3246
u_int8_t byte1
Definition: scsi_sa.h:153
u_int8_t opcode
Definition: scsi_sa.h:152
u_int8_t cap_proportion[2]
Definition: scsi_sa.h:156
u_int8_t code
Definition: scsi_sa.h:101
u_int8_t opcode
Definition: scsi_sa.h:100
u_int8_t control
Definition: scsi_sa.h:104
u_int8_t count[3]
Definition: scsi_sa.h:103
u_int8_t blkaddr[4]
Definition: scsi_sa.h:413
u_int8_t byte1
Definition: scsi_sa.h:408
u_int8_t opcode
Definition: scsi_sa.h:407
u_int8_t partition
Definition: scsi_sa.h:416
u_int8_t firstblk[4]
Definition: scsi_sa.h:367
u_int8_t logical_file_num[8]
Definition: scsi_sa.h:384
u_int8_t logical_object_num[8]
Definition: scsi_sa.h:383
u_int8_t length[2]
Definition: scsi_sa.h:351
u_int8_t num_marks[3]
Definition: scsi_sa.h:113
Definition: cam_ccb.h:1345
struct ccb_hdr ccb_h
Definition: cam_ccb.h:1346
struct ccb_scsiio csio
Definition: cam_ccb.h:1347
u_int8_t cdb_bytes[IOCDBLEN]
Definition: cam_ccb.h:742
u_int8_t pagecode
Definition: scsi_sa.h:276
struct sa_comp_t::@26 hdr
struct scsi_dev_conf_page dconf
Definition: scsi_sa.h:277
struct scsi_data_compression_page dcomp
Definition: scsi_sa.h:278