summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authormcneal <none@none>2006-09-06 11:48:01 -0700
committermcneal <none@none>2006-09-06 11:48:01 -0700
commit8a16ae8f6efb5a6c02ab0aec860e229706335bb9 (patch)
tree257b3a9c1e0de2468606f25fc9e3aa1976b7fcec /usr/src
parent433eca90d1a0238667eea28ab4fda24793afcdc6 (diff)
downloadillumos-joyent-8a16ae8f6efb5a6c02ab0aec860e229706335bb9.tar.gz
6456456 target doesn't handle SCSI commands to invalid LU correctly.
6456465 Need to support optional SCSI command VERIFY for Microsoft
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c10
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_sam.c44
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c256
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_sbc.h11
-rw-r--r--usr/src/cmd/iscsi/iscsitgtd/t10_spc.h8
-rw-r--r--usr/src/uts/common/sys/scsi/generic/commands.h3
-rw-r--r--usr/src/uts/common/sys/scsi/impl/commands.h5
7 files changed, 302 insertions, 35 deletions
diff --git a/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c b/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c
index a2d119886a..f18c872074 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c
+++ b/usr/src/cmd/iscsi/iscsitgtd/iscsi_sess.c
@@ -327,8 +327,6 @@ sess_process(void *v)
cmd->c_scb_len, (transport_t)cmd,
&t10_cmd) == False) {
- queue_prt(s->s_mgmtq, Q_SESS_ERRS,
- "SES%x FAILED to create cmd", s->s_num);
/*
* If the command create failed, the T10 layer
* will attempt to create a sense buffer
@@ -337,12 +335,16 @@ sess_process(void *v)
* things are really bad and we need to just
* close the connection.
*/
- if (cmd->c_t10_cmd != NULL) {
+ if (t10_cmd != NULL) {
queue_message_set(
cmd->c_allegiance->c_dataq,
0, msg_cmd_cmplt, t10_cmd);
- } else
+ } else {
+ queue_prt(s->s_mgmtq, Q_SESS_ERRS,
+ "SES%x FAILED to create cmd",
+ s->s_num);
conn_state(cmd->c_allegiance, T11);
+ }
} else {
(void) pthread_mutex_lock(
&cmd->c_allegiance->c_mutex);
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c b/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c
index 24f2f52f2c..2f07b921d5 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_sam.c
@@ -71,7 +71,7 @@
/*
* Forward declarations
*/
-static t10_lu_impl_t *t10_find_lun(t10_targ_impl_t *t, int lun);
+static Boolean_t t10_find_lun(t10_targ_impl_t *t, int lun, t10_cmd_t *);
static void *lu_runner(void *v);
static Boolean_t t10_lu_initialize(t10_lu_common_t *lu, char *basedir);
static void *t10_aio_done(void *v);
@@ -353,11 +353,8 @@ t10_cmd_create(t10_targ_handle_t t, int lun_number, uint8_t *cdb,
cmd->c_trans_id = trans_id;
*cmdp = cmd;
- if ((cmd->c_lu = t10_find_lun((t10_targ_impl_t *)t, lun_number)) ==
- NULL) {
- spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
+ if (t10_find_lun((t10_targ_impl_t *)t, lun_number, cmd) == False)
goto error;
- }
(void) pthread_mutex_lock(&cmd->c_lu->l_cmd_mutex);
avl_add(&cmd->c_lu->l_cmds, (void *)cmd);
@@ -1095,8 +1092,8 @@ trans_params_area(t10_cmd_t *cmd)
* []----
*/
/*ARGSUSED*/
-static t10_lu_impl_t *
-t10_find_lun(t10_targ_impl_t *t, int lun)
+static Boolean_t
+t10_find_lun(t10_targ_impl_t *t, int lun, t10_cmd_t *cmd)
{
t10_lu_impl_t *l = NULL,
search;
@@ -1128,14 +1125,17 @@ t10_find_lun(t10_targ_impl_t *t, int lun)
* and there's fewer than 64 an array of pointers would be
* even faster than an AVL tree and not take up to much space.
*/
- return (l);
+ cmd->c_lu = l;
+ return (True);
}
/*
* First access for this I_T_L so we need to allocate space for it.
*/
- if ((l = calloc(1, sizeof (*l))) == NULL)
- return (NULL);
+ if ((l = calloc(1, sizeof (*l))) == NULL) {
+ spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
+ return (False);
+ }
/*
* Initialize the various local fields. Certain fields will not be
@@ -1163,6 +1163,9 @@ t10_find_lun(t10_targ_impl_t *t, int lun)
(void) pthread_mutex_lock(&lu_list_mutex);
if ((xml_fd = open(path, O_RDONLY)) < 0) {
(void) pthread_mutex_unlock(&lu_list_mutex);
+ spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
+ /* ---- ACCESS DENIED - INVALID LU IDENTIFIER ---- */
+ spc_sense_ascq(cmd, 0x20, 0x9);
goto error;
}
if ((r = (xmlTextReaderPtr)xmlReaderForFd(xml_fd, NULL, NULL,
@@ -1172,16 +1175,25 @@ t10_find_lun(t10_targ_impl_t *t, int lun)
break;
} else {
(void) pthread_mutex_unlock(&lu_list_mutex);
+ spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
goto error;
}
(void) close(xml_fd);
+ /*
+ * Set xml_fd back to -1 so that if an error occurs later we don't
+ * attempt to close a file descriptor that another thread might have
+ * opened.
+ */
+ xml_fd = -1;
+
xmlTextReaderClose(r);
xmlFreeTextReader(r);
r = NULL;
if (xml_find_value_str(n, XML_ELEMENT_GUID, &guid) == False) {
(void) pthread_mutex_unlock(&lu_list_mutex);
+ spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
goto error;
}
@@ -1189,24 +1201,29 @@ t10_find_lun(t10_targ_impl_t *t, int lun)
free(guid);
if (util_create_guid(&guid) == False) {
(void) pthread_mutex_unlock(&lu_list_mutex);
+ spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
goto error;
}
if ((n1 = xml_find_child(n, XML_ELEMENT_GUID)) == NULL) {
(void) pthread_mutex_unlock(&lu_list_mutex);
+ spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
goto error;
}
if (xml_update_value_str(n1, XML_ELEMENT_GUID, guid) == False) {
(void) pthread_mutex_unlock(&lu_list_mutex);
+ spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
goto error;
}
if (xml_dump2file(n, path) == False) {
(void) pthread_mutex_unlock(&lu_list_mutex);
+ spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
goto error;
}
}
if (xml_decode_bytes(guid, &lc.l_guid, &lc.l_guid_len) == False) {
(void) pthread_mutex_unlock(&lu_list_mutex);
+ spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
goto error;
}
@@ -1222,6 +1239,7 @@ t10_find_lun(t10_targ_impl_t *t, int lun)
*/
if ((common = calloc(1, sizeof (*common))) == NULL) {
(void) pthread_mutex_unlock(&lu_list_mutex);
+ spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
goto error;
}
@@ -1242,6 +1260,7 @@ t10_find_lun(t10_targ_impl_t *t, int lun)
"SAM%x FAILED to initialize LU %d",
t->s_targ_num, lun);
(void) pthread_mutex_unlock(&lu_list_mutex);
+ spc_sense_create(cmd, KEY_HARDWARE_ERROR, 0);
goto error;
}
@@ -1300,7 +1319,8 @@ t10_find_lun(t10_targ_impl_t *t, int lun)
free(guid);
xml_tree_free(n);
- return (l);
+ cmd->c_lu = l;
+ return (True);
error:
if (guid)
@@ -1319,7 +1339,7 @@ error:
free(lc.l_guid);
if (common)
free(common);
- return (NULL);
+ return (False);
}
static Boolean_t
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c b/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c
index 5fc39376d1..14c5d1dc5d 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.c
@@ -163,7 +163,6 @@ sbc_init_per(t10_lu_impl_t *itl)
itl->l_cmd = spc_cmd_offline;
itl->l_data = sbc_data;
itl->l_cmd_table = lba_table;
-
}
void
@@ -301,8 +300,10 @@ sbc_read(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
disk_params_t *d;
uchar_t addl_sense_len;
- if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL)
+ if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL) {
+ trans_send_complete(cmd, STATUS_BUSY);
return;
+ }
switch (u->scc_cmd) {
case SCMD_READ:
@@ -377,11 +378,6 @@ sbc_read(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
else
err_blkno = d->d_size;
- /*
- * XXX: What's SBC-2 say about ASC/ASCQ here. Solaris
- * doesn't care about these values when key is set
- * to KEY_ILLEGAL_REQUEST.
- */
if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
addl_sense_len = INFORMATION_SENSE_DESCR;
else
@@ -389,7 +385,7 @@ sbc_read(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, addl_sense_len);
spc_sense_info(cmd, err_blkno);
- spc_sense_ascq(cmd, 0x21, 0x00);
+ spc_sense_ascq(cmd, SPC_ASC_BLOCK_RANGE, SPC_ASCQ_BLOCK_RANGE);
trans_send_complete(cmd, STATUS_CHECK);
queue_prt(mgmtq, Q_STE_ERRS,
@@ -503,8 +499,10 @@ sbc_write(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
size_t max_out;
void *mmap_area;
- if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL)
+ if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL) {
+ trans_send_complete(cmd, STATUS_BUSY);
return;
+ }
/*LINTED*/
u = (union scsi_cdb *)cdb;
@@ -580,11 +578,6 @@ sbc_write(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
else
err_blkno = d->d_size;
- /*
- * XXX: What's SBC-2 say about ASC/ASCQ here. Solaris
- * doesn't care about these values when key is set
- * to KEY_ILLEGAL_REQUEST.
- */
if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
addl_sense_len = INFORMATION_SENSE_DESCR;
else
@@ -592,7 +585,7 @@ sbc_write(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, addl_sense_len);
spc_sense_info(cmd, err_blkno);
- spc_sense_ascq(cmd, 0x21, 0x00);
+ spc_sense_ascq(cmd, SPC_ASC_BLOCK_RANGE, SPC_ASCQ_BLOCK_RANGE);
trans_send_complete(cmd, STATUS_CHECK);
queue_prt(mgmtq, Q_STE_ERRS,
@@ -1288,6 +1281,233 @@ sbc_release(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
trans_send_complete(cmd, STATUS_GOOD);
}
+/*ARGSUSED*/
+static void
+sbc_verify(t10_cmd_t *cmd, uint8_t *cdb, size_t cdb_len)
+{
+ /*LINTED*/
+ union scsi_cdb *u = (union scsi_cdb *)cdb;
+ diskaddr_t addr;
+ uint32_t cnt,
+ chk_size;
+ uint64_t sz,
+ err_blkno;
+ Boolean_t bytchk;
+ char *chk_block;
+ disk_io_t *io;
+ disk_params_t *d;
+ uchar_t addl_sense_len;
+
+ if ((d = (disk_params_t *)T10_PARAMS_AREA(cmd)) == NULL) {
+ trans_send_complete(cmd, STATUS_BUSY);
+ return;
+ }
+
+ /*
+ * Check the common reserved bits here and check the CONTROL byte
+ * in each specific section for the different CDB sizes.
+ * NOTE: If the VRPROTECT is non-zero we're required by SBC-3
+ * to return an error since our emulation code doesn't have
+ * any protection information stored on the media that we can
+ * access.
+ */
+ if ((cdb[1] & ~(SBC_VRPROTECT_MASK|SBC_DPO|SBC_BYTCHK)) ||
+ (cdb[1] & SBC_VRPROTECT_MASK)) {
+ spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
+ spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
+ trans_send_complete(cmd, STATUS_CHECK);
+ return;
+ }
+
+ bytchk = cdb[1] & SBC_BYTCHK ? True : False;
+
+ switch (u->scc_cmd) {
+ case SCMD_VERIFY:
+ /*
+ * BYTE 6 of the VERIFY(10) contains bits:
+ * 0-4: Group number -- not supported must be zero
+ * 5-6: Reserved
+ * 7 : Restricted for MMC-4
+ */
+ if (cdb[6] || SAM_CONTROL_BYTE_RESERVED(cdb[9])) {
+ spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
+ spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
+ trans_send_complete(cmd, STATUS_CHECK);
+ return;
+ }
+ addr = (diskaddr_t)(uint32_t)GETG1ADDR(u);
+ cnt = GETG1COUNT(u);
+ break;
+
+ case SCMD_VERIFY_G4:
+ /*
+ * See VERIFY(10) above for definitions of what byte 14
+ * contains.
+ */
+ if (cdb[14] || SAM_CONTROL_BYTE_RESERVED(cdb[15])) {
+ spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
+ spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
+ trans_send_complete(cmd, STATUS_CHECK);
+ return;
+ }
+ addr = GETG4LONGADDR(u);
+ cnt = GETG4COUNT(u);
+ break;
+
+ case SCMD_VERIFY_G5:
+ /*
+ * See VERIFY(10) above for definitions of what byte 10
+ * contains.
+ */
+ if (cdb[10] || SAM_CONTROL_BYTE_RESERVED(cdb[11])) {
+ spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
+ spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
+ trans_send_complete(cmd, STATUS_CHECK);
+ return;
+ }
+ addr = (diskaddr_t)GETG5ADDR(u);
+ cnt = GETG5COUNT(u);
+ break;
+
+ default:
+ spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, 0);
+ spc_sense_ascq(cmd, SPC_ASC_INVALID_CDB, 0x00);
+ trans_send_complete(cmd, STATUS_CHECK);
+ return;
+ }
+
+ if ((addr + cnt) > d->d_size) {
+
+ if (addr > d->d_size)
+ err_blkno = addr;
+ else
+ err_blkno = d->d_size;
+
+ if (err_blkno > FIXED_SENSE_ADDL_INFO_LEN)
+ addl_sense_len = INFORMATION_SENSE_DESCR;
+ else
+ addl_sense_len = 0;
+
+ spc_sense_create(cmd, KEY_ILLEGAL_REQUEST, addl_sense_len);
+ spc_sense_info(cmd, err_blkno);
+ spc_sense_ascq(cmd, SPC_ASC_BLOCK_RANGE, SPC_ASCQ_BLOCK_RANGE);
+ trans_send_complete(cmd, STATUS_CHECK);
+
+ queue_prt(mgmtq, Q_STE_ERRS,
+ "SBC%x LUN%d WRITE Illegal sector "
+ "(0x%llx + 0x%x) > 0x%ullx", cmd->c_lu->l_targ->s_targ_num,
+ cmd->c_lu->l_common->l_num, addr, cnt, d->d_size);
+ return;
+ }
+
+ if (bytchk == False) {
+ /*
+ * With Byte Check being false all we need to do
+ * is make sure that we can read the data off of the
+ * media.
+ */
+ chk_size = 1024 * 1024;
+ if ((chk_block = malloc(chk_size)) == NULL) {
+ trans_send_complete(cmd, STATUS_BUSY);
+ return;
+ }
+ while (cnt) {
+ sz = MIN(chk_size, cnt * 512);
+ /*
+ * Even if the device is mmap'd in use pread. This
+ * way we know directly if a read of the data has
+ * failed.
+ */
+ if (pread(cmd->c_lu->l_common->l_fd, chk_block, sz,
+ addr * 512LL) != sz) {
+ spc_sense_create(cmd, KEY_MEDIUM_ERROR, 0);
+ spc_sense_ascq(cmd, SPC_ASC_DATA_PATH,
+ SPC_ASCQ_DATA_PATH);
+ trans_send_complete(cmd, STATUS_CHECK);
+ free(chk_block);
+ return;
+ }
+ addr += sz / 512LL;
+ cnt -= sz / 512;
+ }
+ free(chk_block);
+ trans_send_complete(cmd, STATUS_GOOD);
+ } else {
+
+ io = cmd->c_emul_id;
+ if (io == NULL) {
+ io = sbc_io_alloc(cmd);
+ io->da_lba = addr;
+ io->da_lba_cnt = cnt;
+ io->da_clear_overlap = False;
+ io->da_aio.a_aio_cmplt = sbc_write_cmplt;
+ io->da_aio.a_id = io;
+ }
+
+ sz = cmd->c_lu->l_targ->s_maxout;
+ io->da_data_alloc = True;
+ io->da_data_len = sz ? MIN(sz, (cnt * 512) - io->da_offset) :
+ (cnt * 512);
+
+ /*
+ * Since we're going to just check the data we don't wish
+ * to possibly change the on disk data. Therefore, even if
+ * the backing store is mmap'd in we allocate space for the
+ * data out buffer.
+ */
+ if ((io->da_data = malloc(io->da_data_len)) == NULL) {
+ trans_send_complete(cmd, STATUS_BUSY);
+ return;
+ }
+
+ if (trans_rqst_dataout(cmd, io->da_data, io->da_data_len,
+ io->da_offset, io) == False)
+ trans_send_complete(cmd, STATUS_BUSY);
+ }
+}
+
+/*ARGSUSED*/
+static void
+sbc_verify_data(t10_cmd_t *cmd, emul_handle_t id, size_t offset, char *data,
+ size_t data_len)
+{
+ disk_io_t *io = (disk_io_t *)id;
+ char *on_disk_buf;
+
+ if ((on_disk_buf = malloc(io->da_data_len)) == NULL) {
+ sbc_io_free(io);
+ trans_send_complete(cmd, STATUS_BUSY);
+ }
+
+ if (pread(cmd->c_lu->l_common->l_fd, on_disk_buf, io->da_data_len,
+ io->da_offset + (io->da_lba * 512LL)) != io->da_data_len) {
+ spc_sense_create(cmd, KEY_MISCOMPARE, 0);
+ spc_sense_ascq(cmd, SPC_ASC_DATA_PATH, SPC_ASCQ_DATA_PATH);
+ trans_send_complete(cmd, STATUS_CHECK);
+ sbc_io_free(io);
+ return;
+ }
+ if (bcmp(on_disk_buf, io->da_data, io->da_data_len) != 0) {
+ spc_sense_create(cmd, KEY_MISCOMPARE, 0);
+ spc_sense_ascq(cmd, SPC_ASC_MISCOMPARE, SPC_ASCQ_MISCOMPARE);
+ trans_send_complete(cmd, STATUS_CHECK);
+ sbc_io_free(io);
+ return;
+ }
+ free(on_disk_buf);
+ io->da_offset += io->da_data_len;
+ if (io->da_offset < (io->da_lba_cnt * 512)) {
+ if (io->da_data_alloc == True) {
+ io->da_data_alloc = False;
+ free(io->da_data);
+ }
+ sbc_verify(cmd, cmd->c_cdb, cmd->c_cdb_len);
+ return;
+ }
+ sbc_io_free(io);
+ trans_send_complete(cmd, STATUS_GOOD);
+}
+
/*
* []------------------------------------------------------------------[]
* | Support related functions for SBC-2 |
@@ -1620,7 +1840,7 @@ static scsi_cmd_table_t lba_table[] = {
{ spc_unsupported, NULL, NULL, NULL },
{ spc_unsupported, NULL, NULL, NULL },
{ spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
+ { sbc_verify, sbc_verify_data, NULL, "VERIFY_G1" },
/* 0x30 -- 0x3f */
{ spc_unsupported, NULL, NULL, NULL },
@@ -1728,7 +1948,7 @@ static scsi_cmd_table_t lba_table[] = {
{ spc_unsupported, NULL, NULL, NULL },
{ spc_unsupported, NULL, NULL, NULL },
{ spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
+ { sbc_verify, sbc_verify_data, NULL, "VERIFY_G4" },
/* 0x90 -- 0x9f */
{ spc_unsupported, NULL, NULL, NULL },
@@ -1764,7 +1984,7 @@ static scsi_cmd_table_t lba_table[] = {
{ spc_unsupported, NULL, NULL, NULL },
{ spc_unsupported, NULL, NULL, NULL },
{ spc_unsupported, NULL, NULL, NULL },
- { spc_unsupported, NULL, NULL, NULL },
+ { sbc_verify, sbc_verify_data, NULL, "VERIFY_G5" },
/* 0xb0 -- 0xbf */
{ spc_unsupported, NULL, NULL, NULL },
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.h b/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.h
index af1404d3c4..4e79c88f29 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.h
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_sbc.h
@@ -43,6 +43,17 @@ extern "C" {
#define SBC_SYNC_CACHE_NV 0x04
/*
+ * SBC-2 revision 16, section 5.20 - VERIFY command.
+ * Bits found in the CDB.
+ */
+/* --- Bits found in byte 1 --- */
+#define SBC_VRPROTECT_MASK 0xe0
+#define SBC_DPO 0x10
+#define SBC_BYTCHK 0x02
+/* --- Bits found in byte 6 --- */
+#define SBC_GROUP_MASK 0x1f
+
+/*
* SBC-2 revision 16, section 5.17 START_STOP
* Table 49 -- POWER CONDITION field
*/
diff --git a/usr/src/cmd/iscsi/iscsitgtd/t10_spc.h b/usr/src/cmd/iscsi/iscsitgtd/t10_spc.h
index 90ec0ac9f1..68bff91e9d 100644
--- a/usr/src/cmd/iscsi/iscsitgtd/t10_spc.h
+++ b/usr/src/cmd/iscsi/iscsitgtd/t10_spc.h
@@ -115,6 +115,14 @@ Boolean_t spc_encode_lu_addr(uint8_t *buf, int select_field, uint32_t lun);
#define SPC_ASCQ_CAP_CHANGE 0x09
#define SPC_ASC_IN_PROG 0x04
#define SPC_ASCQ_IN_PROG 0x07
+#define SPC_ASC_DATA_PATH 0x41
+#define SPC_ASCQ_DATA_PATH 0x00
+#define SPC_ASC_MISCOMPARE 0x1d
+#define SPC_ASCQ_MISCOMPARE 0x00
+#define SPC_ASC_INVALID_LU 0x20
+#define SPC_ASCQ_INVALID_LU 0x09
+#define SPC_ASC_BLOCK_RANGE 0x21
+#define SPC_ASCQ_BLOCK_RANGE 0x00
/*
* []------------------------------------------------------------------[]
diff --git a/usr/src/uts/common/sys/scsi/generic/commands.h b/usr/src/uts/common/sys/scsi/generic/commands.h
index d4b17c18da..66218064c2 100644
--- a/usr/src/uts/common/sys/scsi/generic/commands.h
+++ b/usr/src/uts/common/sys/scsi/generic/commands.h
@@ -298,6 +298,7 @@ extern "C" {
*/
#define SCMD_GROUP4 0x80
#define SCMD_EXTENDED_COPY 0x83
+#define SCMD_VERIFY_G4 0x8f
/*
* Group 4 Commands, Direct Access Devices
@@ -334,7 +335,7 @@ extern "C" {
#define SCMD_WRITE_G5 0xAA
#define SCMD_READ_MEDIA_SERIAL 0xAB
#define SCMD_GET_PERFORMANCE 0xAC
-
+#define SCMD_VERIFY_G5 0xAF
/*
diff --git a/usr/src/uts/common/sys/scsi/impl/commands.h b/usr/src/uts/common/sys/scsi/impl/commands.h
index 059f6b90b6..227e2da724 100644
--- a/usr/src/uts/common/sys/scsi/impl/commands.h
+++ b/usr/src/uts/common/sys/scsi/impl/commands.h
@@ -444,6 +444,11 @@ union scsi_cdb { /* scsi command description block */
((cdb)->scc5_addr1 << 8) + \
((cdb)->scc5_addr0)
+#define GETG5COUNT(cdb) ((cdb)->scc5_count3 << 24) + \
+ ((cdb)->scc5_count2 << 16) + \
+ ((cdb)->scc5_count1 << 8) + \
+ ((cdb)->scc5_count0)
+
#define GETG5TAG(cdb) (cdb)->scc5_reladdr