summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/mt/mt.c5
-rw-r--r--usr/src/uts/common/io/scsi/impl/scsi_subr.c7
-rw-r--r--usr/src/uts/common/io/scsi/targets/st.c762
-rw-r--r--usr/src/uts/common/io/scsi/targets/st_conf.c366
-rw-r--r--usr/src/uts/common/sys/mtio.h2
-rw-r--r--usr/src/uts/common/sys/scsi/generic/commands.h8
-rw-r--r--usr/src/uts/common/sys/scsi/targets/stdef.h179
7 files changed, 1117 insertions, 212 deletions
diff --git a/usr/src/cmd/mt/mt.c b/usr/src/cmd/mt/mt.c
index e4f876fda0..a8af090ce7 100644
--- a/usr/src/cmd/mt/mt.c
+++ b/usr/src/cmd/mt/mt.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -357,6 +357,9 @@ status(struct mtget *bp)
(void) printf("retries= %d\n", bp->mt_dsreg);
(void) printf(" file no= %ld block no= %ld\n",
bp->mt_fileno, bp->mt_blkno);
+ if ((bp->mt_flags & MTF_WORM_MEDIA) != 0) {
+ (void) printf(" WORM media\n");
+ }
} else {
/* Handle non-SCSI drives here. */
if (mt->t_type == 0) {
diff --git a/usr/src/uts/common/io/scsi/impl/scsi_subr.c b/usr/src/uts/common/io/scsi/impl/scsi_subr.c
index 848a5d95a7..8b24239f67 100644
--- a/usr/src/uts/common/io/scsi/impl/scsi_subr.c
+++ b/usr/src/uts/common/io/scsi/impl/scsi_subr.c
@@ -670,6 +670,7 @@ static struct scsi_asq_key_strings extended_sense_list[] = {
0x27, 0x04, "persistent write protect",
0x27, 0x05, "permanent write protect",
0x27, 0x06, "conditional write protect",
+ 0x27, 0x80, "unable to overwrite data",
0x28, 0x00, "medium may have changed",
0x28, 0x01, "import or export element accessed",
0x29, 0x00, "power on, reset, or bus reset occurred",
@@ -709,10 +710,14 @@ static struct scsi_asq_key_strings extended_sense_list[] = {
0x30, 0x07, "cleaning failure",
0x30, 0x08, "cannot write - application code mismatch",
0x30, 0x09, "current session not fixated for append",
+ 0x30, 0x0b, "WORM medium - Overwrite attempted",
+ 0x30, 0x0c, "WORM medium - Cannot Erase",
+ 0x30, 0x0d, "WORM medium - Integrity Check",
0x30, 0x10, "medium not formatted",
0x31, 0x00, "medium format corrupted",
0x31, 0x01, "format command failed",
0x31, 0x02, "zoned formatting failed due to spare linking",
+ 0x31, 0x94, "WORM media corrupted",
0x32, 0x00, "no defect spare location available",
0x32, 0x01, "defect list update failure",
0x33, 0x00, "tape length error",
@@ -795,6 +800,8 @@ static struct scsi_asq_key_strings extended_sense_list[] = {
0x4d, 0x00, "tagged overlapped commands (ASCQ = queue tag)",
0x4e, 0x00, "overlapped commands attempted",
0x50, 0x00, "write append error",
+ 0x50, 0x01, "data protect write append error",
+ 0x50, 0x95, "data protect write append error",
0x51, 0x00, "erase failure",
0x52, 0x00, "cartridge fault",
0x53, 0x00, "media load or eject failed",
diff --git a/usr/src/uts/common/io/scsi/targets/st.c b/usr/src/uts/common/io/scsi/targets/st.c
index 26c1518210..160c23d6b0 100644
--- a/usr/src/uts/common/io/scsi/targets/st.c
+++ b/usr/src/uts/common/io/scsi/targets/st.c
@@ -108,6 +108,7 @@
* Global External Data Definitions
*/
extern struct scsi_key_strings scsi_cmds[];
+extern uchar_t scsi_cdb_size[];
/*
* Local Static Data
@@ -229,7 +230,7 @@ extern const struct st_drivetype st_drivetypes[];
#ifdef STDEBUG
static int st_soft_error_report_debug = 0;
-static int st_debug = 0;
+volatile int st_debug = 0;
#endif
#define ST_MT02_NAME "Emulex MT02 QIC-11/24 "
@@ -486,11 +487,16 @@ static int st_check_cmd_for_need_to_reserve(struct scsi_tape *un, uchar_t cmd,
static int st_take_ownership(dev_t dev);
static int st_check_asc_ascq(struct scsi_tape *un);
static int st_check_clean_bit(dev_t dev);
-static int st_check_alert_clean_bit(dev_t dev);
+static int st_check_alert_flags(dev_t dev);
static int st_check_sequential_clean_bit(dev_t dev);
static int st_check_sense_clean_bit(dev_t dev);
static int st_clear_unit_attentions(dev_t dev_instance, int max_trys);
static void st_calculate_timeouts(struct scsi_tape *un);
+static writablity st_is_drive_worm(struct scsi_tape *un);
+static int st_read_attributes(struct scsi_tape *un, uint16_t attribute,
+ caddr_t buf, size_t size);
+static int st_get_special_inquiry(struct scsi_tape *un, uchar_t size,
+ caddr_t dest, uchar_t page);
#if defined(__i386) || defined(__amd64)
/*
@@ -932,9 +938,22 @@ st_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
*/
un->un_maxdma = scsi_ifgetcap(&devp->sd_address, "dma-max", 1);
if (un->un_maxdma == -1) {
+ ST_DEBUG(devi, st_label, SCSI_DEBUG,
+ "Receaved a value that looked like -1. Using 64k maxdma");
un->un_maxdma = (64 * 1024);
}
+ /*
+ * Get the max allowable cdb size
+ */
+ un->un_max_cdb_sz =
+ scsi_ifgetcap(&devp->sd_address, "max-cdb-length", 1);
+ if (un->un_max_cdb_sz < CDB_GROUP0) {
+ ST_DEBUG(devi, st_label, SCSI_DEBUG,
+ "HBA reported max-cdb-length as %d\n", un->un_max_cdb_sz);
+ un->un_max_cdb_sz = CDB_GROUP4; /* optimistic default */
+ }
+
un->un_maxbsize = MAXBSIZE_UNKNOWN;
un->un_mediastate = MTIO_NONE;
@@ -1385,6 +1404,8 @@ st_doattach(struct scsi_device *devp, int (*canwait)())
}
un = ddi_get_soft_state(st_state, instance);
+ ASSERT(un != NULL);
+
un->un_sbufp = getrbuf(km_flags);
un->un_uscsi_rqs_buf = kmem_alloc(SENSE_LENGTH, KM_SLEEP);
@@ -1432,6 +1453,7 @@ st_doattach(struct scsi_device *devp, int (*canwait)())
un->un_rqs_bp = bp;
un->un_swr_token = (opaque_t)NULL;
un->un_comp_page = ST_DEV_DATACOMP_PAGE | ST_DEV_CONFIG_PAGE;
+ un->un_wormable = st_is_drive_worm;
un->un_suspend_fileno = 0;
un->un_suspend_blkno = 0;
@@ -2016,7 +2038,8 @@ st_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
if (un->un_fileno < 0 || (un->un_fileno == 0 &&
un->un_blkno == 0)) {
un->un_state = ST_STATE_OFFLINE;
- } else {
+ } else if (un->un_fileno > 0 ||
+ (un->un_fileno == 0 && un->un_blkno != 0)) {
/*
* set un_read_only/write-protect status.
*
@@ -2029,14 +2052,11 @@ st_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
* Hence make the st state OFFLINE so that
* we re-intialize the tape once again.
*/
- if (un->un_fileno > 0 ||
- (un->un_fileno == 0 && un->un_blkno != 0)) {
- un->un_read_only =
- (un->un_oflags & FWRITE) ? 0 : 1;
- un->un_state = ST_STATE_OPEN_PENDING_IO;
- } else {
- un->un_state = ST_STATE_OFFLINE;
- }
+ un->un_read_only =
+ (un->un_oflags & FWRITE) ? RDWR : RDONLY;
+ un->un_state = ST_STATE_OPEN_PENDING_IO;
+ } else {
+ un->un_state = ST_STATE_OFFLINE;
}
rval = 0;
} else {
@@ -2046,7 +2066,10 @@ st_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
un->un_state = ST_STATE_OPENING;
rval = st_tape_init(dev);
- if (rval) {
+ if ((rval == EACCES) && (un->un_read_only & WORM)) {
+ un->un_state = ST_STATE_OPEN_PENDING_IO;
+ rval = 0; /* so open doesn't fail */
+ } else if (rval) {
/*
* Release the tape unit, if reserved and not
* preserve reserve.
@@ -2360,17 +2383,39 @@ st_tape_init(dev_t dev)
*/
if (un->un_oflags & FWRITE) {
err = 0;
- if (un->un_mspl->wp) {
+ if (un->un_mspl->wp) {
un->un_status = KEY_WRITE_PROTECT;
un->un_laststate = un->un_state;
un->un_state = ST_STATE_CLOSED;
rval = EACCES;
- goto exit;
+ /*
+ * STK sets the wp bit if volsafe tape is loaded.
+ */
+ if ((un->un_dp->type == MT_ISSTK9840) &&
+ (un->un_dp->options & ST_WORMABLE)) {
+ un->un_read_only = RDONLY;
+ } else {
+ goto exit;
+ }
} else {
- un->un_read_only = 0;
+ un->un_read_only = RDWR;
}
} else {
- un->un_read_only = 1;
+ un->un_read_only = RDONLY;
+ }
+
+ if (un->un_dp->options & ST_WORMABLE) {
+ un->un_read_only |= un->un_wormable(un);
+
+ if (((un->un_read_only == WORM) ||
+ (un->un_read_only == RDWORM)) &&
+ ((un->un_oflags & FWRITE) == FWRITE)) {
+ un->un_status = KEY_DATA_PROTECT;
+ rval = EACCES;
+ ST_DEBUG4(ST_DEVINFO, st_label, CE_NOTE,
+ "read_only = %d eof = %d oflag = %d\n",
+ un->un_read_only, un->un_eof, un->un_oflags);
+ }
}
/*
@@ -2378,10 +2423,13 @@ st_tape_init(dev_t dev)
* write 2 filemarks on the HP 1/2 inch drive, to
* create a null file.
*/
- if ((un->un_oflags == FWRITE) && (un->un_dp->options & ST_REEL)) {
- un->un_fmneeded = 2;
- } else if (un->un_oflags == FWRITE) {
- un->un_fmneeded = 1;
+ if ((un->un_read_only == RDWR) ||
+ (un->un_read_only == WORM) && (un->un_oflags & FWRITE)) {
+ if (un->un_dp->options & ST_REEL) {
+ un->un_fmneeded = 2;
+ } else {
+ un->un_fmneeded = 1;
+ }
} else {
un->un_fmneeded = 0;
}
@@ -2391,8 +2439,12 @@ st_tape_init(dev_t dev)
/*
* Make sure the density can be selected correctly.
+ * If WORM can only write at the append point which in most cases
+ * isn't BOP. st_determine_density() with a B_WRITE only attempts
+ * to set and try densities if a BOP.
*/
- if (st_determine_density(dev, B_WRITE)) {
+ if (st_determine_density(dev,
+ un->un_read_only == RDWR ? B_WRITE : B_READ)) {
un->un_status = KEY_ILLEGAL_REQUEST;
un->un_laststate = un->un_state;
un->un_state = ST_STATE_CLOSED;
@@ -2555,6 +2607,10 @@ st_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
case ST_EOT_PENDING:
/* nothing to do */
break;
+ default:
+ scsi_log(ST_DEVINFO, st_label, CE_PANIC,
+ "Undefined state 0x%x", un->un_eof);
+
}
}
@@ -3715,7 +3771,7 @@ st_check_density_or_wfm(dev_t dev, int wfm, int mode, int stepflag)
* If writing, let's check that we're positioned correctly
* at the end of tape before issuing the next write.
*/
- if (!un->un_read_only) {
+ if (un->un_read_only == RDWR) {
un->un_test_append = 1;
}
@@ -3879,6 +3935,11 @@ check_commands:
un->un_maxdma) / SECSIZE;
}
+ if (un->un_read_only == WORM ||
+ un->un_read_only == RDWORM) {
+ mtget->mt_flags |= MTF_WORM_MEDIA;
+ }
+
rval = st_check_clean_bit(dev);
if (rval == -1) {
rval = EIO;
@@ -4657,16 +4718,18 @@ st_mtioctop(struct scsi_tape *un, intptr_t arg, int flag)
* MTERASE rewinds the tape, erase it completely, and returns
* to the beginning of the tape
*/
- if (un->un_dp->options & ST_REEL)
- un->un_fmneeded = 2;
-
- if (un->un_mspl->wp || un->un_read_only) {
+ if (un->un_mspl->wp || un->un_read_only & WORM) {
un->un_status = KEY_WRITE_PROTECT;
un->un_err_resid = mtop->mt_count;
un->un_err_fileno = un->un_fileno;
un->un_err_blkno = un->un_blkno;
return (EACCES);
}
+ if (un->un_dp->options & ST_REEL) {
+ un->un_fmneeded = 2;
+ } else {
+ un->un_fmneeded = 1;
+ }
if (st_check_density_or_wfm(dev, 1, B_WRITE, NO_STEPBACK) ||
st_cmd(dev, SCMD_REWIND, 0, SYNC_CMD) ||
st_cmd(dev, SCMD_ERASE, 0, SYNC_CMD)) {
@@ -4686,7 +4749,7 @@ st_mtioctop(struct scsi_tape *un, intptr_t arg, int flag)
/*
* write an end-of-file record
*/
- if (un->un_mspl->wp || un->un_read_only) {
+ if (un->un_mspl->wp || un->un_read_only & RDONLY) {
un->un_status = KEY_WRITE_PROTECT;
un->un_err_resid = mtop->mt_count;
un->un_err_fileno = un->un_fileno;
@@ -4701,7 +4764,8 @@ st_mtioctop(struct scsi_tape *un, intptr_t arg, int flag)
if (mtop->mt_count < 0)
return (EINVAL);
- if (!un->un_read_only) {
+ /* Not on worm */
+ if (un->un_read_only == RDWR) {
un->un_test_append = 1;
}
@@ -4714,7 +4778,8 @@ st_mtioctop(struct scsi_tape *un, intptr_t arg, int flag)
}
}
- if (st_write_fm(dev, (int)mtop->mt_count)) {
+ rval = st_write_fm(dev, (int)mtop->mt_count);
+ if ((rval != 0) && (rval != EACCES)) {
/*
* Failure due to something other than illegal
* request results in loss of state (st_intr).
@@ -4813,7 +4878,13 @@ st_mtioctop(struct scsi_tape *un, intptr_t arg, int flag)
*/
un->un_state = ST_STATE_INITIALIZING;
- if (st_tape_init(dev)) {
+ rval = st_tape_init(dev);
+ if ((rval == EACCES) && (un->un_read_only & WORM)) {
+ rval = 0;
+ break;
+ }
+
+ if (rval != 0) {
ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
"st_mtioctop : EIO : MTLOAD calls st_tape_init\n");
rval = EIO;
@@ -5634,7 +5705,12 @@ st_ioctl_cmd(dev_t dev, struct uscsi_cmd *ucmd,
/*
* First do some sanity checks for USCSI commands.
*/
- if (ucmd->uscsi_cdblen <= 0) {
+ if ((ucmd->uscsi_cdblen <= 0) ||
+ (ucmd->uscsi_cdblen > un->un_max_cdb_sz)) {
+ if (cdbspace != UIO_SYSSPACE) {
+ scsi_log(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "USCSICMD with cdb larger then transport supports");
+ }
return (EINVAL);
}
@@ -5658,6 +5734,17 @@ st_ioctl_cmd(dev_t dev, struct uscsi_cmd *ucmd,
}
}
+ /*
+ * can't peek at the cdb till is copied into kernal space.
+ */
+ if (scsi_cdb_size[CDB_GROUPID(kcdb[0])] > un->un_max_cdb_sz) {
+ if (cdbspace != UIO_SYSSPACE) {
+ scsi_log(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "USCSICMD with cdb larger then transport supports");
+ }
+ kmem_free(kcdb, ucmd->uscsi_cdblen);
+ return (EINVAL);
+ }
kcmd = kmem_alloc(sizeof (struct uscsi_cmd), KM_SLEEP);
bcopy(ucmd, kcmd, sizeof (struct uscsi_cmd));
kcmd->uscsi_cdb = kcdb;
@@ -5876,6 +5963,7 @@ static int
st_write_fm(dev_t dev, int wfm)
{
int i;
+ int rval;
GET_SOFT_STATE(dev);
@@ -5889,16 +5977,26 @@ st_write_fm(dev_t dev, int wfm)
*/
if (un->un_eof >= ST_EOT) {
for (i = 0; i < wfm; i++) {
- if (st_cmd(dev, SCMD_WRITE_FILE_MARK, 1, SYNC_CMD)) {
+ rval = st_cmd(dev, SCMD_WRITE_FILE_MARK, 1, SYNC_CMD);
+ if (rval == EACCES) {
+ return (rval);
+ }
+ if (rval != 0) {
ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
"st_write_fm : EIO : write EOT file mark");
return (EIO);
}
}
- } else if (st_cmd(dev, SCMD_WRITE_FILE_MARK, wfm, SYNC_CMD)) {
- ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
- "st_write_fm : EIO : write file mark");
- return (EIO);
+ } else {
+ rval = st_cmd(dev, SCMD_WRITE_FILE_MARK, wfm, SYNC_CMD);
+ if (rval == EACCES) {
+ return (rval);
+ }
+ if (rval) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "st_write_fm : EIO : write file mark");
+ return (EIO);
+ }
}
ASSERT(mutex_owned(ST_MUTEX));
@@ -6199,7 +6297,6 @@ exit:
}
-
/*
* st_runout a callback that is called what a resource allocatation failed
*/
@@ -6208,7 +6305,6 @@ st_runout(caddr_t arg)
{
struct scsi_tape *un = (struct scsi_tape *)arg;
struct buf *bp;
-
ASSERT(un != NULL);
mutex_enter(ST_MUTEX);
@@ -6312,7 +6408,7 @@ st_done_and_mutex_exit(struct scsi_tape *un, struct buf *bp)
ST_DEBUG3(ST_DEVINFO, st_label, SCSI_DEBUG,
"st_done_and_mutex_exit(): cmd=0x%x count=%ld resid=%ld flags=0x%x\n",
- (int)*((caddr_t)(BP_PKT(bp))->pkt_cdbp),
+ (uchar_t)*((caddr_t)(BP_PKT(bp))->pkt_cdbp),
bp->b_bcount, bp->b_resid, bp->b_flags);
@@ -9908,7 +10004,7 @@ st_set_state(struct scsi_tape *un)
ST_DEBUG3(ST_DEVINFO, st_label, SCSI_DEBUG,
"st_set_state(): un_eof=%x fmneeded=%x pkt_resid=0x%lx (%ld)\n",
- un->un_eof, un->un_fmneeded, sp->pkt_resid, sp->pkt_resid);
+ un->un_eof, un->un_fmneeded, sp->pkt_resid, sp->pkt_resid);
if (bp != un->un_sbufp) {
#ifdef STDEBUG
@@ -10110,6 +10206,7 @@ st_set_state(struct scsi_tape *un)
case SCMD_LOG_SELECT_G1:
case SCMD_LOG_SENSE_G1:
case SCMD_REPORT_LUNS:
+ case SCMD_READ_ATTRIBUTE:
un->un_lastop = saved_lastop;
break;
case SCMD_LOCATE: /* Locate makes position unknown */
@@ -11303,7 +11400,7 @@ st_check_clean_bit(dev_t dev)
if ((rval <= 0) && (un->un_HeadClean & TAPE_ALERT_SUPPORTED)) {
- rval = st_check_alert_clean_bit(dev);
+ rval = st_check_alert_flags(dev);
}
if ((rval <= 0) && (un->un_dp->options & ST_CLN_MASK)) {
@@ -11426,13 +11523,13 @@ st_check_sequential_clean_bit(dev_t dev)
static int
-st_check_alert_clean_bit(dev_t dev)
+st_check_alert_flags(dev_t dev)
{
struct st_tape_alert *ta;
struct uscsi_cmd *com;
unsigned ix, length;
int rval;
- ushort_t parameter;
+ tape_alert_flags flag;
char cdb[CDB_GROUP1] = {
SCMD_LOG_SENSE_G1,
0,
@@ -11492,37 +11589,34 @@ st_check_alert_clean_bit(dev_t dev)
break;
}
- parameter = ((ta->param[ix].log_param.pc_hi << 8) +
+ flag = ((ta->param[ix].log_param.pc_hi << 8) +
ta->param[ix].log_param.pc_lo);
+ if ((ta->param[ix].param_value & 1) == 0) {
+ continue;
+ }
/*
* check to see if current parameter is of interest.
* CLEAN_FOR_ERRORS is vendor specific to 9840 9940 stk's.
*/
- if ((parameter == CLEAN_NOW) ||
- (parameter == CLEAN_PERIODIC) ||
- ((parameter == CLEAN_FOR_ERRORS) &&
+ if ((flag == TAF_CLEAN_NOW) ||
+ (flag == TAF_CLEAN_PERIODIC) ||
+ ((flag == CLEAN_FOR_ERRORS) &&
(un->un_dp->type == ST_TYPE_STK9840))) {
rval = MTF_TAPE_CLN_SUPPORTED;
- if (ta->param[ix].param_value & 1) {
-
- ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
- "alert_page drive needs clean %d\n",
- parameter);
- un->un_HeadClean |= TAPE_ALERT_STILL_DIRTY;
- rval |= MTF_TAPE_HEAD_DIRTY;
- }
- } else if (parameter == CLEANING_MEDIA) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "alert_page drive needs clean %d\n", flag);
+ un->un_HeadClean |= TAPE_ALERT_STILL_DIRTY;
+ rval |= MTF_TAPE_HEAD_DIRTY;
- if (ta->param[ix].param_value & 1) {
+ } else if (flag == TAF_CLEANING_MEDIA) {
- ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
- "alert_page drive was cleaned\n");
- un->un_HeadClean &= ~TAPE_ALERT_STILL_DIRTY;
- }
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "alert_page drive was cleaned\n");
+ un->un_HeadClean &= ~TAPE_ALERT_STILL_DIRTY;
}
}
@@ -11533,7 +11627,7 @@ st_check_alert_clean_bit(dev_t dev)
if (un->un_HeadClean & TAPE_ALERT_STILL_DIRTY) {
ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
- "alert_page still dirty\n");
+ "alert_page still dirty\n");
rval |= MTF_TAPE_HEAD_DIRTY;
}
@@ -11711,6 +11805,550 @@ st_calculate_timeouts(struct scsi_tape *un)
}
}
+
+/*ARGSUSED*/
+static writablity
+st_is_not_wormable(struct scsi_tape *un)
+{
+ return (RDWR);
+}
+
+static writablity
+st_is_hp_lto_tape_worm(struct scsi_tape *un)
+{
+ writablity wrt;
+
+
+ /* Mode sense should be current */
+ switch (un->un_mspl->media_type) {
+ case 0x00:
+ switch (un->un_mspl->density) {
+ case 0x40:
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive has standard Gen I media loaded\n");
+ break;
+ case 0x42:
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive has standard Gen II media loaded\n");
+ break;
+ case 0x44:
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive has standard Gen III media loaded\n");
+ break;
+ default:
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive has standard unknown 0x%X media loaded\n",
+ un->un_mspl->density);
+ }
+ wrt = RDWR;
+ break;
+ case 0x01:
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive has WORM medium loaded\n");
+ wrt = WORM;
+ break;
+ case 0x80:
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive has CD-ROM emulation medium loaded\n");
+ wrt = WORM;
+ break;
+ default:
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive has an unexpected medium type 0x%X loaded\n",
+ un->un_mspl->media_type);
+ wrt = RDWR;
+ }
+
+ return (wrt);
+}
+
+#define LTO_REQ_INQUIRY 44
+static writablity
+st_is_hp_lto_worm(struct scsi_tape *un)
+{
+ char *buf;
+ int result;
+ writablity wrt;
+
+ buf = kmem_zalloc(LTO_REQ_INQUIRY, KM_SLEEP);
+
+ result = st_get_special_inquiry(un, LTO_REQ_INQUIRY, buf, 0);
+
+ if (result != 0) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Read Standard Inquiry for WORM support failed");
+ wrt = ERROR;
+ } else if ((buf[40] & 1) == 0) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive is NOT WORMable\n");
+ /* This drive doesn't support it so don't check again */
+ un->un_dp->options &= ~ST_WORMABLE;
+ wrt = RDWR;
+ un->un_wormable = st_is_not_wormable;
+ } else {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive supports WORM version %d\n", buf[40] >> 1);
+ un->un_wormable = st_is_hp_lto_tape_worm;
+ wrt = un->un_wormable(un);
+ }
+
+ kmem_free(buf, LTO_REQ_INQUIRY);
+
+ /*
+ * If drive doesn't support it no point in checking further.
+ */
+ return (wrt);
+}
+
+static writablity
+st_is_t10_worm_device(struct scsi_tape *un)
+{
+ writablity wrt;
+
+ if (un->un_mspl->media_type == 0x3c) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive has WORM media loaded\n");
+ wrt = WORM;
+ } else {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive has non WORM media loaded\n");
+ wrt = RDWR;
+ }
+ return (wrt);
+}
+
+#define SEQ_CAP_PAGE (char)0xb0
+static writablity
+st_is_t10_worm(struct scsi_tape *un)
+{
+ char *buf;
+ int result;
+ writablity wrt;
+
+ buf = kmem_zalloc(6, KM_SLEEP);
+
+ result = st_get_special_inquiry(un, 6, buf, SEQ_CAP_PAGE);
+
+ if (result != 0) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Read Vitial Inquiry for Sequental Capability"
+ " WORM support failed %x", result);
+ wrt = ERROR;
+ } else if ((buf[4] & 1) == 0) {
+ ASSERT(buf[1] == SEQ_CAP_PAGE);
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive is NOT WORMable\n");
+ /* This drive doesn't support it so don't check again */
+ un->un_dp->options &= ~ST_WORMABLE;
+ wrt = RDWR;
+ un->un_wormable = st_is_not_wormable;
+ } else {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive supports WORM\n");
+ un->un_wormable = st_is_t10_worm_device;
+ wrt = un->un_wormable(un);
+ }
+
+ kmem_free(buf, 6);
+
+ return (wrt);
+}
+
+
+#define STK_REQ_SENSE 26
+
+static writablity
+st_is_stk_worm(struct scsi_tape *un)
+{
+ char cdb[CDB_GROUP0] = {SCMD_REQUEST_SENSE, 0, 0, 0, STK_REQ_SENSE, 0};
+ struct scsi_extended_sense *sense;
+ struct uscsi_cmd *cmd;
+ char *buf;
+ int result;
+ writablity wrt;
+
+ cmd = kmem_zalloc(sizeof (struct uscsi_cmd), KM_SLEEP);
+ buf = kmem_alloc(STK_REQ_SENSE, KM_SLEEP);
+ sense = (struct scsi_extended_sense *)buf;
+
+ cmd->uscsi_flags = USCSI_READ;
+ cmd->uscsi_timeout = un->un_dp->non_motion_timeout;
+ cmd->uscsi_cdb = &cdb[0];
+ cmd->uscsi_bufaddr = buf;
+ cmd->uscsi_buflen = STK_REQ_SENSE;
+ cmd->uscsi_cdblen = CDB_GROUP0;
+ cmd->uscsi_rqlen = 0;
+ cmd->uscsi_rqbuf = NULL;
+
+ result = st_ioctl_cmd(un->un_dev, cmd,
+ UIO_SYSSPACE, UIO_SYSSPACE, UIO_SYSSPACE);
+
+ if (result != 0 || cmd->uscsi_status != 0) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Request Sense for WORM failed");
+ wrt = RDWR;
+ } else if (sense->es_add_len + 8 < 24) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive didn't send enough sense data for WORM byte %d\n",
+ sense->es_add_len + 8);
+ wrt = RDWR;
+ un->un_wormable = st_is_not_wormable;
+ } else if ((buf[24]) & 0x02) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive has WORM tape loaded\n");
+ wrt = WORM;
+ un->un_wormable = st_is_stk_worm;
+ } else {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive has normal tape loaded\n");
+ wrt = RDWR;
+ un->un_wormable = st_is_stk_worm;
+ }
+
+ kmem_free(buf, STK_REQ_SENSE);
+ kmem_free(cmd, sizeof (struct uscsi_cmd));
+ return (wrt);
+}
+
+#define DLT_INQ_SZ 44
+
+static writablity
+st_is_dlt_tape_worm(struct scsi_tape *un)
+{
+ caddr_t buf;
+ int result;
+ writablity wrt;
+
+ buf = kmem_alloc(DLT_INQ_SZ, KM_SLEEP);
+
+ /* Read Attribute Media Type */
+
+ result = st_read_attributes(un, 0x0408, buf, 10);
+
+ /*
+ * If this quantum drive is attached via an HBA that cannot
+ * support thr read attributes command return error in the
+ * hope that someday they will support the t10 method.
+ */
+ if (result == EINVAL && un->un_max_cdb_sz < CDB_GROUP4) {
+ scsi_log(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Read Attribute Command for WORM Media detection is not "
+ "supported on the HBA that this drive is attached to.");
+ wrt = RDWR;
+ un->un_wormable = st_is_not_wormable;
+ goto out;
+ }
+
+ if (result != 0) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Read Attribute Command for WORM Media returned 0x%x",
+ result);
+ wrt = RDWR;
+ un->un_dp->options &= ~ST_WORMABLE;
+ goto out;
+ }
+
+ if ((uchar_t)buf[9] == 0x80) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive media is WORM\n");
+ wrt = WORM;
+ } else {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive media is not WORM Media 0x%x\n", (uchar_t)buf[9]);
+ wrt = RDWR;
+ }
+
+out:
+ kmem_free(buf, DLT_INQ_SZ);
+ return (wrt);
+}
+
+static writablity
+st_is_dlt_worm(struct scsi_tape *un)
+{
+ caddr_t buf;
+ int result;
+ writablity wrt;
+
+ buf = kmem_alloc(DLT_INQ_SZ, KM_SLEEP);
+
+ result = st_get_special_inquiry(un, DLT_INQ_SZ, buf, 0xC0);
+
+ if (result != 0) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Read Vendor Specific Inquiry for WORM support failed");
+ wrt = RDWR;
+ goto out;
+ }
+
+ if ((buf[2] & 1) == 0) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive is not WORMable\n");
+ wrt = RDWR;
+ un->un_dp->options &= ~ST_WORMABLE;
+ un->un_wormable = st_is_not_wormable;
+ goto out;
+ } else {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drive is WORMable\n");
+ un->un_wormable = st_is_dlt_tape_worm;
+ wrt = un->un_wormable(un);
+ }
+out:
+ kmem_free(buf, DLT_INQ_SZ);
+
+ return (wrt);
+}
+
+typedef struct {
+ struct modeheader_seq header;
+#if defined(_BIT_FIELDS_LTOH) /* X86 */
+ uchar_t pagecode :6,
+ :2;
+ uchar_t page_len;
+ uchar_t syslogalive :2,
+ device :1,
+ abs :1,
+ ulpbot :1,
+ prth :1,
+ ponej :1,
+ ait :1;
+ uchar_t span;
+
+ uchar_t :6,
+ worm :1,
+ mic :1;
+ uchar_t worm_cap :1,
+ :7;
+ uint32_t :32;
+#else /* SPARC */
+ uchar_t :2,
+ pagecode :6;
+ uchar_t page_len;
+ uchar_t ait :1,
+ device :1,
+ abs :1,
+ ulpbot :1,
+ prth :1,
+ ponej :1,
+ syslogalive :2;
+ uchar_t span;
+ uchar_t mic :1,
+ worm :1,
+ :6;
+ uchar_t :7,
+ worm_cap :1;
+ uint32_t :32;
+#endif
+}ait_dev_con;
+
+#define AIT_DEV_PAGE 0x31
+static writablity
+st_is_sony_worm(struct scsi_tape *un)
+{
+ int result;
+ writablity wrt;
+ ait_dev_con *ait_conf;
+
+ ait_conf = kmem_zalloc(sizeof (ait_dev_con), KM_SLEEP);
+
+ result = st_gen_mode_sense(un, AIT_DEV_PAGE,
+ (struct seq_mode *)ait_conf, sizeof (ait_dev_con));
+
+ if (result == 0) {
+
+ if (ait_conf->pagecode != AIT_DEV_PAGE) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "returned page 0x%x not 0x%x AIT_DEV_PAGE\n",
+ ait_conf->pagecode, AIT_DEV_PAGE);
+ wrt = RDWR;
+ un->un_wormable = st_is_not_wormable;
+
+ } else if (ait_conf->worm_cap) {
+
+ un->un_wormable = st_is_sony_worm;
+
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drives is WORMable\n");
+ if (ait_conf->worm) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Media is WORM\n");
+ wrt = WORM;
+ } else {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Media is not WORM\n");
+ wrt = RDWR;
+ }
+
+ } else {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Drives not is WORMable\n");
+ wrt = RDWR;
+ /* No further checking required */
+ un->un_dp->options &= ~ST_WORMABLE;
+ }
+
+ } else {
+
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "AIT device config mode sense page read command failed"
+ " result = %d ", result);
+ wrt = ERROR;
+ un->un_wormable = st_is_not_wormable;
+ }
+
+ kmem_free(ait_conf, sizeof (ait_dev_con));
+ return (wrt);
+}
+
+static writablity
+st_is_drive_worm(struct scsi_tape *un)
+{
+ writablity wrt;
+
+ switch (un->un_dp->type) {
+ case MT_ISDLT:
+ wrt = st_is_dlt_worm(un);
+ break;
+
+ case MT_ISSTK9840:
+ wrt = st_is_stk_worm(un);
+ break;
+
+ case MT_IS8MM:
+ case MT_ISAIT:
+ wrt = st_is_sony_worm(un);
+ break;
+
+ case MT_LTO:
+ if (strncmp("HP ", un->un_dp->vid, 3) == 0) {
+ wrt = st_is_hp_lto_worm(un);
+ } else {
+ wrt = st_is_t10_worm(un);
+ }
+ break;
+
+ default:
+ wrt = ERROR;
+ break;
+ }
+
+ /*
+ * If any of the above failed try the t10 standard method.
+ */
+ if (wrt == ERROR) {
+ wrt = st_is_t10_worm(un);
+ }
+
+ /*
+ * Unknown method for detecting WORM media.
+ */
+ if (wrt == ERROR) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "Unknown method for WORM media detection\n");
+ wrt = RDWR;
+ un->un_dp->options &= ~ST_WORMABLE;
+ }
+
+ return (wrt);
+}
+
+static int
+st_read_attributes(struct scsi_tape *un, uint16_t attribute, caddr_t buf,
+ size_t size)
+{
+ uchar_t cdb[CDB_GROUP4];
+ struct uscsi_cmd *cmd;
+ int result;
+
+ cdb[0] = SCMD_READ_ATTRIBUTE;
+ cdb[1] = 0;
+ cdb[2] = 0;
+ cdb[3] = 0;
+ cdb[4] = 0;
+ cdb[5] = 0;
+ cdb[6] = 0;
+ cdb[7] = 0;
+ cdb[8] = (uchar_t)(attribute >> 8);
+ cdb[9] = (uchar_t)(attribute);
+ cdb[10] = (uchar_t)(size >> 24);
+ cdb[11] = (uchar_t)(size >> 16);
+ cdb[12] = (uchar_t)(size >> 8);
+ cdb[13] = (uchar_t)(size);
+ cdb[14] = 0;
+ cdb[15] = 0;
+
+ cmd = kmem_zalloc(sizeof (struct uscsi_cmd), KM_SLEEP);
+
+ cmd->uscsi_flags = USCSI_READ | USCSI_DIAGNOSE;
+ cmd->uscsi_timeout = un->un_dp->non_motion_timeout;
+ cmd->uscsi_cdb = (caddr_t)&cdb[0];
+ cmd->uscsi_bufaddr = (caddr_t)buf;
+ cmd->uscsi_buflen = size;
+ cmd->uscsi_cdblen = sizeof (cdb);
+
+ result = st_ioctl_cmd(un->un_dev, cmd,
+ UIO_SYSSPACE, UIO_SYSSPACE, UIO_SYSSPACE);
+
+ if (result != 0 || cmd->uscsi_status != 0) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "st_read_attribute failed: result %d status %d\n",
+ result, cmd->uscsi_status);
+ if (result == 0) {
+ result = EIO;
+ }
+ }
+
+ kmem_free(cmd, sizeof (cdb));
+ return (result);
+}
+
+static int
+st_get_special_inquiry(struct scsi_tape *un, uchar_t size, caddr_t dest,
+ uchar_t page)
+{
+ char cdb[CDB_GROUP0];
+ struct scsi_extended_sense *sense;
+ struct uscsi_cmd *cmd;
+ int result;
+
+ cdb[0] = SCMD_INQUIRY;
+ cdb[1] = page ? 1 : 0;
+ cdb[2] = page;
+ cdb[3] = 0;
+ cdb[4] = size;
+ cdb[5] = 0;
+
+ cmd = kmem_zalloc(sizeof (struct uscsi_cmd), KM_SLEEP);
+ sense = kmem_alloc(sizeof (struct scsi_extended_sense), KM_SLEEP);
+
+ cmd->uscsi_flags = USCSI_READ | USCSI_RQENABLE;
+ cmd->uscsi_timeout = un->un_dp->non_motion_timeout;
+ cmd->uscsi_cdb = &cdb[0];
+ cmd->uscsi_bufaddr = dest;
+ cmd->uscsi_buflen = size;
+ cmd->uscsi_cdblen = CDB_GROUP0;
+ cmd->uscsi_rqlen = sizeof (struct scsi_extended_sense);
+ cmd->uscsi_rqbuf = (caddr_t)sense;
+
+ result = st_ioctl_cmd(un->un_dev, cmd,
+ UIO_SYSSPACE, UIO_SYSSPACE, UIO_SYSSPACE);
+
+ if (result != 0 || cmd->uscsi_status != 0) {
+ ST_DEBUG2(ST_DEVINFO, st_label, SCSI_DEBUG,
+ "st_get_special_inquiry() failed for page %x", page);
+ if (result == 0) {
+ result = EIO;
+ }
+ }
+
+ kmem_free(sense, sizeof (struct scsi_extended_sense));
+ kmem_free(cmd, sizeof (struct uscsi_cmd));
+
+ return (result);
+}
+
+
#if defined(__i386) || defined(__amd64)
/*
diff --git a/usr/src/uts/common/io/scsi/targets/st_conf.c b/usr/src/uts/common/io/scsi/targets/st_conf.c
index f6b9051a29..55420416fa 100644
--- a/usr/src/uts/common/io/scsi/targets/st_conf.c
+++ b/usr/src/uts/common/io/scsi/targets/st_conf.c
@@ -1119,15 +1119,16 @@ const struct st_drivetype st_drivetypes[] =
MT_LTO, /* .type Numeric type (cf. mtio.h) */
0, /* .bsize Block size (0 = variable) */
/* .options Drive option flags: */
- ST_VARIABLE | /* 00001 Supports variable length */
- ST_BSF | /* 00008 Supports SPACE block fwd */
- ST_BSR | /* 00010 Supports SPACE block rev */
- ST_KNOWS_EOD | /* 00200 Recognizes end-of-data */
- ST_UNLOADABLE | /* 00400 Driver can be unloaded */
- ST_NO_RECSIZE_LIMIT | /* 08000 Supports blocks > 64KB */
- ST_MODE_SEL_COMP, /* 10000 Mode select compression */
- /* ----- */
- /* 18619 */
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_KNOWS_EOD | /* 0000200 Recognizes end-of-data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 Mode select compression */
+ ST_WORMABLE, /* 1000000 Drive is WORM capable */
+ /* ------- */
+ /* 1018619 */
-1, /* .max_rretries [Note 3] */
-1, /* .max_wretries [Note 3] */
{0x42, 0x42, 0x44, 0x44}, /* .densities Density codes [Note 1] */
@@ -1358,15 +1359,16 @@ const struct st_drivetype st_drivetypes[] =
ST_TYPE_DLT, /* .type Numeric type (cf. mtio.h) */
0, /* .bsize Block size (0 = variable) */
/* .options Drive option flags: */
- ST_VARIABLE | /* 00001 Supports variable length */
- ST_BSF | /* 00008 Supports SPACE block fwd */
- ST_BSR | /* 00010 Supports SPACE block rev */
- ST_KNOWS_EOD | /* 00200 Recognizes end-of-data */
- ST_UNLOADABLE | /* 00400 Driver can be unloaded */
- ST_NO_RECSIZE_LIMIT | /* 08000 Supports blocks > 64KB */
- ST_MODE_SEL_COMP, /* 10000 Uses Mode select Compress */
- /* -------- */
- /* 00018619 */
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_KNOWS_EOD | /* 0000200 Recognizes end-of-data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 Uses Mode select Compress */
+ ST_WORMABLE, /* 1000000 Is capable of WORM */
+ /* ------- */
+ /* 1018619 */
-1, /* .max_rretries [Note 3] */
-1, /* .max_wretries [Note 3] */
{0x4a, 0x4a, 0x4a, 0x4a}, /* .densities [Note 1] */
@@ -1620,16 +1622,17 @@ const struct st_drivetype st_drivetypes[] =
ST_TYPE_DLT, /* .type Numeric type (cf. mtio.h) */
0, /* .bsize Block size (0 = variable) */
/* .options Drive option flags: */
- ST_VARIABLE | /* 000001 Supports variable length */
- ST_BSF | /* 000008 Supports SPACE block fwd */
- ST_BSR | /* 000010 Supports SPACE block rev */
- ST_KNOWS_EOD | /* 000200 Recognizes end-of-data */
- ST_UNLOADABLE | /* 000400 Driver can be unloaded */
- ST_NO_RECSIZE_LIMIT | /* 008000 Supports blocks > 64KB */
- ST_MODE_SEL_COMP | /* 010000 [Note 1] */
- ST_KNOWS_MEDIA, /* 800000 Media detrmines density */
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_KNOWS_EOD | /* 0000200 Recognizes end-of-data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 [Note 1] */
+ ST_KNOWS_MEDIA | /* 0800000 Media detrmines density */
+ ST_WORMABLE, /* 1000000 Supports WORM */
/* ----- */
- /* 818619 */
+ /* 1818619 */
-1, /* .max_rretries Not used any more. */
-1, /* .max_wretries Not used any more. */
{0x49, 0x4a, 0x4b, 0x4b}, /* .densities Density codes [Note 1] */
@@ -1889,16 +1892,17 @@ const struct st_drivetype st_drivetypes[] =
ST_TYPE_STK9840, /* .type Numeric type (cf. mtio.h)*/
0, /* .bsize Block size (0 = variable)*/
/* .options Drive option flags: */
- ST_VARIABLE | /* 00001 Supports variable length */
- ST_BSF | /* 00008 Supports SPACE block fwd */
- ST_BSR | /* 00010 Supports SPACE block rev */
- ST_AUTODEN_OVERRIDE | /* 00040 Autodensity override flag*/
- ST_KNOWS_EOD | /* 00200 Recognizes end-of-data */
- ST_UNLOADABLE | /* 00400 Driver can be unloaded */
- ST_NO_RECSIZE_LIMIT | /* 08000 Supports blocks > 64KB */
- ST_MODE_SEL_COMP, /* 10000 [Note 1] */
- /* ----- */
- /* 18659 */
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_AUTODEN_OVERRIDE | /* 0000040 Autodensity override flag*/
+ ST_KNOWS_EOD | /* 0000200 Recognizes end-of-data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 [Note 1] */
+ ST_WORMABLE, /* 1000000 Supports WORM */
+ /* ------- */
+ /* 1018659 */
-1, /* .max_rretries [Note 4] */
-1, /* .max_wretries [Note 4] */
{0x4A,0x4A,0x4A,0x4A}, /* .densities Density codes [Note 2] */
@@ -1937,15 +1941,16 @@ const struct st_drivetype st_drivetypes[] =
ST_TYPE_STK9840, /* .type Numeric type (cf. mtio.h)*/
0, /* .bsize Block size (0 = variable)*/
/* .options Drive option flags: */
- ST_VARIABLE | /* 00001 Supports variable length */
- ST_BSF | /* 00008 Supports SPACE block fwd */
- ST_BSR | /* 00010 Supports SPACE block rev */
- ST_KNOWS_EOD | /* 00200 Recognizes end-of-data */
- ST_UNLOADABLE | /* 00400 Driver can be unloaded */
- ST_NO_RECSIZE_LIMIT | /* 08000 Supports blocks > 64KB */
- ST_MODE_SEL_COMP, /* 10000 [Note 1] */
- /* ----- */
- /* 18619 */
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_KNOWS_EOD | /* 0000200 Recognizes end-of-data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 [Note 1] */
+ ST_WORMABLE, /* 1000000 Supports WORM */
+ /* ------- */
+ /* 1018619 */
-1, /* .max_rretries [Note 4] */
-1, /* .max_wretries [Note 4] */
{0x45,0x45,0x45,0x45}, /* .densities Density codes [Note 2] */
@@ -1983,15 +1988,16 @@ const struct st_drivetype st_drivetypes[] =
ST_TYPE_STK9840, /* .type Numeric type (cf. mtio.h)*/
0, /* .bsize Block size (0 = variable)*/
/* .options Drive option flags: */
- ST_VARIABLE | /* 00001 Supports variable length */
- ST_BSF | /* 00008 Supports SPACE block fwd */
- ST_BSR | /* 00010 Supports SPACE block rev */
- ST_KNOWS_EOD | /* 00200 Recognizes end-of-data */
- ST_UNLOADABLE | /* 00400 Driver can be unloaded */
- ST_NO_RECSIZE_LIMIT | /* 08000 Supports blocks > 64KB */
- ST_MODE_SEL_COMP, /* 10000 [Note 1] */
- /* ----- */
- /* 18619 */
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_KNOWS_EOD | /* 0000200 Recognizes end-of-data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 [Note 1] */
+ ST_WORMABLE, /* 1000000 Supports WORM */
+ /* ------- */
+ /* 1018619 */
-1, /* .max_rretries [Note 4] */
-1, /* .max_wretries [Note 4] */
{0x42,0x42,0x42,0x42}, /* .densities Density codes [Note 2] */
@@ -2025,16 +2031,17 @@ const struct st_drivetype st_drivetypes[] =
ST_TYPE_STK9840, /* .type Numeric type (cf. mtio.h) */
0, /* .bsize Block size (0 = variable) */
/* .options Drive option flags: */
- ST_VARIABLE | /* 00001 Supports variable length */
- ST_BSF | /* 00008 Supports SPACE block fwd */
- ST_BSR | /* 00010 Supports SPACE block rev */
- ST_AUTODEN_OVERRIDE | /* 00040 Autodensity override flag */
- ST_KNOWS_EOD | /* 00200 Recognizes end-of-data */
- ST_UNLOADABLE | /* 00400 Driver can be unloaded */
- ST_NO_RECSIZE_LIMIT | /* 08000 Supports blocks > 64KB */
- ST_MODE_SEL_COMP, /* 10000 [Note 1] */
- /* ----- */
- /* 18659 */
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_AUTODEN_OVERRIDE | /* 0000040 Autodensity override flag */
+ ST_KNOWS_EOD | /* 0000200 Recognizes end-of-data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 [Note 1] */
+ ST_WORMABLE, /* 1000000 Supports WORM */
+ /* ------- */
+ /* 1018659 */
-1, /* .max_rretries [Note 4] */
-1, /* .max_wretries [Note 4] */
{0x44,0x44,0x44,0x44}, /* .densities Density codes [Note 2] */
@@ -2068,15 +2075,16 @@ const struct st_drivetype st_drivetypes[] =
ST_TYPE_STK9840, /* .type Numeric type (cf. mtio.h)*/
0, /* .bsize Block size (0 = variable)*/
/* .options Drive option flags: */
- ST_VARIABLE | /* 00001 Supports variable length */
- ST_BSF | /* 00008 Supports SPACE block fwd */
- ST_BSR | /* 00010 Supports SPACE block rev */
- ST_KNOWS_EOD | /* 00200 Recognizes end-of-data */
- ST_UNLOADABLE | /* 00400 Driver can be unloaded */
- ST_NO_RECSIZE_LIMIT | /* 08000 Supports blocks > 64KB */
- ST_MODE_SEL_COMP, /* 10000 [Note 1] */
- /* ----- */
- /* 18619 */
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_KNOWS_EOD | /* 0000200 Recognizes end-of-data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 [Note 1] */
+ ST_WORMABLE, /* 1000000 Supports WORM */
+ /* ------- */
+ /* 1018619 */
-1, /* .max_rretries [Note 4] */
-1, /* .max_wretries [Note 4] */
{0x43,0x43,0x43,0x43}, /* .densities Density codes [Note 2] */
@@ -2116,15 +2124,16 @@ const struct st_drivetype st_drivetypes[] =
ST_TYPE_STK9840, /* .type Numeric type (cf. mtio.h)*/
0, /* .bsize Block size (0 = variable)*/
/* .options Drive option flags: */
- ST_VARIABLE | /* 00001 Supports variable length */
- ST_BSF | /* 00008 Supports SPACE block fwd */
- ST_BSR | /* 00010 Supports SPACE block rev */
- ST_KNOWS_EOD | /* 00200 Recognizes end-of-data */
- ST_UNLOADABLE | /* 00400 Driver can be unloaded */
- ST_NO_RECSIZE_LIMIT | /* 08000 Supports blocks > 64KB */
- ST_MODE_SEL_COMP, /* 10000 [Note 1] */
- /* ----- */
- /* 18619 */
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_KNOWS_EOD | /* 0000200 Recognizes end-of-data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 [Note 1] */
+ ST_WORMABLE, /* 1000000 Supports WORM */
+ /* ------- */
+ /* 1018619 */
10, /* .max_rretries [Note 4] */
10, /* .max_wretries [Note 4] */
{0x00, 0x00, 0x00, 0x00}, /* .densities Density codes [Note 2] */
@@ -2180,6 +2189,155 @@ const struct st_drivetype st_drivetypes[] =
},
/*
+ * Sony SAIT
+ *
+ * Only looking at part of the product ID so it will match SDZ-100 and
+ * SDZ-130. One is SCSI other is Fibre but same configuration otherwise.
+ *
+ */
+ { /* Structure member Description */
+ /* ---------------- ----------- */
+ "Sony Super AIT", /* .name Display ("pretty") name */
+ 13, /* .length Length of next item... */
+ "SONY SDZ-1*", /* .vid Vendor-product ID string */
+ ST_TYPE_AIT, /* .type Numeric type (cf. mtio.h) */
+ 0,
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_AUTODEN_OVERRIDE | /* 0000040 Suports only one density */
+ ST_KNOWS_EOD | /* 0000200 Knows End Of Data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 mode select compression */
+ ST_WORMABLE, /* 1000000 Drive is WORM capable */
+ /* ------- */
+ /* 1018659 */
+ -1, /* .max_rretries Not used */
+ -1, /* .max_wretries Not used */
+ {0x40, 0x40, 0x40, 0x40}, /* .densities Density codes [Note 1] */
+ MT_DENSITY4, /* .default_density (.densities[x]) */
+ {0, 0, 0, 0}, /* .speeds Speed codes [Note 2] */
+ 0, /* .non_motion_timeout Nothing special */
+ 0, /* .io_timeout Four Nothing Special */
+ 0, /* .rewind_timeout Nothing Special */
+ 0, /* .space_timeout Nothing Special */
+ 0, /* .load_timeout Nothing Special */
+ 0, /* .unload_timeout Nothing Special */
+ 0, /* .erase_timeout Six hours */
+ },
+
+ /*
+ * Sony SDX-420
+ * This drive is listed before the more generic AIT drives becouse it runs
+ * only in fixed block mode. It also responds to READ BLOCK LIMITS which
+ * leads st to beleive its a variable block capable but it will fail any
+ * i/o that doesn't have the fix bit set in the CDB.
+ */
+ { /* Structure member Description */
+ /* ---------------- ----------- */
+ "Sony AIT II", /* .name Display ("pretty") name */
+ 15, /* .length Length of next item... */
+ "SONY SDX-420*", /* .vid Vendor-product ID string */
+ ST_TYPE_AIT, /* .type Numeric type (cf. mtio.h) */
+ 512,
+ ST_BSF | /* 00008 Supports SPACE block fwd */
+ ST_BSR | /* 00010 Supports SPACE block rev */
+ ST_AUTODEN_OVERRIDE | /* 00040 One density code */
+ ST_KNOWS_EOD | /* 00200 Knows End Of Data */
+ ST_UNLOADABLE | /* 00400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 08000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP, /* 10000 mode select compression */
+ /* ----- */
+ /* 18658 */
+ -1, /* .max_rretries Not used */
+ -1, /* .max_wretries Not used */
+ {0x30, 0x30, 0x30, 0x30}, /* .densities Density codes [Note 1] */
+ MT_DENSITY4, /* .default_density (.densities[x]) */
+ {0, 0, 0, 0}, /* .speeds Speed codes [Note 2] */
+ 0, /* .non_motion_timeout Nothing special */
+ 0, /* .io_timeout Four Nothing Special */
+ 0, /* .rewind_timeout Nothing Special */
+ 0, /* .space_timeout Nothing Special */
+ 0, /* .load_timeout Nothing Special */
+ 0, /* .unload_timeout Nothing Special */
+ 0, /* .erase_timeout Six hours */
+ },
+
+ /*
+ * Sony SDX-520
+ * This drive is listed before the more generic AIT drives becouse it runs
+ * only in fixed block mode. It also responds to READ BLOCK LIMITS which
+ * leads st to beleive its a variable block capable but it will fail any
+ * i/o that doesn't have the fix bit set in the CDB.
+ */
+ { /* Structure member Description */
+ /* ---------------- ----------- */
+ "Sony AIT II", /* .name Display ("pretty") name */
+ 15, /* .length Length of next item... */
+ "SONY SDX-520*", /* .vid Vendor-product ID string */
+ ST_TYPE_AIT, /* .type Numeric type (cf. mtio.h) */
+ 512,
+ ST_BSF | /* 00008 Supports SPACE block fwd */
+ ST_BSR | /* 00010 Supports SPACE block rev */
+ ST_AUTODEN_OVERRIDE | /* 00040 One density code */
+ ST_KNOWS_EOD | /* 00200 Knows End Of Data */
+ ST_UNLOADABLE | /* 00400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 08000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP, /* 10000 mode select compression */
+ /* ----- */
+ /* 18658 */
+ -1, /* .max_rretries Not used */
+ -1, /* .max_wretries Not used */
+ {0x30, 0x30, 0x30, 0x30}, /* .densities Density codes [Note 1] */
+ MT_DENSITY4, /* .default_density (.densities[x]) */
+ {0, 0, 0, 0}, /* .speeds Speed codes [Note 2] */
+ 0, /* .non_motion_timeout Nothing special */
+ 0, /* .io_timeout Four Nothing Special */
+ 0, /* .rewind_timeout Nothing Special */
+ 0, /* .space_timeout Nothing Special */
+ 0, /* .load_timeout Nothing Special */
+ 0, /* .unload_timeout Nothing Special */
+ 0, /* .erase_timeout Six hours */
+ },
+
+ /* Sony generic AIT
+ *
+ *
+ */
+ { /* Structure member Description */
+ /* ---------------- ----------- */
+ "Sony AIT", /* .name Display ("pretty") name */
+ 12, /* .length Length of next item... */
+ "SONY SDX-*", /* .vid Vendor-product ID string */
+ ST_TYPE_AIT, /* .type Numeric type (cf. mtio.h) */
+ 0,
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_AUTODEN_OVERRIDE | /* 0000040 One density code */
+ ST_KNOWS_EOD | /* 0000200 Knows End Of Data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 mode select compression */
+ ST_WORMABLE, /* 1000000 Drive is WORM capable */
+ /* ------- */
+ /* 1018659 */
+ -1, /* .max_rretries Not used */
+ -1, /* .max_wretries Not used */
+ {0x30, 0x30, 0x30, 0x30}, /* .densities Density codes [Note 1] */
+ MT_DENSITY4, /* .default_density (.densities[x]) */
+ {0, 0, 0, 0}, /* .speeds Speed codes [Note 2] */
+ 0, /* .non_motion_timeout Nothing special */
+ 0, /* .io_timeout Four Nothing Special */
+ 0, /* .rewind_timeout Nothing Special */
+ 0, /* .space_timeout Nothing Special */
+ 0, /* .load_timeout Nothing Special */
+ 0, /* .unload_timeout Nothing Special */
+ 0, /* .erase_timeout Six hours */
+ },
+
+ /*
* Sun DLT7000
*
* NOTES
@@ -2762,16 +2920,17 @@ const struct st_drivetype st_drivetypes[] =
MT_LTO, /* .type Numeric type (cf. mtio.h) */
0, /* .bsize Block size (0 = variable) */
/* .options Drive option flags: */
- ST_VARIABLE | /* 000001 Supports variable length */
- ST_BSF | /* 000008 Supports SPACE block fwd */
- ST_BSR | /* 000010 Supports SPACE block rev */
- ST_KNOWS_EOD | /* 000200 Recognizes end-of-data */
- ST_UNLOADABLE | /* 000400 Driver can be unloaded */
- ST_NO_RECSIZE_LIMIT | /* 008000 Supports blocks > 64KB */
- ST_MODE_SEL_COMP | /* 010000 [Note 1] */
- ST_KNOWS_MEDIA, /* 800000 Media detrmines density */
- /* ----- */
- /* 818619 */
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_KNOWS_EOD | /* 0000200 Recognizes end-of-data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 [Note 1] */
+ ST_KNOWS_MEDIA | /* 0800000 Media detrmines density */
+ ST_WORMABLE, /* 1000000 Is WORM capable */
+ /* ------- */
+ /* 1818619 */
-1, /* .max_rretries Not used any more. */
-1, /* .max_wretries Not used any more. */
{0x40, 0x42, 0x44, 0x44}, /* .densities Density codes [Note 1] */
@@ -2803,16 +2962,17 @@ const struct st_drivetype st_drivetypes[] =
MT_LTO, /* .type Numeric type (cf. mtio.h) */
0, /* .bsize Block size (0 = variable) */
/* .options Drive option flags: */
- ST_VARIABLE | /* 000001 Supports variable length */
- ST_BSF | /* 000008 Supports SPACE block fwd */
- ST_BSR | /* 000010 Supports SPACE block rev */
- ST_KNOWS_EOD | /* 000200 Recognizes end-of-data */
- ST_UNLOADABLE | /* 000400 Driver can be unloaded */
- ST_NO_RECSIZE_LIMIT | /* 008000 Supports blocks > 64KB */
- ST_MODE_SEL_COMP | /* 010000 [Note 1] */
- ST_KNOWS_MEDIA, /* 800000 Media detrmines density */
- /* ----- */
- /* 818619 */
+ ST_VARIABLE | /* 0000001 Supports variable length */
+ ST_BSF | /* 0000008 Supports SPACE block fwd */
+ ST_BSR | /* 0000010 Supports SPACE block rev */
+ ST_KNOWS_EOD | /* 0000200 Recognizes end-of-data */
+ ST_UNLOADABLE | /* 0000400 Driver can be unloaded */
+ ST_NO_RECSIZE_LIMIT | /* 0008000 Supports blocks > 64KB */
+ ST_MODE_SEL_COMP | /* 0010000 [Note 1] */
+ ST_KNOWS_MEDIA | /* 0800000 Media detrmines density */
+ ST_WORMABLE, /* 1000000 Is WORM capable */
+ /* ------- */
+ /* 1818619 */
-1, /* .max_rretries Not used any more. */
-1, /* .max_wretries Not used any more. */
{0x40, 0x42, 0x44, 0x44}, /* .densities Density codes [Note 1] */
diff --git a/usr/src/uts/common/sys/mtio.h b/usr/src/uts/common/sys/mtio.h
index 18b4e9fe4b..ad8845c2b2 100644
--- a/usr/src/uts/common/sys/mtio.h
+++ b/usr/src/uts/common/sys/mtio.h
@@ -162,6 +162,7 @@ struct mtdrivetype_request32 {
#define MTF_TAPE_HEAD_DIRTY 0x08
#define MTF_TAPE_CLN_SUPPORTED 0x10
+#define MTF_WORM_MEDIA 0x20
/*
* Constants for mt_type byte (these are somewhat obsolete)
@@ -225,6 +226,7 @@ struct mtdrivetype_request32 {
#define MT_ISSTK9840 0x39 /* sun: STK 9840, 9940, 9840B */
#define MT_ISBMDLT1 0x3a /* sun: Benchmark DLT1 */
#define MT_LTO 0x3b /* sun: LTO,s by Hp, Seagate, IBM .. */
+#define MT_ISAIT 0x3c /* Sony: AIT I II III and SAIT */
/*
* Device table structure and data for looking tape name from
diff --git a/usr/src/uts/common/sys/scsi/generic/commands.h b/usr/src/uts/common/sys/scsi/generic/commands.h
index 1829959a93..d4b17c18da 100644
--- a/usr/src/uts/common/sys/scsi/generic/commands.h
+++ b/usr/src/uts/common/sys/scsi/generic/commands.h
@@ -319,6 +319,12 @@ extern "C" {
#define SSVC_ACTION_WRITE_LONG_G4 0x11
/*
+ * Group 4 Commands, Sequential Access Devics
+ */
+#define SCMD_READ_ATTRIBUTE 0x8c
+#define SCMD_WRITE_ATTRIBUTE 0x8d
+
+/*
* Define for Group 5 command.
*/
#define SCMD_GROUP5 0xA0
@@ -406,6 +412,8 @@ extern "C" {
/* 0x83 */ SCMD_EXTENDED_COPY, "extended_copy", \
/* 0x88 */ SCMD_READ_G4, "read(16)", \
/* 0x8a */ SCMD_WRITE_G4, "write(16)", \
+/* 0x8c */ SCMD_READ_ATTRIBUTE, "read_attribute", \
+/* 0x8d */ SCMD_WRITE_ATTRIBUTE, "write_attribute", \
/* 0xa0 */ SCMD_REPORT_LUNS, "report_luns", \
/* 0xa8 */ SCMD_READ_G5, "read(12)", \
/* 0xaa */ SCMD_WRITE_G5, "write(12)", \
diff --git a/usr/src/uts/common/sys/scsi/targets/stdef.h b/usr/src/uts/common/sys/scsi/targets/stdef.h
index 5eb4958c67..c22297cc80 100644
--- a/usr/src/uts/common/sys/scsi/targets/stdef.h
+++ b/usr/src/uts/common/sys/scsi/targets/stdef.h
@@ -94,7 +94,8 @@ extern "C" {
#define ST_TYPE_STK9840 MT_ISSTK9840 /* StorageTek 9840, 9940, 9840B */
#define ST_TYPE_BMDLT1 MT_ISBMDLT1 /* Benchmark DTL1 */
#define ST_TYPE_LTO MT_LTO /* sun: LTO's by HP, Seagate, IBM.. */
-#define ST_LAST_TYPE ST_TYPE_LTO /* Add new above type and change this */
+#define ST_TYPE_AIT MT_ISAIT /* Sony AIT I, II, III and SAIT */
+#define ST_LAST_TYPE ST_TYPE_AIT /* Add new above type and change this */
/* Internal flags */
@@ -232,6 +233,10 @@ extern "C" {
#define ST_KNOWS_MEDIA 0x800000 /* Use configured media type */
/* detected to select correct */
/* density code. */
+#define ST_WORMABLE 0x1000000
+ /* Drive is capable of doing */
+ /* Write Appends only at EOM */
+ /* if WORM media type is loaded */
#define ST_CLN_TYPE_1 0x10000000 /* When this flag is set, */
/* the tape drive provides the */
/* clean bit information in */
@@ -255,7 +260,7 @@ extern "C" {
ST_NO_RECSIZE_LIMIT | ST_MODE_SEL_COMP | ST_NO_RESERVE_RELEASE |\
ST_READ_IGNORE_ILI | ST_READ_IGNORE_EOFS | ST_SHORT_FILEMARKS |\
ST_EJECT_ON_CHANGER_FAILURE | ST_RETRY_ON_RECOVERED_DEFERRED_ERROR |\
- ST_CLN_TYPE_1 | ST_CLN_TYPE_2 | ST_CLN_TYPE_3)
+ ST_WORMABLE | ST_CLN_TYPE_1 | ST_CLN_TYPE_2 | ST_CLN_TYPE_3)
#define NDENSITIES MT_NDENSITIES
#define NSPEEDS MT_NSPEEDS
@@ -278,10 +283,68 @@ extern "C" {
/*
* Tape Alert Flag definitions
*/
-#define CLEANING_MEDIA 11
-#define CLEAN_NOW 20
-#define CLEAN_PERIODIC 21
-#define CLEAN_FOR_ERRORS 24
+typedef enum {
+ TAF_READ_WARN = 0x01,
+ TAF_WRITE_WARN = 0x02,
+ TAF_HARD_ERR = 0x03,
+ TAF_MEDIA_ERR = 0x04,
+ TAF_READ_FAIL = 0x05,
+ TAF_WRITE_FAIL = 0x06,
+ TAF_MEDIA_LIFE = 0x07,
+ TAF_MEDIA_NOT_DATA_GRADE = 0x08,
+ TAF_WRITE_PROTECTED = 0x09,
+ TAF_NO_MEDIA_REMOVE = 0x0A,
+ TAF_CLEANING_MEDIA = 0x0B,
+ TAF_UNSUPPERTED_FORMAT = 0x0C,
+ TAF_RECOVERED_TAPE_BREAK = 0x0D,
+ TAF_TAPE_BREAK_FAUL = 0x0E,
+ TAF_CART_MEM_FAIL = 0x0F,
+ TAF_FORCED_EJECT = 0x10,
+ TAF_READ_ONLY_FORMAT = 0x11,
+ TAF_TAPE_DIR_CORRUPT = 0x12,
+ TAF_NEARING_MEDIA_LIFE = 0x13,
+ TAF_CLEAN_NOW = 0x14,
+ TAF_CLEAN_PERIODIC = 0x15,
+ TAF_EXP_CLEAN_CART = 0x16,
+ TAF_INVALID_CLEAN_MEDIA = 0x17,
+ TAF_RETENSION_REQUEST = 0x18,
+ TAF_DUAL_PORT_INTERFACE_ERR = 0x19,
+ TAF_COOLING_FAN_FAIL = 0x1A,
+ TAF_POWER_SUPPLY_FAIL = 0x1B,
+ TAF_POWER_CONSUMPTION = 0x1C,
+ TAF_DRIVE_MAINT_REQUEST = 0x1D,
+ TAF_HARDWARE_A = 0x1E,
+ TAF_HARDWARE_B = 0x1F,
+ TAF_INTERFACE = 0x20,
+ TAF_EJECT_MEDIA = 0x21,
+ TAF_DOWNLOAD_FAIL = 0x22,
+ TAF_DRIVE_HUMIDITY = 0x23,
+ TAF_DRIVE_TEMP = 0x24,
+ TAF_DRIVE_VOLTAGE = 0x25,
+ TAF_PREDICTIVE_FAIL = 0x26,
+ TAF_DIAG_REQUIRED = 0x27,
+ TAF_LOADER_HDWR_A = 0x28,
+ TAF_LOADER_STRAY_TAPE = 0x29,
+ TAF_LOADER_HDWR_B = 0x2A,
+ TAF_LOADER_DOOR = 0x2B,
+ TAF_LOADER_HDWR_C = 0x2C,
+ TAF_LOADER_MAGAZINE = 0x2D,
+ TAF_LOADER_PREDICTIVE_FAIL = 0x2E,
+ TAF_LOST_STATISTICS = 0x32,
+ TAF_TAPE_DIR_CURRUPT_UNLOAD = 0x33,
+ TAF_TAPE_SYS_WRT_FAIL = 0x34,
+ TAF_TAPE_SYS_RD_FAIL = 0x35,
+ TAF_NO_START_OF_DATA = 0x36,
+ TAF_WORM_INTEGRITY = 0x3B,
+ TAF_WORM_OVRWRT_ATTEMPT = 0x3C
+}tape_alert_flags;
+
+/*
+ * For ST_TYPE_STK9840 drives only. STK drive doesn't support retension
+ * so they reuse TAF_RETENSION_REQUEST.
+ */
+#define CLEAN_FOR_ERRORS 0x18
+
#define TAPE_ALERT_SUPPORT_UNKNOWN 0x00
#define TAPE_ALERT_NOT_SUPPORTED 0x01
@@ -373,7 +436,7 @@ struct dev_mode_page {
#if defined(_BIT_FIELDS_LTOH)
uchar_t act_format: 5, /* active format */
caf: 1, /* Change Active Format */
- cap: 1, /* Change Active Partition */
+ cap: 1, /* Change Active Partition OBSOLETE */
: 1;
uchar_t act_partition; /* active partition */
uchar_t wrt_buf_full_ratio; /* write buffer full ratio */
@@ -381,14 +444,16 @@ struct dev_mode_page {
uchar_t wrt_delay_time_msb; /* write delay time MSB */
uchar_t wrt_delay_time_lsb; /* write delay time LSB */
uchar_t rew: 1, /* Report Early Warning */
- rbo: 1, /* Reverse Buffer Order */
+ robo: 1, /* Reverse Object Buffer Order */
socf: 2, /* Stop On Consecutive Filemarks */
avc: 1, /* Automatic Velocity Control */
- rsmk: 1, /* Report SetMarKs */
- bis: 1, /* Block Ids Supported */
- dbr: 1; /* Data Buffer Recovery */
- uchar_t gap_size;
- uchar_t : 3,
+ rsmk: 1, /* Report SetMarKs OBSOLETE */
+ lois: 1, /* Logical Object Identifiers Support */
+ obr: 1; /* Object Buffer Recovery */
+ uchar_t gap_size; /* OBSOLETE */
+ uchar_t bam: 1, /* Block Address Mode */
+ bmal: 1, /* Block Address Mode Lock */
+ swp: 1, /* Software Write Protection */
sew: 1, /* Sync data after Early Warning */
eeg: 1, /* Enable Early Waring */
eod_defined: 3;
@@ -396,11 +461,16 @@ struct dev_mode_page {
uchar_t buf_size_leot_mid;
uchar_t buf_size_leot_lsb;
uchar_t comp_alg; /* Compression Algorithm (enable) */
- uchar_t reservered;
+ uchar_t prmwp: 1, /* PeRManent Write Protect */
+ perswp: 1, /* persistant write protection */
+ asocwp: 1, /* associated write protect */
+ rew_on_rst: 2, /* rewind on reset */
+ oir: 1, /* Only If Reserved */
+ wtre: 2; /* Worm Tamper Read Enable */
#elif defined(_BIT_FIELDS_HTOL)
uchar_t : 1,
- cap: 1, /* Change Active Partition */
+ cap: 1, /* Change Active Partition OBSOLETE */
caf: 1, /* Change Active Format */
act_format: 5; /* active format */
uchar_t act_partition; /* active partition */
@@ -408,23 +478,30 @@ struct dev_mode_page {
uchar_t rd_buf_full_ratio; /* read buffer full ratio */
uchar_t wrt_delay_time_msb; /* write delay time MSB */
uchar_t wrt_delay_time_lsb; /* write delay time LSB */
- uchar_t dbr: 1, /* Data Buffer Recovery */
- bis: 1, /* Block Ids Supported */
- rsmk: 1, /* Report SetMarKs */
+ uchar_t obr: 1, /* Object Buffer Recovery */
+ lois: 1, /* Logical Object Identifiers Support */
+ rsmk: 1, /* Report SetMarKs OBSOLETE */
avc: 1, /* Automatic Velocity Control */
socf: 2, /* Stop On Consecutive Filemarks */
- rbo: 1, /* Reverse Buffer Order */
+ robo: 1, /* Reverse Object Buffer Order */
rew: 1; /* Report Early Warning */
- uchar_t gap_size;
+ uchar_t gap_size; /* OBSELETE */
uchar_t eod_defined: 3,
eeg: 1, /* Enable Early Waring */
sew: 1, /* Sync data after Early Warning */
- : 3;
+ swp: 1, /* Software Write Protection */
+ bmal: 1, /* Block Address Mode Lock */
+ bam: 1; /* Block Address Mode */
uchar_t buf_size_leot_msb; /* Buffer size after early warning */
uchar_t buf_size_leot_mid;
uchar_t buf_size_leot_lsb;
uchar_t comp_alg; /* Compression Algorithm (enable) */
- uchar_t reservered;
+ uchar_t wtre: 2, /* Worm Tamper Read Enable */
+ oir: 1, /* Only If Reserved */
+ rew_on_rst: 2, /* rewind on reset */
+ asocwp: 1, /* associated write protect */
+ perswp: 1, /* persistant write protection */
+ prmwp: 1; /* PeRManent Write Protect */
#endif
};
@@ -540,6 +617,35 @@ struct contig_mem {
#endif /* _KERNEL */
/*
+ * eof/eot/eom codes.
+ */
+
+typedef enum {
+ ST_NO_EOF, /* 0x00 */
+ ST_EOF_PENDING, /* 0x01 filemark pending */
+ ST_EOF, /* 0x02 at filemark */
+ ST_EOT_PENDING, /* 0x03 logical eot pending */
+ ST_EOT, /* 0x04 at logical eot */
+ ST_EOM, /* 0x05 at physical eot */
+ ST_WRITE_AFTER_EOM /* 0x06 flag for allowing writes after EOM */
+}media_st;
+
+#define IN_EOF(un) (un->un_eof == ST_EOF_PENDING || un->un_eof == ST_EOF)
+
+/*
+ * operation codes
+ */
+typedef enum {
+ ST_OP_NIL, /* 0 */
+ ST_OP_CTL, /* 1 */
+ ST_OP_READ, /* 2 */
+ ST_OP_WRITE, /* 3 */
+ ST_OP_WEOF /* 4 */
+}optype;
+
+typedef enum { RDWR, RDONLY, WORM, RDWORM, ERROR } writablity;
+
+/*
* Private info for scsi tapes. Pointed to by the un_private pointer
* of one of the SCSI_DEVICE chains.
*/
@@ -573,14 +679,14 @@ struct scsi_tape {
int un_pwr_mgmt; /* power management state */
uchar_t un_density_known; /* density is known */
uchar_t un_curdens; /* index into density table */
- uchar_t un_lastop; /* last I/O was: read/write/ctl */
- uchar_t un_eof; /* eof states */
+ optype un_lastop; /* last I/O was: read/write/ctl */
+ media_st un_eof; /* eof states */
uchar_t un_laststate; /* last state */
uchar_t un_state; /* current state */
uchar_t un_status; /* status from last sense */
uchar_t un_retry_ct; /* retry count */
uchar_t un_tran_retry_ct; /* transport retry count */
- uchar_t un_read_only; /* 1 == opened O_RDONLY */
+ writablity un_read_only; /* RDWR, RDONLY, WORM, RDWORM */
uchar_t un_test_append; /* check writing at end of tape */
uchar_t un_arq_enabled; /* auto request sense enabled */
uchar_t un_untagged_qing; /* hba has untagged quing */
@@ -632,6 +738,8 @@ struct scsi_tape {
uchar_t un_rqs_state; /* see define below */
caddr_t un_uscsi_rqs_buf; /* uscsi_rqs: buffer for RQS data */
uchar_t un_data_mod; /* Device required data mod */
+ writablity (*un_wormable) (struct scsi_tape *un); /* worm test fuct */
+ int un_max_cdb_sz; /* max cdb size to use */
#if defined(__i386) || defined(__amd64)
ddi_dma_handle_t un_contig_mem_hdl;
@@ -765,29 +873,8 @@ _NOTE(SCHEME_PROTECTS_DATA("save sharing",
#define ST_PWR_NORMAL 0
#define ST_PWR_SUSPENDED 1
-/*
- * operation codes
- */
-
-#define ST_OP_NIL 0
-#define ST_OP_CTL 1
-#define ST_OP_READ 2
-#define ST_OP_WRITE 3
-#define ST_OP_WEOF 4
-
-/*
- * eof/eot/eom codes.
- */
-#define ST_NO_EOF 0x00
-#define ST_EOF_PENDING 0x01 /* filemark pending */
-#define ST_EOF 0x02 /* at filemark */
-#define ST_EOT_PENDING 0x03 /* logical eot pending */
-#define ST_EOT 0x04 /* at logical eot */
-#define ST_EOM 0x05 /* at physical eot */
-#define ST_WRITE_AFTER_EOM 0x06 /* flag for allowing writes after EOM */
-#define IN_EOF(un) (un->un_eof == ST_EOF_PENDING || un->un_eof == ST_EOF)
/* un_rqs_state codes */