blob: 038488ae2a548e8661bec9ca7b831c30c1a290e5 [file] [log] [blame]
Stefan Reinauerc566d202015-08-25 09:52:42 -07001/*
2 * Copyright 2012-2015 Google Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
Stefan Reinauerc566d202015-08-25 09:52:42 -070012 */
13
14#include <stdio.h>
15#include <string.h>
16#include "em100.h"
17
Stefan Reinauer146eeba2020-12-17 19:26:02 -080018int trace_brief = 0;
19
Stefan Reinauerc566d202015-08-25 09:52:42 -070020/* SPI Trace related operations */
21
22/**
23 * reset_spi_trace: clear SPI trace buffer
24 * @param em100: em100 device structure
25 *
26 * out(16 bytes): 0xbd 0 .. 0
27 */
28int reset_spi_trace(struct em100 *em100)
29{
30 unsigned char cmd[16];
31 memset(cmd, 0, 16);
32 cmd[0] = 0xbd; /* reset SPI trace buffer*/
33 if (!send_cmd(em100->dev, cmd)) {
34 return 0;
35 }
36 return 1;
37}
38
39/**
40 * read_spi_trace: fetch SPI trace data
41 * @param em100: em100 device structure
42 * globals: curpos, counter, cmdid
43 *
44 * out(16 bytes): bc 00 00 00 08 00 00 00 00 15 00 00 00 00 00 00
45 * in(8x8192 bytes): 2 bytes (BE) number of records (0..0x3ff),
46 * then records of 8 bytes each
47 */
48static unsigned int counter = 0;
49static unsigned char curpos = 0;
50static unsigned char cmdid = 0xff; // timestamp, so never a valid command id
51
Martin Roth330de302015-09-17 16:33:07 -060052#define REPORT_BUFFER_LENGTH 8192
53#define REPORT_BUFFER_COUNT 8
54
Stefan Reinauerabd3e322019-12-04 18:29:24 -080055static int read_report_buffer(struct em100 *em100,
Martin Roth330de302015-09-17 16:33:07 -060056 unsigned char reportdata[REPORT_BUFFER_COUNT][REPORT_BUFFER_LENGTH])
Stefan Reinauerc566d202015-08-25 09:52:42 -070057{
Martin Roth330de302015-09-17 16:33:07 -060058 unsigned char cmd[16] = {0};
59 int len;
60 unsigned int report;
61
Stefan Reinauerc566d202015-08-25 09:52:42 -070062 cmd[0] = 0xbc; /* read SPI trace buffer*/
63
Stefan Reinauerabd3e322019-12-04 18:29:24 -080064 /*
Martin Roth330de302015-09-17 16:33:07 -060065 * Trace length, unit is 4k according to specs
66 *
67 * cmd1..cmd4 are probably u32BE on how many
68 * reports (8192 bytes each) to fetch
69 */
Stefan Reinauerc566d202015-08-25 09:52:42 -070070 cmd[1] = 0x00;
71 cmd[2] = 0x00;
72 cmd[3] = 0x00;
Martin Roth330de302015-09-17 16:33:07 -060073 cmd[4] = REPORT_BUFFER_COUNT;
Stefan Reinauerc566d202015-08-25 09:52:42 -070074 /* Timeout in ms */
75 cmd[5] = 0x00;
76 cmd[6] = 0x00;
77 cmd[7] = 0x00;
78 cmd[8] = 0x00;
79 /* Trace Config
80 * [1:0] 00 start/stop spi trace according to emulation status
81 * 01 start when TraceConfig[2] == 1
82 * 10 start when trig signal goes high
83 * 11 RFU
84 * [2] When TraceConfig[1:0] == 01 this bit starts the trace
85 * [7:3] RFU
86 */
87 cmd[9] = 0x15;
88
89 if (!send_cmd(em100->dev, cmd)) {
90 printf("sending trace command failed\n");
91 return 0;
92 }
Stefan Reinauerd7f959b2015-09-03 16:03:40 -070093
Martin Roth330de302015-09-17 16:33:07 -060094 for (report = 0; report < REPORT_BUFFER_COUNT; report++) {
Martin Rothb54d6ba2015-09-29 14:49:37 -060095 len = get_response(em100->dev, &reportdata[report][0],
96 REPORT_BUFFER_LENGTH);
Martin Roth330de302015-09-17 16:33:07 -060097 if (len != REPORT_BUFFER_LENGTH) {
98 printf("error, report length = %d instead of %d.\n\n",
99 len, REPORT_BUFFER_LENGTH);
Stefan Reinauerc566d202015-08-25 09:52:42 -0700100 return 0;
101 }
Martin Roth330de302015-09-17 16:33:07 -0600102 }
103
104 return 1;
105}
106
Stefan Reinauer55e9b042020-12-11 13:41:53 -0800107typedef enum { ADDR_NONE, ADDR_NO_OFF_3B, ADDR_3B, ADDR_4B, ADDR_DYNAMIC } address_t;
108
Martin Rothe8a72dd2015-09-17 17:14:48 -0600109struct spi_cmd_values {
Stefan Reinauer79533882019-11-22 00:57:29 -0800110 const char *cmd_name;
Martin Rothe8a72dd2015-09-17 17:14:48 -0600111 uint8_t cmd;
Stefan Reinauer55e9b042020-12-11 13:41:53 -0800112 address_t address_type;
Martin Rothe8a72dd2015-09-17 17:14:48 -0600113 uint8_t pad_bytes;
114};
115
116struct spi_cmd_values spi_command_list[] = {
Stefan Reinauer55e9b042020-12-11 13:41:53 -0800117 /* name cmd, addr, pad */
118 {"read SFDP", 0x5a, ADDR_NO_OFF_3B, 0},
119 {"write status register", 0x01, ADDR_NONE, 0},
120 {"page program", 0x02, ADDR_DYNAMIC, 0},
121 {"read", 0x03, ADDR_DYNAMIC, 0},
122 {"write disable", 0x04, ADDR_NONE, 0},
123 {"read status register", 0x05, ADDR_NONE, 0},
124 {"write enable", 0x06, ADDR_NONE, 0},
125 {"fast read", 0x0b, ADDR_DYNAMIC, 1},
126 {"EM100 specific", 0x11, ADDR_NONE, 0},
127 {"fast dual read", 0x3b, ADDR_DYNAMIC, 2},
128 {"chip erase", 0x60, ADDR_NONE, 0},
129 {"read JEDEC ID", 0x9f, ADDR_NONE, 0},
130 {"chip erase c7h", 0xc7, ADDR_NONE, 0},
131 {"chip erase 60h", 0x60, ADDR_NONE, 0},
132 {"sector erase", 0xd8, ADDR_DYNAMIC, 0},
133 {"dual I/O read", 0xbb, ADDR_DYNAMIC, 2},
134 {"quad I/O read", 0xeb, ADDR_DYNAMIC, 0},
135 {"quad read", 0x6b, ADDR_DYNAMIC, 0},
136 {"quad I/O dt read", 0xed, ADDR_DYNAMIC, 0},
137 {"quad page program", 0x38, ADDR_DYNAMIC, 0},
138 {"sector erase", 0x20, ADDR_DYNAMIC, 0},
139 {"block erase 32KB", 0x52, ADDR_DYNAMIC, 0},
140 {"block erase 64KB", 0xd8, ADDR_DYNAMIC, 0},
141 {"enter 4b mode", 0xb7, ADDR_NONE, 0},
142 {"exit 4b mode", 0xe9, ADDR_NONE, 0},
143 {"read 4b", 0x13, ADDR_4B, 0},
144 {"fast read 4b", 0x0c, ADDR_4B, 0},
145 {"dual I/O read 4b", 0xbc, ADDR_4B, 0},
146 {"dual out read 4b", 0x3c, ADDR_4B, 0},
147 {"quad I/O read 4b", 0xec, ADDR_4B, 0},
148 {"quad out read 4b", 0x6c, ADDR_4B, 0},
149 {"quad I/O dt read 4b", 0xee, ADDR_4B, 0},
150 {"page program 4b", 0x12, ADDR_4B, 0},
151 {"quad page program 4b", 0x3e, ADDR_4B, 0},
152 {"block erase 64KB 4b", 0xdc, ADDR_4B, 0},
153 {"block erase 32KB 4b", 0x5c, ADDR_4B, 0},
154 {"sector erase 4b", 0x21, ADDR_4B, 0},
155 {"enter quad I/O mode", 0x35, ADDR_NONE, 0},
156 {"exit quad I/O mode", 0xf5, ADDR_NONE, 0},
Martin Rothe8a72dd2015-09-17 17:14:48 -0600157
Stefan Reinauer55e9b042020-12-11 13:41:53 -0800158 {"unknown command", 0xff, ADDR_NONE, 0}
159
Martin Rothe8a72dd2015-09-17 17:14:48 -0600160};
161
Stefan Reinauerabd3e322019-12-04 18:29:24 -0800162static struct spi_cmd_values * get_command_vals(uint8_t command)
163{
Martin Rothe8a72dd2015-09-17 17:14:48 -0600164 /* cache last command so a search isn't needed every time */
165 static struct spi_cmd_values *spi_cmd = &spi_command_list[3]; /* init to read */
166 int i;
167
168 if (spi_cmd->cmd != command) {
169 for (i = 0; spi_command_list[i].cmd != 0xff; i++) {
170 if (spi_command_list[i].cmd == command)
171 break;
172 }
173 spi_cmd = &spi_command_list[i];
174 }
175
176 return spi_cmd;
177}
178
179#define MAX_TRACE_BLOCKLENGTH 6
Martin Roth712262a2015-09-18 14:01:18 -0600180int read_spi_trace(struct em100 *em100, int display_terminal,
181 unsigned long addr_offset)
Martin Roth330de302015-09-17 16:33:07 -0600182{
Martin Rothb54d6ba2015-09-29 14:49:37 -0600183 unsigned char reportdata[REPORT_BUFFER_COUNT][REPORT_BUFFER_LENGTH] =
184 {{0}};
Martin Roth330de302015-09-17 16:33:07 -0600185 unsigned char *data;
186 unsigned int count, i, report;
187 static int outbytes = 0;
Martin Rothe8a72dd2015-09-17 17:14:48 -0600188 static int additional_pad_bytes = 0;
Stefan Reinauer55e9b042020-12-11 13:41:53 -0800189 static unsigned long address = 0;
Martin Rothe8a72dd2015-09-17 17:14:48 -0600190 static unsigned long long timestamp = 0;
191 static unsigned long long start_timestamp = 0;
192 static struct spi_cmd_values *spi_cmd_vals = &spi_command_list[3];
Martin Roth330de302015-09-17 16:33:07 -0600193
194 if (!read_report_buffer(em100, reportdata))
195 return 0;
196
197 for (report = 0; report < REPORT_BUFFER_COUNT; report++) {
198 data = &reportdata[report][0];
Stefan Reinauerc566d202015-08-25 09:52:42 -0700199 count = (data[0] << 8) | data[1];
Stefan Reinauerd6180e22020-12-11 14:20:57 -0800200 if (!count)
201 continue;
202 if (count > 1023) {
Stefan Reinauer2372d7a2015-10-10 10:46:45 +0000203 printf("Warning: EM100pro sends too much data.\n");
Stefan Reinauerd6180e22020-12-11 14:20:57 -0800204 count = 1023;
Stefan Reinauer2372d7a2015-10-10 10:46:45 +0000205 }
Stefan Reinauerc566d202015-08-25 09:52:42 -0700206 for (i = 0; i < count; i++) {
Stefan Reinauer55e9b042020-12-11 13:41:53 -0800207 int address_bytes = 0;
Martin Rothe8a72dd2015-09-17 17:14:48 -0600208 unsigned int j = additional_pad_bytes;
209 additional_pad_bytes = 0;
Stefan Reinauerc566d202015-08-25 09:52:42 -0700210 unsigned char cmd = data[2 + i*8];
Stefan Reinauerdfb107d2020-12-10 19:22:40 -0800211
212 if (cmd == 0x00) {
213 /* packet without valid data */
214 continue;
215 }
Stefan Reinauerc566d202015-08-25 09:52:42 -0700216 if (cmd == 0xff) {
217 /* timestamp */
Stefan Reinauerc566d202015-08-25 09:52:42 -0700218 timestamp = data[2 + i*8 + 2];
219 timestamp = (timestamp << 8) | data[2 + i*8 + 3];
220 timestamp = (timestamp << 8) | data[2 + i*8 + 4];
221 timestamp = (timestamp << 8) | data[2 + i*8 + 5];
222 timestamp = (timestamp << 8) | data[2 + i*8 + 6];
223 timestamp = (timestamp << 8) | data[2 + i*8 + 7];
Martin Rothdfdff3e2015-09-18 09:42:03 -0600224 if (display_terminal)
225 read_spi_terminal(em100, 1);
Stefan Reinauerc566d202015-08-25 09:52:42 -0700226 continue;
227 }
Martin Rothe8a72dd2015-09-17 17:14:48 -0600228
Stefan Reinauerc566d202015-08-25 09:52:42 -0700229 /* from here, it must be data */
230 if (cmd != cmdid) {
Martin Rothe8a72dd2015-09-17 17:14:48 -0600231 unsigned char spi_command = data[i * 8 + 4];
232 spi_cmd_vals = get_command_vals(spi_command);
233
Stefan Reinauerc566d202015-08-25 09:52:42 -0700234 /* new command */
235 cmdid = cmd;
Martin Rothe8a72dd2015-09-17 17:14:48 -0600236 if (counter == 0)
237 start_timestamp = timestamp;
238
Stefan Reinauerdfb107d2020-12-10 19:22:40 -0800239 /* Special commands */
240 switch (spi_command) {
241 case 0xb7:
242 address_mode = 4;
243 break;
244 case 0xe9:
245 address_mode = 3;
246 break;
247 }
248
Stefan Reinauer55e9b042020-12-11 13:41:53 -0800249 /* skip command byte */
250 j = 1;
Martin Rothe8a72dd2015-09-17 17:14:48 -0600251
Stefan Reinauer55e9b042020-12-11 13:41:53 -0800252 /* Set up address if used by this command */
253 switch (spi_cmd_vals->address_type) {
254 case ADDR_DYNAMIC:
255 address_bytes = address_mode;
256 break;
257 case ADDR_NO_OFF_3B:
258 case ADDR_3B:
259 address_bytes = 3;
260 break;
261 case ADDR_4B:
262 address_bytes = 4;
263 break;
264 case ADDR_NONE:
265 break;
Martin Rothe8a72dd2015-09-17 17:14:48 -0600266 }
Stefan Reinauer55e9b042020-12-11 13:41:53 -0800267
268 if (address_bytes == 3)
269 address = (data[i * 8 + 5] << 16)
270 + (data[i * 8 + 6] << 8)
271 + data[i * 8 + 7];
272 else if (address_bytes == 4)
273 address = (data[i * 8 + 5] << 24)
274 + (data[i * 8 + 6] << 16)
275 + (data[i * 8 + 7] << 8)
276 + data[i * 8 + 8];
277
Patrick Georgi62df8622021-10-18 20:08:28 +0200278 /* truncate any potential sign extension */
279 address &= 0xffffffff;
280
Stefan Reinauer55e9b042020-12-11 13:41:53 -0800281 /* skip address bytes and padding */
282 j += address_bytes + spi_cmd_vals->pad_bytes;
283
284 if (j > MAX_TRACE_BLOCKLENGTH) {
285 additional_pad_bytes = j -
286 MAX_TRACE_BLOCKLENGTH;
287 j = MAX_TRACE_BLOCKLENGTH;
288 }
289
Stefan Reinauer146eeba2020-12-17 19:26:02 -0800290 if (trace_brief) {
291 if (start_timestamp)
292 start_timestamp = 0;
293
294 if (spi_cmd_vals->address_type != ADDR_NONE)
295 printf("0x%02x @ 0x%08lx (%s)\n",
296 spi_command, address, spi_cmd_vals->cmd_name);
297 else
298 printf("0x%02x (%s)\n",
299 spi_command, spi_cmd_vals->cmd_name);
300 } else {
301 printf("\nTime: %06lld.%08lld",
Martin Rothb54d6ba2015-09-29 14:49:37 -0600302 (timestamp - start_timestamp) /
303 100000000,
304 (timestamp - start_timestamp) %
305 100000000);
Stefan Reinauer146eeba2020-12-17 19:26:02 -0800306 printf(" command # %-6d : 0x%02x - %s",
Martin Rothb54d6ba2015-09-29 14:49:37 -0600307 ++counter, spi_command,
308 spi_cmd_vals->cmd_name);
Stefan Reinauer146eeba2020-12-17 19:26:02 -0800309 }
310
Stefan Reinauerc566d202015-08-25 09:52:42 -0700311 curpos = 0;
Stefan Reinauerd7f959b2015-09-03 16:03:40 -0700312 outbytes = 0;
Stefan Reinauerc566d202015-08-25 09:52:42 -0700313 }
Martin Rothe8a72dd2015-09-17 17:14:48 -0600314
Stefan Reinauer146eeba2020-12-17 19:26:02 -0800315 if (trace_brief) {
316 if (outbytes)
317 outbytes++;
318 } else {
319 /* this exploits 8bit wrap around in curpos */
320 unsigned char blocklen = (data[2 + i*8 + 1] - curpos);
321 blocklen /= 8;
Martin Rothe8a72dd2015-09-17 17:14:48 -0600322
Stefan Reinauer146eeba2020-12-17 19:26:02 -0800323 for (; j < blocklen; j++) {
324 if (outbytes == 0) {
325 switch (spi_cmd_vals->address_type) {
326 case ADDR_DYNAMIC:
327 case ADDR_3B:
328 case ADDR_4B:
329 printf("\n%08lx : ",
330 addr_offset + address);
331 break;
332 case ADDR_NO_OFF_3B:
333 printf("\n%08lx : ", address);
334 break;
335 case ADDR_NONE:
336 printf("\n : ");
337 break;
338 }
Martin Rothe8a72dd2015-09-17 17:14:48 -0600339 }
Stefan Reinauer146eeba2020-12-17 19:26:02 -0800340 printf("%02x ", data[i * 8 + 4 + j]);
341 outbytes++;
342 if (outbytes == 16) {
343 outbytes = 0;
344 address += 16;
345 }
Stefan Reinauerd7f959b2015-09-03 16:03:40 -0700346 }
Stefan Reinauerc566d202015-08-25 09:52:42 -0700347 }
Martin Rothb54d6ba2015-09-29 14:49:37 -0600348 // this is because the em100 counts funny
349 curpos = data[2 + i*8 + 1] + 0x10;
Martin Rothe8a72dd2015-09-17 17:14:48 -0600350 fflush(stdout);
Stefan Reinauerc566d202015-08-25 09:52:42 -0700351 }
352 }
353 return 1;
354}
Martin Rothdfdff3e2015-09-18 09:42:03 -0600355
Stefan Reinauercafd1512020-12-11 17:36:28 -0800356int read_spi_trace_console(struct em100 *em100, unsigned long addr_offset,
357 unsigned long addr_len)
358{
359 unsigned char reportdata[REPORT_BUFFER_COUNT][REPORT_BUFFER_LENGTH] =
360 {{0}};
361 unsigned char *data;
362 unsigned int count, i, report;
363 static int additional_pad_bytes = 0;
364 static unsigned int address = 0;
365 static int do_write = 0;
366 static struct spi_cmd_values *spi_cmd_vals = &spi_command_list[3];
367 int addr_bytes = 0;
368
369 if (addr_offset == 0) {
370 printf("Address offset for console buffer required\n");
371 return -1;
372 }
373 if (addr_len == 0) {
374 printf("Console buffer length required\n");
375 return -1;
376 }
377
378 if (!read_report_buffer(em100, reportdata))
379 return -1;
380
381 for (report = 0; report < REPORT_BUFFER_COUNT; report++) {
382 data = &reportdata[report][0];
383 count = (data[0] << 8) | data[1];
384 if (!count)
385 continue;
386 if (count > 1023) {
387 printf("Warning: EM100pro sends too much data: %d.\n", count);
388 count = 1023;
389 }
390 for (i = 0; i < count; i++) {
391 unsigned int j = additional_pad_bytes;
392 unsigned int address_bytes = 0;
393 additional_pad_bytes = 0;
394 unsigned char cmd = data[2 + i*8];
395
396 /* from here, it must be data */
397 if (cmd != cmdid) {
398 unsigned char spi_command = data[i * 8 + 4];
399 spi_cmd_vals = get_command_vals(spi_command);
400
401 /* new command */
402 cmdid = cmd;
403
404 /* Special commands */
405 switch (spi_command) {
406 case 0xb7:
407 address_mode = 4;
408 break;
409 case 0xe9:
410 address_mode = 3;
411 break;
412 }
413
414 /* skip command byte */
415 j = 1;
416
417 /* Set up address if used by this command */
418 switch (spi_cmd_vals->address_type) {
419 case ADDR_DYNAMIC:
420 address_bytes = address_mode;
421 break;
422 case ADDR_NO_OFF_3B:
423 case ADDR_3B:
424 address_bytes = 3;
425 break;
426 case ADDR_4B:
427 address_bytes = 4;
428 break;
429 case ADDR_NONE:
430 break;
431 }
432
433 if (address_bytes == 3)
434 address = (data[i * 8 + 5] << 16)
435 + (data[i * 8 + 6] << 8)
436 + data[i * 8 + 7];
437 else if (address_bytes == 4)
438 address = (data[i * 8 + 5] << 24)
439 + (data[i * 8 + 6] << 16)
440 + (data[i * 8 + 7] << 8)
441 + data[i * 8 + 8];
442
443 /* skip address bytes and padding */
444 j += address_bytes + spi_cmd_vals->pad_bytes;
445
446 if (j > MAX_TRACE_BLOCKLENGTH) {
447 additional_pad_bytes = j -
448 MAX_TRACE_BLOCKLENGTH;
449 j = MAX_TRACE_BLOCKLENGTH;
450 }
451
452#if 0
453 if (spi_cmd_vals->address_type != ADDR_NONE)
454 printf("0x%02x @ 0x%08x (%s)\n",
455 spi_command, address, spi_cmd_vals->cmd_name);
456 else
457 printf("0x%02x (%s)\n",
458 spi_command, spi_cmd_vals->cmd_name);
459#endif
460
461 curpos = 0;
462 if (spi_command == 0x02)
463 do_write = 1;
464 else
465 do_write = 0;
466 }
467
468 if (do_write == 0 ||
469 (spi_cmd_vals->address_type == ADDR_NONE ||
470 address < addr_offset ||
471 address > (addr_offset + addr_len))) {
472 curpos = data[2 + i*8 + 1] + 0x10;
473 continue;
474 }
475
476 /* this exploits 8bit wrap around in curpos */
477 unsigned char blocklen = (data[2 + i*8 + 1] - curpos);
478 blocklen /= 8;
479
480 for (; j < blocklen; j++) {
481 printf("%c", data[i * 8 + addr_bytes + j]);
482 }
483
484 /* this is because the em100 counts funny */
485 curpos = data[2 + i*8 + 1] + 0x10;
486 fflush(stdout);
487 }
488 }
489 return 1;
490}
491
Martin Rothdfdff3e2015-09-18 09:42:03 -0600492#define UFIFO_SIZE 512
493#define UFIFO_TIMEOUT 0x00
494
495/*
496 * Polls the uFIFO buffer to see if there's any data. The HT registers don't
497 * seem to ever be updated to reflect that there's data present, and the
498 * Dediprog software doesn't use them either.
Martin Rothc69319c2015-09-29 14:09:40 -0600499 *
Martin Rothdfdff3e2015-09-18 09:42:03 -0600500 * Multiple messages can be in a single uFIFO transfer, so loop through
501 * the data looking for the signature.
502 */
Stefan Reinauerabd3e322019-12-04 18:29:24 -0800503int read_spi_terminal(struct em100 *em100, int show_counter)
504{
Martin Rothdfdff3e2015-09-18 09:42:03 -0600505 unsigned char data[UFIFO_SIZE] = { 0 };
506 static unsigned int msg_counter = 1; /* Number of messages */
Martin Rothc69319c2015-09-29 14:09:40 -0600507 uint16_t data_length;
Martin Rothdfdff3e2015-09-18 09:42:03 -0600508 unsigned char *data_start;
509 unsigned int j, k;
510 struct em100_msg *msg = NULL;
511
512 if (!read_ufifo(em100, UFIFO_SIZE, UFIFO_TIMEOUT, &data[0]))
513 return 0;
514
515 /* the first two bytes are the amount of valid data */
Martin Rothc69319c2015-09-29 14:09:40 -0600516 data_length = (data[0] << 8) + data[1];
517 if (data_length == 0)
Martin Rothdfdff3e2015-09-18 09:42:03 -0600518 return 1;
519
520 /* actual data starts after the length */
521 data_start = &data[sizeof(uint16_t)];
522
523 /* examine data; stop when we run out of message or buffer */
Martin Rothc69319c2015-09-29 14:09:40 -0600524 for (j = 0; j < data_length &&
Martin Rothdfdff3e2015-09-18 09:42:03 -0600525 j < UFIFO_SIZE - sizeof(struct em100_msg_header); j++) {
526
527 msg = (struct em100_msg *)(data_start + j);
528 if (msg->header.signature == EM100_MSG_SIGNATURE) {
529
530 if (show_counter)
531 printf("\nHT%06d: ", msg_counter);
532
533 /* print message byte according to format */
534 for (k = 0; k < msg->header.data_length; k++) {
Martin Rothc69319c2015-09-29 14:09:40 -0600535 if (&msg->data[k] >= data_start + data_length)
Martin Rothdfdff3e2015-09-18 09:42:03 -0600536 break;
537 if (&msg->data[k] >= &data[0] + UFIFO_SIZE)
538 break;
539
540 switch (msg->header.data_type) {
541 case ht_checkpoint_1byte:
542 case ht_checkpoint_2bytes:
543 case ht_checkpoint_4bytes:
544 case ht_hexadecimal_data:
545 case ht_timestamp_data:
546 printf("%02x ", msg->data[k]);
547 break;
548 case ht_ascii_data:
549 printf("%c", msg->data[k]);
550 break;
551 case ht_lookup_table:
552 /* TODO - support lookup table */
553 printf("Lookup unsupported: %02x%02x",
554 msg->data[k], msg->data[k + 1]);
555 k++;
556 break;
557 }
558 }
559
560 /* advance to the end of the message */
Martin Rothb54d6ba2015-09-29 14:49:37 -0600561 j += msg->header.data_length +
562 sizeof(struct em100_msg_header) - 1;
Martin Rothdfdff3e2015-09-18 09:42:03 -0600563 msg_counter++;
564 fflush(stdout);
565 }
566 }
567
568 return 1;
569}
570
571int init_spi_terminal (struct em100 *em100)
572{
573 int retval = 0x01;
574 uint16_t val;
575
576 retval &= write_ht_register(em100, ufifo_data_fmt_reg, 0);
577 retval &= write_ht_register(em100, status_reg, START_SPI_EMULATION);
578
579 /* set em100 to recognize spi command 0x11 */
580 retval &= write_fpga_register(em100, 0x82, EM100_SPECIFIC_CMD);
581 retval &= read_fpga_register(em100, 0x28, &val);
582
583 return retval;
584}