aboutsummaryrefslogtreecommitdiffstats
path: root/tools/firewire/nosy-dump.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/firewire/nosy-dump.c')
-rw-r--r--tools/firewire/nosy-dump.c1663
1 files changed, 819 insertions, 844 deletions
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}