Get rid of an unused variable.
[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.9 2002/04/14 23:04:04 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 #ifdef HAVE_SYS_TYPES_H
83 # include <sys/types.h>
84 #endif
85
86 #include <glib.h>
87 #include <string.h>
88 #include <epan/strutil.h>
89 #include <epan/conversation.h>
90 #include "prefs.h"
91 #include "packet-scsi.h"
92
93 static int proto_scsi                    = -1;
94 static int hf_scsi_spcopcode             = -1;
95 static int hf_scsi_sbcopcode             = -1;
96 static int hf_scsi_control               = -1;
97 static int hf_scsi_inquiry_flags         = -1;
98 static int hf_scsi_inquiry_evpd_page     = -1;
99 static int hf_scsi_inquiry_cmdt_page     = -1;
100 static int hf_scsi_alloclen              = -1;
101 static int hf_scsi_logsel_flags          = -1;
102 static int hf_scsi_log_pc                = -1;
103 static int hf_scsi_paramlen              = -1;
104 static int hf_scsi_logsns_flags          = -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_modesns_pagecode      = -1;
111 static int hf_scsi_modesns_flags         = -1;
112 static int hf_scsi_persresvin_svcaction  = -1;
113 static int hf_scsi_persresvout_svcaction = -1;
114 static int hf_scsi_persresv_scope        = -1;
115 static int hf_scsi_persresv_type         = -1;
116 static int hf_scsi_release_flags         = -1;
117 static int hf_scsi_release_thirdpartyid  = -1;
118 static int hf_scsi_alloclen32            = -1;
119 static int hf_scsi_formatunit_flags      = -1;
120 static int hf_scsi_formatunit_interleave = -1;
121 static int hf_scsi_formatunit_vendor     = -1;
122 static int hf_scsi_rdwr6_lba             = -1;
123 static int hf_scsi_rdwr6_xferlen         = -1;
124 static int hf_scsi_rdwr10_lba            = -1;
125 static int hf_scsi_read_flags            = -1;
126 static int hf_scsi_rdwr12_xferlen        = -1;
127 static int hf_scsi_rdwr16_lba            = -1;
128 static int hf_scsi_readcapacity_flags    = -1;
129 static int hf_scsi_readcapacity_lba      = -1;
130 static int hf_scsi_readcapacity_pmi      = -1;
131 static int hf_scsi_rdwr10_xferlen        = -1;
132 static int hf_scsi_readdefdata_flags     = -1;
133 static int hf_scsi_cdb_defectfmt         = -1;
134 static int hf_scsi_reassignblks_flags    = -1;
135 static int hf_scsi_inq_devtype           = -1;
136 static int hf_scsi_inq_version           = -1;
137 static int hf_scsi_rluns_lun             = -1;
138 static int hf_scsi_rluns_multilun        = -1;
139 static int hf_scsi_modesns_errrep        = -1;
140 static int hf_scsi_modesns_tst           = -1;
141 static int hf_scsi_modesns_qmod          = -1;
142 static int hf_scsi_modesns_qerr          = -1;
143 static int hf_scsi_modesns_rac           = -1;
144 static int hf_scsi_modesns_tas           = -1;
145 static int hf_scsi_protocol              = -1;
146 static int hf_scsi_sns_errtype           = -1;
147 static int hf_scsi_snskey                = -1;
148 static int hf_scsi_snsinfo               = -1;
149 static int hf_scsi_addlsnslen            = -1;
150 static int hf_scsi_asc                   = -1;
151 static int hf_scsi_ascascq               = -1;
152 static int hf_scsi_ascq                  = -1;
153 static int hf_scsi_fru                   = -1;
154 static int hf_scsi_sksv                  = -1;
155 static int hf_scsi_inq_normaca           = -1;
156 static int hf_scsi_persresv_key          = -1;
157 static int hf_scsi_persresv_scopeaddr    = -1;
158 static int hf_scsi_sscopcode             = -1;
159 static int hf_scsi_add_cdblen = -1;
160 static int hf_scsi_svcaction = -1;
161
162
163 static gint ett_scsi         = -1;
164 static gint ett_scsi_page    = -1;
165
166 typedef guint32 scsi_cmnd_type;
167 typedef guint32 scsi_device_type;
168
169 /* Valid SCSI Device Types */
170 #define SCSI_CMND_SPC2                   1
171 #define SCSI_CMND_SBC2                   2
172 #define SCSI_CMND_SSC2                   3
173
174 /* SPC-2 Commands */
175
176 #define SCSI_SPC2_INQUIRY                0x12
177 #define SCSI_SPC2_EXTCOPY                0x83
178 #define SCSI_SPC2_LOGSELECT              0x4C
179 #define SCSI_SPC2_LOGSENSE               0x4D
180 #define SCSI_SPC2_MODESELECT6            0x15
181 #define SCSI_SPC2_MODESELECT10           0x55
182 #define SCSI_SPC2_MODESENSE6             0x1A
183 #define SCSI_SPC2_MODESENSE10            0x5A
184 #define SCSI_SPC2_PERSRESVIN             0x5E
185 #define SCSI_SPC2_PERSRESVOUT            0x5F
186 #define SCSI_SPC2_PREVMEDREMOVAL         0x1E
187 #define SCSI_SPC2_READBUFFER             0x3C
188 #define SCSI_SPC2_RCVCOPYRESULTS         0x84
189 #define SCSI_SPC2_RCVDIAGRESULTS         0x1C
190 #define SCSI_SPC2_RELEASE6               0x17
191 #define SCSI_SPC2_RELEASE10              0x57
192 #define SCSI_SPC2_REPORTDEVICEID         0xA3
193 #define SCSI_SPC2_REPORTLUNS             0xA0
194 #define SCSI_SPC2_REQSENSE               0x03 
195 #define SCSI_SPC2_RESERVE6               0x16 
196 #define SCSI_SPC2_RESERVE10              0x56
197 #define SCSI_SPC2_SENDDIAG               0x1D
198 #define SCSI_SPC2_SETDEVICEID            0xA4
199 #define SCSI_SPC2_TESTUNITRDY            0x00
200 #define SCSI_SPC2_WRITEBUFFER            0x3B
201 #define SCSI_SPC2_VARLENCDB              0x7F
202
203 static const value_string scsi_spc2_val[] = {
204     {SCSI_SPC2_EXTCOPY           , "Extended Copy"},
205     {SCSI_SPC2_INQUIRY           , "Inquiry"},
206     {SCSI_SPC2_LOGSELECT         , "Log Select"},
207     {SCSI_SPC2_LOGSENSE          , "Log Sense"},
208     {SCSI_SPC2_MODESELECT6       , "Mode Select (6)"},
209     {SCSI_SPC2_MODESELECT10      , "Mode Select (10)"},
210     {SCSI_SPC2_MODESENSE6        , "Mode Sense (6)"},
211     {SCSI_SPC2_MODESENSE10       , "Mode Sense (10)"},
212     {SCSI_SPC2_PERSRESVIN        , "Persistent Reserve In"},
213     {SCSI_SPC2_PERSRESVOUT       , "Persistent Reserve Out"},
214     {SCSI_SPC2_PREVMEDREMOVAL    , "Prevent/Allow Medium Removal"},
215     {SCSI_SPC2_RCVCOPYRESULTS    , "Receive Copy Results"},
216     {SCSI_SPC2_RCVDIAGRESULTS    , "Receive Diagnostics Results"},
217     {SCSI_SPC2_READBUFFER        , "Read Buffer"},
218     {SCSI_SPC2_RELEASE6          , "Release (6)"},
219     {SCSI_SPC2_RELEASE10         , "Release (10)"},
220     {SCSI_SPC2_REPORTDEVICEID    , "Report Device ID"},
221     {SCSI_SPC2_REPORTLUNS        , "Report LUNs"},
222     {SCSI_SPC2_REQSENSE          , "Request Sense"},
223     {SCSI_SPC2_RESERVE6          , "Reserve (6)"},
224     {SCSI_SPC2_RESERVE10         , "Reserve (10)"},
225     {SCSI_SPC2_TESTUNITRDY       , "Test Unit Ready"},
226     {SCSI_SPC2_WRITEBUFFER       , "Write Buffer"},
227     {SCSI_SPC2_VARLENCDB         , "Variable Length CDB"},
228     {0, NULL},
229 };
230
231 /* SBC-2 Commands */
232 #define SCSI_SBC2_FORMATUNIT             0x04
233 #define SCSI_SBC2_LOCKUNLKCACHE10        0x36
234 #define SCSI_SPC2_LOCKUNLKCACHE16        0x92
235 #define SCSI_SBC2_PREFETCH10             0x34
236 #define SCSI_SBC2_PREFETCH16             0x90
237 #define SCSI_SBC2_READ6                  0x08
238 #define SCSI_SBC2_READ10                 0x28
239 #define SCSI_SBC2_READ12                 0xA8
240 #define SCSI_SBC2_READ16                 0x88
241 #define SCSI_SBC2_READCAPACITY           0x25
242 #define SCSI_SBC2_READDEFDATA10          0x37
243 #define SCSI_SBC2_READDEFDATA12          0xB7
244 #define SCSI_SBC2_READLONG               0x3E
245 #define SCSI_SBC2_REASSIGNBLKS           0x07
246 #define SCSI_SBC2_REBUILD16              0x81
247 #define SCSI_SBC2_REBUILD32              0x7F
248 #define SCSI_SBC2_REGENERATE16           0x82
249 #define SCSI_SBC2_REGENERATE32           0x7F
250 #define SCSI_SBC2_SEEK10                 0x2B
251 #define SCSI_SBC2_SETLIMITS10            0x33
252 #define SCSI_SBC2_SETLIMITS12            0xB3
253 #define SCSI_SBC2_STARTSTOPUNIT          0x1B
254 #define SCSI_SBC2_SYNCCACHE10            0x35
255 #define SCSI_SBC2_SYNCCACHE16            0x91
256 #define SCSI_SBC2_VERIFY10               0x2F
257 #define SCSI_SBC2_VERIFY12               0xAF
258 #define SCSI_SBC2_VERIFY16               0x8F
259 #define SCSI_SBC2_WRITE6                 0x0A
260 #define SCSI_SBC2_WRITE10                0x2A
261 #define SCSI_SBC2_WRITE12                0xAA
262 #define SCSI_SBC2_WRITE16                0x8A
263 #define SCSI_SBC2_WRITENVERIFY10         0x2E
264 #define SCSI_SBC2_WRITENVERIFY12         0xAE
265 #define SCSI_SBC2_WRITENVERIFY16         0x8E
266 #define SCSI_SBC2_WRITELONG              0x3F
267 #define SCSI_SBC2_WRITESAME10            0x41
268 #define SCSI_SBC2_WRITESAME16            0x93
269 #define SCSI_SBC2_XDREAD10               0x52
270 #define SCSI_SBC2_XDREAD32               0x7F
271 #define SCSI_SBC2_XDWRITE10              0x50
272 #define SCSI_SBC2_XDWRITE32              0x7F
273 #define SCSI_SBC2_XDWRITEREAD10          0x53
274 #define SCSI_SBC2_XDWRITEREAD32          0x7F
275 #define SCSI_SBC2_XDWRITEEXTD16          0x80
276 #define SCSI_SBC2_XDWRITEEXTD32          0x7F
277 #define SCSI_SBC2_XPWRITE10              0x51
278 #define SCSI_SBC2_XPWRITE32              0x7F
279
280
281 static const value_string scsi_sbc2_val[] = {
282     {SCSI_SBC2_FORMATUNIT    , "Format Unit"},
283     {SCSI_SBC2_LOCKUNLKCACHE10, "Lock Unlock Cache (10)"},
284     {SCSI_SPC2_LOCKUNLKCACHE16, "Lock Unlock Cache (16)"},
285     {SCSI_SBC2_PREFETCH10, "Pre-Fetch (10)"},
286     {SCSI_SBC2_PREFETCH16, "Pre-Fetch (16)"},
287     {SCSI_SBC2_READ6         , "Read (6)"},
288     {SCSI_SBC2_READ10        , "Read (10)"},
289     {SCSI_SBC2_READ12        , "Read (12)"},
290     {SCSI_SBC2_READ16        , "Read (16)"},
291     {SCSI_SBC2_READCAPACITY  , "Read Capacity"},
292     {SCSI_SBC2_READDEFDATA10 , "Read Defect Data (10)"},
293     {SCSI_SBC2_READDEFDATA12 , "Read Defect Data (12)"},
294     {SCSI_SBC2_READLONG, "Read Long"},
295     {SCSI_SBC2_REASSIGNBLKS  , "Reassign Blocks"},
296     {SCSI_SBC2_REBUILD16, "Rebuild (16)"},
297     {SCSI_SBC2_REBUILD32, "Rebuild (32)"},
298     {SCSI_SBC2_REGENERATE16, "Regenerate (16)"},
299     {SCSI_SBC2_REGENERATE32, "Regenerate (32)"},
300     {SCSI_SBC2_SEEK10, "Seek (10)"},
301     {SCSI_SBC2_SETLIMITS10, "Set Limits (10)"},
302     {SCSI_SBC2_SETLIMITS12, "Set Limits (12)"},
303     {SCSI_SBC2_STARTSTOPUNIT, "Start Stop Unit"},
304     {SCSI_SBC2_SYNCCACHE10, "Synchronize Cache (10)"},
305     {SCSI_SBC2_SYNCCACHE16, "Synchronize Cache (16)"},
306     {SCSI_SBC2_VERIFY10, "Verify (10)"},
307     {SCSI_SBC2_VERIFY12, "Verify (12)"},
308     {SCSI_SBC2_VERIFY16, "Verify (16)"},
309     {SCSI_SBC2_WRITE6        , "Write (6)"},
310     {SCSI_SBC2_WRITE10       , "Write (10)"},
311     {SCSI_SBC2_WRITE12       , "Write (12)"},
312     {SCSI_SBC2_WRITE16       , "Write (16)"},
313     {SCSI_SBC2_WRITENVERIFY10, "Write & Verify (10)"},
314     {SCSI_SBC2_WRITENVERIFY12, "Write & Verify (12)"},
315     {SCSI_SBC2_WRITENVERIFY16, "Write & Verify (16)"},
316     {SCSI_SBC2_WRITELONG, "Write Long"},
317     {SCSI_SBC2_WRITESAME10, "Write Same (10)"},
318     {SCSI_SBC2_WRITESAME16, "Write Same (16)"},
319     {SCSI_SBC2_XDREAD10, "XdRead (10)"},
320     {SCSI_SBC2_XDREAD32, "XdRead (32)"},
321     {SCSI_SBC2_XDWRITE10, "XdWrite (10)"},
322     {SCSI_SBC2_XDWRITE32, "XdWrite(32)"},
323     {SCSI_SBC2_XDWRITEREAD10, "XdWriteRead (10)"},
324     {SCSI_SBC2_XDWRITEREAD32, "XdWriteRead (32)"},
325     {SCSI_SBC2_XDWRITEEXTD16, "XdWrite Extended (16)"},
326     {SCSI_SBC2_XDWRITEEXTD32, "XdWrite Extended (32)"},
327     {SCSI_SBC2_XPWRITE10, "XpWrite (10)"},
328     {SCSI_SBC2_XPWRITE32, "XpWrite (32)"},
329     {0, NULL},
330 };
331
332 /* SSC2 Commands */
333 #define SCSI_SSC2_ERASE_16                      0x93
334 #define SCSI_SSC2_FORMAT_MEDIUM                 0x04
335 #define SCSI_SSC2_LOAD_UNLOAD                   0x1B
336 #define SCSI_SSC2_LOCATE_16                     0x92
337 #define SCSI_SSC2_MOVE_MEDIUM                   0xA5
338 #define SCSI_SSC2_MOVE_MEDIUM_ATTACHED          0xA7
339 #define SCSI_SSC2_READ_16                       0x88
340 #define SCSI_SSC2_READ_BLOCK_LIMITS             0x05
341 #define SCSI_SSC2_READ_ELEMENT_STATUS           0xB8
342 #define SCSI_SSC2_READ_ELEMENT_STATUS_ATTACHED  0xB4
343 #define SCSI_SSC2_READ_POSITION                 0x34
344 #define SCSI_SSC2_READ_REVERSE_16               0x81
345 #define SCSI_SSC2_RECOVER_BUFFERED_DATA         0x14
346 #define SCSI_SSC2_REPORT_DENSITY_SUPPORT        0x44
347 #define SCSI_SSC2_REWIND                        0x01
348 #define SCSI_SSC2_SET_CAPACITY                  0x0B
349 #define SCSI_SSC2_SPACE_16                      0x91
350 #define SCSI_SSC2_VERIFY_16                     0x8F
351 #define SCSI_SSC2_WRITE_16                      0x8A
352 #define SCSI_SSC2_WRITE_FILEMARKS_16            0x80
353 #define SCSI_SSC2_ERASE_6                       0x19
354 #define SCSI_SSC2_LOCATE_10                     0x2B
355 #define SCSI_SSC2_LOCATE_16                     0x92
356 #define SCSI_SSC2_READ_6                        0x08
357 #define SCSI_SSC2_READ_REVERSE_6                0x0F
358 #define SCSI_SSC2_SPACE_6                       0x11
359 #define SCSI_SSC2_VERIFY_6                      0x13
360 #define SCSI_SSC2_WRITE_6                       0x0A
361 #define SCSI_SSC2_WRITE_FILEMARKS_6             0x10
362
363 static const value_string scsi_ssc2_val[] = {
364     {SCSI_SSC2_ERASE_16                    , "Erase(16)"},
365     {SCSI_SSC2_FORMAT_MEDIUM               , "Format Medium"},
366     {SCSI_SSC2_LOAD_UNLOAD                 , "Load Unload"},
367     {SCSI_SSC2_LOCATE_16                   , "Locate(16)"},
368     {SCSI_SSC2_MOVE_MEDIUM                 , "Move Medium"},
369     {SCSI_SSC2_MOVE_MEDIUM_ATTACHED        , "Move Medium Attached"},
370     {SCSI_SSC2_READ_16                     , "Read(16)"},
371     {SCSI_SSC2_READ_BLOCK_LIMITS           , "Read Block Limits"},
372     {SCSI_SSC2_READ_ELEMENT_STATUS         , "Read Element Status"},
373     {SCSI_SSC2_READ_ELEMENT_STATUS_ATTACHED, "Read Element Status Attached"},
374     {SCSI_SSC2_READ_POSITION               , "Read Position"},
375     {SCSI_SSC2_READ_REVERSE_16             , "Read Reverse(16)"},
376     {SCSI_SSC2_RECOVER_BUFFERED_DATA       , "Recover Buffered Data"},
377     {SCSI_SSC2_REPORT_DENSITY_SUPPORT      , "Report Density Support"},
378     {SCSI_SSC2_REWIND                      , "Rewind"},
379     {SCSI_SSC2_SET_CAPACITY                , "Set Capacity"},
380     {SCSI_SSC2_SPACE_16                    , "Space(16)"},
381     {SCSI_SSC2_VERIFY_16                   , "Verify(16)"},
382     {SCSI_SSC2_WRITE_16                    , "Write(16)"},
383     {SCSI_SSC2_WRITE_FILEMARKS_16          , "Write Filemarks(16)"},
384     {SCSI_SSC2_ERASE_6                     , "Erase(6)"},
385     {SCSI_SSC2_LOCATE_10                   , "Locate(10)"},
386     {SCSI_SSC2_LOCATE_16                   , "Locate(16)"},
387     {SCSI_SSC2_READ_6                      , "Read(6)"},
388     {SCSI_SSC2_READ_REVERSE_6              , "Read Reverse(6)"},
389     {SCSI_SSC2_SPACE_6                     , "Space(6)"},
390     {SCSI_SSC2_VERIFY_6                    , "Verify(6)"},
391     {SCSI_SSC2_WRITE_6                     , "Write(6)"},
392     {SCSI_SSC2_WRITE_FILEMARKS_6           , "Write Filemarks(6)"},
393 };
394
395 static const value_string scsi_evpd_pagecode_val[] = {
396     {0x00, "Supported Vital Data Product Pages"},
397     {0x80, "Unit Serial Number Page"},
398     {0x82, "ASCII Implemented Operating Definition Page"},
399     {0x01, "ASCII Information Page"},
400     {0x02, "ASCII Information Page"},
401     {0x03, "ASCII Information Page"},
402     {0x04, "ASCII Information Page"},
403     {0x05, "ASCII Information Page"},
404     {0x06, "ASCII Information Page"},
405     {0x07, "ASCII Information Page"},
406     {0x83, "Device Identification Page"},
407     {0, NULL},
408 };
409
410 static const value_string scsi_logsel_pc_val[] = {
411     {0, "Current Threshold Values"},
412     {1, "Current Cumulative Values"},
413     {2, "Default Threshold Values"},
414     {3, "Default Cumulative Values"},
415     {0, NULL},
416 };
417
418 static const value_string scsi_logsns_pc_val[] = {
419     {0, "Threshold Values"},
420     {1, "Cumulative Values"},
421     {2, "Default Threshold Values"},
422     {3, "Default Cumulative Values"},
423     {0, NULL},
424 };
425
426 static const value_string scsi_logsns_page_val[] = {
427     {0xF, "Application Client Page"},
428     {0x1, "Buffer Overrun/Underrun Page"},
429     {0x3, "Error Counter (read) Page"},
430     {0x4, "Error Counter (read reverse) Page"},
431     {0x5, "Error Counter (verify) Page"},
432     {0x1, "Error Counter (write) Page"},
433     {0xB, "Last n Deferred Errors or Async Events Page"},
434     {0x7, "Last n Error Events Page"},
435     {0x6, "Non-medium Error Page"},
436     {0x10, "Self-test Results Page"},
437     {0xE, "Start-Stop Cycle Counter Page"},
438     {0x0, "Supported Log Pages"},
439     {0xD, "Temperature Page"},
440     {0, NULL},
441 };
442
443 static const value_string scsi_modesns_pc_val[] = {
444     {0, "Current Values"},
445     {1, "Changeable Values"},
446     {2, "Default Values"},
447     {3, "Saved Values"},
448     {0, NULL},
449 };
450
451 #define SCSI_MODEPAGE_VEND          0x0
452 #define SCSI_MODEPAGE_CTL           0x0A
453 #define SCSI_MODEPAGE_DISCON        0x02
454 #define SCSI_MODEPAGE_INFOEXCP      0x1C
455 #define SCSI_MODEPAGE_PWR           0x1A
456 #define SCSI_MODEPAGE_LUN           0x18
457 #define SCSI_MODEPAGE_PORT          0x19
458 #define SCSI_MODEPAGE_RDWRERR       0x01
459 #define SCSI_MODEPAGE_FMTDEV        0x03
460 #define SCSI_MODEPAGE_DISKGEOM      0x04
461 #define SCSI_MODEPAGE_FLEXDISK      0x05
462 #define SCSI_MODEPAGE_VERERR        0x07
463 #define SCSI_MODEPAGE_CACHE         0x08
464 #define SCSI_MODEPAGE_PERDEV        0x09
465 #define SCSI_MODEPAGE_MEDTYPE       0x0B
466 #define SCSI_MODEPAGE_NOTPART       0x0C
467 #define SCSI_MODEPAGE_XORCTL        0x10
468
469 static const value_string scsi_modesns_page_val[] = {
470     {0, "Vendor Specific Page"},
471     {0x0A, "Control"},
472     {0x02, "Disconnect-Reconnect"},
473     {0x1C, "Informational Exceptions Control"},
474     {0x1A, "Power Condition"},
475     {0x18, "Protocol Specific LUN"},
476     {0x19, "Protocol-Specific Port"},
477     {0x01, "Read/Write Error Recovery"},
478     {0x03, "Format Device"},
479     {0x04, "Rigid Disk Geometry"},
480     {0x05, "Flexible Disk"},
481     {0x07, "Verify Error Recovery"},
482     {0x08, "Caching"},
483     {0x09, "Peripheral Device"},
484     {0x0B, "Medium Types Supported"},
485     {0x0C, "Notch & Partition"},
486     {0x10, "XOR Control"},
487     {0x3F, "Return All Mode Pages"},
488     {0, NULL},
489 };
490
491 #define SCSI_SPC2_RESVIN_SVCA_RDKEYS 0
492 #define SCSI_SPC2_RESVIN_SVCA_RDRESV 1
493
494 static const value_string scsi_persresvin_svcaction_val[] = {
495     {SCSI_SPC2_RESVIN_SVCA_RDKEYS, "Read Keys"},
496     {SCSI_SPC2_RESVIN_SVCA_RDRESV, "Read Reservation"},
497     {0, NULL},
498 };
499
500 static const value_string scsi_persresvout_svcaction_val[] = {
501     {0, "Register"},
502     {1, "Reserve"},
503     {2, "Release"},
504     {3, "Clear"},
505     {4, "Preempt"},
506     {5, "Preempt & Abort"},
507     {6, "Register & Ignore Existing Key"},
508     {0, NULL},
509 };
510
511 static const value_string scsi_persresv_scope_val[] = {
512     {0, "LU Scope"},
513     {1, "Obsolete"},
514     {2, "Element Scope"},
515     {0, NULL},
516 };
517
518 static const value_string scsi_persresv_type_val[] = {
519     {1, "Write Excl"},
520     {3, "Excl Access"},
521     {5, "Write Excl, Registrants Only"},
522     {7, "Excl Access, Registrants Only"},
523     {0, NULL},
524 };
525
526 /* SCSI Device Types */
527 #define SCSI_DEV_SBC       0x0
528 #define SCSI_DEV_SSC       0x1
529 #define SCSI_DEV_PRNT      0x2
530 #define SCSI_DEV_PROC      0x3
531 #define SCSI_DEV_WORM      0x4
532 #define SCSI_DEV_CDROM     0x5
533 #define SCSI_DEV_SCAN      0x6
534 #define SCSI_DEV_OPTMEM    0x7
535 #define SCSI_DEV_SMC       0x8
536 #define SCSI_DEV_COMM      0x9
537 #define SCSI_DEV_RAID      0xC
538 #define SCSI_DEV_SES       0xD
539 #define SCSI_DEV_RBC       0xE
540 #define SCSI_DEV_OCRW      0xF
541 #define SCSI_DEV_OSD       0x11
542
543 static const value_string scsi_devtype_val[] = {
544     {SCSI_DEV_SBC   , "Direct Access Device"},
545     {SCSI_DEV_SSC   , "Sequential Access Device"},
546     {SCSI_DEV_PRNT  , "Printer"},
547     {SCSI_DEV_PROC  , "Processor"},
548     {SCSI_DEV_WORM  , "WORM"},
549     {SCSI_DEV_CDROM , "CD ROM"},
550     {SCSI_DEV_SCAN  , "Scanner"},
551     {SCSI_DEV_OPTMEM, "Optical Memory"},
552     {SCSI_DEV_SMC   , "Medium Changer"},
553     {SCSI_DEV_COMM  , "Communication"},
554     {SCSI_DEV_RAID  , "Storage Array"},
555     {SCSI_DEV_SES   , "Enclosure Services"},
556     {SCSI_DEV_RBC   , "Simplified Block Device"},
557     {SCSI_DEV_OCRW  , "OCRW"},
558     {SCSI_DEV_OSD   , "OSD"},
559     {0, NULL},
560 };
561
562 static const enum_val_t scsi_devtype_options[] = {
563     {"Block Device", SCSI_DEV_SBC},
564     {"Sequential Device", SCSI_DEV_SSC},
565     {NULL, -1},
566 };
567
568 static const value_string scsi_inquiry_vers_val[] = {
569     {0, "No Compliance to any Standard"},
570     {2, "Compliance to ANSI X3.131:1994"},
571     {3, "Compliance to ANSI X3.301:1997"},
572     {4, "Compliance to SPC-2"},
573     {0x80, "Compliance to ISO/IEC 9316:1995"},
574     {0x82, "Compliance to ISO/IEC 9316:1995 and to ANSI X3.131:1994"},
575     {0x83, "Compliance to ISO/IEC 9316:1995 and to ANSI X3.301:1997"},
576     {0x84, "Compliance to ISO/IEC 9316:1995 and SPC-2"},
577     {0, NULL},
578 };
579
580 static const value_string scsi_modesense_medtype_val[] = {
581     {0, "Default"},
582     {1, "Flexible Disk, Single-sided"},
583     {2, "Flexible Disk, Double-sided"},
584     {0, NULL},
585 };
586
587 static const value_string scsi_verdesc_val[] = {
588     {0x0d40, "FC-AL (No Version)"},
589     {0x0d5c, "FC-AL ANSI X3.272:1996"},
590     {0x0d60, "FC-AL-2 (no version claimed)"},
591     {0x0d7c, "FC-AL-2 ANSI NCITS.332:1999"},
592     {0x0d61, "FC-AL-2 T11/1133 revision 7.0"},
593     {0x1320, "FC-FLA (no version claimed)"},
594     {0x133c, "FC-FLA ANSI NCITS TR-20:1998"},
595     {0x133b, "FC-FLA T11/1235 revision 7"},
596     {0x0da0, "FC-FS (no version claimed)"},
597     {0x0db7, "FC-FS T11/1331 revision 1.2"},
598     {0x08c0, "FCP (no version claimed)"},
599     {0x08dc, "FCP ANSI X3.269:1996"},
600     {0x08db, "FCP T10/0993 revision 12"},
601     {0x1340, "FC-PLDA (no version claimed)"},
602     {0x135c, "FC-PLDA ANSI NCITS TR-19:1998"},
603     {0x135b, "FC-PLDA T11/1162 revision 2.1"},
604     {0x0900, "FCP-2 (no version claimed)"},
605     {0x0901, "FCP-2 T10/1144 revision 4"},
606     {0x003c, "SAM ANSI X3.270:1996"},
607     {0x003b, "SAM T10/0994 revision 18"},
608     {0x0040, "SAM-2 (no version claimed)"},
609     {0x0020, "SAM (no version claimed)"},
610     {0x0180, "SBC (no version claimed)"},
611     {0x019c, "SBC ANSI NCITS.306:1998"},
612     {0x019b, "SBC T10/0996 revision 08c"},
613     {0x0320, "SBC-2 (no version claimed)"},
614     {0x01c0, "SES (no version claimed)"},
615     {0x01dc, "SES ANSI NCITS.305:1998"},
616     {0x01db, "SES T10/1212 revision 08b"},
617     {0x01de, "SES ANSI NCITS.305:1998 w/ Amendment ANSI NCITS.305/AM1:2000"},
618     {0x01dd, "SES T10/1212 revision 08b w/ Amendment ANSI NCITS.305/AM1:2000"},
619     {0x0120, "SPC (no version claimed)"},
620     {0x013c, "SPC ANSI X3.301:1997"},
621     {0x013b, "SPC T10/0995 revision 11a"},
622     {0x0260, "SPC-2 (no version claimed)"},
623     {0x0267, "SPC-2 T10/1236 revision 12"},
624     {0x0269, "SPC-2 T10/1236 revision 18"},
625     {0x0300, "SPC-3 (no version claimed)"},
626     {0x0960, "iSCSI (no version claimed)"},
627     {0x0d80, "FC-PH-3 (no version claimed)"},
628     {0x0d9c, "FC-PH-3 ANSI X3.303-1998"},
629     {0x0d20, "FC-PH (no version claimed)"},
630     {0, NULL},
631 };
632
633 #define SCSI_EVPD_SUPPPG          0
634 #define SCSI_EVPD_ASCIIOPER       0x82
635 #define SCSI_EVPD_DEVID           0x83
636 #define SCSI_EVPD_DEVSERNUM       0x80
637
638 static const value_string scsi_inq_evpd_val[] = {
639     {SCSI_EVPD_SUPPPG, "Supported Vital Product Data Page"},
640     {SCSI_EVPD_ASCIIOPER, "ASCII Implemented Operating Definition Page"},
641     {SCSI_EVPD_DEVID, "Device ID Page"},
642     {SCSI_EVPD_DEVSERNUM, "Unit Serial Number Page"},
643     {0x0, NULL},
644 };
645
646 /* Command Support Data "Support" field definitions */
647 static const value_string scsi_cmdt_supp_val[] = {
648     {0, "Data not currently available"},
649     {1, "SCSI Command not supported"},
650     {2, "Reserved"},
651     {3, "SCSI Command supported in conformance with a SCSI standard"},
652     {4, "Vendor Specific"},
653     {5, "SCSI Command supported in a vendor specific manner"},
654     {6, "Vendor Specific"},
655     {7, "Reserved"},
656     {0, NULL},
657 };
658
659 static const value_string scsi_devid_codeset_val[] = {
660     {0, "Reserved"},
661     {1, "Identifier field contains binary values"},
662     {2, "Identifier field contains ASCII graphic codes"},
663     {0, NULL},
664 };
665
666 static const value_string scsi_devid_assoc_val[] = {
667     {0, "Identifier is associated with addressed logical/physical device"},
668     {1, "Identifier is associated with the port that received the request"},
669     {0, NULL},
670 };
671
672 static const value_string scsi_devid_idtype_val[] = {
673     {0, "Vendor-specific ID (non-globally unique)"},
674     {1, "Vendor-ID + vendor-specific ID (globally unique)"},
675     {2, "EUI-64 ID"},
676     {3, "WWN"},
677     {4, "4-byte Binary Number/Reserved"},
678     {0, NULL},
679 };
680
681 static const value_string scsi_modesns_mrie_val[] = {
682     {0, "No Reporting of Informational Exception Condition"},
683     {1, "Asynchronous Error Reporting"},
684     {2, "Generate Unit Attention"},
685     {3, "Conditionally Generate Recovered Error"},
686     {4, "Unconditionally Generate Recovered Error"},
687     {5, "Generate No Sense"},
688     {6, "Only Report Informational Exception Condition on Request"},
689     {0, NULL},
690 };
691
692 static const value_string scsi_modesns_tst_val[] = {
693     {0, "Task Set Per LU For All Initiators"},
694     {1, "Task Set Per Initiator Per LU"},
695     {0, NULL},
696 };
697
698 static const value_string scsi_modesns_qmod_val[] = {
699     {0, "Restricted reordering"},
700     {1, "Unrestricted reordering"},
701     {0, NULL},
702 };
703
704 static const true_false_string scsi_modesns_qerr_val = {
705     "All blocked tasks shall be aborted on CHECK CONDITION",
706     "Blocked tasks shall resume after ACA/CA is cleared",
707 };
708
709 static const true_false_string scsi_modesns_tas_val = {
710     "Terminated tasks aborted without informing initiators",
711     "Tasks aborted by another initiator terminated with TASK ABORTED",
712 };
713
714 static const true_false_string scsi_modesns_rac_val = {
715     "Report a CHECK CONDITION Instead of Long Busy Condition",
716     "Long Busy Conditions Maybe Reported",
717 };
718
719 /* SCSI Transport Protocols */
720 #define SCSI_PROTO_FCP          0
721 #define SCSI_PROTO_iSCSI        5
722
723 static const value_string scsi_proto_val[] = {
724     {0, "FCP"},
725     {5, "iSCSI"},
726     {0, NULL},
727 };
728
729 static const value_string scsi_fcp_rrtov_val[] = {
730     {0, "No Timer Specified"},
731     {1, "0.001 secs"},
732     {3, "0.1 secs"},
733     {5, "10 secs"},
734     {0, NULL},
735 };
736
737 static const value_string scsi_sensekey_val[] = {
738     {0x0, "No Sense"},
739     {0x1, "Recovered Error"},
740     {0x2, "Not Ready"},
741     {0x3, "Medium Error"},
742     {0x4, "Hardware Error"},
743     {0x5, "Illegal Request"},
744     {0x6, "Unit Attention"},
745     {0x7, "Data Protection"},
746     {0x8, "Blank Check"},
747     {0x9, "Vendor Specific"},
748     {0xA, "Copy Aborted"},
749     {0xB, "Command Aborted"},
750     {0xC, "Obsolete Error Code"},
751     {0xD, "Overflow Command"},
752     {0xE, "Miscompare"},
753     {0xF, "Reserved"},
754     {0, NULL},
755 };
756
757 static const value_string scsi_sns_errtype_val[] = {
758     {0x70, "Current Error"},
759     {0x71, "Deferred Error"},
760     {0x7F, "Vendor Specific"},
761     {0, NULL},
762 };
763
764 static const value_string scsi_asc_val[] = {
765     {0x0000,  "No Additional Sense Information"},
766     {0x0006,  "I/O Process Terminated"},
767     {0x0016,  "Operation In Progress"},
768     {0x0017,  "Cleaning Requested"},
769     {0x0100,  "No Index/Sector Signal"},
770     {0x0200,  "No Seek Complete"},
771     {0x0300,  "Peripheral Device Write Fault"},
772     {0x0400,  "Logical Unit Not Ready, Cause Not Reportable"},
773     {0x0401,  "Logical Unit Is In Process Of Becoming Ready"},
774     {0x0402,  "Logical Unit Not Ready, Initializing Cmd. Required"},
775     {0x0403,  "Logical Unit Not Ready, Manual Intervention Required"},
776     {0x0404,  "Logical Unit Not Ready, Format In Progress"},
777     {0x0405,  "Logical Unit Not Ready, Rebuild In Progress"},
778     {0x0406,  "Logical Unit Not Ready, Recalculation In Progress"},
779     {0x0407,  "Logical Unit Not Ready, Operation In Progress"},
780     {0x0409,  "Logical Unit Not Ready, Self-Test In Progress"},
781     {0x0500,  "Logical Unit Does Not Respond To Selection"},
782     {0x0600,  "No Reference Position Found"},
783     {0x0700,  "Multiple Peripheral Devices Selected"},
784     {0x0800,  "Logical Unit Communication Failure"},
785     {0x0801,  "Logical Unit Communication Time-Out"},
786     {0x0802,  "Logical Unit Communication Parity Error"},
787     {0x0803,  "Logical Unit Communication Crc Error (Ultra-Dma/32)"},
788     {0x0804,  "Unreachable Copy Target"},
789     {0x0900,  "Track Following Error"},
790     {0x0904,  "Head Select Fault"},
791     {0x0A00,  "Error Log Overflow"},
792     {0x0B00,  "Warning"},
793     {0x0B01,  "Warning - Specified Temperature Exceeded"},
794     {0x0B02,  "Warning - Enclosure Degraded"},
795     {0x0C02,  "Write Error - Auto Reallocation Failed"},
796     {0x0C03,  "Write Error - Recommend Reassignment"},
797     {0x0C04,  "Compression Check Miscompare Error"},
798     {0x0C05,  "Data Expansion Occurred During Compression"},
799     {0x0C06,  "Block Not Compressible"},
800     {0x0D00,  "Error Detected By Third Party Temporary Initiator"},
801     {0x0D01,  "Third Party Device Failure"},
802     {0x0D02,  "Copy Target Device Not Reachable"},
803     {0x0D03,  "Incorrect Copy Target Device Type"},
804     {0x0D04,  "Copy Target Device Data Underrun"},
805     {0x0D05,  "Copy Target Device Data Overrun"},
806     {0x1000,  "Id Crc Or Ecc Error"},
807     {0x1100,  "Unrecovered Read Error"},
808     {0x1101,  "Read Retries Exhausted"},
809     {0x1102,  "Error Too Long To Correct"},
810     {0x1103,  "Multiple Read Errors"},
811     {0x1104,  "Unrecovered Read Error - Auto Reallocate Failed"},
812     {0x110A,  "Miscorrected Error"},
813     {0x110B,  "Unrecovered Read Error - Recommend Reassignment"},
814     {0x110C,  "Unrecovered Read Error - Recommend Rewrite The Data"},
815     {0x110D,  "De-Compression Crc Error"},
816     {0x110E,  "Cannot Decompress Using Declared Algorithm"},
817     {0x1200,  "Address Mark Not Found For Id Field"},
818     {0x1300,  "Address Mark Not Found For Data Field"},
819     {0x1400,  "Recorded Entity Not Found"},
820     {0x1401,  "Record Not Found"},
821     {0x1405,  "Record Not Found - Recommend Reassignment"},
822     {0x1406,  "Record Not Found - Data Auto-Reallocated"},
823     {0x1500,  "Random Positioning Error"},
824     {0x1501,  "Mechanical Positioning Error"},
825     {0x1502,  "Positioning Error Detected By Read Of Medium"},
826     {0x1600,  "Data Synchronization Mark Error"},
827     {0x1601,  "Data Sync Error - Data Rewritten"},
828     {0x1602,  "Data Sync Error - Recommend Rewrite"},
829     {0x1603,  "Data Sync Error - Data Auto-Reallocated"},
830     {0x1604,  "Data Sync Error - Recommend Reassignment"},
831     {0x1700,  "Recovered Data With No Error Correction Applied"},
832     {0x1701,  "Recovered Data With Retries"},
833     {0x1702,  "Recovered Data With Positive Head Offset"},
834     {0x1703,  "Recovered Data With Negative Head Offset"},
835     {0x1705,  "Recovered Data Using Previous Sector Id"},
836     {0x1706,  "Recovered Data Without Ecc - Data Auto-Reallocated"},
837     {0x1707,  "Recovered Data Without Ecc - Recommend Reassignment"},
838     {0x1708,  "Recovered Data Without Ecc - Recommend Rewrite"},
839     {0x1709,  "Recovered Data Without Ecc - Data Rewritten"},
840     {0x1800,  "Recovered Data With Error Correction Applied"},
841     {0x1801,  "Recovered Data With Error Corr. & Retries Applied"},
842     {0x1802,  "Recovered Data - Data Auto-Reallocated"},
843     {0x1805,  "Recovered Data - Recommend Reassignment"},
844     {0x1806,  "Recovered Data - Recommend Rewrite"},
845     {0x1807,  "Recovered Data With Ecc - Data Rewritten"},
846     {0x1900,  "List Error"},
847     {0x1901,  "List Not Available"},
848     {0x1902,  "List Error In Primary List"},
849     {0x1903,  "List Error In Grown List"},
850     {0x1A00,  "Parameter List Length Error"},
851     {0x1B00,  "Synchronous Data Transfer Error"},
852     {0x1C00,  "Defect List Not Found"},
853     {0x1C01,  "Primary Defect List Not Found"},
854     {0x1C02,  "Grown Defect List Not Found"},
855     {0x1D00,  "Miscompare During Verify Operation"},
856     {0x1E00,  "Recovered Id With Ecc Correction"},
857     {0x1F00,  "Defect List Transfer"},
858     {0x2000,  "Invalid Command Operation Code"},
859     {0x2100,  "Logical Block Address Out Of Range"},
860     {0x2101,  "Invalid Element Address"},
861     {0x2400,  "Invalid Field In Cdb"},
862     {0x2401,  "Cdb Decryption Error"},
863     {0x2500,  "Logical Unit Not Supported"},
864     {0x2600,  "Invalid Field In Parameter List"},
865     {0x2601,  "Parameter Not Supported"},
866     {0x2602,  "Parameter Value Invalid"},
867     {0x2603,  "Threshold Parameters Not Supported"},
868     {0x2604,  "Invalid Release Of Persistent Reservation"},
869     {0x2605,  "Data Decryption Error"},
870     {0x2606,  "Too Many Target Descriptors"},
871     {0x2607,  "Unsupported Target Descriptor Type Code"},
872     {0x2608,  "Too Many Segment Descriptors"},
873     {0x2609,  "Unsupported Segment Descriptor Type Code"},
874     {0x260A,  "Unexpected Inexact Segment"},
875     {0x260B,  "Inline Data Length Exceeded"},
876     {0x260C,  "Invalid Operation For Copy Source Or Destination"},
877     {0x260D,  "Copy Segment Granularity Violation"},
878     {0x2700,  "Write Protected"},
879     {0x2701,  "Hardware Write Protected"},
880     {0x2702,  "Logical Unit Software Write Protected"},
881     {0x2800,  "Not Ready To Ready Change, Medium May Have Changed"},
882     {0x2801,  "Import Or Export Element Accessed"},
883     {0x2900,  "Power On, Reset, Or Bus Device Reset Occurred"},
884     {0x2901,  "Power On Occurred"},
885     {0x2902,  "Scsi Bus Reset Occurred"},
886     {0x2903,  "Bus Device Reset Function Occurred"},
887     {0x2904,  "Device Internal Reset"},
888     {0x2905,  "Transceiver Mode Changed To Single-Ended"},
889     {0x2906,  "Transceiver Mode Changed To Lvd"},
890     {0x2A00,  "Parameters Changed"},
891     {0x2A01,  "Mode Parameters Changed"},
892     {0x2A02,  "Log Parameters Changed"},
893     {0x2A03,  "Reservations Preempted"},
894     {0x2A04,  "Reservations Released"},
895     {0x2A05,  "Registrations Preempted"},
896     {0x2B00,  "Copy Cannot Execute Since Host Cannot Disconnect"},
897     {0x2C00,  "Command Sequence Error"},
898     {0x2F00,  "Commands Cleared By Another Initiator"},
899     {0x3000,  "Incompatible Medium Installed"},
900     {0x3001,  "Cannot Read Medium - Unknown Format"},
901     {0x3002,  "Cannot Read Medium - Incompatible Format"},
902     {0x3003,  "Cleaning Cartridge Installed"},
903     {0x3004,  "Cannot Write Medium - Unknown Format"},
904     {0x3005,  "Cannot Write Medium - Incompatible Format"},
905     {0x3006,  "Cannot Format Medium - Incompatible Medium"},
906     {0x3007,  "Cleaning Failure"},
907     {0x3100,  "Medium Format Corrupted"},
908     {0x3101,  "Format Command Failed"},
909     {0x3200,  "No Defect Spare Location Available"},
910     {0x3201,  "Defect List Update Failure"},
911     {0x3400,  "Enclosure Failure"},
912     {0x3500,  "Enclosure Services Failure"},
913     {0x3501,  "Unsupported Enclosure Function"},
914     {0x3502,  "Enclosure Services Unavailable"},
915     {0x3503,  "Enclosure Services Transfer Failure"},
916     {0x3504,  "Enclosure Services Transfer Refused"},
917     {0x3700,  "Rounded Parameter"},
918     {0x3900,  "Saving Parameters Not Supported"},
919     {0x3A00,  "Medium Not Present"},
920     {0x3A01,  "Medium Not Present - Tray Closed"},
921     {0x3A02,  "Medium Not Present - Tray Open"},
922     {0x3A03,  "Medium Not Present - Loadable"},
923     {0x3A04,  "Medium Not Present - Medium Auxiliary Memory Accessible"},
924     {0x3B0D,  "Medium Destination Element Full"},
925     {0x3B0E,  "Medium Source Element Empty"},
926     {0x3B11,  "Medium Magazine Not Accessible"},
927     {0x3B12,  "Medium Magazine Removed"},
928     {0x3B13,  "Medium Magazine Inserted"},
929     {0x3B14,  "Medium Magazine Locked"},
930     {0x3B15,  "Medium Magazine Unlocked"},
931     {0x3D00,  "Invalid Bits In Identify Message"},
932     {0x3E00,  "Logical Unit Has Not Self-Configured Yet"},
933     {0x3E01,  "Logical Unit Failure"},
934     {0x3E02,  "Timeout On Logical Unit"},
935     {0x3E03,  "Logical Unit Failed Self-Test"},
936     {0x3E04,  "Logical Unit Unable To Update Self-Test Log"},
937     {0x3F00,  "Target Operating Conditions Have Changed"},
938     {0x3F01,  "Microcode Has Been Changed"},
939     {0x3F02,  "Changed Operating Definition"},
940     {0x3F03,  "Inquiry Data Has Changed"},
941     {0x3F04,  "Component Device Attached"},
942     {0x3F05,  "Device Identifier Changed"},
943     {0x3F06,  "Redundancy Group Created Or Modified"},
944     {0x3F07,  "Redundancy Group Deleted"},
945     {0x3F08,  "Spare Created Or Modified"},
946     {0x3F09,  "Spare Deleted"},
947     {0x3F0A,  "Volume Set Created Or Modified"},
948     {0x3F0B,  "Volume Set Deleted"},
949     {0x3F0C,  "Volume Set Deassigned"},
950     {0x3F0D,  "Volume Set Reassigned"},
951     {0x3F0E,  "Reported Luns Data Has Changed"},
952     {0x3F0F,  "Echo Buffer Overwritten"},
953     {0x3F10,  "Medium Loadable"},
954     {0x3F11,  "Medium Auxiliary Memory Accessible"},
955     {0x4200,  "Self-Test Failure (Should Use 40 Nn)"},
956     {0x4300,  "Message Error"},
957     {0x4400,  "Internal Target Failure"},
958     {0x4500,  "Select Or Reselect Failure"},
959     {0x4600,  "Unsuccessful Soft Reset"},
960     {0x4700,  "Scsi Parity Error"},
961     {0x4701,  "Data Phase Crc Error Detected"},
962     {0x4702,  "Scsi Parity Error Detected During St Data Phase"},
963     {0x4703,  "Information Unit Crc Error Detected"},
964     {0x4704,  "Asynchronous Information Protection Error Detected"},
965     {0x4800,  "Initiator Detected Error Message Received"},
966     {0x4900,  "Invalid Message Error"},
967     {0x4A00,  "Command Phase Error"},
968     {0x4B00,  "Data Phase Error"},
969     {0x4C00,  "Logical Unit Failed Self-Configuration"},
970     {0x4D00,  "Tagged Overlapped Commands (Nn = Queue Tag)"},
971     {0x4E00,  "Overlapped Commands Attempted"},
972     {0x5300,  "Media Load Or Eject Failed"},
973     {0x5302,  "Medium Removal Prevented"},
974     {0x5501,  "System Buffer Full"},
975     {0x5502,  "Insufficient Reservation Resources"},
976     {0x5503,  "Insufficient Resources"},
977     {0x5504,  "Insufficient Registration Resources"},
978     {0x5A00,  "Operator Request Or State Change Input"},
979     {0x5A01,  "Operator Medium Removal Request"},
980     {0x5A02,  "Operator Selected Write Protect"},
981     {0x5A03,  "Operator Selected Write Permit"},
982     {0x5B00,  "Log Exception"},
983     {0x5B01,  "Threshold Condition Met"},
984     {0x5B02,  "Log Counter At Maximum"},
985     {0x5B03,  "Log List Codes Exhausted"},
986     {0x5C00,  "Change"},
987     {0x5C02,  "Synchronized"},
988     {0x5D00,  "Failure Prediction Threshold Exceeded"},
989     {0x5D10,  "Failure General Hard Drive Failure"},
990     {0x5D11,  "Failure Drive Error Rate Too High"},
991     {0x5D12,  "Failure Data Error Rate Too High"},
992     {0x5D13,  "Failure Seek Error Rate Too High"},
993     {0x5D14,  "Failure Too Many Block Reassigns"},
994     {0x5D15,  "Failure Access Times Too High"},
995     {0x5D16,  "Failure Start Unit Times Too High"},
996     {0x5D17,  "Failure Channel Parametrics"},
997     {0x5D18,  "Failure Controller Detected"},
998     {0x5D19,  "Failure Throughput Performance"},
999     {0x5D1A,  "Failure Seek Time Performance"},
1000     {0x5D1B,  "Failure Spin-Up Retry Count"},
1001     {0x5D1C,  "Failure Drive Calibration Retry"},
1002     {0x5D20,  "Failure General Hard Drive Failure"},
1003     {0x5D21,  "Failure Drive Error Rate Too High"},
1004     {0x5D22,  "Failure Data Error Rate Too High"},
1005     {0x5D23,  "Failure Seek Error Rate Too High"},
1006     {0x5D24,  "Failure Too Many Block Reassigns"},
1007     {0x5D25,  "Failure Access Times Too High"},
1008     {0x5D26,  "Failure Start Unit Times Too High"},
1009     {0x5D27,  "Failure Channel Parametrics"},
1010     {0x5D28,  "Failure Controller Detected"},
1011     {0x5D29,  "Failure Throughput Performance"},
1012     {0x5D2A,  "Failure Seek Time Performance"},
1013     {0x5D2B,  "Failure Spin-Up Retry Count"},
1014     {0x5D2C,  "Failure Drive Calibration Retry"},
1015     {0x5D30,  "Impending Failure General Hard Drive"},
1016     {0x5D31,  "Impending Failure Drive Error Rate Too High"},
1017     {0x5D32,  "Impending Failure Data Error Rate Too High"},
1018     {0x5D33,  "Impending Failure Seek Error Rate Too High"},
1019     {0x5D34,  "Impending Failure Too Many Block Reassigns"},
1020     {0x5D35,  "Impending Failure Access Times Too High"},
1021     {0x5D36,  "Impending Failure Start Unit Times Too High"},
1022     {0x5D37,  "Impending Failure Channel Parametrics"},
1023     {0x5D38,  "Impending Failure Controller Detected"},
1024     {0x5D39,  "Impending Failure Throughput Performance"},
1025     {0x5D3A,  "Impending Failure Seek Time Performance"},
1026     {0x5D3B,  "Impending Failure Spin-Up Retry Count"},
1027     {0x5D3C,  "Impending Failure Drive Calibration Retry"},
1028     {0x5D40,  "Failure General Hard Drive Failure"},
1029     {0x5D41,  "Failure Drive Error Rate Too High"},
1030     {0x5D42,  "Failure Data Error Rate Too High"},
1031     {0x5D43,  "Failure Seek Error Rate Too High"},
1032     {0x5D44,  "Failure Too Many Block Reassigns"},
1033     {0x5D45,  "Failure Access Times Too High"},
1034     {0x5D46,  "Failure Start Unit Times Too High"},
1035     {0x5D47,  "Failure Channel Parametrics"},
1036     {0x5D48,  "Failure Controller Detected"},
1037     {0x5D49,  "Failure Throughput Performance"},
1038     {0x5D4A,  "Failure Seek Time Performance"},
1039     {0x5D4B,  "Failure Spin-Up Retry Count"},
1040     {0x5D4C,  "Failure Drive Calibration Retry Count"},
1041     {0x5D50,  "Failure General Hard Drive Failure"},
1042     {0x5D51,  "Failure Drive Error Rate Too High"},
1043     {0x5D52,  "Failure Data Error Rate Too High"},
1044     {0x5D53,  "Failure Seek Error Rate Too High"},
1045     {0x5D54,  "Failure Too Many Block Reassigns"},
1046     {0x5D55,  "Failure Access Times Too High"},
1047     {0x5D56,  "Failure Start Unit Times Too High"},
1048     {0x5D57,  "Failure Channel Parametrics"},
1049     {0x5D58,  "Failure Controller Detected"},
1050     {0x5D59,  "Failure Throughput Performance"},
1051     {0x5D5A,  "Failure Seek Time Performance"},
1052     {0x5D5B,  "Failure Spin-Up Retry Count"},
1053     {0x5D5C,  "Failure Drive Calibration Retry Count"},
1054     {0x5D60,  "Failure General Hard Drive Failure"},
1055     {0x5D61,  "Failure Drive Error Rate Too High"},
1056     {0x5D62,  "Failure Data Error Rate Too High"},
1057     {0x5D63,  "Failure Seek Error Rate Too High"},
1058     {0x5D64,  "Failure Too Many Block Reassigns"},
1059     {0x5D65,  "Failure Access Times Too High"},
1060     {0x5D66,  "Failure Start Unit Times Too High"},
1061     {0x5D67,  "Failure Channel Parametrics"},
1062     {0x5D68,  "Failure Controller Detected"},
1063     {0x5D69,  "Failure Throughput Performance"},
1064     {0x5D6A,  "Failure Seek Time Performance"},
1065     {0x5D6B,  "Failure Spin-Up Retry Count"},
1066     {0x5D6C,  "Failure Drive Calibration Retry Count"},
1067     {0x5DFF,  "Failure Prediction Threshold Exceeded (False)"},
1068     {0x5E00,  "Low Power Condition On"},
1069     {0x5E01,  "Idle Condition Activated By Timer"},
1070     {0x5E02,  "Standby Condition Activated By Timer"},
1071     {0x5E03,  "Idle Condition Activated By Command"},
1072     {0x5E04,  "Standby Condition Activated By Command"},
1073     {0x6500,  "Voltage Fault"},
1074     {0, NULL},
1075 };
1076
1077 /* SCSI Status Codes */
1078 const value_string scsi_status_val[] = {
1079     {0x00, "Good"},
1080     {0x02, "Check Condition"},
1081     {0x04, "Condition Met"},
1082     {0x08, "Busy"},
1083     {0x10, "Intermediate"},
1084     {0x14, "Intermediate Condition Met"},
1085     {0x18, "Reservation Conflict"},
1086     {0x28, "Task Set Full"},
1087     {0x30, "ACA Active"},
1088     {0x40, "Task Aborted"},
1089     {0, NULL},
1090 };
1091
1092 static gint scsi_def_devtype = SCSI_DEV_SBC;
1093
1094 /*
1095  * We track SCSI requests and responses with a hash table.
1096  * The key is a "scsi_task_id_t" structure; the data is a
1097  * "scsi_task_data_t" structure.
1098  */
1099 typedef struct _scsi_task_data {
1100     guint32 opcode;
1101     scsi_device_type devtype;
1102     guint8 flags;               /* used by SCSI Inquiry */
1103 } scsi_task_data_t;
1104
1105 /* The next two data structures are used to track SCSI device type */
1106 typedef struct _scsi_devtype_key {
1107     address devid;
1108 } scsi_devtype_key_t;
1109
1110 typedef struct _scsi_devtype_data {
1111     scsi_device_type devtype;
1112 } scsi_devtype_data_t;
1113
1114 static GHashTable *scsi_req_hash = NULL;
1115 static GMemChunk *scsi_req_keys = NULL;
1116 static GMemChunk *scsi_req_vals = NULL;
1117 static guint32 scsi_init_count = 25;
1118
1119 static GHashTable *scsidev_req_hash = NULL;
1120 static GMemChunk *scsidev_req_keys = NULL;
1121 static GMemChunk *scsidev_req_vals = NULL;
1122 static guint32 scsidev_init_count = 25;
1123
1124 static dissector_handle_t data_handle;
1125
1126 /*
1127  * Hash Functions
1128  */
1129 static gint
1130 scsi_equal(gconstpointer v, gconstpointer w)
1131 {
1132   scsi_task_id_t *v1 = (scsi_task_id_t *)v;
1133   scsi_task_id_t *v2 = (scsi_task_id_t *)w;
1134
1135   return (v1->conv_id == v2->conv_id && v1->task_id == v2->task_id);
1136 }
1137
1138 static guint
1139 scsi_hash (gconstpointer v)
1140 {
1141         scsi_task_id_t *key = (scsi_task_id_t *)v;
1142         guint val;
1143
1144         val = key->conv_id + key->task_id;
1145
1146         return val;
1147 }
1148
1149 static gint
1150 scsidev_equal (gconstpointer v, gconstpointer w)
1151 {
1152     scsi_devtype_key_t *k1 = (scsi_devtype_key_t *)v;
1153     scsi_devtype_key_t *k2 = (scsi_devtype_key_t *)w;
1154
1155     if (ADDRESSES_EQUAL (&k1->devid, &k2->devid))
1156         return 1;
1157     else
1158         return 0;
1159 }
1160
1161 static guint
1162 scsidev_hash (gconstpointer v)
1163 {
1164     scsi_devtype_key_t *key = (scsi_devtype_key_t *)v;
1165     guint val;
1166     int i;
1167
1168     val = 0;
1169     for (i = 0; i < key->devid.len; i++)
1170         val += key->devid.data[i];
1171     val += key->devid.type;
1172
1173     return val;
1174 }
1175
1176 static scsi_task_data_t *
1177 scsi_new_task (packet_info *pinfo)
1178 {
1179     scsi_task_data_t *cdata = NULL;
1180     scsi_task_id_t ckey, *req_key;
1181     
1182     if ((pinfo != NULL) && (pinfo->private_data)) {
1183         ckey = *(scsi_task_id_t *)pinfo->private_data;
1184
1185         cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
1186                                                          &ckey);
1187         if (!cdata) {
1188             req_key = g_mem_chunk_alloc (scsi_req_keys);
1189             *req_key = *(scsi_task_id_t *)pinfo->private_data;
1190             
1191             cdata = g_mem_chunk_alloc (scsi_req_vals);
1192             
1193             g_hash_table_insert (scsi_req_hash, req_key, cdata);
1194         }
1195     }
1196     return (cdata);
1197 }
1198
1199 static scsi_task_data_t *
1200 scsi_find_task (packet_info *pinfo)
1201 {
1202     scsi_task_data_t *cdata = NULL;
1203     scsi_task_id_t ckey;
1204
1205     if ((pinfo != NULL) && (pinfo->private_data)) {
1206         ckey = *(scsi_task_id_t *)pinfo->private_data;
1207
1208         cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
1209                                                          &ckey);
1210     }
1211     return (cdata);
1212 }
1213
1214 static void
1215 scsi_end_task (packet_info *pinfo)
1216 {
1217     scsi_task_data_t *cdata = NULL;
1218     scsi_task_id_t ckey;
1219
1220     if ((pinfo != NULL) && (pinfo->private_data)) {
1221         ckey = *(scsi_task_id_t *)pinfo->private_data;
1222         cdata = (scsi_task_data_t *)g_hash_table_lookup (scsi_req_hash,
1223                                                          &ckey);
1224         if (cdata) {
1225             g_mem_chunk_free (scsi_req_vals, cdata);
1226             g_hash_table_remove (scsi_req_hash, &ckey);
1227         }
1228     }
1229 }
1230
1231 /*
1232  * Protocol initialization
1233  */
1234 static void
1235 scsi_init_protocol(void)
1236 {
1237         if (scsi_req_keys)
1238             g_mem_chunk_destroy(scsi_req_keys);
1239         if (scsi_req_vals)
1240             g_mem_chunk_destroy(scsi_req_vals);
1241         if (scsidev_req_keys)
1242             g_mem_chunk_destroy (scsidev_req_keys);
1243         if (scsidev_req_vals)
1244             g_mem_chunk_destroy (scsidev_req_vals);
1245         if (scsi_req_hash)
1246             g_hash_table_destroy(scsi_req_hash);
1247         if (scsidev_req_hash)
1248             g_hash_table_destroy (scsidev_req_hash);
1249
1250         scsi_req_hash = g_hash_table_new(scsi_hash, scsi_equal);
1251         scsi_req_keys = g_mem_chunk_new("scsi_req_keys",
1252                                         sizeof(scsi_task_id_t),
1253                                         scsi_init_count *
1254                                         sizeof(scsi_task_id_t),
1255                                         G_ALLOC_AND_FREE);
1256         scsi_req_vals = g_mem_chunk_new("scsi_req_vals",
1257                                         sizeof(scsi_task_data_t),
1258                                         scsi_init_count *
1259                                         sizeof(scsi_task_data_t),
1260                                         G_ALLOC_AND_FREE);
1261         scsidev_req_hash = g_hash_table_new (scsidev_hash, scsidev_equal);
1262         scsidev_req_keys = g_mem_chunk_new("scsidev_req_keys",
1263                                            sizeof(scsi_devtype_key_t),
1264                                            scsidev_init_count *
1265                                            sizeof(scsi_devtype_key_t),
1266                                            G_ALLOC_AND_FREE);
1267         scsidev_req_vals = g_mem_chunk_new("scsidev_req_vals",
1268                                            sizeof(scsi_devtype_data_t),
1269                                            scsidev_init_count *
1270                                            sizeof(scsi_devtype_data_t),
1271                                            G_ALLOC_AND_FREE);
1272 }
1273
1274 static void
1275 dissect_scsi_evpd (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1276                    guint offset, guint tot_len _U_)
1277 {
1278     proto_tree *evpd_tree;
1279     proto_item *ti;
1280     guint pcode, plen, i, idlen;
1281     guint8 flags;
1282     char str[32];
1283
1284     if (tree) {
1285         pcode = tvb_get_guint8 (tvb, offset+1);
1286         plen = tvb_get_guint8 (tvb, offset+3);
1287         ti = proto_tree_add_text (tree, tvb, offset, plen+4, "Page Code: %s",
1288                                   val_to_str (pcode, scsi_evpd_pagecode_val,
1289                                               "Unknown (0x%08x)"));
1290         evpd_tree = proto_item_add_subtree (ti, ett_scsi_page);
1291         
1292         proto_tree_add_text (evpd_tree, tvb, offset, 1,
1293                              "Peripheral Qualifier: 0x%x",
1294                              (tvb_get_guint8 (tvb, offset) & 0xF0)>>4);
1295         proto_tree_add_item (evpd_tree, hf_scsi_inq_devtype, tvb, offset,
1296                              1, 0);
1297         proto_tree_add_text (evpd_tree, tvb, offset+1, 1,
1298                              "Page Code: %s",
1299                              val_to_str (pcode, scsi_evpd_pagecode_val,
1300                                          "Unknown (0x%02x)"));
1301         proto_tree_add_text (evpd_tree, tvb, offset+3, 1,
1302                              "Page Length: %u", plen);
1303         offset += 4;
1304         switch (pcode) {
1305         case SCSI_EVPD_SUPPPG:
1306             for (i = 0; i < plen; i++) {
1307                 proto_tree_add_text (evpd_tree, tvb, offset+i, 1,
1308                                      "Supported Page: %s",
1309                                      val_to_str (tvb_get_guint8 (tvb, offset+i),
1310                                                  scsi_evpd_pagecode_val,
1311                                                  "Unknown (0x%02x)"));
1312             }
1313             break;
1314         case SCSI_EVPD_DEVID:
1315             while (plen > 0) {
1316                 flags = tvb_get_guint8 (tvb, offset);
1317                 proto_tree_add_text (evpd_tree, tvb, offset, 1,
1318                                      "Code Set: %s",
1319                                      val_to_str (plen & 0x0F,
1320                                                  scsi_devid_codeset_val,
1321                                                  "Unknown (0x%02x)"));
1322                 flags = tvb_get_guint8 (tvb, offset+1);
1323                 proto_tree_add_text (evpd_tree, tvb, offset+1, 1,
1324                                      "Association: %s",
1325                                      val_to_str ((flags & 0x30) >> 4,
1326                                                  scsi_devid_assoc_val,
1327                                                  "Unknown (0x%02x)"));
1328                 proto_tree_add_text (evpd_tree, tvb, offset+1, 1,
1329                                      "Identifier Type: %s", 
1330                                      val_to_str ((flags & 0x0F),
1331                                                  scsi_devid_idtype_val, 
1332                                                  "Unknown (0x%02x)"));
1333                 idlen = tvb_get_guint8 (tvb, offset+3);
1334                 proto_tree_add_text (evpd_tree, tvb, offset+3, 1,
1335                                      "Identifier Length: %u", idlen);
1336                 proto_tree_add_text (evpd_tree, tvb, offset+4, idlen,
1337                                          "Identifier: %s",
1338                                          tvb_bytes_to_str (tvb, offset+4,
1339                                                            idlen));
1340                 plen -= idlen;
1341                 offset += idlen;
1342             }
1343             break;
1344         case SCSI_EVPD_DEVSERNUM:
1345             str[0] = '\0';
1346             tvb_get_nstringz0 (tvb, offset, plen, str);
1347             proto_tree_add_text (evpd_tree, tvb, offset, plen,
1348                                  "Product Serial Number: %s", str);
1349             break;
1350         }
1351     }
1352 }
1353
1354 static void
1355 dissect_scsi_cmddt (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1356                     guint offset, guint tot_len _U_)
1357 {
1358     proto_tree *cmdt_tree;
1359     proto_item *ti;
1360     guint plen;
1361
1362     if (tree) {
1363         plen = tvb_get_guint8 (tvb, offset+5);
1364         ti = proto_tree_add_text (tree, tvb, offset, plen, "Command Data");
1365         cmdt_tree = proto_item_add_subtree (ti, ett_scsi_page);
1366
1367         proto_tree_add_text (cmdt_tree, tvb, offset, 1,
1368                              "Peripheral Qualifier: 0x%x",
1369                              (tvb_get_guint8 (tvb, offset) & 0xF0)>>4);
1370         proto_tree_add_item (cmdt_tree, hf_scsi_inq_devtype, tvb, offset,
1371                              1, 0);
1372         proto_tree_add_text (cmdt_tree, tvb, offset+1, 1, "Support: %s",
1373                              match_strval (tvb_get_guint8 (tvb, offset+1) & 0x7,
1374                                            scsi_cmdt_supp_val));
1375         proto_tree_add_text (cmdt_tree, tvb, offset+2, 1, "Version: %s",
1376                              val_to_str (tvb_get_guint8 (tvb, offset+2),
1377                                          scsi_verdesc_val,
1378                                          "Unknown (0x%02x)"));
1379         proto_tree_add_text (cmdt_tree, tvb, offset+5, 1, "CDB Size: %u",
1380                              plen);
1381     }
1382 }
1383
1384 static void
1385 dissect_scsi_inquiry (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1386                       guint offset, gboolean isreq, gboolean iscdb,
1387                       guint32 payload_len, scsi_task_data_t *cdata)
1388 {
1389     guint8 flags, i;
1390     gchar str[32];
1391     guint tot_len;
1392     scsi_devtype_data_t *devdata = NULL;
1393     scsi_devtype_key_t dkey, *req_key;
1394
1395     /* Add device type to list of known devices & their types */
1396     COPY_ADDRESS (&(dkey.devid), &(pinfo->src));
1397     devdata = (scsi_devtype_data_t *)g_hash_table_lookup (scsidev_req_hash,
1398                                                           &dkey);
1399     if (!devdata) {
1400         req_key = g_mem_chunk_alloc (scsidev_req_keys);
1401         COPY_ADDRESS (&(req_key->devid), &(pinfo->src));
1402         
1403         devdata = g_mem_chunk_alloc (scsidev_req_vals);
1404         devdata->devtype = tvb_get_guint8 (tvb, offset) & 0x10;
1405         
1406         g_hash_table_insert (scsidev_req_hash, req_key, devdata);
1407     }
1408         
1409     if (!tree)
1410         return;
1411     
1412     if (isreq && iscdb) {
1413         flags = tvb_get_guint8 (tvb, offset);
1414         if (cdata != NULL) {
1415             cdata->flags = flags;
1416         }
1417         
1418         proto_tree_add_uint_format (tree, hf_scsi_inquiry_flags, tvb, offset, 1,
1419                                     flags, "CMDT = %u, EVPD = %u",
1420                                     flags & 0x2, flags & 0x1);
1421         if (flags & 0x1) {
1422             proto_tree_add_item (tree, hf_scsi_inquiry_evpd_page, tvb, offset+1,
1423                                  1, 0);
1424         }
1425         else if (flags & 0x2) {
1426             proto_tree_add_item (tree, hf_scsi_inquiry_cmdt_page, tvb, offset+1,
1427                                  1, 0);
1428         }
1429
1430         proto_tree_add_uint (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
1431         flags = tvb_get_guint8 (tvb, offset+4);
1432         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1433                                     flags,
1434                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1435                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1436     }
1437     else if (!isreq) {
1438         if (cdata && (cdata->flags & 0x1)) {
1439             dissect_scsi_evpd (tvb, pinfo, tree, offset, payload_len);
1440             return;
1441         }
1442         else if (cdata && (cdata->flags & 0x2)) {
1443             dissect_scsi_cmddt (tvb, pinfo, tree, offset, payload_len);
1444             return;
1445         }
1446
1447         proto_tree_add_text (tree, tvb, offset, 1, "Peripheral Qualifier: 0x%x",
1448                              (tvb_get_guint8 (tvb, offset) & 0xF0)>>4);
1449         proto_tree_add_item (tree, hf_scsi_inq_devtype, tvb, offset, 1, 0);
1450         proto_tree_add_item (tree, hf_scsi_inq_version, tvb, offset+2, 1, 0);
1451
1452         flags = tvb_get_guint8 (tvb, offset+3);
1453         proto_tree_add_item_hidden (tree, hf_scsi_inq_normaca, tvb,
1454                                     offset+3, 1, 0);
1455         proto_tree_add_text (tree, tvb, offset+3, 1, "NormACA: %u, HiSup: %u",
1456                              ((flags & 0x20) >> 5), ((flags & 0x10) >> 4));
1457         tot_len = tvb_get_guint8 (tvb, offset+4);
1458         proto_tree_add_text (tree, tvb, offset+4, 1, "Additional Length: %u",
1459                              tot_len);
1460         flags = tvb_get_guint8 (tvb, offset+6);
1461         proto_tree_add_text (tree, tvb, offset+6, 1,
1462                              "BQue: %u, SES: %u, MultiP: %u, Addr16: %u",
1463                              ((flags & 0x80) >> 7), (flags & 0x40) >> 6,
1464                              (flags & 10) >> 4, (flags & 0x01));
1465         flags = tvb_get_guint8 (tvb, offset+7);
1466         proto_tree_add_text (tree, tvb, offset+7, 1,
1467                              "RelAdr: %u, Linked: %u, CmdQue: %u",
1468                              (flags & 0x80) >> 7, (flags & 0x08) >> 3,
1469                              (flags & 0x02) >> 1);
1470         tvb_get_nstringz0 (tvb, offset+8, 8, str);
1471         proto_tree_add_text (tree, tvb, offset+8, 8, "Vendor Id: %s", str);
1472         tvb_get_nstringz0 (tvb, offset+16, 16, str);
1473         proto_tree_add_text (tree, tvb, offset+16, 16, "Product ID: %s", str);
1474         tvb_get_nstringz0 (tvb, offset+32, 4, str);
1475         proto_tree_add_text (tree, tvb, offset+32, 4, "Product Revision: %s",
1476                              str);
1477         
1478         offset += 58;
1479         if ((tot_len > 58) && tvb_bytes_exist (tvb, offset, 16)) {
1480             for (i = 0; i < 8; i++) {
1481                 proto_tree_add_text (tree, tvb, offset, 2,
1482                                      "Vendor Descriptor %u: %s",
1483                                      i,
1484                                      val_to_str (tvb_get_ntohs (tvb, offset),
1485                                                  scsi_verdesc_val,
1486                                                  "Unknown (0x%04x)"));
1487                 offset += 2;
1488             }
1489         }
1490     }
1491 }
1492
1493 static void
1494 dissect_scsi_extcopy (tvbuff_t *tvb _U_, packet_info *pinfo _U_, 
1495                       proto_tree *tree _U_, guint offset _U_, 
1496                       gboolean isreq _U_, gboolean iscdb _U_)
1497 {
1498     
1499 }
1500
1501 static void
1502 dissect_scsi_logselect (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1503                         guint offset, gboolean isreq, gboolean iscdb)
1504 {
1505     guint8 flags;
1506     
1507     if (!tree)
1508         return;
1509     
1510     if (isreq && iscdb) {
1511         flags = tvb_get_guint8 (tvb, offset);
1512         
1513         proto_tree_add_uint_format (tree, hf_scsi_logsel_flags, tvb, offset, 1,
1514                                     flags, "PCR = %u, SP = %u", flags & 0x2,
1515                                     flags & 0x1);
1516         proto_tree_add_uint_format (tree, hf_scsi_log_pc, tvb, offset+1, 1,
1517                                     tvb_get_guint8 (tvb, offset+1),
1518                                     "PC: 0x%x", flags & 0xC0);
1519         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
1520
1521         flags = tvb_get_guint8 (tvb, offset+8);
1522         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1523                                     flags,
1524                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1525                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1526     }
1527     else {
1528     }
1529 }
1530
1531 static void
1532 dissect_scsi_logsense (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
1533                        guint offset, gboolean isreq, gboolean iscdb)
1534 {
1535     guint8 flags;
1536     
1537     if (!tree)
1538         return;
1539     
1540     if (isreq && iscdb) {
1541         flags = tvb_get_guint8 (tvb, offset);
1542         
1543         proto_tree_add_uint_format (tree, hf_scsi_logsns_flags, tvb, offset, 1,
1544                                     flags, "PPC = %u, SP = %u", flags & 0x2,
1545                                     flags & 0x1);
1546         proto_tree_add_uint_format (tree, hf_scsi_log_pc, tvb, offset+1, 1,
1547                                     tvb_get_guint8 (tvb, offset+1),
1548                                     "PC: 0x%x", flags & 0xC0);
1549         proto_tree_add_item (tree, hf_scsi_logsns_pagecode, tvb, offset+1,
1550                              1, 0);
1551         proto_tree_add_text (tree, tvb, offset+4, 2, "Parameter Pointer: 0x%04x",
1552                              tvb_get_ntohs (tvb, offset+4));
1553         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
1554
1555         flags = tvb_get_guint8 (tvb, offset+8);
1556         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1557                                     flags,
1558                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1559                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1560     }
1561     else {
1562     }
1563 }
1564
1565 static guint8
1566 dissect_scsi_modepage (tvbuff_t *tvb, packet_info *pinfo _U_, 
1567                        proto_tree *scsi_tree, guint offset)
1568 {
1569     guint8 pcode, plen, flags, proto;
1570     proto_tree *tree;
1571     proto_item *ti;
1572
1573     pcode = tvb_get_guint8 (tvb, offset);
1574     plen = tvb_get_guint8 (tvb, offset+1);
1575
1576     ti = proto_tree_add_text (scsi_tree, tvb, offset, plen+2, "%s Mode Page",
1577                               val_to_str (pcode & 0x3F, scsi_modesns_page_val,
1578                                           "Unknown (0x%08x)"));
1579     tree = proto_item_add_subtree (ti, ett_scsi_page);
1580     proto_tree_add_text (tree, tvb, offset, 1, "PS: %u", (pcode & 0x80) >> 8);
1581                          
1582     proto_tree_add_item (tree, hf_scsi_modesns_pagecode, tvb, offset, 1, 0);
1583     proto_tree_add_text (tree, tvb, offset+1, 1, "Page Length: %u",
1584                          plen);
1585
1586     if (!tvb_bytes_exist (tvb, offset, plen)) {
1587         return (plen + 2);
1588     }
1589     
1590     pcode &= 0x3F;
1591     switch (pcode) {
1592     case SCSI_MODEPAGE_CTL:
1593         flags = tvb_get_guint8 (tvb, offset+2);
1594         proto_tree_add_item (tree, hf_scsi_modesns_tst, tvb, offset+2, 1, 0);
1595         proto_tree_add_text (tree, tvb, offset+2, 1,
1596                              "Global Logging Target Save Disable: %u, Report Log Exception Condition: %u",
1597                              (flags & 0x2) >> 1, (flags & 0x1));
1598         flags = tvb_get_guint8 (tvb, offset+3);
1599         proto_tree_add_item (tree, hf_scsi_modesns_qmod, tvb, offset+3, 1, 0);
1600         proto_tree_add_item (tree, hf_scsi_modesns_qerr, tvb, offset+3, 1, 0);
1601         proto_tree_add_text (tree, tvb, offset+3, 1, "Disable Queuing: %u",
1602                              flags & 0x1);
1603         flags = tvb_get_guint8 (tvb, offset+4);
1604         proto_tree_add_item (tree, hf_scsi_modesns_rac, tvb, offset+4, 1, 0);
1605         proto_tree_add_item (tree, hf_scsi_modesns_tas, tvb, offset+4, 1, 0);
1606         proto_tree_add_text (tree, tvb, offset+4, 1,
1607                              "SWP: %u, RAERP: %u, UAAERP: %u, EAERP: %u",
1608                              (flags & 0x8) >> 3, (flags & 0x4) >> 2,
1609                              (flags & 0x2) >> 2, (flags & 0x1));
1610         proto_tree_add_text (tree, tvb, offset+5, 1, "Autoload Mode: 0x%x",
1611                              tvb_get_guint8 (tvb, offset+5) & 0x7);
1612         proto_tree_add_text (tree, tvb, offset+6, 2,
1613                              "Ready AER Holdoff Period: %u ms",
1614                              tvb_get_ntohs (tvb, offset+6));
1615         proto_tree_add_text (tree, tvb, offset+8, 2,
1616                              "Busy Timeout Period: %u ms",
1617                              tvb_get_ntohs (tvb, offset+8)*100);
1618         proto_tree_add_text (tree, tvb, offset+10, 2,
1619                              "Extended Self-Test Completion Time: %u",
1620                              tvb_get_ntohs (tvb, offset+10));
1621         break;
1622     case SCSI_MODEPAGE_DISCON:
1623         proto_tree_add_text (tree, tvb, offset+2, 1, "Buffer Full Ratio: %u",
1624                              tvb_get_guint8 (tvb, offset+2));
1625         proto_tree_add_text (tree, tvb, offset+3, 1, "Buffer Empty Ratio: %u",
1626                              tvb_get_guint8 (tvb, offset+3));
1627         proto_tree_add_text (tree, tvb, offset+4, 2, "Bus Inactivity Limit: %u",
1628                              tvb_get_ntohs (tvb, offset+4));
1629         proto_tree_add_text (tree, tvb, offset+6, 2, "Disconnect Time Limit: %u",
1630                              tvb_get_ntohs (tvb, offset+6));
1631         proto_tree_add_text (tree, tvb, offset+8, 2, "Connect Time Limit: %u",
1632                              tvb_get_ntohs (tvb, offset+8));
1633         proto_tree_add_text (tree, tvb, offset+10, 2,
1634                              "Maximum Burst Size: %u bytes",
1635                              tvb_get_ntohs (tvb, offset+10)*512);
1636         flags = tvb_get_guint8 (tvb, offset+12);
1637         proto_tree_add_text (tree, tvb, offset+12, 1,
1638                              "EMDP: %u, FAA: %u, FAB: %u, FAC: %u",
1639                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
1640                              (flags & 0x20) >> 5, (flags & 0x10) >> 4);
1641         proto_tree_add_text (tree, tvb, offset+14, 2,
1642                              "First Burst Size: %u bytes",
1643                              tvb_get_ntohs (tvb, offset+14)*512);
1644         break;
1645     case SCSI_MODEPAGE_INFOEXCP:
1646         flags = tvb_get_guint8 (tvb, offset+2);
1647         proto_tree_add_text (tree, tvb, offset+2, 1,
1648                              "Perf: %u, EBF: %u, EWasc: %u, DExcpt: %u, Test: %u, LogErr: %u",
1649                              (flags & 0x80) >> 7, (flags & 0x20) >> 5,
1650                              (flags & 0x10) >> 4, (flags & 0x08) >> 3,
1651                              (flags & 0x04) >> 2, (flags & 0x01));
1652         if (!((flags & 0x10) >> 4) && ((flags & 0x08) >> 3)) {
1653             proto_tree_add_item_hidden (tree, hf_scsi_modesns_errrep, tvb,
1654                                         offset+3, 1, 0);
1655         }
1656         else {
1657             proto_tree_add_item (tree, hf_scsi_modesns_errrep, tvb, offset+3, 1, 0);
1658         }
1659         proto_tree_add_text (tree, tvb, offset+4, 4, "Interval Timer: %u",
1660                              tvb_get_ntohl (tvb, offset+4));
1661         proto_tree_add_text (tree, tvb, offset+8, 4, "Report Count: %u",
1662                              tvb_get_ntohl (tvb, offset+8));
1663         break;
1664     case SCSI_MODEPAGE_PWR:
1665         flags = tvb_get_guint8 (tvb, offset+3);
1666         proto_tree_add_text (tree, tvb, offset+3, 1, "Idle: %u, Standby: %u",
1667                              (flags & 0x2) >> 1, (flags & 0x1));
1668         proto_tree_add_text (tree, tvb, offset+4, 2,
1669                              "Idle Condition Timer: %u ms",
1670                              tvb_get_ntohs (tvb, offset+4) * 100);
1671         proto_tree_add_text (tree, tvb, offset+6, 2,
1672                              "Standby Condition Timer: %u ms",
1673                              tvb_get_ntohs (tvb, offset+6) * 100);
1674         break;
1675     case SCSI_MODEPAGE_LUN:
1676         break;
1677     case SCSI_MODEPAGE_PORT:
1678         proto = tvb_get_guint8 (tvb, offset+2) & 0x0F;
1679         proto_tree_add_item (tree, hf_scsi_protocol, tvb, offset+2, 1, 0);
1680         if (proto == SCSI_PROTO_FCP) {
1681             flags = tvb_get_guint8 (tvb, offset+3);
1682             proto_tree_add_text (tree, tvb, offset+3, 1,
1683                                  "DTFD: %u, PLPB: %u, DDIS: %u, DLM: %u, RHA: %u, ALWI: %u, DTIPE: %u, DTOLI:%u",
1684                                  (flags & 0x80) >> 7, (flags & 0x40) >> 6,
1685                                  (flags & 0x20) >> 5, (flags & 0x10) >> 4,
1686                                  (flags & 0x08) >> 3, (flags & 0x04) >> 2,
1687                                  (flags & 0x02) >> 1, (flags & 0x1));
1688             proto_tree_add_text (tree, tvb, offset+6, 1, "RR_TOV Units: %s",
1689                                  val_to_str (tvb_get_guint8 (tvb, offset+6) & 0x7,
1690                                              scsi_fcp_rrtov_val,
1691                                              "Unknown (0x%02x)"));
1692             proto_tree_add_text (tree, tvb, offset+7, 1, "RR_TOV: %u",
1693                                  tvb_get_guint8 (tvb, offset+7));
1694         }
1695         else if (proto == SCSI_PROTO_iSCSI) {
1696         }
1697         else {
1698         }
1699         break;
1700     case SCSI_MODEPAGE_FMTDEV:
1701         proto_tree_add_text (tree, tvb, offset+2, 2, "Tracks Per Zone: %u",
1702                              tvb_get_ntohs (tvb, offset+2));
1703         proto_tree_add_text (tree, tvb, offset+4, 2,
1704                              "Alternate Sectors Per Zone: %u",
1705                              tvb_get_ntohs (tvb, offset+4));
1706         proto_tree_add_text (tree, tvb, offset+6, 2,
1707                              "Alternate Tracks Per Zone: %u",
1708                              tvb_get_ntohs (tvb, offset+6));
1709         proto_tree_add_text (tree, tvb, offset+8, 2,
1710                              "Alternate Tracks Per LU: %u",
1711                              tvb_get_ntohs (tvb, offset+8));
1712         proto_tree_add_text (tree, tvb, offset+10, 2, "Sectors Per Track: %u",
1713                              tvb_get_ntohs (tvb, offset+10));
1714         proto_tree_add_text (tree, tvb, offset+12, 2,
1715                              "Data Bytes Per Physical Sector: %u",
1716                              tvb_get_ntohs (tvb, offset+12));
1717         proto_tree_add_text (tree, tvb, offset+14, 2, "Interleave: %u",
1718                              tvb_get_ntohs (tvb, offset+14));
1719         proto_tree_add_text (tree, tvb, offset+16, 2, "Track Skew Factor: %u",
1720                              tvb_get_ntohs (tvb, offset+16));
1721         proto_tree_add_text (tree, tvb, offset+18, 2,
1722                              "Cylinder Skew Factor: %u",
1723                              tvb_get_ntohs (tvb, offset+18));
1724         flags = tvb_get_guint8 (tvb, offset+20);
1725         proto_tree_add_text (tree, tvb, offset+20, 1,
1726                              "SSEC: %u, HSEC: %u, RMB: %u, SURF: %u",
1727                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
1728                              (flags & 0x20) >> 5, (flags & 0x10) >> 4);
1729         break;
1730     case SCSI_MODEPAGE_RDWRERR:
1731         flags = tvb_get_guint8 (tvb, offset+2);
1732         proto_tree_add_text (tree, tvb, offset+2, 1,
1733                              "AWRE: %u, ARRE: %u, TB: %u, RC: %u, EER: %u, PER: %u, DTE: %u, DCR: %u",
1734                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
1735                              (flags & 0x20) >> 5, (flags & 0x10) >> 4,
1736                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
1737                              (flags & 0x02) >> 1, (flags & 0x01));
1738         proto_tree_add_text (tree, tvb, offset+3, 1, "Read Retry Count: %u",
1739                              tvb_get_guint8 (tvb, offset+3));
1740         proto_tree_add_text (tree, tvb, offset+4, 1, "Correction Span: %u",
1741                              tvb_get_guint8 (tvb, offset+4));
1742         proto_tree_add_text (tree, tvb, offset+5, 1, "Head Offset Count: %u",
1743                              tvb_get_guint8 (tvb, offset+5));
1744         proto_tree_add_text (tree, tvb, offset+6, 1,
1745                              "Data Strobe Offset Count: %u",
1746                              tvb_get_guint8 (tvb, offset+6));
1747         proto_tree_add_text (tree, tvb, offset+8, 1, "Write Retry Count: %u",
1748                              tvb_get_guint8 (tvb, offset+8));
1749         proto_tree_add_text (tree, tvb, offset+10, 2,
1750                              "Recovery Time Limit: %u ms",
1751                              tvb_get_ntohs (tvb, offset+10));
1752         break;
1753     case SCSI_MODEPAGE_DISKGEOM:
1754         proto_tree_add_text (tree, tvb, offset+2, 3, "Number of Cylinders: %u",
1755                              tvb_get_ntoh24 (tvb, offset+2));
1756         proto_tree_add_text (tree, tvb, offset+5, 1, "Number of Heads: %u",
1757                              tvb_get_guint8 (tvb, offset+5));
1758         proto_tree_add_text (tree, tvb, offset+6, 3,
1759                              "Starting Cyl Pre-compensation: %u",
1760                              tvb_get_ntoh24 (tvb, offset+6));
1761         proto_tree_add_text (tree, tvb, offset+9, 3,
1762                              "Starting Cyl-reduced Write Current: %u",
1763                              tvb_get_ntoh24 (tvb, offset+9));
1764         proto_tree_add_text (tree, tvb, offset+12, 2, "Device Step Rate: %u",
1765                              tvb_get_ntohs (tvb, offset+12));
1766         proto_tree_add_text (tree, tvb, offset+14, 3, "Landing Zone Cyl: %u",
1767                              tvb_get_ntoh24 (tvb, offset+14));
1768         proto_tree_add_text (tree, tvb, offset+18, 1, "Rotational Offset: %u",
1769                              tvb_get_guint8 (tvb, offset+18));
1770         proto_tree_add_text (tree, tvb, offset+20, 2,
1771                              "Medium Rotation Rate: %u",
1772                              tvb_get_ntohs (tvb, offset+20));
1773         break;
1774     case SCSI_MODEPAGE_FLEXDISK:
1775         break;
1776     case SCSI_MODEPAGE_VERERR:
1777         break;
1778     case SCSI_MODEPAGE_CACHE:
1779         flags = tvb_get_guint8 (tvb, offset+2);
1780         proto_tree_add_text (tree, tvb, offset+2, 1,
1781                              "IC: %u, ABPF: %u, CAP %u, Disc: %u, Size: %u, WCE: %u, MF: %u, RCD: %u",
1782                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
1783                              (flags & 0x20) >> 5, (flags & 0x10) >> 4,
1784                              (flags & 0x08) >> 3, (flags & 0x04) >> 2,
1785                              (flags & 0x02) >> 1, (flags & 0x01));
1786         flags = tvb_get_guint8 (tvb, offset+3);
1787         proto_tree_add_text (tree, tvb, offset+3, 1,
1788                              "Demand Read Retention Priority: %u, Write Retention Priority: %u",
1789                              (flags & 0xF0) >> 4, (flags & 0x0F));
1790         proto_tree_add_text (tree, tvb, offset+4, 2,
1791                              "Disable Pre-fetch Xfer Len: %u",
1792                              tvb_get_ntohs (tvb, offset+4));
1793         proto_tree_add_text (tree, tvb, offset+6, 2, "Minimum Pre-Fetch: %u",
1794                              tvb_get_ntohs (tvb, offset+6));
1795         proto_tree_add_text (tree, tvb, offset+8, 2, "Maximum Pre-Fetch: %u",
1796                              tvb_get_ntohs (tvb, offset+8));
1797         proto_tree_add_text (tree, tvb, offset+10, 2,
1798                              "Maximum Pre-Fetch Ceiling: %u",
1799                              tvb_get_ntohs (tvb, offset+10));
1800         flags = tvb_get_guint8 (tvb, offset+12);
1801         proto_tree_add_text (tree, tvb, offset+12, 1,
1802                              "FSW: %u, LBCSS: %u, DRA: %u, Vendor Specific: %u",
1803                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
1804                              (flags & 0x20) >> 5, (flags & 0x1F) >> 4);
1805         proto_tree_add_text (tree, tvb, offset+13, 1,
1806                              "Number of Cache Segments: %u",
1807                              tvb_get_guint8 (tvb, offset+13));
1808         proto_tree_add_text (tree, tvb, offset+14, 2, "Cache Segment Size: %u",
1809                              tvb_get_ntohs (tvb, offset+14));
1810         proto_tree_add_text (tree, tvb, offset+17, 3,
1811                              "Non-Cache Segment Size: %u",
1812                              tvb_get_ntoh24 (tvb, offset+17));
1813         break;
1814     case SCSI_MODEPAGE_PERDEV:
1815         break;
1816     case SCSI_MODEPAGE_MEDTYPE:
1817         break;
1818     case SCSI_MODEPAGE_NOTPART:
1819         break;
1820     case SCSI_MODEPAGE_XORCTL:
1821         break;
1822     default:
1823         proto_tree_add_text (tree, tvb, offset, plen,
1824                              "Unknown Page");
1825         break;
1826     }
1827     return (plen+2);
1828 }
1829
1830 static void
1831 dissect_scsi_modeselect6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1832                           guint offset, gboolean isreq, gboolean iscdb,
1833                           guint payload_len _U_)
1834 {
1835     guint8 flags;
1836     guint tot_len, desclen, plen;
1837     
1838     if (!tree)
1839         return;
1840     
1841     if (isreq && iscdb) {
1842         flags = tvb_get_guint8 (tvb, offset);
1843         
1844         proto_tree_add_uint_format (tree, hf_scsi_modesel_flags, tvb, offset, 1,
1845                                     flags, "PF = %u, SP = %u", flags & 0x10,
1846                                     flags & 0x1);
1847         proto_tree_add_item (tree, hf_scsi_paramlen, tvb, offset+3, 1, 0);
1848
1849         flags = tvb_get_guint8 (tvb, offset+4);
1850         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1851                                     flags,
1852                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1853                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1854     }
1855     else {
1856         /* Mode Parameter has the following format:
1857          * Mode Parameter Header
1858          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
1859          *      Blk Desc Len
1860          * Block Descriptor (s)
1861          *    - Number of blocks, density code, block length
1862          * Page (s)
1863          *    - Page code, Page length, Page Parameters
1864          */
1865         tot_len = tvb_get_guint8 (tvb, offset);
1866         proto_tree_add_text (tree, tvb, offset, 1, "Mode Data Length: %u",
1867                              tot_len);
1868         proto_tree_add_text (tree, tvb, offset+1, 1, "Medium Type: 0x%02x",
1869                              tvb_get_guint8 (tvb, offset+1));
1870         proto_tree_add_text (tree, tvb, offset+2, 1,
1871                              "Device-Specific Parameter: 0x%02x",
1872                              tvb_get_guint8 (tvb, offset+2));
1873         desclen = tvb_get_guint8 (tvb, offset+3);
1874         proto_tree_add_text (tree, tvb, offset+3, 1,
1875                              "Block Descriptor Length: %u", desclen);
1876         offset = 4;
1877         tot_len -= 3;           /* tot_len does not include the len field */
1878         if (desclen) {
1879             proto_tree_add_text (tree, tvb, offset, 4, "No. of Blocks: %u",
1880                                  tvb_get_ntohl (tvb, offset));
1881             proto_tree_add_text (tree, tvb, offset+4, 1, "Density Code: 0x%02x",
1882                                  tvb_get_guint8 (tvb, offset+4));
1883             proto_tree_add_text (tree, tvb, offset+5, 3, "Block Length: %u",
1884                                  tvb_get_ntoh24 (tvb, offset+5));
1885             offset += 8;        /* increment the offset by 8 */
1886             tot_len -= 8;       /* subtract by the block desc len */
1887         }
1888         /* offset points to the start of the mode page */
1889         while ((tot_len > offset) && tvb_bytes_exist (tvb, offset, 2)) {
1890             plen = dissect_scsi_modepage (tvb, pinfo, tree, offset);
1891             offset += plen;
1892         }
1893     }
1894 }
1895
1896 static void
1897 dissect_scsi_modeselect10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1898                            guint offset, gboolean isreq, gboolean iscdb,
1899                            guint payload_len _U_)
1900 {
1901     guint8 flags;
1902     gboolean longlba;
1903     guint tot_len, desclen;
1904     
1905     if (!tree)
1906         return;
1907     
1908     if (isreq && iscdb) {
1909         flags = tvb_get_guint8 (tvb, offset);
1910         
1911         proto_tree_add_uint_format (tree, hf_scsi_modesel_flags, tvb, offset, 1,
1912                                     flags, "PF = %u, SP = %u", flags & 0x10,
1913                                     flags & 0x1);
1914         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
1915
1916         flags = tvb_get_guint8 (tvb, offset+8);
1917         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
1918                                     flags,
1919                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1920                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1921     }
1922     else {
1923         /* Mode Parameter has the following format:
1924          * Mode Parameter Header
1925          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
1926          *      Blk Desc Len
1927          * Block Descriptor (s)
1928          *    - Number of blocks, density code, block length
1929          * Page (s)
1930          *    - Page code, Page length, Page Parameters
1931          */
1932         tot_len = tvb_get_ntohs (tvb, offset);
1933         proto_tree_add_text (tree, tvb, offset, 2, "Mode Data Length: %u",
1934                              tot_len);
1935         proto_tree_add_text (tree, tvb, offset+2, 1, "Medium Type: 0x%02x",
1936                              tvb_get_guint8 (tvb, offset+2));
1937         proto_tree_add_text (tree, tvb, offset+3, 1,
1938                              "Device-Specific Parameter: 0x%02x",
1939                              tvb_get_guint8 (tvb, offset+3));
1940         longlba = tvb_get_guint8 (tvb, offset+4) & 0x1;
1941         proto_tree_add_text (tree, tvb, offset+4, 1, "LongLBA: %u", longlba);
1942         desclen = tvb_get_guint8 (tvb, offset+6);
1943         proto_tree_add_text (tree, tvb, offset+6, 1,
1944                              "Block Descriptor Length: %u", desclen);
1945         offset = 8;
1946         tot_len -= 6;           /* tot_len does not include the len field */
1947         if (desclen) {
1948             proto_tree_add_text (tree, tvb, offset, 8, "No. of Blocks: %s",
1949                                  bytes_to_str (tvb_get_ptr (tvb, offset, 8),
1950                                                8));
1951             proto_tree_add_text (tree, tvb, offset+8, 1, "Density Code: 0x%02x",
1952                                  tvb_get_guint8 (tvb, offset+4));
1953             proto_tree_add_text (tree, tvb, offset+12, 4, "Block Length: %u",
1954                                  tvb_get_ntohl (tvb, offset+12));
1955             offset += 16;        /* increment the offset by 8 */
1956             tot_len -= 16;       /* subtract by the block desc len */
1957         }
1958         /* offset points to the start of the mode page */
1959         while ((tot_len > offset) && tvb_bytes_exist (tvb, offset, 2)) {
1960             offset += dissect_scsi_modepage (tvb, pinfo, tree, offset);
1961         }
1962     }
1963 }
1964
1965 static void
1966 dissect_scsi_modesense6 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1967                          guint offset, gboolean isreq, gboolean iscdb,
1968                          guint payload_len)
1969 {
1970     guint8 flags;
1971     guint tot_len, desclen;
1972     
1973     if (!tree)
1974         return;
1975     
1976     if (isreq && iscdb) {
1977         flags = tvb_get_guint8 (tvb, offset);
1978         
1979         proto_tree_add_uint_format (tree, hf_scsi_modesns_flags, tvb, offset, 1,
1980                                     flags, "DBD = %u", flags & 0x8);
1981         proto_tree_add_item (tree, hf_scsi_modesns_pc, tvb, offset+1, 1, 0);
1982         proto_tree_add_item (tree, hf_scsi_modesns_pagecode, tvb, offset+1, 1,
1983                              0);
1984         proto_tree_add_item (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
1985
1986         flags = tvb_get_guint8 (tvb, offset+4);
1987         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
1988                                     flags,
1989                                     "Vendor Unique = %u, NACA = %u, Link = %u",
1990                                     flags & 0xC0, flags & 0x4, flags & 0x1);
1991     }
1992     else {
1993         /* Mode sense response has the following format:
1994          * Mode Parameter Header
1995          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
1996          *      Blk Desc Len
1997          * Block Descriptor (s)
1998          *    - Number of blocks, density code, block length
1999          * Page (s)
2000          *    - Page code, Page length, Page Parameters
2001          */
2002         tot_len = tvb_get_guint8 (tvb, offset);
2003         proto_tree_add_text (tree, tvb, offset, 1, "Mode Data Length: %u",
2004                              tot_len);
2005         proto_tree_add_text (tree, tvb, offset+1, 1, "Medium Type: 0x%02x",
2006                              tvb_get_guint8 (tvb, offset+1));
2007         proto_tree_add_text (tree, tvb, offset+2, 1,
2008                              "Device-Specific Parameter: 0x%02x",
2009                              tvb_get_guint8 (tvb, offset+2));
2010         desclen = tvb_get_guint8 (tvb, offset+3);
2011         proto_tree_add_text (tree, tvb, offset+3, 1,
2012                              "Block Descriptor Length: %u", desclen);
2013         offset = 4;
2014         /* The actual payload is the min of the length in the response & the
2015          * space allocated by the initiator as specified in the request.
2016          */
2017         if (payload_len && (tot_len > payload_len))
2018             tot_len = payload_len;
2019         if (desclen) {
2020             proto_tree_add_text (tree, tvb, offset, 4, "No. of Blocks: %u",
2021                                  tvb_get_ntohl (tvb, offset));
2022             proto_tree_add_text (tree, tvb, offset+4, 1, "Density Code: 0x%02x",
2023                                  tvb_get_guint8 (tvb, offset+4));
2024             proto_tree_add_text (tree, tvb, offset+5, 3, "Block Length: %u",
2025                                  tvb_get_ntoh24 (tvb, offset+5));
2026             offset += 8;        /* increment the offset by 8 */
2027         }
2028         /* offset points to the start of the mode page */
2029         while ((tot_len > offset) && tvb_bytes_exist (tvb, offset, 2)) {
2030             offset += dissect_scsi_modepage (tvb, pinfo, tree, offset);
2031         }
2032     }
2033 }
2034
2035 static void
2036 dissect_scsi_modesense10 (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2037                           guint offset, gboolean isreq, gboolean iscdb,
2038                           guint payload_len)
2039 {
2040     guint8 flags;
2041     gboolean longlba;
2042     guint tot_len, desclen;
2043  
2044     if (!tree)
2045         return;
2046     
2047     if (isreq && iscdb) {
2048         flags = tvb_get_guint8 (tvb, offset);
2049         
2050         proto_tree_add_uint_format (tree, hf_scsi_modesns_flags, tvb, offset, 1,
2051                                     flags, "LLBAA = %u, DBD = %u", flags & 0x10,
2052                                     flags & 0x8);
2053         proto_tree_add_item (tree, hf_scsi_modesns_pc, tvb, offset+1, 1, 0);
2054         proto_tree_add_item (tree, hf_scsi_modesns_pagecode, tvb, offset+1, 1,
2055                              0);
2056         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
2057
2058         flags = tvb_get_guint8 (tvb, offset+8);
2059         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2060                                     flags,
2061                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2062                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2063     }
2064     else {
2065         /* Mode sense response has the following format:
2066          * Mode Parameter Header
2067          *    - Mode Data Len, Medium Type, Dev Specific Parameter,
2068          *      Blk Desc Len
2069          * Block Descriptor (s)
2070          *    - Number of blocks, density code, block length
2071          * Page (s)
2072          *    - Page code, Page length, Page Parameters
2073          */
2074         tot_len = tvb_get_ntohs (tvb, offset);
2075         proto_tree_add_text (tree, tvb, offset, 2, "Mode Data Length: %u",
2076                              tot_len);
2077         proto_tree_add_text (tree, tvb, offset+2, 1, "Medium Type: 0x%02x",
2078                              tvb_get_guint8 (tvb, offset+2));
2079         proto_tree_add_text (tree, tvb, offset+3, 1,
2080                              "Device-Specific Parameter: 0x%02x",
2081                              tvb_get_guint8 (tvb, offset+3));
2082         longlba = tvb_get_guint8 (tvb, offset+4) & 0x1;
2083         proto_tree_add_text (tree, tvb, offset+4, 1, "LongLBA: %u", longlba);
2084         desclen = tvb_get_guint8 (tvb, offset+6);
2085         proto_tree_add_text (tree, tvb, offset+6, 1,
2086                              "Block Descriptor Length: %u", desclen);
2087         offset = 8;
2088
2089         if (payload_len && (tot_len > payload_len))
2090             tot_len = payload_len;
2091
2092         if (desclen) {
2093             proto_tree_add_text (tree, tvb, offset, 8, "No. of Blocks: %s",
2094                                  bytes_to_str (tvb_get_ptr (tvb, offset, 8),
2095                                                8));
2096             proto_tree_add_text (tree, tvb, offset+8, 1, "Density Code: 0x%02x",
2097                                  tvb_get_guint8 (tvb, offset+4));
2098             proto_tree_add_text (tree, tvb, offset+12, 4, "Block Length: %u",
2099                                  tvb_get_ntohl (tvb, offset+12));
2100             offset += 16;        /* increment the offset by 8 */
2101             tot_len -= 16;       /* subtract by the block desc len */
2102         }
2103         /* offset points to the start of the mode page */
2104         while ((tot_len > offset) && tvb_bytes_exist (tvb, offset, 2)) {
2105             offset += dissect_scsi_modepage (tvb, pinfo, tree, offset);
2106         }
2107     }
2108 }
2109
2110 static void
2111 dissect_scsi_persresvin (tvbuff_t *tvb, packet_info *pinfo _U_,
2112                          proto_tree *tree, guint offset, gboolean isreq,
2113                          gboolean iscdb, scsi_task_data_t *cdata,
2114                          guint payload_len)
2115 {
2116     guint8 flags;
2117     int numrec, i;
2118     guint len;
2119
2120     if (!tree)
2121         return;
2122     
2123     if (isreq && iscdb) {
2124         proto_tree_add_item (tree, hf_scsi_persresvin_svcaction, tvb, offset+1,
2125                              1, 0);
2126         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
2127
2128         flags = tvb_get_guint8 (tvb, offset+8);
2129         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2130                                     flags,
2131                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2132                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2133         /* We store the service action since we want to interpret the data */
2134         cdata->flags = tvb_get_guint8 (tvb, offset+1);
2135     }
2136     else {
2137         if (cdata) {
2138             flags = cdata->flags;
2139         }
2140         else {
2141             flags = 0xFF;
2142         }
2143         proto_tree_add_text (tree, tvb, offset, 4, "Generation Number: 0x%08x",
2144                              tvb_get_ntohl (tvb, offset));
2145         len = tvb_get_ntohl (tvb, offset+4);
2146         proto_tree_add_text (tree, tvb, offset, 4, "Additional Length: %u",
2147                              len);
2148         len = (payload_len > len) ? len : payload_len;
2149         
2150         if ((flags & 0x1F) == SCSI_SPC2_RESVIN_SVCA_RDKEYS) {
2151             /* XXX - what if len is < 8?  That may be illegal, but
2152                that doesn't make it impossible.... */
2153             numrec = (len - 8)/8;
2154             offset += 8;
2155             
2156             for (i = 0; i < numrec; i++) {
2157                 proto_tree_add_item (tree, hf_scsi_persresv_key, tvb, offset,
2158                                      8, 0);
2159                 offset -= 8;
2160             }
2161         }
2162         else if ((flags & 0x1F) == SCSI_SPC2_RESVIN_SVCA_RDRESV) {
2163             proto_tree_add_item (tree, hf_scsi_persresv_key, tvb, offset+8,
2164                                  8, 0);
2165             proto_tree_add_item (tree, hf_scsi_persresv_scopeaddr, tvb,
2166                                  offset+8, 4, 0);
2167             proto_tree_add_item (tree, hf_scsi_persresv_scope, tvb, offset+13,
2168                                  1, 0);
2169             proto_tree_add_item (tree, hf_scsi_persresv_type, tvb, offset+13,
2170                                  1, 0);
2171         }
2172     }
2173 }
2174
2175 static void
2176 dissect_scsi_persresvout (tvbuff_t *tvb, packet_info *pinfo _U_,
2177                           proto_tree *tree, guint offset, gboolean isreq,
2178                           gboolean iscdb, scsi_task_data_t *cdata _U_,
2179                           guint payload_len _U_)
2180 {
2181     guint8 flags;
2182
2183     if (!tree)
2184         return;
2185     
2186     if (isreq && iscdb) {
2187         proto_tree_add_item (tree, hf_scsi_persresvin_svcaction, tvb, offset,
2188                              1, 0);
2189         proto_tree_add_item (tree, hf_scsi_persresv_scope, tvb, offset+1, 1, 0);
2190         proto_tree_add_item (tree, hf_scsi_persresv_type, tvb, offset+1, 1, 0);
2191         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
2192
2193         flags = tvb_get_guint8 (tvb, offset+8);
2194         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2195                                     flags,
2196                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2197                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2198     }
2199     else {
2200     }
2201 }
2202
2203 static void
2204 dissect_scsi_release6 (tvbuff_t *tvb, packet_info *pinfo _U_,
2205                        proto_tree *tree, guint offset, gboolean isreq,
2206                        gboolean iscdb)
2207 {
2208     guint8 flags;
2209
2210     if (!tree)
2211         return;
2212     
2213     if (isreq && iscdb) {
2214         flags = tvb_get_guint8 (tvb, offset+4);
2215         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
2216                                     flags,
2217                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2218                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2219     }
2220 }
2221
2222 static void
2223 dissect_scsi_release10 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, 
2224                         guint offset, gboolean isreq, gboolean iscdb)
2225 {
2226     guint8 flags;
2227
2228     if (!tree)
2229         return;
2230     
2231     if (isreq && iscdb) {
2232         flags = tvb_get_guint8 (tvb, offset);
2233
2234         proto_tree_add_uint_format (tree, hf_scsi_release_flags, tvb, offset, 1,
2235                                     flags,
2236                                     "Flags: 3rd Party ID = %u, LongID = %u",
2237                                     flags & 0x10, flags & 0x2);
2238         if ((flags & 0x12) == 0x10) {
2239             proto_tree_add_item (tree, hf_scsi_release_thirdpartyid, tvb,
2240                                  offset+2, 1, 0);
2241         }
2242         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
2243
2244         flags = tvb_get_guint8 (tvb, offset+8);
2245         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2246                                     flags,
2247                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2248                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2249     }
2250 }
2251
2252 static void
2253 dissect_scsi_reportdeviceid (tvbuff_t *tvb _U_, packet_info *pinfo _U_,
2254                              proto_tree *tree _U_, guint offset _U_,
2255                              gboolean isreq _U_, gboolean iscdb _U_)
2256 {
2257     
2258 }
2259
2260 static void
2261 dissect_scsi_reportluns (tvbuff_t *tvb, packet_info *pinfo _U_,
2262                          proto_tree *tree, guint offset, gboolean isreq,
2263                          gboolean iscdb)
2264 {
2265     guint8 flags;
2266     guint numelem, i;
2267
2268     if (!tree)
2269         return;
2270     
2271     if (isreq && iscdb) {
2272         proto_tree_add_item (tree, hf_scsi_alloclen32, tvb, offset+5, 4, 0);
2273
2274         flags = tvb_get_guint8 (tvb, offset+10);
2275         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
2276                                     flags,
2277                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2278                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2279     }
2280     else if (!isreq) {
2281         numelem = tvb_get_ntohl (tvb, offset);
2282         proto_tree_add_text (tree, tvb, offset, 4, "LUN List Length: %u",
2283                              numelem);
2284         offset += 8;
2285         for (i = 0; i < numelem/8; i++) {
2286             if (!tvb_get_guint8 (tvb, offset))
2287                 proto_tree_add_item (tree, hf_scsi_rluns_lun, tvb, offset+1, 1,
2288                                      0);
2289             else
2290                 proto_tree_add_item (tree, hf_scsi_rluns_multilun, tvb, offset,
2291                                      8, 0);
2292             offset += 8;
2293         }
2294     }
2295 }
2296
2297 static void
2298 dissect_scsi_reqsense (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2299                        guint offset, gboolean isreq, gboolean iscdb)
2300 {
2301     guint8 flags;
2302
2303     if (!tree)
2304         return;
2305     
2306     if (isreq && iscdb) {
2307         proto_tree_add_item (tree, hf_scsi_alloclen, tvb, offset+3, 1, 0);
2308
2309         flags = tvb_get_guint8 (tvb, offset+4);
2310         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
2311                                     flags,
2312                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2313                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2314     }
2315 }
2316
2317 static void
2318 dissect_scsi_reserve6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2319                        guint offset, gboolean isreq, gboolean iscdb)
2320 {
2321     guint8 flags;
2322
2323     if (!tree)
2324         return;
2325     
2326     if (isreq && iscdb) {
2327         flags = tvb_get_guint8 (tvb, offset+4);
2328         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
2329                                     flags,
2330                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2331                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2332     }
2333 }
2334
2335 static void
2336 dissect_scsi_reserve10 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2337                         guint offset, gboolean isreq, gboolean iscdb)
2338 {
2339     guint8 flags;
2340
2341     if (!tree)
2342         return;
2343     
2344     if (isreq && iscdb) {
2345         flags = tvb_get_guint8 (tvb, offset);
2346
2347         proto_tree_add_uint_format (tree, hf_scsi_release_flags, tvb, offset, 1,
2348                                     flags,
2349                                     "Flags: 3rd Party ID = %u, LongID = %u",
2350                                     flags & 0x10, flags & 0x2);
2351         if ((flags & 0x12) == 0x10) {
2352             proto_tree_add_item (tree, hf_scsi_release_thirdpartyid, tvb,
2353                                  offset+2, 1, 0);
2354         }
2355         proto_tree_add_item (tree, hf_scsi_paramlen16, tvb, offset+6, 2, 0);
2356
2357         flags = tvb_get_guint8 (tvb, offset+8);
2358         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2359                                     flags,
2360                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2361                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2362     }
2363 }
2364
2365 static void
2366 dissect_scsi_testunitrdy (tvbuff_t *tvb, packet_info *pinfo _U_,
2367                           proto_tree *tree, guint offset, gboolean isreq,
2368                           gboolean iscdb)
2369 {
2370     guint8 flags;
2371
2372     if (!tree)
2373         return;
2374     
2375     if (isreq && iscdb) {
2376         flags = tvb_get_guint8 (tvb, offset+4);
2377         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
2378                                     flags,
2379                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2380                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2381     }
2382 }
2383
2384 static void
2385 dissect_scsi_formatunit (tvbuff_t *tvb, packet_info *pinfo _U_,
2386                          proto_tree *tree, guint offset, gboolean isreq,
2387                          gboolean iscdb)
2388 {
2389     guint8 flags;
2390
2391     if (!tree)
2392         return;
2393     
2394     if (isreq && iscdb) {
2395         flags = tvb_get_guint8 (tvb, offset);
2396         proto_tree_add_uint_format (tree, hf_scsi_formatunit_flags, tvb, offset,
2397                                     1, flags,
2398                                     "Flags: Longlist = %u, FMTDATA = %u, CMPLIST = %u",
2399                                     flags & 0x20, flags & 0x8, flags & 0x4);
2400         proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
2401         proto_tree_add_item (tree, hf_scsi_formatunit_vendor, tvb, offset+1,
2402                              1, 0);
2403         proto_tree_add_item (tree, hf_scsi_formatunit_interleave, tvb, offset+2,
2404                              2, 0);
2405         flags = tvb_get_guint8 (tvb, offset+4);
2406         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
2407                                     flags,
2408                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2409                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2410     }
2411 }
2412
2413 static void
2414 dissect_scsi_rdwr6 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2415                     guint offset, gboolean isreq, gboolean iscdb)
2416 {
2417     guint8 flags;
2418
2419     if (isreq) {
2420         if (check_col (pinfo->cinfo, COL_INFO))
2421             col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%06x, Len: %u)",
2422                              tvb_get_ntoh24 (tvb, offset),
2423                              tvb_get_guint8 (tvb, offset+3));
2424     }
2425     
2426     if (tree && isreq && iscdb) {
2427         proto_tree_add_item (tree, hf_scsi_rdwr6_lba, tvb, offset, 3, 0);
2428         proto_tree_add_item (tree, hf_scsi_rdwr6_xferlen, tvb, offset+3, 1, 0);
2429         flags = tvb_get_guint8 (tvb, offset+4);
2430         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
2431                                     flags,
2432                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2433                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2434     }
2435 }
2436
2437 static void
2438 dissect_scsi_rdwr10 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2439                      guint offset, gboolean isreq, gboolean iscdb)
2440 {
2441     guint8 flags;
2442
2443     if (isreq) {
2444         if (check_col (pinfo->cinfo, COL_INFO))
2445             col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%08x, Len: %u)",
2446                              tvb_get_ntohl (tvb, offset+1),
2447                              tvb_get_ntohs (tvb, offset+6));
2448     }
2449
2450     if (tree && isreq && iscdb) {
2451         flags = tvb_get_guint8 (tvb, offset);
2452
2453         proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
2454                                     flags,
2455                                     "DPO = %u, FUA = %u, RelAddr = %u",
2456                                     flags & 0x10, flags & 0x8, flags & 0x1);
2457         proto_tree_add_item (tree, hf_scsi_rdwr10_lba, tvb, offset+1, 4, 0);
2458         proto_tree_add_item (tree, hf_scsi_rdwr10_xferlen, tvb, offset+6, 2, 0);
2459         flags = tvb_get_guint8 (tvb, offset+8);
2460         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2461                                     flags,
2462                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2463                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2464     }
2465 }
2466
2467 static void
2468 dissect_scsi_rdwr12 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2469                      guint offset, gboolean isreq, gboolean iscdb)
2470 {
2471     guint8 flags;
2472
2473     if (isreq) {
2474         if (check_col (pinfo->cinfo, COL_INFO))
2475             col_append_fstr (pinfo->cinfo, COL_INFO, "(LBA: 0x%08x, Len: %u)",
2476                              tvb_get_ntohl (tvb, offset+1),
2477                              tvb_get_ntohl (tvb, offset+5));
2478     }
2479
2480     if (tree && isreq && iscdb) {
2481         flags = tvb_get_guint8 (tvb, offset);
2482
2483         proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
2484                                     flags,
2485                                     "DPO = %u, FUA = %u, RelAddr = %u",
2486                                     flags & 0x10, flags & 0x8, flags & 0x1);
2487         proto_tree_add_item (tree, hf_scsi_rdwr10_lba, tvb, offset+1, 4, 0);
2488         proto_tree_add_item (tree, hf_scsi_rdwr12_xferlen, tvb, offset+5, 4, 0);
2489         flags = tvb_get_guint8 (tvb, offset+10);
2490         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
2491                                     flags,
2492                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2493                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2494     }
2495 }
2496
2497 static void
2498 dissect_scsi_rdwr16 (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2499                      guint offset, gboolean isreq, gboolean iscdb)
2500 {
2501     guint8 flags;
2502
2503     if (tree && isreq && iscdb) {
2504         flags = tvb_get_guint8 (tvb, offset);
2505
2506         proto_tree_add_uint_format (tree, hf_scsi_read_flags, tvb, offset, 1,
2507                                     flags,
2508                                     "DPO = %u, FUA = %u, RelAddr = %u",
2509                                     flags & 0x10, flags & 0x8, flags & 0x1);
2510         proto_tree_add_item (tree, hf_scsi_rdwr16_lba, tvb, offset+1, 8, 0);
2511         proto_tree_add_item (tree, hf_scsi_rdwr12_xferlen, tvb, offset+9, 4, 0);
2512         flags = tvb_get_guint8 (tvb, offset+14);
2513         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+14, 1,
2514                                     flags,
2515                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2516                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2517     }
2518 }
2519
2520 static void
2521 dissect_scsi_readcapacity (tvbuff_t *tvb, packet_info *pinfo _U_,
2522                            proto_tree *tree, guint offset, gboolean isreq,
2523                            gboolean iscdb)
2524 {
2525     guint8 flags;
2526     guint len;
2527
2528     if (!tree)
2529         return;
2530     
2531     if (isreq && iscdb) {
2532         flags = tvb_get_guint8 (tvb, offset);
2533
2534         proto_tree_add_uint_format (tree, hf_scsi_readcapacity_flags, tvb,
2535                                     offset, 1, flags,
2536                                     "LongLBA = %u, RelAddr = %u", 
2537                                     flags & 0x2, flags & 0x1);
2538         proto_tree_add_item (tree, hf_scsi_readcapacity_lba, tvb, offset+1,
2539                              4, 0);
2540         proto_tree_add_item (tree, hf_scsi_readcapacity_pmi, tvb, offset+7,
2541                              1, 0);
2542
2543         flags = tvb_get_guint8 (tvb, offset+8);
2544         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2545                                     flags,
2546                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2547                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2548     }
2549     else if (!iscdb) {
2550         len = tvb_get_ntohl (tvb, offset);
2551         proto_tree_add_text (tree, tvb, offset, 4, "LBA: %u (%u MB)",
2552                              len, len/(1024*1024));
2553         proto_tree_add_text (tree, tvb, offset+4, 4, "Block Length: %u bytes",
2554                              tvb_get_ntohl (tvb, offset+4));
2555     }
2556 }
2557
2558 static void
2559 dissect_scsi_readdefdata10 (tvbuff_t *tvb, packet_info *pinfo _U_,
2560                             proto_tree *tree, guint offset, gboolean isreq,
2561                             gboolean iscdb)
2562 {
2563     guint8 flags;
2564
2565     if (!tree)
2566         return;
2567     
2568     if (isreq && iscdb) {
2569         flags = tvb_get_guint8 (tvb, offset);
2570
2571         proto_tree_add_uint_format (tree, hf_scsi_readdefdata_flags, tvb,
2572                                     offset, 1, flags, "PLIST = %u, GLIST = %u",
2573                                     flags & 0x10, flags & 0x8);
2574         proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
2575         proto_tree_add_item (tree, hf_scsi_alloclen16, tvb, offset+6, 2, 0);
2576         flags = tvb_get_guint8 (tvb, offset+8);
2577         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+8, 1,
2578                                     flags,
2579                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2580                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2581     }
2582 }
2583
2584 static void
2585 dissect_scsi_readdefdata12 (tvbuff_t *tvb, packet_info *pinfo _U_,
2586                             proto_tree *tree, guint offset, gboolean isreq,
2587                             gboolean iscdb)
2588 {
2589     guint8 flags;
2590
2591     if (!tree)
2592         return;
2593     
2594     if (isreq && iscdb) {
2595         flags = tvb_get_guint8 (tvb, offset);
2596
2597         proto_tree_add_uint_format (tree, hf_scsi_readdefdata_flags, tvb,
2598                                     offset, 1, flags, "PLIST = %u, GLIST = %u",
2599                                     flags & 0x10, flags & 0x8);
2600         proto_tree_add_item (tree, hf_scsi_cdb_defectfmt, tvb, offset, 1, 0);
2601         proto_tree_add_item (tree, hf_scsi_alloclen32, tvb, offset+5, 4, 0);
2602         flags = tvb_get_guint8 (tvb, offset+10);
2603         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+10, 1,
2604                                     flags,
2605                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2606                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2607     }
2608 }
2609
2610 static void
2611 dissect_scsi_reassignblks (tvbuff_t *tvb, packet_info *pinfo _U_,
2612                            proto_tree *tree, guint offset, gboolean isreq,
2613                            gboolean iscdb)
2614 {
2615     guint8 flags;
2616
2617     if (!tree)
2618         return;
2619     
2620     if (isreq && iscdb) {
2621         flags = tvb_get_guint8 (tvb, offset);
2622
2623         proto_tree_add_uint_format (tree, hf_scsi_reassignblks_flags, tvb,
2624                                     offset, 1, flags,
2625                                     "LongLBA = %u, LongList = %u",
2626                                     flags & 0x2, flags & 0x1);
2627         flags = tvb_get_guint8 (tvb, offset+4);
2628         proto_tree_add_uint_format (tree, hf_scsi_control, tvb, offset+4, 1,
2629                                     flags,
2630                                     "Vendor Unique = %u, NACA = %u, Link = %u",
2631                                     flags & 0xC0, flags & 0x4, flags & 0x1);
2632     }
2633 }
2634
2635 static void
2636 dissect_scsi_varlencdb (tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree,
2637                         guint offset, gboolean isreq, gboolean iscdb)
2638 {
2639     if (!tree)
2640         return;
2641     
2642     if (isreq && iscdb) {
2643         proto_tree_add_item (tree, hf_scsi_control, tvb, offset, 1, 0);
2644         proto_tree_add_item (tree, hf_scsi_add_cdblen, tvb, offset+6, 1, 0);
2645         proto_tree_add_item (tree, hf_scsi_svcaction, tvb, offset+7, 2, 0);
2646
2647     }
2648 }
2649
2650 void
2651 dissect_scsi_rsp (tvbuff_t *tvb _U_, packet_info *pinfo _U_,
2652                   proto_tree *tree _U_)
2653 {
2654     /* Nothing to do here, just blow up the data structures for this SCSI
2655      * transaction
2656     if (tree)
2657         scsi_end_task (pinfo);
2658      */
2659 }
2660
2661 void
2662 dissect_scsi_snsinfo (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2663                       guint offset, guint snslen)
2664 {
2665     guint8 flags;
2666     proto_item *ti;
2667     proto_tree *sns_tree;
2668
2669     scsi_end_task (pinfo);
2670     
2671     if (tree) {
2672         ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
2673                                              snslen, "SCSI: SNS Info");
2674         sns_tree = proto_item_add_subtree (ti, ett_scsi);
2675
2676         flags = tvb_get_guint8 (tvb, offset);
2677         proto_tree_add_text (sns_tree, tvb, offset, 1, "Valid: %u",
2678                              (flags & 0x80) >> 7);
2679         proto_tree_add_item (sns_tree, hf_scsi_sns_errtype, tvb, offset, 1, 0);
2680         flags = tvb_get_guint8 (tvb, offset+2);
2681         proto_tree_add_text (sns_tree, tvb, offset+2, 1,
2682                              "Filemark: %u, EOM: %u, ILI: %u",
2683                              (flags & 0x80) >> 7, (flags & 0x40) >> 6,
2684                              (flags & 0x20) >> 5);
2685         proto_tree_add_item (sns_tree, hf_scsi_snskey, tvb, offset+2, 1, 0);
2686         proto_tree_add_item (sns_tree, hf_scsi_snsinfo, tvb, offset+3, 4, 0);
2687         proto_tree_add_item (sns_tree, hf_scsi_addlsnslen, tvb, offset+7, 1, 0);
2688         proto_tree_add_text (sns_tree, tvb, offset+8, 4,
2689                              "Command-Specific Information: %s",
2690                              tvb_bytes_to_str (tvb, offset+8, 4));
2691         proto_tree_add_item (sns_tree, hf_scsi_ascascq, tvb, offset+12, 2, 0);
2692         proto_tree_add_item_hidden (sns_tree, hf_scsi_asc, tvb, offset+12, 1, 0);
2693         proto_tree_add_item_hidden (sns_tree, hf_scsi_ascq, tvb, offset+13,
2694                                     1, 0);
2695         proto_tree_add_item (sns_tree, hf_scsi_fru, tvb, offset+14, 1, 0);
2696         proto_tree_add_item (sns_tree, hf_scsi_sksv, tvb, offset+15, 1, 0);
2697         proto_tree_add_text (sns_tree, tvb, offset+15, 3,
2698                              "Sense Key Specific: %s",
2699                              tvb_bytes_to_str (tvb, offset+15, 3));
2700     }
2701 }
2702
2703 void
2704 dissect_scsi_cdb (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2705                   guint start, guint cdblen)
2706 {
2707     int offset = start;
2708     proto_item *ti;
2709     proto_tree *scsi_tree = NULL;
2710     guint8 opcode;
2711     scsi_cmnd_type cmd = 0;     /* 0 is undefined type */
2712     scsi_device_type devtype = 0;
2713     gchar *valstr;
2714     scsi_task_data_t *cdata;
2715     scsi_devtype_key_t dkey;
2716     scsi_devtype_data_t *devdata;
2717     
2718     opcode = tvb_get_guint8 (tvb, offset);
2719
2720     /* Identify target if possible */
2721     COPY_ADDRESS (&(dkey.devid), &pinfo->dst);
2722
2723     devdata = (scsi_devtype_data_t *)g_hash_table_lookup (scsidev_req_hash,
2724                                                           &dkey);
2725     if (devdata != NULL) {
2726         devtype = devdata->devtype;
2727     }
2728     else {
2729         devtype = (scsi_device_type)scsi_def_devtype;
2730     }
2731
2732     if ((valstr = match_strval (opcode, scsi_spc2_val)) == NULL) {
2733         if (devtype == SCSI_DEV_SBC) {
2734             valstr = match_strval (opcode, scsi_sbc2_val);
2735             cmd = SCSI_CMND_SBC2;
2736         }
2737         else {
2738             /* Right now, the only choices are SBC or SSC. If we ever expand
2739              * this to decode other device types, this piece of code needs to
2740              * be modified.
2741              */
2742             valstr = match_strval (opcode, scsi_ssc2_val);
2743             cmd = SCSI_CMND_SSC2;
2744         }
2745     }
2746     else {
2747         cmd = SCSI_CMND_SPC2;
2748     }
2749     
2750     if (valstr != NULL) {
2751         if (check_col (pinfo->cinfo, COL_INFO)) {
2752             col_add_fstr (pinfo->cinfo, COL_INFO, "SCSI: %s", valstr);
2753         }
2754     }
2755     else {
2756         if (check_col (pinfo->cinfo, COL_INFO)) {
2757             col_add_fstr (pinfo->cinfo, COL_INFO, "SCSI Command: 0x%02x", opcode);
2758         }
2759     }
2760
2761     cdata = scsi_new_task (pinfo);
2762
2763     if (cdata) {
2764         cdata->opcode = opcode;
2765         cdata->devtype = cmd;
2766     }
2767     
2768     if (tree) {
2769         ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, start,
2770                                              cdblen, "SCSI CDB");
2771         scsi_tree = proto_item_add_subtree (ti, ett_scsi);
2772
2773         if (valstr != NULL) {
2774             if (cmd == SCSI_CMND_SPC2) {
2775                 proto_tree_add_uint_format (scsi_tree, hf_scsi_spcopcode, tvb,
2776                                             offset, 1,
2777                                             tvb_get_guint8 (tvb, offset),
2778                                             "Opcode: %s (0x%02x)", valstr,
2779                                             opcode);
2780             }
2781             else if (cmd == SCSI_CMND_SBC2) {
2782                 proto_tree_add_uint_format (scsi_tree, hf_scsi_sbcopcode, tvb,
2783                                             offset, 1,
2784                                             tvb_get_guint8 (tvb, offset),
2785                                             "Opcode: %s (0x%02x)", valstr,
2786                                             opcode);
2787             }
2788             else {
2789                  proto_tree_add_uint_format (scsi_tree, hf_scsi_sscopcode, tvb,
2790                                              offset, 1,
2791                                              tvb_get_guint8 (tvb, offset),
2792                                              "Opcode: %s (0x%02x)", valstr,
2793                                              opcode);
2794             }
2795         }
2796         else {
2797             proto_tree_add_item (scsi_tree, hf_scsi_sbcopcode, tvb, offset, 1, 0);
2798         }
2799     }
2800         
2801     if (cmd == SCSI_CMND_SPC2) {
2802         switch (opcode) {
2803         case SCSI_SPC2_INQUIRY:
2804             dissect_scsi_inquiry (tvb, pinfo, scsi_tree, offset+1, TRUE,
2805                                   TRUE, 0, cdata);
2806             break;
2807
2808         case SCSI_SPC2_EXTCOPY:
2809             dissect_scsi_extcopy (tvb, pinfo, scsi_tree, offset+1, TRUE,
2810                                   TRUE);
2811             break;
2812
2813         case SCSI_SPC2_LOGSELECT:
2814             dissect_scsi_logselect (tvb, pinfo, scsi_tree, offset+1, TRUE,
2815                                     TRUE);
2816             break;
2817
2818         case SCSI_SPC2_LOGSENSE:
2819             dissect_scsi_logsense (tvb, pinfo, scsi_tree, offset+1, TRUE,
2820                                    TRUE);
2821             break;
2822
2823         case SCSI_SPC2_MODESELECT6:
2824             dissect_scsi_modeselect6 (tvb, pinfo, scsi_tree, offset+1,
2825                                       TRUE, TRUE, 0);
2826             break;
2827
2828         case SCSI_SPC2_MODESELECT10:
2829             dissect_scsi_modeselect10 (tvb, pinfo, scsi_tree, offset+1,
2830                                        TRUE, TRUE, 0);
2831             break;
2832
2833         case SCSI_SPC2_MODESENSE6:
2834             dissect_scsi_modesense6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2835                                      TRUE, 0);
2836             break;
2837
2838         case SCSI_SPC2_MODESENSE10:
2839             dissect_scsi_modesense10 (tvb, pinfo, scsi_tree, offset+1,
2840                                       TRUE, TRUE, 0);
2841             break;
2842
2843         case SCSI_SPC2_PERSRESVIN:
2844             dissect_scsi_persresvin (tvb, pinfo, scsi_tree, offset+1, TRUE,
2845                                      TRUE, cdata, 0);
2846             break;
2847
2848         case SCSI_SPC2_PERSRESVOUT:
2849             dissect_scsi_persresvout (tvb, pinfo, scsi_tree, offset+1,
2850                                       TRUE, TRUE, cdata, 0);
2851             break;
2852
2853         case SCSI_SPC2_RELEASE6:
2854             dissect_scsi_release6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2855                                    TRUE);
2856             break;
2857
2858         case SCSI_SPC2_RELEASE10:
2859             dissect_scsi_release10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2860                                     TRUE);
2861             break;
2862
2863         case SCSI_SPC2_REPORTDEVICEID:
2864             dissect_scsi_reportdeviceid (tvb, pinfo, scsi_tree, offset+1,
2865                                          TRUE, TRUE);
2866             break;
2867
2868         case SCSI_SPC2_REPORTLUNS:
2869             dissect_scsi_reportluns (tvb, pinfo, scsi_tree, offset+1, TRUE,
2870                                      TRUE);
2871             break;
2872
2873         case SCSI_SPC2_REQSENSE:
2874             dissect_scsi_reqsense (tvb, pinfo, scsi_tree, offset+1, TRUE,
2875                                    TRUE);
2876             break;
2877
2878         case SCSI_SPC2_RESERVE6:
2879             dissect_scsi_reserve6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2880                                    TRUE);
2881             break;
2882
2883         case SCSI_SPC2_RESERVE10:
2884             dissect_scsi_reserve10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2885                                     TRUE);
2886             break;
2887
2888         case SCSI_SPC2_TESTUNITRDY:
2889             dissect_scsi_testunitrdy (tvb, pinfo, scsi_tree, offset+1,
2890                                       TRUE, TRUE);
2891             break;
2892
2893         case SCSI_SPC2_VARLENCDB:
2894             dissect_scsi_varlencdb (tvb, pinfo, scsi_tree, offset+1,
2895                                     TRUE, TRUE);
2896             break;
2897
2898         default:
2899             call_dissector (data_handle, tvb, pinfo, scsi_tree);
2900             break;
2901         }
2902     }
2903     else if (cmd == SCSI_CMND_SBC2) {
2904         switch (opcode) {
2905
2906         case SCSI_SBC2_FORMATUNIT:
2907             dissect_scsi_formatunit (tvb, pinfo, scsi_tree, offset+1, TRUE,
2908                                      TRUE);
2909             break;
2910
2911         case SCSI_SBC2_READ6:
2912             dissect_scsi_rdwr6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2913                                 TRUE);
2914             break;
2915
2916         case SCSI_SBC2_READ10:
2917             dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2918                                  TRUE);
2919             break;
2920
2921         case SCSI_SBC2_READ12:
2922             dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2923                                  TRUE);
2924             break;
2925
2926         case SCSI_SBC2_READ16:
2927             dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2928                                  TRUE);
2929             break;
2930
2931         case SCSI_SBC2_READCAPACITY:
2932             dissect_scsi_readcapacity (tvb, pinfo, scsi_tree, offset+1,
2933                                        TRUE, TRUE);
2934             break;
2935
2936         case SCSI_SBC2_READDEFDATA10:
2937             dissect_scsi_readdefdata10 (tvb, pinfo, scsi_tree, offset+1,
2938                                         TRUE, TRUE);
2939             break;
2940
2941         case SCSI_SBC2_READDEFDATA12:
2942             dissect_scsi_readdefdata12 (tvb, pinfo, scsi_tree, offset+1,
2943                                         TRUE, TRUE);
2944             break;
2945
2946         case SCSI_SBC2_REASSIGNBLKS:
2947             dissect_scsi_reassignblks (tvb, pinfo, scsi_tree, offset+1,
2948                                        TRUE, TRUE);
2949             break;
2950
2951         case SCSI_SBC2_WRITE6:
2952             dissect_scsi_rdwr6 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2953                                 TRUE);
2954             break;
2955
2956         case SCSI_SBC2_WRITE10:
2957             dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2958                                  TRUE);
2959             break;
2960
2961         case SCSI_SBC2_WRITE12:
2962             dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2963                                  TRUE);
2964             break;
2965
2966         case SCSI_SBC2_WRITE16:
2967             dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset+1, TRUE,
2968                                  TRUE);
2969             break;
2970
2971         default:
2972             call_dissector (data_handle, tvb, pinfo, scsi_tree);
2973             break;
2974         }
2975     }
2976     else if (cmd == SCSI_CMND_SSC2) {
2977         call_dissector (data_handle, tvb, pinfo, scsi_tree);
2978     }
2979 }
2980
2981 static void
2982 dissect_scsi (tvbuff_t *tvb _U_, packet_info *pinfo _U_, proto_tree *tree _U_)
2983 {
2984 }
2985
2986 void
2987 dissect_scsi_payload (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
2988                       guint offset, gboolean isreq, guint32 payload_len)
2989 {
2990     proto_item *ti;
2991     proto_tree *scsi_tree;
2992     guint8 opcode = 0xFF;
2993     scsi_cmnd_type cmd = 0;     /* 0 is undefined type */
2994     scsi_task_data_t *cdata = NULL;
2995     
2996     cdata = scsi_find_task (pinfo);
2997     
2998     if (!cdata) {
2999         /* we have no record of this exchange and so we can't dissect the
3000          * payload
3001          */
3002         return;
3003     }
3004
3005     opcode = cdata->opcode;
3006     cmd = cdata->devtype;
3007     
3008     if (tree) {
3009         if (cmd == SCSI_CMND_SPC2) {
3010             ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
3011                                                  payload_len,
3012                                                  "SCSI Payload (%s %s)",
3013                                                  val_to_str (opcode,
3014                                                              scsi_spc2_val,
3015                                                              "0x%02x"),
3016                                                  isreq ? "Request" : "Response");
3017         }
3018         else if (cmd == SCSI_CMND_SBC2) {
3019             ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
3020                                                  payload_len,
3021                                                  "SCSI Payload (%s %s)",
3022                                                  val_to_str (opcode,
3023                                                              scsi_sbc2_val,
3024                                                              "0x%02x"),
3025                                                  isreq ? "Request" : "Response");
3026         }
3027         else {
3028             ti = proto_tree_add_protocol_format (tree, proto_scsi, tvb, offset,
3029                                                  payload_len,
3030                                                  "SCSI Payload (0x%02x %s)",
3031                                                  opcode,
3032                                                  isreq ? "Request" : "Response");
3033         }
3034
3035         scsi_tree = proto_item_add_subtree (ti, ett_scsi);
3036
3037         if (cmd == SCSI_CMND_SPC2) {
3038             switch (opcode) {
3039             case SCSI_SPC2_INQUIRY:
3040                 dissect_scsi_inquiry (tvb, pinfo, scsi_tree, offset, isreq,
3041                                       FALSE, payload_len, cdata);
3042                 break;
3043
3044             case SCSI_SPC2_EXTCOPY:
3045                 dissect_scsi_extcopy (tvb, pinfo, scsi_tree, offset, isreq,
3046                                       FALSE);
3047                 break;
3048
3049             case SCSI_SPC2_LOGSELECT:
3050                 dissect_scsi_logselect (tvb, pinfo, scsi_tree, offset, isreq,
3051                                         FALSE);
3052                 break;
3053
3054             case SCSI_SPC2_LOGSENSE:
3055                 dissect_scsi_logsense (tvb, pinfo, scsi_tree, offset, isreq,
3056                                        FALSE);
3057                 break;
3058
3059             case SCSI_SPC2_MODESELECT6:
3060                 dissect_scsi_modeselect6 (tvb, pinfo, scsi_tree, offset,
3061                                           isreq, FALSE, payload_len);
3062                 break;
3063
3064             case SCSI_SPC2_MODESELECT10:
3065                 dissect_scsi_modeselect10 (tvb, pinfo, scsi_tree, offset,
3066                                            isreq, FALSE, payload_len);
3067                 break;
3068
3069             case SCSI_SPC2_MODESENSE6:
3070                 dissect_scsi_modesense6 (tvb, pinfo, scsi_tree, offset, isreq,
3071                                          FALSE, payload_len);
3072                 break;
3073
3074             case SCSI_SPC2_MODESENSE10:
3075                 dissect_scsi_modesense10 (tvb, pinfo, scsi_tree, offset,
3076                                           isreq, FALSE, payload_len);
3077                 break;
3078
3079             case SCSI_SPC2_PERSRESVIN:
3080                 dissect_scsi_persresvin (tvb, pinfo, scsi_tree, offset, isreq,
3081                                          FALSE, cdata, payload_len);
3082                 break;
3083
3084             case SCSI_SPC2_PERSRESVOUT:
3085                 dissect_scsi_persresvout (tvb, pinfo, scsi_tree, offset,
3086                                           isreq, FALSE, cdata, payload_len);
3087                 break;
3088
3089             case SCSI_SPC2_RELEASE6:
3090                 dissect_scsi_release6 (tvb, pinfo, scsi_tree, offset, isreq,
3091                                        FALSE);
3092                 break;
3093
3094             case SCSI_SPC2_RELEASE10:
3095                 dissect_scsi_release10 (tvb, pinfo, scsi_tree, offset, isreq,
3096                                         FALSE);
3097                 break;
3098
3099             case SCSI_SPC2_REPORTDEVICEID:
3100                 dissect_scsi_reportdeviceid (tvb, pinfo, scsi_tree, offset,
3101                                              isreq, FALSE);
3102                 break;
3103
3104             case SCSI_SPC2_REPORTLUNS:
3105                 dissect_scsi_reportluns (tvb, pinfo, scsi_tree, offset, isreq,
3106                                          FALSE);
3107                 break;
3108
3109             case SCSI_SPC2_REQSENSE:
3110                 dissect_scsi_reqsense (tvb, pinfo, scsi_tree, offset, isreq,
3111                                        FALSE);
3112                 break;
3113
3114             case SCSI_SPC2_RESERVE6:
3115                 dissect_scsi_reserve6 (tvb, pinfo, scsi_tree, offset, isreq,
3116                                        FALSE);
3117                 break;
3118
3119             case SCSI_SPC2_RESERVE10:
3120                 dissect_scsi_reserve10 (tvb, pinfo, scsi_tree, offset, isreq,
3121                                         FALSE);
3122                 break;
3123
3124             case SCSI_SPC2_TESTUNITRDY:
3125                 dissect_scsi_testunitrdy (tvb, pinfo, scsi_tree, offset,
3126                                           isreq, FALSE);
3127                 break;
3128
3129             default:
3130                 call_dissector (data_handle, tvb, pinfo, scsi_tree);
3131                 break;
3132             }
3133         }
3134         else if (cmd == SCSI_CMND_SBC2) {
3135             switch (opcode) {
3136
3137             case SCSI_SBC2_FORMATUNIT:
3138                 dissect_scsi_formatunit (tvb, pinfo, scsi_tree, offset, isreq,
3139                                          FALSE);
3140                 break;
3141
3142             case SCSI_SBC2_READ6:
3143                 dissect_scsi_rdwr6 (tvb, pinfo, scsi_tree, offset, isreq,
3144                                     FALSE);
3145                 break;
3146
3147             case SCSI_SBC2_READ10:
3148                 dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset, isreq,
3149                                      FALSE);
3150                 break;
3151
3152             case SCSI_SBC2_READ12:
3153                 dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset, isreq,
3154                                      FALSE);
3155                 break;
3156
3157             case SCSI_SBC2_READ16:
3158                 dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset, isreq,
3159                                      FALSE);
3160                 break;
3161
3162             case SCSI_SBC2_READCAPACITY:
3163                 dissect_scsi_readcapacity (tvb, pinfo, scsi_tree, offset,
3164                                            isreq, FALSE);
3165                 break;
3166
3167             case SCSI_SBC2_READDEFDATA10:
3168                 dissect_scsi_readdefdata10 (tvb, pinfo, scsi_tree, offset,
3169                                             isreq, FALSE);
3170                 break;
3171
3172             case SCSI_SBC2_READDEFDATA12:
3173                 dissect_scsi_readdefdata12 (tvb, pinfo, scsi_tree, offset,
3174                                             isreq, FALSE);
3175                 break;
3176
3177             case SCSI_SBC2_REASSIGNBLKS:
3178                 dissect_scsi_reassignblks (tvb, pinfo, scsi_tree, offset,
3179                                            isreq, FALSE);
3180                 break;
3181
3182             case SCSI_SBC2_WRITE6:
3183                 dissect_scsi_rdwr6 (tvb, pinfo, scsi_tree, offset, isreq,
3184                                     FALSE);
3185                 break;
3186
3187             case SCSI_SBC2_WRITE10:
3188                 dissect_scsi_rdwr10 (tvb, pinfo, scsi_tree, offset, isreq,
3189                                      FALSE);
3190                 break;
3191
3192             case SCSI_SBC2_WRITE12:
3193                 dissect_scsi_rdwr12 (tvb, pinfo, scsi_tree, offset, isreq,
3194                                      FALSE);
3195                 break;
3196
3197             case SCSI_SBC2_WRITE16:
3198                 dissect_scsi_rdwr16 (tvb, pinfo, scsi_tree, offset, isreq,
3199                                      FALSE);
3200                 break;
3201
3202             default:
3203                 call_dissector (data_handle, tvb, pinfo, scsi_tree);
3204                 break;
3205             }
3206         }
3207         else {
3208             call_dissector (data_handle, tvb, pinfo, scsi_tree);
3209         }
3210     }
3211 }
3212
3213 void
3214 proto_register_scsi (void)
3215 {
3216     /* Setup list of header fields  See Section 1.6.1 for details*/
3217     static hf_register_info hf[] = {
3218         { &hf_scsi_spcopcode,
3219           {"SPC-2 Opcode", "scsi.spc.opcode", FT_UINT8, BASE_HEX,
3220            VALS (scsi_spc2_val), 0x0, "", HFILL}},
3221         { &hf_scsi_sbcopcode,
3222           {"SBC-2 Opcode", "scsi.sbc.opcode", FT_UINT8, BASE_HEX,
3223            VALS (scsi_sbc2_val), 0x0, "", HFILL}},
3224         { &hf_scsi_sscopcode,
3225           {"SSC-2 Opcode", "scsi.ssc.opcode", FT_UINT8, BASE_HEX,
3226            VALS (scsi_ssc2_val), 0x0, "", HFILL}},
3227         { &hf_scsi_control,
3228           {"Control", "scsi.cdb.control", FT_UINT8, BASE_HEX, NULL, 0x0, "",
3229            HFILL}},
3230         { &hf_scsi_inquiry_flags,
3231           {"Flags", "scsi.inquiry.flags", FT_UINT8, BASE_BIN, NULL, 0x0, "",
3232            HFILL}},
3233         { &hf_scsi_inquiry_evpd_page,
3234           {"EVPD Page Code", "scsi.inquiry.evpd.pagecode", FT_UINT8, BASE_HEX,
3235            VALS (scsi_evpd_pagecode_val), 0x0, "", HFILL}},
3236         { &hf_scsi_inquiry_cmdt_page,
3237           {"CMDT Page Code", "scsi.inquiry.cmdt.pagecode", FT_UINT8, BASE_HEX,
3238            NULL, 0x0, "", HFILL}},
3239         { &hf_scsi_alloclen,
3240           {"Allocation Length", "scsi.cdb.alloclen", FT_UINT8, BASE_DEC, NULL,
3241            0x0, "", HFILL}},
3242         { &hf_scsi_logsel_flags,
3243           {"Flags", "scsi.logsel.flags", FT_UINT8, BASE_BIN, NULL, 0x0, "",
3244            HFILL}},
3245         { &hf_scsi_log_pc,
3246           {"Page Control", "scsi.log.pc", FT_UINT8, BASE_BIN,
3247            VALS (scsi_logsel_pc_val), 0xC0, "", HFILL}},
3248         { &hf_scsi_paramlen,
3249           {"Parameter Length", "scsi.cdb.paramlen", FT_UINT8, BASE_DEC, NULL,
3250            0x0, "", HFILL}},
3251         { &hf_scsi_logsns_flags,
3252           {"Flags", "scsi.logsns.flags", FT_UINT16, BASE_BIN, NULL, 0x0, "",
3253            HFILL}},
3254         { &hf_scsi_logsns_pagecode,
3255           {"Page Code", "scsi.logsns.pagecode", FT_UINT8, BASE_HEX,
3256            VALS (scsi_logsns_page_val), 0x3F0, "", HFILL}},
3257         { &hf_scsi_paramlen16,
3258           {"Parameter Length", "scsi.cdb.paramlen16", FT_UINT16, BASE_DEC, NULL,
3259            0x0, "", HFILL}},
3260         { &hf_scsi_modesel_flags,
3261           {"Mode Sense/Select Flags", "scsi.cdb.mode.flags", FT_UINT8, BASE_BIN,
3262            NULL, 0x0, "", HFILL}},
3263         { &hf_scsi_alloclen16,
3264           {"Allocation Length", "scsi.cdb.alloclen16", FT_UINT16, BASE_DEC,
3265            NULL, 0x0, "", HFILL}},
3266         { &hf_scsi_modesns_pc,
3267           {"Page Control", "scsi.mode.pc", FT_UINT8, BASE_BIN,
3268            VALS (scsi_modesns_pc_val), 0xC0, "", HFILL}},
3269         { &hf_scsi_modesns_pagecode,
3270           {"Page Code", "scsi.mode.pagecode", FT_UINT8, BASE_HEX,
3271            VALS (scsi_modesns_page_val), 0x3F, "", HFILL}},
3272         { &hf_scsi_modesns_flags,
3273           {"Flags", "scsi.mode.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
3274            HFILL}},
3275         { &hf_scsi_persresvin_svcaction,
3276           {"Service Action", "scsi.persresvin.svcaction", FT_UINT8, BASE_HEX,
3277            VALS (scsi_persresvin_svcaction_val), 0x0F, "", HFILL}},
3278         { &hf_scsi_persresvout_svcaction,
3279           {"Service Action", "scsi.persresvout.svcaction", FT_UINT8, BASE_HEX,
3280            VALS (scsi_persresvout_svcaction_val), 0x0F, "", HFILL}},
3281         { &hf_scsi_persresv_scope,
3282           {"Reservation Scope", "scsi.persresv.scope", FT_UINT8, BASE_HEX,
3283            VALS (scsi_persresv_scope_val), 0xF0, "", HFILL}},
3284         { &hf_scsi_persresv_type,
3285           {"Reservation Type", "scsi.persresv.type", FT_UINT8, BASE_HEX,
3286            VALS (scsi_persresv_type_val), 0x0F, "", HFILL}},
3287         { &hf_scsi_release_flags,
3288           {"Release Flags", "scsi.release.flags", FT_UINT8, BASE_BIN, NULL,
3289            0x0, "", HFILL}},
3290         { &hf_scsi_release_thirdpartyid,
3291           {"Third-Party ID", "scsi.release.thirdpartyid", FT_BYTES, BASE_HEX,
3292            NULL, 0x0, "", HFILL}},
3293         { &hf_scsi_alloclen32,
3294           {"Allocation Length", "scsi.cdb.alloclen32", FT_UINT32, BASE_DEC,
3295            NULL, 0x0, "", HFILL}},
3296         { &hf_scsi_formatunit_flags,
3297           {"Flags", "scsi.formatunit.flags", FT_UINT8, BASE_BIN, NULL, 0xF8,
3298            "", HFILL}},
3299         { &hf_scsi_cdb_defectfmt,
3300           {"Defect List Format", "scsi.cdb.defectfmt", FT_UINT8, BASE_BIN,
3301            NULL, 0x7, "", HFILL}},
3302         { &hf_scsi_formatunit_interleave,
3303           {"Interleave", "scsi.formatunit.interleave", FT_UINT16, BASE_HEX,
3304            NULL, 0x0, "", HFILL}},
3305         { &hf_scsi_formatunit_vendor,
3306           {"Vendor Unique", "scsi.formatunit.vendor", FT_UINT8, BASE_HEX, NULL,
3307            0x0, "", HFILL}},
3308         { &hf_scsi_rdwr6_lba,
3309           {"Logical Block Address (LBA)", "scsi.rdwr6.lba", FT_UINT24, BASE_DEC,
3310            NULL, 0x0FFFFF, "", HFILL}},
3311         { &hf_scsi_rdwr6_xferlen,
3312           {"Transfer Length", "scsi.rdwr6.xferlen", FT_UINT8, BASE_DEC, NULL, 0x0,
3313            "", HFILL}},
3314         { &hf_scsi_rdwr10_lba,
3315           {"Logical Block Address (LBA)", "scsi.rdwr10.lba", FT_UINT32, BASE_DEC,
3316            NULL, 0x0, "", HFILL}},
3317         { &hf_scsi_rdwr10_xferlen,
3318           {"Transfer Length", "scsi.rdwr10.xferlen", FT_UINT16, BASE_DEC, NULL,
3319            0x0, "", HFILL}},
3320         { &hf_scsi_read_flags,
3321           {"Flags", "scsi.read.flags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
3322            HFILL}},
3323         { &hf_scsi_rdwr12_xferlen,
3324           {"Transfer Length", "scsi.rdwr12.xferlen", FT_UINT32, BASE_DEC, NULL,
3325            0x0, "", HFILL}},
3326         { &hf_scsi_rdwr16_lba,
3327           {"Logical Block Address (LBA)", "scsi.rdwr16.lba", FT_BYTES, BASE_DEC,
3328            NULL, 0x0, "", HFILL}},
3329         { &hf_scsi_readcapacity_flags,
3330           {"Flags", "scsi.readcapacity.flags", FT_UINT8, BASE_BIN, NULL, 0x0,
3331            "", HFILL}},
3332         { &hf_scsi_readcapacity_lba,
3333           {"Logical Block Address", "scsi.readcapacity.lba", FT_UINT32, BASE_DEC,
3334            NULL, 0x0, "", HFILL}},
3335         { &hf_scsi_readcapacity_pmi,
3336           {"PMI", "scsi.readcapacity.pmi", FT_UINT8, BASE_BIN, NULL, 0x1, "",
3337            HFILL}},
3338         { &hf_scsi_readdefdata_flags,
3339           {"Flags", "scsi.readdefdata.flags", FT_UINT8, BASE_BIN, NULL, 0x0, "",
3340            HFILL}},
3341         { &hf_scsi_reassignblks_flags,
3342           {"Flags", "scsi.reassignblks.flags", FT_UINT8, BASE_BIN, NULL, 0x0, "",
3343            HFILL}},
3344         { &hf_scsi_inq_devtype,
3345           {"Device Type", "scsi.inquiry.devtype", FT_UINT8, BASE_HEX,
3346            VALS (scsi_devtype_val), 0x0F, "", HFILL}},
3347         { & hf_scsi_inq_version,
3348           {"Version", "scsi.inquiry.version", FT_UINT8, BASE_HEX,
3349            VALS (scsi_inquiry_vers_val), 0x0, "", HFILL}},
3350         { &hf_scsi_inq_normaca,
3351           {"NormACA", "scsi.inquiry.normaca", FT_UINT8, BASE_HEX, NULL, 0x20,
3352            "", HFILL}},
3353         { &hf_scsi_rluns_lun,
3354           {"LUN", "scsi.reportluns.lun", FT_UINT8, BASE_DEC, NULL, 0x0, "",
3355            HFILL}},
3356         { &hf_scsi_rluns_multilun,
3357           {"Multi-level LUN", "scsi.reportluns.mlun", FT_BYTES, BASE_HEX, NULL,
3358            0x0, "", HFILL}},
3359         { &hf_scsi_modesns_errrep,
3360           {"MRIE", "scsi.mode.mrie", FT_UINT8, BASE_HEX,
3361            VALS (scsi_modesns_mrie_val), 0x0F, "", HFILL}},
3362         { &hf_scsi_modesns_tst,
3363           {"Task Set Type", "scsi.mode.tst", FT_UINT8, BASE_BIN,
3364            VALS (scsi_modesns_tst_val), 0xE0, "", HFILL}},
3365         { &hf_scsi_modesns_qmod,
3366           {"Queue Algorithm Modifier", "scsi.mode.qmod", FT_UINT8, BASE_HEX,
3367            VALS (scsi_modesns_qmod_val), 0xF0, "", HFILL}},
3368         { &hf_scsi_modesns_qerr,
3369           {"Queue Error Management", "scsi.mode.qerr", FT_BOOLEAN, BASE_HEX,
3370            TFS (&scsi_modesns_qerr_val), 0x2, "", HFILL}},
3371         { &hf_scsi_modesns_tas,
3372           {"Task Aborted Status", "scsi.mode.tac", FT_BOOLEAN, BASE_HEX,
3373            TFS (&scsi_modesns_tas_val), 0x80, "", HFILL}},
3374         { &hf_scsi_modesns_rac,
3375           {"Report a Check", "ssci.mode.rac", FT_BOOLEAN, BASE_HEX,
3376            TFS (&scsi_modesns_rac_val), 0x40, "", HFILL}},
3377         { &hf_scsi_protocol,
3378           {"Protocol", "scsi.proto", FT_UINT8, BASE_DEC, VALS (scsi_proto_val),
3379            0x0F, "", HFILL}},
3380         { &hf_scsi_sns_errtype,
3381           {"SNS Error Type", "scsi.sns.errtype", FT_UINT8, BASE_HEX,
3382            VALS (scsi_sns_errtype_val), 0x7F, "", HFILL}},
3383         { &hf_scsi_snskey,
3384           {"Sense Key", "scsi.sns.key", FT_UINT8, BASE_HEX,
3385            VALS (scsi_sensekey_val), 0x0F, "", HFILL}},
3386         { &hf_scsi_snsinfo,
3387           {"Sense Info", "scsi.sns.info", FT_UINT32, BASE_HEX, NULL, 0x0, "",
3388            HFILL}},
3389         { &hf_scsi_addlsnslen,
3390           {"Additional Sense Length", "scsi.sns.addlen", FT_UINT8, BASE_DEC,
3391            NULL, 0x0, "", HFILL}},
3392         { &hf_scsi_asc,
3393           {"Additional Sense Code", "scsi.sns.asc", FT_UINT8, BASE_HEX, NULL,
3394            0x0, "", HFILL}},
3395         { &hf_scsi_ascq,
3396           {"Additional Sense Code Qualifier", "scsi.sns.ascq", FT_UINT8,
3397            BASE_HEX, NULL, 0x0, "", HFILL}},
3398         { &hf_scsi_ascascq,
3399           {"Additional Sense Code+Qualifier", "scsi.sns.ascascq", FT_UINT16,
3400            BASE_HEX, VALS (scsi_asc_val), 0x0, "", HFILL}},
3401         { &hf_scsi_fru,
3402           {"Field Replaceable Unit Code", "scsi.sns.fru", FT_UINT8, BASE_HEX,
3403            NULL, 0x0, "", HFILL}},
3404         { &hf_scsi_sksv,
3405           {"SKSV", "scsi.sns.sksv", FT_BOOLEAN, BASE_HEX, NULL, 0x80, "",
3406            HFILL}},
3407         { &hf_scsi_persresv_key,
3408           {"Reservation Key", "scsi.spc2.resv.key", FT_BYTES, BASE_HEX, NULL,
3409            0x0, "", HFILL}},
3410         { &hf_scsi_persresv_scopeaddr,
3411           {"Scope Address", "scsi.spc2.resv.scopeaddr", FT_BYTES, BASE_HEX, NULL,
3412            0x0, "", HFILL}},
3413         { &hf_scsi_add_cdblen,
3414           {"Additional CDB Length", "scsi.spc2.addcdblen", FT_UINT8, BASE_DEC,
3415            NULL, 0x0, "", HFILL}},
3416         { &hf_scsi_svcaction,
3417           {"Service Action", "scsi.spc2.svcaction", FT_UINT16, BASE_HEX, NULL,
3418            0x0, "", HFILL}},
3419     };
3420
3421     /* Setup protocol subtree array */
3422     static gint *ett[] = {
3423         &ett_scsi,
3424         &ett_scsi_page,
3425     };
3426     module_t *scsi_module;
3427     
3428     /* Register the protocol name and description */
3429     proto_scsi = proto_register_protocol("SCSI", "SCSI", "scsi");
3430
3431     /* Required function calls to register the header fields and subtrees used */
3432     proto_register_field_array(proto_scsi, hf, array_length(hf));
3433     proto_register_subtree_array(ett, array_length(ett));
3434     register_init_routine (&scsi_init_protocol);
3435     register_dissector ("SCSI", dissect_scsi, proto_scsi);
3436     data_handle = find_dissector ("data");
3437
3438     /* add preferences to decode SCSI message */
3439     scsi_module = prefs_register_protocol (proto_scsi, NULL);
3440     prefs_register_enum_preference (scsi_module, "decode_scsi_messages_as",
3441                                     "Decode SCSI Messages As",
3442                                     "When Target Cannot Be Identified, Decode SCSI Messages As",
3443                                     &scsi_def_devtype, scsi_devtype_options, TRUE);
3444 }