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