SCSI: Add support for mode subpages

Add support for modepages that contain subpages and add
a simple subpage for the Control page.


svn path=/trunk/; revision=43952
This commit is contained in:
Ronnie Sahlberg 2012-07-24 02:00:50 +00:00
parent 045b5b03ce
commit 3b0eb70b23
1 changed files with 120 additions and 49 deletions

View File

@ -128,7 +128,16 @@ static int hf_scsi_paramlen = -1;
static int hf_scsi_paramlen16 = -1;
static int hf_scsi_modesel_flags = -1;
static int hf_scsi_modesns_pc = -1;
static int hf_scsi_spcpagecode = -1;
static int hf_scsi_modepage_ps = -1;
static int hf_scsi_modepage_spf = -1;
static int hf_scsi_modepage_plen = -1;
static int hf_scsi_modepage_tcmos = -1;
static int hf_scsi_modepage_scsip = -1;
static int hf_scsi_modepage_ialuae = -1;
static int hf_scsi_modepage_icp = -1;
static int hf_scsi_modepage_msdl = -1;
static int hf_scsi_spc_pagecode = -1;
static int hf_scsi_spc_subpagecode = -1;
static int hf_scsi_sbcpagecode = -1;
static int hf_scsi_sscpagecode = -1;
static int hf_scsi_smcpagecode = -1;
@ -2808,40 +2817,62 @@ dissect_scsi_blockdescs(tvbuff_t *tvb, packet_info *pinfo _U_,
static gboolean
dissect_scsi_spc_modepage(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, guint offset, guint8 pcode)
proto_tree *tree, guint offset, guint8 pcode, guint8 spf, guint8 subpcode)
{
guint8 flags, proto;
switch (pcode) {
case SCSI_SPC_MODEPAGE_CTL:
flags = tvb_get_guint8(tvb, offset+2);
proto_tree_add_item(tree, hf_scsi_modesns_tst, tvb, offset+2, 1, ENC_BIG_ENDIAN);
proto_tree_add_text(tree, tvb, offset+2, 1,
"Global Logging Target Save Disable: %u, Report Log Exception Condition: %u",
(flags & 0x2) >> 1, (flags & 0x1));
flags = tvb_get_guint8(tvb, offset+3);
proto_tree_add_item(tree, hf_scsi_modesns_qmod, tvb, offset+3, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_scsi_modesns_qerr, tvb, offset+3, 1, ENC_BIG_ENDIAN);
proto_tree_add_text(tree, tvb, offset+3, 1, "Disable Queuing: %u",
flags & 0x1);
flags = tvb_get_guint8(tvb, offset+4);
proto_tree_add_item(tree, hf_scsi_modesns_rac, tvb, offset+4, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_scsi_modesns_tas, tvb, offset+4, 1, ENC_BIG_ENDIAN);
proto_tree_add_text(tree, tvb, offset+4, 1,
"SWP: %u, RAERP: %u, UAAERP: %u, EAERP: %u",
(flags & 0x8) >> 3, (flags & 0x4) >> 2,
(flags & 0x2) >> 1, (flags & 0x1));
proto_tree_add_text(tree, tvb, offset+5, 1, "Autoload Mode: 0x%x",
tvb_get_guint8(tvb, offset+5) & 0x7);
proto_tree_add_text(tree, tvb, offset+6, 2,
"Ready AER Holdoff Period: %u ms",
tvb_get_ntohs(tvb, offset+6));
proto_tree_add_text(tree, tvb, offset+8, 2,
"Busy Timeout Period: %u ms",
tvb_get_ntohs(tvb, offset+8)*100);
proto_tree_add_text(tree, tvb, offset+10, 2,
"Extended Self-Test Completion Time: %u",
tvb_get_ntohs(tvb, offset+10));
if (!spf) {
/* standard page for control */
flags = tvb_get_guint8(tvb, offset+2);
proto_tree_add_item(tree, hf_scsi_modesns_tst, tvb, offset+2, 1, ENC_BIG_ENDIAN);
proto_tree_add_text(tree, tvb, offset+2, 1,
"Global Logging Target Save Disable: %u, Report Log Exception Condition: %u",
(flags & 0x2) >> 1, (flags & 0x1));
flags = tvb_get_guint8(tvb, offset+3);
proto_tree_add_item(tree, hf_scsi_modesns_qmod, tvb, offset+3, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_scsi_modesns_qerr, tvb, offset+3, 1, ENC_BIG_ENDIAN);
proto_tree_add_text(tree, tvb, offset+3, 1, "Disable Queuing: %u",
flags & 0x1);
flags = tvb_get_guint8(tvb, offset+4);
proto_tree_add_item(tree, hf_scsi_modesns_rac, tvb, offset+4, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_scsi_modesns_tas, tvb, offset+4, 1, ENC_BIG_ENDIAN);
proto_tree_add_text(tree, tvb, offset+4, 1,
"SWP: %u, RAERP: %u, UAAERP: %u, EAERP: %u",
(flags & 0x8) >> 3, (flags & 0x4) >> 2,
(flags & 0x2) >> 1, (flags & 0x1));
proto_tree_add_text(tree, tvb, offset+5, 1, "Autoload Mode: 0x%x",
tvb_get_guint8(tvb, offset+5) & 0x7);
proto_tree_add_text(tree, tvb, offset+6, 2,
"Ready AER Holdoff Period: %u ms",
tvb_get_ntohs(tvb, offset+6));
proto_tree_add_text(tree, tvb, offset+8, 2,
"Busy Timeout Period: %u ms",
tvb_get_ntohs(tvb, offset+8)*100);
proto_tree_add_text(tree, tvb, offset+10, 2,
"Extended Self-Test Completion Time: %u",
tvb_get_ntohs(tvb, offset+10));
} else {
switch (subpcode) {
case 1:
/* control extension subpage */
proto_item_append_text(tree, " Control Extension");
/* TCMOS SCSIP IALUAE */
proto_tree_add_item(tree, hf_scsi_modepage_tcmos, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_scsi_modepage_scsip, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_scsi_modepage_ialuae, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
/* Initial Command Priority */
proto_tree_add_item(tree, hf_scsi_modepage_icp, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
/* Maximum Sense Data Length */
proto_tree_add_item(tree, hf_scsi_modepage_msdl, tvb, offset + 6, 1, ENC_BIG_ENDIAN);
break;
}
}
break;
case SCSI_SPC_MODEPAGE_DISCON:
proto_tree_add_text(tree, tvb, offset+2, 1, "Buffer Full Ratio: %u",
@ -2935,7 +2966,7 @@ dissect_scsi_spc_modepage(tvbuff_t *tvb, packet_info *pinfo _U_,
static gboolean
dissect_scsi_sbc_modepage(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, guint offset, guint8 pcode)
proto_tree *tree, guint offset, guint8 pcode, guint8 spf _U_, guint8 subpcode _U_)
{
guint8 flags;
@ -3081,7 +3112,7 @@ static const value_string compression_algorithm_vals[] = {
static gboolean
dissect_scsi_ssc2_modepage(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
proto_tree *tree _U_, guint offset _U_,
guint8 pcode)
guint8 pcode, guint8 spf _U_, guint8 subpcode _U_)
{
guint8 flags;
@ -3199,7 +3230,7 @@ dissect_scsi_ssc2_modepage(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
static gboolean
dissect_scsi_mmc5_modepage(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
proto_tree *tree _U_, guint offset _U_, guint8 pcode)
proto_tree *tree _U_, guint offset _U_, guint8 pcode, guint8 spf _U_, guint8 subpcode _U_)
{
guint8 flags;
guint8 i;
@ -3331,7 +3362,7 @@ dissect_scsi_mmc5_modepage(tvbuff_t *tvb _U_, packet_info *pinfo _U_,
static gboolean
dissect_scsi_smc_modepage(tvbuff_t *tvb, packet_info *pinfo _U_,
proto_tree *tree, guint offset, guint8 pcode)
proto_tree *tree, guint offset, guint8 pcode, guint8 spf _U_, guint8 subpcode _U_)
{
guint8 flags;
guint8 param_list_len;
@ -3441,16 +3472,23 @@ dissect_scsi_modepage(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *scsi_tree, guint offset,
scsi_device_type devtype)
{
guint8 pcode, plen;
guint16 plen;
guint8 pcode, spf, subpcode = 0;
proto_tree *tree;
proto_item *ti;
const value_string *modepage_val;
int hf_pagecode;
gboolean (*dissect_modepage)(tvbuff_t *, packet_info *, proto_tree *,
guint, guint8);
guint, guint8, guint8, guint8);
pcode = tvb_get_guint8(tvb, offset);
plen = tvb_get_guint8(tvb, offset+1);
pcode = tvb_get_guint8(tvb, offset) & SCSI_MS_PCODE_BITS;
spf = tvb_get_guint8(tvb, offset) & 0x40;
if (spf) {
subpcode = tvb_get_guint8(tvb, offset + 1);
plen = tvb_get_ntohs(tvb, offset + 2);
} else {
plen = tvb_get_guint8(tvb, offset + 1);
}
if (match_strval(pcode & SCSI_MS_PCODE_BITS,
scsi_spc_modepage_val) == NULL) {
@ -3491,24 +3529,30 @@ dissect_scsi_modepage(tvbuff_t *tvb, packet_info *pinfo,
* "Unknown (XXX)", which is what we want.
*/
modepage_val = scsi_spc_modepage_val;
hf_pagecode = hf_scsi_spcpagecode;
hf_pagecode = hf_scsi_spc_pagecode;
dissect_modepage = dissect_scsi_spc_modepage;
break;
}
} else {
modepage_val = scsi_spc_modepage_val;
hf_pagecode = hf_scsi_spcpagecode;
hf_pagecode = hf_scsi_spc_pagecode;
dissect_modepage = dissect_scsi_spc_modepage;
}
ti = proto_tree_add_text(scsi_tree, tvb, offset, plen+2, "%s Mode Page",
ti = proto_tree_add_text(scsi_tree, tvb, offset, plen + spf ? 4 : 2, "%s Mode Page",
val_to_str(pcode & SCSI_MS_PCODE_BITS,
modepage_val, "Unknown (0x%08x)"));
tree = proto_item_add_subtree(ti, ett_scsi_page);
proto_tree_add_text(tree, tvb, offset, 1, "PS: %u", (pcode & 0x80) >> 7);
proto_tree_add_item(tree, hf_scsi_modepage_ps, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_scsi_modepage_spf, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_pagecode, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_text(tree, tvb, offset+1, 1, "Page Length: %u",
plen);
if (spf) {
proto_tree_add_item(tree, hf_scsi_spc_subpagecode, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(tree, hf_scsi_modepage_plen, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
} else {
proto_tree_add_item(tree, hf_scsi_modepage_plen, tvb, offset + 1, 1, ENC_BIG_ENDIAN);
}
if (!tvb_bytes_exist(tvb, offset, plen)) {
/* XXX - why not just drive on and throw an exception? */
@ -3516,7 +3560,7 @@ dissect_scsi_modepage(tvbuff_t *tvb, packet_info *pinfo,
}
if (!(*dissect_modepage)(tvb, pinfo, tree, offset,
(guint8) (pcode & SCSI_MS_PCODE_BITS))) {
pcode, spf, subpcode)) {
proto_tree_add_text(tree, tvb, offset+2, plen,
"Unknown Page");
}
@ -3757,11 +3801,11 @@ dissect_scsi_pagecode(tvbuff_t *tvb, packet_info *pinfo _U_,
break;
default:
hf_pagecode = hf_scsi_spcpagecode;
hf_pagecode = hf_scsi_spc_pagecode;
break;
}
} else {
hf_pagecode = hf_scsi_spcpagecode;
hf_pagecode = hf_scsi_spc_pagecode;
}
proto_tree_add_uint(tree, hf_pagecode, tvb, offset, 1, pcode);
}
@ -5150,7 +5194,10 @@ proto_register_scsi(void)
{ &hf_scsi_modesns_pc,
{"Page Control", "scsi.mode.pc", FT_UINT8, BASE_DEC,
VALS(scsi_modesns_pc_val), 0xC0, NULL, HFILL}},
{ &hf_scsi_spcpagecode,
{ &hf_scsi_spc_subpagecode,
{"SubPage Code", "scsi.mode.spc.subpagecode", FT_UINT8, BASE_HEX,
NULL, 0, NULL, HFILL}},
{ &hf_scsi_spc_pagecode,
{"SPC-2 Page Code", "scsi.mode.spc.pagecode", FT_UINT8, BASE_HEX,
VALS(scsi_spc_modepage_val), 0x3F, NULL, HFILL}},
{ &hf_scsi_sbcpagecode,
@ -5738,6 +5785,30 @@ proto_register_scsi(void)
{ &hf_scsi_block_limits_mwsl,
{"Maximum Write Same Length", "scsi.sbc.bl.mwsl", FT_UINT64, BASE_DEC, NULL, 0,
NULL, HFILL}},
{ &hf_scsi_modepage_ps,
{"PS", "scsi.spc.modepage.ps", FT_BOOLEAN, 8, NULL, 0x80,
NULL, HFILL}},
{ &hf_scsi_modepage_spf,
{"SPF", "scsi.spc.modepage.spf", FT_BOOLEAN, 8, NULL, 0x40,
NULL, HFILL}},
{ &hf_scsi_modepage_plen,
{"Page Length", "scsi.spc.modepage.plen", FT_UINT16, BASE_DEC, NULL, 0,
NULL, HFILL}},
{ &hf_scsi_modepage_tcmos,
{"TCMOS", "scsi.spc.modepage.tcmos", FT_BOOLEAN, 8, NULL, 0x04,
NULL, HFILL}},
{ &hf_scsi_modepage_scsip,
{"SCSIP", "scsi.spc.modepage.scsip", FT_BOOLEAN, 8, NULL, 0x02,
NULL, HFILL}},
{ &hf_scsi_modepage_ialuae,
{"IALUAE", "scsi.spc.modepage.ialuae", FT_BOOLEAN, 8, NULL, 0x01,
NULL, HFILL}},
{ &hf_scsi_modepage_icp,
{"Initial Command Priority", "scsi.spc.modepage.icp", FT_UINT8, BASE_DEC,
NULL, 0x0f, NULL, HFILL}},
{ &hf_scsi_modepage_msdl,
{"Maximum Sense Data Length", "scsi.spc.modepage.msdl", FT_UINT8, BASE_DEC,
NULL, 0, NULL, HFILL}},
};
/* Setup protocol subtree array */