aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/firewire/decode-fcp.c364
-rw-r--r--tools/firewire/list.h24
-rw-r--r--tools/firewire/nosy-dump.c1663
-rw-r--r--tools/firewire/nosy-dump.h280
4 files changed, 1139 insertions, 1192 deletions
diff --git a/tools/firewire/decode-fcp.c b/tools/firewire/decode-fcp.c
index b6b372537618..9cd1550db24a 100644
--- a/tools/firewire/decode-fcp.c
+++ b/tools/firewire/decode-fcp.c
@@ -6,234 +6,206 @@
6#define CSR_FCP_COMMAND 0xfffff0000b00ull 6#define CSR_FCP_COMMAND 0xfffff0000b00ull
7#define CSR_FCP_RESPONSE 0xfffff0000d00ull 7#define CSR_FCP_RESPONSE 0xfffff0000d00ull
8 8
9static const char * const ctype_names[16] = { 9static const char * const ctype_names[] = {
10 "control", 10 [0x0] = "control", [0x8] = "not implemented",
11 "status", 11 [0x1] = "status", [0x9] = "accepted",
12 "specific inquiry", 12 [0x2] = "specific inquiry", [0xa] = "rejected",
13 "notify", 13 [0x3] = "notify", [0xb] = "in transition",
14 "general inquiry", 14 [0x4] = "general inquiry", [0xc] = "stable",
15 "(reserved 0x05)", 15 [0x5] = "(reserved 0x05)", [0xd] = "changed",
16 "(reserved 0x06)", 16 [0x6] = "(reserved 0x06)", [0xe] = "(reserved 0x0e)",
17 "(reserved 0x07)", 17 [0x7] = "(reserved 0x07)", [0xf] = "interim",
18 "not implemented",
19 "accepted",
20 "rejected",
21 "in transition",
22 "stable",
23 "changed",
24 "(reserved 0x0e)",
25 "interim"
26}; 18};
27 19
28static const char * const subunit_type_names[32] = { 20static const char * const subunit_type_names[] = {
29 "monitor", 21 [0x00] = "monitor", [0x10] = "(reserved 0x10)",
30 "audio", 22 [0x01] = "audio", [0x11] = "(reserved 0x11)",
31 "printer", 23 [0x02] = "printer", [0x12] = "(reserved 0x12)",
32 "disc", 24 [0x03] = "disc", [0x13] = "(reserved 0x13)",
33 "tape recorder/player", 25 [0x04] = "tape recorder/player",[0x14] = "(reserved 0x14)",
34 "tuner", 26 [0x05] = "tuner", [0x15] = "(reserved 0x15)",
35 "ca", 27 [0x06] = "ca", [0x16] = "(reserved 0x16)",
36 "camera", 28 [0x07] = "camera", [0x17] = "(reserved 0x17)",
37 "(reserved 0x08)", 29 [0x08] = "(reserved 0x08)", [0x18] = "(reserved 0x18)",
38 "panel", 30 [0x09] = "panel", [0x19] = "(reserved 0x19)",
39 "bulletin board", 31 [0x0a] = "bulletin board", [0x1a] = "(reserved 0x1a)",
40 "camera storage", 32 [0x0b] = "camera storage", [0x1b] = "(reserved 0x1b)",
41 "(reserved 0x0c)", 33 [0x0c] = "(reserved 0x0c)", [0x1c] = "vendor unique",
42 "(reserved 0x0d)", 34 [0x0d] = "(reserved 0x0d)", [0x1d] = "all subunit types",
43 "(reserved 0x0e)", 35 [0x0e] = "(reserved 0x0e)", [0x1e] = "subunit_type extended to next byte",
44 "(reserved 0x0f)", 36 [0x0f] = "(reserved 0x0f)", [0x1f] = "unit",
45 "(reserved 0x10)",
46 "(reserved 0x11)",
47 "(reserved 0x12)",
48 "(reserved 0x13)",
49 "(reserved 0x14)",
50 "(reserved 0x15)",
51 "(reserved 0x16)",
52 "(reserved 0x17)",
53 "(reserved 0x18)",
54 "(reserved 0x19)",
55 "(reserved 0x1a)",
56 "(reserved 0x1b)",
57 "vendor unique",
58 "all subunit types",
59 "subunit_type extended to next byte",
60 "unit"
61}; 37};
62 38
63struct avc_enum { 39struct avc_enum {
64 int value; 40 int value;
65 const char *name; 41 const char *name;
66}; 42};
67 43
68struct avc_field { 44struct avc_field {
69 const char *name; /* Short name for field. */ 45 const char *name; /* Short name for field. */
70 int offset; /* Location of field, specified in bits. 46 int offset; /* Location of field, specified in bits; */
71 * Negative means from end of packet */ 47 /* negative means from end of packet. */
72 int width; /* Width of field, 0 means use data_length. */ 48 int width; /* Width of field, 0 means use data_length. */
73 struct avc_enum *names; 49 struct avc_enum *names;
74}; 50};
75 51
76struct avc_opcode_info { 52struct avc_opcode_info {
77 const char *name; 53 const char *name;
78 struct avc_field fields[8]; 54 struct avc_field fields[8];
79}; 55};
80 56
81struct avc_enum power_field_names[] = { 57struct avc_enum power_field_names[] = {
82 { 0x70, "on" }, 58 { 0x70, "on" },
83 { 0x60, "off" }, 59 { 0x60, "off" },
84 { } 60 { }
85}; 61};
86 62
87static const struct avc_opcode_info opcode_info[256] = { 63static const struct avc_opcode_info opcode_info[256] = {
88 64
89 /* TA Document 1999026 65 /* TA Document 1999026 */
90 * AV/C Digital Interface Command Set General Specification 66 /* AV/C Digital Interface Command Set General Specification 4.0 */
91 * Version 4.0 */ 67 [0xb2] = { "power", {
92 [0xb2] = 68 { "state", 0, 8, power_field_names }
93 { "power", { 69 }
94 { "state", 0, 8, power_field_names } 70 },
95 } 71 [0x30] = { "unit info", {
96 }, 72 { "foo", 0, 8 },
97 [0x30] = 73 { "unit_type", 8, 5 },
98 { "unit info", { 74 { "unit", 13, 3 },
99 { "foo", 0, 8 }, 75 { "company id", 16, 24 },
100 { "unit_type", 8, 5 }, 76 }
101 { "unit", 13, 3 }, 77 },
102 { "company id", 16, 24 }, 78 [0x31] = { "subunit info" },
103 } 79 [0x01] = { "reserve" },
104 }, 80 [0xb0] = { "version" },
105 [0x31] = { "subunit info" }, 81 [0x00] = { "vendor dependent" },
106 [0x01] = { "reserve" }, 82 [0x02] = { "plug info" },
107 [0xb0] = { "version" }, 83 [0x12] = { "channel usage" },
108 [0x00] = { "vendor dependent" }, 84 [0x24] = { "connect" },
109 85 [0x20] = { "connect av" },
110 [0x02] = { "plug info" }, 86 [0x22] = { "connections" },
111 [0x12] = { "channel usage" }, 87 [0x11] = { "digital input" },
112 [0x24] = { "connect" }, 88 [0x10] = { "digital output" },
113 [0x20] = { "connect av" }, 89 [0x25] = { "disconnect" },
114 [0x22] = { "connections" }, 90 [0x21] = { "disconnect av" },
115 [0x11] = { "digital input" }, 91 [0x19] = { "input plug signal format" },
116 [0x10] = { "digital output" }, 92 [0x18] = { "output plug signal format" },
117 [0x25] = { "disconnect" }, 93 [0x1f] = { "general bus setup" },
118 [0x21] = { "disconnect av" }, 94
119 [0x19] = { "input plug signal format" }, 95 /* TA Document 1999025 */
120 [0x18] = { "output plug signal format" }, 96 /* AV/C Descriptor Mechanism Specification Version 1.0 */
121 [0x1f] = { "general bus setup" }, 97 [0x0c] = { "create descriptor" },
122 98 [0x08] = { "open descriptor" },
123 /* TA Document 1999025 99 [0x09] = { "read descriptor" },
124 * AV/C Descriptor Mechanism Specification Version 1.0 */ 100 [0x0a] = { "write descriptor" },
125 [0x0c] = { "create descriptor" }, 101 [0x05] = { "open info block" },
126 [0x08] = { "open descriptor" }, 102 [0x06] = { "read info block" },
127 [0x09] = { "read descriptor" }, 103 [0x07] = { "write info block" },
128 [0x0a] = { "write descriptor" }, 104 [0x0b] = { "search descriptor" },
129 [0x05] = { "open info block" }, 105 [0x0d] = { "object number select" },
130 [0x06] = { "read info block" }, 106
131 [0x07] = { "write info block" }, 107 /* TA Document 1999015 */
132 [0x0b] = { "search descriptor" }, 108 /* AV/C Command Set for Rate Control of Isochronous Data Flow 1.0 */
133 [0x0d] = { "object number select" }, 109 [0xb3] = { "rate", {
134 110 { "subfunction", 0, 8 },
135 /* TA Document 1999015 111 { "result", 8, 8 },
136 * AV/C Command Set for Rate Control of Isochronous Data Flow 1.0 */ 112 { "plug_type", 16, 8 },
137 [0xb3] = { "rate", { 113 { "plug_id", 16, 8 },
138 { "subfunction", 0, 8 }, 114 }
139 { "result", 8, 8 }, 115 },
140 { "plug_type", 16, 8 }, 116
141 { "plug_id", 16, 8 }, 117 /* TA Document 1999008 */
142 } 118 /* AV/C Audio Subunit Specification 1.0 */
143 }, 119 [0xb8] = { "function block" },
144 120
145 /* TA Document 1999008 121 /* TA Document 2001001 */
146 * AV/C Audio Subunit Specification 1.0 */ 122 /* AV/C Panel Subunit Specification 1.1 */
147 [0xb8] = { "function block" }, 123 [0x7d] = { "gui update" },
148 124 [0x7e] = { "push gui data" },
149 /* TA Document 2001001 125 [0x7f] = { "user action" },
150 * AV/C Panel Subunit Specification 1.1 */ 126 [0x7c] = { "pass through" },
151 [0x7d] = { "gui update" }, 127
152 [0x7e] = { "push gui data" }, 128 /* */
153 [0x7f] = { "user action" }, 129 [0x26] = { "asynchronous connection" },
154 [0x7c] = { "pass through" },
155
156 /* */
157 [0x26] = { "asynchronous connection" },
158}; 130};
159 131
160struct avc_frame { 132struct avc_frame {
161 uint32_t operand0:8; 133 uint32_t operand0:8;
162 uint32_t opcode:8; 134 uint32_t opcode:8;
163 uint32_t subunit_id:3; 135 uint32_t subunit_id:3;
164 uint32_t subunit_type:5; 136 uint32_t subunit_type:5;
165 uint32_t ctype:4; 137 uint32_t ctype:4;
166 uint32_t cts:4; 138 uint32_t cts:4;
167}; 139};
168 140
169static void 141static void
170decode_avc(struct link_transaction *t) 142decode_avc(struct link_transaction *t)
171{ 143{
172 struct avc_frame *frame = (struct avc_frame *) t->request->packet.write_block.data; 144 struct avc_frame *frame =
173 const struct avc_opcode_info *info; 145 (struct avc_frame *) t->request->packet.write_block.data;
174 const char *name; 146 const struct avc_opcode_info *info;
175 char buffer[32]; 147 const char *name;
176 int i; 148 char buffer[32];
177 149 int i;
178 info = &opcode_info[frame->opcode]; 150
179 if (info->name == NULL) { 151 info = &opcode_info[frame->opcode];
180 snprintf(buffer, sizeof buffer, "(unknown opcode 0x%02x)", frame->opcode); 152 if (info->name == NULL) {
181 name = buffer; 153 snprintf(buffer, sizeof(buffer),
182 } else { 154 "(unknown opcode 0x%02x)", frame->opcode);
183 name = info->name; 155 name = buffer;
184 } 156 } else {
185 157 name = info->name;
186 printf("av/c %s, subunit_type=%s, subunit_id=%d, opcode=%s", 158 }
187 ctype_names[frame->ctype], subunit_type_names[frame->subunit_type],
188 frame->subunit_id, name);
189
190 for (i = 0; info->fields[i].name != NULL; i++) {
191 printf(", %s", info->fields[i].name);
192 }
193
194 printf("\n");
195}
196 159
160 printf("av/c %s, subunit_type=%s, subunit_id=%d, opcode=%s",
161 ctype_names[frame->ctype], subunit_type_names[frame->subunit_type],
162 frame->subunit_id, name);
163
164 for (i = 0; info->fields[i].name != NULL; i++)
165 printf(", %s", info->fields[i].name);
166
167 printf("\n");
168}
197 169
198int 170int
199decode_fcp(struct link_transaction *t) 171decode_fcp(struct link_transaction *t)
200{ 172{
201 struct avc_frame *frame = (struct avc_frame *) t->request->packet.write_block.data; 173 struct avc_frame *frame =
202 unsigned long long offset; 174 (struct avc_frame *) t->request->packet.write_block.data;
203 175 unsigned long long offset =
204 offset = ((unsigned long long) t->request->packet.common.offset_high << 32) | 176 ((unsigned long long) t->request->packet.common.offset_high << 32) |
205 t->request->packet.common.offset_low; 177 t->request->packet.common.offset_low;
206 178
207 if (t->request->packet.common.tcode != TCODE_WRITE_BLOCK) 179 if (t->request->packet.common.tcode != TCODE_WRITE_BLOCK)
208 return 0; 180 return 0;
209 181
210 if (offset == CSR_FCP_COMMAND || offset == CSR_FCP_RESPONSE) { 182 if (offset == CSR_FCP_COMMAND || offset == CSR_FCP_RESPONSE) {
211 switch (frame->cts) { 183 switch (frame->cts) {
212 case 0x00: 184 case 0x00:
213 decode_avc(t); 185 decode_avc(t);
214 break; 186 break;
215 case 0x01: 187 case 0x01:
216 printf("cal fcp frame (cts=0x01)\n"); 188 printf("cal fcp frame (cts=0x01)\n");
217 break; 189 break;
218 case 0x02: 190 case 0x02:
219 printf("ehs fcp frame (cts=0x02)\n"); 191 printf("ehs fcp frame (cts=0x02)\n");
220 break; 192 break;
221 case 0x03: 193 case 0x03:
222 printf("havi fcp frame (cts=0x03)\n"); 194 printf("havi fcp frame (cts=0x03)\n");
223 break; 195 break;
224 case 0x0e: 196 case 0x0e:
225 printf("vendor specific fcp frame (cts=0x0e)\n"); 197 printf("vendor specific fcp frame (cts=0x0e)\n");
226 break; 198 break;
227 case 0x0f: 199 case 0x0f:
228 printf("extended cts\n"); 200 printf("extended cts\n");
229 break; 201 break;
230 default: 202 default:
231 printf("reserved fcp frame (ctx=0x%02x)\n", frame->cts); 203 printf("reserved fcp frame (ctx=0x%02x)\n", frame->cts);
232 break; 204 break;
205 }
206 return 1;
233 } 207 }
234 return 1;
235 }
236 208
237 return 0; 209 return 0;
238} 210}
239 211
diff --git a/tools/firewire/list.h b/tools/firewire/list.h
index fa119dd371fe..41f4bdadf634 100644
--- a/tools/firewire/list.h
+++ b/tools/firewire/list.h
@@ -1,46 +1,46 @@
1struct list { 1struct list {
2 struct list *next, *prev; 2 struct list *next, *prev;
3}; 3};
4 4
5static inline void 5static inline void
6list_init(struct list *list) 6list_init(struct list *list)
7{ 7{
8 list->next = list; 8 list->next = list;
9 list->prev = list; 9 list->prev = list;
10} 10}
11 11
12static inline int 12static inline int
13list_empty(struct list *list) 13list_empty(struct list *list)
14{ 14{
15 return list->next == list; 15 return list->next == list;
16} 16}
17 17
18static inline void 18static inline void
19list_insert(struct list *link, struct list *new_link) 19list_insert(struct list *link, struct list *new_link)
20{ 20{
21 new_link->prev = link->prev; 21 new_link->prev = link->prev;
22 new_link->next = link; 22 new_link->next = link;
23 new_link->prev->next = new_link; 23 new_link->prev->next = new_link;
24 new_link->next->prev = new_link; 24 new_link->next->prev = new_link;
25} 25}
26 26
27static inline void 27static inline void
28list_append(struct list *list, struct list *new_link) 28list_append(struct list *list, struct list *new_link)
29{ 29{
30 list_insert((struct list *)list, new_link); 30 list_insert((struct list *)list, new_link);
31} 31}
32 32
33static inline void 33static inline void
34list_prepend(struct list *list, struct list *new_link) 34list_prepend(struct list *list, struct list *new_link)
35{ 35{
36 list_insert(list->next, new_link); 36 list_insert(list->next, new_link);
37} 37}
38 38
39static inline void 39static inline void
40list_remove(struct list *link) 40list_remove(struct list *link)
41{ 41{
42 link->prev->next = link->next; 42 link->prev->next = link->next;
43 link->next->prev = link->prev; 43 link->next->prev = link->prev;
44} 44}
45 45
46#define list_entry(link, type, member) \ 46#define list_entry(link, type, member) \
diff --git a/tools/firewire/nosy-dump.c b/tools/firewire/nosy-dump.c
index 1d4dd5439d43..3d7e1a6dfe93 100644
--- a/tools/firewire/nosy-dump.c
+++ b/tools/firewire/nosy-dump.c
@@ -1,5 +1,3 @@
1/* -*- mode: c; c-basic-offset: 2 -*- */
2
3/* 1/*
4 * nosy-dump - Interface to snoop mode driver for TI PCILynx 1394 controllers 2 * nosy-dump - Interface to snoop mode driver for TI PCILynx 1394 controllers
5 * Copyright (C) 2002-2006 Kristian Høgsberg 3 * Copyright (C) 2002-2006 Kristian Høgsberg
@@ -19,642 +17,628 @@
19 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 17 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 */ 18 */
21 19
22#include <stdlib.h> 20#include <byteswap.h>
21#include <endian.h>
22#include <fcntl.h>
23#include <poll.h>
24#include <popt.h>
25#include <signal.h>
23#include <stdio.h> 26#include <stdio.h>
27#include <stdlib.h>
24#include <string.h> 28#include <string.h>
25#include <unistd.h>
26#include <fcntl.h>
27#include <sys/ioctl.h> 29#include <sys/ioctl.h>
28#include <sys/time.h> 30#include <sys/time.h>
29#include <endian.h>
30#include <popt.h>
31#include <poll.h>
32#include <byteswap.h>
33#include <termios.h> 31#include <termios.h>
34 32#include <unistd.h>
35#include <signal.h>
36 33
37#include "list.h" 34#include "list.h"
38#include "nosy-user.h"
39#include "nosy-dump.h" 35#include "nosy-dump.h"
36#include "nosy-user.h"
40 37
41enum { 38enum {
42 PACKET_FIELD_DETAIL = 0x01, 39 PACKET_FIELD_DETAIL = 0x01,
43 PACKET_FIELD_DATA_LENGTH = 0x02, 40 PACKET_FIELD_DATA_LENGTH = 0x02,
44 /* Marks the fields we print in transaction view. */ 41 /* Marks the fields we print in transaction view. */
45 PACKET_FIELD_TRANSACTION = 0x04 42 PACKET_FIELD_TRANSACTION = 0x04,
46}; 43};
47 44
48static void 45static void print_packet(uint32_t *data, size_t length);
49print_packet(uint32_t *data, size_t length); 46static void decode_link_packet(struct link_packet *packet, size_t length,
50static void 47 int include_flags, int exclude_flags);
51decode_link_packet(struct link_packet *packet, size_t length, 48static int run = 1;
52 int include_flags, int exclude_flags);
53
54static int run = 1;
55sig_t sys_sigint_handler; 49sig_t sys_sigint_handler;
56 50
57static char *option_nosy_device = "/dev/nosy"; 51static char *option_nosy_device = "/dev/nosy";
58static char *option_view = "packet"; 52static char *option_view = "packet";
59static char *option_output = NULL; 53static char *option_output;
60static char *option_input = NULL; 54static char *option_input;
61static int option_hex; 55static int option_hex;
62static int option_iso; 56static int option_iso;
63static int option_cycle_start; 57static int option_cycle_start;
64static int option_version; 58static int option_version;
65static int option_verbose; 59static int option_verbose;
66 60
67enum { 61enum {
68 VIEW_TRANSACTION, 62 VIEW_TRANSACTION,
69 VIEW_PACKET, 63 VIEW_PACKET,
70 VIEW_STATS 64 VIEW_STATS,
71}; 65};
72 66
73static const struct poptOption options[] = { 67static const struct poptOption options[] = {
74 { 68 {
75 longName: "device", 69 .longName = "device",
76 shortName: 'd', 70 .shortName = 'd',
77 argInfo: POPT_ARG_STRING, 71 .argInfo = POPT_ARG_STRING,
78 arg: &option_nosy_device, 72 .arg = &option_nosy_device,
79 descrip: "Path to nosy device.", 73 .descrip = "Path to nosy device.",
80 argDescrip: "DEVICE" 74 .argDescrip = "DEVICE"
81 }, 75 },
82 { 76 {
83 longName: "view", 77 .longName = "view",
84 argInfo: POPT_ARG_STRING, 78 .argInfo = POPT_ARG_STRING,
85 arg: &option_view, 79 .arg = &option_view,
86 descrip: "Specify view of bus traffic: packet, transaction or stats.", 80 .descrip = "Specify view of bus traffic: packet, transaction or stats.",
87 argDescrip: "VIEW" 81 .argDescrip = "VIEW"
88 }, 82 },
89 { 83 {
90 longName: "hex", 84 .longName = "hex",
91 shortName: 'x', 85 .shortName = 'x',
92 argInfo: POPT_ARG_NONE, 86 .argInfo = POPT_ARG_NONE,
93 arg: &option_hex, 87 .arg = &option_hex,
94 descrip: "Print each packet in hex.", 88 .descrip = "Print each packet in hex.",
95 }, 89 },
96 { 90 {
97 longName: "iso", 91 .longName = "iso",
98 argInfo: POPT_ARG_NONE, 92 .argInfo = POPT_ARG_NONE,
99 arg: &option_iso, 93 .arg = &option_iso,
100 descrip: "Print iso packets.", 94 .descrip = "Print iso packets.",
101 }, 95 },
102 { 96 {
103 longName: "cycle-start", 97 .longName = "cycle-start",
104 argInfo: POPT_ARG_NONE, 98 .argInfo = POPT_ARG_NONE,
105 arg: &option_cycle_start, 99 .arg = &option_cycle_start,
106 descrip: "Print cycle start packets.", 100 .descrip = "Print cycle start packets.",
107 }, 101 },
108 { 102 {
109 longName: "verbose", 103 .longName = "verbose",
110 shortName: 'v', 104 .shortName = 'v',
111 argInfo: POPT_ARG_NONE, 105 .argInfo = POPT_ARG_NONE,
112 arg: &option_verbose, 106 .arg = &option_verbose,
113 descrip: "Verbose packet view.", 107 .descrip = "Verbose packet view.",
114 }, 108 },
115 { 109 {
116 longName: "output", 110 .longName = "output",
117 shortName: 'o', 111 .shortName = 'o',
118 argInfo: POPT_ARG_STRING, 112 .argInfo = POPT_ARG_STRING,
119 arg: &option_output, 113 .arg = &option_output,
120 descrip: "Log to output file.", 114 .descrip = "Log to output file.",
121 argDescrip: "FILENAME" 115 .argDescrip = "FILENAME"
122 }, 116 },
123 { 117 {
124 longName: "input", 118 .longName = "input",
125 shortName: 'i', 119 .shortName = 'i',
126 argInfo: POPT_ARG_STRING, 120 .argInfo = POPT_ARG_STRING,
127 arg: &option_input, 121 .arg = &option_input,
128 descrip: "Decode log from file.", 122 .descrip = "Decode log from file.",
129 argDescrip: "FILENAME" 123 .argDescrip = "FILENAME"
130 }, 124 },
131 { 125 {
132 longName: "version", 126 .longName = "version",
133 argInfo: POPT_ARG_NONE, 127 .argInfo = POPT_ARG_NONE,
134 arg: &option_version, 128 .arg = &option_version,
135 descrip: "Specify print version info.", 129 .descrip = "Specify print version info.",
136 }, 130 },
137 POPT_AUTOHELP 131 POPT_AUTOHELP
138 POPT_TABLEEND 132 POPT_TABLEEND
139}; 133};
140 134
141void 135/* Allow all ^C except the first to interrupt the program in the usual way. */
136void
142sigint_handler(int signal_num) 137sigint_handler(int signal_num)
143{ 138{
144 if (run == 1) { 139 if (run == 1) {
145 run = 0; 140 run = 0;
146 /* Allow all Ctrl-C's except the first to interrupt the program in 141 signal(SIGINT, SIG_DFL);
147 * the usual way. 142 }
148 */
149 signal(SIGINT, SIG_DFL);
150 }
151} 143}
152 144
153struct subaction * 145struct subaction *
154subaction_create(uint32_t *data, size_t length) 146subaction_create(uint32_t *data, size_t length)
155{ 147{
156 struct subaction *sa; 148 struct subaction *sa;
157 149
158 /* we put the ack in the subaction struct for easy access. */ 150 /* we put the ack in the subaction struct for easy access. */
159 sa = malloc(sizeof *sa - sizeof sa->packet + length); 151 sa = malloc(sizeof *sa - sizeof sa->packet + length);
160 sa->ack = data[length / 4 - 1]; 152 sa->ack = data[length / 4 - 1];
161 sa->length = length; 153 sa->length = length;
162 memcpy (&sa->packet, data, length); 154 memcpy(&sa->packet, data, length);
163 155
164 return sa; 156 return sa;
165} 157}
166 158
167void 159void
168subaction_destroy(struct subaction *sa) 160subaction_destroy(struct subaction *sa)
169{ 161{
170 free(sa); 162 free(sa);
171} 163}
172 164
173struct list pending_transaction_list = 165struct list pending_transaction_list = {
174 { &pending_transaction_list, &pending_transaction_list }; 166 &pending_transaction_list, &pending_transaction_list
167};
175 168
176struct link_transaction * 169struct link_transaction *
177link_transaction_lookup(int request_node, int response_node, int tlabel) 170link_transaction_lookup(int request_node, int response_node, int tlabel)
178{ 171{
179 struct link_transaction *t; 172 struct link_transaction *t;
180 173
181 list_for_each_entry(t, &pending_transaction_list, link) { 174 list_for_each_entry(t, &pending_transaction_list, link) {
182 if (t->request_node == request_node && 175 if (t->request_node == request_node &&
183 t->response_node == response_node && 176 t->response_node == response_node &&
184 t->tlabel == tlabel) 177 t->tlabel == tlabel)
185 return t; 178 return t;
186 } 179 }
187 180
188 t = malloc(sizeof *t); 181 t = malloc(sizeof *t);
189 t->request_node = request_node; 182 t->request_node = request_node;
190 t->response_node = response_node; 183 t->response_node = response_node;
191 t->tlabel = tlabel; 184 t->tlabel = tlabel;
192 list_init(&t->request_list); 185 list_init(&t->request_list);
193 list_init(&t->response_list); 186 list_init(&t->response_list);
194 187
195 list_append(&pending_transaction_list, &t->link); 188 list_append(&pending_transaction_list, &t->link);
196 189
197 return t; 190 return t;
198} 191}
199 192
200void 193void
201link_transaction_destroy(struct link_transaction *t) 194link_transaction_destroy(struct link_transaction *t)
202{ 195{
203 while (!list_empty(&t->request_list)) { 196 struct subaction *sa;
204 struct subaction *sa = list_head(&t->request_list, struct subaction, link); 197
205 list_remove(&sa->link); 198 while (!list_empty(&t->request_list)) {
206 subaction_destroy(sa); 199 sa = list_head(&t->request_list, struct subaction, link);
207 } 200 list_remove(&sa->link);
208 201 subaction_destroy(sa);
209 while (!list_empty(&t->response_list)) { 202 }
210 struct subaction *sa = list_head(&t->response_list, struct subaction, link); 203 while (!list_empty(&t->response_list)) {
211 list_remove(&sa->link); 204 sa = list_head(&t->response_list, struct subaction, link);
212 subaction_destroy(sa); 205 list_remove(&sa->link);
213 } 206 subaction_destroy(sa);
214 207 }
215 free(t); 208 free(t);
216} 209}
217 210
218struct protocol_decoder { 211struct protocol_decoder {
219 const char *name; 212 const char *name;
220 int (*decode)(struct link_transaction *t); 213 int (*decode)(struct link_transaction *t);
221}; 214};
222 215
223static struct protocol_decoder protocol_decoders[] = { 216static struct protocol_decoder protocol_decoders[] = {
224 { "FCP", decode_fcp } 217 { "FCP", decode_fcp }
225}; 218};
226 219
227void 220void
228handle_transaction(struct link_transaction *t) 221handle_transaction(struct link_transaction *t)
229{ 222{
230 struct subaction *sa; 223 struct subaction *sa;
231 int i; 224 int i;
232 225
233 if (!t->request) { 226 if (!t->request) {
234 printf("BUG in handle_transaction\n"); 227 printf("BUG in handle_transaction\n");
235 return; 228 return;
236 } 229 }
237 230
238 for (i = 0; i < array_length(protocol_decoders); i++) 231 for (i = 0; i < array_length(protocol_decoders); i++)
239 if (protocol_decoders[i].decode(t)) 232 if (protocol_decoders[i].decode(t))
240 break; 233 break;
241 234
242 /* HACK: decode only fcp right now. */ 235 /* HACK: decode only fcp right now. */
243 return; 236 return;
244 237
245 decode_link_packet(&t->request->packet, t->request->length, 238 decode_link_packet(&t->request->packet, t->request->length,
246 PACKET_FIELD_TRANSACTION, 0); 239 PACKET_FIELD_TRANSACTION, 0);
247 if (t->response) 240 if (t->response)
248 decode_link_packet(&t->response->packet, t->request->length, 241 decode_link_packet(&t->response->packet, t->request->length,
249 PACKET_FIELD_TRANSACTION, 0); 242 PACKET_FIELD_TRANSACTION, 0);
250 else 243 else
251 printf("[no response]"); 244 printf("[no response]");
252 245
253 if (option_verbose) { 246 if (option_verbose) {
254 list_for_each_entry(sa, &t->request_list, link) 247 list_for_each_entry(sa, &t->request_list, link)
255 print_packet((uint32_t *) &sa->packet, sa->length); 248 print_packet((uint32_t *) &sa->packet, sa->length);
256 list_for_each_entry(sa, &t->response_list, link) 249 list_for_each_entry(sa, &t->response_list, link)
257 print_packet((uint32_t *) &sa->packet, sa->length); 250 print_packet((uint32_t *) &sa->packet, sa->length);
258 } 251 }
259 printf("\r\n"); 252 printf("\r\n");
260 253
261 link_transaction_destroy(t); 254 link_transaction_destroy(t);
262} 255}
263 256
264void 257void
265clear_pending_transaction_list(void) 258clear_pending_transaction_list(void)
266{ 259{
267 struct link_transaction *t; 260 struct link_transaction *t;
268 261
269 while (!list_empty(&pending_transaction_list)) { 262 while (!list_empty(&pending_transaction_list)) {
270 t = list_head(&pending_transaction_list, struct link_transaction, link); 263 t = list_head(&pending_transaction_list,
271 list_remove(&t->link); 264 struct link_transaction, link);
272 link_transaction_destroy(t); 265 list_remove(&t->link);
273 /* print unfinished transactions */ 266 link_transaction_destroy(t);
274 } 267 /* print unfinished transactions */
268 }
275} 269}
276 270
277static const char * const tcode_names[] = { 271static const char * const tcode_names[] = {
278 "write_quadlet_request", 272 [0x0] = "write_quadlet_request", [0x6] = "read_quadlet_response",
279 "write_block_request", 273 [0x1] = "write_block_request", [0x7] = "read_block_response",
280 "write_response", 274 [0x2] = "write_response", [0x8] = "cycle_start",
281 "reserved", 275 [0x3] = "reserved", [0x9] = "lock_request",
282 "read_quadlet_request", 276 [0x4] = "read_quadlet_request", [0xa] = "iso_data",
283 "read_block_request", 277 [0x5] = "read_block_request", [0xb] = "lock_response",
284 "read_quadlet_response",
285 "read_block_response",
286 "cycle_start",
287 "lock_request",
288 "iso_data",
289 "lock_response"
290}; 278};
291 279
292static const char * const ack_names[] = { 280static const char * const ack_names[] = {
293 "no ack", 281 [0x0] = "no ack", [0x8] = "reserved (0x08)",
294 "ack_complete", 282 [0x1] = "ack_complete", [0x9] = "reserved (0x09)",
295 "ack_pending", 283 [0x2] = "ack_pending", [0xa] = "reserved (0x0a)",
296 "reserved (0x03)", 284 [0x3] = "reserved (0x03)", [0xb] = "reserved (0x0b)",
297 "ack_busy_x", 285 [0x4] = "ack_busy_x", [0xc] = "reserved (0x0c)",
298 "ack_busy_a", 286 [0x5] = "ack_busy_a", [0xd] = "ack_data_error",
299 "ack_busy_b", 287 [0x6] = "ack_busy_b", [0xe] = "ack_type_error",
300 "reserved (0x07)", 288 [0x7] = "reserved (0x07)", [0xf] = "reserved (0x0f)",
301 "reserved (0x08)",
302 "reserved (0x09)",
303 "reserved (0x0a)",
304 "reserved (0x0b)",
305 "reserved (0x0c)",
306 "ack_data_error",
307 "ack_type_error",
308 "reserved (0x0f)",
309}; 289};
310 290
311static const char * const rcode_names[] = { 291static const char * const rcode_names[] = {
312 "complete", 292 [0x0] = "complete", [0x4] = "conflict_error",
313 "reserved (0x01)", 293 [0x1] = "reserved (0x01)", [0x5] = "data_error",
314 "reserved (0x02)", 294 [0x2] = "reserved (0x02)", [0x6] = "type_error",
315 "reserved (0x03)", 295 [0x3] = "reserved (0x03)", [0x7] = "address_error",
316 "conflict_error",
317 "data_error",
318 "type_error",
319 "address_error",
320}; 296};
321 297
322static const char * const retry_names[] = { 298static const char * const retry_names[] = {
323 "retry_1", 299 [0x0] = "retry_1",
324 "retry_x", 300 [0x1] = "retry_x",
325 "retry_a", 301 [0x2] = "retry_a",
326 "retry_b", 302 [0x3] = "retry_b",
327}; 303};
328 304
329enum { 305enum {
330 PACKET_RESERVED, 306 PACKET_RESERVED,
331 PACKET_REQUEST, 307 PACKET_REQUEST,
332 PACKET_RESPONSE, 308 PACKET_RESPONSE,
333 PACKET_OTHER, 309 PACKET_OTHER,
334}; 310};
335 311
336struct packet_info { 312struct packet_info {
337 const char *name; 313 const char *name;
338 int type; 314 int type;
339 int response_tcode; 315 int response_tcode;
340 struct packet_field *fields; 316 struct packet_field *fields;
341 int field_count; 317 int field_count;
342}; 318};
343 319
344struct packet_field { 320struct packet_field {
345 const char *name; /* Short name for field. */ 321 const char *name; /* Short name for field. */
346 int offset; /* Location of field, specified in bits. 322 int offset; /* Location of field, specified in bits; */
347 * Negative means from end of packet */ 323 /* negative means from end of packet. */
348 int width; /* Width of field, 0 means use data_length. */ 324 int width; /* Width of field, 0 means use data_length. */
349 int flags; /* Show options. */ 325 int flags; /* Show options. */
350 const char * const *value_names; 326 const char * const *value_names;
351}; 327};
352 328
353#define COMMON_REQUEST_FIELDS \ 329#define COMMON_REQUEST_FIELDS \
354 { "dest", 0, 16, PACKET_FIELD_TRANSACTION }, \ 330 { "dest", 0, 16, PACKET_FIELD_TRANSACTION }, \
355 { "tl", 16, 6 }, \ 331 { "tl", 16, 6 }, \
356 { "rt", 22, 2, PACKET_FIELD_DETAIL, retry_names }, \ 332 { "rt", 22, 2, PACKET_FIELD_DETAIL, retry_names }, \
357 { "tcode", 24, 4, PACKET_FIELD_TRANSACTION, tcode_names }, \ 333 { "tcode", 24, 4, PACKET_FIELD_TRANSACTION, tcode_names }, \
358 { "pri", 28, 4, PACKET_FIELD_DETAIL }, \ 334 { "pri", 28, 4, PACKET_FIELD_DETAIL }, \
359 { "src", 32, 16, PACKET_FIELD_TRANSACTION }, \ 335 { "src", 32, 16, PACKET_FIELD_TRANSACTION }, \
360 { "offs", 48, 48, PACKET_FIELD_TRANSACTION } 336 { "offs", 48, 48, PACKET_FIELD_TRANSACTION }
361 337
362#define COMMON_RESPONSE_FIELDS \ 338#define COMMON_RESPONSE_FIELDS \
363 { "dest", 0, 16 }, \ 339 { "dest", 0, 16 }, \
364 { "tl", 16, 6 }, \ 340 { "tl", 16, 6 }, \
365 { "rt", 22, 2, PACKET_FIELD_DETAIL, retry_names }, \ 341 { "rt", 22, 2, PACKET_FIELD_DETAIL, retry_names }, \
366 { "tcode", 24, 4, 0, tcode_names }, \ 342 { "tcode", 24, 4, 0, tcode_names }, \
367 { "pri", 28, 4, PACKET_FIELD_DETAIL }, \ 343 { "pri", 28, 4, PACKET_FIELD_DETAIL }, \
368 { "src", 32, 16 }, \ 344 { "src", 32, 16 }, \
369 { "rcode", 48, 4, PACKET_FIELD_TRANSACTION, rcode_names } 345 { "rcode", 48, 4, PACKET_FIELD_TRANSACTION, rcode_names }
370 346
371struct packet_field read_quadlet_request_fields[] = { 347struct packet_field read_quadlet_request_fields[] = {
372 COMMON_REQUEST_FIELDS, 348 COMMON_REQUEST_FIELDS,
373 { "crc", 96, 32, PACKET_FIELD_DETAIL }, 349 { "crc", 96, 32, PACKET_FIELD_DETAIL },
374 { "ack", 156, 4, 0, ack_names } 350 { "ack", 156, 4, 0, ack_names },
375}; 351};
376 352
377struct packet_field read_quadlet_response_fields[] = { 353struct packet_field read_quadlet_response_fields[] = {
378 COMMON_RESPONSE_FIELDS, 354 COMMON_RESPONSE_FIELDS,
379 { "data", 96, 32, PACKET_FIELD_TRANSACTION }, 355 { "data", 96, 32, PACKET_FIELD_TRANSACTION },
380 { "crc", 128, 32, PACKET_FIELD_DETAIL }, 356 { "crc", 128, 32, PACKET_FIELD_DETAIL },
381 { "ack", 188, 4, 0, ack_names } 357 { "ack", 188, 4, 0, ack_names },
382}; 358};
383 359
384struct packet_field read_block_request_fields[] = { 360struct packet_field read_block_request_fields[] = {
385 COMMON_REQUEST_FIELDS, 361 COMMON_REQUEST_FIELDS,
386 { "data_length", 96, 16, PACKET_FIELD_TRANSACTION }, 362 { "data_length", 96, 16, PACKET_FIELD_TRANSACTION },
387 { "extended_tcode", 112, 16 }, 363 { "extended_tcode", 112, 16 },
388 { "crc", 128, 32, PACKET_FIELD_DETAIL }, 364 { "crc", 128, 32, PACKET_FIELD_DETAIL },
389 { "ack", 188, 4, 0, ack_names }, 365 { "ack", 188, 4, 0, ack_names },
390}; 366};
391 367
392struct packet_field block_response_fields[] = { 368struct packet_field block_response_fields[] = {
393 COMMON_RESPONSE_FIELDS, 369 COMMON_RESPONSE_FIELDS,
394 { "data_length", 96, 16, PACKET_FIELD_DATA_LENGTH }, 370 { "data_length", 96, 16, PACKET_FIELD_DATA_LENGTH },
395 { "extended_tcode", 112, 16 }, 371 { "extended_tcode", 112, 16 },
396 { "crc", 128, 32, PACKET_FIELD_DETAIL }, 372 { "crc", 128, 32, PACKET_FIELD_DETAIL },
397 { "data", 160, 0, PACKET_FIELD_TRANSACTION }, 373 { "data", 160, 0, PACKET_FIELD_TRANSACTION },
398 { "crc", -64, 32, PACKET_FIELD_DETAIL }, 374 { "crc", -64, 32, PACKET_FIELD_DETAIL },
399 { "ack", -4, 4, 0, ack_names } 375 { "ack", -4, 4, 0, ack_names },
400}; 376};
401 377
402struct packet_field write_quadlet_request_fields[] = { 378struct packet_field write_quadlet_request_fields[] = {
403 COMMON_REQUEST_FIELDS, 379 COMMON_REQUEST_FIELDS,
404 { "data", 96, 32, PACKET_FIELD_TRANSACTION }, 380 { "data", 96, 32, PACKET_FIELD_TRANSACTION },
405 { "ack", -4, 4, 0, ack_names } 381 { "ack", -4, 4, 0, ack_names },
406}; 382};
407 383
408struct packet_field block_request_fields[] = { 384struct packet_field block_request_fields[] = {
409 COMMON_REQUEST_FIELDS, 385 COMMON_REQUEST_FIELDS,
410 { "data_length", 96, 16, PACKET_FIELD_DATA_LENGTH | PACKET_FIELD_TRANSACTION }, 386 { "data_length", 96, 16, PACKET_FIELD_DATA_LENGTH | PACKET_FIELD_TRANSACTION },
411 { "extended_tcode", 112, 16, PACKET_FIELD_TRANSACTION }, 387 { "extended_tcode", 112, 16, PACKET_FIELD_TRANSACTION },
412 { "crc", 128, 32, PACKET_FIELD_DETAIL }, 388 { "crc", 128, 32, PACKET_FIELD_DETAIL },
413 { "data", 160, 0, PACKET_FIELD_TRANSACTION }, 389 { "data", 160, 0, PACKET_FIELD_TRANSACTION },
414 { "crc", -64, 32, PACKET_FIELD_DETAIL }, 390 { "crc", -64, 32, PACKET_FIELD_DETAIL },
415 { "ack", -4, 4, 0, ack_names } 391 { "ack", -4, 4, 0, ack_names },
416}; 392};
417 393
418struct packet_field write_response_fields[] = { 394struct packet_field write_response_fields[] = {
419 COMMON_RESPONSE_FIELDS, 395 COMMON_RESPONSE_FIELDS,
420 { "reserved", 64, 32, PACKET_FIELD_DETAIL }, 396 { "reserved", 64, 32, PACKET_FIELD_DETAIL },
421 { "ack", -4, 4, 0, ack_names } 397 { "ack", -4, 4, 0, ack_names },
422}; 398};
423 399
424struct packet_field iso_data_fields[] = { 400struct packet_field iso_data_fields[] = {
425 { "data_length", 0, 16, PACKET_FIELD_DATA_LENGTH }, 401 { "data_length", 0, 16, PACKET_FIELD_DATA_LENGTH },
426 { "tag", 16, 2 }, 402 { "tag", 16, 2 },
427 { "channel", 18, 6 }, 403 { "channel", 18, 6 },
428 { "tcode", 24, 4, 0, tcode_names }, 404 { "tcode", 24, 4, 0, tcode_names },
429 { "sy", 28, 4 }, 405 { "sy", 28, 4 },
430 { "crc", 32, 32, PACKET_FIELD_DETAIL }, 406 { "crc", 32, 32, PACKET_FIELD_DETAIL },
431 { "data", 64, 0 }, 407 { "data", 64, 0 },
432 { "crc", -64, 32, PACKET_FIELD_DETAIL }, 408 { "crc", -64, 32, PACKET_FIELD_DETAIL },
433 { "ack", -4, 4, 0, ack_names } 409 { "ack", -4, 4, 0, ack_names },
434}; 410};
435 411
436static struct packet_info packet_info[] = { 412static struct packet_info packet_info[] = {
437 { 413 {
438 .name = "write_quadlet_request", 414 .name = "write_quadlet_request",
439 .type = PACKET_REQUEST, 415 .type = PACKET_REQUEST,
440 .response_tcode = TCODE_WRITE_RESPONSE, 416 .response_tcode = TCODE_WRITE_RESPONSE,
441 .fields = write_quadlet_request_fields, 417 .fields = write_quadlet_request_fields,
442 .field_count = array_length(write_quadlet_request_fields) 418 .field_count = array_length(write_quadlet_request_fields)
443 }, 419 },
444 { 420 {
445 .name = "write_block_request", 421 .name = "write_block_request",
446 .type = PACKET_REQUEST, 422 .type = PACKET_REQUEST,
447 .response_tcode = TCODE_WRITE_RESPONSE, 423 .response_tcode = TCODE_WRITE_RESPONSE,
448 .fields = block_request_fields, 424 .fields = block_request_fields,
449 .field_count = array_length(block_request_fields) 425 .field_count = array_length(block_request_fields)
450 }, 426 },
451 { 427 {
452 .name = "write_response", 428 .name = "write_response",
453 .type = PACKET_RESPONSE, 429 .type = PACKET_RESPONSE,
454 .fields = write_response_fields, 430 .fields = write_response_fields,
455 .field_count = array_length(write_response_fields) 431 .field_count = array_length(write_response_fields)
456 }, 432 },
457 { 433 {
458 .name = "reserved", 434 .name = "reserved",
459 .type = PACKET_RESERVED, 435 .type = PACKET_RESERVED,
460 }, 436 },
461 { 437 {
462 .name = "read_quadlet_request", 438 .name = "read_quadlet_request",
463 .type = PACKET_REQUEST, 439 .type = PACKET_REQUEST,
464 .response_tcode = TCODE_READ_QUADLET_RESPONSE, 440 .response_tcode = TCODE_READ_QUADLET_RESPONSE,
465 .fields = read_quadlet_request_fields, 441 .fields = read_quadlet_request_fields,
466 .field_count = array_length(read_quadlet_request_fields) 442 .field_count = array_length(read_quadlet_request_fields)
467 }, 443 },
468 { 444 {
469 .name = "read_block_request", 445 .name = "read_block_request",
470 .type = PACKET_REQUEST, 446 .type = PACKET_REQUEST,
471 .response_tcode = TCODE_READ_BLOCK_RESPONSE, 447 .response_tcode = TCODE_READ_BLOCK_RESPONSE,
472 .fields = read_block_request_fields, 448 .fields = read_block_request_fields,
473 .field_count = array_length(read_block_request_fields) 449 .field_count = array_length(read_block_request_fields)
474 }, 450 },
475 { 451 {
476 .name = "read_quadlet_response", 452 .name = "read_quadlet_response",
477 .type = PACKET_RESPONSE, 453 .type = PACKET_RESPONSE,
478 .fields = read_quadlet_response_fields, 454 .fields = read_quadlet_response_fields,
479 .field_count = array_length(read_quadlet_response_fields) 455 .field_count = array_length(read_quadlet_response_fields)
480 }, 456 },
481 { 457 {
482 .name = "read_block_response", 458 .name = "read_block_response",
483 .type = PACKET_RESPONSE, 459 .type = PACKET_RESPONSE,
484 .fields = block_response_fields, 460 .fields = block_response_fields,
485 .field_count = array_length(block_response_fields) 461 .field_count = array_length(block_response_fields)
486 }, 462 },
487 { 463 {
488 .name = "cycle_start", 464 .name = "cycle_start",
489 .type = PACKET_OTHER, 465 .type = PACKET_OTHER,
490 .fields = write_quadlet_request_fields, 466 .fields = write_quadlet_request_fields,
491 .field_count = array_length(write_quadlet_request_fields) 467 .field_count = array_length(write_quadlet_request_fields)
492 }, 468 },
493 { 469 {
494 .name = "lock_request", 470 .name = "lock_request",
495 .type = PACKET_REQUEST, 471 .type = PACKET_REQUEST,
496 .fields = block_request_fields, 472 .fields = block_request_fields,
497 .field_count = array_length(block_request_fields) 473 .field_count = array_length(block_request_fields)
498 }, 474 },
499 { 475 {
500 .name = "iso_data", 476 .name = "iso_data",
501 .type = PACKET_OTHER, 477 .type = PACKET_OTHER,
502 .fields = iso_data_fields, 478 .fields = iso_data_fields,
503 .field_count = array_length(iso_data_fields) 479 .field_count = array_length(iso_data_fields)
504 }, 480 },
505 { 481 {
506 .name = "lock_response", 482 .name = "lock_response",
507 .type = PACKET_RESPONSE, 483 .type = PACKET_RESPONSE,
508 .fields = block_response_fields, 484 .fields = block_response_fields,
509 .field_count = array_length(block_response_fields) 485 .field_count = array_length(block_response_fields)
510 } 486 },
511}; 487};
512 488
513int 489int
514handle_packet(uint32_t *data, size_t length) 490handle_packet(uint32_t *data, size_t length)
515{ 491{
516 if (length == 0) { 492 if (length == 0) {
517 printf("bus reset\r\n"); 493 printf("bus reset\r\n");
518 clear_pending_transaction_list(); 494 clear_pending_transaction_list();
519 } 495 } else if (length > sizeof(struct phy_packet)) {
520 else if (length > sizeof(struct phy_packet)) { 496 struct link_packet *p = (struct link_packet *) data;
521 struct link_packet *p = (struct link_packet *) data; 497 struct subaction *sa, *prev;
522 struct subaction *sa, *prev; 498 struct link_transaction *t;
523 struct link_transaction *t; 499
524 500 switch (packet_info[p->common.tcode].type) {
525 switch (packet_info[p->common.tcode].type) { 501 case PACKET_REQUEST:
526 case PACKET_REQUEST: 502 t = link_transaction_lookup(p->common.source, p->common.destination,
527 t = link_transaction_lookup(p->common.source, p->common.destination, 503 p->common.tlabel);
528 p->common.tlabel); 504 sa = subaction_create(data, length);
529 sa = subaction_create(data, length); 505 t->request = sa;
530 t->request = sa; 506
531 507 if (!list_empty(&t->request_list)) {
532 if (!list_empty(&t->request_list)) { 508 prev = list_tail(&t->request_list,
533 prev = list_tail(&t->request_list, struct subaction, link); 509 struct subaction, link);
534 510
535 if (!ACK_BUSY(prev->ack)) { 511 if (!ACK_BUSY(prev->ack)) {
536 /* error, we should only see ack_busy_* before the 512 /*
537 * ack_pending/ack_complete -- this is an ack_pending 513 * error, we should only see ack_busy_* before the
538 * instead (ack_complete would have finished the 514 * ack_pending/ack_complete -- this is an ack_pending
539 * transaction). */ 515 * instead (ack_complete would have finished the
516 * transaction).
517 */
518 }
519
520 if (prev->packet.common.tcode != sa->packet.common.tcode ||
521 prev->packet.common.tlabel != sa->packet.common.tlabel) {
522 /* memcmp() ? */
523 /* error, these should match for retries. */
524 }
525 }
526
527 list_append(&t->request_list, &sa->link);
528
529 switch (sa->ack) {
530 case ACK_COMPLETE:
531 if (p->common.tcode != TCODE_WRITE_QUADLET &&
532 p->common.tcode != TCODE_WRITE_BLOCK)
533 /* error, unified transactions only allowed for write */;
534 list_remove(&t->link);
535 handle_transaction(t);
536 break;
537
538 case ACK_NO_ACK:
539 case ACK_DATA_ERROR:
540 case ACK_TYPE_ERROR:
541 list_remove(&t->link);
542 handle_transaction(t);
543 break;
544
545 case ACK_PENDING:
546 /* request subaction phase over, wait for response. */
547 break;
548
549 case ACK_BUSY_X:
550 case ACK_BUSY_A:
551 case ACK_BUSY_B:
552 /* ok, wait for retry. */
553 /* check that retry protocol is respected. */
554 break;
555 }
556 break;
557
558 case PACKET_RESPONSE:
559 t = link_transaction_lookup(p->common.destination, p->common.source,
560 p->common.tlabel);
561 if (list_empty(&t->request_list)) {
562 /* unsolicited response */
563 }
564
565 sa = subaction_create(data, length);
566 t->response = sa;
567
568 if (!list_empty(&t->response_list)) {
569 prev = list_tail(&t->response_list, struct subaction, link);
570
571 if (!ACK_BUSY(prev->ack)) {
572 /*
573 * error, we should only see ack_busy_* before the
574 * ack_pending/ack_complete
575 */
576 }
577
578 if (prev->packet.common.tcode != sa->packet.common.tcode ||
579 prev->packet.common.tlabel != sa->packet.common.tlabel) {
580 /* use memcmp() instead? */
581 /* error, these should match for retries. */
582 }
583 } else {
584 prev = list_tail(&t->request_list, struct subaction, link);
585 if (prev->ack != ACK_PENDING) {
586 /*
587 * error, should not get response unless last request got
588 * ack_pending.
589 */
590 }
591
592 if (packet_info[prev->packet.common.tcode].response_tcode !=
593 sa->packet.common.tcode) {
594 /* error, tcode mismatch */
595 }
596 }
597
598 list_append(&t->response_list, &sa->link);
599
600 switch (sa->ack) {
601 case ACK_COMPLETE:
602 case ACK_NO_ACK:
603 case ACK_DATA_ERROR:
604 case ACK_TYPE_ERROR:
605 list_remove(&t->link);
606 handle_transaction(t);
607 /* transaction complete, remove t from pending list. */
608 break;
609
610 case ACK_PENDING:
611 /* error for responses. */
612 break;
613
614 case ACK_BUSY_X:
615 case ACK_BUSY_A:
616 case ACK_BUSY_B:
617 /* no problem, wait for next retry */
618 break;
619 }
620
621 break;
622
623 case PACKET_OTHER:
624 case PACKET_RESERVED:
625 return 0;
626 }
540 } 627 }
541 628
542 if (prev->packet.common.tcode != sa->packet.common.tcode || 629 return 1;
543 prev->packet.common.tlabel != sa->packet.common.tlabel)
544 /* memcmp() ? */
545 /* error, these should match for retries. */;
546 }
547
548 list_append(&t->request_list, &sa->link);
549
550 switch (sa->ack) {
551 case ACK_COMPLETE:
552 if (p->common.tcode != TCODE_WRITE_QUADLET &&
553 p->common.tcode != TCODE_WRITE_BLOCK)
554 /* error, unified transactions only allowed for write */;
555 list_remove(&t->link);
556 handle_transaction(t);
557 break;
558
559 case ACK_NO_ACK:
560 case ACK_DATA_ERROR:
561 case ACK_TYPE_ERROR:
562 list_remove(&t->link);
563 handle_transaction(t);
564 break;
565
566 case ACK_PENDING:
567 /* request subaction phase over, wait for response. */
568 break;
569
570 case ACK_BUSY_X:
571 case ACK_BUSY_A:
572 case ACK_BUSY_B:
573 /* ok, wait for retry. */
574 /* check that retry protocol is respected. */
575 break;
576 }
577 break;
578
579 case PACKET_RESPONSE:
580 t = link_transaction_lookup(p->common.destination, p->common.source,
581 p->common.tlabel);
582 if (list_empty(&t->request_list)) {
583 /* unsolicited response */
584 }
585
586 sa = subaction_create(data, length);
587 t->response = sa;
588
589 if (!list_empty(&t->response_list)) {
590 prev = list_tail(&t->response_list, struct subaction, link);
591
592 if (!ACK_BUSY(prev->ack))
593 /* error, we should only see ack_busy_* before the
594 * ack_pending/ack_complete */;
595
596 if (prev->packet.common.tcode != sa->packet.common.tcode ||
597 prev->packet.common.tlabel != sa->packet.common.tlabel)
598 /* use memcmp() instead? */
599 /* error, these should match for retries. */;
600 }
601 else {
602 prev = list_tail(&t->request_list, struct subaction, link);
603 if (prev->ack != ACK_PENDING) {
604 /* error, should not get response unless last request got
605 * ack_pending. */
606 }
607
608 if (packet_info[prev->packet.common.tcode].response_tcode !=
609 sa->packet.common.tcode) {
610 /* error, tcode mismatch */
611 }
612 }
613
614 list_append(&t->response_list, &sa->link);
615
616 switch (sa->ack) {
617 case ACK_COMPLETE:
618 case ACK_NO_ACK:
619 case ACK_DATA_ERROR:
620 case ACK_TYPE_ERROR:
621 list_remove(&t->link);
622 handle_transaction(t);
623 /* transaction complete, remove t from pending list. */
624 break;
625
626 case ACK_PENDING:
627 /* error for responses. */
628 break;
629
630 case ACK_BUSY_X:
631 case ACK_BUSY_A:
632 case ACK_BUSY_B:
633 /* no problem, wait for next retry */
634 break;
635 }
636
637 break;
638
639 case PACKET_OTHER:
640 case PACKET_RESERVED:
641 return 0;
642 }
643 }
644
645 return 1;
646} 630}
647 631
648unsigned int get_bits(struct link_packet *packet, int offset, int width) 632unsigned int get_bits(struct link_packet *packet, int offset, int width)
649{ 633{
650 uint32_t *data = (uint32_t *) packet; 634 uint32_t *data = (uint32_t *) packet;
651 uint32_t index, shift, mask; 635 uint32_t index, shift, mask;
652 636
653 index = offset / 32 + 1; 637 index = offset / 32 + 1;
654 shift = 32 - (offset & 31) - width; 638 shift = 32 - (offset & 31) - width;
655 mask = width == 32 ? ~0 : (1 << width) - 1; 639 mask = width == 32 ? ~0 : (1 << width) - 1;
656 640
657 return (data[index] >> shift) & mask; 641 return (data[index] >> shift) & mask;
658} 642}
659 643
660#if __BYTE_ORDER == __LITTLE_ENDIAN 644#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -667,166 +651,159 @@ unsigned int get_bits(struct link_packet *packet, int offset, int width)
667 651
668void dump_data(unsigned char *data, int length) 652void dump_data(unsigned char *data, int length)
669{ 653{
670 int i, print_length; 654 int i, print_length;
671 655
672 if (length > 128) 656 if (length > 128)
673 print_length = 128; 657 print_length = 128;
674 else 658 else
675 print_length = length; 659 print_length = length;
676 660
677 for (i = 0; i < print_length; i++) 661 for (i = 0; i < print_length; i++)
678 printf("%s%02hhx", 662 printf("%s%02hhx",
679 (i % 4 == 0 && i != 0) ? " " : "", 663 (i % 4 == 0 && i != 0) ? " " : "",
680 data[byte_index(i)]); 664 data[byte_index(i)]);
681 665
682 if (print_length < length) 666 if (print_length < length)
683 printf(" (%d more bytes)", length - print_length); 667 printf(" (%d more bytes)", length - print_length);
684} 668}
685 669
686static void 670static void
687decode_link_packet(struct link_packet *packet, size_t length, 671decode_link_packet(struct link_packet *packet, size_t length,
688 int include_flags, int exclude_flags) 672 int include_flags, int exclude_flags)
689{ 673{
690 struct packet_info *pi; 674 struct packet_info *pi;
691 int data_length = 0; 675 int data_length = 0;
692 int i; 676 int i;
693 677
694 pi = &packet_info[packet->common.tcode]; 678 pi = &packet_info[packet->common.tcode];
695 679
696 for (i = 0; i < pi->field_count; i++) { 680 for (i = 0; i < pi->field_count; i++) {
697 struct packet_field *f = &pi->fields[i]; 681 struct packet_field *f = &pi->fields[i];
698 int offset; 682 int offset;
699 683
700 if (f->flags & exclude_flags) 684 if (f->flags & exclude_flags)
701 continue; 685 continue;
702 if (include_flags && !(f->flags & include_flags)) 686 if (include_flags && !(f->flags & include_flags))
703 continue; 687 continue;
704 688
705 if (f->offset < 0) 689 if (f->offset < 0)
706 offset = length * 8 + f->offset - 32; 690 offset = length * 8 + f->offset - 32;
707 else 691 else
708 offset = f->offset; 692 offset = f->offset;
709 693
710 if (f->value_names != NULL) { 694 if (f->value_names != NULL) {
711 uint32_t bits; 695 uint32_t bits;
712 696
713 bits = get_bits(packet, offset, f->width); 697 bits = get_bits(packet, offset, f->width);
714 printf("%s", f->value_names[bits]); 698 printf("%s", f->value_names[bits]);
715 } 699 } else if (f->width == 0) {
716 else if (f->width == 0) { 700 printf("%s=[", f->name);
717 printf("%s=[", f->name); 701 dump_data((unsigned char *) packet + (offset / 8 + 4), data_length);
718 dump_data((unsigned char *) packet + (offset / 8 + 4), data_length); 702 printf("]");
719 printf("]"); 703 } else {
720 } 704 unsigned long long bits;
721 else { 705 int high_width, low_width;
722 unsigned long long bits; 706
723 int high_width, low_width; 707 if ((offset & ~31) != ((offset + f->width - 1) & ~31)) {
724 708 /* Bit field spans quadlet boundary. */
725 if ((offset & ~31) != ((offset + f->width - 1) & ~31)) { 709 high_width = ((offset + 31) & ~31) - offset;
726 /* Bit field spans quadlet boundary. */ 710 low_width = f->width - high_width;
727 high_width = ((offset + 31) & ~31) - offset; 711
728 low_width = f->width - high_width; 712 bits = get_bits(packet, offset, high_width);
729 713 bits = (bits << low_width) |
730 bits = get_bits(packet, offset, high_width); 714 get_bits(packet, offset + high_width, low_width);
731 bits = (bits << low_width) | 715 } else {
732 get_bits(packet, offset + high_width, low_width); 716 bits = get_bits(packet, offset, f->width);
733 } 717 }
734 else 718
735 bits = get_bits(packet, offset, f->width); 719 printf("%s=0x%0*llx", f->name, (f->width + 3) / 4, bits);
736 720
737 printf("%s=0x%0*llx", f->name, (f->width + 3) / 4, bits); 721 if (f->flags & PACKET_FIELD_DATA_LENGTH)
738 722 data_length = bits;
739 if (f->flags & PACKET_FIELD_DATA_LENGTH) 723 }
740 data_length = bits; 724
741 } 725 if (i < pi->field_count - 1)
742 726 printf(", ");
743 if (i < pi->field_count - 1) 727 }
744 printf(", ");
745 }
746} 728}
747 729
748static void 730static void
749print_packet(uint32_t *data, size_t length) 731print_packet(uint32_t *data, size_t length)
750{ 732{
751 int i; 733 int i;
752 734
753 printf("%6u ", data[0]); 735 printf("%6u ", data[0]);
754 736
755 if (length == 4) 737 if (length == 4) {
756 printf("bus reset"); 738 printf("bus reset");
757 else if (length < sizeof(struct phy_packet)) { 739 } else if (length < sizeof(struct phy_packet)) {
758 printf("short packet: "); 740 printf("short packet: ");
759 for (i = 1; i < length / 4; i++) 741 for (i = 1; i < length / 4; i++)
760 printf("%s%08x", i == 0 ? "[" : " ", data[i]); 742 printf("%s%08x", i == 0 ? "[" : " ", data[i]);
761 printf("]"); 743 printf("]");
762 744
763 } 745 } else if (length == sizeof(struct phy_packet) && data[1] == ~data[2]) {
764 else if (length == sizeof(struct phy_packet) && data[1] == ~data[2]) { 746 struct phy_packet *pp = (struct phy_packet *) data;
765 struct phy_packet *pp = (struct phy_packet *) data; 747
766 748 /* phy packet are 3 quadlets: the 1 quadlet payload,
767 /* phy packet are 3 quadlets: the 1 quadlet payload, 749 * the bitwise inverse of the payload and the snoop
768 * the bitwise inverse of the payload and the snoop 750 * mode ack */
769 * mode ack */ 751
770 752 switch (pp->common.identifier) {
771 switch (pp->common.identifier) { 753 case PHY_PACKET_CONFIGURATION:
772 case PHY_PACKET_CONFIGURATION: 754 if (!pp->phy_config.set_root && !pp->phy_config.set_gap_count) {
773 if (!pp->phy_config.set_root && !pp->phy_config.set_gap_count) { 755 printf("ext phy config: phy_id=%02x", pp->phy_config.root_id);
774 printf("ext phy config: phy_id=%02x", pp->phy_config.root_id); 756 } else {
775 } 757 printf("phy config:");
776 else { 758 if (pp->phy_config.set_root)
777 printf("phy config:"); 759 printf(" set_root_id=%02x", pp->phy_config.root_id);
778 if (pp->phy_config.set_root) 760 if (pp->phy_config.set_gap_count)
779 printf(" set_root_id=%02x", pp->phy_config.root_id); 761 printf(" set_gap_count=%d", pp->phy_config.gap_count);
780 if (pp->phy_config.set_gap_count) 762 }
781 printf(" set_gap_count=%d", pp->phy_config.gap_count); 763 break;
782 } 764
783 break; 765 case PHY_PACKET_LINK_ON:
784 766 printf("link-on packet, phy_id=%02x", pp->link_on.phy_id);
785 case PHY_PACKET_LINK_ON: 767 break;
786 printf("link-on packet, phy_id=%02x", pp->link_on.phy_id); 768
787 break; 769 case PHY_PACKET_SELF_ID:
788 770 if (pp->self_id.extended) {
789 case PHY_PACKET_SELF_ID: 771 printf("extended self id: phy_id=%02x, seq=%d",
790 if (pp->self_id.extended) { 772 pp->ext_self_id.phy_id, pp->ext_self_id.sequence);
791 printf("extended self id: phy_id=%02x, seq=%d", 773 } else {
792 pp->ext_self_id.phy_id, pp->ext_self_id.sequence); 774 static const char * const speed_names[] = {
793 } 775 "S100", "S200", "S400", "BETA"
794 else { 776 };
795 static const char * const speed_names[] = { 777 printf("self id: phy_id=%02x, link %s, gap_count=%d, speed=%s%s%s",
796 "S100", "S200", "S400", "BETA" 778 pp->self_id.phy_id,
797 }; 779 (pp->self_id.link_active ? "active" : "not active"),
798 printf("self id: phy_id=%02x, link %s, gap_count=%d, speed=%s%s%s", 780 pp->self_id.gap_count,
799 pp->self_id.phy_id, 781 speed_names[pp->self_id.phy_speed],
800 (pp->self_id.link_active ? "active" : "not active"), 782 (pp->self_id.contender ? ", irm contender" : ""),
801 pp->self_id.gap_count, 783 (pp->self_id.initiated_reset ? ", initiator" : ""));
802 speed_names[pp->self_id.phy_speed], 784 }
803 (pp->self_id.contender ? ", irm contender" : ""), 785 break;
804 (pp->self_id.initiated_reset ? ", initiator" : "")); 786 default:
805 787 printf("unknown phy packet: ");
806 } 788 for (i = 1; i < length / 4; i++)
807 break; 789 printf("%s%08x", i == 0 ? "[" : " ", data[i]);
808 default: 790 printf("]");
809 printf("unknown phy packet: "); 791 break;
810 for (i = 1; i < length / 4; i++) 792 }
811 printf("%s%08x", i == 0 ? "[" : " ", data[i]); 793 } else {
812 printf("]"); 794 struct link_packet *packet = (struct link_packet *) data;
813 break; 795
814 } 796 decode_link_packet(packet, length, 0,
815 } 797 option_verbose ? 0 : PACKET_FIELD_DETAIL);
816 else { 798 }
817 struct link_packet *packet = (struct link_packet *) data; 799
818 800 if (option_hex) {
819 decode_link_packet(packet, length, 0, 801 printf(" [");
820 option_verbose ? 0 : PACKET_FIELD_DETAIL); 802 dump_data((unsigned char *) data + 4, length - 4);
821 } 803 printf("]");
822 804 }
823 if (option_hex) { 805
824 printf(" ["); 806 printf("\r\n");
825 dump_data((unsigned char *) data + 4, length - 4);
826 printf("]");
827 }
828
829 printf("\r\n");
830} 807}
831 808
832#define HIDE_CURSOR "\033[?25l" 809#define HIDE_CURSOR "\033[?25l"
@@ -836,206 +813,204 @@ print_packet(uint32_t *data, size_t length)
836static void 813static void
837print_stats(uint32_t *data, size_t length) 814print_stats(uint32_t *data, size_t length)
838{ 815{
839 static int bus_reset_count, short_packet_count, phy_packet_count; 816 static int bus_reset_count, short_packet_count, phy_packet_count;
840 static int tcode_count[16]; 817 static int tcode_count[16];
841 static struct timeval last_update; 818 static struct timeval last_update;
842 struct timeval now; 819 struct timeval now;
843 int i; 820 int i;
844 821
845 if (length == 0) 822 if (length == 0)
846 bus_reset_count++; 823 bus_reset_count++;
847 else if (length < sizeof(struct phy_packet)) 824 else if (length < sizeof(struct phy_packet))
848 short_packet_count++; 825 short_packet_count++;
849 else if (length == sizeof(struct phy_packet) && data[1] == ~data[2]) 826 else if (length == sizeof(struct phy_packet) && data[1] == ~data[2])
850 phy_packet_count++; 827 phy_packet_count++;
851 else { 828 else {
852 struct link_packet *packet = (struct link_packet *) data; 829 struct link_packet *packet = (struct link_packet *) data;
853 tcode_count[packet->common.tcode]++; 830 tcode_count[packet->common.tcode]++;
854 } 831 }
855 832
856 gettimeofday(&now, NULL); 833 gettimeofday(&now, NULL);
857 if (now.tv_sec <= last_update.tv_sec && 834 if (now.tv_sec <= last_update.tv_sec &&
858 now.tv_usec < last_update.tv_usec + 500000) 835 now.tv_usec < last_update.tv_usec + 500000)
859 return; 836 return;
860 837
861 last_update = now; 838 last_update = now;
862 printf(CLEAR HIDE_CURSOR 839 printf(CLEAR HIDE_CURSOR
863 " bus resets : %8d\n" 840 " bus resets : %8d\n"
864 " short packets : %8d\n" 841 " short packets : %8d\n"
865 " phy packets : %8d\n", 842 " phy packets : %8d\n",
866 bus_reset_count, short_packet_count, phy_packet_count); 843 bus_reset_count, short_packet_count, phy_packet_count);
867 844
868 for (i = 0; i < array_length(packet_info); i++) 845 for (i = 0; i < array_length(packet_info); i++)
869 if (packet_info[i].type != PACKET_RESERVED) 846 if (packet_info[i].type != PACKET_RESERVED)
870 printf(" %-24s: %8d\n", packet_info[i].name, tcode_count[i]); 847 printf(" %-24s: %8d\n", packet_info[i].name, tcode_count[i]);
871 printf(SHOW_CURSOR "\n"); 848 printf(SHOW_CURSOR "\n");
872} 849}
873 850
874struct termios saved_attributes; 851struct termios saved_attributes;
875 852
876void 853void
877reset_input_mode (void) 854reset_input_mode(void)
878{ 855{
879 tcsetattr (STDIN_FILENO, TCSANOW, &saved_attributes); 856 tcsetattr(STDIN_FILENO, TCSANOW, &saved_attributes);
880} 857}
881 858
882void 859void
883set_input_mode (void) 860set_input_mode(void)
884{ 861{
885 struct termios tattr; 862 struct termios tattr;
886 863
887 /* Make sure stdin is a terminal. */ 864 /* Make sure stdin is a terminal. */
888 if (!isatty(STDIN_FILENO)) { 865 if (!isatty(STDIN_FILENO)) {
889 fprintf(stderr, "Not a terminal.\n"); 866 fprintf(stderr, "Not a terminal.\n");
890 exit(EXIT_FAILURE); 867 exit(EXIT_FAILURE);
891 } 868 }
892 869
893 /* Save the terminal attributes so we can restore them later. */ 870 /* Save the terminal attributes so we can restore them later. */
894 tcgetattr(STDIN_FILENO, &saved_attributes); 871 tcgetattr(STDIN_FILENO, &saved_attributes);
895 atexit(reset_input_mode); 872 atexit(reset_input_mode);
896 873
897 /* Set the funny terminal modes. */ 874 /* Set the funny terminal modes. */
898 tcgetattr(STDIN_FILENO, &tattr); 875 tcgetattr(STDIN_FILENO, &tattr);
899 tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */ 876 tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
900 tattr.c_cc[VMIN] = 1; 877 tattr.c_cc[VMIN] = 1;
901 tattr.c_cc[VTIME] = 0; 878 tattr.c_cc[VTIME] = 0;
902 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tattr); 879 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tattr);
903} 880}
904 881
905int main(int argc, const char *argv[]) 882int main(int argc, const char *argv[])
906{ 883{
907 int fd = -1; 884 int fd = -1;
908 FILE *output = NULL, *input = NULL; 885 FILE *output = NULL, *input = NULL;
909 poptContext con; 886 poptContext con;
910 int retval; 887 int retval;
911 int view; 888 int view;
912 char c; 889 char c;
913 struct pollfd pollfds[2]; 890 struct pollfd pollfds[2];
914 891
915 sys_sigint_handler = signal(SIGINT, sigint_handler); 892 sys_sigint_handler = signal(SIGINT, sigint_handler);
916 893
917 con = poptGetContext(NULL, argc, argv, options, 0); 894 con = poptGetContext(NULL, argc, argv, options, 0);
918 retval = poptGetNextOpt(con); 895 retval = poptGetNextOpt(con);
919 if (retval < -1) { 896 if (retval < -1) {
920 poptPrintUsage(con, stdout, 0); 897 poptPrintUsage(con, stdout, 0);
921 return -1; 898 return -1;
922 } 899 }
923 900
924 if (option_version) { 901 if (option_version) {
925 printf("dump tool for nosy sniffer, version %s\n", VERSION); 902 printf("dump tool for nosy sniffer, version %s\n", VERSION);
926 return 0; 903 return 0;
927 }
928
929 if (__BYTE_ORDER != __LITTLE_ENDIAN)
930 fprintf(stderr, "warning: nosy has only been tested on little "
931 "endian machines\n");
932
933 if (option_input != NULL) {
934 input = fopen(option_input, "r");
935 if (input == NULL) {
936 fprintf(stderr, "Could not open %s, %m\n", option_input);
937 return -1;
938 }
939 }
940 else {
941 fd = open(option_nosy_device, O_RDWR);
942 if (fd < 0) {
943 fprintf(stderr, "Could not open %s, %m\n", option_nosy_device);
944 return -1;
945 }
946 set_input_mode();
947 }
948
949 if (strcmp(option_view, "transaction") == 0)
950 view = VIEW_TRANSACTION;
951 else if (strcmp(option_view, "stats") == 0)
952 view = VIEW_STATS;
953 else
954 view = VIEW_PACKET;
955
956 if (option_output) {
957 output = fopen(option_output, "w");
958 if (output == NULL) {
959 fprintf(stderr, "Could not open %s, %m\n", option_output);
960 return -1;
961 }
962 }
963
964 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
965
966 if (1) {
967 uint32_t buf[128 * 1024];
968 uint32_t filter;
969 int length;
970
971 filter = ~0;
972 if (!option_iso)
973 filter &= ~(1 <<TCODE_ISO_DATA);
974 if (!option_cycle_start)
975 filter &= ~(1 << TCODE_CYCLE_START);
976 if (view == VIEW_STATS)
977 filter = ~(1 << TCODE_CYCLE_START);
978
979 ioctl(fd, NOSY_IOC_FILTER, filter);
980
981 ioctl(fd, NOSY_IOC_START);
982
983 pollfds[0].fd = fd;
984 pollfds[0].events = POLLIN;
985 pollfds[1].fd = STDIN_FILENO;
986 pollfds[1].events = POLLIN;
987
988 while (run) {
989 if (input != NULL) {
990 if (fread(&length, sizeof length, 1, input) != 1)
991 return 0;
992 fread(buf, 1, length, input);
993 }
994 else {
995 poll(pollfds, 2, -1);
996 if (pollfds[1].revents) {
997 read(STDIN_FILENO, &c, sizeof c);
998 switch (c) {
999 case 'q':
1000 if (output != NULL)
1001 fclose(output);
1002 return 0;
1003 }
1004 } 904 }
1005 905
1006 if (pollfds[0].revents) 906 if (__BYTE_ORDER != __LITTLE_ENDIAN)
1007 length = read(fd, buf, sizeof buf); 907 fprintf(stderr, "warning: nosy has only been tested on little "
908 "endian machines\n");
909
910 if (option_input != NULL) {
911 input = fopen(option_input, "r");
912 if (input == NULL) {
913 fprintf(stderr, "Could not open %s, %m\n", option_input);
914 return -1;
915 }
916 } else {
917 fd = open(option_nosy_device, O_RDWR);
918 if (fd < 0) {
919 fprintf(stderr, "Could not open %s, %m\n", option_nosy_device);
920 return -1;
921 }
922 set_input_mode();
923 }
924
925 if (strcmp(option_view, "transaction") == 0)
926 view = VIEW_TRANSACTION;
927 else if (strcmp(option_view, "stats") == 0)
928 view = VIEW_STATS;
1008 else 929 else
1009 continue; 930 view = VIEW_PACKET;
1010 } 931
1011 932 if (option_output) {
1012 if (output != NULL) { 933 output = fopen(option_output, "w");
1013 fwrite(&length, sizeof length, 1, output); 934 if (output == NULL) {
1014 fwrite(buf, 1, length, output); 935 fprintf(stderr, "Could not open %s, %m\n", option_output);
1015 } 936 return -1;
1016 937 }
1017 switch (view) { 938 }
1018 case VIEW_TRANSACTION: 939
1019 handle_packet(buf, length); 940 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
1020 break; 941
1021 case VIEW_PACKET: 942 if (1) {
1022 print_packet(buf, length); 943 uint32_t buf[128 * 1024];
1023 break; 944 uint32_t filter;
1024 case VIEW_STATS: 945 int length;
1025 print_stats(buf, length); 946
1026 break; 947 filter = ~0;
1027 } 948 if (!option_iso)
1028 } 949 filter &= ~(1 << TCODE_ISO_DATA);
1029 } 950 if (!option_cycle_start)
1030 else 951 filter &= ~(1 << TCODE_CYCLE_START);
1031 poptPrintUsage(con, stdout, 0); 952 if (view == VIEW_STATS)
1032 953 filter = ~(1 << TCODE_CYCLE_START);
1033 if (output != NULL) 954
1034 fclose(output); 955 ioctl(fd, NOSY_IOC_FILTER, filter);
1035 956
1036 close(fd); 957 ioctl(fd, NOSY_IOC_START);
1037 958
1038 poptFreeContext(con); 959 pollfds[0].fd = fd;
1039 960 pollfds[0].events = POLLIN;
1040 return 0; 961 pollfds[1].fd = STDIN_FILENO;
962 pollfds[1].events = POLLIN;
963
964 while (run) {
965 if (input != NULL) {
966 if (fread(&length, sizeof length, 1, input) != 1)
967 return 0;
968 fread(buf, 1, length, input);
969 } else {
970 poll(pollfds, 2, -1);
971 if (pollfds[1].revents) {
972 read(STDIN_FILENO, &c, sizeof c);
973 switch (c) {
974 case 'q':
975 if (output != NULL)
976 fclose(output);
977 return 0;
978 }
979 }
980
981 if (pollfds[0].revents)
982 length = read(fd, buf, sizeof buf);
983 else
984 continue;
985 }
986
987 if (output != NULL) {
988 fwrite(&length, sizeof length, 1, output);
989 fwrite(buf, 1, length, output);
990 }
991
992 switch (view) {
993 case VIEW_TRANSACTION:
994 handle_packet(buf, length);
995 break;
996 case VIEW_PACKET:
997 print_packet(buf, length);
998 break;
999 case VIEW_STATS:
1000 print_stats(buf, length);
1001 break;
1002 }
1003 }
1004 } else {
1005 poptPrintUsage(con, stdout, 0);
1006 }
1007
1008 if (output != NULL)
1009 fclose(output);
1010
1011 close(fd);
1012
1013 poptFreeContext(con);
1014
1015 return 0;
1041} 1016}
diff --git a/tools/firewire/nosy-dump.h b/tools/firewire/nosy-dump.h
index 60cf556e228e..fe8be630efaa 100644
--- a/tools/firewire/nosy-dump.h
+++ b/tools/firewire/nosy-dump.h
@@ -36,60 +36,60 @@
36#include <stdint.h> 36#include <stdint.h>
37 37
38struct phy_packet { 38struct phy_packet {
39 uint32_t timestamp; 39 uint32_t timestamp;
40 union { 40 union {
41 struct { 41 struct {
42 uint32_t zero:24; 42 uint32_t zero:24;
43 uint32_t phy_id:6; 43 uint32_t phy_id:6;
44 uint32_t identifier:2; 44 uint32_t identifier:2;
45 } common, link_on; 45 } common, link_on;
46 46
47 struct { 47 struct {
48 uint32_t zero:16; 48 uint32_t zero:16;
49 uint32_t gap_count:6; 49 uint32_t gap_count:6;
50 uint32_t set_gap_count:1; 50 uint32_t set_gap_count:1;
51 uint32_t set_root:1; 51 uint32_t set_root:1;
52 uint32_t root_id:6; 52 uint32_t root_id:6;
53 uint32_t identifier:2; 53 uint32_t identifier:2;
54 } phy_config; 54 } phy_config;
55 55
56 struct { 56 struct {
57 uint32_t more_packets:1; 57 uint32_t more_packets:1;
58 uint32_t initiated_reset:1; 58 uint32_t initiated_reset:1;
59 uint32_t port2:2; 59 uint32_t port2:2;
60 uint32_t port1:2; 60 uint32_t port1:2;
61 uint32_t port0:2; 61 uint32_t port0:2;
62 uint32_t power_class:3; 62 uint32_t power_class:3;
63 uint32_t contender:1; 63 uint32_t contender:1;
64 uint32_t phy_delay:2; 64 uint32_t phy_delay:2;
65 uint32_t phy_speed:2; 65 uint32_t phy_speed:2;
66 uint32_t gap_count:6; 66 uint32_t gap_count:6;
67 uint32_t link_active:1; 67 uint32_t link_active:1;
68 uint32_t extended:1; 68 uint32_t extended:1;
69 uint32_t phy_id:6; 69 uint32_t phy_id:6;
70 uint32_t identifier:2; 70 uint32_t identifier:2;
71 } self_id; 71 } self_id;
72 72
73 struct { 73 struct {
74 uint32_t more_packets:1; 74 uint32_t more_packets:1;
75 uint32_t reserved1:1; 75 uint32_t reserved1:1;
76 uint32_t porth:2; 76 uint32_t porth:2;
77 uint32_t portg:2; 77 uint32_t portg:2;
78 uint32_t portf:2; 78 uint32_t portf:2;
79 uint32_t porte:2; 79 uint32_t porte:2;
80 uint32_t portd:2; 80 uint32_t portd:2;
81 uint32_t portc:2; 81 uint32_t portc:2;
82 uint32_t portb:2; 82 uint32_t portb:2;
83 uint32_t porta:2; 83 uint32_t porta:2;
84 uint32_t reserved0:2; 84 uint32_t reserved0:2;
85 uint32_t sequence:3; 85 uint32_t sequence:3;
86 uint32_t extended:1; 86 uint32_t extended:1;
87 uint32_t phy_id:6; 87 uint32_t phy_id:6;
88 uint32_t identifier:2; 88 uint32_t identifier:2;
89 } ext_self_id; 89 } ext_self_id;
90 }; 90 };
91 uint32_t inverted; 91 uint32_t inverted;
92 uint32_t ack; 92 uint32_t ack;
93}; 93};
94 94
95#define PHY_PACKET_CONFIGURATION 0x00 95#define PHY_PACKET_CONFIGURATION 0x00
@@ -97,98 +97,98 @@ struct phy_packet {
97#define PHY_PACKET_SELF_ID 0x02 97#define PHY_PACKET_SELF_ID 0x02
98 98
99struct link_packet { 99struct link_packet {
100 uint32_t timestamp; 100 uint32_t timestamp;
101 union { 101 union {
102 struct { 102 struct {
103 uint32_t priority:4; 103 uint32_t priority:4;
104 uint32_t tcode:4; 104 uint32_t tcode:4;
105 uint32_t rt:2; 105 uint32_t rt:2;
106 uint32_t tlabel:6; 106 uint32_t tlabel:6;
107 uint32_t destination:16; 107 uint32_t destination:16;
108 108
109 uint32_t offset_high:16; 109 uint32_t offset_high:16;
110 uint32_t source:16; 110 uint32_t source:16;
111 111
112 uint32_t offset_low; 112 uint32_t offset_low;
113 } common; 113 } common;
114 114
115 struct { 115 struct {
116 uint32_t common[3]; 116 uint32_t common[3];
117 uint32_t crc; 117 uint32_t crc;
118 } read_quadlet; 118 } read_quadlet;
119 119
120 struct { 120 struct {
121 uint32_t common[3]; 121 uint32_t common[3];
122 uint32_t data; 122 uint32_t data;
123 uint32_t crc; 123 uint32_t crc;
124 } read_quadlet_response; 124 } read_quadlet_response;
125 125
126 struct { 126 struct {
127 uint32_t common[3]; 127 uint32_t common[3];
128 uint32_t extended_tcode:16; 128 uint32_t extended_tcode:16;
129 uint32_t data_length:16; 129 uint32_t data_length:16;
130 uint32_t crc; 130 uint32_t crc;
131 } read_block; 131 } read_block;
132 132
133 struct { 133 struct {
134 uint32_t common[3]; 134 uint32_t common[3];
135 uint32_t extended_tcode:16; 135 uint32_t extended_tcode:16;
136 uint32_t data_length:16; 136 uint32_t data_length:16;
137 uint32_t crc; 137 uint32_t crc;
138 uint32_t data[0]; 138 uint32_t data[0];
139 /* crc and ack follows. */ 139 /* crc and ack follows. */
140 } read_block_response; 140 } read_block_response;
141 141
142 struct { 142 struct {
143 uint32_t common[3]; 143 uint32_t common[3];
144 uint32_t data; 144 uint32_t data;
145 uint32_t crc; 145 uint32_t crc;
146 } write_quadlet; 146 } write_quadlet;
147 147
148 struct { 148 struct {
149 uint32_t common[3]; 149 uint32_t common[3];
150 uint32_t extended_tcode:16; 150 uint32_t extended_tcode:16;
151 uint32_t data_length:16; 151 uint32_t data_length:16;
152 uint32_t crc; 152 uint32_t crc;
153 uint32_t data[0]; 153 uint32_t data[0];
154 /* crc and ack follows. */ 154 /* crc and ack follows. */
155 } write_block; 155 } write_block;
156 156
157 struct { 157 struct {
158 uint32_t common[3]; 158 uint32_t common[3];
159 uint32_t crc; 159 uint32_t crc;
160 } write_response; 160 } write_response;
161 161
162 struct { 162 struct {
163 uint32_t common[3]; 163 uint32_t common[3];
164 uint32_t data; 164 uint32_t data;
165 uint32_t crc; 165 uint32_t crc;
166 } cycle_start; 166 } cycle_start;
167 167
168 struct { 168 struct {
169 uint32_t sy:4; 169 uint32_t sy:4;
170 uint32_t tcode:4; 170 uint32_t tcode:4;
171 uint32_t channel:6; 171 uint32_t channel:6;
172 uint32_t tag:2; 172 uint32_t tag:2;
173 uint32_t data_length:16; 173 uint32_t data_length:16;
174 174
175 uint32_t crc; 175 uint32_t crc;
176 } iso_data; 176 } iso_data;
177 }; 177 };
178}; 178};
179 179
180struct subaction { 180struct subaction {
181 uint32_t ack; 181 uint32_t ack;
182 size_t length; 182 size_t length;
183 struct list link; 183 struct list link;
184 struct link_packet packet; 184 struct link_packet packet;
185}; 185};
186 186
187struct link_transaction { 187struct link_transaction {
188 int request_node, response_node, tlabel; 188 int request_node, response_node, tlabel;
189 struct subaction *request, *response; 189 struct subaction *request, *response;
190 struct list request_list, response_list; 190 struct list request_list, response_list;
191 struct list link; 191 struct list link;
192}; 192};
193 193
194int decode_fcp(struct link_transaction *t); 194int decode_fcp(struct link_transaction *t);