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>
16 #define IPDBG_BUFFER_SIZE 16384
17 #define IPDBG_MIN_NUM_OF_OPTIONS 4
18 #define IPDBG_MAX_NUM_OF_OPTIONS 14
19 #define IPDBG_MIN_DR_LENGTH 11
20 #define IPDBG_MAX_DR_LENGTH 13
21 #define IPDBG_TCP_PORT_STR_MAX_LENGTH 6
23 /* private connection data for IPDBG */
27 char buffer
[IPDBG_BUFFER_SIZE
];
30 struct ipdbg_connection
{
31 struct ipdbg_fifo dn_fifo
;
32 struct ipdbg_fifo up_fifo
;
36 struct ipdbg_service
{
37 struct ipdbg_hub
*hub
;
38 struct ipdbg_service
*next
;
40 struct ipdbg_connection connection
;
44 struct ipdbg_virtual_ir_info
{
51 uint32_t user_instruction
;
53 uint32_t active_connections
;
54 uint32_t active_services
;
58 uint32_t last_dn_tool
;
59 struct ipdbg_hub
*next
;
61 struct connection
**connections
;
62 uint8_t data_register_length
;
64 struct ipdbg_virtual_ir_info
*virtual_ir
;
67 static struct ipdbg_hub
*ipdbg_first_hub
;
69 static struct ipdbg_service
*ipdbg_first_service
;
71 static void ipdbg_init_fifo(struct ipdbg_fifo
*fifo
)
77 static bool ipdbg_fifo_is_empty(struct ipdbg_fifo
*fifo
)
79 return fifo
->count
== 0;
82 static bool ipdbg_fifo_is_full(struct ipdbg_fifo
*fifo
)
84 return fifo
->count
== IPDBG_BUFFER_SIZE
;
87 static void ipdbg_zero_rd_idx(struct ipdbg_fifo
*fifo
)
89 if (fifo
->rd_idx
== 0)
92 size_t ri
= fifo
->rd_idx
;
93 for (size_t idx
= 0; idx
< fifo
->count
; ++idx
)
94 fifo
->buffer
[idx
] = fifo
->buffer
[ri
++];
98 static void ipdbg_append_to_fifo(struct ipdbg_fifo
*fifo
, char data
)
100 if (ipdbg_fifo_is_full(fifo
))
103 ipdbg_zero_rd_idx(fifo
);
104 fifo
->buffer
[fifo
->count
++] = data
;
107 static char ipdbg_get_from_fifo(struct ipdbg_fifo
*fifo
)
109 if (ipdbg_fifo_is_empty(fifo
))
113 return fifo
->buffer
[fifo
->rd_idx
++];
116 static int ipdbg_move_buffer_to_connection(struct connection
*conn
, struct ipdbg_fifo
*fifo
)
118 if (ipdbg_fifo_is_empty(fifo
))
121 struct ipdbg_connection
*connection
= conn
->priv
;
122 if (connection
->closed
)
123 return ERROR_SERVER_REMOTE_CLOSED
;
125 ipdbg_zero_rd_idx(fifo
);
126 size_t bytes_written
= connection_write(conn
, fifo
->buffer
, fifo
->count
);
127 if (bytes_written
!= fifo
->count
) {
128 LOG_ERROR("error during write: %zu != %zu", bytes_written
, fifo
->count
);
129 connection
->closed
= true;
130 return ERROR_SERVER_REMOTE_CLOSED
;
133 fifo
->count
-= bytes_written
;
138 static int ipdbg_max_tools_from_data_register_length(uint8_t data_register_length
)
141 data_register_length
-= 10; /* 8 bit payload, 1 xoff-flag, 1 valid-flag; remaining bits used to select tool*/
142 while (data_register_length
--)
145 /* last tool is used to reset JtagCDC and transfer "XON" to host*/
146 return max_tools
- 1;
149 static struct ipdbg_service
*ipdbg_find_service(struct ipdbg_hub
*hub
, uint8_t tool
)
151 struct ipdbg_service
*service
;
152 for (service
= ipdbg_first_service
; service
; service
= service
->next
) {
153 if (service
->hub
== hub
&& service
->tool
== tool
)
159 static void ipdbg_add_service(struct ipdbg_service
*service
)
161 struct ipdbg_service
*iservice
;
162 if (ipdbg_first_service
) {
163 for (iservice
= ipdbg_first_service
; iservice
->next
; iservice
= iservice
->next
)
165 iservice
->next
= service
;
167 ipdbg_first_service
= service
;
170 static int ipdbg_create_service(struct ipdbg_hub
*hub
, uint8_t tool
, struct ipdbg_service
**service
, uint16_t port
)
172 *service
= calloc(1, sizeof(struct ipdbg_service
));
174 LOG_ERROR("Out of memory");
178 (*service
)->hub
= hub
;
179 (*service
)->tool
= tool
;
180 (*service
)->port
= port
;
185 static int ipdbg_remove_service(struct ipdbg_service
*service
)
187 if (!ipdbg_first_service
)
190 if (service
== ipdbg_first_service
) {
191 ipdbg_first_service
= ipdbg_first_service
->next
;
195 for (struct ipdbg_service
*iservice
= ipdbg_first_service
; iservice
->next
; iservice
= iservice
->next
) {
196 if (service
== iservice
->next
) {
197 iservice
->next
= service
->next
;
204 static struct ipdbg_hub
*ipdbg_find_hub(struct jtag_tap
*tap
,
205 uint32_t user_instruction
, struct ipdbg_virtual_ir_info
*virtual_ir
)
207 struct ipdbg_hub
*hub
= NULL
;
208 for (hub
= ipdbg_first_hub
; hub
; hub
= hub
->next
) {
209 if (hub
->tap
== tap
&& hub
->user_instruction
== user_instruction
) {
210 if ((!virtual_ir
&& !hub
->virtual_ir
) ||
211 (virtual_ir
&& hub
->virtual_ir
&&
212 virtual_ir
->instruction
== hub
->virtual_ir
->instruction
&&
213 virtual_ir
->length
== hub
->virtual_ir
->length
&&
214 virtual_ir
->value
== hub
->virtual_ir
->value
)) {
222 static void ipdbg_add_hub(struct ipdbg_hub
*hub
)
224 struct ipdbg_hub
*ihub
;
225 if (ipdbg_first_hub
) {
226 for (ihub
= ipdbg_first_hub
; ihub
->next
; ihub
= ihub
->next
)
230 ipdbg_first_hub
= hub
;
233 static int ipdbg_create_hub(struct jtag_tap
*tap
, uint32_t user_instruction
, uint8_t data_register_length
,
234 struct ipdbg_virtual_ir_info
*virtual_ir
, struct ipdbg_hub
**hub
)
237 struct ipdbg_hub
*new_hub
= calloc(1, sizeof(struct ipdbg_hub
));
240 LOG_ERROR("Out of memory");
244 new_hub
->max_tools
= ipdbg_max_tools_from_data_register_length(data_register_length
);
245 new_hub
->connections
= calloc(new_hub
->max_tools
, sizeof(struct connection
*));
246 if (!new_hub
->connections
) {
249 LOG_ERROR("Out of memory");
253 new_hub
->user_instruction
= user_instruction
;
254 new_hub
->data_register_length
= data_register_length
;
255 new_hub
->valid_mask
= BIT(data_register_length
- 1);
256 new_hub
->xoff_mask
= BIT(data_register_length
- 2);
257 new_hub
->tool_mask
= (new_hub
->xoff_mask
- 1) >> 8;
258 new_hub
->last_dn_tool
= new_hub
->tool_mask
;
259 new_hub
->virtual_ir
= virtual_ir
;
266 static void ipdbg_free_hub(struct ipdbg_hub
*hub
)
270 free(hub
->connections
);
271 free(hub
->virtual_ir
);
275 static int ipdbg_remove_hub(struct ipdbg_hub
*hub
)
277 if (!ipdbg_first_hub
)
279 if (hub
== ipdbg_first_hub
) {
280 ipdbg_first_hub
= ipdbg_first_hub
->next
;
284 for (struct ipdbg_hub
*ihub
= ipdbg_first_hub
; ihub
->next
; ihub
= ihub
->next
) {
285 if (hub
== ihub
->next
) {
286 ihub
->next
= hub
->next
;
294 static void ipdbg_init_scan_field(struct scan_field
*fields
, uint8_t *in_value
, int num_bits
, const uint8_t *out_value
)
296 fields
->check_mask
= NULL
;
297 fields
->check_value
= NULL
;
298 fields
->in_value
= in_value
;
299 fields
->num_bits
= num_bits
;
300 fields
->out_value
= out_value
;
303 static int ipdbg_shift_instr(struct ipdbg_hub
*hub
, uint32_t instr
)
308 struct jtag_tap
*tap
= hub
->tap
;
312 if (buf_get_u32(tap
->cur_instr
, 0, tap
->ir_length
) == instr
) {
313 /* there is already the requested instruction in the ir */
317 uint8_t *ir_out_val
= calloc(DIV_ROUND_UP(tap
->ir_length
, 8), 1);
319 LOG_ERROR("Out of memory");
322 buf_set_u32(ir_out_val
, 0, tap
->ir_length
, instr
);
324 struct scan_field fields
;
325 ipdbg_init_scan_field(&fields
, NULL
, tap
->ir_length
, ir_out_val
);
326 jtag_add_ir_scan(tap
, &fields
, TAP_IDLE
);
327 int retval
= jtag_execute_queue();
334 static int ipdbg_shift_vir(struct ipdbg_hub
*hub
)
339 if (!hub
->virtual_ir
)
342 int retval
= ipdbg_shift_instr(hub
, hub
->virtual_ir
->instruction
);
343 if (retval
!= ERROR_OK
)
346 struct jtag_tap
*tap
= hub
->tap
;
350 uint8_t *dr_out_val
= calloc(DIV_ROUND_UP(hub
->virtual_ir
->length
, 8), 1);
352 LOG_ERROR("Out of memory");
355 buf_set_u32(dr_out_val
, 0, hub
->virtual_ir
->length
, hub
->virtual_ir
->value
);
357 struct scan_field fields
;
358 ipdbg_init_scan_field(&fields
, NULL
, hub
->virtual_ir
->length
, dr_out_val
);
359 jtag_add_dr_scan(tap
, 1, &fields
, TAP_IDLE
);
360 retval
= jtag_execute_queue();
367 static int ipdbg_shift_data(struct ipdbg_hub
*hub
, uint32_t dn_data
, uint32_t *up_data
)
372 struct jtag_tap
*tap
= hub
->tap
;
376 uint8_t *dr_out_val
= calloc(DIV_ROUND_UP(hub
->data_register_length
, 8), 1);
378 LOG_ERROR("Out of memory");
381 buf_set_u32(dr_out_val
, 0, hub
->data_register_length
, dn_data
);
383 uint8_t *dr_in_val
= NULL
;
385 dr_in_val
= calloc(DIV_ROUND_UP(hub
->data_register_length
, 8), 1);
387 LOG_ERROR("Out of memory");
393 struct scan_field fields
;
394 ipdbg_init_scan_field(&fields
, dr_in_val
, hub
->data_register_length
, dr_out_val
);
395 jtag_add_dr_scan(tap
, 1, &fields
, TAP_IDLE
);
396 int retval
= jtag_execute_queue();
398 if (up_data
&& retval
== ERROR_OK
)
399 *up_data
= buf_get_u32(dr_in_val
, 0, hub
->data_register_length
);
407 static int ipdbg_distribute_data_from_hub(struct ipdbg_hub
*hub
, uint32_t up
)
409 const bool valid_up_data
= up
& hub
->valid_mask
;
413 const size_t tool
= (up
>> 8) & hub
->tool_mask
;
414 if (tool
== hub
->tool_mask
) {
415 const uint8_t xon_cmd
= up
& 0x00ff;
416 hub
->dn_xoff
&= ~xon_cmd
;
417 LOG_INFO("received xon cmd: %d\n", xon_cmd
);
421 struct connection
*conn
= hub
->connections
[tool
];
423 struct ipdbg_connection
*connection
= conn
->priv
;
424 if (ipdbg_fifo_is_full(&connection
->up_fifo
)) {
425 int retval
= ipdbg_move_buffer_to_connection(conn
, &connection
->up_fifo
);
426 if (retval
!= ERROR_OK
)
429 ipdbg_append_to_fifo(&connection
->up_fifo
, up
);
434 static int ipdbg_jtag_transfer_byte(struct ipdbg_hub
*hub
, size_t tool
, struct ipdbg_connection
*connection
)
436 uint32_t dn
= hub
->valid_mask
| ((tool
& hub
->tool_mask
) << 8) |
437 (0x00fful
& ipdbg_get_from_fifo(&connection
->dn_fifo
));
439 int ret
= ipdbg_shift_data(hub
, dn
, &up
);
443 ret
= ipdbg_distribute_data_from_hub(hub
, up
);
447 if ((up
& hub
->xoff_mask
) && (hub
->last_dn_tool
!= hub
->max_tools
)) {
448 hub
->dn_xoff
|= BIT(hub
->last_dn_tool
);
449 LOG_INFO("tool %d sent xoff", hub
->last_dn_tool
);
452 hub
->last_dn_tool
= tool
;
457 static int ipdbg_polling_callback(void *priv
)
459 struct ipdbg_hub
*hub
= priv
;
461 int ret
= ipdbg_shift_vir(hub
);
465 ret
= ipdbg_shift_instr(hub
, hub
->user_instruction
);
469 /* transfer dn buffers to jtag-hub */
470 unsigned int num_transfers
= 0;
471 for (size_t tool
= 0; tool
< hub
->max_tools
; ++tool
) {
472 struct connection
*conn
= hub
->connections
[tool
];
473 if (conn
&& conn
->priv
) {
474 struct ipdbg_connection
*connection
= conn
->priv
;
475 while (((hub
->dn_xoff
& BIT(tool
)) == 0) && !ipdbg_fifo_is_empty(&connection
->dn_fifo
)) {
476 ret
= ipdbg_jtag_transfer_byte(hub
, tool
, connection
);
484 /* some transfers to get data from jtag-hub in case there is no dn data */
485 while (num_transfers
++ < hub
->max_tools
) {
489 int retval
= ipdbg_shift_data(hub
, dn
, &up
);
490 if (retval
!= ERROR_OK
)
493 retval
= ipdbg_distribute_data_from_hub(hub
, up
);
494 if (retval
!= ERROR_OK
)
498 /* write from up fifos to sockets */
499 for (size_t tool
= 0; tool
< hub
->max_tools
; ++tool
) {
500 struct connection
*conn
= hub
->connections
[tool
];
501 if (conn
&& conn
->priv
) {
502 struct ipdbg_connection
*connection
= conn
->priv
;
503 int retval
= ipdbg_move_buffer_to_connection(conn
, &connection
->up_fifo
);
504 if (retval
!= ERROR_OK
)
512 static int ipdbg_start_polling(struct ipdbg_service
*service
, struct connection
*connection
)
514 struct ipdbg_hub
*hub
= service
->hub
;
515 hub
->connections
[service
->tool
] = connection
;
516 hub
->active_connections
++;
517 if (hub
->active_connections
> 1) {
518 /* hub is already initialized */
522 const uint32_t reset_hub
= hub
->valid_mask
| ((hub
->max_tools
) << 8);
524 int ret
= ipdbg_shift_vir(hub
);
528 ret
= ipdbg_shift_instr(hub
, hub
->user_instruction
);
532 ret
= ipdbg_shift_data(hub
, reset_hub
, NULL
);
533 hub
->last_dn_tool
= hub
->tool_mask
;
538 LOG_INFO("IPDBG start_polling");
540 const int time_ms
= 20;
541 const int periodic
= 1;
542 return target_register_timer_callback(ipdbg_polling_callback
, time_ms
, periodic
, hub
);
545 static int ipdbg_stop_polling(struct ipdbg_service
*service
)
547 struct ipdbg_hub
*hub
= service
->hub
;
548 hub
->connections
[service
->tool
] = NULL
;
549 hub
->active_connections
--;
550 if (hub
->active_connections
== 0) {
551 LOG_INFO("IPDBG stop_polling");
553 return target_unregister_timer_callback(ipdbg_polling_callback
, hub
);
559 static int ipdbg_on_new_connection(struct connection
*connection
)
561 struct ipdbg_service
*service
= connection
->service
->priv
;
562 connection
->priv
= &service
->connection
;
563 /* initialize ipdbg connection information */
564 ipdbg_init_fifo(&service
->connection
.up_fifo
);
565 ipdbg_init_fifo(&service
->connection
.dn_fifo
);
567 int retval
= ipdbg_start_polling(service
, connection
);
568 if (retval
!= ERROR_OK
) {
569 LOG_ERROR("BUG: ipdbg_start_polling failed");
573 struct ipdbg_connection
*conn
= connection
->priv
;
574 conn
->closed
= false;
576 LOG_INFO("New IPDBG Connection");
581 static int ipdbg_on_connection_input(struct connection
*connection
)
583 struct ipdbg_connection
*conn
= connection
->priv
;
584 struct ipdbg_fifo
*fifo
= &conn
->dn_fifo
;
586 if (ipdbg_fifo_is_full(fifo
))
589 ipdbg_zero_rd_idx(fifo
);
590 int bytes_read
= connection_read(connection
, fifo
->buffer
+ fifo
->count
, IPDBG_BUFFER_SIZE
- fifo
->count
);
591 if (bytes_read
<= 0) {
593 LOG_ERROR("error during read: %s", strerror(errno
));
594 return ERROR_SERVER_REMOTE_CLOSED
;
597 fifo
->count
+= bytes_read
;
602 static int ipdbg_on_connection_closed(struct connection
*connection
)
604 struct ipdbg_connection
*conn
= connection
->priv
;
606 LOG_INFO("Closed IPDBG Connection");
608 return ipdbg_stop_polling(connection
->service
->priv
);
611 static const struct service_driver ipdbg_service_driver
= {
613 .new_connection_during_keep_alive_handler
= NULL
,
614 .new_connection_handler
= ipdbg_on_new_connection
,
615 .input_handler
= ipdbg_on_connection_input
,
616 .connection_closed_handler
= ipdbg_on_connection_closed
,
617 .keep_client_alive_handler
= NULL
,
620 static int ipdbg_start(uint16_t port
, struct jtag_tap
*tap
, uint32_t user_instruction
,
621 uint8_t data_register_length
, struct ipdbg_virtual_ir_info
*virtual_ir
, uint8_t tool
)
623 LOG_INFO("starting ipdbg service on port %d for tool %d", port
, tool
);
625 struct ipdbg_hub
*hub
= ipdbg_find_hub(tap
, user_instruction
, virtual_ir
);
628 if (hub
->data_register_length
!= data_register_length
) {
629 LOG_DEBUG("hub must have the same data_register_length for all tools");
633 int retval
= ipdbg_create_hub(tap
, user_instruction
, data_register_length
, virtual_ir
, &hub
);
634 if (retval
!= ERROR_OK
) {
640 struct ipdbg_service
*service
= NULL
;
641 int retval
= ipdbg_create_service(hub
, tool
, &service
, port
);
643 if (retval
!= ERROR_OK
|| !service
) {
644 if (hub
->active_services
== 0 && hub
->active_connections
== 0)
649 char port_str_buffer
[IPDBG_TCP_PORT_STR_MAX_LENGTH
];
650 snprintf(port_str_buffer
, IPDBG_TCP_PORT_STR_MAX_LENGTH
, "%u", port
);
651 retval
= add_service(&ipdbg_service_driver
, port_str_buffer
, 1, service
);
652 if (retval
== ERROR_OK
) {
653 ipdbg_add_service(service
);
654 if (hub
->active_services
== 0 && hub
->active_connections
== 0)
656 hub
->active_services
++;
658 if (hub
->active_services
== 0 && hub
->active_connections
== 0)
666 static int ipdbg_stop(struct jtag_tap
*tap
, uint32_t user_instruction
,
667 struct ipdbg_virtual_ir_info
*virtual_ir
, uint8_t tool
)
669 struct ipdbg_hub
*hub
= ipdbg_find_hub(tap
, user_instruction
, virtual_ir
);
674 struct ipdbg_service
*service
= ipdbg_find_service(hub
, tool
);
678 int retval
= ipdbg_remove_service(service
);
679 if (retval
!= ERROR_OK
) {
680 LOG_ERROR("BUG: ipdbg_remove_service failed");
684 char port_str_buffer
[IPDBG_TCP_PORT_STR_MAX_LENGTH
];
685 snprintf(port_str_buffer
, IPDBG_TCP_PORT_STR_MAX_LENGTH
, "%u", service
->port
);
686 retval
= remove_service("ipdbg", port_str_buffer
);
687 /* The ipdbg_service structure is freed by server.c:remove_service().
688 There the "priv" pointer is freed.*/
689 if (retval
!= ERROR_OK
) {
690 LOG_ERROR("BUG: remove_service failed");
693 hub
->active_services
--;
694 if (hub
->active_connections
== 0 && hub
->active_services
== 0) {
695 retval
= ipdbg_remove_hub(hub
);
696 if (retval
!= ERROR_OK
) {
697 LOG_ERROR("BUG: ipdbg_remove_hub failed");
705 COMMAND_HANDLER(handle_ipdbg_command
)
707 struct jtag_tap
*tap
= NULL
;
708 uint16_t port
= 4242;
710 uint32_t user_instruction
= 0x00;
711 uint8_t data_register_length
= IPDBG_MAX_DR_LENGTH
;
713 bool hub_configured
= false;
714 bool has_virtual_ir
= false;
715 uint32_t virtual_ir_instruction
= 0x00e;
716 uint32_t virtual_ir_length
= 5;
717 uint32_t virtual_ir_value
= 0x11;
718 struct ipdbg_virtual_ir_info
*virtual_ir
= NULL
;
720 if ((CMD_ARGC
< IPDBG_MIN_NUM_OF_OPTIONS
) || (CMD_ARGC
> IPDBG_MAX_NUM_OF_OPTIONS
))
721 return ERROR_COMMAND_SYNTAX_ERROR
;
723 for (unsigned int i
= 0; i
< CMD_ARGC
; ++i
) {
724 if (strcmp(CMD_ARGV
[i
], "-tap") == 0) {
725 if (i
+ 1 >= CMD_ARGC
|| CMD_ARGV
[i
+ 1][0] == '-') {
726 command_print(CMD
, "no TAP given");
729 tap
= jtag_tap_by_string(CMD_ARGV
[i
+ 1]);
731 command_print(CMD
, "Tap %s unknown", CMD_ARGV
[i
+ 1]);
735 } else if (strcmp(CMD_ARGV
[i
], "-hub") == 0) {
736 COMMAND_PARSE_ADDITIONAL_NUMBER(u32
, i
, user_instruction
, "ir_value to select hub");
737 hub_configured
= true;
738 COMMAND_PARSE_OPTIONAL_NUMBER(u8
, i
, data_register_length
);
739 if (data_register_length
< IPDBG_MIN_DR_LENGTH
||
740 data_register_length
> IPDBG_MAX_DR_LENGTH
) {
741 command_print(CMD
, "length of \"user\"-data register must be at least %d and at most %d.",
742 IPDBG_MIN_DR_LENGTH
, IPDBG_MAX_DR_LENGTH
);
745 } else if (strcmp(CMD_ARGV
[i
], "-vir") == 0) {
746 COMMAND_PARSE_OPTIONAL_NUMBER(u32
, i
, virtual_ir_value
);
747 COMMAND_PARSE_OPTIONAL_NUMBER(u32
, i
, virtual_ir_length
);
748 COMMAND_PARSE_OPTIONAL_NUMBER(u32
, i
, virtual_ir_instruction
);
749 has_virtual_ir
= true;
750 } else if (strcmp(CMD_ARGV
[i
], "-port") == 0) {
751 COMMAND_PARSE_ADDITIONAL_NUMBER(u16
, i
, port
, "port number");
752 } else if (strcmp(CMD_ARGV
[i
], "-tool") == 0) {
753 COMMAND_PARSE_ADDITIONAL_NUMBER(u8
, i
, tool
, "tool");
754 } else if (strcmp(CMD_ARGV
[i
], "-stop") == 0) {
756 } else if (strcmp(CMD_ARGV
[i
], "-start") == 0) {
759 command_print(CMD
, "Unknown argument: %s", CMD_ARGV
[i
]);
765 command_print(CMD
, "no valid tap selected");
769 if (!hub_configured
) {
770 command_print(CMD
, "hub not configured correctly");
774 if (tool
>= ipdbg_max_tools_from_data_register_length(data_register_length
)) {
775 command_print(CMD
, "Tool: %d is invalid", tool
);
779 if (has_virtual_ir
) {
780 virtual_ir
= calloc(1, sizeof(struct ipdbg_virtual_ir_info
));
782 LOG_ERROR("Out of memory");
785 virtual_ir
->instruction
= virtual_ir_instruction
;
786 virtual_ir
->length
= virtual_ir_length
;
787 virtual_ir
->value
= virtual_ir_value
;
791 return ipdbg_start(port
, tap
, user_instruction
, data_register_length
, virtual_ir
, tool
);
793 return ipdbg_stop(tap
, user_instruction
, virtual_ir
, tool
);
796 static const struct command_registration ipdbg_command_handlers
[] = {
799 .handler
= handle_ipdbg_command
,
800 .mode
= COMMAND_EXEC
,
801 .help
= "Starts or stops an IPDBG JTAG-Host server.",
802 .usage
= "[-start|-stop] -tap device.tap -hub ir_value [dr_length]"
803 " [-port number] [-tool number] [-vir [vir_value [length [instr_code]]]]",
805 COMMAND_REGISTRATION_DONE
808 int ipdbg_register_commands(struct command_context
*cmd_ctx
)
810 return register_commands(cmd_ctx
, NULL
, ipdbg_command_handlers
);