server/gdb-server: fix type error.
[openocd.git] / src / server / ipdbg.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Copyright (C) 2020 by Daniel Anselmi <danselmi@gmx.ch> */
3
4 #ifdef HAVE_CONFIG_H
5 #include "config.h"
6 #endif
7
8 #include <helper/bits.h>
9 #include <helper/time_support.h>
10 #include <jtag/jtag.h>
11 #include <server/server.h>
12 #include <target/target.h>
13 #include <pld/pld.h>
14
15 #include "ipdbg.h"
16
17 #define IPDBG_BUFFER_SIZE 16384
18 #define IPDBG_MIN_NUM_OF_OPTIONS 2
19 #define IPDBG_MAX_NUM_OF_OPTIONS 14
20 #define IPDBG_MIN_DR_LENGTH 11
21 #define IPDBG_MAX_DR_LENGTH 13
22 #define IPDBG_TCP_PORT_STR_MAX_LENGTH 6
23 #define IPDBG_SCRATCH_MEMORY_SIZE 1024
24 #define IPDBG_EMPTY_DOWN_TRANSFERS 1024
25 #define IPDBG_CONSECUTIVE_UP_TRANSFERS 1024
26
27 #if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_EMPTY_DOWN_TRANSFERS
28 #error "scratch Memory must be at least IPDBG_EMPTY_DOWN_TRANSFERS"
29 #endif
30
31 #if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_CONSECUTIVE_UP_TRANSFERS
32 #error "scratch Memory must be at least IPDBG_CONSECUTIVE_UP_TRANSFERS"
33 #endif
34
35 /* private connection data for IPDBG */
36 struct ipdbg_fifo {
37 size_t count;
38 size_t rd_idx;
39 char buffer[IPDBG_BUFFER_SIZE];
40 };
41
42 struct ipdbg_connection {
43 struct ipdbg_fifo dn_fifo;
44 struct ipdbg_fifo up_fifo;
45 bool closed;
46 };
47
48 struct ipdbg_service {
49 struct ipdbg_hub *hub;
50 struct ipdbg_service *next;
51 uint16_t port;
52 struct ipdbg_connection connection;
53 uint8_t tool;
54 };
55
56 struct ipdbg_virtual_ir_info {
57 uint32_t instruction;
58 uint32_t length;
59 uint32_t value;
60 };
61
62 struct ipdbg_hub_scratch_memory {
63 uint8_t *dr_out_vals;
64 uint8_t *dr_in_vals;
65 uint8_t *vir_out_val;
66 struct scan_field *fields;
67 };
68
69 struct ipdbg_hub {
70 uint32_t user_instruction;
71 uint32_t max_tools;
72 uint32_t active_connections;
73 uint32_t active_services;
74 uint32_t valid_mask;
75 uint32_t xoff_mask;
76 uint32_t tool_mask;
77 uint32_t last_dn_tool;
78 struct ipdbg_hub *next;
79 struct jtag_tap *tap;
80 struct connection **connections;
81 uint8_t data_register_length;
82 uint8_t dn_xoff;
83 uint8_t flow_control_enabled;
84 struct ipdbg_virtual_ir_info *virtual_ir;
85 struct ipdbg_hub_scratch_memory scratch_memory;
86 };
87
88 static struct ipdbg_hub *ipdbg_first_hub;
89
90 static struct ipdbg_service *ipdbg_first_service;
91
92 static void ipdbg_init_fifo(struct ipdbg_fifo *fifo)
93 {
94 fifo->count = 0;
95 fifo->rd_idx = 0;
96 }
97
98 static bool ipdbg_fifo_is_empty(struct ipdbg_fifo *fifo)
99 {
100 return fifo->count == 0;
101 }
102
103 static bool ipdbg_fifo_is_full(struct ipdbg_fifo *fifo)
104 {
105 return fifo->count == IPDBG_BUFFER_SIZE;
106 }
107
108 static void ipdbg_zero_rd_idx(struct ipdbg_fifo *fifo)
109 {
110 if (fifo->rd_idx == 0)
111 return;
112
113 size_t ri = fifo->rd_idx;
114 for (size_t idx = 0; idx < fifo->count; ++idx)
115 fifo->buffer[idx] = fifo->buffer[ri++];
116 fifo->rd_idx = 0;
117 }
118
119 static void ipdbg_append_to_fifo(struct ipdbg_fifo *fifo, char data)
120 {
121 if (ipdbg_fifo_is_full(fifo))
122 return;
123
124 ipdbg_zero_rd_idx(fifo);
125 fifo->buffer[fifo->count++] = data;
126 }
127
128 static char ipdbg_get_from_fifo(struct ipdbg_fifo *fifo)
129 {
130 if (ipdbg_fifo_is_empty(fifo))
131 return 0;
132
133 fifo->count--;
134 return fifo->buffer[fifo->rd_idx++];
135 }
136
137 static int ipdbg_move_buffer_to_connection(struct connection *conn, struct ipdbg_fifo *fifo)
138 {
139 if (ipdbg_fifo_is_empty(fifo))
140 return ERROR_OK;
141
142 struct ipdbg_connection *connection = conn->priv;
143 if (connection->closed)
144 return ERROR_SERVER_REMOTE_CLOSED;
145
146 ipdbg_zero_rd_idx(fifo);
147 size_t bytes_written = connection_write(conn, fifo->buffer, fifo->count);
148 if (bytes_written != fifo->count) {
149 LOG_ERROR("error during write: %zu != %zu", bytes_written, fifo->count);
150 connection->closed = true;
151 return ERROR_SERVER_REMOTE_CLOSED;
152 }
153
154 fifo->count -= bytes_written;
155
156 return ERROR_OK;
157 }
158
159 static int ipdbg_max_tools_from_data_register_length(uint8_t data_register_length)
160 {
161 int max_tools = 1;
162 data_register_length -= 10; /* 8 bit payload, 1 xoff-flag, 1 valid-flag; remaining bits used to select tool*/
163 while (data_register_length--)
164 max_tools *= 2;
165
166 /* last tool is used to reset JtagCDC and transfer "XON" to host*/
167 return max_tools - 1;
168 }
169
170 static struct ipdbg_service *ipdbg_find_service(struct ipdbg_hub *hub, uint8_t tool)
171 {
172 struct ipdbg_service *service;
173 for (service = ipdbg_first_service; service; service = service->next) {
174 if (service->hub == hub && service->tool == tool)
175 break;
176 }
177 return service;
178 }
179
180 static void ipdbg_add_service(struct ipdbg_service *service)
181 {
182 struct ipdbg_service *iservice;
183 if (ipdbg_first_service) {
184 for (iservice = ipdbg_first_service; iservice->next; iservice = iservice->next)
185 ;
186 iservice->next = service;
187 } else
188 ipdbg_first_service = service;
189 }
190
191 static int ipdbg_create_service(struct ipdbg_hub *hub, uint8_t tool, struct ipdbg_service **service, uint16_t port)
192 {
193 *service = calloc(1, sizeof(struct ipdbg_service));
194 if (!*service) {
195 LOG_ERROR("Out of memory");
196 return ERROR_FAIL;
197 }
198
199 (*service)->hub = hub;
200 (*service)->tool = tool;
201 (*service)->port = port;
202
203 return ERROR_OK;
204 }
205
206 static int ipdbg_remove_service(struct ipdbg_service *service)
207 {
208 if (!ipdbg_first_service)
209 return ERROR_FAIL;
210
211 if (service == ipdbg_first_service) {
212 ipdbg_first_service = ipdbg_first_service->next;
213 return ERROR_OK;
214 }
215
216 for (struct ipdbg_service *iservice = ipdbg_first_service; iservice->next; iservice = iservice->next) {
217 if (service == iservice->next) {
218 iservice->next = service->next;
219 return ERROR_OK;
220 }
221 }
222 return ERROR_FAIL;
223 }
224
225 static struct ipdbg_hub *ipdbg_find_hub(struct jtag_tap *tap,
226 uint32_t user_instruction, struct ipdbg_virtual_ir_info *virtual_ir)
227 {
228 struct ipdbg_hub *hub = NULL;
229 for (hub = ipdbg_first_hub; hub; hub = hub->next) {
230 if (hub->tap == tap && hub->user_instruction == user_instruction) {
231 if ((!virtual_ir && !hub->virtual_ir) ||
232 (virtual_ir && hub->virtual_ir &&
233 virtual_ir->instruction == hub->virtual_ir->instruction &&
234 virtual_ir->length == hub->virtual_ir->length &&
235 virtual_ir->value == hub->virtual_ir->value)) {
236 break;
237 }
238 }
239 }
240 return hub;
241 }
242
243 static void ipdbg_add_hub(struct ipdbg_hub *hub)
244 {
245 struct ipdbg_hub *ihub;
246 if (ipdbg_first_hub) {
247 for (ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next)
248 ;
249 ihub->next = hub;
250 } else
251 ipdbg_first_hub = hub;
252 }
253
254 static int ipdbg_create_hub(struct jtag_tap *tap, uint32_t user_instruction, uint8_t data_register_length,
255 struct ipdbg_virtual_ir_info *virtual_ir, struct ipdbg_hub **hub)
256 {
257 *hub = NULL;
258 struct ipdbg_hub *new_hub = calloc(1, sizeof(struct ipdbg_hub));
259 if (!new_hub)
260 goto mem_err_hub;
261
262 const size_t dreg_buffer_size = DIV_ROUND_UP(data_register_length, 8);
263 new_hub->max_tools = ipdbg_max_tools_from_data_register_length(data_register_length);
264
265 new_hub->scratch_memory.dr_out_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size);
266 new_hub->scratch_memory.dr_in_vals = calloc(IPDBG_SCRATCH_MEMORY_SIZE, dreg_buffer_size);
267 new_hub->scratch_memory.fields = calloc(IPDBG_SCRATCH_MEMORY_SIZE, sizeof(struct scan_field));
268 new_hub->connections = calloc(new_hub->max_tools, sizeof(struct connection *));
269
270 if (virtual_ir)
271 new_hub->scratch_memory.vir_out_val = calloc(1, DIV_ROUND_UP(virtual_ir->length, 8));
272
273 if (!new_hub->scratch_memory.dr_out_vals || !new_hub->scratch_memory.dr_in_vals ||
274 !new_hub->scratch_memory.fields || (virtual_ir && !new_hub->scratch_memory.vir_out_val) ||
275 !new_hub->connections)
276 goto mem_err2;
277
278 if (virtual_ir)
279 buf_set_u32(new_hub->scratch_memory.vir_out_val, 0, virtual_ir->length, virtual_ir->value);
280
281 new_hub->tap = tap;
282 new_hub->user_instruction = user_instruction;
283 new_hub->data_register_length = data_register_length;
284 new_hub->valid_mask = BIT(data_register_length - 1);
285 new_hub->xoff_mask = BIT(data_register_length - 2);
286 new_hub->tool_mask = (new_hub->xoff_mask - 1) >> 8;
287 new_hub->last_dn_tool = new_hub->tool_mask;
288 new_hub->virtual_ir = virtual_ir;
289
290 *hub = new_hub;
291 return ERROR_OK;
292
293 mem_err2:
294 free(new_hub->scratch_memory.vir_out_val);
295 free(new_hub->connections);
296 free(new_hub->scratch_memory.fields);
297 free(new_hub->scratch_memory.dr_in_vals);
298 free(new_hub->scratch_memory.dr_out_vals);
299 free(new_hub);
300 mem_err_hub:
301 free(virtual_ir);
302 LOG_ERROR("Out of memory");
303 return ERROR_FAIL;
304 }
305
306 static void ipdbg_free_hub(struct ipdbg_hub *hub)
307 {
308 if (!hub)
309 return;
310 free(hub->connections);
311 free(hub->virtual_ir);
312 free(hub->scratch_memory.dr_out_vals);
313 free(hub->scratch_memory.dr_in_vals);
314 free(hub->scratch_memory.fields);
315 free(hub->scratch_memory.vir_out_val);
316 free(hub);
317 }
318
319 static int ipdbg_remove_hub(struct ipdbg_hub *hub)
320 {
321 if (!ipdbg_first_hub)
322 return ERROR_FAIL;
323 if (hub == ipdbg_first_hub) {
324 ipdbg_first_hub = ipdbg_first_hub->next;
325 return ERROR_OK;
326 }
327
328 for (struct ipdbg_hub *ihub = ipdbg_first_hub; ihub->next; ihub = ihub->next) {
329 if (hub == ihub->next) {
330 ihub->next = hub->next;
331 return ERROR_OK;
332 }
333 }
334
335 return ERROR_FAIL;
336 }
337
338 static void ipdbg_init_scan_field(struct scan_field *fields, uint8_t *in_value, int num_bits, const uint8_t *out_value)
339 {
340 fields->check_mask = NULL;
341 fields->check_value = NULL;
342 fields->in_value = in_value;
343 fields->num_bits = num_bits;
344 fields->out_value = out_value;
345 }
346
347 static int ipdbg_shift_instr(struct ipdbg_hub *hub, uint32_t instr)
348 {
349 if (!hub)
350 return ERROR_FAIL;
351
352 struct jtag_tap *tap = hub->tap;
353 if (!tap)
354 return ERROR_FAIL;
355
356 if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) == instr) {
357 /* there is already the requested instruction in the ir */
358 return ERROR_OK;
359 }
360
361 uint8_t *ir_out_val = calloc(DIV_ROUND_UP(tap->ir_length, 8), 1);
362 if (!ir_out_val) {
363 LOG_ERROR("Out of memory");
364 return ERROR_FAIL;
365 }
366 buf_set_u32(ir_out_val, 0, tap->ir_length, instr);
367
368 struct scan_field fields;
369 ipdbg_init_scan_field(&fields, NULL, tap->ir_length, ir_out_val);
370 jtag_add_ir_scan(tap, &fields, TAP_IDLE);
371 int retval = jtag_execute_queue();
372
373 free(ir_out_val);
374
375 return retval;
376 }
377
378 static int ipdbg_shift_vir(struct ipdbg_hub *hub)
379 {
380 if (!hub)
381 return ERROR_FAIL;
382
383 if (!hub->virtual_ir)
384 return ERROR_OK;
385
386 int retval = ipdbg_shift_instr(hub, hub->virtual_ir->instruction);
387 if (retval != ERROR_OK)
388 return retval;
389
390 struct jtag_tap *tap = hub->tap;
391 if (!tap)
392 return ERROR_FAIL;
393
394 ipdbg_init_scan_field(hub->scratch_memory.fields, NULL,
395 hub->virtual_ir->length, hub->scratch_memory.vir_out_val);
396 jtag_add_dr_scan(tap, 1, hub->scratch_memory.fields, TAP_IDLE);
397 retval = jtag_execute_queue();
398
399 return retval;
400 }
401
402 static int ipdbg_shift_data(struct ipdbg_hub *hub, uint32_t dn_data, uint32_t *up_data)
403 {
404 if (!hub)
405 return ERROR_FAIL;
406
407 struct jtag_tap *tap = hub->tap;
408 if (!tap)
409 return ERROR_FAIL;
410
411 buf_set_u32(hub->scratch_memory.dr_out_vals, 0, hub->data_register_length, dn_data);
412
413 ipdbg_init_scan_field(hub->scratch_memory.fields, hub->scratch_memory.dr_in_vals,
414 hub->data_register_length, hub->scratch_memory.dr_out_vals);
415 jtag_add_dr_scan(tap, 1, hub->scratch_memory.fields, TAP_IDLE);
416 int retval = jtag_execute_queue();
417
418 if (up_data && retval == ERROR_OK)
419 *up_data = buf_get_u32(hub->scratch_memory.dr_in_vals, 0, hub->data_register_length);
420
421 return retval;
422 }
423
424 static int ipdbg_distribute_data_from_hub(struct ipdbg_hub *hub, uint32_t up)
425 {
426 const bool valid_up_data = up & hub->valid_mask;
427 if (!valid_up_data)
428 return ERROR_OK;
429
430 const size_t tool = (up >> 8) & hub->tool_mask;
431 if (tool == hub->tool_mask) {
432 const uint8_t xon_cmd = up & 0x00ff;
433 hub->dn_xoff &= ~xon_cmd;
434 LOG_INFO("received xon cmd: %d\n", xon_cmd);
435 return ERROR_OK;
436 }
437
438 struct connection *conn = hub->connections[tool];
439 if (conn) {
440 struct ipdbg_connection *connection = conn->priv;
441 if (ipdbg_fifo_is_full(&connection->up_fifo)) {
442 int retval = ipdbg_move_buffer_to_connection(conn, &connection->up_fifo);
443 if (retval != ERROR_OK)
444 return retval;
445 }
446 ipdbg_append_to_fifo(&connection->up_fifo, up);
447 }
448 return ERROR_OK;
449 }
450
451 static void ipdbg_check_for_xoff(struct ipdbg_hub *hub, size_t tool,
452 uint32_t rx_data)
453 {
454 if ((rx_data & hub->xoff_mask) && hub->last_dn_tool != hub->max_tools) {
455 hub->dn_xoff |= BIT(hub->last_dn_tool);
456 LOG_INFO("tool %d sent xoff", hub->last_dn_tool);
457 }
458
459 hub->last_dn_tool = tool;
460 }
461
462 static int ipdbg_shift_empty_data(struct ipdbg_hub *hub)
463 {
464 if (!hub)
465 return ERROR_FAIL;
466
467 struct jtag_tap *tap = hub->tap;
468 if (!tap)
469 return ERROR_FAIL;
470
471 const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8);
472 memset(hub->scratch_memory.dr_out_vals, 0, dreg_buffer_size);
473 for (size_t i = 0; i < IPDBG_EMPTY_DOWN_TRANSFERS; ++i) {
474 ipdbg_init_scan_field(hub->scratch_memory.fields + i,
475 hub->scratch_memory.dr_in_vals + i * dreg_buffer_size,
476 hub->data_register_length,
477 hub->scratch_memory.dr_out_vals);
478 jtag_add_dr_scan(tap, 1, hub->scratch_memory.fields + i, TAP_IDLE);
479 }
480
481 int retval = jtag_execute_queue();
482
483 if (retval == ERROR_OK) {
484 uint32_t up_data;
485 for (size_t i = 0; i < IPDBG_EMPTY_DOWN_TRANSFERS; ++i) {
486 up_data = buf_get_u32(hub->scratch_memory.dr_in_vals +
487 i * dreg_buffer_size, 0,
488 hub->data_register_length);
489 int rv = ipdbg_distribute_data_from_hub(hub, up_data);
490 if (rv != ERROR_OK)
491 retval = rv;
492
493 if (i == 0) {
494 /* check if xoff sent is only needed on the first transfer which
495 may contain the xoff of the prev down transfer.
496 */
497 ipdbg_check_for_xoff(hub, hub->max_tools, up_data);
498 }
499 }
500 }
501
502 return retval;
503 }
504
505 static int ipdbg_jtag_transfer_byte(struct ipdbg_hub *hub, size_t tool, struct ipdbg_connection *connection)
506 {
507 uint32_t dn = hub->valid_mask | ((tool & hub->tool_mask) << 8) |
508 (0x00fful & ipdbg_get_from_fifo(&connection->dn_fifo));
509 uint32_t up = 0;
510 int ret = ipdbg_shift_data(hub, dn, &up);
511 if (ret != ERROR_OK)
512 return ret;
513
514 ret = ipdbg_distribute_data_from_hub(hub, up);
515 if (ret != ERROR_OK)
516 return ret;
517
518 ipdbg_check_for_xoff(hub, tool, up);
519
520 return ERROR_OK;
521 }
522
523 static int ipdbg_jtag_transfer_bytes(struct ipdbg_hub *hub,
524 size_t tool, struct ipdbg_connection *connection)
525 {
526 if (!hub)
527 return ERROR_FAIL;
528
529 struct jtag_tap *tap = hub->tap;
530 if (!tap)
531 return ERROR_FAIL;
532
533 const size_t dreg_buffer_size = DIV_ROUND_UP(hub->data_register_length, 8);
534 size_t num_tx = (connection->dn_fifo.count < IPDBG_CONSECUTIVE_UP_TRANSFERS) ?
535 connection->dn_fifo.count : IPDBG_CONSECUTIVE_UP_TRANSFERS;
536
537 for (size_t i = 0; i < num_tx; ++i) {
538 uint32_t dn_data = hub->valid_mask | ((tool & hub->tool_mask) << 8) |
539 (0x00fful & ipdbg_get_from_fifo(&connection->dn_fifo));
540 buf_set_u32(hub->scratch_memory.dr_out_vals + i * dreg_buffer_size, 0,
541 hub->data_register_length, dn_data);
542
543 ipdbg_init_scan_field(hub->scratch_memory.fields + i,
544 hub->scratch_memory.dr_in_vals +
545 i * dreg_buffer_size,
546 hub->data_register_length,
547 hub->scratch_memory.dr_out_vals +
548 i * dreg_buffer_size);
549 jtag_add_dr_scan(tap, 1, hub->scratch_memory.fields + i, TAP_IDLE);
550 }
551
552 int retval = jtag_execute_queue();
553
554 if (retval == ERROR_OK) {
555 uint32_t up_data;
556 for (size_t i = 0; i < num_tx; ++i) {
557 up_data = buf_get_u32(hub->scratch_memory.dr_in_vals +
558 i * dreg_buffer_size,
559 0, hub->data_register_length);
560 int rv = ipdbg_distribute_data_from_hub(hub, up_data);
561 if (rv != ERROR_OK)
562 retval = rv;
563 if (i == 0) {
564 /* check if xoff sent is only needed on the first transfer which
565 may contain the xoff of the prev down transfer.
566 No checks for this channel because this function is only
567 called for channels without enabled flow control.
568 */
569 ipdbg_check_for_xoff(hub, tool, up_data);
570 }
571 }
572 }
573
574 return retval;
575 }
576
577 static int ipdbg_polling_callback(void *priv)
578 {
579 struct ipdbg_hub *hub = priv;
580
581 int ret = ipdbg_shift_vir(hub);
582 if (ret != ERROR_OK)
583 return ret;
584
585 ret = ipdbg_shift_instr(hub, hub->user_instruction);
586 if (ret != ERROR_OK)
587 return ret;
588
589 /* transfer dn buffers to jtag-hub */
590 for (size_t tool = 0; tool < hub->max_tools; ++tool) {
591 struct connection *conn = hub->connections[tool];
592 if (conn && conn->priv) {
593 struct ipdbg_connection *connection = conn->priv;
594 while (((hub->dn_xoff & BIT(tool)) == 0) && !ipdbg_fifo_is_empty(&connection->dn_fifo)) {
595 if (hub->flow_control_enabled & BIT(tool))
596 ret = ipdbg_jtag_transfer_byte(hub, tool, connection);
597 else
598 ret = ipdbg_jtag_transfer_bytes(hub, tool, connection);
599 if (ret != ERROR_OK)
600 return ret;
601 }
602 }
603 }
604
605 /* some transfers to get data from jtag-hub in case there is no dn data */
606 ret = ipdbg_shift_empty_data(hub);
607 if (ret != ERROR_OK)
608 return ret;
609
610 /* write from up fifos to sockets */
611 for (size_t tool = 0; tool < hub->max_tools; ++tool) {
612 struct connection *conn = hub->connections[tool];
613 if (conn && conn->priv) {
614 struct ipdbg_connection *connection = conn->priv;
615 int retval = ipdbg_move_buffer_to_connection(conn, &connection->up_fifo);
616 if (retval != ERROR_OK)
617 return retval;
618 }
619 }
620
621 return ERROR_OK;
622 }
623
624 static int ipdbg_get_flow_control_info_from_hub(struct ipdbg_hub *hub)
625 {
626 uint32_t up_data;
627
628 /* on older implementations the flow_control_enable_word is not sent to us.
629 so we don't know -> assume it's enabled on all channels */
630 hub->flow_control_enabled = 0x7f;
631
632 int ret = ipdbg_shift_data(hub, 0UL, &up_data);
633 if (ret != ERROR_OK)
634 return ret;
635
636 const bool valid_up_data = up_data & hub->valid_mask;
637 if (valid_up_data) {
638 const size_t tool = (up_data >> 8) & hub->tool_mask;
639 /* the first valid data from hub is flow_control_enable_word */
640 if (tool == hub->tool_mask)
641 hub->flow_control_enabled = up_data & 0x007f;
642 else
643 ipdbg_distribute_data_from_hub(hub, up_data);
644 }
645
646 LOG_INFO("Flow control enabled on IPDBG JTAG Hub: 0x%02x", hub->flow_control_enabled);
647
648 return ERROR_OK;
649 }
650
651 static int ipdbg_start_polling(struct ipdbg_service *service, struct connection *connection)
652 {
653 struct ipdbg_hub *hub = service->hub;
654 hub->connections[service->tool] = connection;
655 hub->active_connections++;
656 if (hub->active_connections > 1) {
657 /* hub is already initialized */
658 return ERROR_OK;
659 }
660
661 const uint32_t reset_hub = hub->valid_mask | ((hub->max_tools) << 8);
662
663 int ret = ipdbg_shift_vir(hub);
664 if (ret != ERROR_OK)
665 return ret;
666
667 ret = ipdbg_shift_instr(hub, hub->user_instruction);
668 if (ret != ERROR_OK)
669 return ret;
670
671 ret = ipdbg_shift_data(hub, reset_hub, NULL);
672 hub->last_dn_tool = hub->tool_mask;
673 hub->dn_xoff = 0;
674 if (ret != ERROR_OK)
675 return ret;
676
677 ret = ipdbg_get_flow_control_info_from_hub(hub);
678 if (ret != ERROR_OK)
679 return ret;
680
681 LOG_INFO("IPDBG start_polling");
682
683 const int time_ms = 20;
684 const int periodic = 1;
685 return target_register_timer_callback(ipdbg_polling_callback, time_ms, periodic, hub);
686 }
687
688 static int ipdbg_stop_polling(struct ipdbg_service *service)
689 {
690 struct ipdbg_hub *hub = service->hub;
691 hub->connections[service->tool] = NULL;
692 hub->active_connections--;
693 if (hub->active_connections == 0) {
694 LOG_INFO("IPDBG stop_polling");
695
696 return target_unregister_timer_callback(ipdbg_polling_callback, hub);
697 }
698
699 return ERROR_OK;
700 }
701
702 static int ipdbg_on_new_connection(struct connection *connection)
703 {
704 struct ipdbg_service *service = connection->service->priv;
705 connection->priv = &service->connection;
706 /* initialize ipdbg connection information */
707 ipdbg_init_fifo(&service->connection.up_fifo);
708 ipdbg_init_fifo(&service->connection.dn_fifo);
709
710 int retval = ipdbg_start_polling(service, connection);
711 if (retval != ERROR_OK) {
712 LOG_ERROR("BUG: ipdbg_start_polling failed");
713 return retval;
714 }
715
716 struct ipdbg_connection *conn = connection->priv;
717 conn->closed = false;
718
719 LOG_INFO("New IPDBG Connection");
720
721 return ERROR_OK;
722 }
723
724 static int ipdbg_on_connection_input(struct connection *connection)
725 {
726 struct ipdbg_connection *conn = connection->priv;
727 struct ipdbg_fifo *fifo = &conn->dn_fifo;
728
729 if (ipdbg_fifo_is_full(fifo))
730 return ERROR_OK;
731
732 ipdbg_zero_rd_idx(fifo);
733 int bytes_read = connection_read(connection, fifo->buffer + fifo->count, IPDBG_BUFFER_SIZE - fifo->count);
734 if (bytes_read <= 0) {
735 if (bytes_read < 0)
736 LOG_ERROR("error during read: %s", strerror(errno));
737 return ERROR_SERVER_REMOTE_CLOSED;
738 }
739
740 fifo->count += bytes_read;
741
742 return ERROR_OK;
743 }
744
745 static int ipdbg_on_connection_closed(struct connection *connection)
746 {
747 struct ipdbg_connection *conn = connection->priv;
748 conn->closed = true;
749 LOG_INFO("Closed IPDBG Connection");
750
751 return ipdbg_stop_polling(connection->service->priv);
752 }
753
754 static const struct service_driver ipdbg_service_driver = {
755 .name = "ipdbg",
756 .new_connection_during_keep_alive_handler = NULL,
757 .new_connection_handler = ipdbg_on_new_connection,
758 .input_handler = ipdbg_on_connection_input,
759 .connection_closed_handler = ipdbg_on_connection_closed,
760 .keep_client_alive_handler = NULL,
761 };
762
763 static int ipdbg_start(uint16_t port, struct jtag_tap *tap, uint32_t user_instruction,
764 uint8_t data_register_length, struct ipdbg_virtual_ir_info *virtual_ir, uint8_t tool)
765 {
766 LOG_INFO("starting ipdbg service on port %d for tool %d", port, tool);
767
768 struct ipdbg_hub *hub = ipdbg_find_hub(tap, user_instruction, virtual_ir);
769 if (hub) {
770 free(virtual_ir);
771 if (hub->data_register_length != data_register_length) {
772 LOG_DEBUG("hub must have the same data_register_length for all tools");
773 return ERROR_FAIL;
774 }
775 } else {
776 int retval = ipdbg_create_hub(tap, user_instruction, data_register_length, virtual_ir, &hub);
777 if (retval != ERROR_OK)
778 return retval;
779 }
780
781 struct ipdbg_service *service = NULL;
782 int retval = ipdbg_create_service(hub, tool, &service, port);
783
784 if (retval != ERROR_OK || !service) {
785 if (hub->active_services == 0 && hub->active_connections == 0)
786 ipdbg_free_hub(hub);
787 return ERROR_FAIL;
788 }
789
790 char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH];
791 snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", port);
792 retval = add_service(&ipdbg_service_driver, port_str_buffer, 1, service);
793 if (retval == ERROR_OK) {
794 ipdbg_add_service(service);
795 if (hub->active_services == 0 && hub->active_connections == 0)
796 ipdbg_add_hub(hub);
797 hub->active_services++;
798 } else {
799 if (hub->active_services == 0 && hub->active_connections == 0)
800 ipdbg_free_hub(hub);
801 free(service);
802 }
803
804 return retval;
805 }
806
807 static int ipdbg_stop(struct jtag_tap *tap, uint32_t user_instruction,
808 struct ipdbg_virtual_ir_info *virtual_ir, uint8_t tool)
809 {
810 struct ipdbg_hub *hub = ipdbg_find_hub(tap, user_instruction, virtual_ir);
811 free(virtual_ir);
812 if (!hub)
813 return ERROR_FAIL;
814
815 struct ipdbg_service *service = ipdbg_find_service(hub, tool);
816 if (!service)
817 return ERROR_FAIL;
818
819 int retval = ipdbg_remove_service(service);
820 if (retval != ERROR_OK) {
821 LOG_ERROR("BUG: ipdbg_remove_service failed");
822 return retval;
823 }
824
825 char port_str_buffer[IPDBG_TCP_PORT_STR_MAX_LENGTH];
826 snprintf(port_str_buffer, IPDBG_TCP_PORT_STR_MAX_LENGTH, "%u", service->port);
827 retval = remove_service("ipdbg", port_str_buffer);
828 /* The ipdbg_service structure is freed by server.c:remove_service().
829 There the "priv" pointer is freed.*/
830 if (retval != ERROR_OK) {
831 LOG_ERROR("BUG: remove_service failed");
832 return retval;
833 }
834 hub->active_services--;
835 if (hub->active_connections == 0 && hub->active_services == 0) {
836 retval = ipdbg_remove_hub(hub);
837 if (retval != ERROR_OK) {
838 LOG_ERROR("BUG: ipdbg_remove_hub failed");
839 return retval;
840 }
841 ipdbg_free_hub(hub);
842 }
843 return ERROR_OK;
844 }
845
846 COMMAND_HANDLER(handle_ipdbg_command)
847 {
848 struct jtag_tap *tap = NULL;
849 uint16_t port = 4242;
850 uint8_t tool = 1;
851 uint32_t user_instruction = 0x00;
852 uint8_t data_register_length = IPDBG_MAX_DR_LENGTH;
853 bool start = true;
854 bool hub_configured = false;
855 bool has_virtual_ir = false;
856 uint32_t virtual_ir_instruction = 0x00e;
857 uint32_t virtual_ir_length = 5;
858 uint32_t virtual_ir_value = 0x11;
859 struct ipdbg_virtual_ir_info *virtual_ir = NULL;
860 int user_num = 1;
861
862 if ((CMD_ARGC < IPDBG_MIN_NUM_OF_OPTIONS) || (CMD_ARGC > IPDBG_MAX_NUM_OF_OPTIONS))
863 return ERROR_COMMAND_SYNTAX_ERROR;
864
865 for (unsigned int i = 0; i < CMD_ARGC; ++i) {
866 if (strcmp(CMD_ARGV[i], "-tap") == 0) {
867 if (i + 1 >= CMD_ARGC || CMD_ARGV[i + 1][0] == '-') {
868 command_print(CMD, "no TAP given");
869 return ERROR_FAIL;
870 }
871 tap = jtag_tap_by_string(CMD_ARGV[i + 1]);
872 if (!tap) {
873 command_print(CMD, "Tap %s unknown", CMD_ARGV[i + 1]);
874 return ERROR_FAIL;
875 }
876 ++i;
877 } else if (strcmp(CMD_ARGV[i], "-hub") == 0) {
878 COMMAND_PARSE_ADDITIONAL_NUMBER(u32, i, user_instruction, "ir_value to select hub");
879 hub_configured = true;
880 COMMAND_PARSE_OPTIONAL_NUMBER(u8, i, data_register_length);
881 if (data_register_length < IPDBG_MIN_DR_LENGTH ||
882 data_register_length > IPDBG_MAX_DR_LENGTH) {
883 command_print(CMD, "length of \"user\"-data register must be at least %d and at most %d.",
884 IPDBG_MIN_DR_LENGTH, IPDBG_MAX_DR_LENGTH);
885 return ERROR_FAIL;
886 }
887 } else if (strcmp(CMD_ARGV[i], "-pld") == 0) {
888 ++i;
889 if (i >= CMD_ARGC || CMD_ARGV[i][0] == '-')
890 return ERROR_COMMAND_SYNTAX_ERROR;
891 struct pld_device *device = get_pld_device_by_name_or_numstr(CMD_ARGV[i]);
892 if (!device || !device->driver) {
893 command_print(CMD, "pld device '#%s' is out of bounds or unknown", CMD_ARGV[i]);
894 return ERROR_FAIL;
895 }
896 COMMAND_PARSE_OPTIONAL_NUMBER(int, i, user_num);
897 struct pld_ipdbg_hub pld_hub;
898 struct pld_driver *driver = device->driver;
899 if (!driver->get_ipdbg_hub) {
900 command_print(CMD, "pld driver has no ipdbg support");
901 return ERROR_FAIL;
902 }
903 if (driver->get_ipdbg_hub(user_num, device, &pld_hub) != ERROR_OK) {
904 command_print(CMD, "unable to retrieve hub from pld driver");
905 return ERROR_FAIL;
906 }
907 if (!pld_hub.tap) {
908 command_print(CMD, "no tap received from pld driver");
909 return ERROR_FAIL;
910 }
911 hub_configured = true;
912 user_instruction = pld_hub.user_ir_code;
913 tap = pld_hub.tap;
914
915 } else if (strcmp(CMD_ARGV[i], "-vir") == 0) {
916 COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_value);
917 COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_length);
918 COMMAND_PARSE_OPTIONAL_NUMBER(u32, i, virtual_ir_instruction);
919 has_virtual_ir = true;
920 } else if (strcmp(CMD_ARGV[i], "-port") == 0) {
921 COMMAND_PARSE_ADDITIONAL_NUMBER(u16, i, port, "port number");
922 } else if (strcmp(CMD_ARGV[i], "-tool") == 0) {
923 COMMAND_PARSE_ADDITIONAL_NUMBER(u8, i, tool, "tool");
924 } else if (strcmp(CMD_ARGV[i], "-stop") == 0) {
925 start = false;
926 } else if (strcmp(CMD_ARGV[i], "-start") == 0) {
927 start = true;
928 } else {
929 command_print(CMD, "Unknown argument: %s", CMD_ARGV[i]);
930 return ERROR_FAIL;
931 }
932 }
933
934 if (!tap) {
935 command_print(CMD, "no valid tap selected");
936 return ERROR_FAIL;
937 }
938
939 if (!hub_configured) {
940 command_print(CMD, "hub not configured correctly");
941 return ERROR_FAIL;
942 }
943
944 if (tool >= ipdbg_max_tools_from_data_register_length(data_register_length)) {
945 command_print(CMD, "Tool: %d is invalid", tool);
946 return ERROR_FAIL;
947 }
948
949 if (has_virtual_ir) {
950 virtual_ir = calloc(1, sizeof(struct ipdbg_virtual_ir_info));
951 if (!virtual_ir) {
952 LOG_ERROR("Out of memory");
953 return ERROR_FAIL;
954 }
955 virtual_ir->instruction = virtual_ir_instruction;
956 virtual_ir->length = virtual_ir_length;
957 virtual_ir->value = virtual_ir_value;
958 }
959
960 if (start)
961 return ipdbg_start(port, tap, user_instruction, data_register_length, virtual_ir, tool);
962 else
963 return ipdbg_stop(tap, user_instruction, virtual_ir, tool);
964 }
965
966 static const struct command_registration ipdbg_command_handlers[] = {
967 {
968 .name = "ipdbg",
969 .handler = handle_ipdbg_command,
970 .mode = COMMAND_EXEC,
971 .help = "Starts or stops an IPDBG JTAG-Host server.",
972 .usage = "[-start|-stop] -tap device.tap -hub ir_value [dr_length]"
973 " [-port number] [-tool number] [-vir [vir_value [length [instr_code]]]]",
974 },
975 COMMAND_REGISTRATION_DONE
976 };
977
978 int ipdbg_register_commands(struct command_context *cmd_ctx)
979 {
980 return register_commands(cmd_ctx, NULL, ipdbg_command_handlers);
981 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)