1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Copyright (C) 2020 by Daniel Anselmi <danselmi@gmx.ch> */
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>
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
27 #if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_EMPTY_DOWN_TRANSFERS
28 #error "scratch Memory must be at least IPDBG_EMPTY_DOWN_TRANSFERS"
31 #if IPDBG_SCRATCH_MEMORY_SIZE < IPDBG_CONSECUTIVE_UP_TRANSFERS
32 #error "scratch Memory must be at least IPDBG_CONSECUTIVE_UP_TRANSFERS"
35 /* private connection data for IPDBG */
39 char buffer
[IPDBG_BUFFER_SIZE
];
42 struct ipdbg_connection
{
43 struct ipdbg_fifo dn_fifo
;
44 struct ipdbg_fifo up_fifo
;
48 struct ipdbg_service
{
49 struct ipdbg_hub
*hub
;
50 struct ipdbg_service
*next
;
52 struct ipdbg_connection connection
;
56 struct ipdbg_virtual_ir_info
{
62 struct ipdbg_hub_scratch_memory
{
66 struct scan_field
*fields
;
70 uint32_t user_instruction
;
72 uint32_t active_connections
;
73 uint32_t active_services
;
77 uint32_t last_dn_tool
;
78 struct ipdbg_hub
*next
;
80 struct connection
**connections
;
81 uint8_t data_register_length
;
83 uint8_t flow_control_enabled
;
84 struct ipdbg_virtual_ir_info
*virtual_ir
;
85 struct ipdbg_hub_scratch_memory scratch_memory
;
88 static struct ipdbg_hub
*ipdbg_first_hub
;
90 static struct ipdbg_service
*ipdbg_first_service
;
92 static void ipdbg_init_fifo(struct ipdbg_fifo
*fifo
)
98 static bool ipdbg_fifo_is_empty(struct ipdbg_fifo
*fifo
)
100 return fifo
->count
== 0;
103 static bool ipdbg_fifo_is_full(struct ipdbg_fifo
*fifo
)
105 return fifo
->count
== IPDBG_BUFFER_SIZE
;
108 static void ipdbg_zero_rd_idx(struct ipdbg_fifo
*fifo
)
110 if (fifo
->rd_idx
== 0)
113 size_t ri
= fifo
->rd_idx
;
114 for (size_t idx
= 0; idx
< fifo
->count
; ++idx
)
115 fifo
->buffer
[idx
] = fifo
->buffer
[ri
++];
119 static void ipdbg_append_to_fifo(struct ipdbg_fifo
*fifo
, char data
)
121 if (ipdbg_fifo_is_full(fifo
))
124 ipdbg_zero_rd_idx(fifo
);
125 fifo
->buffer
[fifo
->count
++] = data
;
128 static char ipdbg_get_from_fifo(struct ipdbg_fifo
*fifo
)
130 if (ipdbg_fifo_is_empty(fifo
))
134 return fifo
->buffer
[fifo
->rd_idx
++];
137 static int ipdbg_move_buffer_to_connection(struct connection
*conn
, struct ipdbg_fifo
*fifo
)
139 if (ipdbg_fifo_is_empty(fifo
))
142 struct ipdbg_connection
*connection
= conn
->priv
;
143 if (connection
->closed
)
144 return ERROR_SERVER_REMOTE_CLOSED
;
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
;
154 fifo
->count
-= bytes_written
;
159 static int ipdbg_max_tools_from_data_register_length(uint8_t data_register_length
)
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
--)
166 /* last tool is used to reset JtagCDC and transfer "XON" to host*/
167 return max_tools
- 1;
170 static struct ipdbg_service
*ipdbg_find_service(struct ipdbg_hub
*hub
, uint8_t tool
)
172 struct ipdbg_service
*service
;
173 for (service
= ipdbg_first_service
; service
; service
= service
->next
) {
174 if (service
->hub
== hub
&& service
->tool
== tool
)
180 static void ipdbg_add_service(struct ipdbg_service
*service
)
182 struct ipdbg_service
*iservice
;
183 if (ipdbg_first_service
) {
184 for (iservice
= ipdbg_first_service
; iservice
->next
; iservice
= iservice
->next
)
186 iservice
->next
= service
;
188 ipdbg_first_service
= service
;
191 static int ipdbg_create_service(struct ipdbg_hub
*hub
, uint8_t tool
, struct ipdbg_service
**service
, uint16_t port
)
193 *service
= calloc(1, sizeof(struct ipdbg_service
));
195 LOG_ERROR("Out of memory");
199 (*service
)->hub
= hub
;
200 (*service
)->tool
= tool
;
201 (*service
)->port
= port
;
206 static int ipdbg_remove_service(struct ipdbg_service
*service
)
208 if (!ipdbg_first_service
)
211 if (service
== ipdbg_first_service
) {
212 ipdbg_first_service
= ipdbg_first_service
->next
;
216 for (struct ipdbg_service
*iservice
= ipdbg_first_service
; iservice
->next
; iservice
= iservice
->next
) {
217 if (service
== iservice
->next
) {
218 iservice
->next
= service
->next
;
225 static struct ipdbg_hub
*ipdbg_find_hub(struct jtag_tap
*tap
,
226 uint32_t user_instruction
, struct ipdbg_virtual_ir_info
*virtual_ir
)
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
)) {
243 static void ipdbg_add_hub(struct ipdbg_hub
*hub
)
245 struct ipdbg_hub
*ihub
;
246 if (ipdbg_first_hub
) {
247 for (ihub
= ipdbg_first_hub
; ihub
->next
; ihub
= ihub
->next
)
251 ipdbg_first_hub
= hub
;
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
)
258 struct ipdbg_hub
*new_hub
= calloc(1, sizeof(struct ipdbg_hub
));
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
);
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
*));
271 new_hub
->scratch_memory
.vir_out_val
= calloc(1, DIV_ROUND_UP(virtual_ir
->length
, 8));
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
)
279 buf_set_u32(new_hub
->scratch_memory
.vir_out_val
, 0, virtual_ir
->length
, virtual_ir
->value
);
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
;
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
);
302 LOG_ERROR("Out of memory");
306 static void ipdbg_free_hub(struct ipdbg_hub
*hub
)
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
);
319 static int ipdbg_remove_hub(struct ipdbg_hub
*hub
)
321 if (!ipdbg_first_hub
)
323 if (hub
== ipdbg_first_hub
) {
324 ipdbg_first_hub
= ipdbg_first_hub
->next
;
328 for (struct ipdbg_hub
*ihub
= ipdbg_first_hub
; ihub
->next
; ihub
= ihub
->next
) {
329 if (hub
== ihub
->next
) {
330 ihub
->next
= hub
->next
;
338 static void ipdbg_init_scan_field(struct scan_field
*fields
, uint8_t *in_value
, int num_bits
, const uint8_t *out_value
)
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
;
347 static int ipdbg_shift_instr(struct ipdbg_hub
*hub
, uint32_t instr
)
352 struct jtag_tap
*tap
= hub
->tap
;
356 if (buf_get_u32(tap
->cur_instr
, 0, tap
->ir_length
) == instr
) {
357 /* there is already the requested instruction in the ir */
361 uint8_t *ir_out_val
= calloc(DIV_ROUND_UP(tap
->ir_length
, 8), 1);
363 LOG_ERROR("Out of memory");
366 buf_set_u32(ir_out_val
, 0, tap
->ir_length
, instr
);
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();
378 static int ipdbg_shift_vir(struct ipdbg_hub
*hub
)
383 if (!hub
->virtual_ir
)
386 int retval
= ipdbg_shift_instr(hub
, hub
->virtual_ir
->instruction
);
387 if (retval
!= ERROR_OK
)
390 struct jtag_tap
*tap
= hub
->tap
;
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();
402 static int ipdbg_shift_data(struct ipdbg_hub
*hub
, uint32_t dn_data
, uint32_t *up_data
)
407 struct jtag_tap
*tap
= hub
->tap
;
411 buf_set_u32(hub
->scratch_memory
.dr_out_vals
, 0, hub
->data_register_length
, dn_data
);
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();
418 if (up_data
&& retval
== ERROR_OK
)
419 *up_data
= buf_get_u32(hub
->scratch_memory
.dr_in_vals
, 0, hub
->data_register_length
);
424 static int ipdbg_distribute_data_from_hub(struct ipdbg_hub
*hub
, uint32_t up
)
426 const bool valid_up_data
= up
& hub
->valid_mask
;
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
);
438 struct connection
*conn
= hub
->connections
[tool
];
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
)
446 ipdbg_append_to_fifo(&connection
->up_fifo
, up
);
451 static void ipdbg_check_for_xoff(struct ipdbg_hub
*hub
, size_t tool
,
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
);
459 hub
->last_dn_tool
= tool
;
462 static int ipdbg_shift_empty_data(struct ipdbg_hub
*hub
)
467 struct jtag_tap
*tap
= hub
->tap
;
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
);
481 int retval
= jtag_execute_queue();
483 if (retval
== ERROR_OK
) {
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
);
494 /* check if xoff sent is only needed on the first transfer which
495 may contain the xoff of the prev down transfer.
497 ipdbg_check_for_xoff(hub
, hub
->max_tools
, up_data
);
505 static int ipdbg_jtag_transfer_byte(struct ipdbg_hub
*hub
, size_t tool
, struct ipdbg_connection
*connection
)
507 uint32_t dn
= hub
->valid_mask
| ((tool
& hub
->tool_mask
) << 8) |
508 (0x00fful
& ipdbg_get_from_fifo(&connection
->dn_fifo
));
510 int ret
= ipdbg_shift_data(hub
, dn
, &up
);
514 ret
= ipdbg_distribute_data_from_hub(hub
, up
);
518 ipdbg_check_for_xoff(hub
, tool
, up
);
523 static int ipdbg_jtag_transfer_bytes(struct ipdbg_hub
*hub
,
524 size_t tool
, struct ipdbg_connection
*connection
)
529 struct jtag_tap
*tap
= hub
->tap
;
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
;
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
);
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
);
552 int retval
= jtag_execute_queue();
554 if (retval
== ERROR_OK
) {
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
);
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.
569 ipdbg_check_for_xoff(hub
, tool
, up_data
);
577 static int ipdbg_polling_callback(void *priv
)
579 struct ipdbg_hub
*hub
= priv
;
581 int ret
= ipdbg_shift_vir(hub
);
585 ret
= ipdbg_shift_instr(hub
, hub
->user_instruction
);
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
);
598 ret
= ipdbg_jtag_transfer_bytes(hub
, tool
, connection
);
605 /* some transfers to get data from jtag-hub in case there is no dn data */
606 ret
= ipdbg_shift_empty_data(hub
);
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
)
624 static int ipdbg_get_flow_control_info_from_hub(struct ipdbg_hub
*hub
)
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;
632 int ret
= ipdbg_shift_data(hub
, 0UL, &up_data
);
636 const bool valid_up_data
= up_data
& hub
->valid_mask
;
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;
643 ipdbg_distribute_data_from_hub(hub
, up_data
);
646 LOG_INFO("Flow control enabled on IPDBG JTAG Hub: 0x%02x", hub
->flow_control_enabled
);
651 static int ipdbg_start_polling(struct ipdbg_service
*service
, struct connection
*connection
)
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 */
661 const uint32_t reset_hub
= hub
->valid_mask
| ((hub
->max_tools
) << 8);
663 int ret
= ipdbg_shift_vir(hub
);
667 ret
= ipdbg_shift_instr(hub
, hub
->user_instruction
);
671 ret
= ipdbg_shift_data(hub
, reset_hub
, NULL
);
672 hub
->last_dn_tool
= hub
->tool_mask
;
677 ret
= ipdbg_get_flow_control_info_from_hub(hub
);
681 LOG_INFO("IPDBG start_polling");
683 const int time_ms
= 20;
684 const int periodic
= 1;
685 return target_register_timer_callback(ipdbg_polling_callback
, time_ms
, periodic
, hub
);
688 static int ipdbg_stop_polling(struct ipdbg_service
*service
)
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");
696 return target_unregister_timer_callback(ipdbg_polling_callback
, hub
);
702 static int ipdbg_on_new_connection(struct connection
*connection
)
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
);
710 int retval
= ipdbg_start_polling(service
, connection
);
711 if (retval
!= ERROR_OK
) {
712 LOG_ERROR("BUG: ipdbg_start_polling failed");
716 struct ipdbg_connection
*conn
= connection
->priv
;
717 conn
->closed
= false;
719 LOG_INFO("New IPDBG Connection");
724 static int ipdbg_on_connection_input(struct connection
*connection
)
726 struct ipdbg_connection
*conn
= connection
->priv
;
727 struct ipdbg_fifo
*fifo
= &conn
->dn_fifo
;
729 if (ipdbg_fifo_is_full(fifo
))
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) {
736 LOG_ERROR("error during read: %s", strerror(errno
));
737 return ERROR_SERVER_REMOTE_CLOSED
;
740 fifo
->count
+= bytes_read
;
745 static int ipdbg_on_connection_closed(struct connection
*connection
)
747 struct ipdbg_connection
*conn
= connection
->priv
;
749 LOG_INFO("Closed IPDBG Connection");
751 return ipdbg_stop_polling(connection
->service
->priv
);
754 static const struct service_driver ipdbg_service_driver
= {
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
,
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
)
766 LOG_INFO("starting ipdbg service on port %d for tool %d", port
, tool
);
768 struct ipdbg_hub
*hub
= ipdbg_find_hub(tap
, user_instruction
, 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");
776 int retval
= ipdbg_create_hub(tap
, user_instruction
, data_register_length
, virtual_ir
, &hub
);
777 if (retval
!= ERROR_OK
)
781 struct ipdbg_service
*service
= NULL
;
782 int retval
= ipdbg_create_service(hub
, tool
, &service
, port
);
784 if (retval
!= ERROR_OK
|| !service
) {
785 if (hub
->active_services
== 0 && hub
->active_connections
== 0)
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)
797 hub
->active_services
++;
799 if (hub
->active_services
== 0 && hub
->active_connections
== 0)
807 static int ipdbg_stop(struct jtag_tap
*tap
, uint32_t user_instruction
,
808 struct ipdbg_virtual_ir_info
*virtual_ir
, uint8_t tool
)
810 struct ipdbg_hub
*hub
= ipdbg_find_hub(tap
, user_instruction
, virtual_ir
);
815 struct ipdbg_service
*service
= ipdbg_find_service(hub
, tool
);
819 int retval
= ipdbg_remove_service(service
);
820 if (retval
!= ERROR_OK
) {
821 LOG_ERROR("BUG: ipdbg_remove_service failed");
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");
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");
846 COMMAND_HANDLER(handle_ipdbg_command
)
848 struct jtag_tap
*tap
= NULL
;
849 uint16_t port
= 4242;
851 uint32_t user_instruction
= 0x00;
852 uint8_t data_register_length
= IPDBG_MAX_DR_LENGTH
;
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
;
862 if ((CMD_ARGC
< IPDBG_MIN_NUM_OF_OPTIONS
) || (CMD_ARGC
> IPDBG_MAX_NUM_OF_OPTIONS
))
863 return ERROR_COMMAND_SYNTAX_ERROR
;
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");
871 tap
= jtag_tap_by_string(CMD_ARGV
[i
+ 1]);
873 command_print(CMD
, "Tap %s unknown", CMD_ARGV
[i
+ 1]);
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
);
887 } else if (strcmp(CMD_ARGV
[i
], "-pld") == 0) {
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
]);
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");
903 if (driver
->get_ipdbg_hub(user_num
, device
, &pld_hub
) != ERROR_OK
) {
904 command_print(CMD
, "unable to retrieve hub from pld driver");
908 command_print(CMD
, "no tap received from pld driver");
911 hub_configured
= true;
912 user_instruction
= pld_hub
.user_ir_code
;
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) {
926 } else if (strcmp(CMD_ARGV
[i
], "-start") == 0) {
929 command_print(CMD
, "Unknown argument: %s", CMD_ARGV
[i
]);
935 command_print(CMD
, "no valid tap selected");
939 if (!hub_configured
) {
940 command_print(CMD
, "hub not configured correctly");
944 if (tool
>= ipdbg_max_tools_from_data_register_length(data_register_length
)) {
945 command_print(CMD
, "Tool: %d is invalid", tool
);
949 if (has_virtual_ir
) {
950 virtual_ir
= calloc(1, sizeof(struct ipdbg_virtual_ir_info
));
952 LOG_ERROR("Out of memory");
955 virtual_ir
->instruction
= virtual_ir_instruction
;
956 virtual_ir
->length
= virtual_ir_length
;
957 virtual_ir
->value
= virtual_ir_value
;
961 return ipdbg_start(port
, tap
, user_instruction
, data_register_length
, virtual_ir
, tool
);
963 return ipdbg_stop(tap
, user_instruction
, virtual_ir
, tool
);
966 static const struct command_registration ipdbg_command_handlers
[] = {
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]]]]",
975 COMMAND_REGISTRATION_DONE
978 int ipdbg_register_commands(struct command_context
*cmd_ctx
)
980 return register_commands(cmd_ctx
, NULL
, ipdbg_command_handlers
);
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)