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