OpenOCD
jtag_dpi.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /*
4  * JTAG to DPI driver
5  *
6  * Copyright (C) 2013 Franck Jullien, <elec4fun@gmail.com>
7  *
8  * Copyright (C) 2019-2020, Ampere Computing LLC
9  *
10  * See file CREDITS for list of people who contributed to this
11  * project.
12  */
13 
14 #ifdef HAVE_CONFIG_H
15 #include "config.h"
16 #endif
17 
18 #include <jtag/interface.h>
19 #ifdef HAVE_NETDB_H
20 #include <netdb.h>
21 #endif
22 #ifdef HAVE_ARPA_INET_H
23 #include <arpa/inet.h>
24 #endif
25 
26 #ifndef _WIN32
27 #include <netinet/tcp.h>
28 #endif
29 
30 #define SERVER_ADDRESS "127.0.0.1"
31 #define SERVER_PORT 5555
32 
33 static uint16_t server_port = SERVER_PORT;
34 static char *server_address;
35 
36 static int sockfd;
37 
38 static uint8_t *last_ir_buf;
39 static int last_ir_num_bits;
40 
41 static int write_sock(char *buf, size_t len)
42 {
43  if (!buf) {
44  LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
45  __func__, __FILE__, __LINE__);
46  return ERROR_FAIL;
47  }
48  if (write(sockfd, buf, len) != (ssize_t)len) {
49  LOG_ERROR("%s: %s, file %s, line %d", __func__,
50  strerror(errno), __FILE__, __LINE__);
51  return ERROR_FAIL;
52  }
53  return ERROR_OK;
54 }
55 
56 static int read_sock(char *buf, size_t len)
57 {
58  if (!buf) {
59  LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
60  __func__, __FILE__, __LINE__);
61  return ERROR_FAIL;
62  }
63  if (read(sockfd, buf, len) != (ssize_t)len) {
64  LOG_ERROR("%s: %s, file %s, line %d", __func__,
65  strerror(errno), __FILE__, __LINE__);
66  return ERROR_FAIL;
67  }
68  return ERROR_OK;
69 }
70 
76 static int jtag_dpi_reset(int trst, int srst)
77 {
78  char *buf = "reset\n";
79  int ret = ERROR_OK;
80 
81  LOG_DEBUG_IO("JTAG DRIVER DEBUG: reset trst: %i srst %i", trst, srst);
82 
83  if (trst == 1) {
84  /* reset the JTAG TAP controller */
85  ret = write_sock(buf, strlen(buf));
86  if (ret != ERROR_OK) {
87  LOG_ERROR("write_sock() fail, file %s, line %d",
88  __FILE__, __LINE__);
89  }
90  }
91 
92  if (srst == 1) {
93  /* System target reset not supported */
94  LOG_ERROR("DPI SRST not supported");
95  ret = ERROR_FAIL;
96  }
97 
98  return ret;
99 }
100 
109 static int jtag_dpi_scan(struct scan_command *cmd)
110 {
111  char buf[20];
112  uint8_t *data_buf;
113  int num_bits, bytes;
114  int ret = ERROR_OK;
115 
116  num_bits = jtag_build_buffer(cmd, &data_buf);
117  if (!data_buf) {
118  LOG_ERROR("jtag_build_buffer call failed, data_buf == NULL, "
119  "file %s, line %d", __FILE__, __LINE__);
120  return ERROR_FAIL;
121  }
122 
123  bytes = DIV_ROUND_UP(num_bits, 8);
124  if (cmd->ir_scan) {
125  free(last_ir_buf);
126  last_ir_buf = (uint8_t *)malloc(bytes * sizeof(uint8_t));
127  if (!last_ir_buf) {
128  LOG_ERROR("%s: malloc fail, file %s, line %d",
129  __func__, __FILE__, __LINE__);
130  ret = ERROR_FAIL;
131  goto out;
132  }
133  memcpy(last_ir_buf, data_buf, bytes);
134  last_ir_num_bits = num_bits;
135  }
136  snprintf(buf, sizeof(buf), "%s %d\n", cmd->ir_scan ? "ib" : "db", num_bits);
137  ret = write_sock(buf, strlen(buf));
138  if (ret != ERROR_OK) {
139  LOG_ERROR("write_sock() fail, file %s, line %d",
140  __FILE__, __LINE__);
141  goto out;
142  }
143  ret = write_sock((char *)data_buf, bytes);
144  if (ret != ERROR_OK) {
145  LOG_ERROR("write_sock() fail, file %s, line %d",
146  __FILE__, __LINE__);
147  goto out;
148  }
149  ret = read_sock((char *)data_buf, bytes);
150  if (ret != ERROR_OK) {
151  LOG_ERROR("read_sock() fail, file %s, line %d",
152  __FILE__, __LINE__);
153  goto out;
154  }
155 
156  ret = jtag_read_buffer(data_buf, cmd);
157  if (ret != ERROR_OK) {
158  LOG_ERROR("jtag_read_buffer() fail, file %s, line %d",
159  __FILE__, __LINE__);
160  goto out;
161  }
162 
163 out:
164  free(data_buf);
165  return ret;
166 }
167 
168 static int jtag_dpi_runtest(unsigned int num_cycles)
169 {
170  char buf[20];
171  uint8_t *data_buf = last_ir_buf, *read_scan;
172  int num_bits = last_ir_num_bits, bytes;
173  int ret = ERROR_OK;
174 
175  if (!data_buf) {
176  LOG_ERROR("%s: NULL 'data_buf' argument, file %s, line %d",
177  __func__, __FILE__, __LINE__);
178  return ERROR_FAIL;
179  }
180  if (num_bits <= 0) {
181  LOG_ERROR("%s: 'num_bits' invalid value, file %s, line %d",
182  __func__, __FILE__, __LINE__);
183  return ERROR_FAIL;
184  }
185 
186  bytes = DIV_ROUND_UP(num_bits, 8);
187  read_scan = (uint8_t *)malloc(bytes * sizeof(uint8_t));
188  if (!read_scan) {
189  LOG_ERROR("%s: malloc fail, file %s, line %d",
190  __func__, __FILE__, __LINE__);
191  return ERROR_FAIL;
192  }
193  snprintf(buf, sizeof(buf), "ib %d\n", num_bits);
194  for (unsigned int cycle = 0; cycle < num_cycles; cycle += num_bits + 6) {
195  ret = write_sock(buf, strlen(buf));
196  if (ret != ERROR_OK) {
197  LOG_ERROR("write_sock() fail, file %s, line %d",
198  __FILE__, __LINE__);
199  goto out;
200  }
201  ret = write_sock((char *)data_buf, bytes);
202  if (ret != ERROR_OK) {
203  LOG_ERROR("write_sock() fail, file %s, line %d",
204  __FILE__, __LINE__);
205  goto out;
206  }
207  ret = read_sock((char *)read_scan, bytes);
208  if (ret != ERROR_OK) {
209  LOG_ERROR("read_sock() fail, file %s, line %d",
210  __FILE__, __LINE__);
211  goto out;
212  }
213  }
214 
215 out:
216  free(read_scan);
217  return ret;
218 }
219 
220 static int jtag_dpi_stableclocks(unsigned int num_cycles)
221 {
222  return jtag_dpi_runtest(num_cycles);
223 }
224 
225 static int jtag_dpi_execute_queue(struct jtag_command *cmd_queue)
226 {
227  struct jtag_command *cmd;
228  int ret = ERROR_OK;
229 
230  for (cmd = cmd_queue; ret == ERROR_OK && cmd;
231  cmd = cmd->next) {
232  switch (cmd->type) {
233  case JTAG_RUNTEST:
234  ret = jtag_dpi_runtest(cmd->cmd.runtest->num_cycles);
235  break;
236  case JTAG_STABLECLOCKS:
237  ret = jtag_dpi_stableclocks(cmd->cmd.stableclocks->num_cycles);
238  break;
239  case JTAG_TLR_RESET:
240  /* Enter Test-Logic-Reset state by asserting TRST */
241  if (cmd->cmd.statemove->end_state == TAP_RESET)
242  jtag_dpi_reset(1, 0);
243  break;
244  case JTAG_PATHMOVE:
245  /* unsupported */
246  break;
247  case JTAG_TMS:
248  /* unsupported */
249  break;
250  case JTAG_SLEEP:
251  jtag_sleep(cmd->cmd.sleep->us);
252  break;
253  case JTAG_SCAN:
254  ret = jtag_dpi_scan(cmd->cmd.scan);
255  break;
256  default:
257  LOG_ERROR("BUG: unknown JTAG command type 0x%X",
258  cmd->type);
259  ret = ERROR_FAIL;
260  break;
261  }
262  }
263 
264  return ret;
265 }
266 
267 static int jtag_dpi_init(void)
268 {
269  if (!server_address) {
270  server_address = strdup(SERVER_ADDRESS);
271  if (!server_address) {
272  LOG_ERROR("%s: strdup fail, file %s, line %d",
273  __func__, __FILE__, __LINE__);
274  return ERROR_FAIL;
275  }
276  }
277 
278  const struct addrinfo hints = {
279  .ai_family = AF_UNSPEC,
280  .ai_socktype = SOCK_STREAM
281  };
282 
283  char port_str[5 + 1];
284  snprintf(port_str, sizeof(port_str), "%" PRIu16, server_port);
285 
286  struct addrinfo *result;
287  int ret = getaddrinfo(server_address, port_str, &hints, &result);
288 
289  if (ret != 0) {
290  LOG_ERROR("getaddrinfo: %s", gai_strerror(ret));
291  return ERROR_FAIL;
292  }
293 
294  struct addrinfo *rp;
295  for (rp = result; rp ; rp = rp->ai_next) {
296  sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
297  if (sockfd == -1)
298  continue;
299 
300  if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) != -1)
301  break;
302 
303  close(sockfd);
304  }
305 
306  if (!rp) {
307  LOG_ERROR("Can't connect to %s : %" PRIu16, server_address,
308  server_port);
309  freeaddrinfo(result);
310  return ERROR_FAIL;
311  }
312 
313  bool is_loopback = false;
314  if (rp->ai_family == AF_INET) {
315  struct sockaddr_in sa;
316  memcpy(&sa, rp->ai_addr, sizeof(sa));
317  is_loopback = (sa.sin_addr.s_addr == htonl(INADDR_LOOPBACK));
318  } else if (rp->ai_family == AF_INET6) {
319  struct sockaddr_in6 sa;
320  memcpy(&sa, rp->ai_addr, sizeof(sa));
321  is_loopback = IN6_IS_ADDR_LOOPBACK(&sa.sin6_addr);
322  }
323 
324  if (is_loopback) {
325  LOG_DEBUG("Enabling TCP_NODELAY to enhance the speed of local connections");
326 
327  /* This increases performance dramatically for local
328  * connections, which is the most likely arrangement
329  * for a DPI connection. */
330  int flag = 1;
331  setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag,
332  sizeof(int));
333  }
334 
335  freeaddrinfo(result);
336 
337  LOG_INFO("Connection to %s : %" PRIu16 " succeed", server_address, server_port);
338 
339  return ERROR_OK;
340 }
341 
342 static int jtag_dpi_quit(void)
343 {
344  free(server_address);
346 
347  return close(sockfd);
348 }
349 
350 COMMAND_HANDLER(jtag_dpi_set_port)
351 {
352  if (CMD_ARGC > 1)
354  else if (CMD_ARGC == 0)
355  LOG_INFO("Using server port %" PRIu16, server_port);
356  else {
358  LOG_INFO("Set server port to %" PRIu16, server_port);
359  }
360 
361  return ERROR_OK;
362 }
363 
364 COMMAND_HANDLER(jtag_dpi_set_address)
365 {
366  if (CMD_ARGC > 1)
368  else if (CMD_ARGC == 0) {
369  if (!server_address) {
370  server_address = strdup(SERVER_ADDRESS);
371  if (!server_address) {
372  LOG_ERROR("%s: strdup fail, file %s, line %d",
373  __func__, __FILE__, __LINE__);
374  return ERROR_FAIL;
375  }
376  }
377  LOG_INFO("Using server address %s", server_address);
378  } else {
379  free(server_address);
380  server_address = strdup(CMD_ARGV[0]);
381  if (!server_address) {
382  LOG_ERROR("%s: strdup fail, file %s, line %d",
383  __func__, __FILE__, __LINE__);
384  return ERROR_FAIL;
385  }
386  LOG_INFO("Set server address to %s", server_address);
387  }
388 
389  return ERROR_OK;
390 }
391 
392 static const struct command_registration jtag_dpi_subcommand_handlers[] = {
393  {
394  .name = "set_port",
395  .handler = &jtag_dpi_set_port,
396  .mode = COMMAND_CONFIG,
397  .help = "set the port of the DPI server",
398  .usage = "[port]",
399  },
400  {
401  .name = "set_address",
402  .handler = &jtag_dpi_set_address,
403  .mode = COMMAND_CONFIG,
404  .help = "set the hostname or IP address of the DPI server",
405  .usage = "[address]",
406  },
408 };
409 
410 static const struct command_registration jtag_dpi_command_handlers[] = {
411  {
412  .name = "jtag_dpi",
413  .mode = COMMAND_ANY,
414  .help = "perform jtag_dpi management",
416  .usage = "",
417  },
419 };
420 
421 static struct jtag_interface jtag_dpi_interface = {
423  .execute_queue = jtag_dpi_execute_queue,
424 };
425 
427  .name = "jtag_dpi",
428  .transport_ids = TRANSPORT_JTAG,
429  .transport_preferred_id = TRANSPORT_JTAG,
430  .commands = jtag_dpi_command_handlers,
431  .init = jtag_dpi_init,
432  .quit = jtag_dpi_quit,
433  .reset = jtag_dpi_reset,
434  .jtag_ops = &jtag_dpi_interface,
435 };
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:161
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:405
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:156
#define COMMAND_PARSE_NUMBER(type, in, out)
parses the string in into out as a type, or prints a command error and passes the error code to the c...
Definition: command.h:445
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:256
@ COMMAND_CONFIG
Definition: command.h:41
@ COMMAND_ANY
Definition: command.h:42
int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer)
Definition: commands.c:192
int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd)
Definition: commands.c:230
@ JTAG_TLR_RESET
Definition: commands.h:137
@ JTAG_SCAN
Definition: commands.h:129
@ JTAG_PATHMOVE
Definition: commands.h:140
@ JTAG_STABLECLOCKS
Definition: commands.h:142
@ JTAG_RUNTEST
Definition: commands.h:138
@ JTAG_SLEEP
Definition: commands.h:141
@ JTAG_TMS
Definition: commands.h:143
#define DEBUG_CAP_TMS_SEQ
Definition: interface.h:188
void jtag_sleep(uint32_t us)
Definition: jtag/core.c:1070
@ TAP_RESET
Definition: jtag.h:56
static struct jtag_interface jtag_dpi_interface
Definition: jtag_dpi.c:421
static int jtag_dpi_runtest(unsigned int num_cycles)
Definition: jtag_dpi.c:168
static int jtag_dpi_reset(int trst, int srst)
jtag_dpi_reset - ask to reset the JTAG device
Definition: jtag_dpi.c:76
static int last_ir_num_bits
Definition: jtag_dpi.c:39
static const struct command_registration jtag_dpi_command_handlers[]
Definition: jtag_dpi.c:410
static int jtag_dpi_stableclocks(unsigned int num_cycles)
Definition: jtag_dpi.c:220
static int jtag_dpi_execute_queue(struct jtag_command *cmd_queue)
Definition: jtag_dpi.c:225
static const struct command_registration jtag_dpi_subcommand_handlers[]
Definition: jtag_dpi.c:392
static uint8_t * last_ir_buf
Definition: jtag_dpi.c:38
static int write_sock(char *buf, size_t len)
Definition: jtag_dpi.c:41
static uint16_t server_port
Definition: jtag_dpi.c:33
COMMAND_HANDLER(jtag_dpi_set_port)
Definition: jtag_dpi.c:350
static int read_sock(char *buf, size_t len)
Definition: jtag_dpi.c:56
static int jtag_dpi_quit(void)
Definition: jtag_dpi.c:342
#define SERVER_ADDRESS
Definition: jtag_dpi.c:30
static int jtag_dpi_scan(struct scan_command *cmd)
jtag_dpi_scan - launches a DR-scan or IR-scan
Definition: jtag_dpi.c:109
#define SERVER_PORT
Definition: jtag_dpi.c:31
static int sockfd
Definition: jtag_dpi.c:36
static int jtag_dpi_init(void)
Definition: jtag_dpi.c:267
static char * server_address
Definition: jtag_dpi.c:34
struct adapter_driver jtag_dpi_adapter_driver
Definition: jtag_dpi.c:426
#define LOG_DEBUG_IO(expr ...)
Definition: log.h:116
#define ERROR_FAIL
Definition: log.h:188
#define LOG_ERROR(expr ...)
Definition: log.h:147
#define LOG_INFO(expr ...)
Definition: log.h:141
#define LOG_DEBUG(expr ...)
Definition: log.h:124
#define ERROR_OK
Definition: log.h:182
int flag
Definition: mips64.c:29
Represents a driver for a debugging interface.
Definition: interface.h:208
const char *const name
The name of the interface driver.
Definition: interface.h:210
const char * name
Definition: command.h:239
const char * usage
a string listing the options and arguments, required or optional
Definition: command.h:244
Represents a driver for a debugging interface.
Definition: interface.h:183
unsigned int supported
Bit vector listing capabilities exposed by this driver.
Definition: interface.h:187
The scan_command provide a means of encapsulating a set of scan_field structures that should be scann...
Definition: commands.h:35
#define TRANSPORT_JTAG
Definition: transport.h:19
#define DIV_ROUND_UP(m, n)
Rounds m up to the nearest multiple of n using division.
Definition: types.h:79
#define NULL
Definition: usb.h:16
uint8_t cmd
Definition: vdebug.c:1