diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/mt/mt.c | 5 | ||||
-rw-r--r-- | usr/src/uts/common/io/scsi/impl/scsi_subr.c | 7 | ||||
-rw-r--r-- | usr/src/uts/common/io/scsi/targets/st.c | 762 | ||||
-rw-r--r-- | usr/src/uts/common/io/scsi/targets/st_conf.c | 366 | ||||
-rw-r--r-- | usr/src/uts/common/sys/mtio.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/sys/scsi/generic/commands.h | 8 | ||||
-rw-r--r-- | usr/src/uts/common/sys/scsi/targets/stdef.h | 179 |
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 */ |