Q.933 dissector. (Not complete.)
[metze/wireshark/wip.git] / packet-scsi.c
1 /* packet-scsi.c
2  * Routines for decoding SCSI CDBs and responses
3  * Author: Dinesh G Dutt (ddutt@cisco.com)
4  *
5  * $Id: packet-scsi.c,v 1.32 2003/07/09 03:42:55 guy Exp $
6  *
7  * Ethereal - Network traffic analyzer
8  * By Gerald Combs <gerald@ethereal.com>
9  * Copyright 2002 Gerald Combs
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 /*
27  * Some Notes on using the SCSI Decoder:
28  *
29  * The SCSI decoder has been built right now that it is invoked directly by the
30  * SCSI transport layers as compared to the standard mechanism of being invoked
31  * via a dissector chain. There are multiple reasons for this:
32  * - The SCSI CDB is typically embedded inside the transport along with other
33  *   header fields that have nothing to do with SCSI. So, it is required to be
34  *   invoked on a embedded subset of the packet.
35  * - Originally, Ethereal couldn't do filtering on protocol trees that were not
36  *   on the top level.
37  *
38  * There are four main routines that are provided:
39  * o dissect_scsi_cdb - invoked on receiving a SCSI Command
40  *   void dissect_scsi_cdb (tvbuff_t *, packet_info *, proto_tree *, guint,
41  *   guint);
42  * o dissect_scsi_payload - invoked to decode SCSI responses
43  *   void dissect_scsi_payload (tvbuff_t *, packet_info *, proto_tree *, guint,
44  *                              gboolean, guint32);
45  *   The final parameter is the length of the response field that is negotiated
46  *   as part of the SCSI transport layer. If this is not tracked by the
47  *   transport, it can be set to 0.
48  * o dissect_scsi_rsp - invoked to destroy the data structures associated with a
49  *                      SCSI task.
50  *   void dissect_scsi_rsp (tvbuff_t *, packet_info *, proto_tree *);
51  * o dissect_scsi_snsinfo - invoked to decode the sense data provided in case of
52  *                          an error.
53  *   void dissect_scsi_snsinfo (tvbuff_t *, packet_info *, proto_tree *, guint,
54  *   guint);
55  *
56  * In addition to this, the other requirement made from the transport is to
57  * provide a unique way to determine a SCSI task. In Fibre Channel networks,
58  * this is the exchange ID pair alongwith the source/destination addresses; in
59  * iSCSI it is the initiator task tag along with the src/dst address and port
60  * numbers. This is to be provided to the SCSI decoder via the private_data
61  * field in the packet_info data structure. The private_data field is treated
62  * as a pointer to a "scsi_task_id_t" structure, containing a conversation
63  * ID (a number uniquely identifying a conversation between a particular
64  * initiator and target, e.g. between two Fibre Channel addresses or between
65  * two TCP address/port pairs for iSCSI or NDMP) and a task ID (a number
66  * uniquely identifying a task within that conversation).
67  *
68  * This decoder attempts to track the type of SCSI device based on the response
69  * to the Inquiry command. If the trace does not contain an Inquiry command,
70  * the decoding of the commands is done as per a user preference. Currently,
71  * only SBC (disks) and SSC (tapes) are the alternatives offered. The basic
72  * SCSI command set (SPC-2/3) is decoded for all SCSI devices. If there is a
73  * mixture of devices in the trace, some with Inquiry response and some
74  * without, the user preference is used only for those devices whose type the
75  * decoder has not been able to determine.
76  *
77  */
78 #ifdef HAVE_CONFIG_H
79 # include "config.h"
80 #endif
81
82 #include <glib.h>
83 #include <string.h>
84 #include <epan/strutil.h>
85 #include <epan/conversation.h>
86 #include <epan/int-64bit.h>
87 #include "prefs.h"
88 #include "packet-scsi.h"
89
90 static int proto_scsi                    = -1;
91 static int hf_scsi_spcopcode             = -1;
92 static int hf_scsi_sbcopcode             = -1;
93 static int hf_scsi_sscopcode             = -1;
94 static int hf_scsi_smcopcode             = -1;
95 static int hf_scsi_control               = -1;
96 static int hf_scsi_inquiry_flags         = -1;
97 static int hf_scsi_inquiry_evpd_page     = -1;
98 static int hf_scsi_inquiry_cmdt_page     = -1;
99 static int hf_scsi_alloclen              = -1;
100 static int hf_scsi_logsel_flags          = -1;
101 static int hf_scsi_logsel_pc             = -1;
102 static int hf_scsi_paramlen              = -1;
103 static int hf_scsi_logsns_flags          = -1;
104 static int hf_scsi_logsns_pc             = -1;
105 static int hf_scsi_logsns_pagecode       = -1;
106 static int hf_scsi_paramlen16            = -1;
107 static int hf_scsi_modesel_flags         = -1;
108 static int hf_scsi_alloclen16            = -1;
109 static int hf_scsi_modesns_pc            = -1;
110 static int hf_scsi_spcpagecode           = -1;
111 static int hf_scsi_sbcpagecode           = -1;
112 static int hf_scsi_sscpagecode           = -1;
113 static int hf_scsi_smcpagecode           = -1;
114 static int hf_scsi_modesns_flags         = -1;
115 static int hf_scsi_persresvin_svcaction  = -1;
116 static int hf_scsi_persresvout_svcaction = -1;
117 static int hf_scsi_persresv_scope        = -1;
118 static int hf_scsi_persresv_type         = -1;
119 static int hf_scsi_release_flags         = -1;
120 static int hf_scsi_release_thirdpartyid  = -1;
121 static int hf_scsi_alloclen32            = -1;
122 static int hf_scsi_formatunit_flags      = -1;
123 static int hf_scsi_formatunit_interleave = -1;
124 static int hf_scsi_formatunit_vendor     = -1;
125 static int hf_scsi_rdwr6_lba             = -1;
126 static int hf_scsi_rdwr6_xferlen         = -1;
127 static int hf_scsi_rdwr10_lba            = -1;
128 static int hf_scsi_read_flags            = -1;
129 static int hf_scsi_rdwr12_xferlen        = -1;
130 static int hf_scsi_rdwr16_lba            = -1;
131 static int hf_scsi_readcapacity_flags    = -1;
132 static int hf_scsi_readcapacity_lba      = -1;
133 static int hf_scsi_readcapacity_pmi      = -1;
134 static int hf_scsi_rdwr10_xferlen        = -1;
135 static int hf_scsi_readdefdata_flags     = -1;
136 static int hf_scsi_cdb_defectfmt         = -1;
137 static int hf_scsi_reassignblks_flags    = -1;
138 static int hf_scsi_inq_qualifier         = -1;
139 static int hf_scsi_inq_devtype           = -1;
140 static int hf_scsi_inq_version           = -1;
141 static int hf_scsi_rluns_lun             = -1;
142 static int hf_scsi_rluns_multilun        = -1;
143 static int hf_scsi_modesns_errrep        = -1;
144 static int hf_scsi_modesns_tst           = -1;
145 static int hf_scsi_modesns_qmod          = -1;
146 static int hf_scsi_modesns_qerr          = -1;
147 static int hf_scsi_modesns_rac           = -1;
148 static int hf_scsi_modesns_tas           = -1;
149 static int hf_scsi_protocol              = -1;
150 static int hf_scsi_sns_errtype           = -1;
151 static int hf_scsi_snskey                = -1;
152 static int hf_scsi_snsinfo               = -1;
153 static int hf_scsi_addlsnslen            = -1;
154 static int hf_scsi_asc                   = -1;
155 static int hf_scsi_ascascq               = -1;
156 static int hf_scsi_ascq                  = -1;
157 static int hf_scsi_fru                   = -1;
158 static int hf_scsi_sksv                  = -1;
159 static int hf_scsi_inq_normaca           = -1;
160 static int hf_scsi_persresv_key          = -1;
161 static int hf_scsi_persresv_scopeaddr    = -1;
162 static int hf_scsi_add_cdblen = -1;
163 static int hf_scsi_svcaction = -1;
164
165
166 static gint ett_scsi         = -1;
167 static gint ett_scsi_page    = -1;
168
169 typedef guint32 scsi_cmnd_type;
170 typedef guint32 scsi_device_type;
171
172 /* Valid SCSI Command Types */
173 #define SCSI_CMND_SPC2                   1
174 #define SCSI_CMND_SBC2                   2
175 #define SCSI_CMND_SSC2                   3
176 #define SCSI_CMND_SMC2                   4
177
178 /* SPC and SPC-2 Commands */
179
180 #define SCSI_SPC_CHANGE_DEFINITION       0x40
181 #define SCSI_SPC_COMPARE                 0x39
182 #define SCSI_SPC_COPY                    0x18
183 #define SCSI_SPC_COPY_AND_VERIFY         0x3A
184 #define SCSI_SPC2_INQUIRY                0x12
185 #define SCSI_SPC2_EXTCOPY                0x83
186 #define SCSI_SPC2_LOGSELECT              0x4C
187 #define SCSI_SPC2_LOGSENSE               0x4D
188 #define SCSI_SPC2_MODESELECT6            0x15
189 #define SCSI_SPC2_MODESELECT10           0x55
190 #define SCSI_SPC2_MODESENSE6             0x1A
191 #define SCSI_SPC2_MODESENSE10            0x5A
192 #define SCSI_SPC2_PERSRESVIN             0x5E
193 #define SCSI_SPC2_PERSRESVOUT            0x5F
194 #define SCSI_SPC2_PREVMEDREMOVAL         0x1E
195 #define SCSI_SPC2_READBUFFER             0x3C
196 #define SCSI_SPC2_RCVCOPYRESULTS         0x84
197 #define SCSI_SPC2_RCVDIAGRESULTS         0x1C
198 #define SCSI_SPC2_RELEASE6               0x17
199 #define SCSI_SPC2_RELEASE10              0x57
200 #define SCSI_SPC2_REPORTDEVICEID         0xA3
201 #define SCSI_SPC2_REPORTLUNS             0xA0
202 #define SCSI_SPC2_REQSENSE               0x03
203 #define SCSI_SPC2_RESERVE6               0x16
204 #define SCSI_SPC2_RESERVE10              0x56
205 #define SCSI_SPC2_SENDDIAG               0x1D
206 #define SCSI_SPC2_SETDEVICEID            0xA4
207 #define SCSI_SPC2_TESTUNITRDY            0x00
208 #define SCSI_SPC2_WRITEBUFFER            0x3B
209 #define SCSI_SPC2_VARLENCDB              0x7F
210
211 static const value_string scsi_spc2_val[] = {
212     {SCSI_SPC_CHANGE_DEFINITION  , "Change Definition"},
213     {SCSI_SPC_COMPARE            , "Compare"},
214     {SCSI_SPC_COPY               , "Copy"},
215     {SCSI_SPC_COPY_AND_VERIFY    , "Copy And Verify"},
216     {SCSI_SPC2_EXTCOPY           , "Extended Copy"},
217     {SCSI_SPC2_INQUIRY           , "Inquiry"},
218     {SCSI_SPC2_LOGSELECT         , "Log Select"},
219     {SCSI_SPC2_LOGSENSE          , "Log Sense"},
220     {SCSI_SPC2_MODESELECT6       , "Mode Select(6)"},
221     {SCSI_SPC2_MODESELECT10      , "Mode Select(10)"},
222     {SCSI_SPC2_MODESENSE6        , "Mode Sense(6)"},
223     {SCSI_SPC2_MODESENSE10       , "Mode Sense(10)"},
224     {SCSI_SPC2_PERSRESVIN        , "Persistent Reserve In"},
225     {SCSI_SPC2_PERSRESVOUT       , "Persistent Reserve Out"},
226     {SCSI_SPC2_PREVMEDREMOVAL    , "Prevent/Allow Medium Removal"},
227     {SCSI_SPC2_RCVCOPYRESULTS    , "Receive Copy Results"},
228     {SCSI_SPC2_RCVDIAGRESULTS    , "Receive Diagnostics Results"},
229     {SCSI_SPC2_READBUFFER        , "Read Buffer"},
230     {SCSI_SPC2_RELEASE6          , "Release(6)"},
231     {SCSI_SPC2_RELEASE10         , "Release(10)"},
232     {SCSI_SPC2_REPORTDEVICEID    , "Report Device ID"},
233     {SCSI_SPC2_REPORTLUNS        , "Report LUNs"},
234     {SCSI_SPC2_REQSENSE          , "Request Sense"},
235     {SCSI_SPC2_RESERVE6          , "Reserve(6)"},
236     {SCSI_SPC2_RESERVE10         , "Reserve(10)"},
237     {SCSI_SPC2_SENDDIAG          , "Send Diagnostic"},
238     {SCSI_SPC2_TESTUNITRDY       , "Test Unit Ready"},
239     {SCSI_SPC2_WRITEBUFFER       , "Write Buffer"},
240     {SCSI_SPC2_VARLENCDB         , "Variable Length CDB"},
241     {0, NULL},
242 };
243
244 /* SBC-2 Commands */
245 #define SCSI_SBC2_FORMATUNIT             0x04
246 #define SCSI_SBC2_LOCKUNLKCACHE10        0x36
247 #define SCSI_SBC2_LOCKUNLKCACHE16        0x92
248 #define SCSI_SBC2_PREFETCH10             0x34
249 #define SCSI_SBC2_PREFETCH16             0x90
250 #define SCSI_SBC2_READ6                  0x08
251 #define SCSI_SBC2_READ10                 0x28
252 #define SCSI_SBC2_READ12                 0xA8
253 #define SCSI_SBC2_READ16                 0x88
254 #define SCSI_SBC2_READCAPACITY           0x25
255 #define SCSI_SBC2_READDEFDATA10          0x37
256 #define SCSI_SBC2_READDEFDATA12          0xB7
257 #define SCSI_SBC2_READLONG               0x3E
258 #define SCSI_SBC2_REASSIGNBLKS           0x07
259 #define SCSI_SBC2_REBUILD16              0x81
260 #define SCSI_SBC2_REBUILD32              0x7F
261 #define SCSI_SBC2_REGENERATE16           0x82
262 #define SCSI_SBC2_REGENERATE32           0x7F
263 #define SCSI_SBC2_SEEK10                 0x2B
264 #define SCSI_SBC2_SETLIMITS10            0x33
265 #define SCSI_SBC2_SETLIMITS12            0xB3
266 #define SCSI_SBC2_STARTSTOPUNIT          0x1B
267 #define SCSI_SBC2_SYNCCACHE10            0x35
268 #define SCSI_SBC2_SYNCCACHE16            0x91
269 #define SCSI_SBC2_VERIFY10               0x2F
270 #define SCSI_SBC2_VERIFY12               0xAF
271 #define SCSI_SBC2_VERIFY16               0x8F
272 #define SCSI_SBC2_WRITE6                 0x0A
273 #define SCSI_SBC2_WRITE10                0x2A
274 #define SCSI_SBC2_WRITE12                0xAA
275 #define SCSI_SBC2_WRITE16                0x8A
276 #define SCSI_SBC2_WRITENVERIFY10         0x2E
277 #define SCSI_SBC2_WRITENVERIFY12         0xAE
278 #define SCSI_SBC2_WRITENVERIFY16         0x8E
279 #define SCSI_SBC2_WRITELONG              0x3F
280 #define SCSI_SBC2_WRITESAME10            0x41
281 #define SCSI_SBC2_WRITESAME16            0x93
282 #define SCSI_SBC2_XDREAD10               0x52
283 #define SCSI_SBC2_XDREAD32               0x7F
284 #define SCSI_SBC2_XDWRITE10              0x50
285 #define SCSI_SBC2_XDWRITE32              0x7F
286 #define SCSI_SBC2_XDWRITEREAD10          0x53
287 #define SCSI_SBC2_XDWRITEREAD32          0x7F
288 #define SCSI_SBC2_XDWRITEEXTD16          0x80
289 #define SCSI_SBC2_XDWRITEEXTD32          0x7F
290 #define SCSI_SBC2_XPWRITE10              0x51
291 #define SCSI_SBC2_XPWRITE32              0x7F
292
293
294 static const value_string scsi_sbc2_val[] = {
295     {SCSI_SBC2_FORMATUNIT    , "Format Unit"},
296     {SCSI_SBC2_LOCKUNLKCACHE10, "Lock Unlock Cache(10)"},
297     {SCSI_SBC2_LOCKUNLKCACHE16, "Lock Unlock Cache(16)"},
298     {SCSI_SBC2_PREFETCH10, "Pre-Fetch(10)"},
299     {SCSI_SBC2_PREFETCH16, "Pre-Fetch(16)"},
300     {SCSI_SBC2_READ6         , "Read(6)"},
301     {SCSI_SBC2_READ10        , "Read(10)"},
302     {SCSI_SBC2_READ12        , "Read(12)"},
303     {SCSI_SBC2_READ16        , "Read(16)"},
304     {SCSI_SBC2_READCAPACITY  , "Read Capacity"},
305     {SCSI_SBC2_READDEFDATA10 , "Read Defect Data(10)"},
306     {SCSI_SBC2_READDEFDATA12 , "Read Defect Data(12)"},
307     {SCSI_SBC2_READLONG, "Read Long"},
308     {SCSI_SBC2_REASSIGNBLKS  , "Reassign Blocks"},
309     {SCSI_SBC2_REBUILD16, "Rebuild(16)"},
310     {SCSI_SBC2_REBUILD32, "Rebuild(32)"},
311     {SCSI_SBC2_REGENERATE16, "Regenerate(16)"},
312     {SCSI_SBC2_REGENERATE32, "Regenerate(32)"},
313     {SCSI_SBC2_SEEK10, "Seek(10)"},
314     {SCSI_SBC2_SETLIMITS10, "Set Limits(10)"},
315     {SCSI_SBC2_SETLIMITS12, "Set Limits(12)"},
316     {SCSI_SBC2_STARTSTOPUNIT, "Start Stop Unit"},
317     {SCSI_SBC2_SYNCCACHE10, "Synchronize Cache(10)"},
318     {SCSI_SBC2_SYNCCACHE16, "Synchronize Cache(16)"},
319     {SCSI_SBC2_VERIFY10, "Verify(10)"},
320     {SCSI_SBC2_VERIFY12, "Verify(12)"},
321     {SCSI_SBC2_VERIFY16, "Verify(16)"},
322     {SCSI_SBC2_WRITE6        , "Write(6)"},
323     {SCSI_SBC2_WRITE10       , "Write(10)"},
324     {SCSI_SBC2_WRITE12       , "Write(12)"},
325     {SCSI_SBC2_WRITE16       , "Write(16)"},
326     {SCSI_SBC2_WRITENVERIFY10, "Write & Verify(10)"},
327     {SCSI_SBC2_WRITENVERIFY12, "Write & Verify(12)"},
328     {SCSI_SBC2_WRITENVERIFY16, "Write & Verify(16)"},
329     {SCSI_SBC2_WRITELONG, "Write Long"},
330     {SCSI_SBC2_WRITESAME10, "Write Same(10)"},
331     {SCSI_SBC2_WRITESAME16, "Write Same(16)"},
332     {SCSI_SBC2_XDREAD10, "XdRead(10)"},
333     {SCSI_SBC2_XDREAD32, "XdRead(32)"},
334     {SCSI_SBC2_XDWRITE10, "XdWrite(10)"},
335     {SCSI_SBC2_XDWRITE32, "XdWrite(32)"},
336     {SCSI_SBC2_XDWRITEREAD10, "XdWriteRead(10)"},
337     {SCSI_SBC2_XDWRITEREAD32, "XdWriteRead(32)"},
338     {SCSI_SBC2_XDWRITEEXTD16, "XdWrite Extended(16)"},
339     {SCSI_SBC2_XDWRITEEXTD32, "XdWrite Extended(32)"},
340     {SCSI_SBC2_XPWRITE10, "XpWrite(10)"},
341     {SCSI_SBC2_XPWRITE32, "XpWrite(32)"},
342     {0, NULL},
343 };
344
345 /* SSC2 Commands */
346 #define SCSI_SSC2_ERASE_16                      0x93
347 #define SCSI_SSC2_FORMAT_MEDIUM                 0x04
348 #define SCSI_SSC2_LOAD_UNLOAD                   0x1B
349 #define SCSI_SSC2_LOCATE_16                     0x92
350 #define SCSI_SSC2_READ_16                       0x88
351 #define SCSI_SSC2_READ_BLOCK_LIMITS             0x05
352 #define SCSI_SSC2_READ_POSITION                 0x34
353 #define SCSI_SSC2_READ_REVERSE_16               0x81
354 #define SCSI_SSC2_RECOVER_BUFFERED_DATA         0x14
355 #define SCSI_SSC2_REPORT_DENSITY_SUPPORT        0x44
356 #define SCSI_SSC2_REWIND                        0x01
357 #define SCSI_SSC2_SET_CAPACITY                  0x0B
358 #define SCSI_SSC2_SPACE_16                      0x91
359 #define SCSI_SSC2_VERIFY_16                     0x8F
360 #define SCSI_SSC2_WRITE_16                      0x8A
361 #define SCSI_SSC2_WRITE_FILEMARKS_16            0x80
362 #define SCSI_SSC2_ERASE_6                       0x19
363 #define SCSI_SSC2_LOCATE_10                     0x2B
364 #define SCSI_SSC2_LOCATE_16                     0x92
365 #define SCSI_SSC2_READ6                         0x08
366 #define SCSI_SSC2_READ_REVERSE_6                0x0F
367 #define SCSI_SSC2_SPACE_6                       0x11
368 #define SCSI_SSC2_VERIFY_6                      0x13
369 #define SCSI_SSC2_WRITE6                        0x0A
370 #define SCSI_SSC2_WRITE_FILEMARKS_6             0x10
371
372 static const value_string scsi_ssc2_val[] = {
373     {SCSI_SSC2_ERASE_16                    , "Erase(16)"},
374     {SCSI_SSC2_FORMAT_MEDIUM               , "Format Medium"},
375     {SCSI_SSC2_LOAD_UNLOAD                 , "Load Unload"},
376     {SCSI_SSC2_LOCATE_16                   , "Locate(16)"},
377     {SCSI_SSC2_READ_16                     , "Read(16)"},
378     {SCSI_SSC2_READ_BLOCK_LIMITS           , "Read Block Limits"},
379     {SCSI_SSC2_READ_POSITION               , "Read Position"},
380     {SCSI_SSC2_READ_REVERSE_16             , "Read Reverse(16)"},
381     {SCSI_SSC2_RECOVER_BUFFERED_DATA       , "Recover Buffered Data"},
382     {SCSI_SSC2_REPORT_DENSITY_SUPPORT      , "Report Density Support"},
383     {SCSI_SSC2_REWIND                      , "Rewind"},
384     {SCSI_SSC2_SET_CAPACITY                , "Set Capacity"},
385     {SCSI_SSC2_SPACE_16                    , "Space(16)"},
386     {SCSI_SSC2_VERIFY_16                   , "Verify(16)"},
387     {SCSI_SSC2_WRITE_16                    , "Write(16)"},
388     {SCSI_SSC2_WRITE_FILEMARKS_16          , "Write Filemarks(16)"},
389     {SCSI_SSC2_ERASE_6                     , "Erase(6)"},
390     {SCSI_SSC2_LOCATE_10                   , "Locate(10)"},
391     {SCSI_SSC2_LOCATE_16                   , "Locate(16)"},
392     {SCSI_SSC2_READ6                       , "Read(6)"},
393     {SCSI_SSC2_READ_REVERSE_6              , "Read Reverse(6)"},
394     {SCSI_SSC2_SPACE_6                     , "Space(6)"},
395     {SCSI_SSC2_VERIFY_6                    , "Verify(6)"},
396     {SCSI_SSC2_WRITE6                      , "Write(6)"},
397     {SCSI_SSC2_WRITE_FILEMARKS_6           , "Write Filemarks(6)"},
398     {0, NULL},
399 };
400
401 /* SMC2 Commands */
402 #define SCSI_SMC2_EXCHANGE_MEDIUM                 0x40
403 #define SCSI_SMC2_INITIALIZE_ELEMENT_STATUS       0x07
404 #define SCSI_SMC2_INITIALIZE_ELEMENT_STATUS_RANGE 0x37
405 #define SCSI_SMC2_MOVE_MEDIUM                     0xA5
406 #define SCSI_SMC2_MOVE_MEDIUM_ATTACHED            0xA7
407 #define SCSI_SMC2_POSITION_TO_ELEMENT             0x2B
408 #define SCSI_SMC2_READ_ATTRIBUTE                  0x8C
409 #define SCSI_SMC2_READ_ELEMENT_STATUS             0xB8
410 #define SCSI_SMC2_READ_ELEMENT_STATUS_ATTACHED    0xB4
411 #define SCSI_SMC2_REQUEST_VOLUME_ELEMENT_ADDRESS  0xB5
412 #define SCSI_SMC2_SEND_VOLUME_TAG                 0xB6
413 #define SCSI_SMC2_WRITE_ATTRIBUTE                 0x8D
414
415 static const value_string scsi_smc2_val[] = {
416     {SCSI_SMC2_EXCHANGE_MEDIUM                , "Exchange Medium"},
417     {SCSI_SMC2_INITIALIZE_ELEMENT_STATUS      , "Initialize Element Status"},
418     {SCSI_SMC2_INITIALIZE_ELEMENT_STATUS_RANGE, "Initialize Element Status With Range"},
419     {SCSI_SMC2_MOVE_MEDIUM                    , "Move Medium"},
420     {SCSI_SMC2_MOVE_MEDIUM_ATTACHED           , "Move Medium Attached"},
421     {SCSI_SMC2_POSITION_TO_ELEMENT            , "Position To Element"},
422     {SCSI_SMC2_READ_ATTRIBUTE                 , "Read Attribute"},
423     {SCSI_SMC2_READ_ELEMENT_STATUS            , "Read Element Status"},
424     {SCSI_SMC2_READ_ELEMENT_STATUS_ATTACHED   , "Read Element Status Attached"},
425     {SCSI_SMC2_REQUEST_VOLUME_ELEMENT_ADDRESS , "Request Volume Element Address"},
426     {SCSI_SMC2_SEND_VOLUME_TAG                , "Send Volume Tag"},
427     {SCSI_SMC2_WRITE_ATTRIBUTE                , "Write Attribute"},
428     {0, NULL},
429 };
430
431 #define SCSI_EVPD_SUPPPG          0x00
432 #define SCSI_EVPD_DEVSERNUM       0x80
433 #define SCSI_EVPD_OPER            0x81
434 #define SCSI_EVPD_ASCIIOPER       0x82
435 #define SCSI_EVPD_DEVID           0x83
436
437 static const value_string scsi_evpd_pagecode_val[] = {
438     {SCSI_EVPD_SUPPPG,    "Supported Vital Product Data Pages"},
439     {0x01,                "ASCII Information Page"},
440     {0x02,                "ASCII Information Page"},
441     {0x03,                "ASCII Information Page"},
442     {0x04,                "ASCII Information Page"},
443     {0x05,                "ASCII Information Page"},
444     {0x06,                "ASCII Information Page"},
445     {0x07,                "ASCII Information Page"},
446     /* XXX - 0x01 through 0x7F are all ASCII information pages */
447     {SCSI_EVPD_DEVSERNUM, "Unit Serial Number Page"},
448     {SCSI_EVPD_OPER,      "Implemented Operating Definition Page"},
449     {SCSI_EVPD_ASCIIOPER, "ASCII Implemented Operating Definition Page"},
450     {SCSI_EVPD_DEVID,     "Device Identification Page"},
451     {0, NULL},
452 };
453
454 static const value_string scsi_logsel_pc_val[] = {
455     {0, "Current Threshold Values"},
456     {1, "Current Cumulative Values"},
457     {2, "Default Threshold Values"},
458     {3, "Default Cumulative Values"},
459     {0, NULL},
460 };
461
462 static const value_string scsi_logsns_pc_val[] = {
463     {0, "Threshold Values"},
464     {1, "Cumulative Values"},
465     {2, "Default Threshold Values"},
466     {3, "Default Cumulative Values"},
467     {0, NULL},
468 };
469
470 static const value_string scsi_logsns_page_val[] = {
471     {0xF, "Application Client Page"},
472     {0x1, "Buffer Overrun/Underrun Page"},
473     {0x3, "Error Counter (read) Page"},
474     {0x4, "Error Counter (read reverse) Page"},
475     {0x5, "Error Counter (verify) Page"},
476     {0x1, "Error Counter (write) Page"},
477     {0xB, "Last n Deferred Errors or Async Events Page"},
478     {0x7, "Last n Error Events Page"},
479     {0x6, "Non-medium Error Page"},
480     {0x10, "Self-test Results Page"},
481     {0xE, "Start-Stop Cycle Counter Page"},
482     {0x0, "Supported Log Pages"},
483     {0xD, "Temperature Page"},
484     {0, NULL},
485 };
486
487 static const value_string scsi_modesns_pc_val[] = {
488     {0, "Current Values"},
489     {1, "Changeable Values"},
490     {2, "Default Values"},
491     {3, "Saved Values"},
492     {0, NULL},
493 };
494
495 #define SCSI_SPC2_MODEPAGE_CTL      0x0A
496 #define SCSI_SPC2_MODEPAGE_DISCON   0x02
497 #define SCSI_SCSI2_MODEPAGE_PERDEV  0x09  /* Obsolete in SPC-2; generic in SCSI-2 */
498 #define SCSI_SPC2_MODEPAGE_INFOEXCP 0x1C
499 #define SCSI_SPC2_MODEPAGE_PWR      0x1A
500 #define SCSI_SPC2_MODEPAGE_LUN      0x18
501 #define SCSI_SPC2_MODEPAGE_PORT     0x19
502 #define SCSI_SPC2_MODEPAGE_VEND     0x00
503
504 static const value_string scsi_spc2_modepage_val[] = {
505     {SCSI_SPC2_MODEPAGE_CTL,      "Control"},
506     {SCSI_SPC2_MODEPAGE_DISCON,   "Disconnect-Reconnect"},
507     {SCSI_SCSI2_MODEPAGE_PERDEV,  "Peripheral Device"},
508     {SCSI_SPC2_MODEPAGE_INFOEXCP, "Informational Exceptions Control"},
509     {SCSI_SPC2_MODEPAGE_PWR,      "Power Condition"},
510     {SCSI_SPC2_MODEPAGE_LUN,      "Protocol Specific LUN"},
511     {SCSI_SPC2_MODEPAGE_PORT,     "Protocol-Specific Port"},
512     {SCSI_SPC2_MODEPAGE_VEND,     "Vendor Specific Page"},
513     {0x3F,                        "Return All Mode Pages"},
514     {0, NULL},
515 };
516
517 #define SCSI_SBC2_MODEPAGE_RDWRERR  0x01
518 #define SCSI_SBC2_MODEPAGE_FMTDEV   0x03
519 #define SCSI_SBC2_MODEPAGE_DISKGEOM 0x04
520 #define SCSI_SBC2_MODEPAGE_FLEXDISK 0x05
521 #define SCSI_SBC2_MODEPAGE_VERERR   0x07
522 #define SCSI_SBC2_MODEPAGE_CACHE    0x08
523 #define SCSI_SBC2_MODEPAGE_MEDTYPE  0x0B
524 #define SCSI_SBC2_MODEPAGE_NOTPART  0x0C
525 #define SCSI_SBC2_MODEPAGE_XORCTL   0x10
526
527 static const value_string scsi_sbc2_modepage_val[] = {
528     {SCSI_SBC2_MODEPAGE_RDWRERR,  "Read/Write Error Recovery"},
529     {SCSI_SBC2_MODEPAGE_FMTDEV,   "Format Device"},
530     {SCSI_SBC2_MODEPAGE_DISKGEOM, "Rigid Disk Geometry"},
531     {SCSI_SBC2_MODEPAGE_FLEXDISK, "Flexible Disk"},
532     {SCSI_SBC2_MODEPAGE_VERERR,   "Verify Error Recovery"},
533     {SCSI_SBC2_MODEPAGE_CACHE,    "Caching"},
534     {SCSI_SBC2_MODEPAGE_MEDTYPE,  "Medium Types Supported"},
535     {SCSI_SBC2_MODEPAGE_NOTPART,  "Notch & Partition"},
536     {SCSI_SBC2_MODEPAGE_XORCTL,   "XOR Control"},
537     {0x3F,                        "Return All Mode Pages"},
538     {0, NULL},
539 };
540
541 #define SCSI_SSC2_MODEPAGE_DATACOMP 0x0F  /* data compression */
542 #define SCSI_SSC2_MODEPAGE_DEVCONF  0x10  /* device configuration */
543 #define SCSI_SSC2_MODEPAGE_MEDPAR1  0x11  /* medium partition (1) */
544 #define SCSI_SSC2_MODEPAGE_MEDPAR2  0x12  /* medium partition (2) */
545 #define SCSI_SSC2_MODEPAGE_MEDPAR3  0x13  /* medium partition (3) */
546 #define SCSI_SSC2_MODEPAGE_MEDPAR4  0x14  /* medium partition (4) */
547
548 static const value_string scsi_ssc2_modepage_val[] = {
549     {SCSI_SSC2_MODEPAGE_DATACOMP, "Data Compression"},
550     {SCSI_SSC2_MODEPAGE_DEVCONF,  "Device Configuration"},
551     {SCSI_SSC2_MODEPAGE_MEDPAR1,  "Medium Partition (1)"},
552     {SCSI_SSC2_MODEPAGE_MEDPAR2,  "Medium Partition (2)"},
553     {SCSI_SSC2_MODEPAGE_MEDPAR3,  "Medium Partition (3)"},
554     {SCSI_SSC2_MODEPAGE_MEDPAR4,  "Medium Partition (4)"},
555     {0x3F,                        "Return All Mode Pages"},
556     {0, NULL},
557 };
558
559 #define SCSI_SMC2_MODEPAGE_EAA      0x1D  /* element address assignment */
560 #define SCSI_SMC2_MODEPAGE_TRANGEOM 0x1E  /* transport geometry parameters */
561 #define SCSI_SMC2_MODEPAGE_DEVCAP   0x1F  /* device capabilities */
562
563 static const value_string scsi_smc2_modepage_val[] = {
564     {SCSI_SMC2_MODEPAGE_EAA,      "Element Address Assignment"},
565     {SCSI_SMC2_MODEPAGE_TRANGEOM, "Transport Geometry Parameters"},
566     {SCSI_SMC2_MODEPAGE_DEVCAP,   "Device Capabilities"},
567     {0x3F,                        "Return All Mode Pages"},
568     {0, NULL},
569 };
570
571 #define SCSI_SPC2_RESVIN_SVCA_RDKEYS 0
572 #define SCSI_SPC2_RESVIN_SVCA_RDRESV 1
573
574 static const value_string scsi_persresvin_svcaction_val[] = {
575     {SCSI_SPC2_RESVIN_SVCA_RDKEYS, "Read Keys"},
576     {SCSI_SPC2_RESVIN_SVCA_RDRESV, "Read Reservation"},
577     {0, NULL},
578 };
579
580 static const value_string scsi_persresvout_svcaction_val[] = {
581     {0, "Register"},
582     {1, "Reserve"},
583     {2, "Release"},
584     {3, "Clear"},
585     {4, "Preempt"},
586     {5, "Preempt & Abort"},
587     {6, "Register & Ignore Existing Key"},
588     {0, NULL},
589 };
590
591 static const value_string scsi_persresv_scope_val[] = {
592     {0, "LU Scope"},
593     {1, "Obsolete"},
594     {2, "Element Scope"},
595     {0, NULL},
596 };
597
598 static const value_string scsi_persresv_type_val[] = {
599     {1, "Write Excl"},
600     {3, "Excl Access"},
601     {5, "Write Excl, Registrants Only"},
602     {7, "Excl Access, Registrants Only"},
603     {0, NULL},
604 };
605
606 static const value_string scsi_qualifier_val[] = {
607     {0x0, "Device type is connected to logical unit"},
608     {0x1, "Device type is supported by server but is not connected to logical unit"},
609     {0x3, "Device type is not supported by server"},
610 };
611
612 static const value_string scsi_devtype_val[] = {
613     {SCSI_DEV_SBC   , "Direct Access Device"},
614     {SCSI_DEV_SSC   , "Sequential Access Device"},
615     {SCSI_DEV_PRNT  , "Printer"},
616     {SCSI_DEV_PROC  , "Processor"},
617     {SCSI_DEV_WORM  , "WORM"},
618     {SCSI_DEV_CDROM , "CD-ROM"},
619     {SCSI_DEV_SCAN  , "Scanner"},
620     {SCSI_DEV_OPTMEM, "Optical Memory"},
621     {SCSI_DEV_SMC   , "Medium Changer"},
622     {SCSI_DEV_COMM  , "Communication"},
623     {SCSI_DEV_RAID  , "Storage Array"},
624     {SCSI_DEV_SES   , "Enclosure Services"},
625     {SCSI_DEV_RBC   , "Simplified Block Device"},
626     {SCSI_DEV_OCRW  , "Optical Card Reader/Writer"},
627     {SCSI_DEV_OSD   , "Object-based Storage Device"},
628     {SCSI_DEV_ADC   , "Automation/Drive Interface"},
629     {0x1E           , "Well known logical unit"},
630     {SCSI_DEV_NOLUN , "Unknown or no device type"},
631     {0, NULL},
632 };
633
634 static const enum_val_t scsi_devtype_options[] = {
635     {"Block Device", SCSI_DEV_SBC},
636     {"Sequential Device", SCSI_DEV_SSC},
637     {NULL, -1},
638 };
639
640 static const value_string scsi_inquiry_vers_val[] = {
641     {0, "No Compliance to any Standard"},
642     {2, "Compliance to ANSI X3.131:1994"},
643     {3, "Compliance to ANSI X3.301:1997"},
644     {4, "Compliance to SPC-2"},
645     {0x80, "Compliance to ISO/IEC 9316:1995"},
646     {0x82, "Compliance to ISO/IEC 9316:1995 and to ANSI X3.131:1994"},
647     {0x83, "Compliance to ISO/IEC 9316:1995 and to ANSI X3.301:1997"},
648     {0x84, "Compliance to ISO/IEC 9316:1995 and SPC-2"},
649     {0, NULL},
650 };
651
652 static const value_string scsi_modesense_medtype_sbc_val[] = {
653     {0x00, "Default"},
654     {0x01, "Flexible disk, single-sided; unspecified medium"},
655     {0x02, "Flexible disk, double-sided; unspecified medium"},
656     {0x05, "Flexible disk, single-sided, single density; 200mm/8in diameter"},
657     {0x06, "Flexible disk, double-sided, single density; 200mm/8in diameter"},
658     {0x09, "Flexible disk, single-sided, double density; 200mm/8in diameter"},
659     {0x0A, "Flexible disk, double-sided, double density; 200mm/8in diameter"},
660     {0x0D, "Flexible disk, single-sided, single density; 130mm/5.25in diameter"},
661     {0x12, "Flexible disk, double-sided, single density; 130mm/5.25in diameter"},
662     {0x16, "Flexible disk, single-sided, double density; 130mm/5.25in diameter"},
663     {0x1A, "Flexible disk, double-sided, double density; 130mm/5.25in diameter"},
664     {0x1E, "Flexible disk, double-sided; 90mm/3.5in diameter"},
665     {0x40, "Direct-access magnetic tape, 12 tracks"},
666     {0x44, "Direct-access magnetic tape, 24 tracks"},
667     {0, NULL},
668 };
669
670 static const value_string scsi_verdesc_val[] = {
671     {0x0d40, "FC-AL (No Version)"},
672     {0x0d5c, "FC-AL ANSI X3.272:1996"},
673     {0x0d60, "FC-AL-2 (no version claimed)"},
674     {0x0d7c, "FC-AL-2 ANSI NCITS.332:1999"},
675     {0x0d61, "FC-AL-2 T11/1133 revision 7.0"},
676     {0x1320, "FC-FLA (no version claimed)"},
677     {0x133c, "FC-FLA ANSI NCITS TR-20:1998"},
678     {0x133b, "FC-FLA T11/1235 revision 7"},
679     {0x0da0, "FC-FS (no version claimed)"},
680     {0x0db7, "FC-FS T11/1331 revision 1.2"},
681     {0x08c0, "FCP (no version claimed)"},
682     {0x08dc, "FCP ANSI X3.269:1996"},
683     {0x08db, "FCP T10/0993 revision 12"},
684     {0x1340, "FC-PLDA (no version claimed)"},
685     {0x135c, "FC-PLDA ANSI NCITS TR-19:1998"},
686     {0x135b, "FC-PLDA T11/1162 revision 2.1"},
687     {0x0900, "FCP-2 (no version claimed)"},
688     {0x0901, "FCP-2 T10/1144 revision 4"},
689     {0x003c, "SAM ANSI X3.270:1996"},
690     {0x003b, "SAM T10/0994 revision 18"},
691     {0x0040, "SAM-2 (no version claimed)"},
692     {0x0020, "SAM (no version claimed)"},
693     {0x0180, "SBC (no version claimed)"},
694     {0x019c, "SBC ANSI NCITS.306:1998"},
695     {0x019b, "SBC T10/0996 revision 08c"},
696     {0x0320, "SBC-2 (no version claimed)"},
697     {0x01c0, "SES (no version claimed)"},
698     {0x01dc, "SES ANSI NCITS.305:1998"},
699     {0x01db, "SES T10/1212 revision 08b"},
700     {0x01de, "SES ANSI NCITS.305:1998 w/ Amendment ANSI NCITS.305/AM1:2000"},
701     {0x01dd, "SES T10/1212 revision 08b w/ Amendment ANSI NCITS.305/AM1:2000"},
702     {0x0120, "SPC (no version claimed)"},
703     {0x013c, "SPC ANSI X3.301:1997"},
704     {0x013b, "SPC T10/0995 revision 11a"},
705     {0x0260, "SPC-2 (no version claimed)"},
706     {0x0267, "SPC-2 T10/1236 revision 12"},
707     {0x0269, "SPC-2 T10/1236 revision 18"},
708     {0x0300, "SPC-3 (no version claimed)"},
709     {0x0960, "iSCSI (no version claimed)"},
710     {0x0d80, "FC-PH-3 (no version claimed)"},
711     {0x0d9c, "FC-PH-3 ANSI X3.303-1998"},
712     {0x0d20, "FC-PH (no version claimed)"},
713     {0, NULL},
714 };
715
716 /* Command Support Data "Support" field definitions */
717 static const value_string scsi_cmdt_supp_val[] = {
718     {0, "Data not currently available"},
719     {1, "SCSI Command not supported"},
720     {2, "Reserved"},
721     {3, "SCSI Command supported in conformance with a SCSI standard"},
722     {4, "Vendor Specific"},
723     {5, "SCSI Command supported in a vendor specific manner"},
724     {6, "Vendor Specific"},
725     {7, "Reserved"},
726     {0, NULL},
727 };
728
729 #define CODESET_BINARY  1
730 #define CODESET_ASCII   2
731
732 static const value_string scsi_devid_codeset_val[] = {
733     {0,              "Reserved"},
734     {CODESET_BINARY, "Identifier field contains binary values"},
735     {CODESET_ASCII,  "Identifier field contains ASCII graphic codes"},
736     {0,              NULL},
737 };
738
739 static const value_string scsi_devid_assoc_val[] = {
740     {0, "Identifier is associated with addressed logical/physical device"},
741     {1, "Identifier is associated with the port that received the request"},
742     {0, NULL},
743 };
744
745 static const value_string scsi_devid_idtype_val[] = {
746     {0, "Vendor-specific ID (non-globally unique)"},
747     {1, "Vendor-ID + vendor-specific ID (globally unique)"},
748     {2, "EUI-64 ID"},
749     {3, "WWN"},
750     {4, "4-byte Binary Number/Reserved"},
751     {0, NULL},
752 };
753
754 static const value_string scsi_modesns_mrie_val[] = {
755     {0, "No Reporting of Informational Exception Condition"},
756     {1, "Asynchronous Error Reporting"},
757     {2, "Generate Unit Attention"},
758     {3, "Conditionally Generate Recovered Error"},
759     {4, "Unconditionally Generate Recovered Error"},
760     {5, "Generate No Sense"},
761     {6, "Only Report Informational Exception Condition on Request"},
762     {0, NULL},
763 };
764
765 static const value_string scsi_modesns_tst_val[] = {
766     {0, "Task Set Per LU For All Initiators"},
767     {1, "Task Set Per Initiator Per LU"},
768     {0, NULL},
769 };
770
771 static const value_string scsi_modesns_qmod_val[] = {
772     {0, "Restricted reordering"},
773     {1, "Unrestricted reordering"},
774     {0, NULL},
775 };
776
777 static const true_false_string scsi_modesns_qerr_val = {
778     "All blocked tasks shall be aborted on CHECK CONDITION",
779     "Blocked tasks shall resume after ACA/CA is cleared",
780 };
781
782 static const true_false_string scsi_modesns_tas_val = {
783     "Terminated tasks aborted without informing initiators",
784     "Tasks aborted by another initiator terminated with TASK ABORTED",
785 };
786
787 static const true_false_string scsi_modesns_rac_val = {
788     "Report a CHECK CONDITION Instead of Long Busy Condition",
789     "Long Busy Conditions Maybe Reported",
790 };
791
792 /* SCSI Transport Protocols */
793 #define SCSI_PROTO_FCP          0
794 #define SCSI_PROTO_iSCSI        5
795
796 static const value_string scsi_proto_val[] = {
797     {0, "FCP"},
798     {5, "iSCSI"},
799     {0, NULL},
800 };
801
802 static const value_string scsi_fcp_rrtov_val[] = {
803     {0, "No Timer Specified"},
804     {1, "0.001 secs"},
805     {3, "0.1 secs"},
806     {5, "10 secs"},
807     {0, NULL},
808 };
809
810 static const value_string scsi_sensekey_val[] = {
811     {0x0, "No Sense"},
812     {0x1, "Recovered Error"},
813     {0x2, "Not Ready"},
814     {0x3, "Medium Error"},
815     {0x4, "Hardware Error"},
816     {0x5, "Illegal Request"},
817     {0x6, "Unit Attention"},
818     {0x7, "Data Protection"},
819     {0x8, "Blank Check"},
820     {0x9, "Vendor Specific"},
821     {0xA, "Copy Aborted"},
822     {0xB, "Command Aborted"},
823     {0xC, "Obsolete Error Code"},
824     {0xD, "Overflow Command"},
825     {0xE, "Miscompare"},
826     {0xF, "Reserved"},
827     {0, NULL},
828 };
829
830 static const value_string scsi_sns_errtype_val[] = {
831     {0x70, "Current Error"},
832     {0x71, "Deferred Error"},
833     {0x7F, "Vendor Specific"},
834     {0, NULL},
835 };
836
837 static const value_string scsi_asc_val[] = {
838     {0x0000,  "No Additional Sense Information"},
839     {0x0006,  "I/O Process Terminated"},
840     {0x0016,  "Operation In Progress"},
841     {0x0017,  "Cleaning Requested"},
842     {0x0100,  "No Index/Sector Signal"},
843     {0x0200,  "No Seek Complete"},
844     {0x0300,  "Peripheral Device Write Fault"},
845     {0x0400,  "Logical Unit Not Ready, Cause Not Reportable"},
846     {0x0401,  "Logical Unit Is In Process Of Becoming Ready"},
847     {0x0402,  "Logical Unit Not Ready, Initializing Cmd. Required"},
848     {0x0403,  "Logical Unit Not Ready, Manual Intervention Required"},
849     {0x0404,  "Logical Unit Not Ready, Format In Progress"},
850     {0x0405,  "Logical Unit Not Ready, Rebuild In Progress"},
851     {0x0406,  "Logical Unit Not Ready, Recalculation In Progress"},
852     {0x0407,  "Logical Unit Not Ready, Operation In Progress"},
853     {0x0409,  "Logical Unit Not Ready, Self-Test In Progress"},
854     {0x0500,  "Logical Unit Does Not Respond To Selection"},
855     {0x0600,  "No Reference Position Found"},
856     {0x0700,  "Multiple Peripheral Devices Selected"},
857     {0x0800,  "Logical Unit Communication Failure"},
858     {0x0801,  "Logical Unit Communication Time-Out"},
859     {0x0802,  "Logical Unit Communication Parity Error"},
860     {0x0803,  "Logical Unit Communication Crc Error (Ultra-Dma/32)"},
861     {0x0804,  "Unreachable Copy Target"},
862     {0x0900,  "Track Following Error"},
863     {0x0904,  "Head Select Fault"},
864     {0x0A00,  "Error Log Overflow"},
865     {0x0B00,  "Warning"},
866     {0x0B01,  "Warning - Specified Temperature Exceeded"},
867     {0x0B02,  "Warning - Enclosure Degraded"},
868     {0x0C02,  "Write Error - Auto Reallocation Failed"},
869     {0x0C03,  "Write Error - Recommend Reassignment"},
870     {0x0C04,  "Compression Check Miscompare Error"},
871     {0x0C05,  "Data Expansion Occurred During Compression"},
872     {0x0C06,  "Block Not Compressible"},
873     {0x0D00,  "Error Detected By Third Party Temporary Initiator"},
874     {0x0D01,  "Third Party Device Failure"},
875     {0x0D02,  "Copy Target Device Not Reachable"},
876     {0x0D03,  "Incorrect Copy Target Device Type"},
877     {0x0D04,  "Copy Target Device Data Underrun"},
878     {0x0D05,  "Copy Target Device Data Overrun"},
879     {0x1000,  "Id Crc Or Ecc Error"},
880     {0x1100,  "Unrecovered Read Error"},
881     {0x1101,  "Read Retries Exhausted"},
882     {0x1102,  "Error Too Long To Correct"},
883     {0x1103,  "Multiple Read Errors"},
884     {0x1104,  "Unrecovered Read Error - Auto Reallocate Failed"},
885     {0x110A,  "Miscorrected Error"},
886     {0x110B,  "Unrecovered Read Error - Recommend Reassignment"},
887     {0x110C,  "Unrecovered Read Error - Recommend Rewrite The Data"},
888     {0x110D,  "De-Compression Crc Error"},
889     {0x110E,  "Cannot Decompress Using Declared Algorithm"},
890     {0x1200,  "Address Mark Not Found For Id Field"},
891     {0x1300,  "Address Mark Not Found For Data Field"},
892     {0x1400,  "Recorded Entity Not Found"},
893     {0x1401,  "Record Not Found"},
894     {0x1405,  "Record Not Found - Recommend Reassignment"},
895     {0x1406,  "Record Not Found - Data Auto-Reallocated"},
896     {0x1500,  "Random Positioning Error"},
897     {0x1501,  "Mechanical Positioning Error"},
898     {0x1502,  "Positioning Error Detected By Read Of Medium"},
899     {0x1600,  "Data Synchronization Mark Error"},
900     {0x1601,  "Data Sync Error - Data Rewritten"},
901     {0x1602,  "Data Sync Error - Recommend Rewrite"},
902     {0x1603,  "Data Sync Error - Data Auto-Reallocated"},
903     {0x1604,  "Data Sync Error - Recommend Reassignment"},
904     {0x1700,  "Recovered Data With No Error Correction Applied"},
905     {0x1701,  "Recovered Data With Retries"},
906     {0x1702,  "Recovered Data With Positive Head Offset"},
907     {0x1703,  "Recovered Data With Negative Head Offset"},
908     {0x1705,  "Recovered Data Using Previous Sector Id"},
909     {0x1706,  "Recovered Data Without Ecc - Data Auto-Reallocated"},
910     {0x1707,  "Recovered Data Without Ecc - Recommend Reassignment"},
911     {0x1708,  "Recovered Data Without Ecc - Recommend Rewrite"},
912     {0x1709,  "Recovered Data Without Ecc - Data Rewritten"},
913     {0x1800,  "Recovered Data With Error Correction Applied"},
914     {0x1801,  "Recovered Data With Error Corr. & Retries Applied"},
915     {0x1802,  "Recovered Data - Data Auto-Reallocated"},
916     {0x1805,  "Recovered Data - Recommend Reassignment"},
917     {0x1806,  "Recovered Data - Recommend Rewrite"},
918     {0x1807,  "Recovered Data With Ecc - Data Rewritten"},
919     {0x1900,  "List Error"},
920     {0x1901,  "List Not Available"},
921     {0x1902,  "List Error In Primary List"},
922     {0x1903,  "List Error In Grown List"},
923     {0x1A00,  "Parameter List Length Error"},
924     {0x1B00,  "Synchronous Data Transfer Error"},
925     {0x1C00,  "Defect List Not Found"},
926     {0x1C01,  "Primary Defect List Not Found"},
927     {0x1C02,  "Grown Defect List Not Found"},
928     {0x1D00,  "Miscompare During Verify Operation"},
929     {0x1E00,  "Recovered Id With Ecc Correction"},
930     {0x1F00,  "Defect List Transfer"},
931     {0x2000,  "Invalid Command Operation Code"},
932     {0x2100,  "Logical Block Address Out Of Range"},
933     {0x2101,  "Invalid Element Address"},
934     {0x2400,  "Invalid Field In Cdb"},
935     {0x2401,  "Cdb Decryption Error"},
936     {0x2500,  "Logical Unit Not Supported"},
937     {0x2600,  "Invalid Field In Parameter List"},
938     {0x2601,  "Parameter Not Supported"},
939     {0x2602,  "Parameter Value Invalid"},
940     {0x2603,  "Threshold Parameters Not Supported"},
941     {0x2604,  "Invalid Release Of Persistent Reservation"},
942     {0x2605,  "Data Decryption Error"},
943     {0x2606,  "Too Many Target Descriptors"},
944     {0x2607,  "Unsupported Target Descriptor Type Code"},
945     {0x2608,  "Too Many Segment Descriptors"},
946     {0x2609,  "Unsupported Segment Descriptor Type Code"},
947     {0x260A,  "Unexpected Inexact Segment"},
948     {0x260B,  "Inline Data Length Exceeded"},
949     {0x260C,  "Invalid Operation For Copy Source Or Destination"},
950     {0x260D,  "Copy Segment Granularity Violation"},
951     {0x2700,  "Write Protected"},
952     {0x2701,  "Hardware Write Protected"},
953     {0x2702,  "Logical Unit Software Write Protected"},
954     {0x2800,  "Not Ready To Ready Change, Medium May Have Changed"},
955     {0x2801,  "Import Or Export Element Accessed"},
956     {0x2900,  "Power On, Reset, Or Bus Device Reset Occurred"},
957     {0x2901,  "Power On Occurred"},
958     {0x2902,  "Scsi Bus Reset Occurred"},
959     {0x2903,  "Bus Device Reset Function Occurred"},
960     {0x2904,  "Device Internal Reset"},
961     {0x2905,  "Transceiver Mode Changed To Single-Ended"},
962     {0x2906,  "Transceiver Mode Changed To Lvd"},
963     {0x2A00,  "Parameters Changed"},
964     {0x2A01,  "Mode Parameters Changed"},
965     {0x2A02,  "Log Parameters Changed"},
966     {0x2A03,  "Reservations Preempted"},
967     {0x2A04,  "Reservations Released"},
968     {0x2A05,  "Registrations Preempted"},
969     {0x2B00,  "Copy Cannot Execute Since Host Cannot Disconnect"},
970     {0x2C00,  "Command Sequence Error"},
971     {0x2F00,  "Commands Cleared By Another Initiator"},
972     {0x3000,  "Incompatible Medium Installed"},
973     {0x3001,  "Cannot Read Medium - Unknown Format"},
974     {0x3002,  "Cannot Read Medium - Incompatible Format"},
975     {0x3003,  "Cleaning Cartridge Installed"},
976     {0x3004,  "Cannot Write Medium - Unknown Format"},
977     {0x3005,  "Cannot Write Medium - Incompatible Format"},
978     {0x3006,  "Cannot Format Medium - Incompatible Medium"},
979     {0x3007,  "Cleaning Failure"},
980     {0x3100,  "Medium Format Corrupted"},
981     {0x3101,  "Format Command Failed"},
982     {0x3200,  "No Defect Spare Location Available"},
983     {0x3201,  "Defect List Update Failure"},
984     {0x3400,  "Enclosure Failure"},
985     {0x3500,  "Enclosure Services Failure"},
986     {0x3501,  "Unsupported Enclosure Function"},
987     {0x3502,  "Enclosure Services Unavailable"},
988     {0x3503,  "Enclosure Services Transfer Failure"},
989     {0x3504,  "Enclosure Services Transfer Refused"},
990     {0x3700,  "Rounded Parameter"},
991     {0x3900,  "Saving Parameters Not Supported"},
992     {0x3A00,  "Medium Not Present"},
993     {0x3A01,  "Medium Not Present - Tray Closed"},
994     {0x3A02,  "Medium Not Present - Tray Open"},
995     {0x3A03,  "Medium Not Present - Loadable"},
996     {0x3A04,  "Medium Not Present - Medium Auxiliary Memory Accessible"},
997     {0x3B0D,  "Medium Destination Element Full"},
998     {0x3B0E,  "Medium Source Element Empty"},
999     {0x3B11,  "Medium Magazine Not Accessible"},
1000     {0x3B12,  "Medium Magazine Removed"},
1001     {0x3B13,  "Medium Magazine Inserted"},
1002     {0x3B14,  "Medium Magazine Locked"},
1003     {0x3B15,  "Medium Magazine Unlocked"},
1004     {0x3D00,  "Invalid Bits In Identify Message"},
1005     {0x3E00,  "Logical Unit Has Not Self-Configured Yet"},
1006     {0x3E01,  "Logical Unit Failure"},
1007     {0x3E02,  "Timeout On Logical Unit"},
1008     {0x3E03,  "Logical Unit Failed Self-Test"},
1009     {0x3E04,  "Logical Unit Unable To Update Self-Test Log"},
1010     {0x3F00,  "Target Operating Conditions Have Changed"},
1011     {0x3F01,  "Microcode Has Been Changed"},
1012     {0x3F02,  "Changed Operating Definition"},
1013     {0x3F03,  "Inquiry Data Has Changed"},
1014     {0x3F04,  "Component Device Attached"},
1015     {0x3F05,  "Device Identifier Changed"},
1016     {0x3F06,  "Redundancy Group Created Or Modified"},
1017     {0x3F07,  "Redundancy Group Deleted"},
1018     {0x3F08,  "Spare Created Or Modified"},
1019     {0x3F09,  "Spare Deleted"},
1020     {0x3F0A,  "Volume Set Created Or Modified"},
1021     {0x3F0B,  "Volume Set Deleted"},
1022     {0x3F0C,  "Volume Set Deassigned"},
1023     {0x3F0D,  "Volume Set Reassigned"},
1024     {0x3F0E,  "Reported Luns Data Has Changed"},
1025     {0x3F0F,  "Echo Buffer Overwritten"},
1026     {0x3F10,  "Medium Loadable"},
1027     {0x3F11,  "Medium Auxiliary Memory Accessible"},
1028     {0x4200,  "Self-Test Failure (Should Use 40 Nn)"},
1029     {0x4300,  "Message Error"},
1030     {0x4400,  "Internal Target Failure"},
1031     {0x4500,  "Select Or Reselect Failure"},
1032     {0x4600,  "Unsuccessful Soft Reset"},
1033     {0x4700,  "Scsi Parity Error"},
1034     {0x4701,  "Data Phase Crc Error Detected"},
1035     {0x4702,  "Scsi Parity Error Detected During St Data Phase"},
1036     {0x4703,  "Information Unit Crc Error Detected"},
1037     {0x4704,  "Asynchronous Information Protection Error Detected"},
1038     {0x4800,  "Initiator Detected Error Message Received"},
1039     {0x4900,  "Invalid Message Error"},
1040     {0x4A00,  "Command Phase Error"},
1041     {0x4B00,  "Data Phase Error"},
1042     {0x4C00,  "Logical Unit Failed Self-Configuration"},
1043     {0x4D00,  "Tagged Overlapped Commands (Nn = Queue Tag)"},
1044     {0x4E00,  "Overlapped Commands Attempted"},
1045     {0x5300,  "Media Load Or Eject Failed"},
1046     {0x5302,  "Medium Removal Prevented"},
1047     {0x5501,  "System Buffer Full"},
1048     {0x5502,  "Insufficient Reservation Resources"},
1049     {0x5503,  "Insufficient Resources"},
1050     {0x5504,  "Insufficient Registration Resources"},
1051     {0x5A00,  "Operator Request Or State Change Input"},
1052     {0x5A01,  "Operator Medium Removal Request"},
1053     {0x5A02,  "Operator Selected Write Protect"},
1054     {0x5A03,  "Operator Selected Write Permit"},
1055     {0x5B00,  "Log Exception"},
1056     {0x5B01,  "Threshold Condition Met"},
1057     {0x5B02,  "Log Counter At Maximum"},
1058     {0x5B03,  "Log List Codes Exhausted"},
1059     {0x5C00,  "Change"},
1060     {0x5C02,  "Synchronized"},
1061     {0x5D00,  "Failure Prediction Threshold Exceeded"},
1062     {0x5D10,  "Failure General Hard Drive Failure"},
1063     {0x5D11,  "Failure Drive Error Rate Too High"},
1064     {0x5D12,  "Failure Data Error Rate Too High"},
1065     {0x5D13,  "Failure Seek Error Rate Too High"},
1066     {0x5D14,  "Failure Too Many Block Reassigns"},
1067     {0x5D15,  "Failure Access Times Too High"},
1068     {0x5D16,  "Failure Start Unit Times Too High"},
1069     {0x5D17,  "Failure Channel Parametrics"},
1070     {0x5D18,  "Failure Controller Detected"},
1071     {0x5D19,  "Failure Throughput Performance"},
1072     {0x5D1A,  "Failure Seek Time Performance"},
1073     {0x5D1B,  "Failure Spin-Up Retry Count"},
1074     {0x5D1C,  "Failure Drive Calibration Retry"},
1075     {0x5D20,  "Failure General Hard Drive Failure"},
1076     {0x5D21,  "Failure Drive Error Rate Too High"},
1077     {0x5D22,  "Failure Data Error Rate Too High"},
1078     {0x5D23,  "Failure Seek Error Rate Too High"},
1079     {0x5D24,  "Failure Too Many Block Reassigns"},
1080     {0x5D25,  "Failure Access Times Too High"},
1081     {0x5D26,  "Failure Start Unit Times Too High"},
1082     {0x5D27,  "Failure Channel Parametrics"},
1083     {0x5D28,  "Failure Controller Detected"},
1084     {0x5D29,  "Failure Throughput Performance"},
1085     {0x5D2A,  "Failure Seek Time Performance"},
1086     {0x5D2B,  "Failure Spin-Up Retry Count"},
1087     {0x5D2C,  "Failure Drive Calibration Retry"},
1088     {0x5D30,  "Impending Failure General Hard Drive"},
1089     {0x5D31,  "Impending Failure Drive Error Rate Too High"},
1090     {0x5D32,  "Impending Failure Data Error Rate Too High"},
1091     {0x5D33,  "Impending Failure Seek Error Rate Too High"},
1092     {0x5D34,  "Impending Failure Too Many Block Reassigns"},
1093     {0x5D35,  "Impending Failure Access Times Too High"},
1094     {0x5D36,  "Impending Failure Start Unit Times Too High"},
1095     {0x5D37,  "Impending Failure Channel Parametrics"},
1096     {0x5D38,  "Impending Failure Controller Detected"},
1097     {0x5D39,  "Impending Failure Throughput Performance"},
1098     {0x5D3A,  "Impending Failure Seek Time Performance"},
1099     {0x5D3B,  "Impending Failure Spin-Up Retry Count"},
1100     {0x5D3C,  "Impending Failure Drive Calibration Retry"},
1101     {0x5D40,  "Failure General Hard Drive Failure"},
1102     {0x5D41,  "Failure Drive Error Rate Too High"},
1103     {0x5D42,  "Failure Data Error Rate Too High"},
1104     {0x5D43,  "Failure Seek Error Rate Too High"},
1105     {0x5D44,  "Failure Too Many Block Reassigns"},
1106     {0x5D45,  "Failure Access Times Too High"},
1107     {0x5D46,  "Failure Start Unit Times Too High"},
1108     {0x5D47,  "Failure Channel Parametrics"},
1109     {0x5D48,  "Failure Controller Detected"},
1110     {0x5D49,  "Failure Throughput Performance"},
1111     {0x5D4A,  "Failure Seek Time Performance"},
1112     {0x5D4B,  "Failure Spin-Up Retry Count"},
1113     {0x5D4C,  "Failure Drive Calibration Retry Count"},
1114     {0x5D50,  "Failure General Hard Drive Failure"},
1115     {0x5D51,  "Failure Drive Error Rate Too High"},
1116     {0x5D52,  "Failure Data Error Rate Too High"},
1117     {0x5D53,  "Failure Seek Error Rate Too High"},
1118     {0x5D54,  "Failure Too Many Block Reassigns"},
1119     {0x5D55,  "Failure Access Times Too High"},
1120     {0x5D56,  "Failure Start Unit Times Too High"},
1121     {0x5D57,  "Failure Channel Parametrics"},
1122     {0x5D58,  "Failure Controller Detected"},
1123     {0x5D59,  "Failure Throughput Performance"},
1124     {0x5D5A,  "Failure Seek Time Performance"},
1125     {0x5D5B,  "Failure Spin-Up Retry Count"},
1126     {0x5D5C,  "Failure Drive Calibration Retry Count"},
1127     {0x5D60,  "Failure General Hard Drive Failure"},
1128     {0x5D61,  "Failure Drive Error Rate Too High"},
1129     {0x5D62,  "Failure Data Error Rate Too High"},
1130     {0x5D63,  "Failure Seek Error Rate Too High"},
1131     {0x5D64,  "Failure Too Many Block Reassigns"},
1132     {0x5D65,  "Failure Access Times Too High"},
1133     {0x5D66,  "Failure Start Unit Times Too High"},
1134     {0x5D67,  "Failure Channel Parametrics"},
1135     {0x5D68,  "Failure Controller Detected"},
1136     {0x5D69,  "Failure Throughput Performance"},
1137     {0x5D6A,  "Failure Seek Time Performance"},
1138     {0x5D6B,  "Failure Spin-Up Retry Count"},
1139     {0x5D6C,  "Failure Drive Calibration Retry Count"},
1140     {0x5DFF,  "Failure Prediction Threshold Exceeded (False)"},
1141     {0x5E00,  "Low Power Condition On"},
1142     {0x5E01,  "Idle Condition Activated By Timer"},
1143     {0x5E02,  "Standby Condition Activated By Timer"},
1144     {0x5E03,  "Idle Condition Activated By Command"},
1145     {0x5E04,  "Standby Condition Activated By Command"},
1146     {0x6500,  "Voltage Fault"},
1147     {0, NULL},
1148 };
1149
1150 /* SCSI Status Codes */
1151 const value_string scsi_status_val[] = {
1152     {0x00, "Good"},
1153     {0x02, "Check Condition"},
1154     {0x04, "Condition Met"},
1155     {0x08, "Busy"},
1156     {0x10, "Intermediate"},
1157     {0x14, "Intermediate Condition Met"},
1158     {0x18, "Reservation Conflict"},
1159     {0x28, "Task Set Full"},
1160     {0x30, "ACA Active"},
1161     {0x40, "Task Aborted"},
1162     {0, NULL},
1163 };
1164
1165 static gint scsi_def_devtype = SCSI_DEV_SBC;
1166
1167 /*
1168  * We track SCSI requests and responses with a hash table.
1169  * The key is a "scsi_task_id_t" structure; the data is a
1170  * "scsi_task_data_t" structure.
1171  *
1172  * We remember:
1173  *
1174  *    the command code and type of command (it's not present in the
1175  *        response, and we need it to dissect the response);
1176  *    the type of device it's on;
1177  *
1178  * and we also have a field to record flags in case the interpretation
1179  * of the response data depends on data from the command.
1180  */
1181 typedef struct _scsi_task_data {
1182     guint32 opcode;
1183     scsi_cmnd_type cmd;
1184     scsi_device_type devtype;
1185     guint8 flags;
1186 } scsi_task_data_t;
1187
1188 /*
1189  * The next two data structures are used to track SCSI device type.
1190  *
1191  * XXX - it might not be sufficient to use the address of the server
1192  * to which SCSI CDBs are being sent to identify the device, as
1193  *
1194  *      1) a server might have multiple targets or logical units;
1195  *
1196  *      2) a server might make a different logical unit refer to
1197  *         different devices for different clients;
1198  *
1199  * so we should really base this on the connection index for the
1200  * connection and on a device identifier supplied to us by our caller,
1201  * not on a network-layer address.
1202  */
1203 typedef struct _scsi_devtype_key {
1204     address devid;
1205 } scsi_devtype_key_t;
1206
1207 typedef struct _scsi_devtype_data {
1208     scsi_device_type devtype;
1209 } scsi_devtype_data_t;
1210
1211 static GHashTable *scsi_req_hash = NULL;
1212 static GMemChunk *scsi_req_keys = NULL;
1213 static GMemChunk *scsi_req_vals = NULL;
1214 static guint32 scsi_init_count = 25;
1215
1216 static GHashTable *scsidev_req_hash = NULL;
1217 static GMemChunk *scsidev_req_keys = NULL;
1218 static GMemChunk *scsidev_req_vals = NULL;
1219 static guint32 scsidev_init_count = 25;
1220
1221 static dissector_handle_t data_handle;
1222
1223 /*
1224  * Hash Functions
1225  */
1226 static gint
1227 scsi_equal(gconstpointer v, gconstpointer w)
1228 {
1229   const scsi_task_id_t *v1 = (const scsi_task_id_t *)v;
1230   const scsi_task_id_t *v2 = (const scsi_task_id_t *)w;
1231
1232   return (v1->conv_id == v2->conv_id && v1->task_id == v2->task_id);
1233 }
1234
1235 static guint
1236 scsi_hash (gconstpointer v)
1237 {
1238         const scsi_task_id_t *key = (const scsi_task_id_t *)v;
1239         guint val;
1240
1241         val = key->conv_id + key->task_id;
1242
1243         return val;
1244 }
1245
1246 static gint
1247 scsidev_equal (gconstpointer v, gconstpointer w)
1248 {
1249     const scsi_devtype_key_t *k1 = (const scsi_devtype_key_t *)v;
1250     const scsi_devtype_key_t *k2 = (const scsi_devtype_key_t *)w;
1251
1252     if (ADDRESSES_EQUAL (&k1->devid, &k2->devid))
1253         return 1;
1254     else
1255         return 0;
1256 }
1257
1258 static guint
1259 scsidev_hash (gconstpointer v)
1260 {
1261     const scsi_devtype_key_t *key = (const scsi_devtype_key_t *)v;
1262     guint val;
1263     int i;
1264
1265     val = 0;
1266     for (i = 0; i < key->devid.len; i++)
1267         val += key->devid.data[i];
1268     val += key->devid.type;
1269
1270     return val;
1271 }
1272
1273 static scsi_task_data_t *
1274 scsi_new_task (packet_info *pinfo)
1275 {
1276     scsi_task_data_t *cdata = NULL;
1277     scsi_task_id_t ckey, *req_key;
1278
1279     if ((pinfo != NULL) && (pinfo->private_data)) {
1280         ckey = *(scsi_task_id_t *)pinfo->private_data;
1281
1282         cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
1283                                                          &ckey);
1284         if (!cdata) {
1285             req_key = g_mem_chunk_alloc (scsi_req_keys);
1286             *req_key = *(scsi_task_id_t *)pinfo->private_data;
1287
1288             cdata = g_mem_chunk_alloc (scsi_req_vals);
1289
1290             g_hash_table_insert (scsi_req_hash, req_key, cdata);
1291         }
1292     }
1293     return (cdata);
1294 }
1295
1296 static scsi_task_data_t *
1297 scsi_find_task (packet_info *pinfo)
1298 {
1299     scsi_task_data_t *cdata = NULL;
1300     scsi_task_id_t ckey;
1301
1302     if ((pinfo != NULL) && (pinfo->private_data)) {
1303         ckey = *(scsi_task_id_t *)pinfo->private_data;
1304
1305         cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
1306                                                          &ckey);
1307     }
1308     return (cdata);
1309 }
1310
1311 static void
1312 scsi_end_task (packet_info *pinfo)
1313 {
1314     scsi_task_data_t *cdata = NULL;
1315     scsi_task_id_t ckey;
1316
1317     if ((pinfo != NULL) && (pinfo->private_data)) {
1318         ckey = *(scsi_task_id_t *)pinfo->private_data;
1319         cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
1320                                                          &ckey);
1321         if (cdata) {
1322             g_mem_chunk_free (scsi_req_vals, cdata);
1323             g_hash_table_remove (scsi_req_hash, &ckey);
1324         }
1325     }
1326 }
1327
1328 /*
1329  * Protocol initialization
1330  */
1331 static void
1332 free_devtype_key_dev_info(gpointer key_arg, gpointer value_arg _U_,
1333     gpointer user_data _U_)
1334 {
1335         scsi_devtype_key_t *key = key_arg;
1336
1337         if (key->devid.data != NULL) {
1338                 g_free((gpointer)key->devid.data);
1339                 key->devid.data = NULL;
1340         }
1341 }
1342
1343 static void
1344 scsi_init_protocol(void)
1345 {
1346         /*
1347          * First, free up the data for the addresses attached to
1348          * scsi_devtype_key_t structures.  Do so before we free
1349          * those structures or destroy the hash table in which
1350          * they're stored.
1351          */
1352         if (scsidev_req_hash != NULL) {
1353                 g_hash_table_foreach(scsidev_req_hash, free_devtype_key_dev_info,
1354                     NULL);
1355         }
1356
1357         if (scsi_req_keys)
1358             g_mem_chunk_destroy(scsi_req_keys);
1359         if (scsi_req_vals)
1360             g_mem_chunk_destroy(scsi_req_vals);
1361         if (scsidev_req_keys)
1362             g_mem_chunk_destroy (scsidev_req_keys);
1363         if (scsidev_req_vals)
1364             g_mem_chunk_destroy (scsidev_req_vals);
1365         if (scsi_req_hash)
1366             g_hash_table_destroy(scsi_req_hash);
1367         if (scsidev_req_hash)
1368             g_hash_table_destroy (scsidev_req_hash);
1369
1370         scsi_req_hash = g_hash_table_new(scsi_hash, scsi_equal);
1371         scsi_req_keys = g_mem_chunk_new("scsi_req_keys",
1372                                         sizeof(scsi_task_id_t),
1373                                         scsi_init_count *
1374                                         sizeof(scsi_task_id_t),
1375                                         G_ALLOC_AND_FREE);
1376         scsi_req_vals = g_mem_chunk_new("scsi_req_vals",
1377                                         sizeof(scsi_task_data_t),
1378                                         scsi_init_count *
1379                                         sizeof(scsi_task_data_t),
1380                                         G_ALLOC_AND_FREE);
1381         scsidev_req_hash = g_hash_table_new (scsidev_hash, scsidev_equal);
1382         scsidev_req_keys = g_mem_chunk_new("scsidev_req_keys",
1383                                            sizeof(scsi_devtype_key_t),
1384                                            scsidev_init_count *
1385                                            sizeof(scsi_devtype_key_t),
1386                                            G_ALLOC_AND_FREE);
1387         scsidev_req_vals = g_mem_chunk_new("scsidev_req_vals",
1388                                            sizeof(scsi_devtype_data_t),
1389                                            scsidev_init_count *
1390                                            sizeof(scsi_devtype_data_t),
1391                                            G_ALLOC_AND_FREE);
1392 }
1393
1394 static void
1395 dissect_scsi_evpd (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1396                    guint offset, guint tot_len _U_)
1397 {
1398     proto_tree *evpd_tree;
1399     proto_item *ti;
1400     guint pcode, plen, i, idlen;
1401     guint8 codeset, flags;
1402     char str[256+1];
1403
1404     if (tree) {
1405         pcode = tvb_get_guint8 (tvb, offset+1);
1406         plen = tvb_get_guint8 (tvb, offset+3);
1407         ti = proto_tree_add_text (tree, tvb, offset, plen+4, "Page Code: %s",
1408                                   val_to_str (pcode, scsi_evpd_pagecode_val,
1409                                               "Unknown (0x%08x)"));
1410         evpd_tree = proto_item_add_subtree (ti, ett_scsi_page);
1411
1412         proto_tree_add_item (evpd_tree, hf_scsi_inq_qualifier, tvb, offset,
1413                              1, 0);
1414         proto_tree_add_item (evpd_tree, hf_scsi_inq_devtype, tvb, offset,
1415                              1, 0);
1416         proto_tree_add_text (evpd_tree, tvb, offset+1, 1,
1417                              "Page Code: %s",
1418                              val_to_str (pcode, scsi_evpd_pagecode_val,
1419                                          "Unknown (0x%02x)"));
1420         proto_tree_add_text (evpd_tree, tvb, offset+3, 1,
1421                              "Page Length: %u", plen);
1422         offset += 4;
1423         switch (pcode) {
1424         case SCSI_EVPD_SUPPPG:
1425             for (i = 0; i < plen; i++) {
1426                 proto_tree_add_text (evpd_tree, tvb, offset+i, 1,
1427                                      "Supported Page: %s",
1428                                      val_to_str (tvb_get_guint8 (tvb, offset+i),
1429                                                  scsi_evpd_pagecode_val,
1430                                                  "Unknown (0x%02x)"));
1431             }
1432             break;
1433         case SCSI_EVPD_DEVID:
1434             while (plen != 0) {
1435                 codeset = tvb_get_guint8 (tvb, offset) & 0x0F;
1436                 proto_tree_add_text (evpd_tree, tvb, offset, 1,
1437                                      "Code Set: %s",
1438                                      val_to_str (codeset,
1439                                                  scsi_devid_codeset_val,
1440                                                  "Unknown (0x%02x)"));
1441                 plen -= 1;
1442                 offset += 1;
1443
1444                 if (plen < 1) {
1445                     proto_tree_add_text (evpd_tree, tvb, offset, 0,
1446                                          "Product data goes past end of page");
1447                     break;
1448                 }
1449                 flags = tvb_get_guint8 (tvb, offset);
1450                 proto_tree_add_text (evpd_tree, tvb, offset, 1,
1451                                      "Association: %s",
1452                                      val_to_str ((flags & 0x30) >> 4,
1453                                                  scsi_devid_assoc_val,
1454                                                  "Unknown (0x%02x)"));
1455                 proto_tree_add_text (evpd_tree, tvb, offset, 1,
1456                                      "Identifier Type: %s",
1457                                      val_to_str ((flags & 0x0F),
1458                                                  scsi_devid_idtype_val,
1459                                                  "Unknown (0x%02x)"));
1460                 plen -= 1;
1461                 offset += 1;
1462
1463                 /* Skip reserved byte */
1464                 if (plen < 1) {
1465                     proto_tree_add_text (evpd_tree, tvb, offset, 0,
1466                                          "Product data goes past end of page");
1467                     break;
1468                 }
1469                 plen -= 1;
1470                 offset += 1;
1471
1472                 if (plen < 1) {
1473                     proto_tree_add_text (evpd_tree, tvb, offset, 0,
1474                                          "Product data goes past end of page");
1475                     break;
1476                 }
1477                 idlen = tvb_get_guint8 (tvb, offset);
1478                 proto_tree_add_text (evpd_tree, tvb, offset, 1,
1479                                      "Identifier Length: %u", idlen);
1480                 plen -= 1;
1481                 offset += 1;
1482
1483                 if (idlen != 0) {
1484                     if (plen < idlen) {
1485                         proto_tree_add_text (evpd_tree, tvb, offset, 0,
1486                                              "Product data goes past end of page");
1487                         break;
1488                     }
1489                     if (codeset == CODESET_ASCII) {
1490                         proto_tree_add_text (evpd_tree, tvb, offset, idlen,
1491                                              "Identifier: %s",
1492                                              tvb_format_text (tvb, offset,
1493                                                               idlen));
1494                     } else {
1495                         /*
1496                          * XXX - decode this based on the identifier type,
1497                          * if the codeset is CODESET_BINARY?
1498                          */
1499                         proto_tree_add_text (evpd_tree, tvb, offset, idlen,
1500                                              "Identifier: %s",
1501                                              tvb_bytes_to_str (tvb, offset,
1502                                                                idlen));
1503                     }
1504                     plen -= idlen;
1505                     offset += idlen;
1506                 }
1507             }
1508             break;
1509         case SCSI_EVPD_DEVSERNUM:
1510             if (plen > 0) {
1511                 tvb_memcpy (tvb, str, offset, MIN(plen, sizeof(str) - 1));
1512                 str[sizeof(str) - 1] = '\0';
1513                 proto_tree_add_text (evpd_tree, tvb, offset, plen,
1514                                      "Product Serial Number: %s", str);
1515             }
1516             break;
1517         }
1518     }
1519 }
1520
1521 static void
1522 dissect_scsi_cmddt (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1523                     guint offset, guint tot_len _U_)
1524 {
1525     proto_tree *cmdt_tree;
1526     proto_item *ti;
1527     guint plen;
1528
1529     if (tree) {
1530         plen = tvb_get_guint8 (tvb, offset+5);
1531         ti = proto_tree_add_text (tree, tvb, offset, plen, "Command Data");
1532         cmdt_tree = proto_item_add_subtree (ti, ett_scsi_page);
1533
1534         proto_tree_add_item (cmdt_tree, hf_scsi_inq_qualifier, tvb, offset,
1535                              1, 0);
1536         proto_tree_add_item (cmdt_tree, hf_scsi_inq_devtype, tvb, offset,
1537                              1, 0);
1538         proto_tree_add_text (cmdt_tree, tvb, offset+1, 1, "Support: %s",
1539                              match_strval (tvb_get_guint8 (tvb, offset+1) & 0x7,
1540                                            scsi_cmdt_supp_val));
1541         proto_tree_add_text (cmdt_tree, tvb, offset+2, 1, "Version: %s",
1542                              val_to_str (tvb_get_guint8 (tvb, offset+2),
1543                                          scsi_verdesc_val,
1544                                          "Unknown (0x%02x)"));
1545         proto_tree_add_text (cmdt_tree, tvb, offset+5, 1, "CDB Size: %u",
1546                              plen);
1547     }
1548 }
1549
1550 static void
1551 dissect_scsi_inquiry (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1552                       guint offset, gboolean isreq, gboolean iscdb,
1553                       guint32 payload_len, scsi_task_data_t *cdata)
1554 {
1555     guint8 flags, i, devtype;
1556     gchar str[32];
1557     guint tot_len;
1558     scsi_devtype_data_t *devdata = NULL;
1559     scsi_devtype_key_t dkey, *req_key;
1560
1561     if (!isreq && (cdata == NULL || !(cdata->flags & 0x3))) {
1562         /*
1563          * INQUIRY response with device type information; add device type
1564          * to list of known devices & their types if not already known.
1565          *
1566          * We don't use COPY_ADDRESS because "dkey.devid" isn't
1567          * persistent, and therefore it can point to the stuff
1568          * in "pinfo->src".  (Were we to use COPY_ADDRESS, we'd
1569          * have to free the address data it allocated before we return.)
1570          */
1571         dkey.devid = pinfo->src;
1572         devdata = (scsi_devtype_data_t *)g_hash_table_lookup (scsidev_req_hash,
1573                                                               &dkey);
1574         if (!devdata) {
1575             req_key = g_mem_chunk_alloc (scsidev_req_keys);
1576             COPY_ADDRESS (&(req_key->devid), &(pinfo->src));
1577
1578             devdata = g_mem_chunk_alloc (scsidev_req_vals);
1579             devdata->devtype = tvb_get_guint8 (tvb, offset) & SCSI_DEV_BITS;
1580
1581             g_hash_table_insert (scsidev_req_hash, req_key, devdata);
1582         }
1583         else {
1584             devtype = tvb_get_guint8 (tvb, offset);
1585             if ((devtype & SCSI_DEV_BITS) != SCSI_DEV_NOLUN) {
1586                 /* Some initiators probe more than the available LUNs which
1587                  * results in Inquiry data being returned indicating that a LUN
1588                  * is not supported. We don't want to overwrite the device type
1589                  * with such responses.
1590                  */
1591                 devdata->devtype = (devtype & SCSI_DEV_BITS);
1592             }
1593         }
1594     }
1595
1596     if (!tree)
1597         return;
1598
1599     if (isreq && iscdb) {
1600         flags = tvb_get_guint8 (tvb, offset);
1601         if (cdata != NULL) {
1602             cdata->flags = flags;
1603         }
1604
1605         proto_tree_add_uint_format (tree, hf_scsi_inquiry_flags, tvb, offset, 1,
1606                                     flags, "CMDT = %u, EVPD = %u",
1607                                     flags & 0x2, flags & 0x1);
1608         if (flags & 0x1) {
1609             proto_tree_add_item (tree, hf_scsi_inquiry_evpd_page, tvb, offset+1,
1610                                  1, 0);
1611         }
1612         else if (flags & 0x2) {
1613             proto_tree_add_item (tree, hf_scsi_inquiry_cmdt_page, tvb, offset+1,
1614                                  1, 0);
1615         }
1616
1617         proto_tree_add_item (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
1618         flags = tvb_get_guint8 (tvb, offset+4);
1619         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1620                                     flags,
1621                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1622                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1623     }
1624     else if (!isreq) {
1625         if (cdata && (cdata->flags & 0x1)) {
1626             dissect_scsi_evpd (tvb, pinfo, tree, offset, payload_len);
1627             return;
1628         }
1629         else if (cdata && (cdata->flags & 0x2)) {
1630             dissect_scsi_cmddt (tvb, pinfo, tree, offset, payload_len);
1631             return;
1632         }
1633
1634         proto_tree_add_item (tree, hf_scsi_inq_qualifier, tvb, offset,
1635                              1, 0);
1636         proto_tree_add_item (tree, hf_scsi_inq_devtype, tvb, offset, 1, 0);
1637         proto_tree_add_item (tree, hf_scsi_inq_version, tvb, offset+2, 1, 0);
1638
1639         flags = tvb_get_guint8 (tvb, offset+3);
1640         proto_tree_add_item_hidden (tree, hf_scsi_inq_normaca, tvb,
1641                                     offset+3, 1, 0);
1642         proto_tree_add_text (tree, tvb, offset+3, 1, "NormACA: %u, HiSup: %u",
1643                              ((flags & 0x20) >> 5), ((flags & 0x10) >> 4));
1644         tot_len = tvb_get_guint8 (tvb, offset+4);
1645         proto_tree_add_text (tree, tvb, offset+4, 1, "Additional Length: %u",
1646                              tot_len);
1647         flags = tvb_get_guint8 (tvb, offset+6);
1648         proto_tree_add_text (tree, tvb, offset+6, 1,
1649                              "BQue: %u, SES: %u, MultiP: %u, Addr16: %u",
1650                              ((flags & 0x80) >> 7), (flags & 0x40) >> 6,
1651                              (flags & 10) >> 4, (flags & 0x01));
1652         flags = tvb_get_guint8 (tvb, offset+7);
1653         proto_tree_add_text (tree, tvb, offset+7, 1,
1654                              "RelAdr: %u, Linked: %u, CmdQue: %u",
1655                              (flags & 0x80) >> 7, (flags & 0x08) >> 3,
1656                              (flags & 0x02) >> 1);
1657         tvb_memcpy (tvb, str, offset+8, 8);
1658         str[8] = '\0';
1659         proto_tree_add_text (tree, tvb, offset+8, 8, "Vendor Id: %s", str);
1660         tvb_memcpy (tvb, str, offset+16, 16);
1661         str[16] = '\0';
1662         proto_tree_add_text (tree, tvb, offset+16, 16, "Product ID: %s", str);
1663         tvb_memcpy (tvb, str, offset+32, 4);
1664         str[4] = '\0';
1665         proto_tree_add_text (tree, tvb, offset+32, 4, "Product Revision: %s",
1666                              str);
1667
1668         offset += 58;
1669         if ((tot_len > 58) && tvb_bytes_exist (tvb, offset, 16)) {
1670             for (i = 0; i < 8; i++) {
1671                 proto_tree_add_text (tree, tvb, offset, 2,
1672                                      "Vendor Descriptor %u: %s",
1673                                      i,
1674                                      val_to_str (tvb_get_ntohs (tvb, offset),
1675                                                  scsi_verdesc_val,
1676                                                  "Unknown (0x%04x)"));
1677                 offset += 2;
1678             }
1679         }
1680     }
1681 }
1682
1683 static void
1684 dissect_scsi_extcopy (tvbuff_t *tvb _U_, packet_info *pinfo _U_,
1685                       proto_tree *tree _U_, guint offset _U_,
1686                       gboolean isreq _U_, gboolean iscdb _U_)
1687 {
1688
1689 }
1690
1691 static void
1692 dissect_scsi_logselect (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1693                         guint offset, gboolean isreq, gboolean iscdb)
1694 {
1695     guint8 flags;
1696
1697     if (!tree)
1698         return;
1699
1700     if (isreq && iscdb) {
1701         flags = tvb_get_guint8 (tvb, offset);
1702
1703         proto_tree_add_uint_format (tree, hf_scsi_logsel_flags, tvb, offset, 1,
1704                                     flags, "PCR = %u, SP = %u", flags & 0x2,
1705                                     flags & 0x1);
1706         proto_tree_add_uint_format (tree, hf_scsi_logsel_pc, tvb, offset+1, 1,
1707                                     tvb_get_guint8 (tvb, offset+1),
1708                                     "PC: 0x%x", flags & 0xC0);
1709         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
1710
1711         flags = tvb_get_guint8 (tvb, offset+8);
1712         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1713                                     flags,
1714                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1715                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1716     }
1717     else {
1718     }
1719 }
1720
1721 static void
1722 dissect_scsi_logsense (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1723                        guint offset, gboolean isreq, gboolean iscdb)
1724 {
1725     guint8 flags;
1726
1727     if (!tree)
1728         return;
1729
1730     if (isreq && iscdb) {
1731         flags = tvb_get_guint8 (tvb, offset);
1732
1733         proto_tree_add_uint_format (tree, hf_scsi_logsns_flags, tvb, offset, 1,
1734                                     flags, "PPC = %u, SP = %u", flags & 0x2,
1735                                     flags & 0x1);
1736         proto_tree_add_uint_format (tree, hf_scsi_logsns_pc, tvb, offset+1, 1,
1737                                     tvb_get_guint8 (tvb, offset+1),
1738                                     "PC: 0x%x", flags & 0xC0);
1739         proto_tree_add_item (tree, hf_scsi_logsns_pagecode, tvb, offset+1,
1740                              1, 0);
1741         proto_tree_add_text (tree, tvb, offset+4, 2, "Parameter Pointer: 0x%04x",
1742                              tvb_get_ntohs (tvb, offset+4));
1743         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
1744
1745         flags = tvb_get_guint8 (tvb, offset+8);
1746         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1747                                     flags,
1748                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1749                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1750     }
1751     else {
1752     }
1753 }
1754
1755 static gboolean
1756 dissect_scsi_blockdescs (tvbuff_t *tvb, packet_info *pinfo _U_,
1757                         proto_tree *scsi_tree, guint offset,
1758                         guint payload_len, guint desclen,
1759                         scsi_device_type devtype, gboolean longlba)
1760 {
1761     while (desclen != 0) {
1762         if (longlba) {
1763             if (payload_len < 8)
1764                 return FALSE;
1765             if (desclen < 8) {
1766                 offset += desclen;
1767                 payload_len -= desclen;
1768                 break;
1769             }
1770             proto_tree_add_text (scsi_tree, tvb, offset, 8, "No. of Blocks: %s",
1771                                  u64toa (tvb_get_ptr (tvb, offset, 8)));
1772             offset += 8;
1773             payload_len -= 8;
1774             desclen -= 8;
1775
1776             if (payload_len < 1)
1777                 return FALSE;
1778             if (desclen < 1)
1779                 break;
1780             proto_tree_add_text (scsi_tree, tvb, offset, 1, "Density Code: 0x%02x",
1781                                  tvb_get_guint8 (tvb, offset));
1782             offset += 1;
1783             payload_len -= 1;
1784             desclen -= 1;
1785
1786             if (payload_len < 3)
1787                 return FALSE;
1788             if (desclen < 3) {
1789                 offset += desclen;
1790                 payload_len -= desclen;
1791                 break;
1792             }
1793             /* 3 reserved bytes */
1794             offset += 3;
1795             payload_len -= 3;
1796             desclen -= 3;
1797
1798             if (payload_len < 4)
1799                 return FALSE;
1800             if (desclen < 4) {
1801                 offset += desclen;
1802                 payload_len -= desclen;
1803                 break;
1804             }
1805             proto_tree_add_text (scsi_tree, tvb, offset, 4, "Block Length: %u",
1806                                      tvb_get_ntohl (tvb, offset));
1807             offset += 4;
1808             payload_len -= 4;
1809             desclen -= 4;
1810         } else {
1811             if (devtype == SCSI_DEV_SBC) {
1812                 if (payload_len < 4)
1813                     return FALSE;
1814                 if (desclen < 4) {
1815                     offset += desclen;
1816                     payload_len -= desclen;
1817                     break;
1818                 }
1819                 proto_tree_add_text (scsi_tree, tvb, offset, 4, "No. of Blocks: %u",
1820                                      tvb_get_ntohl (tvb, offset));
1821                 offset += 4;
1822                 payload_len -= 4;
1823                 desclen -= 4;
1824
1825                 if (payload_len < 1)
1826                     return FALSE;
1827                 if (desclen < 1)
1828                     break;
1829                 proto_tree_add_text (scsi_tree, tvb, offset, 1, "Density Code: 0x%02x",
1830                                      tvb_get_guint8 (tvb, offset));
1831                 offset += 1;
1832                 payload_len -= 1;
1833                 desclen -= 1;
1834
1835                 if (payload_len < 3)
1836                     return FALSE;
1837                 if (desclen < 3) {
1838                     offset += desclen;
1839                     payload_len -= desclen;
1840                     break;
1841                 }
1842                 proto_tree_add_text (scsi_tree, tvb, offset, 3, "Block Length: %u",
1843                                          tvb_get_ntoh24 (tvb, offset));
1844                 offset += 3;
1845                 payload_len -= 3;
1846                 desclen -= 3;
1847             } else {
1848                 if (payload_len < 1)
1849                     return FALSE;
1850                 if (desclen < 1)
1851                     break;
1852                 proto_tree_add_text (scsi_tree, tvb, offset, 1, "Density Code: 0x%02x",
1853                                      tvb_get_guint8 (tvb, offset));
1854                 offset += 1;
1855                 payload_len -= 1;
1856                 desclen -= 1;
1857
1858                 if (payload_len < 3)
1859                     return FALSE;
1860                 if (desclen < 3) {
1861                     offset += desclen;
1862                     payload_len -= desclen;
1863                     break;
1864                 }
1865                 proto_tree_add_text (scsi_tree, tvb, offset, 3, "No. of Blocks: %u",
1866                                      tvb_get_ntoh24 (tvb, offset));
1867                 offset += 3;
1868                 payload_len -= 3;
1869                 desclen -= 3;
1870
1871                 if (payload_len < 1)
1872                     return FALSE;
1873                 if (desclen < 1)
1874                     break;
1875                 /* Reserved byte */
1876                 offset += 1;
1877                 payload_len -= 1;
1878                 desclen -= 1;
1879
1880                 if (payload_len < 3)
1881                     return FALSE;
1882                 if (desclen < 3) {
1883                     offset += desclen;
1884                     payload_len -= desclen;
1885                     break;
1886                 }
1887                 proto_tree_add_text (scsi_tree, tvb, offset, 3, "Block Length: %u",
1888                                          tvb_get_ntoh24 (tvb, offset));
1889                 offset += 3;
1890                 payload_len -= 3;
1891                 desclen -= 3;
1892             }
1893         }
1894     }
1895     return TRUE;
1896 }
1897
1898 static gboolean
1899 dissect_scsi_spc2_modepage (tvbuff_t *tvb, packet_info *pinfo _U_,
1900                             proto_tree *tree, guint offset, guint8 pcode)
1901 {
1902     guint8 flags, proto;
1903
1904     switch (pcode) {
1905     case SCSI_SPC2_MODEPAGE_CTL:
1906         flags = tvb_get_guint8 (tvb, offset+2);
1907         proto_tree_add_item (tree, hf_scsi_modesns_tst, tvb, offset+2, 1, 0);
1908         proto_tree_add_text (tree, tvb, offset+2, 1,
1909                              "Global Logging Target Save Disable: %u, Report Log Exception Condition: %u",
1910                              (flags & 0x2) >> 1, (flags & 0x1));
1911         flags = tvb_get_guint8 (tvb, offset+3);
1912         proto_tree_add_item (tree, hf_scsi_modesns_qmod, tvb, offset+3, 1, 0);
1913         proto_tree_add_item (tree, hf_scsi_modesns_qerr, tvb, offset+3, 1, 0);
1914         proto_tree_add_text (tree, tvb, offset+3, 1, "Disable Queuing: %u",
1915                              flags & 0x1);
1916         flags = tvb_get_guint8 (tvb, offset+4);
1917         proto_tree_add_item (tree, hf_scsi_modesns_rac, tvb, offset+4, 1, 0);
1918         proto_tree_add_item (tree, hf_scsi_modesns_tas, tvb, offset+4, 1, 0);
1919         proto_tree_add_text (tree, tvb, offset+4, 1,
1920                              "SWP: %u, RAERP: %u, UAAERP: %u, EAERP: %u",
1921                              (flags & 0x8) >> 3, (flags & 0x4) >> 2,
1922                              (flags & 0x2) >> 2, (flags & 0x1));
1923         proto_tree_add_text (tree, tvb, offset+5, 1, "Autoload Mode: 0x%x",
1924                              tvb_get_guint8 (tvb, offset+5) & 0x7);
1925         proto_tree_add_text (tree, tvb, offset+6, 2,
1926                              "Ready AER Holdoff Period: %u ms",
1927                              tvb_get_ntohs (tvb, offset+6));
1928         proto_tree_add_text (tree, tvb, offset+8, 2,
1929                              "Busy Timeout Period: %u ms",
1930                              tvb_get_ntohs (tvb, offset+8)*100);
1931         proto_tree_add_text (tree, tvb, offset+10, 2,
1932                              "Extended Self-Test Completion Time: %u",
1933                              tvb_get_ntohs (tvb, offset+10));
1934         break;
1935     case SCSI_SPC2_MODEPAGE_DISCON:
1936         proto_tree_add_text (tree, tvb, offset+2, 1, "Buffer Full Ratio: %u",
1937                              tvb_get_guint8 (tvb, offset+2));
1938         proto_tree_add_text (tree, tvb, offset+3, 1, "Buffer Empty Ratio: %u",
1939                              tvb_get_guint8 (tvb, offset+3));
1940         proto_tree_add_text (tree, tvb, offset+4, 2, "Bus Inactivity Limit: %u",
1941                              tvb_get_ntohs (tvb, offset+4));
1942         proto_tree_add_text (tree, tvb, offset+6, 2, "Disconnect Time Limit: %u",
1943                              tvb_get_ntohs (tvb, offset+6));
1944         proto_tree_add_text (tree, tvb, offset+8, 2, "Connect Time Limit: %u",
1945                              tvb_get_ntohs (tvb, offset+8));
1946         proto_tree_add_text (tree, tvb, offset+10, 2,
1947                              "Maximum Burst Size: %u bytes",
1948                              tvb_get_ntohs (tvb, offset+10)*512);
1949         flags = tvb_get_guint8 (tvb, offset+12);
1950         proto_tree_add_text (tree, tvb, offset+12, 1,
1951                              "EMDP: %u, FAA: %u, FAB: %u, FAC: %u",
1952                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
1953                              (flags & 0x20) >> 5, (flags & 0x10) >> 4);
1954         proto_tree_add_text (tree, tvb, offset+14, 2,
1955                              "First Burst Size: %u bytes",
1956                              tvb_get_ntohs (tvb, offset+14)*512);
1957         break;
1958     case SCSI_SPC2_MODEPAGE_INFOEXCP:
1959         flags = tvb_get_guint8 (tvb, offset+2);
1960         proto_tree_add_text (tree, tvb, offset+2, 1,
1961                              "Perf: %u, EBF: %u, EWasc: %u, DExcpt: %u, Test: %u, LogErr: %u",
1962                              (flags & 0x80) >> 7, (flags & 0x20) >> 5,
1963                              (flags & 0x10) >> 4, (flags & 0x08) >> 3,
1964                              (flags & 0x04) >> 2, (flags & 0x01));
1965         if (!((flags & 0x10) >> 4) && ((flags & 0x08) >> 3)) {
1966             proto_tree_add_item_hidden (tree, hf_scsi_modesns_errrep, tvb,
1967                                         offset+3, 1, 0);
1968         }
1969         else {
1970             proto_tree_add_item (tree, hf_scsi_modesns_errrep, tvb, offset+3, 1, 0);
1971         }
1972         proto_tree_add_text (tree, tvb, offset+4, 4, "Interval Timer: %u",
1973                              tvb_get_ntohl (tvb, offset+4));
1974         proto_tree_add_text (tree, tvb, offset+8, 4, "Report Count: %u",
1975                              tvb_get_ntohl (tvb, offset+8));
1976         break;
1977     case SCSI_SPC2_MODEPAGE_PWR:
1978         flags = tvb_get_guint8 (tvb, offset+3);
1979         proto_tree_add_text (tree, tvb, offset+3, 1, "Idle: %u, Standby: %u",
1980                              (flags & 0x2) >> 1, (flags & 0x1));
1981         proto_tree_add_text (tree, tvb, offset+4, 2,
1982                              "Idle Condition Timer: %u ms",
1983                              tvb_get_ntohs (tvb, offset+4) * 100);
1984         proto_tree_add_text (tree, tvb, offset+6, 2,
1985                              "Standby Condition Timer: %u ms",
1986                              tvb_get_ntohs (tvb, offset+6) * 100);
1987         break;
1988     case SCSI_SPC2_MODEPAGE_LUN:
1989         return FALSE;
1990     case SCSI_SPC2_MODEPAGE_PORT:
1991         proto = tvb_get_guint8 (tvb, offset+2) & 0x0F;
1992         proto_tree_add_item (tree, hf_scsi_protocol, tvb, offset+2, 1, 0);
1993         if (proto == SCSI_PROTO_FCP) {
1994             flags = tvb_get_guint8 (tvb, offset+3);
1995             proto_tree_add_text (tree, tvb, offset+3, 1,
1996                                  "DTFD: %u, PLPB: %u, DDIS: %u, DLM: %u, RHA: %u, ALWI: %u, DTIPE: %u, DTOLI:%u",
1997                                  (flags & 0x80) >> 7, (flags & 0x40) >> 6,
1998                                  (flags & 0x20) >> 5, (flags & 0x10) >> 4,
1999                                  (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2000                                  (flags & 0x02) >> 1, (flags & 0x1));
2001             proto_tree_add_text (tree, tvb, offset+6, 1, "RR_TOV Units: %s",
2002                                  val_to_str (tvb_get_guint8 (tvb, offset+6) & 0x7,
2003                                              scsi_fcp_rrtov_val,
2004                                              "Unknown (0x%02x)"));
2005             proto_tree_add_text (tree, tvb, offset+7, 1, "RR_TOV: %u",
2006                                  tvb_get_guint8 (tvb, offset+7));
2007         }
2008         else if (proto == SCSI_PROTO_iSCSI) {
2009             return FALSE;
2010         }
2011         else {
2012             return FALSE;
2013         }
2014         break;
2015     case SCSI_SCSI2_MODEPAGE_PERDEV:
2016         return FALSE;
2017     default:
2018         return FALSE;
2019     }
2020     return TRUE;
2021 }
2022
2023 static gboolean
2024 dissect_scsi_sbc2_modepage (tvbuff_t *tvb, packet_info *pinfo _U_,
2025                             proto_tree *tree, guint offset, guint8 pcode)
2026 {
2027     guint8 flags;
2028
2029     switch (pcode) {
2030     case SCSI_SBC2_MODEPAGE_FMTDEV:
2031         proto_tree_add_text (tree, tvb, offset+2, 2, "Tracks Per Zone: %u",
2032                              tvb_get_ntohs (tvb, offset+2));
2033         proto_tree_add_text (tree, tvb, offset+4, 2,
2034                              "Alternate Sectors Per Zone: %u",
2035                              tvb_get_ntohs (tvb, offset+4));
2036         proto_tree_add_text (tree, tvb, offset+6, 2,
2037                              "Alternate Tracks Per Zone: %u",
2038                              tvb_get_ntohs (tvb, offset+6));
2039         proto_tree_add_text (tree, tvb, offset+8, 2,
2040                              "Alternate Tracks Per LU: %u",
2041                              tvb_get_ntohs (tvb, offset+8));
2042         proto_tree_add_text (tree, tvb, offset+10, 2, "Sectors Per Track: %u",
2043                              tvb_get_ntohs (tvb, offset+10));
2044         proto_tree_add_text (tree, tvb, offset+12, 2,
2045                              "Data Bytes Per Physical Sector: %u",
2046                              tvb_get_ntohs (tvb, offset+12));
2047         proto_tree_add_text (tree, tvb, offset+14, 2, "Interleave: %u",
2048                              tvb_get_ntohs (tvb, offset+14));
2049         proto_tree_add_text (tree, tvb, offset+16, 2, "Track Skew Factor: %u",
2050                              tvb_get_ntohs (tvb, offset+16));
2051         proto_tree_add_text (tree, tvb, offset+18, 2,
2052                              "Cylinder Skew Factor: %u",
2053                              tvb_get_ntohs (tvb, offset+18));
2054         flags = tvb_get_guint8 (tvb, offset+20);
2055         proto_tree_add_text (tree, tvb, offset+20, 1,
2056                              "SSEC: %u, HSEC: %u, RMB: %u, SURF: %u",
2057                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
2058                              (flags & 0x20) >> 5, (flags & 0x10) >> 4);
2059         break;
2060     case SCSI_SBC2_MODEPAGE_RDWRERR:
2061         flags = tvb_get_guint8 (tvb, offset+2);
2062         proto_tree_add_text (tree, tvb, offset+2, 1,
2063                              "AWRE: %u, ARRE: %u, TB: %u, RC: %u, EER: %u, PER: %u, DTE: %u, DCR: %u",
2064                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
2065                              (flags & 0x20) >> 5, (flags & 0x10) >> 4,
2066                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2067                              (flags & 0x02) >> 1, (flags & 0x01));
2068         proto_tree_add_text (tree, tvb, offset+3, 1, "Read Retry Count: %u",
2069                              tvb_get_guint8 (tvb, offset+3));
2070         proto_tree_add_text (tree, tvb, offset+4, 1, "Correction Span: %u",
2071                              tvb_get_guint8 (tvb, offset+4));
2072         proto_tree_add_text (tree, tvb, offset+5, 1, "Head Offset Count: %u",
2073                              tvb_get_guint8 (tvb, offset+5));
2074         proto_tree_add_text (tree, tvb, offset+6, 1,
2075                              "Data Strobe Offset Count: %u",
2076                              tvb_get_guint8 (tvb, offset+6));
2077         proto_tree_add_text (tree, tvb, offset+8, 1, "Write Retry Count: %u",
2078                              tvb_get_guint8 (tvb, offset+8));
2079         proto_tree_add_text (tree, tvb, offset+10, 2,
2080                              "Recovery Time Limit: %u ms",
2081                              tvb_get_ntohs (tvb, offset+10));
2082         break;
2083    case SCSI_SBC2_MODEPAGE_DISKGEOM:
2084         proto_tree_add_text (tree, tvb, offset+2, 3, "Number of Cylinders: %u",
2085                              tvb_get_ntoh24 (tvb, offset+2));
2086         proto_tree_add_text (tree, tvb, offset+5, 1, "Number of Heads: %u",
2087                              tvb_get_guint8 (tvb, offset+5));
2088         proto_tree_add_text (tree, tvb, offset+6, 3,
2089                              "Starting Cyl Pre-compensation: %u",
2090                              tvb_get_ntoh24 (tvb, offset+6));
2091         proto_tree_add_text (tree, tvb, offset+9, 3,
2092                              "Starting Cyl-reduced Write Current: %u",
2093                              tvb_get_ntoh24 (tvb, offset+9));
2094         proto_tree_add_text (tree, tvb, offset+12, 2, "Device Step Rate: %u",
2095                              tvb_get_ntohs (tvb, offset+12));
2096         proto_tree_add_text (tree, tvb, offset+14, 3, "Landing Zone Cyl: %u",
2097                              tvb_get_ntoh24 (tvb, offset+14));
2098         proto_tree_add_text (tree, tvb, offset+18, 1, "Rotational Offset: %u",
2099                              tvb_get_guint8 (tvb, offset+18));
2100         proto_tree_add_text (tree, tvb, offset+20, 2,
2101                              "Medium Rotation Rate: %u",
2102                              tvb_get_ntohs (tvb, offset+20));
2103         break;
2104     case SCSI_SBC2_MODEPAGE_FLEXDISK:
2105         return FALSE;
2106     case SCSI_SBC2_MODEPAGE_VERERR:
2107         return FALSE;
2108     case SCSI_SBC2_MODEPAGE_CACHE:
2109         flags = tvb_get_guint8 (tvb, offset+2);
2110         proto_tree_add_text (tree, tvb, offset+2, 1,
2111                              "IC: %u, ABPF: %u, CAP %u, Disc: %u, Size: %u, WCE: %u, MF: %u, RCD: %u",
2112                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
2113                              (flags & 0x20) >> 5, (flags & 0x10) >> 4,
2114                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2115                              (flags & 0x02) >> 1, (flags & 0x01));
2116         flags = tvb_get_guint8 (tvb, offset+3);
2117         proto_tree_add_text (tree, tvb, offset+3, 1,
2118                              "Demand Read Retention Priority: %u, Write Retention Priority: %u",
2119                              (flags & 0xF0) >> 4, (flags & 0x0F));
2120         proto_tree_add_text (tree, tvb, offset+4, 2,
2121                              "Disable Pre-fetch Xfer Len: %u",
2122                              tvb_get_ntohs (tvb, offset+4));
2123         proto_tree_add_text (tree, tvb, offset+6, 2, "Minimum Pre-Fetch: %u",
2124                              tvb_get_ntohs (tvb, offset+6));
2125         proto_tree_add_text (tree, tvb, offset+8, 2, "Maximum Pre-Fetch: %u",
2126                              tvb_get_ntohs (tvb, offset+8));
2127         proto_tree_add_text (tree, tvb, offset+10, 2,
2128                              "Maximum Pre-Fetch Ceiling: %u",
2129                              tvb_get_ntohs (tvb, offset+10));
2130         flags = tvb_get_guint8 (tvb, offset+12);
2131         proto_tree_add_text (tree, tvb, offset+12, 1,
2132                              "FSW: %u, LBCSS: %u, DRA: %u, Vendor Specific: %u",
2133                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
2134                              (flags & 0x20) >> 5, (flags & 0x1F) >> 4);
2135         proto_tree_add_text (tree, tvb, offset+13, 1,
2136                              "Number of Cache Segments: %u",
2137                              tvb_get_guint8 (tvb, offset+13));
2138         proto_tree_add_text (tree, tvb, offset+14, 2, "Cache Segment Size: %u",
2139                              tvb_get_ntohs (tvb, offset+14));
2140         proto_tree_add_text (tree, tvb, offset+17, 3,
2141                              "Non-Cache Segment Size: %u",
2142                              tvb_get_ntoh24 (tvb, offset+17));
2143         break;
2144     case SCSI_SBC2_MODEPAGE_MEDTYPE:
2145         return FALSE;
2146     case SCSI_SBC2_MODEPAGE_NOTPART:
2147         return FALSE;
2148     case SCSI_SBC2_MODEPAGE_XORCTL:
2149         return FALSE;
2150     default:
2151         return FALSE;
2152     }
2153     return TRUE;
2154 }
2155
2156 static const value_string compression_algorithm_vals[] = {
2157         {0x00, "No algorithm selected"},
2158         {0x01, "Default algorithm"},
2159         {0x03, "IBM ALDC with 512-byte buffer"},
2160         {0x04, "IBM ALDC with 1024-byte buffer"},
2161         {0x05, "IBM ALDC with 2048-byte buffer"},
2162         {0x10, "IBM IDRC"},
2163         {0x20, "DCLZ"},
2164         {0xFF, "Unregistered algorithm"},
2165         {0, NULL}
2166 };
2167
2168 static gboolean
2169 dissect_scsi_ssc2_modepage (tvbuff_t *tvb _U_, packet_info *pinfo _U_,
2170                             proto_tree *tree _U_, guint offset _U_,
2171                             guint8 pcode)
2172 {
2173     guint8 flags;
2174
2175     switch (pcode) {
2176     case SCSI_SSC2_MODEPAGE_DATACOMP:
2177         flags = tvb_get_guint8 (tvb, offset+2);
2178         proto_tree_add_text (tree, tvb, offset+2, 1,
2179                              "DCE: %u, DCC: %u",
2180                              (flags & 0x80) >> 7, (flags & 0x40) >> 6);
2181         flags = tvb_get_guint8 (tvb, offset+3);
2182         proto_tree_add_text (tree, tvb, offset+3, 1,
2183                              "DDE: %u, RED: %u",
2184                              (flags & 0x80) >> 7, (flags & 0x60) >> 5);
2185         proto_tree_add_text (tree, tvb, offset+4, 4,
2186                              "Compression algorithm: %s",
2187                              val_to_str (tvb_get_ntohl (tvb, offset+4),
2188                                          compression_algorithm_vals,
2189                                          "Unknown (0x%08x)"));
2190         proto_tree_add_text (tree, tvb, offset+8, 4,
2191                              "Decompression algorithm: %s",
2192                              val_to_str (tvb_get_ntohl (tvb, offset+4),
2193                                          compression_algorithm_vals,
2194                                          "Unknown (0x%08x)"));
2195         break;
2196     case SCSI_SSC2_MODEPAGE_DEVCONF:
2197         return FALSE;
2198     case SCSI_SSC2_MODEPAGE_MEDPAR1:
2199         return FALSE;
2200     case SCSI_SSC2_MODEPAGE_MEDPAR2:
2201         return FALSE;
2202     case SCSI_SSC2_MODEPAGE_MEDPAR3:
2203         return FALSE;
2204     case SCSI_SSC2_MODEPAGE_MEDPAR4:
2205         return FALSE;
2206     default:
2207         return FALSE;
2208     }
2209     return TRUE;
2210 }
2211
2212 static gboolean
2213 dissect_scsi_smc2_modepage (tvbuff_t *tvb, packet_info *pinfo _U_,
2214                             proto_tree *tree, guint offset, guint8 pcode)
2215 {
2216     guint8 flags;
2217     guint8 param_list_len;
2218
2219     switch (pcode) {
2220     case SCSI_SMC2_MODEPAGE_EAA:
2221         param_list_len = tvb_get_guint8 (tvb, offset+2);
2222         proto_tree_add_text (tree, tvb, offset+2, 1, "Parameter List Length: %u",
2223                              param_list_len);
2224         if (param_list_len < 2)
2225             break;
2226         proto_tree_add_text (tree, tvb, offset+3, 2, "First Medium Transport Element Address: %u",
2227                              tvb_get_ntohs (tvb, offset+3));
2228         param_list_len -= 2;
2229         if (param_list_len < 2)
2230             break;
2231         proto_tree_add_text (tree, tvb, offset+5, 2, "Number of Medium Transport Elements: %u",
2232                              tvb_get_ntohs (tvb, offset+5));
2233         param_list_len -= 2;
2234         if (param_list_len < 2)
2235             break;
2236         proto_tree_add_text (tree, tvb, offset+7, 2, "First Storage Element Address: %u",
2237                              tvb_get_ntohs (tvb, offset+7));
2238         param_list_len -= 2;
2239         if (param_list_len < 2)
2240             break;
2241         proto_tree_add_text (tree, tvb, offset+9, 2, "Number of Storage Elements: %u",
2242                              tvb_get_ntohs (tvb, offset+9));
2243         param_list_len -= 2;
2244         if (param_list_len < 2)
2245             break;
2246         proto_tree_add_text (tree, tvb, offset+11, 2, "First Import/Export Element Address: %u",
2247                              tvb_get_ntohs (tvb, offset+11));
2248         param_list_len -= 2;
2249         if (param_list_len < 2)
2250             break;
2251         proto_tree_add_text (tree, tvb, offset+13, 2, "Number of Import/Export Elements: %u",
2252                              tvb_get_ntohs (tvb, offset+13));
2253         param_list_len -= 2;
2254         if (param_list_len < 2)
2255             break;
2256         proto_tree_add_text (tree, tvb, offset+15, 2, "First Data Transfer Element Address: %u",
2257                              tvb_get_ntohs (tvb, offset+15));
2258         param_list_len -= 2;
2259         if (param_list_len < 2)
2260             break;
2261         proto_tree_add_text (tree, tvb, offset+17, 2, "Number of Data Transfer Elements: %u",
2262                              tvb_get_ntohs (tvb, offset+17));
2263         break;
2264     case SCSI_SMC2_MODEPAGE_TRANGEOM:
2265         return FALSE;
2266     case SCSI_SMC2_MODEPAGE_DEVCAP:
2267         flags = tvb_get_guint8 (tvb, offset+2);
2268         proto_tree_add_text (tree, tvb, offset+2, 1,
2269                              "STORDT: %u, STORI/E: %u, STORST: %u, STORMT: %u",
2270                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2271                              (flags & 0x02) >> 1, (flags & 0x01));
2272         flags = tvb_get_guint8 (tvb, offset+4);
2273         proto_tree_add_text (tree, tvb, offset+4, 1,
2274                              "MT->DT: %u, MT->I/E: %u, MT->ST: %u, MT->MT: %u",
2275                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2276                              (flags & 0x02) >> 1, (flags & 0x01));
2277         flags = tvb_get_guint8 (tvb, offset+5);
2278         proto_tree_add_text (tree, tvb, offset+5, 1,
2279                              "ST->DT: %u, ST->I/E: %u, ST->ST: %u, ST->MT: %u",
2280                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2281                              (flags & 0x02) >> 1, (flags & 0x01));
2282         flags = tvb_get_guint8 (tvb, offset+6);
2283         proto_tree_add_text (tree, tvb, offset+6, 1,
2284                              "I/E->DT: %u, I/E->I/E: %u, I/E->ST: %u, I/E->MT: %u",
2285                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2286                              (flags & 0x02) >> 1, (flags & 0x01));
2287         flags = tvb_get_guint8 (tvb, offset+7);
2288         proto_tree_add_text (tree, tvb, offset+7, 1,
2289                              "DT->DT: %u, DT->I/E: %u, DT->ST: %u, DT->MT: %u",
2290                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2291                              (flags & 0x02) >> 1, (flags & 0x01));
2292         flags = tvb_get_guint8 (tvb, offset+12);
2293         proto_tree_add_text (tree, tvb, offset+12, 1,
2294                              "MT<>DT: %u, MT<>I/E: %u, MT<>ST: %u, MT<>MT: %u",
2295                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2296                              (flags & 0x02) >> 1, (flags & 0x01));
2297         flags = tvb_get_guint8 (tvb, offset+13);
2298         proto_tree_add_text (tree, tvb, offset+13, 1,
2299                              "ST<>DT: %u, ST<>I/E: %u, ST<>ST: %u, ST<>MT: %u",
2300                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2301                              (flags & 0x02) >> 1, (flags & 0x01));
2302         flags = tvb_get_guint8 (tvb, offset+14);
2303         proto_tree_add_text (tree, tvb, offset+14, 1,
2304                              "I/E<>DT: %u, I/E<>I/E: %u, I/E<>ST: %u, I/E<>MT: %u",
2305                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2306                              (flags & 0x02) >> 1, (flags & 0x01));
2307         flags = tvb_get_guint8 (tvb, offset+15);
2308         proto_tree_add_text (tree, tvb, offset+15, 1,
2309                              "DT<>DT: %u, DT<>I/E: %u, DT<>ST: %u, DT<>MT: %u",
2310                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
2311                              (flags & 0x02) >> 1, (flags & 0x01));
2312         break;
2313     default:
2314         return FALSE;
2315     }
2316     return TRUE;
2317 }
2318
2319 static guint
2320 dissect_scsi_modepage (tvbuff_t *tvb, packet_info *pinfo,
2321                        proto_tree *scsi_tree, guint offset,
2322                        scsi_device_type devtype)
2323 {
2324     guint8 pcode, plen;
2325     proto_tree *tree;
2326     proto_item *ti;
2327     const value_string *modepage_val;
2328     int hf_pagecode;
2329     gboolean (*dissect_modepage)(tvbuff_t *, packet_info *, proto_tree *,
2330                                  guint, guint8);
2331
2332     pcode = tvb_get_guint8 (tvb, offset);
2333     plen = tvb_get_guint8 (tvb, offset+1);
2334
2335     if (match_strval (pcode & SCSI_MS_PCODE_BITS,
2336                       scsi_spc2_modepage_val) == NULL) {
2337         /*
2338          * This isn't a generic mode page that applies to all SCSI
2339          * device types; try to interpret it based on what we deduced,
2340          * or were told, the device type is.
2341          */
2342         switch (devtype) {
2343         case SCSI_DEV_SBC:
2344             modepage_val = scsi_sbc2_modepage_val;
2345             hf_pagecode = hf_scsi_sbcpagecode;
2346             dissect_modepage = dissect_scsi_sbc2_modepage;
2347             break;
2348
2349         case SCSI_DEV_SSC:
2350             modepage_val = scsi_ssc2_modepage_val;
2351             hf_pagecode = hf_scsi_sscpagecode;
2352             dissect_modepage = dissect_scsi_ssc2_modepage;
2353             break;
2354
2355         case SCSI_DEV_SMC:
2356             modepage_val = scsi_smc2_modepage_val;
2357             hf_pagecode = hf_scsi_smcpagecode;
2358             dissect_modepage = dissect_scsi_smc2_modepage;
2359             break;
2360
2361         default:
2362             /*
2363              * The "val_to_str()" lookup will fail in this table
2364              * (it failed in "match_strval()"), so it'll return
2365              * "Unknown (XXX)", which is what we want.
2366              */
2367             modepage_val = scsi_spc2_modepage_val;
2368             hf_pagecode = hf_scsi_spcpagecode;
2369             dissect_modepage = dissect_scsi_spc2_modepage;
2370             break;
2371         }
2372     } else {
2373         modepage_val = scsi_spc2_modepage_val;
2374         hf_pagecode = hf_scsi_spcpagecode;
2375         dissect_modepage = dissect_scsi_spc2_modepage;
2376     }
2377     ti = proto_tree_add_text (scsi_tree, tvb, offset, plen+2, "%s Mode Page",
2378                               val_to_str (pcode & SCSI_MS_PCODE_BITS,
2379                                           modepage_val, "Unknown (0x%08x)"));
2380     tree = proto_item_add_subtree (ti, ett_scsi_page);
2381     proto_tree_add_text (tree, tvb, offset, 1, "PS: %u", (pcode & 0x80) >> 7);
2382
2383     proto_tree_add_item (tree, hf_pagecode, tvb, offset, 1, 0);
2384     proto_tree_add_text (tree, tvb, offset+1, 1, "Page Length: %u",
2385                          plen);
2386
2387     if (!tvb_bytes_exist (tvb, offset, plen)) {
2388         /* XXX - why not just drive on and throw an exception? */
2389         return (plen + 2);
2390     }
2391
2392     if (!(*dissect_modepage)(tvb, pinfo, tree, offset,
2393                              pcode & SCSI_MS_PCODE_BITS)) {
2394         proto_tree_add_text (tree, tvb, offset+2, plen,
2395                              "Unknown Page");
2396     }
2397     return (plen+2);
2398 }
2399
2400 static void
2401 dissect_scsi_modeselect6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2402                           guint offset, gboolean isreq, gboolean iscdb,
2403                           scsi_device_type devtype, guint payload_len)
2404 {
2405     guint8 flags;
2406     guint tot_len, desclen, plen;
2407
2408     if (!tree)
2409         return;
2410
2411     if (isreq && iscdb) {
2412         flags = tvb_get_guint8 (tvb, offset);
2413
2414         proto_tree_add_uint_format (tree, hf_scsi_modesel_flags, tvb, offset, 1,
2415                                     flags, "PF = %u, SP = %u", flags & 0x10,
2416                                     flags & 0x1);
2417         proto_tree_add_item (tree, hf_scsi_paramlen, tvb, offset+3, 1, 0);
2418
2419         flags = tvb_get_guint8 (tvb, offset+4);
2420         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
2421                                     flags,
2422                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2423                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2424     }
2425     else {
2426         /* Mode Parameter has the following format:
2427          * Mode Parameter Header
2428          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
2429          *      Blk Desc Len
2430          * Block Descriptor (s)
2431          *    - Number of blocks, density code, block length
2432          * Page (s)
2433          *    - Page code, Page length, Page Parameters
2434          */
2435         if (payload_len < 1)
2436             return;
2437         tot_len = tvb_get_guint8 (tvb, offset);
2438         proto_tree_add_text (tree, tvb, offset, 1, "Mode Data Length: %u",
2439                              tot_len);
2440         offset += 1;
2441         payload_len -= 1;
2442         /* The mode data length is reserved for MODE SELECT, so we just
2443            use the payload length. */
2444
2445         if (payload_len < 1)
2446             return;
2447         switch (devtype) {
2448
2449         case SCSI_DEV_SBC:
2450             proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: %s",
2451                                  val_to_str(tvb_get_guint8 (tvb, offset),
2452                                             scsi_modesense_medtype_sbc_val,
2453                                             "Unknown (0x%02x)"));
2454             break;
2455
2456         default:
2457             proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: 0x%02x",
2458                                  tvb_get_guint8 (tvb, offset));
2459             break;
2460         }
2461         offset += 1;
2462         payload_len -= 1;
2463
2464         if (payload_len < 1)
2465             return;
2466         proto_tree_add_text (tree, tvb, offset, 1,
2467                              "Device-Specific Parameter: 0x%02x",
2468                              tvb_get_guint8 (tvb, offset));
2469         offset += 1;
2470         payload_len -= 1;
2471
2472         if (payload_len < 1)
2473             return;
2474         desclen = tvb_get_guint8 (tvb, offset);
2475         proto_tree_add_text (tree, tvb, offset, 1,
2476                              "Block Descriptor Length: %u", desclen);
2477         offset += 1;
2478         payload_len -= 1;
2479
2480         if (!dissect_scsi_blockdescs (tvb, pinfo, tree, offset, payload_len,
2481                                      desclen, devtype, FALSE))
2482             return;
2483         offset += desclen;
2484         payload_len -= desclen;
2485
2486         /* offset points to the start of the mode page */
2487         while ((payload_len > 0) && tvb_bytes_exist (tvb, offset, 2)) {
2488             plen = dissect_scsi_modepage (tvb, pinfo, tree, offset, devtype);
2489             offset += plen;
2490             payload_len -= plen;
2491         }
2492     }
2493 }
2494
2495 static void
2496 dissect_scsi_modeselect10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2497                            guint offset, gboolean isreq, gboolean iscdb,
2498                            scsi_device_type devtype, guint payload_len)
2499 {
2500     guint8 flags;
2501     gboolean longlba;
2502     guint tot_len, desclen, plen;
2503
2504     if (!tree)
2505         return;
2506
2507     if (isreq && iscdb) {
2508         flags = tvb_get_guint8 (tvb, offset);
2509
2510         proto_tree_add_uint_format (tree, hf_scsi_modesel_flags, tvb, offset, 1,
2511                                     flags, "PF = %u, SP = %u", flags & 0x10,
2512                                     flags & 0x1);
2513         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
2514
2515         flags = tvb_get_guint8 (tvb, offset+8);
2516         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2517                                     flags,
2518                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2519                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2520     }
2521     else {
2522         /* Mode Parameter has the following format:
2523          * Mode Parameter Header
2524          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
2525          *      Blk Desc Len
2526          * Block Descriptor (s)
2527          *    - Number of blocks, density code, block length
2528          * Page (s)
2529          *    - Page code, Page length, Page Parameters
2530          */
2531         if (payload_len < 1)
2532             return;
2533         tot_len = tvb_get_ntohs (tvb, offset);
2534         proto_tree_add_text (tree, tvb, offset, 2, "Mode Data Length: %u",
2535                              tot_len);
2536         offset += 2;
2537         payload_len -= 2;
2538         /* The mode data length is reserved for MODE SELECT, so we just
2539            use the payload length. */
2540
2541         if (payload_len < 1)
2542             return;
2543         switch (devtype) {
2544
2545         case SCSI_DEV_SBC:
2546             proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: %s",
2547                                  val_to_str(tvb_get_guint8 (tvb, offset),
2548                                             scsi_modesense_medtype_sbc_val,
2549                                             "Unknown (0x%02x)"));
2550             break;
2551
2552         default:
2553             proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: 0x%02x",
2554                                  tvb_get_guint8 (tvb, offset));
2555             break;
2556         }
2557         offset += 1;
2558         payload_len -= 1;
2559
2560         if (payload_len < 1)
2561             return;
2562         proto_tree_add_text (tree, tvb, offset, 1,
2563                              "Device-Specific Parameter: 0x%02x",
2564                              tvb_get_guint8 (tvb, offset));
2565         offset += 1;
2566         payload_len -= 1;
2567
2568         if (payload_len < 1)
2569             return;
2570         longlba = tvb_get_guint8 (tvb, offset) & 0x1;
2571         proto_tree_add_text (tree, tvb, offset, 1, "LongLBA: %u", longlba);
2572         offset += 2;    /* skip LongLBA byte and reserved byte */
2573         payload_len -= 2;
2574
2575         if (payload_len < 1)
2576             return;
2577         desclen = tvb_get_guint8 (tvb, offset);
2578         proto_tree_add_text (tree, tvb, offset, 1,
2579                              "Block Descriptor Length: %u", desclen);
2580         offset += 1;
2581         payload_len -= 1;
2582
2583         if (!dissect_scsi_blockdescs (tvb, pinfo, tree, offset, payload_len,
2584                                      desclen, devtype, longlba))
2585             return;
2586         offset += desclen;
2587         payload_len -= desclen;
2588
2589         /* offset points to the start of the mode page */
2590         while ((payload_len > 0) && tvb_bytes_exist (tvb, offset, 2)) {
2591             plen = dissect_scsi_modepage (tvb, pinfo, tree, offset, devtype);
2592             offset += plen;
2593             payload_len -= plen;
2594         }
2595     }
2596 }
2597
2598 static void
2599 dissect_scsi_pagecode (tvbuff_t *tvb, packet_info *pinfo _U_,
2600                        proto_tree *tree, guint offset,
2601                        scsi_device_type devtype)
2602 {
2603     guint8 pcode;
2604     gchar *valstr;
2605     int hf_pagecode;
2606
2607     pcode = tvb_get_guint8 (tvb, offset);
2608     if ((valstr = match_strval (pcode & SCSI_MS_PCODE_BITS,
2609                                 scsi_spc2_modepage_val)) == NULL) {
2610         /*
2611          * This isn't a generic mode page that applies to all SCSI
2612          * device types; try to interpret it based on what we deduced,
2613          * or were told, the device type is.
2614          */
2615         switch (devtype) {
2616         case SCSI_DEV_SBC:
2617             hf_pagecode = hf_scsi_sbcpagecode;
2618             break;
2619
2620         case SCSI_DEV_SSC:
2621             hf_pagecode = hf_scsi_sscpagecode;
2622             break;
2623
2624         case SCSI_DEV_SMC:
2625             hf_pagecode = hf_scsi_smcpagecode;
2626             break;
2627
2628         default:
2629             hf_pagecode = hf_scsi_spcpagecode;
2630             break;
2631         }
2632     } else {
2633         hf_pagecode = hf_scsi_spcpagecode;
2634     }
2635     proto_tree_add_uint (tree, hf_pagecode, tvb, offset, 1, pcode);
2636 }
2637
2638 static void
2639 dissect_scsi_modesense6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2640                          guint offset, gboolean isreq, gboolean iscdb,
2641                          scsi_device_type devtype, guint payload_len)
2642 {
2643     guint8 flags;
2644     guint tot_len, desclen, plen;
2645
2646     if (!tree)
2647         return;
2648
2649     if (isreq && iscdb) {
2650         flags = tvb_get_guint8 (tvb, offset);
2651
2652         proto_tree_add_uint_format (tree, hf_scsi_modesns_flags, tvb, offset, 1,
2653                                     flags, "DBD = %u", flags & 0x8);
2654         proto_tree_add_item (tree, hf_scsi_modesns_pc, tvb, offset+1, 1, 0);
2655         dissect_scsi_pagecode (tvb, pinfo, tree, offset+1, devtype);
2656         proto_tree_add_item (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
2657
2658         flags = tvb_get_guint8 (tvb, offset+4);
2659         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
2660                                     flags,
2661                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2662                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2663     }
2664     else {
2665         /* Mode sense response has the following format:
2666          * Mode Parameter Header
2667          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
2668          *      Blk Desc Len
2669          * Block Descriptor (s)
2670          *    - Number of blocks, density code, block length
2671          * Page (s)
2672          *    - Page code, Page length, Page Parameters
2673          */
2674         tot_len = tvb_get_guint8 (tvb, offset);
2675         proto_tree_add_text (tree, tvb, offset, 1, "Mode Data Length: %u",
2676                              tot_len);
2677         offset += 1;
2678
2679         /* The actual payload is the min of the length in the response & the
2680          * space allocated by the initiator as specified in the request.
2681          *
2682          * XXX - the payload length includes the length field, so we
2683          * really should subtract the length of the length field from
2684          * the payload length - but can it really be zero here?
2685          */
2686         if (payload_len && (tot_len > payload_len))
2687             tot_len = payload_len;
2688
2689         if (tot_len < 1)
2690             return;
2691         proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: 0x%02x",
2692                              tvb_get_guint8 (tvb, offset));
2693         offset += 1;
2694         tot_len -= 1;
2695
2696         if (tot_len < 1)
2697             return;
2698         proto_tree_add_text (tree, tvb, offset, 1,
2699                              "Device-Specific Parameter: 0x%02x",
2700                              tvb_get_guint8 (tvb, offset));
2701         offset += 1;
2702         tot_len -= 1;
2703
2704         if (tot_len < 1)
2705             return;
2706         desclen = tvb_get_guint8 (tvb, offset);
2707         proto_tree_add_text (tree, tvb, offset, 1,
2708                              "Block Descriptor Length: %u", desclen);
2709         offset += 1;
2710         tot_len -= 1;
2711
2712         if (!dissect_scsi_blockdescs (tvb, pinfo, tree, offset, tot_len,
2713                                      desclen, devtype, FALSE))
2714             return;
2715         offset += desclen;
2716         tot_len -= desclen;
2717
2718         /* offset points to the start of the mode page */
2719         while ((tot_len > 0) && tvb_bytes_exist (tvb, offset, 2)) {
2720             plen = dissect_scsi_modepage (tvb, pinfo, tree, offset, devtype);
2721             offset += plen;
2722             tot_len -= plen;
2723         }
2724     }
2725 }
2726
2727 static void
2728 dissect_scsi_modesense10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2729                           guint offset, gboolean isreq, gboolean iscdb,
2730                           scsi_device_type devtype, guint payload_len)
2731 {
2732     guint8 flags;
2733     gboolean longlba;
2734     guint tot_len, desclen, plen;
2735
2736     if (!tree)
2737         return;
2738
2739     if (isreq && iscdb) {
2740         flags = tvb_get_guint8 (tvb, offset);
2741
2742         proto_tree_add_uint_format (tree, hf_scsi_modesns_flags, tvb, offset, 1,
2743                                     flags, "LLBAA = %u, DBD = %u", flags & 0x10,
2744                                     flags & 0x8);
2745         proto_tree_add_item (tree, hf_scsi_modesns_pc, tvb, offset+1, 1, 0);
2746         dissect_scsi_pagecode (tvb, pinfo, tree, offset+1, devtype);
2747         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
2748
2749         flags = tvb_get_guint8 (tvb, offset+8);
2750         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2751                                     flags,
2752                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2753                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2754     }
2755     else {
2756         /* Mode sense response has the following format:
2757          * Mode Parameter Header
2758          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
2759          *      Blk Desc Len
2760          * Block Descriptor (s)
2761          *    - Number of blocks, density code, block length
2762          * Page (s)
2763          *    - Page code, Page length, Page Parameters
2764          */
2765         tot_len = tvb_get_ntohs (tvb, offset);
2766         proto_tree_add_text (tree, tvb, offset, 2, "Mode Data Length: %u",
2767                              tot_len);
2768         offset += 2;
2769         /* The actual payload is the min of the length in the response & the
2770          * space allocated by the initiator as specified in the request.
2771          *
2772          * XXX - the payload length includes the length field, so we
2773          * really should subtract the length of the length field from
2774          * the payload length - but can it really be zero here?
2775          */
2776         if (payload_len && (tot_len > payload_len))
2777             tot_len = payload_len;
2778
2779         if (tot_len < 1)
2780             return;
2781         proto_tree_add_text (tree, tvb, offset, 1, "Medium Type: 0x%02x",
2782                              tvb_get_guint8 (tvb, offset));
2783         offset += 1;
2784         tot_len -= 1;
2785
2786         if (tot_len < 1)
2787             return;
2788         proto_tree_add_text (tree, tvb, offset, 1,
2789                              "Device-Specific Parameter: 0x%02x",
2790                              tvb_get_guint8 (tvb, offset));
2791         offset += 1;
2792         tot_len -= 1;
2793
2794         if (tot_len < 1)
2795             return;
2796         longlba = tvb_get_guint8 (tvb, offset) & 0x1;
2797         proto_tree_add_text (tree, tvb, offset, 1, "LongLBA: %u", longlba);
2798         offset += 2;    /* skip LongLBA byte and reserved byte */
2799         tot_len -= 2;
2800
2801         if (tot_len < 1)
2802             return;
2803         desclen = tvb_get_guint8 (tvb, offset);
2804         proto_tree_add_text (tree, tvb, offset, 1,
2805                              "Block Descriptor Length: %u", desclen);
2806         offset += 1;
2807         tot_len -= 1;
2808
2809         if (!dissect_scsi_blockdescs (tvb, pinfo, tree, offset, tot_len,
2810                                      desclen, devtype, longlba))
2811             return;
2812         offset += desclen;
2813         tot_len -= desclen;
2814
2815         /* offset points to the start of the mode page */
2816         while ((tot_len > 0) && tvb_bytes_exist (tvb, offset, 2)) {
2817             plen = dissect_scsi_modepage (tvb, pinfo, tree, offset, devtype);
2818             offset += plen;
2819             tot_len -= plen;
2820         }
2821     }
2822 }
2823
2824 static void
2825 dissect_scsi_persresvin (tvbuff_t *tvb, packet_info *pinfo _U_,
2826                          proto_tree *tree, guint offset, gboolean isreq,
2827                          gboolean iscdb, scsi_task_data_t *cdata,
2828                          guint payload_len)
2829 {
2830     guint8 flags;
2831     int numrec, i;
2832     guint len;
2833
2834     if (!tree)
2835         return;
2836
2837     if (isreq && iscdb) {
2838         proto_tree_add_item (tree, hf_scsi_persresvin_svcaction, tvb, offset+1,
2839                              1, 0);
2840         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
2841
2842         flags = tvb_get_guint8 (tvb, offset+8);
2843         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2844                                     flags,
2845                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2846                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2847         /* We store the service action since we want to interpret the data */
2848         cdata->flags = tvb_get_guint8 (tvb, offset+1);
2849     }
2850     else {
2851         if (cdata) {
2852             flags = cdata->flags;
2853         }
2854         else {
2855             flags = 0xFF;
2856         }
2857         proto_tree_add_text (tree, tvb, offset, 4, "Generation Number: 0x%08x",
2858                              tvb_get_ntohl (tvb, offset));
2859         len = tvb_get_ntohl (tvb, offset+4);
2860         proto_tree_add_text (tree, tvb, offset, 4, "Additional Length: %u",
2861                              len);
2862         len = (payload_len > len) ? len : payload_len;
2863
2864         if ((flags & 0x1F) == SCSI_SPC2_RESVIN_SVCA_RDKEYS) {
2865             /* XXX - what if len is < 8?  That may be illegal, but
2866                that doesn't make it impossible.... */
2867             numrec = (len - 8)/8;
2868             offset += 8;
2869
2870             for (i = 0; i < numrec; i++) {
2871                 proto_tree_add_item (tree, hf_scsi_persresv_key, tvb, offset,
2872                                      8, 0);
2873                 offset -= 8;
2874             }
2875         }
2876         else if ((flags & 0x1F) == SCSI_SPC2_RESVIN_SVCA_RDRESV) {
2877             proto_tree_add_item (tree, hf_scsi_persresv_key, tvb, offset+8,
2878                                  8, 0);
2879             proto_tree_add_item (tree, hf_scsi_persresv_scopeaddr, tvb,
2880                                  offset+8, 4, 0);
2881             proto_tree_add_item (tree, hf_scsi_persresv_scope, tvb, offset+13,
2882                                  1, 0);
2883             proto_tree_add_item (tree, hf_scsi_persresv_type, tvb, offset+13,
2884                                  1, 0);
2885         }
2886     }
2887 }
2888
2889 static void
2890 dissect_scsi_persresvout (tvbuff_t *tvb, packet_info *pinfo _U_,
2891                           proto_tree *tree, guint offset, gboolean isreq,
2892                           gboolean iscdb, scsi_task_data_t *cdata _U_,
2893                           guint payload_len _U_)
2894 {
2895     guint8 flags;
2896
2897     if (!tree)
2898         return;
2899
2900     if (isreq && iscdb) {
2901         proto_tree_add_item (tree, hf_scsi_persresvin_svcaction, tvb, offset,
2902                              1, 0);
2903         proto_tree_add_item (tree, hf_scsi_persresv_scope, tvb, offset+1, 1, 0);
2904         proto_tree_add_item (tree, hf_scsi_persresv_type, tvb, offset+1, 1, 0);
2905         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
2906
2907         flags = tvb_get_guint8 (tvb, offset+8);
2908         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2909                                     flags,
2910                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2911                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2912     }
2913     else {
2914     }
2915 }
2916
2917 static void
2918 dissect_scsi_release6 (tvbuff_t *tvb, packet_info *pinfo _U_,
2919                        proto_tree *tree, guint offset, gboolean isreq,
2920                        gboolean iscdb)
2921 {
2922     guint8 flags;
2923
2924     if (!tree)
2925         return;
2926
2927     if (isreq && iscdb) {
2928         flags = tvb_get_guint8 (tvb, offset+4);
2929         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
2930                                     flags,
2931                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2932                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2933     }
2934 }
2935
2936 static void
2937 dissect_scsi_release10 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2938                         guint offset, gboolean isreq, gboolean iscdb)
2939 {
2940     guint8 flags;
2941
2942     if (!tree)
2943         return;
2944
2945     if (isreq && iscdb) {
2946         flags = tvb_get_guint8 (tvb, offset);
2947
2948         proto_tree_add_uint_format (tree, hf_scsi_release_flags, tvb, offset, 1,
2949                                     flags,
2950                                     "Flags: 3rd Party ID = %u, LongID = %u",
2951                                     flags & 0x10, flags & 0x2);
2952         if ((flags & 0x12) == 0x10) {
2953             proto_tree_add_item (tree, hf_scsi_release_thirdpartyid, tvb,
2954                                  offset+2, 1, 0);
2955         }
2956         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
2957
2958         flags = tvb_get_guint8 (tvb, offset+8);
2959         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2960                                     flags,
2961                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2962                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2963     }
2964 }
2965
2966 static void
2967 dissect_scsi_reportdeviceid (tvbuff_t *tvb _U_, packet_info *pinfo _U_,
2968                              proto_tree *tree _U_, guint offset _U_,
2969                              gboolean isreq _U_, gboolean iscdb _U_)
2970 {
2971
2972 }
2973
2974 static void
2975 dissect_scsi_reportluns (tvbuff_t *tvb, packet_info *pinfo _U_,
2976                          proto_tree *tree, guint offset, gboolean isreq,
2977                          gboolean iscdb, guint payload_len)
2978 {
2979     guint8 flags;
2980     guint listlen, i;
2981
2982     if (!tree)
2983         return;
2984
2985     if (isreq && iscdb) {
2986         proto_tree_add_item (tree, hf_scsi_alloclen32, tvb, offset+5, 4, 0);
2987
2988         flags = tvb_get_guint8 (tvb, offset+10);
2989         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
2990                                     flags,
2991                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2992                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2993     }
2994     else if (!isreq) {
2995         listlen = tvb_get_ntohl (tvb, offset);
2996         proto_tree_add_text (tree, tvb, offset, 4, "LUN List Length: %u",
2997                              listlen);
2998         offset += 8;
2999         payload_len -= 8;
3000         if (payload_len != 0) {
3001             listlen = (listlen < payload_len) ? listlen : payload_len;
3002         }
3003         
3004         for (i = 0; i < listlen/8; i++) {
3005             if (!tvb_get_guint8 (tvb, offset))
3006                 proto_tree_add_item (tree, hf_scsi_rluns_lun, tvb, offset+1, 1,
3007                                      0);
3008             else
3009                 proto_tree_add_item (tree, hf_scsi_rluns_multilun, tvb, offset,
3010                                      8, 0);
3011             offset += 8;
3012         }
3013     }
3014 }
3015
3016 static void
3017 dissect_scsi_reqsense (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3018                        guint offset, gboolean isreq, gboolean iscdb)
3019 {
3020     guint8 flags;
3021
3022     if (!tree)
3023         return;
3024
3025     if (isreq && iscdb) {
3026         proto_tree_add_item (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
3027
3028         flags = tvb_get_guint8 (tvb, offset+4);
3029         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3030                                     flags,
3031                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3032                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3033     }
3034 }
3035
3036 static void
3037 dissect_scsi_reserve6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3038                        guint offset, gboolean isreq, gboolean iscdb)
3039 {
3040     guint8 flags;
3041
3042     if (!tree)
3043         return;
3044
3045     if (isreq && iscdb) {
3046         flags = tvb_get_guint8 (tvb, offset+4);
3047         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3048                                     flags,
3049                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3050                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3051     }
3052 }
3053
3054 static void
3055 dissect_scsi_reserve10 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3056                         guint offset, gboolean isreq, gboolean iscdb)
3057 {
3058     guint8 flags;
3059
3060     if (!tree)
3061         return;
3062
3063     if (isreq && iscdb) {
3064         flags = tvb_get_guint8 (tvb, offset);
3065
3066         proto_tree_add_uint_format (tree, hf_scsi_release_flags, tvb, offset, 1,
3067                                     flags,
3068                                     "Flags: 3rd Party ID = %u, LongID = %u",
3069                                     flags & 0x10, flags & 0x2);
3070         if ((flags & 0x12) == 0x10) {
3071             proto_tree_add_item (tree, hf_scsi_release_thirdpartyid, tvb,
3072                                  offset+2, 1, 0);
3073         }
3074         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
3075
3076         flags = tvb_get_guint8 (tvb, offset+8);
3077         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
3078                                     flags,
3079                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3080                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3081     }
3082 }
3083
3084 static void
3085 dissect_scsi_testunitrdy (tvbuff_t *tvb, packet_info *pinfo _U_,
3086                           proto_tree *tree, guint offset, gboolean isreq,
3087                           gboolean iscdb)
3088 {
3089     guint8 flags;
3090
3091     if (!tree)
3092         return;
3093
3094     if (isreq && iscdb) {
3095         flags = tvb_get_guint8 (tvb, offset+4);
3096         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3097                                     flags,
3098                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3099                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3100     }
3101 }
3102
3103 static void
3104 dissect_scsi_formatunit (tvbuff_t *tvb, packet_info *pinfo _U_,
3105                          proto_tree *tree, guint offset, gboolean isreq,
3106                          gboolean iscdb)
3107 {
3108     guint8 flags;
3109
3110     if (!tree)
3111         return;
3112
3113     if (isreq && iscdb) {
3114         flags = tvb_get_guint8 (tvb, offset);
3115         proto_tree_add_uint_format (tree, hf_scsi_formatunit_flags, tvb, offset,
3116                                     1, flags,
3117                                     "Flags: Longlist = %u, FMTDATA = %u, CMPLIST = %u",
3118                                     flags & 0x20, flags & 0x8, flags & 0x4);
3119         proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
3120         proto_tree_add_item (tree, hf_scsi_formatunit_vendor, tvb, offset+1,
3121                              1, 0);
3122         proto_tree_add_item (tree, hf_scsi_formatunit_interleave, tvb, offset+2,
3123                              2, 0);
3124         flags = tvb_get_guint8 (tvb, offset+4);
3125         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3126                                     flags,
3127                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3128                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3129     }
3130 }
3131
3132 static void
3133 dissect_scsi_sbc2_rdwr6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3134                     guint offset, gboolean isreq, gboolean iscdb)
3135 {
3136     guint8 flags;
3137
3138     if (isreq) {
3139         if (check_col (pinfo->cinfo, COL_INFO))
3140             col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%06x, Len: %u)",
3141                              tvb_get_ntoh24 (tvb, offset),
3142                              tvb_get_guint8 (tvb, offset+3));
3143     }
3144
3145     if (tree && isreq && iscdb) {
3146         proto_tree_add_item (tree, hf_scsi_rdwr6_lba, tvb, offset, 3, 0);
3147         proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+3, 1, 0);
3148         flags = tvb_get_guint8 (tvb, offset+4);
3149         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3150                                     flags,
3151                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3152                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3153     }
3154 }
3155
3156 static void
3157 dissect_scsi_rdwr10 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3158                      guint offset, gboolean isreq, gboolean iscdb)
3159 {
3160     guint8 flags;
3161
3162     if (isreq) {
3163         if (check_col (pinfo->cinfo, COL_INFO))
3164             col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%08x, Len: %u)",
3165                              tvb_get_ntohl (tvb, offset+1),
3166                              tvb_get_ntohs (tvb, offset+6));
3167     }
3168
3169     if (tree && isreq && iscdb) {
3170         flags = tvb_get_guint8 (tvb, offset);
3171
3172         proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
3173                                     flags,
3174                                     "DPO = %u, FUA = %u, RelAddr = %u",
3175                                     flags & 0x10, flags & 0x8, flags & 0x1);
3176         proto_tree_add_item (tree, hf_scsi_rdwr10_lba, tvb, offset+1, 4, 0);
3177         proto_tree_add_item (tree, hf_scsi_rdwr10_xferlen, tvb, offset+6, 2, 0);
3178         flags = tvb_get_guint8 (tvb, offset+8);
3179         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
3180                                     flags,
3181                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3182                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3183     }
3184 }
3185
3186 static void
3187 dissect_scsi_rdwr12 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3188                      guint offset, gboolean isreq, gboolean iscdb)
3189 {
3190     guint8 flags;
3191
3192     if (isreq) {
3193         if (check_col (pinfo->cinfo, COL_INFO))
3194             col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%08x, Len: %u)",
3195                              tvb_get_ntohl (tvb, offset+1),
3196                              tvb_get_ntohl (tvb, offset+5));
3197     }
3198
3199     if (tree && isreq && iscdb) {
3200         flags = tvb_get_guint8 (tvb, offset);
3201
3202         proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
3203                                     flags,
3204                                     "DPO = %u, FUA = %u, RelAddr = %u",
3205                                     flags & 0x10, flags & 0x8, flags & 0x1);
3206         proto_tree_add_item (tree, hf_scsi_rdwr10_lba, tvb, offset+1, 4, 0);
3207         proto_tree_add_item (tree, hf_scsi_rdwr12_xferlen, tvb, offset+5, 4, 0);
3208         flags = tvb_get_guint8 (tvb, offset+10);
3209         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
3210                                     flags,
3211                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3212                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3213     }
3214 }
3215
3216 static void
3217 dissect_scsi_rdwr16 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3218                      guint offset, gboolean isreq, gboolean iscdb)
3219 {
3220     guint8 flags;
3221
3222     if (tree && isreq && iscdb) {
3223         flags = tvb_get_guint8 (tvb, offset);
3224
3225         proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
3226                                     flags,
3227                                     "DPO = %u, FUA = %u, RelAddr = %u",
3228                                     flags & 0x10, flags & 0x8, flags & 0x1);
3229         proto_tree_add_item (tree, hf_scsi_rdwr16_lba, tvb, offset+1, 8, 0);
3230         proto_tree_add_item (tree, hf_scsi_rdwr12_xferlen, tvb, offset+9, 4, 0);
3231         flags = tvb_get_guint8 (tvb, offset+14);
3232         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+14, 1,
3233                                     flags,
3234                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3235                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3236     }
3237 }
3238
3239 static void
3240 dissect_scsi_readcapacity (tvbuff_t *tvb, packet_info *pinfo _U_,
3241                            proto_tree *tree, guint offset, gboolean isreq,
3242                            gboolean iscdb)
3243 {
3244     guint8 flags;
3245     guint len;
3246
3247     if (!tree)
3248         return;
3249
3250     if (isreq && iscdb) {
3251         flags = tvb_get_guint8 (tvb, offset);
3252
3253         proto_tree_add_uint_format (tree, hf_scsi_readcapacity_flags, tvb,
3254                                     offset, 1, flags,
3255                                     "LongLBA = %u, RelAddr = %u",
3256                                     flags & 0x2, flags & 0x1);
3257         proto_tree_add_item (tree, hf_scsi_readcapacity_lba, tvb, offset+1,
3258                              4, 0);
3259         proto_tree_add_item (tree, hf_scsi_readcapacity_pmi, tvb, offset+7,
3260                              1, 0);
3261
3262         flags = tvb_get_guint8 (tvb, offset+8);
3263         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
3264                                     flags,
3265                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3266                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3267     }
3268     else if (!iscdb) {
3269         len = tvb_get_ntohl (tvb, offset);
3270         proto_tree_add_text (tree, tvb, offset, 4, "LBA: %u (%u MB)",
3271                              len, len/(1024*1024));
3272         proto_tree_add_text (tree, tvb, offset+4, 4, "Block Length: %u bytes",
3273                              tvb_get_ntohl (tvb, offset+4));
3274     }
3275 }
3276
3277 static void
3278 dissect_scsi_readdefdata10 (tvbuff_t *tvb, packet_info *pinfo _U_,
3279                             proto_tree *tree, guint offset, gboolean isreq,
3280                             gboolean iscdb)
3281 {
3282     guint8 flags;
3283
3284     if (!tree)
3285         return;
3286
3287     if (isreq && iscdb) {
3288         flags = tvb_get_guint8 (tvb, offset);
3289
3290         proto_tree_add_uint_format (tree, hf_scsi_readdefdata_flags, tvb,
3291                                     offset, 1, flags, "PLIST = %u, GLIST = %u",
3292                                     flags & 0x10, flags & 0x8);
3293         proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
3294         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
3295         flags = tvb_get_guint8 (tvb, offset+8);
3296         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
3297                                     flags,
3298                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3299                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3300     }
3301 }
3302
3303 static void
3304 dissect_scsi_readdefdata12 (tvbuff_t *tvb, packet_info *pinfo _U_,
3305                             proto_tree *tree, guint offset, gboolean isreq,
3306                             gboolean iscdb)
3307 {
3308     guint8 flags;
3309
3310     if (!tree)
3311         return;
3312
3313     if (isreq && iscdb) {
3314         flags = tvb_get_guint8 (tvb, offset);
3315
3316         proto_tree_add_uint_format (tree, hf_scsi_readdefdata_flags, tvb,
3317                                     offset, 1, flags, "PLIST = %u, GLIST = %u",
3318                                     flags & 0x10, flags & 0x8);
3319         proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
3320         proto_tree_add_item (tree, hf_scsi_alloclen32, tvb, offset+5, 4, 0);
3321         flags = tvb_get_guint8 (tvb, offset+10);
3322         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
3323                                     flags,
3324                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3325                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3326     }
3327 }
3328
3329 static void
3330 dissect_scsi_reassignblks (tvbuff_t *tvb, packet_info *pinfo _U_,
3331                            proto_tree *tree, guint offset, gboolean isreq,
3332                            gboolean iscdb)
3333 {
3334     guint8 flags;
3335
3336     if (!tree)
3337         return;
3338
3339     if (isreq && iscdb) {
3340         flags = tvb_get_guint8 (tvb, offset);
3341
3342         proto_tree_add_uint_format (tree, hf_scsi_reassignblks_flags, tvb,
3343                                     offset, 1, flags,
3344                                     "LongLBA = %u, LongList = %u",
3345                                     flags & 0x2, flags & 0x1);
3346         flags = tvb_get_guint8 (tvb, offset+4);
3347         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3348                                     flags,
3349                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3350                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3351     }
3352 }
3353
3354 static void
3355 dissect_scsi_varlencdb (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3356                         guint offset, gboolean isreq, gboolean iscdb)
3357 {
3358     if (!tree)
3359         return;
3360
3361     if (isreq && iscdb) {
3362         proto_tree_add_item (tree, hf_scsi_control, tvb, offset, 1, 0);
3363         proto_tree_add_item (tree, hf_scsi_add_cdblen, tvb, offset+6, 1, 0);
3364         proto_tree_add_item (tree, hf_scsi_svcaction, tvb, offset+7, 2, 0);
3365
3366     }
3367 }
3368
3369 static void
3370 dissect_scsi_ssc2_read6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3371                     guint offset, gboolean isreq, gboolean iscdb)
3372 {
3373     guint8 flags;
3374
3375     if (isreq) {
3376         if (check_col (pinfo->cinfo, COL_INFO))
3377             col_append_fstr (pinfo->cinfo, COL_INFO, "(Len: %u)",
3378                              tvb_get_ntoh24 (tvb, offset+1));
3379     }
3380
3381     if (tree && isreq && iscdb) {
3382         flags = tvb_get_guint8 (tvb, offset);
3383         proto_tree_add_text (tree, tvb, offset, 1,
3384                              "SILI: %u, FIXED: %u",
3385                              (flags & 0x02) >> 1, flags & 0x01);
3386         proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+1, 3, 0);
3387         flags = tvb_get_guint8 (tvb, offset+4);
3388         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3389                                     flags,
3390                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3391                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3392     }
3393 }
3394
3395 static void
3396 dissect_scsi_ssc2_write6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3397                     guint offset, gboolean isreq, gboolean iscdb)
3398 {
3399     guint8 flags;
3400
3401     if (isreq) {
3402         if (check_col (pinfo->cinfo, COL_INFO))
3403             col_append_fstr (pinfo->cinfo, COL_INFO, "(Len: %u)",
3404                              tvb_get_ntoh24 (tvb, offset+1));
3405     }
3406
3407     if (tree && isreq && iscdb) {
3408         flags = tvb_get_guint8 (tvb, offset);
3409         proto_tree_add_text (tree, tvb, offset, 1,
3410                              "FIXED: %u", flags & 0x01);
3411         proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+1, 3,
3412                              FALSE);
3413         flags = tvb_get_guint8 (tvb, offset+4);
3414         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3415                                     flags,
3416                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3417                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3418     }
3419 }
3420
3421 static void
3422 dissect_scsi_ssc2_writefilemarks6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3423                     guint offset, gboolean isreq, gboolean iscdb)
3424 {
3425     guint8 flags;
3426
3427     if (isreq) {
3428         if (check_col (pinfo->cinfo, COL_INFO))
3429             col_append_fstr (pinfo->cinfo, COL_INFO, "(Len: %u)",
3430                              tvb_get_ntoh24 (tvb, offset+1));
3431     }
3432
3433     if (tree && isreq && iscdb) {
3434         flags = tvb_get_guint8 (tvb, offset);
3435         proto_tree_add_text (tree, tvb, offset, 1,
3436                              "WSMK: %u, IMMED: %u",
3437                              (flags & 0x02) >> 1, flags & 0x01);
3438         proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+1, 3,
3439                              FALSE);
3440         flags = tvb_get_guint8 (tvb, offset+4);
3441         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3442                                     flags,
3443                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3444                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3445     }
3446 }
3447
3448 static void
3449 dissect_scsi_ssc2_loadunload (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3450                     guint offset, gboolean isreq, gboolean iscdb)
3451 {
3452     guint8 flags;
3453
3454     if (isreq && iscdb) {
3455         if (check_col (pinfo->cinfo, COL_INFO))
3456             col_append_fstr (pinfo->cinfo, COL_INFO, "(Immed: %u)",
3457                              tvb_get_guint8 (tvb, offset) & 0x01);
3458
3459         if (!tree)
3460             return;
3461
3462         proto_tree_add_text (tree, tvb, offset, 1,
3463                              "Immed: %u", tvb_get_guint8 (tvb, offset) & 0x01);
3464         flags = tvb_get_guint8 (tvb, offset+3);
3465         proto_tree_add_text (tree, tvb, offset+3, 1,
3466                              "Hold: %u, EOT: %u, Reten: %u, Load: %u",
3467                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
3468                              (flags & 0x02) >> 1, (flags & 0x01));
3469         flags = tvb_get_guint8 (tvb, offset+4);
3470         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3471                                     flags,
3472                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3473                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3474     }
3475 }
3476
3477 static void
3478 dissect_scsi_ssc2_readblocklimits (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3479                     guint offset, gboolean isreq, gboolean iscdb)
3480 {
3481     guint8 flags, granularity;
3482
3483     if (!tree)
3484         return;
3485
3486     if (isreq && iscdb) {
3487         flags = tvb_get_guint8 (tvb, offset+4);
3488         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3489                                     flags,
3490                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3491                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3492     }
3493     else if (!iscdb) {
3494         granularity = tvb_get_guint8 (tvb, offset);
3495         proto_tree_add_text (tree, tvb, offset, 1, "Granularity: %u (%u %s)",
3496                              granularity, 1 << granularity,
3497                              plurality(1 << granularity, "byte", "bytes"));
3498         proto_tree_add_text (tree, tvb, offset+1, 3, "Maximum Block Length Limit: %u bytes",
3499                              tvb_get_ntoh24 (tvb, offset+1));
3500         proto_tree_add_text (tree, tvb, offset+4, 2, "Minimum Block Length Limit: %u bytes",
3501                              tvb_get_ntohs (tvb, offset+4));
3502     }
3503 }
3504
3505 #define SHORT_FORM_BLOCK_ID        0x00
3506 #define SHORT_FORM_VENDOR_SPECIFIC 0x01
3507 #define LONG_FORM                  0x06
3508 #define EXTENDED_FORM              0x08
3509
3510 static const value_string service_action_vals[] = {
3511         {SHORT_FORM_BLOCK_ID,        "Short Form - Block ID"},
3512         {SHORT_FORM_VENDOR_SPECIFIC, "Short Form - Vendor-Specific"},
3513         {LONG_FORM,                  "Long Form"},
3514         {EXTENDED_FORM,              "Extended Form"},
3515         {0, NULL}
3516 };
3517
3518 #define BCU  0x20
3519 #define BYCU 0x10
3520 #define MPU  0x08
3521 #define BPU  0x04
3522
3523 static void
3524 dissect_scsi_ssc2_readposition (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3525                     guint offset, gboolean isreq, gboolean iscdb,
3526                     scsi_task_data_t *cdata)
3527 {
3528     gint service_action;
3529     guint8 flags;
3530
3531     if (!tree)
3532         return;
3533
3534     if (isreq && iscdb) {
3535         service_action = tvb_get_guint8 (tvb, offset) & 0x1F;
3536         proto_tree_add_text (tree, tvb, offset, 1,
3537                              "Service Action: %s",
3538                              val_to_str (service_action,
3539                                          service_action_vals,
3540                                          "Unknown (0x%02x)"));
3541         /* Remember the service action so we can decode the reply */
3542         if (cdata != NULL) {
3543             cdata->flags = service_action;
3544         }
3545         proto_tree_add_text (tree, tvb, offset+6, 2,
3546                              "Parameter Len: %u",
3547                              tvb_get_ntohs (tvb, offset+6));
3548         flags = tvb_get_guint8 (tvb, offset+8);
3549         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
3550                                     flags,
3551                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3552                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3553     }
3554     else if (!isreq) {
3555         if (cdata)
3556             service_action = cdata->flags;
3557         else
3558             service_action = -1; /* unknown */
3559         switch (service_action) {
3560         case SHORT_FORM_BLOCK_ID:
3561         case SHORT_FORM_VENDOR_SPECIFIC:
3562             flags = tvb_get_guint8 (tvb, offset);
3563             proto_tree_add_text (tree, tvb, offset, 1,
3564                              "BOP: %u, EOP: %u, BCU: %u, BYCU: %u, BPU: %u, PERR: %u",
3565                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
3566                              (flags & BCU) >> 5, (flags & BYCU) >> 4,
3567                              (flags & BPU) >> 2, (flags & 0x02) >> 1);
3568             offset += 1;
3569
3570             proto_tree_add_text (tree, tvb, offset, 1,
3571                                  "Partition Number: %u",
3572                                  tvb_get_guint8 (tvb, offset));
3573             offset += 1;
3574
3575             offset += 2; /* reserved */
3576
3577             if (!(flags & BPU)) {
3578                 proto_tree_add_text (tree, tvb, offset, 4,
3579                                      "First Block Location: %u",
3580                                      tvb_get_ntohl (tvb, offset));
3581                 offset += 4;
3582
3583                 proto_tree_add_text (tree, tvb, offset, 4,
3584                                      "Last Block Location: %u",
3585                                      tvb_get_ntohl (tvb, offset));
3586                 offset += 4;
3587             } else
3588                 offset += 8;
3589
3590             offset += 1; /* reserved */
3591
3592             if (!(flags & BCU)) {
3593                 proto_tree_add_text (tree, tvb, offset, 3,
3594                                      "Number of Blocks in Buffer: %u",
3595                                      tvb_get_ntoh24 (tvb, offset));
3596             }
3597             offset += 3;
3598
3599             if (!(flags & BYCU)) {
3600                 proto_tree_add_text (tree, tvb, offset, 4,
3601                                      "Number of Bytes in Buffer: %u",
3602                                      tvb_get_ntohl (tvb, offset));
3603             }
3604             offset += 4;
3605             break;
3606
3607         case LONG_FORM:
3608             flags = tvb_get_guint8 (tvb, offset);
3609             proto_tree_add_text (tree, tvb, offset, 1,
3610                              "BOP: %u, EOP: %u, MPU: %u, BPU: %u",
3611                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
3612                              (flags & MPU) >> 3, (flags & BPU) >> 2);
3613             offset += 1;
3614
3615             offset += 3; /* reserved */
3616
3617             if (!(flags & BPU)) {
3618                 proto_tree_add_text (tree, tvb, offset, 4,
3619                                      "Partition Number: %u",
3620                                      tvb_get_ntohl (tvb, offset));
3621                 offset += 4;
3622
3623                 proto_tree_add_text (tree, tvb, offset, 8,
3624                                      "Block Number: %s",
3625                                      u64toa (tvb_get_ptr (tvb, offset, 8)));
3626                  offset += 8;
3627             } else
3628                 offset += 12;
3629
3630             if (!(flags & MPU)) {
3631                 proto_tree_add_text (tree, tvb, offset, 8,
3632                                      "File Number: %s",
3633                                      u64toa (tvb_get_ptr (tvb, offset, 8)));
3634                 offset += 8;
3635
3636                 proto_tree_add_text (tree, tvb, offset, 8,
3637                                      "Set Number: %s",
3638                                      u64toa (tvb_get_ptr (tvb, offset, 8)));
3639                 offset += 8;
3640             } else
3641                 offset += 16;
3642             break;
3643
3644         case EXTENDED_FORM:
3645             flags = tvb_get_guint8 (tvb, offset);
3646             proto_tree_add_text (tree, tvb, offset, 1,
3647                              "BOP: %u, EOP: %u, BCU: %u, BYCU: %u, MPU: %u, BPU: %u, PERR: %u",
3648                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
3649                              (flags & BCU) >> 5, (flags & BYCU) >> 4,
3650                              (flags & MPU) >> 3, (flags & BPU) >> 2,
3651                              (flags & 0x02) >> 1);
3652             offset += 1;
3653
3654             proto_tree_add_text (tree, tvb, offset, 1,
3655                                  "Partition Number: %u",
3656                                  tvb_get_guint8 (tvb, offset));
3657             offset += 1;
3658
3659             proto_tree_add_text (tree, tvb, offset, 2,
3660                                  "Additional Length: %u",
3661                                  tvb_get_ntohs (tvb, offset));
3662             offset += 2;
3663
3664             offset += 1; /* reserved */
3665
3666             if (!(flags & BCU)) {
3667                 proto_tree_add_text (tree, tvb, offset, 3,
3668                                      "Number of Blocks in Buffer: %u",
3669                                      tvb_get_ntoh24 (tvb, offset));
3670             }
3671             offset += 3;
3672
3673             if (!(flags & BPU)) {
3674                 proto_tree_add_text (tree, tvb, offset, 8,
3675                                      "First Block Location: %s",
3676                                      u64toa (tvb_get_ptr (tvb, offset, 8)));
3677                 offset += 8;
3678
3679                 proto_tree_add_text (tree, tvb, offset, 8,
3680                                      "Last Block Location: %s",
3681                                      u64toa (tvb_get_ptr (tvb, offset, 8)));
3682                 offset += 8;
3683             } else
3684                 offset += 16;
3685
3686             offset += 1; /* reserved */
3687
3688             if (!(flags & BYCU)) {
3689                 proto_tree_add_text (tree, tvb, offset, 8,
3690                                      "Number of Bytes in Buffer: %s",
3691                                      u64toa (tvb_get_ptr (tvb, offset, 8)));
3692             }
3693             offset += 8;
3694             break;
3695
3696         default:
3697             break;
3698         }
3699     }
3700 }
3701
3702 static void
3703 dissect_scsi_ssc2_rewind (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3704                     guint offset, gboolean isreq, gboolean iscdb)
3705 {
3706     guint8 flags;
3707
3708     if (isreq && iscdb) {
3709         if (check_col (pinfo->cinfo, COL_INFO))
3710             col_append_fstr (pinfo->cinfo, COL_INFO, "(Immed: %u)",
3711                              tvb_get_guint8 (tvb, offset) & 0x01);
3712
3713         if (!tree)
3714             return;
3715
3716         proto_tree_add_text (tree, tvb, offset, 1,
3717                              "Immed: %u", tvb_get_guint8 (tvb, offset) & 0x01);
3718         flags = tvb_get_guint8 (tvb, offset+4);
3719         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
3720                                     flags,
3721                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3722                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3723     }
3724 }
3725
3726 static void
3727 dissect_scsi_smc2_movemedium (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
3728                     guint offset, gboolean isreq, gboolean iscdb)
3729 {
3730     guint8 flags;
3731
3732     if (tree && isreq && iscdb) {
3733         proto_tree_add_text (tree, tvb, offset+1, 2,
3734                              "Medium Transport Address: %u",
3735                              tvb_get_ntohs (tvb, offset+1));
3736         proto_tree_add_text (tree, tvb, offset+3, 2,
3737                              "Source Address: %u",
3738                              tvb_get_ntohs (tvb, offset+3));
3739         proto_tree_add_text (tree, tvb, offset+5, 2,
3740                              "Destination Address: %u",
3741                              tvb_get_ntohs (tvb, offset+5));
3742         flags = tvb_get_guint8 (tvb, offset+9);
3743         proto_tree_add_text (tree, tvb, offset+9, 1,
3744                              "INV: %u", flags & 0x01);
3745         flags = tvb_get_guint8 (tvb, offset+10);
3746         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
3747                                     flags,
3748                                     "Vendor Unique = %u, NACA = %u, Link = %u",
3749                                     flags & 0xC0, flags & 0x4, flags & 0x1);
3750     }
3751 }
3752
3753 #define MT_ELEM  0x1
3754 #define ST_ELEM  0x2
3755 #define I_E_ELEM 0x3
3756 #define DT_ELEM  0x4
3757
3758 static const value_string element_type_code_vals[] = {
3759     {0x0,      "All element types"},
3760     {MT_ELEM,  "Medium transport element"},
3761     {ST_ELEM,  "Storage element"},
3762     {I_E_ELEM, "Import/export element"},
3763     {DT_ELEM,  "Data transfer element"},
3764     {0, NULL}
3765 };
3766
3767 #define PVOLTAG 0x80
3768 #define AVOLTAG 0x40
3769
3770 #define EXCEPT 0x04
3771
3772 #define ID_VALID 0x20
3773 #define LU_VALID 0x10
3774
3775 #define SVALID 0x80
3776
3777 static void
3778 dissect_scsi_smc2_volume_tag (tvbuff_t *tvb, packet_info *pinfo _U_,
3779                               proto_tree *tree, guint offset,
3780                               const char *name)
3781 {
3782     char volid[32+1];
3783     char *p;
3784
3785     tvb_memcpy (tvb, (guint8 *)volid, offset, 32);
3786     p = &volid[32];
3787     for (;;) {
3788         *p = '\0';
3789         if (p == volid)
3790             break;
3791         if (*(p - 1) != ' ')
3792             break;
3793         p--;
3794     }
3795     proto_tree_add_text (tree, tvb, offset, 36,
3796                          "%s: Volume Identification = \"%s\", Volume Sequence Number = %u",
3797                          name, volid, tvb_get_ntohs (tvb, offset+34));
3798 }
3799
3800 static void
3801 dissect_scsi_smc2_element (tvbuff_t *tvb, packet_info *pinfo _U_,
3802                          proto_tree *tree, guint offset,
3803                          guint elem_bytecnt, guint8 elem_type,
3804                          guint8 voltag_flags)
3805 {
3806     guint8 flags;
3807     guint8 ident_len;
3808
3809     if (elem_bytecnt < 2)
3810         return;
3811     proto_tree_add_text (tree, tvb, offset, 2,
3812                          "Element Address: %u",
3813                          tvb_get_ntohs (tvb, offset));
3814     offset += 2;
3815     elem_bytecnt -= 2;
3816
3817     if (elem_bytecnt < 1)
3818         return;
3819     flags = tvb_get_guint8 (tvb, offset);
3820     switch (elem_type) {
3821
3822     case MT_ELEM:
3823         proto_tree_add_text (tree, tvb, offset, 1,
3824                             "EXCEPT: %u, FULL: %u",
3825                              (flags & EXCEPT) >> 2, flags & 0x01);
3826         break;
3827
3828     case ST_ELEM:
3829     case DT_ELEM:
3830         proto_tree_add_text (tree, tvb, offset, 1,
3831                              "ACCESS: %u, EXCEPT: %u, FULL: %u",
3832                              (flags & 0x08) >> 3,
3833                              (flags & EXCEPT) >> 2, flags & 0x01);
3834         break;
3835
3836     case I_E_ELEM:
3837         proto_tree_add_text (tree, tvb, offset, 1,
3838                              "cmc: %u, INENAB: %u, EXENAB: %u, ACCESS: %u, EXCEPT: %u, IMPEXP: %u, FULL: %u",
3839                              (flags & 0x40) >> 6,
3840                              (flags & 0x20) >> 5,
3841                              (flags & 0x10) >> 4,
3842                              (flags & 0x08) >> 3,
3843                              (flags & EXCEPT) >> 2,
3844                              (flags & 0x02) >> 1,
3845                              flags & 0x01);
3846         break;
3847     }
3848     offset += 1;
3849     elem_bytecnt -= 1;
3850
3851     if (elem_bytecnt < 1)
3852         return;
3853     offset += 1; /* reserved */
3854     elem_bytecnt -= 1;
3855
3856     if (elem_bytecnt < 2)
3857         return;
3858     if (flags & EXCEPT) {
3859         proto_tree_add_text (tree, tvb, offset, 2,
3860                              "Additional Sense Code+Qualifier: %s",
3861                              val_to_str (tvb_get_ntohs (tvb, offset),
3862                                          scsi_asc_val, "Unknown (0x%04x)"));
3863     }
3864     offset += 2;
3865     elem_bytecnt -= 2;
3866
3867     if (elem_bytecnt < 3)
3868         return;
3869     switch (elem_type) {
3870
3871     case DT_ELEM:
3872         flags = tvb_get_guint8 (tvb, offset);
3873         if (flags & LU_VALID) {
3874             proto_tree_add_text (tree, tvb, offset, 1,
3875                                  "NOT BUS: %u, ID VALID: %u, LU VALID: 1, LUN: %u",
3876                                  (flags & 0x80) >> 7,
3877                                  (flags & ID_VALID) >> 5,
3878                                  flags & 0x07);
3879         } else if (flags & ID_VALID) {
3880             proto_tree_add_text (tree, tvb, offset, 1,
3881                                  "ID VALID: 1, LU VALID: 0");
3882         } else {
3883             proto_tree_add_text (tree, tvb, offset, 1,
3884                                  "ID VALID: 0, LU VALID: 0");
3885         }
3886         offset += 1;
3887         if (flags & ID_VALID) {
3888             proto_tree_add_text (tree, tvb, offset, 1,
3889                                  "SCSI Bus Address: %u",
3890                                  tvb_get_guint8 (tvb, offset));
3891         }
3892         offset += 1;
3893         offset += 1; /* reserved */
3894         break;
3895
3896     default:
3897         offset += 3; /* reserved */
3898         break;
3899     }
3900     elem_bytecnt -= 3;
3901
3902     if (elem_bytecnt < 3)
3903         return;
3904     flags = tvb_get_guint8 (tvb, offset);
3905     if (flags & SVALID) {
3906         proto_tree_add_text (tree, tvb, offset, 1,
3907                              "SVALID: 1, INVERT: %u",
3908                              (flags & 0x40) >> 6);
3909         offset += 1;
3910         proto_tree_add_text (tree, tvb, offset, 2,
3911                              "Source Storage Element Address: %u",
3912                              tvb_get_ntohs (tvb, offset));
3913         offset += 2;
3914     } else {
3915         proto_tree_add_text (tree, tvb, offset, 1,
3916                              "SVALID: 0");
3917         offset += 3;
3918     }
3919     elem_bytecnt -= 3;
3920
3921     if (voltag_flags & PVOLTAG) {
3922         if (elem_bytecnt < 36)
3923             return;
3924         dissect_scsi_smc2_volume_tag (tvb, pinfo, tree, offset,
3925                                       "Primary Volume Tag Information");
3926         offset += 36;
3927         elem_bytecnt -= 36;
3928     }
3929
3930     if (voltag_flags & AVOLTAG) {
3931         if (elem_bytecnt < 36)
3932             return;
3933         dissect_scsi_smc2_volume_tag (tvb, pinfo, tree, offset,
3934                                       "Alternate Volume Tag Information");
3935         offset += 36;
3936         elem_bytecnt -= 36;
3937     }
3938
3939     if (elem_bytecnt < 1)
3940         return;
3941     flags = tvb_get_guint8 (tvb, offset);
3942     proto_tree_add_text (tree, tvb, offset, 1,
3943                          "Code Set: %s",
3944                          val_to_str (flags & 0x0F,
3945                                      scsi_devid_codeset_val,
3946                                      "Unknown (0x%02x)"));
3947     offset += 1;
3948     elem_bytecnt -= 1;
3949
3950     if (elem_bytecnt < 1)
3951         return;
3952     flags = tvb_get_guint8 (tvb, offset);
3953     proto_tree_add_text (tree, tvb, offset, 1,
3954                          "Identifier Type: %s",
3955                          val_to_str ((flags & 0x0F),
3956                                      scsi_devid_idtype_val,
3957                                      "Unknown (0x%02x)"));
3958     offset += 1;
3959     elem_bytecnt -= 1;
3960
3961     if (elem_bytecnt < 1)
3962         return;
3963     offset += 1; /* reserved */
3964     elem_bytecnt -= 1;
3965
3966     if (elem_bytecnt < 1)
3967         return;
3968     ident_len = tvb_get_guint8 (tvb, offset);
3969     proto_tree_add_text (tree, tvb, offset, 1,
3970                          "Identifier Length: %u",
3971                          ident_len);
3972     offset += 1;
3973     elem_bytecnt -= 1;
3974
3975     if (ident_len != 0) {
3976         if (elem_bytecnt < ident_len)
3977             return;
3978         proto_tree_add_text (tree, tvb, offset, ident_len,
3979                              "Identifier: %s",
3980                              tvb_bytes_to_str (tvb, offset, ident_len));
3981         offset += ident_len;
3982         elem_bytecnt -= ident_len;
3983     }
3984     if (elem_bytecnt != 0) {
3985         proto_tree_add_text (tree, tvb, offset, elem_bytecnt,
3986                              "Vendor-specific Data: %s",
3987                              tvb_bytes_to_str (tvb, offset, elem_bytecnt));
3988     }
3989 }
3990
3991 static void
3992 dissect_scsi_smc2_elements (tvbuff_t *tvb, packet_info *pinfo,
3993                             proto_tree *tree, guint offset,
3994                             guint desc_bytecnt, guint8 elem_type,
3995                             guint8 voltag_flags, guint16 elem_desc_len)
3996 {
3997     guint elem_bytecnt;
3998
3999     while (desc_bytecnt != 0) {
4000         elem_bytecnt = elem_desc_len;
4001         if (elem_bytecnt > desc_bytecnt)
4002             elem_bytecnt = desc_bytecnt;
4003         dissect_scsi_smc2_element (tvb, pinfo, tree, offset, elem_bytecnt,
4004                                    elem_type, voltag_flags);
4005         offset += elem_bytecnt;
4006         desc_bytecnt -= elem_bytecnt;
4007     }
4008 }
4009
4010 static void
4011 dissect_scsi_smc2_readelementstatus (tvbuff_t *tvb, packet_info *pinfo,
4012                          proto_tree *tree, guint offset, gboolean isreq,
4013                          gboolean iscdb)
4014 {
4015     guint8 flags;
4016     guint numelem, bytecnt, desc_bytecnt;
4017     guint8 elem_type;
4018     guint8 voltag_flags;
4019     guint16 elem_desc_len;
4020
4021     if (!tree)
4022         return;
4023
4024     if (isreq && iscdb) {
4025         flags = tvb_get_guint8 (tvb, offset);
4026         proto_tree_add_text (tree, tvb, offset, 1,
4027                              "VOLTAG: %u, Element Type Code: %s",
4028                              (flags & 0x10) >> 4,
4029                              val_to_str (flags & 0xF, element_type_code_vals,
4030                                          "Unknown (0x%x)"));
4031         proto_tree_add_text (tree, tvb, offset+1, 2,
4032                              "Starting Element Address: %u",
4033                              tvb_get_ntohs (tvb, offset+1));
4034         proto_tree_add_text (tree, tvb, offset+3, 2,
4035                              "Number of Elements: %u",
4036                              tvb_get_ntohs (tvb, offset+3));
4037         flags = tvb_get_guint8 (tvb, offset+4);
4038         proto_tree_add_text (tree, tvb, offset+4, 1,
4039                              "CURDATA: %u, DVCID: %u",
4040                              (flags & 0x02) >> 1, flags & 0x01);
4041         proto_tree_add_text (tree, tvb, offset+5, 3,
4042                              "Allocation Length: %u",
4043                              tvb_get_ntoh24 (tvb, offset+5));
4044         flags = tvb_get_guint8 (tvb, offset+10);
4045         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
4046                                     flags,
4047                                     "Vendor Unique = %u, NACA = %u, Link = %u",
4048                                     flags & 0xC0, flags & 0x4, flags & 0x1);
4049     }
4050     else if (!isreq) {
4051         proto_tree_add_text (tree, tvb, offset, 2,
4052                              "First Element Address Reported: %u",
4053                              tvb_get_ntohs (tvb, offset));
4054         offset += 2;
4055         numelem = tvb_get_ntohs (tvb, offset);
4056         proto_tree_add_text (tree, tvb, offset, 2,
4057                              "Number of Elements Available: %u", numelem);
4058         offset += 2;
4059         offset += 1; /* reserved */
4060         bytecnt = tvb_get_ntoh24 (tvb, offset);
4061         proto_tree_add_text (tree, tvb, offset, 3,
4062                              "Byte Count of Report Available: %u", bytecnt);
4063         offset += 3;
4064         while (bytecnt != 0) {
4065             if (bytecnt < 1)
4066                 break;
4067             elem_type = tvb_get_guint8 (tvb, offset);
4068             proto_tree_add_text (tree, tvb, offset, 1,
4069                                  "Element Type Code: %s",
4070                                  val_to_str (elem_type, element_type_code_vals,
4071                                              "Unknown (0x%x)"));
4072             offset += 1;
4073             bytecnt -= 1;
4074
4075             if (bytecnt < 1)
4076                 break;
4077             voltag_flags = tvb_get_guint8 (tvb, offset);
4078             proto_tree_add_text (tree, tvb, offset, 1,
4079                                  "PVOLTAG: %u, AVOLTAG: %u",
4080                                  (voltag_flags & PVOLTAG) >> 7,
4081                                  (voltag_flags & AVOLTAG) >> 6);
4082             offset += 1;
4083             bytecnt -= 1;
4084
4085             if (bytecnt < 2)
4086                 break;
4087             elem_desc_len = tvb_get_ntohs (tvb, offset);
4088             proto_tree_add_text (tree, tvb, offset, 2,
4089                                  "Element Descriptor Length: %u",
4090                                  elem_desc_len);
4091             offset += 2;
4092             bytecnt -= 2;
4093
4094             if (bytecnt < 1)
4095                 break;
4096             offset += 1; /* reserved */
4097             bytecnt -= 1;
4098
4099             if (bytecnt < 3)
4100                 break;
4101             desc_bytecnt = tvb_get_ntoh24 (tvb, offset);
4102             proto_tree_add_text (tree, tvb, offset, 3,
4103                                  "Byte Count Of Descriptor Data Available: %u",
4104                                  desc_bytecnt);
4105             offset += 3;
4106             bytecnt -= 3;
4107
4108             if (desc_bytecnt > bytecnt)
4109                 desc_bytecnt = bytecnt;
4110             dissect_scsi_smc2_elements (tvb, pinfo, tree, offset,
4111                                         desc_bytecnt, elem_type,
4112                                         voltag_flags, elem_desc_len);
4113             offset += desc_bytecnt;
4114             bytecnt -= desc_bytecnt;
4115         }
4116     }
4117 }
4118
4119 void
4120 dissect_scsi_rsp (tvbuff_t *tvb _U_, packet_info *pinfo _U_,
4121                   proto_tree *tree _U_)
4122 {
4123     /* Nothing to do here, just blow up the data structures for this SCSI
4124      * transaction
4125     if (tree)
4126         scsi_end_task (pinfo);
4127      */
4128 }
4129
4130 void
4131 dissect_scsi_snsinfo (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4132                       guint offset, guint snslen)
4133 {
4134     guint8 flags;
4135     proto_item *ti;
4136     proto_tree *sns_tree;
4137
4138     scsi_end_task (pinfo);
4139
4140     if (tree) {
4141         ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
4142                                              snslen, "SCSI: SNS Info");
4143         sns_tree = proto_item_add_subtree (ti, ett_scsi);
4144
4145         flags = tvb_get_guint8 (tvb, offset);
4146         proto_tree_add_text (sns_tree, tvb, offset, 1, "Valid: %u",
4147                              (flags & 0x80) >> 7);
4148         proto_tree_add_item (sns_tree, hf_scsi_sns_errtype, tvb, offset, 1, 0);
4149         flags = tvb_get_guint8 (tvb, offset+2);
4150         proto_tree_add_text (sns_tree, tvb, offset+2, 1,
4151                              "Filemark: %u, EOM: %u, ILI: %u",
4152                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
4153                              (flags & 0x20) >> 5);
4154         proto_tree_add_item (sns_tree, hf_scsi_snskey, tvb, offset+2, 1, 0);
4155         proto_tree_add_item (sns_tree, hf_scsi_snsinfo, tvb, offset+3, 4, 0);
4156         proto_tree_add_item (sns_tree, hf_scsi_addlsnslen, tvb, offset+7, 1, 0);
4157         proto_tree_add_text (sns_tree, tvb, offset+8, 4,
4158                              "Command-Specific Information: %s",
4159                              tvb_bytes_to_str (tvb, offset+8, 4));
4160         proto_tree_add_item (sns_tree, hf_scsi_ascascq, tvb, offset+12, 2, 0);
4161         proto_tree_add_item_hidden (sns_tree, hf_scsi_asc, tvb, offset+12, 1, 0);
4162         proto_tree_add_item_hidden (sns_tree, hf_scsi_ascq, tvb, offset+13,
4163                                     1, 0);
4164         proto_tree_add_item (sns_tree, hf_scsi_fru, tvb, offset+14, 1, 0);
4165         proto_tree_add_item (sns_tree, hf_scsi_sksv, tvb, offset+15, 1, 0);
4166         proto_tree_add_text (sns_tree, tvb, offset+15, 3,
4167                              "Sense Key Specific: %s",
4168                              tvb_bytes_to_str (tvb, offset+15, 3));
4169     }
4170 }
4171
4172 void
4173 dissect_scsi_cdb (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4174                   guint start, guint cdblen, gint devtype_arg)
4175 {
4176     int offset = start;
4177     proto_item *ti;
4178     proto_tree *scsi_tree = NULL;
4179     guint8 opcode;
4180     scsi_device_type devtype;
4181     scsi_cmnd_type cmd = 0;     /* 0 is undefined type */
4182     gchar *valstr;
4183     scsi_task_data_t *cdata;
4184     scsi_devtype_key_t dkey;
4185     scsi_devtype_data_t *devdata;
4186
4187     opcode = tvb_get_guint8 (tvb, offset);
4188
4189     if (devtype_arg != SCSI_DEV_UNKNOWN)
4190         devtype = devtype_arg;
4191     else {
4192         /*
4193          * Try to look up the device data for this device.
4194          *
4195          * We don't use COPY_ADDRESS because "dkey.devid" isn't
4196          * persistent, and therefore it can point to the stuff
4197          * in "pinfo->src".  (Were we to use COPY_ADDRESS, we'd
4198          * have to free the address data it allocated before we return.)
4199          */
4200         dkey.devid = pinfo->dst;
4201
4202         devdata = (scsi_devtype_data_t *)g_hash_table_lookup (scsidev_req_hash,
4203                                                               &dkey);
4204         if (devdata != NULL) {
4205             devtype = devdata->devtype;
4206         }
4207         else {
4208             devtype = (scsi_device_type)scsi_def_devtype;
4209         }
4210     }
4211
4212     if ((valstr = match_strval (opcode, scsi_spc2_val)) == NULL) {
4213         /*
4214          * This isn't a generic command that applies to all SCSI
4215          * device types; try to interpret it based on what we deduced,
4216          * or were told, the device type is.
4217          *
4218          * Right now, the only choices are SBC or SSC. If we ever expand
4219          * this to decode other device types, this piece of code needs to
4220          * be modified.
4221          */
4222         switch (devtype) {
4223         case SCSI_DEV_SBC:
4224             valstr = match_strval (opcode, scsi_sbc2_val);
4225             cmd = SCSI_CMND_SBC2;
4226             break;
4227
4228         case SCSI_DEV_SSC:
4229             valstr = match_strval (opcode, scsi_ssc2_val);
4230             cmd = SCSI_CMND_SSC2;
4231             break;
4232
4233         case SCSI_DEV_SMC:
4234             valstr = match_strval (opcode, scsi_smc2_val);
4235             cmd = SCSI_CMND_SMC2;
4236             break;
4237
4238         default:
4239             cmd = SCSI_CMND_SPC2;
4240             break;
4241         }
4242     }
4243     else {
4244         cmd = SCSI_CMND_SPC2;
4245     }
4246
4247     if (valstr != NULL) {
4248         if (check_col (pinfo->cinfo, COL_INFO)) {
4249             col_add_fstr (pinfo->cinfo, COL_INFO, "SCSI: %s", valstr);
4250         }
4251     }
4252     else {
4253         if (check_col (pinfo->cinfo, COL_INFO)) {
4254             col_add_fstr (pinfo->cinfo, COL_INFO, "SCSI Command: 0x%02x", opcode);
4255         }
4256     }
4257
4258     cdata = scsi_new_task (pinfo);
4259
4260     if (cdata) {
4261         cdata->opcode = opcode;
4262         cdata->cmd = cmd;
4263         cdata->devtype = devtype;
4264     }
4265
4266     if (tree) {
4267         ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, start,
4268                                              cdblen, "SCSI CDB");
4269         scsi_tree = proto_item_add_subtree (ti, ett_scsi);
4270
4271         if (valstr != NULL) {
4272             if (cmd == SCSI_CMND_SPC2) {
4273                 proto_tree_add_uint_format (scsi_tree, hf_scsi_spcopcode, tvb,
4274                                             offset, 1,
4275                                             tvb_get_guint8 (tvb, offset),
4276                                             "Opcode: %s (0x%02x)", valstr,
4277                                             opcode);
4278             }
4279             else if (cmd == SCSI_CMND_SBC2) {
4280                 proto_tree_add_uint_format (scsi_tree, hf_scsi_sbcopcode, tvb,
4281                                             offset, 1,
4282                                             tvb_get_guint8 (tvb, offset),
4283                                             "Opcode: %s (0x%02x)", valstr,
4284                                             opcode);
4285             }
4286             else if (cmd == SCSI_CMND_SSC2) {
4287                 proto_tree_add_uint_format (scsi_tree, hf_scsi_sscopcode, tvb,
4288                                             offset, 1,
4289                                             tvb_get_guint8 (tvb, offset),
4290                                             "Opcode: %s (0x%02x)", valstr,
4291                                             opcode);
4292             }
4293             else if (cmd == SCSI_CMND_SMC2) {
4294                 proto_tree_add_uint_format (scsi_tree, hf_scsi_smcopcode, tvb,
4295                                             offset, 1,
4296                                             tvb_get_guint8 (tvb, offset),
4297                                             "Opcode: %s (0x%02x)", valstr,
4298                                             opcode);
4299             }
4300             else {
4301                 /* "Can't happen" */
4302                 g_assert_not_reached();
4303             }
4304         }
4305         else {
4306             proto_tree_add_item (scsi_tree, hf_scsi_spcopcode, tvb, offset, 1, 0);
4307         }
4308     }
4309
4310     switch (cmd) {
4311     case SCSI_CMND_SPC2:
4312         switch (opcode) {
4313         case SCSI_SPC2_INQUIRY:
4314             dissect_scsi_inquiry (tvb, pinfo, scsi_tree, offset+1, TRUE,
4315                                   TRUE, 0, cdata);
4316             break;
4317
4318         case SCSI_SPC2_EXTCOPY:
4319             dissect_scsi_extcopy (tvb, pinfo, scsi_tree, offset+1, TRUE,
4320                                   TRUE);
4321             break;
4322
4323         case SCSI_SPC2_LOGSELECT:
4324             dissect_scsi_logselect (tvb, pinfo, scsi_tree, offset+1, TRUE,
4325                                     TRUE);
4326             break;
4327
4328         case SCSI_SPC2_LOGSENSE:
4329             dissect_scsi_logsense (tvb, pinfo, scsi_tree, offset+1, TRUE,
4330                                    TRUE);
4331             break;
4332
4333         case SCSI_SPC2_MODESELECT6:
4334             dissect_scsi_modeselect6 (tvb, pinfo, scsi_tree, offset+1,
4335                                       TRUE, TRUE, devtype, 0);
4336             break;
4337
4338         case SCSI_SPC2_MODESELECT10:
4339             dissect_scsi_modeselect10 (tvb, pinfo, scsi_tree, offset+1,
4340                                        TRUE, TRUE, devtype, 0);
4341             break;
4342
4343         case SCSI_SPC2_MODESENSE6:
4344             dissect_scsi_modesense6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4345                                      TRUE, devtype, 0);
4346             break;
4347
4348         case SCSI_SPC2_MODESENSE10:
4349             dissect_scsi_modesense10 (tvb, pinfo, scsi_tree, offset+1,
4350                                       TRUE, TRUE, devtype, 0);
4351             break;
4352
4353         case SCSI_SPC2_PERSRESVIN:
4354             dissect_scsi_persresvin (tvb, pinfo, scsi_tree, offset+1, TRUE,
4355                                      TRUE, cdata, 0);
4356             break;
4357
4358         case SCSI_SPC2_PERSRESVOUT:
4359             dissect_scsi_persresvout (tvb, pinfo, scsi_tree, offset+1,
4360                                       TRUE, TRUE, cdata, 0);
4361             break;
4362
4363         case SCSI_SPC2_RELEASE6:
4364             dissect_scsi_release6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4365                                    TRUE);
4366             break;
4367
4368         case SCSI_SPC2_RELEASE10:
4369             dissect_scsi_release10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4370                                     TRUE);
4371             break;
4372
4373         case SCSI_SPC2_REPORTDEVICEID:
4374             dissect_scsi_reportdeviceid (tvb, pinfo, scsi_tree, offset+1,
4375                                          TRUE, TRUE);
4376             break;
4377
4378         case SCSI_SPC2_REPORTLUNS:
4379             dissect_scsi_reportluns (tvb, pinfo, scsi_tree, offset+1, TRUE,
4380                                      TRUE, 0);
4381             break;
4382
4383         case SCSI_SPC2_REQSENSE:
4384             dissect_scsi_reqsense (tvb, pinfo, scsi_tree, offset+1, TRUE,
4385                                    TRUE);
4386             break;
4387
4388         case SCSI_SPC2_RESERVE6:
4389             dissect_scsi_reserve6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4390                                    TRUE);
4391             break;
4392
4393         case SCSI_SPC2_RESERVE10:
4394             dissect_scsi_reserve10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4395                                     TRUE);
4396             break;
4397
4398         case SCSI_SPC2_TESTUNITRDY:
4399             dissect_scsi_testunitrdy (tvb, pinfo, scsi_tree, offset+1,
4400                                       TRUE, TRUE);
4401             break;
4402
4403         case SCSI_SPC2_VARLENCDB:
4404             dissect_scsi_varlencdb (tvb, pinfo, scsi_tree, offset+1,
4405                                     TRUE, TRUE);
4406             break;
4407
4408         default:
4409             call_dissector (data_handle, tvb, pinfo, scsi_tree);
4410             break;
4411         }
4412         break;
4413
4414     case SCSI_CMND_SBC2:
4415         switch (opcode) {
4416
4417         case SCSI_SBC2_FORMATUNIT:
4418             dissect_scsi_formatunit (tvb, pinfo, scsi_tree, offset+1, TRUE,
4419                                      TRUE);
4420             break;
4421
4422         case SCSI_SBC2_READ6:
4423             dissect_scsi_sbc2_rdwr6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4424                                 TRUE);
4425             break;
4426
4427         case SCSI_SBC2_READ10:
4428             dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4429                                  TRUE);
4430             break;
4431
4432         case SCSI_SBC2_READ12:
4433             dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4434                                  TRUE);
4435             break;
4436
4437         case SCSI_SBC2_READ16:
4438             dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4439                                  TRUE);
4440             break;
4441
4442         case SCSI_SBC2_READCAPACITY:
4443             dissect_scsi_readcapacity (tvb, pinfo, scsi_tree, offset+1,
4444                                        TRUE, TRUE);
4445             break;
4446
4447         case SCSI_SBC2_READDEFDATA10:
4448             dissect_scsi_readdefdata10 (tvb, pinfo, scsi_tree, offset+1,
4449                                         TRUE, TRUE);
4450             break;
4451
4452         case SCSI_SBC2_READDEFDATA12:
4453             dissect_scsi_readdefdata12 (tvb, pinfo, scsi_tree, offset+1,
4454                                         TRUE, TRUE);
4455             break;
4456
4457         case SCSI_SBC2_REASSIGNBLKS:
4458             dissect_scsi_reassignblks (tvb, pinfo, scsi_tree, offset+1,
4459                                        TRUE, TRUE);
4460             break;
4461
4462         case SCSI_SBC2_WRITE6:
4463             dissect_scsi_sbc2_rdwr6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4464                                 TRUE);
4465             break;
4466
4467         case SCSI_SBC2_WRITE10:
4468             dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4469                                  TRUE);
4470             break;
4471
4472         case SCSI_SBC2_WRITE12:
4473             dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4474                                  TRUE);
4475             break;
4476
4477         case SCSI_SBC2_WRITE16:
4478             dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4479                                  TRUE);
4480             break;
4481
4482         default:
4483             call_dissector (data_handle, tvb, pinfo, scsi_tree);
4484             break;
4485         }
4486         break;
4487
4488     case SCSI_CMND_SSC2:
4489         switch (opcode) {
4490
4491         case SCSI_SSC2_READ6:
4492             dissect_scsi_ssc2_read6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4493                                 TRUE);
4494             break;
4495
4496         case SCSI_SSC2_WRITE6:
4497             dissect_scsi_ssc2_write6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4498                                 TRUE);
4499             break;
4500
4501         case SCSI_SSC2_WRITE_FILEMARKS_6:
4502             dissect_scsi_ssc2_writefilemarks6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
4503                                 TRUE);
4504             break;
4505
4506         case SCSI_SSC2_LOAD_UNLOAD:
4507             dissect_scsi_ssc2_loadunload (tvb, pinfo, scsi_tree, offset+1, TRUE,
4508                             TRUE);
4509             break;
4510
4511         case SCSI_SSC2_READ_BLOCK_LIMITS:
4512             dissect_scsi_ssc2_readblocklimits (tvb, pinfo, scsi_tree, offset+1, TRUE,
4513                             TRUE);
4514             break;
4515
4516         case SCSI_SSC2_READ_POSITION:
4517             dissect_scsi_ssc2_readposition (tvb, pinfo, scsi_tree, offset+1, TRUE,
4518                             TRUE, cdata);
4519             break;
4520
4521         case SCSI_SSC2_REWIND:
4522             dissect_scsi_ssc2_rewind (tvb, pinfo, scsi_tree, offset+1, TRUE,
4523                             TRUE);
4524             break;
4525
4526         default:
4527             call_dissector (data_handle, tvb, pinfo, scsi_tree);
4528             break;
4529         }
4530         break;
4531
4532     case SCSI_CMND_SMC2:
4533         switch (opcode) {
4534
4535         case SCSI_SMC2_MOVE_MEDIUM:
4536         case SCSI_SMC2_MOVE_MEDIUM_ATTACHED:
4537             dissect_scsi_smc2_movemedium (tvb, pinfo, scsi_tree, offset+1, TRUE,
4538                             TRUE);
4539             break;
4540
4541         case SCSI_SMC2_READ_ELEMENT_STATUS:
4542         case SCSI_SMC2_READ_ELEMENT_STATUS_ATTACHED:
4543             dissect_scsi_smc2_readelementstatus (tvb, pinfo, scsi_tree, offset+1, TRUE,
4544                             TRUE);
4545             break;
4546
4547         default:
4548             call_dissector (data_handle, tvb, pinfo, scsi_tree);
4549             break;
4550         }
4551         break;
4552
4553     default:
4554         call_dissector (data_handle, tvb, pinfo, scsi_tree);
4555         break;
4556     }
4557 }
4558
4559 void
4560 dissect_scsi_payload (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4561                       guint offset, gboolean isreq, guint32 payload_len)
4562 {
4563     proto_item *ti;
4564     proto_tree *scsi_tree = NULL;
4565     guint8 opcode = 0xFF;
4566     scsi_cmnd_type cmd = 0;     /* 0 is undefined type */
4567     scsi_device_type devtype;
4568     scsi_task_data_t *cdata = NULL;
4569
4570     cdata = scsi_find_task (pinfo);
4571
4572     if (!cdata) {
4573         /* we have no record of this exchange and so we can't dissect the
4574          * payload
4575          */
4576         return;
4577     }
4578
4579     opcode = cdata->opcode;
4580     cmd = cdata->cmd;
4581     devtype = cdata->devtype;
4582
4583     if (tree) {
4584         switch (cmd) {
4585         case SCSI_CMND_SPC2:
4586             ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
4587                                                  payload_len,
4588                                                  "SCSI Payload (%s %s)",
4589                                                  val_to_str (opcode,
4590                                                              scsi_spc2_val,
4591                                                              "0x%02x"),
4592                                                  isreq ? "Request" : "Response");
4593             break;
4594
4595         case SCSI_CMND_SBC2:
4596             ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
4597                                                  payload_len,
4598                                                  "SCSI Payload (%s %s)",
4599                                                  val_to_str (opcode,
4600                                                              scsi_sbc2_val,
4601                                                              "0x%02x"),
4602                                                  isreq ? "Request" : "Response");
4603             break;
4604
4605         case SCSI_CMND_SSC2:
4606             ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
4607                                                  payload_len,
4608                                                  "SCSI Payload (%s %s)",
4609                                                  val_to_str (opcode,
4610                                                              scsi_ssc2_val,
4611                                                              "0x%02x"),
4612                                                  isreq ? "Request" : "Response");
4613             break;
4614
4615         case SCSI_CMND_SMC2:
4616             ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
4617                                                  payload_len,
4618                                                  "SCSI Payload (%s %s)",
4619                                                  val_to_str (opcode,
4620                                                              scsi_smc2_val,
4621                                                              "0x%02x"),
4622                                                  isreq ? "Request" : "Response");
4623             break;
4624
4625         default:
4626             ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
4627                                                  payload_len,
4628                                                  "SCSI Payload (0x%02x %s)",
4629                                                  opcode,
4630                                                  isreq ? "Request" : "Response");
4631             break;
4632         }
4633
4634         scsi_tree = proto_item_add_subtree (ti, ett_scsi);
4635     }
4636
4637     if (tree == NULL) {
4638         /*
4639          * We have to dissect INQUIRY responses, in order to determine the
4640          * types of devices.
4641          *
4642          * We don't bother dissecting other payload if we're not buildng
4643          * a protocol tree.
4644          */
4645         if (cmd == SCSI_CMND_SPC2 && opcode == SCSI_SPC2_INQUIRY) {
4646             dissect_scsi_inquiry (tvb, pinfo, scsi_tree, offset, isreq,
4647                                   FALSE, payload_len, cdata);
4648         }
4649       } else {
4650         switch (cmd) {
4651         case SCSI_CMND_SPC2:
4652             switch (opcode) {
4653             case SCSI_SPC2_INQUIRY:
4654                 dissect_scsi_inquiry (tvb, pinfo, scsi_tree, offset, isreq,
4655                                       FALSE, payload_len, cdata);
4656                 break;
4657
4658             case SCSI_SPC2_EXTCOPY:
4659                 dissect_scsi_extcopy (tvb, pinfo, scsi_tree, offset, isreq,
4660                                       FALSE);
4661                 break;
4662
4663             case SCSI_SPC2_LOGSELECT:
4664                 dissect_scsi_logselect (tvb, pinfo, scsi_tree, offset, isreq,
4665                                         FALSE);
4666                 break;
4667
4668             case SCSI_SPC2_LOGSENSE:
4669                 dissect_scsi_logsense (tvb, pinfo, scsi_tree, offset, isreq,
4670                                        FALSE);
4671                 break;
4672
4673             case SCSI_SPC2_MODESELECT6:
4674                 dissect_scsi_modeselect6 (tvb, pinfo, scsi_tree, offset,
4675                                           isreq, FALSE, devtype, payload_len);
4676                 break;
4677
4678             case SCSI_SPC2_MODESELECT10:
4679                 dissect_scsi_modeselect10 (tvb, pinfo, scsi_tree, offset,
4680                                            isreq, FALSE, devtype, payload_len);
4681                 break;
4682
4683             case SCSI_SPC2_MODESENSE6:
4684                 dissect_scsi_modesense6 (tvb, pinfo, scsi_tree, offset, isreq,
4685                                          FALSE, devtype, payload_len);
4686                 break;
4687
4688             case SCSI_SPC2_MODESENSE10:
4689                 dissect_scsi_modesense10 (tvb, pinfo, scsi_tree, offset,
4690                                           isreq, FALSE, devtype, payload_len);
4691                 break;
4692
4693             case SCSI_SPC2_PERSRESVIN:
4694                 dissect_scsi_persresvin (tvb, pinfo, scsi_tree, offset, isreq,
4695                                          FALSE, cdata, payload_len);
4696                 break;
4697
4698             case SCSI_SPC2_PERSRESVOUT:
4699                 dissect_scsi_persresvout (tvb, pinfo, scsi_tree, offset,
4700                                           isreq, FALSE, cdata, payload_len);
4701                 break;
4702
4703             case SCSI_SPC2_RELEASE6:
4704                 dissect_scsi_release6 (tvb, pinfo, scsi_tree, offset, isreq,
4705                                        FALSE);
4706                 break;
4707
4708             case SCSI_SPC2_RELEASE10:
4709                 dissect_scsi_release10 (tvb, pinfo, scsi_tree, offset, isreq,
4710                                         FALSE);
4711                 break;
4712
4713             case SCSI_SPC2_REPORTDEVICEID:
4714                 dissect_scsi_reportdeviceid (tvb, pinfo, scsi_tree, offset,
4715                                              isreq, FALSE);
4716                 break;
4717
4718             case SCSI_SPC2_REPORTLUNS:
4719                 dissect_scsi_reportluns (tvb, pinfo, scsi_tree, offset, isreq,
4720                                          FALSE, payload_len);
4721                 break;
4722
4723             case SCSI_SPC2_REQSENSE:
4724                 dissect_scsi_reqsense (tvb, pinfo, scsi_tree, offset, isreq,
4725                                        FALSE);
4726                 break;
4727
4728             case SCSI_SPC2_RESERVE6:
4729                 dissect_scsi_reserve6 (tvb, pinfo, scsi_tree, offset, isreq,
4730                                        FALSE);
4731                 break;
4732
4733             case SCSI_SPC2_RESERVE10:
4734                 dissect_scsi_reserve10 (tvb, pinfo, scsi_tree, offset, isreq,
4735                                         FALSE);
4736                 break;
4737
4738             case SCSI_SPC2_TESTUNITRDY:
4739                 dissect_scsi_testunitrdy (tvb, pinfo, scsi_tree, offset,
4740                                           isreq, FALSE);
4741                 break;
4742
4743             default:
4744                 call_dissector (data_handle, tvb, pinfo, scsi_tree);
4745                 break;
4746             }
4747             break;
4748
4749         case SCSI_CMND_SBC2:
4750             switch (opcode) {
4751
4752             case SCSI_SBC2_FORMATUNIT:
4753                 dissect_scsi_formatunit (tvb, pinfo, scsi_tree, offset, isreq,
4754                                          FALSE);
4755                 break;
4756
4757             case SCSI_SBC2_READ6:
4758                 dissect_scsi_sbc2_rdwr6 (tvb, pinfo, scsi_tree, offset, isreq,
4759                                     FALSE);
4760                 break;
4761
4762             case SCSI_SBC2_READ10:
4763                 dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset, isreq,
4764                                      FALSE);
4765                 break;
4766
4767             case SCSI_SBC2_READ12:
4768                 dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset, isreq,
4769                                      FALSE);
4770                 break;
4771
4772             case SCSI_SBC2_READ16:
4773                 dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset, isreq,
4774                                      FALSE);
4775                 break;
4776
4777             case SCSI_SBC2_READCAPACITY:
4778                 dissect_scsi_readcapacity (tvb, pinfo, scsi_tree, offset,
4779                                            isreq, FALSE);
4780                 break;
4781
4782             case SCSI_SBC2_READDEFDATA10:
4783                 dissect_scsi_readdefdata10 (tvb, pinfo, scsi_tree, offset,
4784                                             isreq, FALSE);
4785                 break;
4786
4787             case SCSI_SBC2_READDEFDATA12:
4788                 dissect_scsi_readdefdata12 (tvb, pinfo, scsi_tree, offset,
4789                                             isreq, FALSE);
4790                 break;
4791
4792             case SCSI_SBC2_REASSIGNBLKS:
4793                 dissect_scsi_reassignblks (tvb, pinfo, scsi_tree, offset,
4794                                            isreq, FALSE);
4795                 break;
4796
4797             case SCSI_SBC2_WRITE6:
4798                 dissect_scsi_sbc2_rdwr6 (tvb, pinfo, scsi_tree, offset, isreq,
4799                                     FALSE);
4800                 break;
4801
4802             case SCSI_SBC2_WRITE10:
4803                 dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset, isreq,
4804                                      FALSE);
4805                 break;
4806
4807             case SCSI_SBC2_WRITE12:
4808                 dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset, isreq,
4809                                      FALSE);
4810                 break;
4811
4812             case SCSI_SBC2_WRITE16:
4813                 dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset, isreq,
4814                                      FALSE);
4815                 break;
4816
4817             default:
4818                 call_dissector (data_handle, tvb, pinfo, scsi_tree);
4819                 break;
4820             }
4821             break;
4822
4823         case SCSI_CMND_SSC2:
4824             switch (opcode) {
4825
4826             case SCSI_SSC2_READ6:
4827                 dissect_scsi_ssc2_read6 (tvb, pinfo, scsi_tree, offset, isreq,
4828                                     FALSE);
4829                 break;
4830
4831             case SCSI_SSC2_WRITE6:
4832                 dissect_scsi_ssc2_write6 (tvb, pinfo, scsi_tree, offset, isreq,
4833                                 FALSE);
4834                 break;
4835
4836             case SCSI_SSC2_WRITE_FILEMARKS_6:
4837                 dissect_scsi_ssc2_writefilemarks6 (tvb, pinfo, scsi_tree, offset, isreq,
4838                                 FALSE);
4839                 break;
4840
4841             case SCSI_SSC2_LOAD_UNLOAD:
4842                 dissect_scsi_ssc2_loadunload (tvb, pinfo, scsi_tree, offset, isreq,
4843                                 FALSE);
4844                 break;
4845
4846             case SCSI_SSC2_READ_BLOCK_LIMITS:
4847                 dissect_scsi_ssc2_readblocklimits (tvb, pinfo, scsi_tree, offset, isreq,
4848                                 FALSE);
4849                 break;
4850
4851             case SCSI_SSC2_READ_POSITION:
4852                 dissect_scsi_ssc2_readposition (tvb, pinfo, scsi_tree, offset, isreq,
4853                                 FALSE, cdata);
4854                 break;
4855
4856             case SCSI_SSC2_REWIND:
4857                 dissect_scsi_ssc2_rewind (tvb, pinfo, scsi_tree, offset, isreq,
4858                                 FALSE);
4859                 break;
4860
4861             default:
4862                 call_dissector (data_handle, tvb, pinfo, scsi_tree);
4863                 break;
4864             }
4865             break;
4866
4867         case SCSI_CMND_SMC2:
4868             switch (opcode) {
4869
4870             case SCSI_SMC2_MOVE_MEDIUM:
4871             case SCSI_SMC2_MOVE_MEDIUM_ATTACHED:
4872                 dissect_scsi_smc2_movemedium (tvb, pinfo, scsi_tree, offset, isreq,
4873                                 FALSE);
4874                 break;
4875
4876             case SCSI_SMC2_READ_ELEMENT_STATUS:
4877             case SCSI_SMC2_READ_ELEMENT_STATUS_ATTACHED:
4878                 dissect_scsi_smc2_readelementstatus (tvb, pinfo, scsi_tree, offset, isreq,
4879                                 FALSE);
4880                 break;
4881
4882             default:
4883                 call_dissector (data_handle, tvb, pinfo, scsi_tree);
4884                 break;
4885             }
4886             break;
4887
4888         default:
4889             call_dissector (data_handle, tvb, pinfo, scsi_tree);
4890             break;
4891         }
4892     }
4893 }
4894
4895 void
4896 proto_register_scsi (void)
4897 {
4898     /* Setup list of header fields  See Section 1.6.1 for details*/
4899     static hf_register_info hf[] = {
4900         { &hf_scsi_spcopcode,
4901           {"SPC-2 Opcode", "scsi.spc.opcode", FT_UINT8, BASE_HEX,
4902            VALS (scsi_spc2_val), 0x0, "", HFILL}},
4903         { &hf_scsi_sbcopcode,
4904           {"SBC-2 Opcode", "scsi.sbc.opcode", FT_UINT8, BASE_HEX,
4905            VALS (scsi_sbc2_val), 0x0, "", HFILL}},
4906         { &hf_scsi_sscopcode,
4907           {"SSC-2 Opcode", "scsi.ssc.opcode", FT_UINT8, BASE_HEX,
4908            VALS (scsi_ssc2_val), 0x0, "", HFILL}},
4909         { &hf_scsi_smcopcode,
4910           {"SMC-2 Opcode", "scsi.smc.opcode", FT_UINT8, BASE_HEX,
4911            VALS (scsi_smc2_val), 0x0, "", HFILL}},
4912         { &hf_scsi_control,
4913           {"Control", "scsi.cdb.control", FT_UINT8, BASE_HEX, NULL, 0x0, "",
4914            HFILL}},
4915         { &hf_scsi_inquiry_flags,
4916           {"Flags", "scsi.inquiry.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
4917            HFILL}},
4918         { &hf_scsi_inquiry_evpd_page,
4919           {"EVPD Page Code", "scsi.inquiry.evpd.pagecode", FT_UINT8, BASE_HEX,
4920            VALS (scsi_evpd_pagecode_val), 0x0, "", HFILL}},
4921         { &hf_scsi_inquiry_cmdt_page,
4922           {"CMDT Page Code", "scsi.inquiry.cmdt.pagecode", FT_UINT8, BASE_HEX,
4923            NULL, 0x0, "", HFILL}},
4924         { &hf_scsi_alloclen,
4925           {"Allocation Length", "scsi.cdb.alloclen", FT_UINT8, BASE_DEC, NULL,
4926            0x0, "", HFILL}},
4927         { &hf_scsi_logsel_flags,
4928           {"Flags", "scsi.logsel.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
4929            HFILL}},
4930         { &hf_scsi_logsel_pc,
4931           {"Page Control", "scsi.logsel.pc", FT_UINT8, BASE_DEC,
4932            VALS (scsi_logsel_pc_val), 0xC0, "", HFILL}},
4933         { &hf_scsi_paramlen,
4934           {"Parameter Length", "scsi.cdb.paramlen", FT_UINT8, BASE_DEC, NULL,
4935            0x0, "", HFILL}},
4936         { &hf_scsi_logsns_flags,
4937           {"Flags", "scsi.logsns.flags", FT_UINT16, BASE_HEX, NULL, 0x0, "",
4938            HFILL}},
4939         { &hf_scsi_logsns_pc,
4940           {"Page Control", "scsi.logsns.pc", FT_UINT8, BASE_DEC,
4941            VALS (scsi_logsns_pc_val), 0xC0, "", HFILL}},
4942         { &hf_scsi_logsns_pagecode,
4943           {"Page Code", "scsi.logsns.pagecode", FT_UINT8, BASE_HEX,
4944            VALS (scsi_logsns_page_val), 0x3F0, "", HFILL}},
4945         { &hf_scsi_paramlen16,
4946           {"Parameter Length", "scsi.cdb.paramlen16", FT_UINT16, BASE_DEC, NULL,
4947            0x0, "", HFILL}},
4948         { &hf_scsi_modesel_flags,
4949           {"Mode Sense/Select Flags", "scsi.cdb.mode.flags", FT_UINT8, BASE_HEX,
4950            NULL, 0x0, "", HFILL}},
4951         { &hf_scsi_alloclen16,
4952           {"Allocation Length", "scsi.cdb.alloclen16", FT_UINT16, BASE_DEC,
4953            NULL, 0x0, "", HFILL}},
4954         { &hf_scsi_modesns_pc,
4955           {"Page Control", "scsi.mode.pc", FT_UINT8, BASE_DEC,
4956            VALS (scsi_modesns_pc_val), 0xC0, "", HFILL}},
4957         { &hf_scsi_spcpagecode,
4958           {"SPC-2 Page Code", "scsi.mode.spc.pagecode", FT_UINT8, BASE_HEX,
4959            VALS (scsi_spc2_modepage_val), 0x3F, "", HFILL}},
4960         { &hf_scsi_sbcpagecode,
4961           {"SBC-2 Page Code", "scsi.mode.sbc.pagecode", FT_UINT8, BASE_HEX,
4962            VALS (scsi_sbc2_modepage_val), 0x3F, "", HFILL}},
4963         { &hf_scsi_sscpagecode,
4964           {"SSC-2 Page Code", "scsi.mode.ssc.pagecode", FT_UINT8, BASE_HEX,
4965            VALS (scsi_ssc2_modepage_val), 0x3F, "", HFILL}},
4966         { &hf_scsi_smcpagecode,
4967           {"SMC-2 Page Code", "scsi.mode.smc.pagecode", FT_UINT8, BASE_HEX,
4968            VALS (scsi_smc2_modepage_val), 0x3F, "", HFILL}},
4969         { &hf_scsi_modesns_flags,
4970           {"Flags", "scsi.mode.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
4971            HFILL}},
4972         { &hf_scsi_persresvin_svcaction,
4973           {"Service Action", "scsi.persresvin.svcaction", FT_UINT8, BASE_HEX,
4974            VALS (scsi_persresvin_svcaction_val), 0x0F, "", HFILL}},
4975         { &hf_scsi_persresvout_svcaction,
4976           {"Service Action", "scsi.persresvout.svcaction", FT_UINT8, BASE_HEX,
4977            VALS (scsi_persresvout_svcaction_val), 0x0F, "", HFILL}},
4978         { &hf_scsi_persresv_scope,
4979           {"Reservation Scope", "scsi.persresv.scope", FT_UINT8, BASE_HEX,
4980            VALS (scsi_persresv_scope_val), 0xF0, "", HFILL}},
4981         { &hf_scsi_persresv_type,
4982           {"Reservation Type", "scsi.persresv.type", FT_UINT8, BASE_HEX,
4983            VALS (scsi_persresv_type_val), 0x0F, "", HFILL}},
4984         { &hf_scsi_release_flags,
4985           {"Release Flags", "scsi.release.flags", FT_UINT8, BASE_HEX, NULL,
4986            0x0, "", HFILL}},
4987         { &hf_scsi_release_thirdpartyid,
4988           {"Third-Party ID", "scsi.release.thirdpartyid", FT_BYTES, BASE_HEX,
4989            NULL, 0x0, "", HFILL}},
4990         { &hf_scsi_alloclen32,
4991           {"Allocation Length", "scsi.cdb.alloclen32", FT_UINT32, BASE_DEC,
4992            NULL, 0x0, "", HFILL}},
4993         { &hf_scsi_formatunit_flags,
4994           {"Flags", "scsi.formatunit.flags", FT_UINT8, BASE_HEX, NULL, 0xF8,
4995            "", HFILL}},
4996         { &hf_scsi_cdb_defectfmt,
4997           {"Defect List Format", "scsi.cdb.defectfmt", FT_UINT8, BASE_DEC,
4998            NULL, 0x7, "", HFILL}},
4999         { &hf_scsi_formatunit_interleave,
5000           {"Interleave", "scsi.formatunit.interleave", FT_UINT16, BASE_HEX,
5001            NULL, 0x0, "", HFILL}},
5002         { &hf_scsi_formatunit_vendor,
5003           {"Vendor Unique", "scsi.formatunit.vendor", FT_UINT8, BASE_HEX, NULL,
5004            0x0, "", HFILL}},
5005         { &hf_scsi_rdwr6_lba,
5006           {"Logical Block Address (LBA)", "scsi.rdwr6.lba", FT_UINT24, BASE_DEC,
5007            NULL, 0x0FFFFF, "", HFILL}},
5008         { &hf_scsi_rdwr6_xferlen,
5009           {"Transfer Length", "scsi.rdwr6.xferlen", FT_UINT24, BASE_DEC, NULL, 0x0,
5010            "", HFILL}},
5011         { &hf_scsi_rdwr10_lba,
5012           {"Logical Block Address (LBA)", "scsi.rdwr10.lba", FT_UINT32, BASE_DEC,
5013            NULL, 0x0, "", HFILL}},
5014         { &hf_scsi_rdwr10_xferlen,
5015           {"Transfer Length", "scsi.rdwr10.xferlen", FT_UINT16, BASE_DEC, NULL,
5016            0x0, "", HFILL}},
5017         { &hf_scsi_read_flags,
5018           {"Flags", "scsi.read.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
5019            HFILL}},
5020         { &hf_scsi_rdwr12_xferlen,
5021           {"Transfer Length", "scsi.rdwr12.xferlen", FT_UINT32, BASE_DEC, NULL,
5022            0x0, "", HFILL}},
5023         { &hf_scsi_rdwr16_lba,
5024           {"Logical Block Address (LBA)", "scsi.rdwr16.lba", FT_BYTES, BASE_DEC,
5025            NULL, 0x0, "", HFILL}},
5026         { &hf_scsi_readcapacity_flags,
5027           {"Flags", "scsi.readcapacity.flags", FT_UINT8, BASE_HEX, NULL, 0x0,
5028            "", HFILL}},
5029         { &hf_scsi_readcapacity_lba,
5030           {"Logical Block Address", "scsi.readcapacity.lba", FT_UINT32, BASE_DEC,
5031            NULL, 0x0, "", HFILL}},
5032         { &hf_scsi_readcapacity_pmi,
5033           {"PMI", "scsi.readcapacity.pmi", FT_UINT8, BASE_DEC, NULL, 0x1, "",
5034            HFILL}},
5035         { &hf_scsi_readdefdata_flags,
5036           {"Flags", "scsi.readdefdata.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
5037            HFILL}},
5038         { &hf_scsi_reassignblks_flags,
5039           {"Flags", "scsi.reassignblks.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
5040            HFILL}},
5041         { &hf_scsi_inq_qualifier,
5042           {"Peripheral Qualifier", "scsi.inquiry.qualifier", FT_UINT8, BASE_HEX,
5043            VALS (scsi_qualifier_val), 0xE0, "", HFILL}},
5044         { &hf_scsi_inq_devtype,
5045           {"Peripheral Device Type", "scsi.inquiry.devtype", FT_UINT8, BASE_HEX,
5046            VALS (scsi_devtype_val), SCSI_DEV_BITS, "", HFILL}},
5047         { & hf_scsi_inq_version,
5048           {"Version", "scsi.inquiry.version", FT_UINT8, BASE_HEX,
5049            VALS (scsi_inquiry_vers_val), 0x0, "", HFILL}},
5050         { &hf_scsi_inq_normaca,
5051           {"NormACA", "scsi.inquiry.normaca", FT_UINT8, BASE_HEX, NULL, 0x20,
5052            "", HFILL}},
5053         { &hf_scsi_rluns_lun,
5054           {"LUN", "scsi.reportluns.lun", FT_UINT8, BASE_DEC, NULL, 0x0, "",
5055            HFILL}},
5056         { &hf_scsi_rluns_multilun,
5057           {"Multi-level LUN", "scsi.reportluns.mlun", FT_BYTES, BASE_HEX, NULL,
5058            0x0, "", HFILL}},
5059         { &hf_scsi_modesns_errrep,
5060           {"MRIE", "scsi.mode.mrie", FT_UINT8, BASE_HEX,
5061            VALS (scsi_modesns_mrie_val), 0x0F, "", HFILL}},
5062         { &hf_scsi_modesns_tst,
5063           {"Task Set Type", "scsi.mode.tst", FT_UINT8, BASE_DEC,
5064            VALS (scsi_modesns_tst_val), 0xE0, "", HFILL}},
5065         { &hf_scsi_modesns_qmod,
5066           {"Queue Algorithm Modifier", "scsi.mode.qmod", FT_UINT8, BASE_HEX,
5067            VALS (scsi_modesns_qmod_val), 0xF0, "", HFILL}},
5068         { &hf_scsi_modesns_qerr,
5069           {"Queue Error Management", "scsi.mode.qerr", FT_BOOLEAN, BASE_HEX,
5070            TFS (&scsi_modesns_qerr_val), 0x2, "", HFILL}},
5071         { &hf_scsi_modesns_tas,
5072           {"Task Aborted Status", "scsi.mode.tac", FT_BOOLEAN, BASE_HEX,
5073            TFS (&scsi_modesns_tas_val), 0x80, "", HFILL}},
5074         { &hf_scsi_modesns_rac,
5075           {"Report a Check", "ssci.mode.rac", FT_BOOLEAN, BASE_HEX,
5076            TFS (&scsi_modesns_rac_val), 0x40, "", HFILL}},
5077         { &hf_scsi_protocol,
5078           {"Protocol", "scsi.proto", FT_UINT8, BASE_DEC, VALS (scsi_proto_val),
5079            0x0F, "", HFILL}},
5080         { &hf_scsi_sns_errtype,
5081           {"SNS Error Type", "scsi.sns.errtype", FT_UINT8, BASE_HEX,
5082            VALS (scsi_sns_errtype_val), 0x7F, "", HFILL}},
5083         { &hf_scsi_snskey,
5084           {"Sense Key", "scsi.sns.key", FT_UINT8, BASE_HEX,
5085            VALS (scsi_sensekey_val), 0x0F, "", HFILL}},
5086         { &hf_scsi_snsinfo,
5087           {"Sense Info", "scsi.sns.info", FT_UINT32, BASE_HEX, NULL, 0x0, "",
5088            HFILL}},
5089         { &hf_scsi_addlsnslen,
5090           {"Additional Sense Length", "scsi.sns.addlen", FT_UINT8, BASE_DEC,
5091            NULL, 0x0, "", HFILL}},
5092         { &hf_scsi_asc,
5093           {"Additional Sense Code", "scsi.sns.asc", FT_UINT8, BASE_HEX, NULL,
5094            0x0, "", HFILL}},
5095         { &hf_scsi_ascq,
5096           {"Additional Sense Code Qualifier", "scsi.sns.ascq", FT_UINT8,
5097            BASE_HEX, NULL, 0x0, "", HFILL}},
5098         { &hf_scsi_ascascq,
5099           {"Additional Sense Code+Qualifier", "scsi.sns.ascascq", FT_UINT16,
5100            BASE_HEX, VALS (scsi_asc_val), 0x0, "", HFILL}},
5101         { &hf_scsi_fru,
5102           {"Field Replaceable Unit Code", "scsi.sns.fru", FT_UINT8, BASE_HEX,
5103            NULL, 0x0, "", HFILL}},
5104         { &hf_scsi_sksv,
5105           {"SKSV", "scsi.sns.sksv", FT_BOOLEAN, BASE_HEX, NULL, 0x80, "",
5106            HFILL}},
5107         { &hf_scsi_persresv_key,
5108           {"Reservation Key", "scsi.spc2.resv.key", FT_BYTES, BASE_HEX, NULL,
5109            0x0, "", HFILL}},
5110         { &hf_scsi_persresv_scopeaddr,
5111           {"Scope Address", "scsi.spc2.resv.scopeaddr", FT_BYTES, BASE_HEX, NULL,
5112            0x0, "", HFILL}},
5113         { &hf_scsi_add_cdblen,
5114           {"Additional CDB Length", "scsi.spc2.addcdblen", FT_UINT8, BASE_DEC,
5115            NULL, 0x0, "", HFILL}},
5116         { &hf_scsi_svcaction,
5117           {"Service Action", "scsi.spc2.svcaction", FT_UINT16, BASE_HEX, NULL,
5118            0x0, "", HFILL}},
5119     };
5120
5121     /* Setup protocol subtree array */
5122     static gint *ett[] = {
5123         &ett_scsi,
5124         &ett_scsi_page,
5125     };
5126     module_t *scsi_module;
5127
5128     /* Register the protocol name and description */
5129     proto_scsi = proto_register_protocol("SCSI", "SCSI", "scsi");
5130
5131     /* Required function calls to register the header fields and subtrees used */
5132     proto_register_field_array(proto_scsi, hf, array_length(hf));
5133     proto_register_subtree_array(ett, array_length(ett));
5134     register_init_routine (&scsi_init_protocol);
5135     data_handle = find_dissector ("data");
5136
5137     /* add preferences to decode SCSI message */
5138     scsi_module = prefs_register_protocol (proto_scsi, NULL);
5139     prefs_register_enum_preference (scsi_module, "decode_scsi_messages_as",
5140                                     "Decode SCSI Messages As",
5141                                     "When Target Cannot Be Identified, Decode SCSI Messages As",
5142                                     &scsi_def_devtype, scsi_devtype_options, TRUE);
5143 }