2 * Routines for Fibre Channel Single Byte Protocol (SBCCS); used in FICON.
3 * This decoder is for FC-SB3 version 1.4
4 * Copyright 2003, Dinesh G Dutt <ddutt@cisco.com>
8 * Ethereal - Network traffic analyzer
9 * By Gerald Combs <gerald@ethereal.com>
10 * Copyright 1998 Gerald Combs
12 * Copied from WHATEVER_FILE_YOU_USED (where "WHATEVER_FILE_YOU_USED"
13 * is a dissector file; if you just copied this from README.developer,
14 * don't bother with the "Copied from" - you don't even need to put
15 * in a "Copied from" if you copied an existing dissector, especially
16 * if the bulk of the code in the new dissector is your code)
18 * This program is free software; you can redistribute it and/or
19 * modify it under the terms of the GNU General Public License
20 * as published by the Free Software Foundation; either version 2
21 * of the License, or (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
30 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 #ifdef HAVE_SYS_TYPES_H
42 # include <sys/types.h>
45 #ifdef HAVE_NETINET_IN_H
46 # include <netinet/in.h>
51 #ifdef NEED_SNPRINTF_H
52 # include "snprintf.h"
55 #include <epan/prefs.h>
56 #include <epan/packet.h>
57 #include <epan/conversation.h>
59 #include "packet-fc.h"
60 #include "packet-fcsb3.h"
62 /* Initialize the protocol and registered fields */
63 static int proto_fc_sbccs = -1;
64 static int hf_sbccs_chid = -1;
65 static int hf_sbccs_cuid = -1;
66 static int hf_sbccs_devaddr = -1;
67 static int hf_sbccs_iui = -1;
68 static int hf_sbccs_dhflags = -1;
69 static int hf_sbccs_ccw = -1;
70 static int hf_sbccs_token = -1;
71 static int hf_sbccs_dib_iucnt = -1;
72 static int hf_sbccs_dib_datacnt = -1;
73 static int hf_sbccs_dib_ccw_cmd = -1;
74 static int hf_sbccs_dib_ccw_flags = -1;
75 static int hf_sbccs_dib_ccw_cnt = -1;
76 static int hf_sbccs_dib_statusflags = -1;
77 static int hf_sbccs_dib_status = -1;
78 static int hf_sbccs_dib_residualcnt = -1;
79 static int hf_sbccs_dib_qtuf = -1;
80 static int hf_sbccs_dib_qtu = -1;
81 static int hf_sbccs_dib_dtuf = -1;
82 static int hf_sbccs_dib_dtu = -1;
83 static int hf_sbccs_dib_ctlfn = -1;
84 static int hf_sbccs_dib_ctlparam = -1;
85 static int hf_sbccs_lrc = -1;
86 static int hf_sbccs_dib_iupacing = -1;
87 static int hf_sbccs_dev_xcp_code = -1;
88 static int hf_sbccs_prg_pth_errcode = -1;
89 static int hf_sbccs_prg_rsp_errcode = -1;
90 static int hf_sbccs_dib_ctccntr = -1;
91 static int hf_sbccs_dib_lprcode = -1;
92 static int hf_sbccs_dib_tin_imgid_cnt = -1;
93 static int hf_sbccs_dib_lrjcode = -1;
94 static int hf_sbccs_dib_ioprio = -1;
95 static int hf_sbccs_dib_cmdflags = -1;
96 static int hf_sbccs_dib_linkctlfn = -1;
97 static int hf_sbccs_dib_linkctlinfo = -1;
99 /* Initialize the subtree pointers */
100 static gint ett_fc_sbccs = -1;
102 static dissector_handle_t data_handle;
109 static const value_string fc_sbccs_iu_val[] = {
110 {FC_SBCCS_IU_DATA, "Data"},
111 {FC_SBCCS_IU_CMD_HDR, "Command Header"},
112 {FC_SBCCS_IU_STATUS, "Status"},
113 {FC_SBCCS_IU_CTL, "Control"},
114 {FC_SBCCS_IU_CMD_DATA, "Command Header & Data"},
115 {FC_SBCCS_IU_CMD_LINK_CTL, "Link Control"},
121 static const value_string fc_sbccs_dib_cmd_val[] = {
127 {5, "Write (Modifier)"},
128 {6, "Read (Modifier)"},
129 {7, "Control (Modifier)"},
131 {9, "Write (Modifier)"},
132 {10, "Read (Modifier)"},
133 {11, "Control (Modifier)"},
134 {12, "Read Backward"},
135 {13, "Write (Modifier)"},
136 {14, "Read (Modifier)"},
137 {15, "Control (Modifier)"},
141 static const value_string fc_sbccs_dib_ctl_fn_val[] = {
142 {FC_SBCCS_CTL_FN_CTL_END, "Control End"},
143 {FC_SBCCS_CTL_FN_CMD_RSP, "Command Response"},
144 {FC_SBCCS_CTL_FN_STK_STS, "Stack Status"},
145 {FC_SBCCS_CTL_FN_CANCEL, "Cancel"},
146 {FC_SBCCS_CTL_FN_SYS_RST, "System Reset"},
147 {FC_SBCCS_CTL_FN_SEL_RST, "Selective Reset"},
148 {FC_SBCCS_CTL_FN_REQ_STS, "Request Status"},
149 {FC_SBCCS_CTL_FN_DEV_XCP, "Device Level Exception"},
150 {FC_SBCCS_CTL_FN_STS_ACC, "Status Accepted"},
151 {FC_SBCCS_CTL_FN_DEV_ACK, "Device-Level Ack"},
152 {FC_SBCCS_CTL_FN_PRG_PTH, "Purge Path"},
153 {FC_SBCCS_CTL_FN_PRG_RSP, "Purge Path Response"},
157 static const value_string fc_sbccs_dib_dev_xcpcode_val[] = {
158 {1, "Address Exception"},
162 static const value_string fc_sbccs_dib_purge_path_err_val[] = {
163 {0, "Error Code Xfer Not Supported"},
164 {1, "SB-3 Protocol Timeout"},
165 {2, "SB-3 Link Failure"},
167 {4, "SB-3 Offline Condition"},
168 {5, "FC-PH Link Failure"},
169 {6, "SB-3 Length Error"},
171 {8, "SB-3 CRC Error"},
172 {9, "IU Count Error"},
173 {10, "SB-3 Link Level Protocol Error"},
174 {11, "SB-3 Device Level Protocol Error"},
175 {12, "Receive ABTS"},
176 {13, "Cancel Function Timeout"},
177 {14, "Abnormal Termination of Xchg"},
182 static const value_string fc_sbccs_dib_purge_path_rsp_err_val[] = {
184 {1, "SB-3 Protocol Timeout"},
185 {2, "SB-3 Link Failure"},
186 {3, "Logical Path Timeout Error"},
187 {4, "SB-3 Offline Condition"},
188 {5, "FC-PH Link Failure"},
189 {6, "SB-3 Length Error"},
191 {8, "SB-3 CRC Error"},
192 {9, "IU Count Error"},
193 {10, "SB-3 Link Level Protocol Error"},
194 {11, "SB-3 Device Level Protocol Error"},
195 {12, "Receive ABTS"},
197 {14, "Abnormal Termination of Xchg"},
198 {15, "Logical Path Not Estd"},
199 {16, "Test Init Result Error"},
203 static const value_string fc_sbccs_dib_link_ctl_fn_val[] = {
204 {FC_SBCCS_LINK_CTL_FN_ELP, "ELP"},
205 {FC_SBCCS_LINK_CTL_FN_RLP, "RLP"},
206 {FC_SBCCS_LINK_CTL_FN_TIN, "TIN"},
207 {FC_SBCCS_LINK_CTL_FN_LPE, "LPE"},
208 {FC_SBCCS_LINK_CTL_FN_LPR, "LPR"},
209 {FC_SBCCS_LINK_CTL_FN_TIR, "TIR"},
210 {FC_SBCCS_LINK_CTL_FN_LRJ, "LRJ"},
211 {FC_SBCCS_LINK_CTL_FN_LBY, "LBY"},
212 {FC_SBCCS_LINK_CTL_FN_LACK, "LACK"},
216 static const value_string fc_sbccs_dib_lpr_errcode_val[] = {
217 {0x0, "Response to RLP"},
218 {0x1, "Optional Features Conflict"},
219 {0x2, "Out of Resources"},
220 {0x3, "Device Init In Progress"},
221 {0x4, "No CU Image"},
225 static const value_string fc_sbccs_dib_lrj_errcode_val[] = {
226 {0x6, "Logical Path Not Estd"},
227 {0x9, "Protocol Error"},
231 static gchar *get_iui_string (guint8 iui, gchar *buffer)
237 strcpy (&buffer[pos], "AS, ");
242 strcpy (&buffer[pos], "ES, ");
246 strcpy (&buffer[pos], val_to_str (iui & 0x7, fc_sbccs_iu_val, "0x%x"));
251 static gchar *get_dhflags_string (guint8 dhflags, gchar *buffer)
256 if (dhflags & 0x80) {
257 strcpy (&buffer[pos], "End, ");
261 if (dhflags & 0x10) {
262 strcpy (&buffer[pos], "Chaining, ");
267 strcpy (&buffer[pos], "Early End, ");
272 strcpy (&buffer[pos], "No CRC");
278 static gchar *get_ccw_flags_string (guint8 ccw_flags, gchar *buffer)
284 if (ccw_flags & 0x80) {
285 strcpy (&buffer[pos], "CD, ");
289 if (ccw_flags & 0x40) {
290 strcpy (&buffer[pos], "CC, ");
294 if (ccw_flags & 0x20) {
295 strcpy (&buffer[pos], "SLI, ");
299 if (ccw_flags & 0x8) {
300 strcpy (&buffer[pos], "CRR");
307 static gchar *get_cmd_flag_string (guint8 cmd_flag, gchar *buffer)
313 if (cmd_flag & 0x10) {
314 strcpy (&buffer[pos], "DU, ");
318 if (cmd_flag & 0x8) {
319 strcpy (&buffer[pos], "COC, ");
323 if (cmd_flag & 0x4) {
324 strcpy (&buffer[pos], "SYR, ");
328 if (cmd_flag & 0x2) {
329 strcpy (&buffer[pos], "REX, ");
333 if (cmd_flag & 0x1) {
334 strcpy (&buffer[pos], "SSS");
341 static gchar *get_status_flag_string (guint8 status_flag, gchar *buffer)
344 guint8 ffc = (status_flag & 0xD0) >> 5;
350 break; /* to avoid the catch clause below */
352 strcpy (&buffer[pos], "FFC:Queuing Information Valid, ");
356 strcpy (&buffer[pos], "FFC:Resetting Event, ");
360 strcpy (&buffer[pos], "Reserved");
364 if (status_flag & 10) {
365 strcpy (&buffer[pos], "CI, ");
369 if (status_flag & 0x4) {
370 strcpy (&buffer[pos], "CR, ");
374 if (status_flag & 0x2) {
375 strcpy (&buffer[pos], "LRI, ");
379 if (status_flag & 0x1) {
380 strcpy (&buffer[pos], "RV");
386 static gchar *get_status_string (guint8 status, gchar *buffer)
393 strcpy (&buffer[pos], "Attention, ");
398 strcpy (&buffer[pos], "Status Modifier, ");
403 strcpy (&buffer[pos], "Control-Unit End, ");
408 strcpy (&buffer[pos], "Busy, ");
413 strcpy (&buffer[pos], "Channel End, ");
418 strcpy (&buffer[pos], "Device End, ");
423 strcpy (&buffer[pos], "Unit Check, ");
428 strcpy (&buffer[pos], "Unit Exception");
434 static gchar *get_sel_rst_param_string (guint8 ctlparam, gchar *buffer)
440 if (ctlparam & 0x80) {
441 strcpy (&buffer[pos], "RC, ");
444 if (ctlparam & 0x10) {
445 strcpy (&buffer[pos], "RU, ");
448 if (ctlparam & 0x8) {
449 strcpy (&buffer[pos], "RO");
455 static void get_fc_sbccs_conv_data (tvbuff_t *tvb, guint offset,
456 guint16 *ch_cu_id, guint16 *dev_addr,
459 *ch_cu_id = *dev_addr = *ccw = 0;
461 *ch_cu_id = (tvb_get_guint8 (tvb, offset+1)) << 8;
462 *ch_cu_id |= tvb_get_guint8 (tvb, offset+3);
463 *dev_addr = tvb_get_ntohs (tvb, offset+4);
464 *ccw = tvb_get_ntohs (tvb, offset+10);
467 /* Decode both the SB-3 and basic IU header */
469 dissect_fc_sbccs_sb3_iu_hdr (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
473 proto_tree *sb3hdr_tree;
474 proto_tree *iuhdr_tree;
479 /* Decode the basic SB3 and IU header and determine type of frame */
480 type = get_fc_sbccs_iu_type (tvb, offset);
482 if (check_col (pinfo->cinfo, COL_INFO)) {
483 col_set_str (pinfo->cinfo, COL_INFO, val_to_str (type, fc_sbccs_iu_val,
488 /* Dissect SB3 header first */
489 subti = proto_tree_add_text (tree, tvb, offset, FC_SBCCS_SB3_HDR_SIZE,
491 sb3hdr_tree = proto_item_add_subtree (subti, ett_fc_sbccs);
493 proto_tree_add_item (sb3hdr_tree, hf_sbccs_chid, tvb, offset+1, 1, 0);
494 proto_tree_add_item (sb3hdr_tree, hf_sbccs_cuid, tvb, offset+3, 1, 0);
495 proto_tree_add_item (sb3hdr_tree, hf_sbccs_devaddr, tvb, offset+4, 2, 0);
497 /* Dissect IU Header */
498 subti = proto_tree_add_text (tree, tvb, offset + FC_SBCCS_SB3_HDR_SIZE,
499 FC_SBCCS_IU_HDR_SIZE, "IU Header");
500 iuhdr_tree = proto_item_add_subtree (subti, ett_fc_sbccs);
501 offset += FC_SBCCS_SB3_HDR_SIZE;
503 iui = tvb_get_guint8 (tvb, offset);
504 proto_tree_add_uint_format (iuhdr_tree, hf_sbccs_iui, tvb, offset, 1,
505 iui, "Information Unit Identifier: 0x%x (%s)",
506 iui, get_iui_string (iui, buffer));
507 dhflags = tvb_get_guint8 (tvb, offset+1);
508 proto_tree_add_uint_format (iuhdr_tree, hf_sbccs_dhflags, tvb, offset, 1,
509 dhflags, "DH Flags: 0x%x (%s)",
510 dhflags, get_dhflags_string (dhflags, buffer));
512 proto_tree_add_item (iuhdr_tree, hf_sbccs_ccw, tvb, offset+2, 2, 0);
513 proto_tree_add_item (iuhdr_tree, hf_sbccs_token, tvb, offset+5, 3, 0);
517 static void dissect_fc_sbccs_dib_data_hdr (tvbuff_t *tvb,
518 packet_info *pinfo _U_,
519 proto_tree *tree, guint offset)
522 proto_tree_add_item (tree, hf_sbccs_dib_iucnt, tvb, offset+9, 1, 0);
523 proto_tree_add_item (tree, hf_sbccs_dib_datacnt, tvb, offset+10, 2, 0);
524 proto_tree_add_item (tree, hf_sbccs_lrc, tvb, offset+12, 4, 0);
528 static void dissect_fc_sbccs_dib_cmd_hdr (tvbuff_t *tvb, packet_info *pinfo,
529 proto_tree *tree, guint offset)
534 if (check_col (pinfo->cinfo, COL_INFO)) {
535 col_append_fstr (pinfo->cinfo, COL_INFO,
536 ": %s", val_to_str (tvb_get_guint8 (tvb, offset),
537 fc_sbccs_dib_cmd_val,
542 proto_tree_add_item (tree, hf_sbccs_dib_ccw_cmd, tvb, offset, 1, 0);
544 flags = tvb_get_guint8 (tvb, offset+1);
545 proto_tree_add_uint_format (tree, hf_sbccs_dib_ccw_flags, tvb,
547 "CCW Control Flags: 0x%x(%s)", flags,
548 get_ccw_flags_string (flags, buffer));
549 proto_tree_add_item (tree, hf_sbccs_dib_ccw_cnt, tvb, offset+2, 2, 0);
550 proto_tree_add_item (tree, hf_sbccs_dib_ioprio, tvb, offset+5, 1, 0);
552 flags = tvb_get_guint8 (tvb, offset+7);
553 proto_tree_add_uint_format (tree, hf_sbccs_dib_cmdflags, tvb, offset+7,
554 1, flags, "Command Flags: 0x%x(%s)", flags,
555 get_cmd_flag_string (flags, buffer));
556 proto_tree_add_item (tree, hf_sbccs_dib_iucnt, tvb, offset+9, 1, 0);
557 proto_tree_add_item (tree, hf_sbccs_dib_datacnt, tvb, offset+10, 2, 0);
558 proto_tree_add_item (tree, hf_sbccs_lrc, tvb, offset+12, 4, 0);
563 static void dissect_fc_sbccs_dib_status_hdr (tvbuff_t *tvb, packet_info *pinfo,
564 proto_tree *tree, guint offset)
567 gboolean rv_valid, qparam_valid;
570 guint16 supp_status_cnt = 0;
572 if (check_col (pinfo->cinfo, COL_INFO)) {
573 col_append_fstr (pinfo->cinfo, COL_INFO,
575 get_status_string (tvb_get_guint8 (tvb, offset+1),
580 flags = tvb_get_guint8 (tvb, offset);
581 rv_valid = flags & 0x1; /* if residual count is valid */
582 qparam_valid = (((flags & 0xD0) >> 5) == 0x1); /* From the FFC field */
583 proto_tree_add_uint_format (tree, hf_sbccs_dib_statusflags, tvb, offset,
584 1, flags, "Status Flags: 0x%x(%s)",
585 flags, get_status_flag_string (flags,
588 flags = tvb_get_guint8 (tvb, offset+1);
589 proto_tree_add_uint_format (tree, hf_sbccs_dib_status, tvb, offset+1,
590 1, flags, "Status: 0x%x(%s)", flags,
591 get_status_string (flags, buffer));
593 proto_tree_add_item (tree, hf_sbccs_dib_residualcnt, tvb, offset+2,
597 proto_tree_add_item (tree, hf_sbccs_dib_iupacing, tvb, offset+3,
602 proto_tree_add_item (tree, hf_sbccs_dib_qtuf, tvb, offset+4, 1, 0);
603 proto_tree_add_item (tree, hf_sbccs_dib_qtu, tvb, offset+4, 2, 0);
606 proto_tree_add_item (tree, hf_sbccs_dib_dtuf, tvb, offset+6, 1, 0);
607 proto_tree_add_item (tree, hf_sbccs_dib_dtu, tvb, offset+6, 2, 0);
609 proto_tree_add_item (tree, hf_sbccs_dib_iucnt, tvb, offset+9, 1, 0);
610 proto_tree_add_item (tree, hf_sbccs_dib_datacnt, tvb, offset+10, 2, 0);
611 supp_status_cnt = tvb_get_ntohs (tvb, offset+10);
612 proto_tree_add_item (tree, hf_sbccs_lrc, tvb, offset+12, 4, 0);
614 if (supp_status_cnt) {
615 next_tvb = tvb_new_subset (tvb, offset+FC_SBCCS_DIB_LRC_HDR_SIZE,
617 call_dissector (data_handle, next_tvb, pinfo, tree);
622 static void dissect_fc_sbccs_dib_ctl_hdr (tvbuff_t *tvb, packet_info *pinfo,
623 proto_tree *tree, guint offset)
628 ctlfn = tvb_get_guint8 (tvb, offset);
629 if (check_col (pinfo->cinfo, COL_INFO)) {
630 col_append_fstr (pinfo->cinfo, COL_INFO,
633 fc_sbccs_dib_ctl_fn_val,
637 proto_tree_add_item (tree, hf_sbccs_dib_ctlfn, tvb, offset, 1, 0);
639 /* Control Function Parameter is to be interpreted in some cases */
641 case FC_SBCCS_CTL_FN_SEL_RST:
642 proto_tree_add_uint_format (tree, hf_sbccs_dib_ctlparam, tvb,
644 tvb_get_ntoh24 (tvb, offset+1),
645 "Control Parameter: 0x%x(%s)",
646 tvb_get_ntoh24 (tvb, offset+1),
647 get_sel_rst_param_string (ctlfn,
650 case FC_SBCCS_CTL_FN_DEV_XCP:
651 proto_tree_add_item (tree, hf_sbccs_dev_xcp_code, tvb, offset+1,
654 case FC_SBCCS_CTL_FN_PRG_PTH:
655 proto_tree_add_item (tree, hf_sbccs_prg_pth_errcode, tvb, offset+1,
659 proto_tree_add_item (tree, hf_sbccs_dib_ctlparam, tvb, offset+1,
664 proto_tree_add_item (tree, hf_sbccs_dib_iucnt, tvb, offset+9, 1, 0);
665 proto_tree_add_item (tree, hf_sbccs_dib_datacnt, tvb, offset+10, 2, 0);
666 proto_tree_add_item (tree, hf_sbccs_lrc, tvb, offset+12, 4, 0);
668 if (ctlfn == FC_SBCCS_CTL_FN_PRG_RSP) {
669 /* Need to decode the LESBs */
670 proto_tree_add_item (tree, hf_sbccs_prg_rsp_errcode, tvb, offset+60,
676 static void dissect_fc_sbccs_dib_link_hdr (tvbuff_t *tvb, packet_info *pinfo,
677 proto_tree *tree, guint offset)
682 guint link_payload_len, i;
684 if (check_col (pinfo->cinfo, COL_INFO)) {
685 col_append_fstr (pinfo->cinfo, COL_INFO,
687 val_to_str (tvb_get_guint8 (tvb, offset+1),
688 fc_sbccs_dib_link_ctl_fn_val,
693 link_ctl = tvb_get_guint8 (tvb, offset+1);
694 proto_tree_add_item (tree, hf_sbccs_dib_linkctlfn, tvb, offset+1, 1, 0);
696 ctl_info = tvb_get_ntohs (tvb, offset+2);
698 case FC_SBCCS_LINK_CTL_FN_ELP:
699 case FC_SBCCS_LINK_CTL_FN_LPE:
701 if (ctl_info & 0x1) {
702 strcpy (buffer, "Enhanced CRC Gen, ");
704 if (ctl_info & 0x80) {
705 strcpy (&buffer[18], "CTC Conn");
708 proto_tree_add_uint_format (tree, hf_sbccs_dib_linkctlinfo, tvb,
709 offset+2, 2, ctl_info,
710 "Link Control Info: 0x%x(%s)", ctl_info,
713 case FC_SBCCS_LINK_CTL_FN_LPR:
714 proto_tree_add_item (tree, hf_sbccs_dib_lprcode, tvb, offset+2, 1,
717 case FC_SBCCS_LINK_CTL_FN_TIN:
718 proto_tree_add_item (tree, hf_sbccs_dib_tin_imgid_cnt, tvb,
721 case FC_SBCCS_LINK_CTL_FN_TIR:
722 proto_tree_add_item (tree, hf_sbccs_dib_tin_imgid_cnt, tvb,
725 case FC_SBCCS_LINK_CTL_FN_LRJ:
726 proto_tree_add_item (tree, hf_sbccs_dib_lrjcode, tvb, offset+2,
734 proto_tree_add_item (tree, hf_sbccs_dib_ctccntr, tvb, offset+4, 2, 0);
735 proto_tree_add_item (tree, hf_sbccs_dib_iucnt, tvb, offset+9, 1, 0);
736 proto_tree_add_item (tree, hf_sbccs_dib_datacnt, tvb, offset+10, 2, 0);
737 proto_tree_add_item (tree, hf_sbccs_lrc, tvb, offset+12, 4, 0);
739 if (link_ctl == FC_SBCCS_LINK_CTL_FN_TIR) {
740 link_payload_len = tvb_get_ntohs (tvb, offset+10);
744 while (i < link_payload_len) {
745 proto_tree_add_text (tree, tvb, offset, 4,
746 "Logical Paths %d-%d: %s",
748 tvb_bytes_to_str_punct (tvb, offset, 4, ':'));
756 static void dissect_fc_sbccs (tvbuff_t *tvb, packet_info *pinfo,
760 guint16 ch_cu_id, dev_addr, ccw;
763 proto_tree *sb3_tree = NULL,
766 conversation_t *conversation;
767 sb3_task_id_t task_key;
769 /* Make entries in Protocol column and Info column on summary display */
770 if (check_col(pinfo->cinfo, COL_PROTOCOL))
771 col_set_str(pinfo->cinfo, COL_PROTOCOL, "FC-SB3");
773 /* Decode the basic SB3 and IU header and determine type of frame */
774 type = get_fc_sbccs_iu_type (tvb, offset);
775 get_fc_sbccs_conv_data (tvb, offset, &ch_cu_id, &dev_addr, &ccw);
777 if (check_col (pinfo->cinfo, COL_INFO)) {
778 col_set_str (pinfo->cinfo, COL_INFO, val_to_str (type, fc_sbccs_iu_val,
782 /* Retrieve conversation state to determine expected payload */
783 conversation = find_conversation (pinfo->fd->num, &pinfo->src, &pinfo->dst,
784 PT_SBCCS, ch_cu_id, dev_addr, 0);
787 task_key.conv_id = conversation->index;
788 task_key.task_id = ccw;
789 pinfo->private_data = (void *)&task_key;
792 else if ((type == FC_SBCCS_IU_CMD_HDR) ||
793 (type != FC_SBCCS_IU_CMD_DATA)) {
794 conversation = conversation_new (pinfo->fd->num, &pinfo->src, &pinfo->dst,
795 PT_SBCCS, ch_cu_id, dev_addr, 0);
796 task_key.conv_id = conversation->index;
797 task_key.task_id = ccw;
798 pinfo->private_data = (void *)&task_key;
801 pinfo->private_data = NULL;
805 ti = proto_tree_add_protocol_format (tree, proto_fc_sbccs, tvb, 0, -1,
807 sb3_tree = proto_item_add_subtree (ti, ett_fc_sbccs);
809 dissect_fc_sbccs_sb3_iu_hdr (tvb, pinfo, sb3_tree, offset);
810 offset += (FC_SBCCS_SB3_HDR_SIZE + FC_SBCCS_IU_HDR_SIZE);
812 ti = proto_tree_add_text (sb3_tree, tvb, offset,
813 FC_SBCCS_DIB_LRC_HDR_SIZE, "DIB Header");
814 dib_tree = proto_item_add_subtree (ti, ett_fc_sbccs);
817 offset += (FC_SBCCS_SB3_HDR_SIZE + FC_SBCCS_IU_HDR_SIZE);
821 case FC_SBCCS_IU_DATA:
822 dissect_fc_sbccs_dib_data_hdr (tvb, pinfo, dib_tree, offset);
824 case FC_SBCCS_IU_CMD_HDR:
825 case FC_SBCCS_IU_CMD_DATA:
826 dissect_fc_sbccs_dib_cmd_hdr (tvb, pinfo, dib_tree, offset);
828 case FC_SBCCS_IU_STATUS:
829 dissect_fc_sbccs_dib_status_hdr (tvb, pinfo, dib_tree, offset);
831 case FC_SBCCS_IU_CTL:
832 dissect_fc_sbccs_dib_ctl_hdr (tvb, pinfo, dib_tree, offset);
834 case FC_SBCCS_IU_CMD_LINK_CTL:
835 dissect_fc_sbccs_dib_link_hdr (tvb, pinfo, dib_tree, offset);
838 next_tvb = tvb_new_subset (tvb, offset, -1, -1);
839 call_dissector (data_handle, next_tvb, pinfo, dib_tree);
843 if ((get_fc_sbccs_iu_type (tvb, 0) != FC_SBCCS_IU_CTL) &&
844 (get_fc_sbccs_iu_type (tvb, 0) != FC_SBCCS_IU_CMD_LINK_CTL)) {
845 next_tvb = tvb_new_subset (tvb, offset+FC_SBCCS_DIB_LRC_HDR_SIZE,
847 call_dissector (data_handle, next_tvb, pinfo, tree);
851 /* Register the protocol with Ethereal */
853 /* this format is required because a script is used to build the C function
854 that calls all the protocol registration.
858 proto_register_fcsbccs (void)
860 /* Setup list of header fields See Section 1.6.1 for details*/
861 static hf_register_info hf[] = {
863 {"Channel Image ID", "sbccs.chid", FT_UINT8, BASE_DEC, NULL, 0x0,
866 {"Control Unit Image ID", "sbccs.cuid", FT_UINT8, BASE_DEC, NULL,
869 {"Device Address", "sbccs.devaddr", FT_UINT16, BASE_DEC, NULL, 0x0,
872 {"Information Unit Identifier", "sbccs.iui", FT_UINT8, BASE_HEX,
873 NULL, 0x0, "", HFILL}},
875 {"DH Flags", "sbccs.dhflags", FT_UINT8, BASE_HEX, NULL, 0x0, "",
878 {"CCW Number", "sbccs.ccw", FT_UINT16, BASE_HEX, NULL, 0x0, "",
881 {"Token", "sbccs.token", FT_UINT24, BASE_DEC, NULL, 0x0, "",
883 { &hf_sbccs_dib_iucnt,
884 {"DIB IU Count", "sbccs.iucnt", FT_UINT8, BASE_DEC, NULL, 0x0,
886 { &hf_sbccs_dib_datacnt,
887 {"DIB Data Byte Count", "sbccs.databytecnt", FT_UINT16, BASE_DEC,
888 NULL, 0x0, "", HFILL}},
889 { &hf_sbccs_dib_ccw_cmd,
890 {"CCW Command", "sbccs.ccwcmd", FT_UINT8, BASE_HEX,
891 VALS (fc_sbccs_dib_cmd_val), 0x0, "", HFILL}},
892 { &hf_sbccs_dib_ccw_flags,
893 {"CCW Control Flags", "sbccs.ccwflags", FT_UINT8, BASE_HEX, NULL,
895 { &hf_sbccs_dib_ccw_cnt,
896 {"CCW Count", "sbccs.ccwcnt", FT_UINT16, BASE_DEC, NULL, 0x0, "",
898 { &hf_sbccs_dib_ioprio,
899 {"I/O Priority", "sbccs.ioprio", FT_UINT8, BASE_DEC, NULL, 0x0,
901 { &hf_sbccs_dib_cmdflags,
902 {"Command Flags", "sbccs.cmdflags", FT_UINT8, BASE_HEX, NULL, 0x0,
904 { &hf_sbccs_dib_statusflags,
905 {"Status Flags", "sbccs.statusflags", FT_UINT8, BASE_HEX, NULL,
907 { &hf_sbccs_dib_status,
908 {"Status", "sbccs.status", FT_UINT8, BASE_DEC, NULL, 0x0, "",
910 { &hf_sbccs_dib_residualcnt,
911 {"Residual Count", "sbccs.residualcnt", FT_UINT8, BASE_DEC,
912 NULL, 0x0, "", HFILL}},
913 { &hf_sbccs_dib_iupacing,
914 {"IU Pacing", "sbccs.iupacing", FT_UINT8, BASE_DEC, NULL, 0x0,
916 { &hf_sbccs_dib_qtuf,
917 {"Queue-Time Unit Factor", "sbccs.qtuf", FT_UINT8, BASE_DEC,
918 NULL, 0xF0, "", HFILL}},
920 {"Queue-Time Unit", "sbccs.qtu", FT_UINT16, BASE_DEC, NULL, 0xFFF,
922 { &hf_sbccs_dib_dtuf,
923 {"Defer-Time Unit Function", "sbccs.dtuf", FT_UINT8, BASE_DEC,
924 NULL, 0xF0, "", HFILL}},
926 {"Defer-Time Unit", "sbccs.dtu", FT_UINT16, BASE_DEC, NULL, 0xFFF,
928 { &hf_sbccs_dib_ctlfn,
929 {"Control Function", "sbccs.ctlfn", FT_UINT8, BASE_HEX,
930 VALS (fc_sbccs_dib_ctl_fn_val), 0x0, "", HFILL}},
931 { &hf_sbccs_dib_ctlparam,
932 {"Control Parameters", "sbccs.ctlparam", FT_UINT24, BASE_HEX,
933 NULL, 0x0, "", HFILL}},
934 { &hf_sbccs_dib_linkctlfn,
935 {"Link Control Function", "sbccs.linkctlfn", FT_UINT8, BASE_HEX,
936 VALS (fc_sbccs_dib_link_ctl_fn_val), 0x0, "", HFILL}},
937 { &hf_sbccs_dib_linkctlinfo,
938 {"Link Control Information", "sbccs.linkctlinfo", FT_UINT16,
939 BASE_HEX, NULL, 0x0, "", HFILL}},
940 { &hf_sbccs_dib_ctccntr,
941 {"CTC Counter", "sbccs.ctccntr", FT_UINT16, BASE_DEC, NULL, 0x0,
944 {"LRC", "sbccs.lrc", FT_UINT32, BASE_HEX, NULL, 0x0, "", HFILL}},
945 { &hf_sbccs_dev_xcp_code,
946 {"Device Level Exception Code", "sbccs.dip.xcpcode", FT_UINT8,
947 BASE_DEC, VALS (fc_sbccs_dib_dev_xcpcode_val), 0x0, "", HFILL}},
948 { &hf_sbccs_prg_pth_errcode,
949 {"Purge Path Error Code", "sbccs.purgepathcode", FT_UINT8,
950 BASE_DEC, VALS (fc_sbccs_dib_purge_path_err_val), 0x0, "", HFILL}},
951 { &hf_sbccs_prg_rsp_errcode,
952 {"Purge Path Response Error Code", "sbccs.purgepathrspcode",
953 FT_UINT8, BASE_DEC, VALS (fc_sbccs_dib_purge_path_rsp_err_val),
955 { &hf_sbccs_dib_lprcode,
956 {"LPR Reason Code", "sbccs.lprcode", FT_UINT8, BASE_DEC,
957 VALS (fc_sbccs_dib_lpr_errcode_val), 0xF, "", HFILL}},
958 { &hf_sbccs_dib_tin_imgid_cnt,
959 {"TIN Image ID", "sbccs.tinimageidcnt", FT_UINT8, BASE_DEC, NULL,
961 { &hf_sbccs_dib_lrjcode,
962 {"LRJ Reaspn Code", "sbccs.lrjcode", FT_UINT8, BASE_HEX,
963 VALS (fc_sbccs_dib_lrj_errcode_val), 0x7F, "", HFILL}},
967 /* Setup protocol subtree array */
968 static gint *ett[] = {
972 /* Register the protocol name and description */
973 proto_fc_sbccs = proto_register_protocol ("Fibre Channel Single Byte Command",
976 /* Required function calls to register the header fields and subtrees used */
977 proto_register_field_array(proto_fc_sbccs, hf, array_length(hf));
978 proto_register_subtree_array(ett, array_length(ett));
981 /* If this dissector uses sub-dissector registration add a registration routine.
982 This format is required because a script is used to find these routines and
983 create the code that calls these routines.
986 proto_reg_handoff_fcsbccs (void)
988 dissector_handle_t fc_sbccs_handle;
990 fc_sbccs_handle = create_dissector_handle (dissect_fc_sbccs,
993 dissector_add("fc.ftype", FC_FTYPE_SBCCS, fc_sbccs_handle);
995 data_handle = find_dissector ("data");