jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / jtag / drivers / jtag_vpi.c
1 /*
2 * JTAG to VPI driver
3 *
4 * Copyright (C) 2013 Franck Jullien, <elec4fun@gmail.com>
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26
27 #include <jtag/interface.h>
28 #ifdef HAVE_ARPA_INET_H
29 #include <arpa/inet.h>
30 #endif
31
32 #ifndef _WIN32
33 #include <netinet/tcp.h>
34 #endif
35
36 #include "helper/replacements.h"
37
38 #define NO_TAP_SHIFT 0
39 #define TAP_SHIFT 1
40
41 #define DEFAULT_SERVER_ADDRESS "127.0.0.1"
42 #define DEFAULT_SERVER_PORT 5555
43
44 #define XFERT_MAX_SIZE 512
45
46 #define CMD_RESET 0
47 #define CMD_TMS_SEQ 1
48 #define CMD_SCAN_CHAIN 2
49 #define CMD_SCAN_CHAIN_FLIP_TMS 3
50 #define CMD_STOP_SIMU 4
51
52 /* jtag_vpi server port and address to connect to */
53 static int server_port = DEFAULT_SERVER_PORT;
54 static char *server_address;
55
56 /* Send CMD_STOP_SIMU to server when OpenOCD exits? */
57 static bool stop_sim_on_exit;
58
59 static int sockfd;
60 static struct sockaddr_in serv_addr;
61
62 /* One jtag_vpi "packet" as sent over a TCP channel. */
63 struct vpi_cmd {
64 union {
65 uint32_t cmd;
66 unsigned char cmd_buf[4];
67 };
68 unsigned char buffer_out[XFERT_MAX_SIZE];
69 unsigned char buffer_in[XFERT_MAX_SIZE];
70 union {
71 uint32_t length;
72 unsigned char length_buf[4];
73 };
74 union {
75 uint32_t nb_bits;
76 unsigned char nb_bits_buf[4];
77 };
78 };
79
80 static char *jtag_vpi_cmd_to_str(int cmd_num)
81 {
82 switch (cmd_num) {
83 case CMD_RESET:
84 return "CMD_RESET";
85 case CMD_TMS_SEQ:
86 return "CMD_TMS_SEQ";
87 case CMD_SCAN_CHAIN:
88 return "CMD_SCAN_CHAIN";
89 case CMD_SCAN_CHAIN_FLIP_TMS:
90 return "CMD_SCAN_CHAIN_FLIP_TMS";
91 case CMD_STOP_SIMU:
92 return "CMD_STOP_SIMU";
93 default:
94 return "<unknown>";
95 }
96 }
97
98 static int jtag_vpi_send_cmd(struct vpi_cmd *vpi)
99 {
100 int retval;
101
102 /* Optional low-level JTAG debug */
103 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
104 if (vpi->nb_bits > 0) {
105 /* command with a non-empty data payload */
106 char *char_buf = buf_to_hex_str(vpi->buffer_out,
107 (vpi->nb_bits > DEBUG_JTAG_IOZ)
108 ? DEBUG_JTAG_IOZ
109 : vpi->nb_bits);
110 LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
111 "length=%" PRIu32 ", "
112 "nb_bits=%" PRIu32 ", "
113 "buf_out=0x%s%s",
114 jtag_vpi_cmd_to_str(vpi->cmd),
115 vpi->length,
116 vpi->nb_bits,
117 char_buf,
118 (vpi->nb_bits > DEBUG_JTAG_IOZ) ? "(...)" : "");
119 free(char_buf);
120 } else {
121 /* command without data payload */
122 LOG_DEBUG_IO("sending JTAG VPI cmd: cmd=%s, "
123 "length=%" PRIu32 ", "
124 "nb_bits=%" PRIu32,
125 jtag_vpi_cmd_to_str(vpi->cmd),
126 vpi->length,
127 vpi->nb_bits);
128 }
129 }
130
131 /* Use little endian when transmitting/receiving jtag_vpi cmds.
132 The choice of little endian goes against usual networking conventions
133 but is intentional to remain compatible with most older OpenOCD builds
134 (i.e. builds on little-endian platforms). */
135 h_u32_to_le(vpi->cmd_buf, vpi->cmd);
136 h_u32_to_le(vpi->length_buf, vpi->length);
137 h_u32_to_le(vpi->nb_bits_buf, vpi->nb_bits);
138
139 retry_write:
140 retval = write_socket(sockfd, vpi, sizeof(struct vpi_cmd));
141
142 if (retval < 0) {
143 /* Account for the case when socket write is interrupted. */
144 #ifdef _WIN32
145 int wsa_err = WSAGetLastError();
146 if (wsa_err == WSAEINTR)
147 goto retry_write;
148 #else
149 if (errno == EINTR)
150 goto retry_write;
151 #endif
152 /* Otherwise this is an error using the socket, most likely fatal
153 for the connection. B*/
154 log_socket_error("jtag_vpi xmit");
155 /* TODO: Clean way how adapter drivers can report fatal errors
156 to upper layers of OpenOCD and let it perform an orderly shutdown? */
157 exit(-1);
158 } else if (retval < (int)sizeof(struct vpi_cmd)) {
159 /* This means we could not send all data, which is most likely fatal
160 for the jtag_vpi connection (the underlying TCP connection likely not
161 usable anymore) */
162 LOG_ERROR("jtag_vpi: Could not send all data through jtag_vpi connection.");
163 exit(-1);
164 }
165
166 /* Otherwise the packet has been sent successfully. */
167 return ERROR_OK;
168 }
169
170 static int jtag_vpi_receive_cmd(struct vpi_cmd *vpi)
171 {
172 unsigned bytes_buffered = 0;
173 while (bytes_buffered < sizeof(struct vpi_cmd)) {
174 int bytes_to_receive = sizeof(struct vpi_cmd) - bytes_buffered;
175 int retval = read_socket(sockfd, ((char *)vpi) + bytes_buffered, bytes_to_receive);
176 if (retval < 0) {
177 #ifdef _WIN32
178 int wsa_err = WSAGetLastError();
179 if (wsa_err == WSAEINTR) {
180 /* socket read interrupted by WSACancelBlockingCall() */
181 continue;
182 }
183 #else
184 if (errno == EINTR) {
185 /* socket read interrupted by a signal */
186 continue;
187 }
188 #endif
189 /* Otherwise, this is an error when accessing the socket. */
190 log_socket_error("jtag_vpi recv");
191 exit(-1);
192 } else if (retval == 0) {
193 /* Connection closed by the other side */
194 LOG_ERROR("Connection prematurely closed by jtag_vpi server.");
195 exit(-1);
196 }
197 /* Otherwise, we have successfully received some data */
198 bytes_buffered += retval;
199 }
200
201 /* Use little endian when transmitting/receiving jtag_vpi cmds. */
202 vpi->cmd = le_to_h_u32(vpi->cmd_buf);
203 vpi->length = le_to_h_u32(vpi->length_buf);
204 vpi->nb_bits = le_to_h_u32(vpi->nb_bits_buf);
205
206 return ERROR_OK;
207 }
208
209 /**
210 * jtag_vpi_reset - ask to reset the JTAG device
211 * @param trst 1 if TRST is to be asserted
212 * @param srst 1 if SRST is to be asserted
213 */
214 static int jtag_vpi_reset(int trst, int srst)
215 {
216 struct vpi_cmd vpi;
217 memset(&vpi, 0, sizeof(struct vpi_cmd));
218
219 vpi.cmd = CMD_RESET;
220 vpi.length = 0;
221 return jtag_vpi_send_cmd(&vpi);
222 }
223
224 /**
225 * jtag_vpi_tms_seq - ask a TMS sequence transition to JTAG
226 * @param bits TMS bits to be written (bit0, bit1 .. bitN)
227 * @param nb_bits number of TMS bits (between 1 and 8)
228 *
229 * Write a series of TMS transitions, where each transition consists in :
230 * - writing out TCK=0, TMS=\<new_state>, TDI=\<???>
231 * - writing out TCK=1, TMS=\<new_state>, TDI=\<???> which triggers the transition
232 * The function ensures that at the end of the sequence, the clock (TCK) is put
233 * low.
234 */
235 static int jtag_vpi_tms_seq(const uint8_t *bits, int nb_bits)
236 {
237 struct vpi_cmd vpi;
238 int nb_bytes;
239
240 memset(&vpi, 0, sizeof(struct vpi_cmd));
241 nb_bytes = DIV_ROUND_UP(nb_bits, 8);
242
243 vpi.cmd = CMD_TMS_SEQ;
244 memcpy(vpi.buffer_out, bits, nb_bytes);
245 vpi.length = nb_bytes;
246 vpi.nb_bits = nb_bits;
247
248 return jtag_vpi_send_cmd(&vpi);
249 }
250
251 /**
252 * jtag_vpi_path_move - ask a TMS sequence transition to JTAG
253 * @param cmd path transition
254 *
255 * Write a series of TMS transitions, where each transition consists in :
256 * - writing out TCK=0, TMS=\<new_state>, TDI=\<???>
257 * - writing out TCK=1, TMS=\<new_state>, TDI=\<???> which triggers the transition
258 * The function ensures that at the end of the sequence, the clock (TCK) is put
259 * low.
260 */
261
262 static int jtag_vpi_path_move(struct pathmove_command *cmd)
263 {
264 uint8_t trans[DIV_ROUND_UP(cmd->num_states, 8)];
265
266 memset(trans, 0, DIV_ROUND_UP(cmd->num_states, 8));
267
268 for (int i = 0; i < cmd->num_states; i++) {
269 if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
270 buf_set_u32(trans, i, 1, 1);
271 tap_set_state(cmd->path[i]);
272 }
273
274 return jtag_vpi_tms_seq(trans, cmd->num_states);
275 }
276
277 /**
278 * jtag_vpi_tms - ask a tms command
279 * @param cmd tms command
280 */
281 static int jtag_vpi_tms(struct tms_command *cmd)
282 {
283 return jtag_vpi_tms_seq(cmd->bits, cmd->num_bits);
284 }
285
286 static int jtag_vpi_state_move(tap_state_t state)
287 {
288 if (tap_get_state() == state)
289 return ERROR_OK;
290
291 uint8_t tms_scan = tap_get_tms_path(tap_get_state(), state);
292 int tms_len = tap_get_tms_path_len(tap_get_state(), state);
293
294 int retval = jtag_vpi_tms_seq(&tms_scan, tms_len);
295 if (retval != ERROR_OK)
296 return retval;
297
298 tap_set_state(state);
299
300 return ERROR_OK;
301 }
302
303 static int jtag_vpi_queue_tdi_xfer(uint8_t *bits, int nb_bits, int tap_shift)
304 {
305 struct vpi_cmd vpi;
306 int nb_bytes = DIV_ROUND_UP(nb_bits, 8);
307
308 memset(&vpi, 0, sizeof(struct vpi_cmd));
309
310 vpi.cmd = tap_shift ? CMD_SCAN_CHAIN_FLIP_TMS : CMD_SCAN_CHAIN;
311
312 if (bits)
313 memcpy(vpi.buffer_out, bits, nb_bytes);
314 else
315 memset(vpi.buffer_out, 0xff, nb_bytes);
316
317 vpi.length = nb_bytes;
318 vpi.nb_bits = nb_bits;
319
320 int retval = jtag_vpi_send_cmd(&vpi);
321 if (retval != ERROR_OK)
322 return retval;
323
324 retval = jtag_vpi_receive_cmd(&vpi);
325 if (retval != ERROR_OK)
326 return retval;
327
328 /* Optional low-level JTAG debug */
329 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
330 char *char_buf = buf_to_hex_str(vpi.buffer_in,
331 (nb_bits > DEBUG_JTAG_IOZ) ? DEBUG_JTAG_IOZ : nb_bits);
332 LOG_DEBUG_IO("recvd JTAG VPI data: nb_bits=%d, buf_in=0x%s%s",
333 nb_bits, char_buf, (nb_bits > DEBUG_JTAG_IOZ) ? "(...)" : "");
334 free(char_buf);
335 }
336
337 if (bits)
338 memcpy(bits, vpi.buffer_in, nb_bytes);
339
340 return ERROR_OK;
341 }
342
343 /**
344 * jtag_vpi_queue_tdi - short description
345 * @param bits bits to be queued on TDI (or NULL if 0 are to be queued)
346 * @param nb_bits number of bits
347 * @param tap_shift
348 */
349 static int jtag_vpi_queue_tdi(uint8_t *bits, int nb_bits, int tap_shift)
350 {
351 int nb_xfer = DIV_ROUND_UP(nb_bits, XFERT_MAX_SIZE * 8);
352 int retval;
353
354 while (nb_xfer) {
355 if (nb_xfer == 1) {
356 retval = jtag_vpi_queue_tdi_xfer(bits, nb_bits, tap_shift);
357 if (retval != ERROR_OK)
358 return retval;
359 } else {
360 retval = jtag_vpi_queue_tdi_xfer(bits, XFERT_MAX_SIZE * 8, NO_TAP_SHIFT);
361 if (retval != ERROR_OK)
362 return retval;
363 nb_bits -= XFERT_MAX_SIZE * 8;
364 if (bits)
365 bits += XFERT_MAX_SIZE;
366 }
367
368 nb_xfer--;
369 }
370
371 return ERROR_OK;
372 }
373
374 /**
375 * jtag_vpi_clock_tms - clock a TMS transition
376 * @param tms the TMS to be sent
377 *
378 * Triggers a TMS transition (ie. one JTAG TAP state move).
379 */
380 static int jtag_vpi_clock_tms(int tms)
381 {
382 const uint8_t tms_0 = 0;
383 const uint8_t tms_1 = 1;
384
385 return jtag_vpi_tms_seq(tms ? &tms_1 : &tms_0, 1);
386 }
387
388 /**
389 * jtag_vpi_scan - launches a DR-scan or IR-scan
390 * @param cmd the command to launch
391 *
392 * Launch a JTAG IR-scan or DR-scan
393 *
394 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occurred.
395 */
396 static int jtag_vpi_scan(struct scan_command *cmd)
397 {
398 int scan_bits;
399 uint8_t *buf = NULL;
400 int retval = ERROR_OK;
401
402 scan_bits = jtag_build_buffer(cmd, &buf);
403
404 if (cmd->ir_scan) {
405 retval = jtag_vpi_state_move(TAP_IRSHIFT);
406 if (retval != ERROR_OK)
407 return retval;
408 } else {
409 retval = jtag_vpi_state_move(TAP_DRSHIFT);
410 if (retval != ERROR_OK)
411 return retval;
412 }
413
414 if (cmd->end_state == TAP_DRSHIFT) {
415 retval = jtag_vpi_queue_tdi(buf, scan_bits, NO_TAP_SHIFT);
416 if (retval != ERROR_OK)
417 return retval;
418 } else {
419 retval = jtag_vpi_queue_tdi(buf, scan_bits, TAP_SHIFT);
420 if (retval != ERROR_OK)
421 return retval;
422 }
423
424 if (cmd->end_state != TAP_DRSHIFT) {
425 /*
426 * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it
427 * forward to a stable IRPAUSE or DRPAUSE.
428 */
429 retval = jtag_vpi_clock_tms(0);
430 if (retval != ERROR_OK)
431 return retval;
432
433 if (cmd->ir_scan)
434 tap_set_state(TAP_IRPAUSE);
435 else
436 tap_set_state(TAP_DRPAUSE);
437 }
438
439 retval = jtag_read_buffer(buf, cmd);
440 if (retval != ERROR_OK)
441 return retval;
442
443 free(buf);
444
445 if (cmd->end_state != TAP_DRSHIFT) {
446 retval = jtag_vpi_state_move(cmd->end_state);
447 if (retval != ERROR_OK)
448 return retval;
449 }
450
451 return ERROR_OK;
452 }
453
454 static int jtag_vpi_runtest(int cycles, tap_state_t state)
455 {
456 int retval;
457
458 retval = jtag_vpi_state_move(TAP_IDLE);
459 if (retval != ERROR_OK)
460 return retval;
461
462 retval = jtag_vpi_queue_tdi(NULL, cycles, NO_TAP_SHIFT);
463 if (retval != ERROR_OK)
464 return retval;
465
466 return jtag_vpi_state_move(state);
467 }
468
469 static int jtag_vpi_stableclocks(int cycles)
470 {
471 uint8_t tms_bits[4];
472 int cycles_remain = cycles;
473 int nb_bits;
474 int retval;
475 const int CYCLES_ONE_BATCH = sizeof(tms_bits) * 8;
476
477 assert(cycles >= 0);
478
479 /* use TMS=1 in TAP RESET state, TMS=0 in all other stable states */
480 memset(&tms_bits, (tap_get_state() == TAP_RESET) ? 0xff : 0x00, sizeof(tms_bits));
481
482 /* send the TMS bits */
483 while (cycles_remain > 0) {
484 nb_bits = (cycles_remain < CYCLES_ONE_BATCH) ? cycles_remain : CYCLES_ONE_BATCH;
485 retval = jtag_vpi_tms_seq(tms_bits, nb_bits);
486 if (retval != ERROR_OK)
487 return retval;
488 cycles_remain -= nb_bits;
489 }
490
491 return ERROR_OK;
492 }
493
494 static int jtag_vpi_execute_queue(void)
495 {
496 struct jtag_command *cmd;
497 int retval = ERROR_OK;
498
499 for (cmd = jtag_command_queue; retval == ERROR_OK && cmd;
500 cmd = cmd->next) {
501 switch (cmd->type) {
502 case JTAG_RESET:
503 retval = jtag_vpi_reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
504 break;
505 case JTAG_RUNTEST:
506 retval = jtag_vpi_runtest(cmd->cmd.runtest->num_cycles,
507 cmd->cmd.runtest->end_state);
508 break;
509 case JTAG_STABLECLOCKS:
510 retval = jtag_vpi_stableclocks(cmd->cmd.stableclocks->num_cycles);
511 break;
512 case JTAG_TLR_RESET:
513 retval = jtag_vpi_state_move(cmd->cmd.statemove->end_state);
514 break;
515 case JTAG_PATHMOVE:
516 retval = jtag_vpi_path_move(cmd->cmd.pathmove);
517 break;
518 case JTAG_TMS:
519 retval = jtag_vpi_tms(cmd->cmd.tms);
520 break;
521 case JTAG_SLEEP:
522 jtag_sleep(cmd->cmd.sleep->us);
523 break;
524 case JTAG_SCAN:
525 retval = jtag_vpi_scan(cmd->cmd.scan);
526 break;
527 default:
528 LOG_ERROR("BUG: unknown JTAG command type 0x%X",
529 cmd->type);
530 retval = ERROR_FAIL;
531 break;
532 }
533 }
534
535 return retval;
536 }
537
538 static int jtag_vpi_init(void)
539 {
540 int flag = 1;
541
542 sockfd = socket(AF_INET, SOCK_STREAM, 0);
543 if (sockfd < 0) {
544 LOG_ERROR("jtag_vpi: Could not create client socket");
545 return ERROR_FAIL;
546 }
547
548 memset(&serv_addr, 0, sizeof(serv_addr));
549
550 serv_addr.sin_family = AF_INET;
551 serv_addr.sin_port = htons(server_port);
552
553 if (!server_address)
554 server_address = strdup(DEFAULT_SERVER_ADDRESS);
555
556 serv_addr.sin_addr.s_addr = inet_addr(server_address);
557
558 if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
559 LOG_ERROR("jtag_vpi: inet_addr error occurred");
560 return ERROR_FAIL;
561 }
562
563 if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
564 close(sockfd);
565 LOG_ERROR("jtag_vpi: Can't connect to %s : %u", server_address, server_port);
566 return ERROR_COMMAND_CLOSE_CONNECTION;
567 }
568
569 if (serv_addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
570 /* This increases performance dramatically for local
571 * connections, which is the most likely arrangement
572 * for a VPI connection. */
573 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
574 }
575
576 LOG_INFO("jtag_vpi: Connection to %s : %u successful", server_address, server_port);
577
578 return ERROR_OK;
579 }
580
581 static int jtag_vpi_stop_simulation(void)
582 {
583 struct vpi_cmd cmd;
584 memset(&cmd, 0, sizeof(struct vpi_cmd));
585 cmd.length = 0;
586 cmd.nb_bits = 0;
587 cmd.cmd = CMD_STOP_SIMU;
588 return jtag_vpi_send_cmd(&cmd);
589 }
590
591 static int jtag_vpi_quit(void)
592 {
593 if (stop_sim_on_exit) {
594 if (jtag_vpi_stop_simulation() != ERROR_OK)
595 LOG_WARNING("jtag_vpi: failed to send \"stop simulation\" command");
596 }
597 if (close_socket(sockfd) != 0) {
598 LOG_WARNING("jtag_vpi: could not close jtag_vpi client socket");
599 log_socket_error("jtag_vpi");
600 }
601 free(server_address);
602 return ERROR_OK;
603 }
604
605 COMMAND_HANDLER(jtag_vpi_set_port)
606 {
607 if (CMD_ARGC == 0) {
608 LOG_ERROR("Command \"jtag_vpi set_port\" expects 1 argument (TCP port number)");
609 return ERROR_COMMAND_SYNTAX_ERROR;
610 }
611
612 COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], server_port);
613 LOG_INFO("jtag_vpi: server port set to %u", server_port);
614
615 return ERROR_OK;
616 }
617
618 COMMAND_HANDLER(jtag_vpi_set_address)
619 {
620
621 if (CMD_ARGC == 0) {
622 LOG_ERROR("Command \"jtag_vpi set_address\" expects 1 argument (IP address)");
623 return ERROR_COMMAND_SYNTAX_ERROR;
624 }
625
626 free(server_address);
627 server_address = strdup(CMD_ARGV[0]);
628 LOG_INFO("jtag_vpi: server address set to %s", server_address);
629
630 return ERROR_OK;
631 }
632
633 COMMAND_HANDLER(jtag_vpi_stop_sim_on_exit_handler)
634 {
635 if (CMD_ARGC != 1) {
636 LOG_ERROR("Command \"jtag_vpi stop_sim_on_exit\" expects 1 argument (on|off)");
637 return ERROR_COMMAND_SYNTAX_ERROR;
638 }
639
640 COMMAND_PARSE_ON_OFF(CMD_ARGV[0], stop_sim_on_exit);
641 return ERROR_OK;
642 }
643
644 static const struct command_registration jtag_vpi_subcommand_handlers[] = {
645 {
646 .name = "set_port",
647 .handler = &jtag_vpi_set_port,
648 .mode = COMMAND_CONFIG,
649 .help = "set the TCP port number of the jtag_vpi server (default: 5555)",
650 .usage = "tcp_port_num",
651 },
652 {
653 .name = "set_address",
654 .handler = &jtag_vpi_set_address,
655 .mode = COMMAND_CONFIG,
656 .help = "set the IP address of the jtag_vpi server (default: 127.0.0.1)",
657 .usage = "ipv4_addr",
658 },
659 {
660 .name = "stop_sim_on_exit",
661 .handler = &jtag_vpi_stop_sim_on_exit_handler,
662 .mode = COMMAND_CONFIG,
663 .help = "Configure if simulation stop command shall be sent "
664 "before OpenOCD exits (default: off)",
665 .usage = "<on|off>",
666 },
667 COMMAND_REGISTRATION_DONE
668 };
669
670 static const struct command_registration jtag_vpi_command_handlers[] = {
671 {
672 .name = "jtag_vpi",
673 .mode = COMMAND_ANY,
674 .help = "perform jtag_vpi management",
675 .chain = jtag_vpi_subcommand_handlers,
676 .usage = "",
677 },
678 COMMAND_REGISTRATION_DONE
679 };
680
681 static struct jtag_interface jtag_vpi_interface = {
682 .supported = DEBUG_CAP_TMS_SEQ,
683 .execute_queue = jtag_vpi_execute_queue,
684 };
685
686 struct adapter_driver jtag_vpi_adapter_driver = {
687 .name = "jtag_vpi",
688 .transports = jtag_only,
689 .commands = jtag_vpi_command_handlers,
690
691 .init = jtag_vpi_init,
692 .quit = jtag_vpi_quit,
693
694 .jtag_ops = &jtag_vpi_interface,
695 };

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)