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_ARPA_INET_H
20 #include <arpa/inet.h>
21 #endif
22 
23 #ifndef _WIN32
24 #include <netinet/tcp.h>
25 #endif
26 
27 #define SERVER_ADDRESS "127.0.0.1"
28 #define SERVER_PORT 5555
29 
30 static uint16_t server_port = SERVER_PORT;
31 static char *server_address;
32 
33 static int sockfd;
34 static struct sockaddr_in serv_addr;
35 
36 static uint8_t *last_ir_buf;
37 static int last_ir_num_bits;
38 
39 static int write_sock(char *buf, size_t len)
40 {
41  if (!buf) {
42  LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
43  __func__, __FILE__, __LINE__);
44  return ERROR_FAIL;
45  }
46  if (write(sockfd, buf, len) != (ssize_t)len) {
47  LOG_ERROR("%s: %s, file %s, line %d", __func__,
48  strerror(errno), __FILE__, __LINE__);
49  return ERROR_FAIL;
50  }
51  return ERROR_OK;
52 }
53 
54 static int read_sock(char *buf, size_t len)
55 {
56  if (!buf) {
57  LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
58  __func__, __FILE__, __LINE__);
59  return ERROR_FAIL;
60  }
61  if (read(sockfd, buf, len) != (ssize_t)len) {
62  LOG_ERROR("%s: %s, file %s, line %d", __func__,
63  strerror(errno), __FILE__, __LINE__);
64  return ERROR_FAIL;
65  }
66  return ERROR_OK;
67 }
68 
74 static int jtag_dpi_reset(int trst, int srst)
75 {
76  char *buf = "reset\n";
77  int ret = ERROR_OK;
78 
79  LOG_DEBUG_IO("JTAG DRIVER DEBUG: reset trst: %i srst %i", trst, srst);
80 
81  if (trst == 1) {
82  /* reset the JTAG TAP controller */
83  ret = write_sock(buf, strlen(buf));
84  if (ret != ERROR_OK) {
85  LOG_ERROR("write_sock() fail, file %s, line %d",
86  __FILE__, __LINE__);
87  }
88  }
89 
90  if (srst == 1) {
91  /* System target reset not supported */
92  LOG_ERROR("DPI SRST not supported");
93  ret = ERROR_FAIL;
94  }
95 
96  return ret;
97 }
98 
107 static int jtag_dpi_scan(struct scan_command *cmd)
108 {
109  char buf[20];
110  uint8_t *data_buf;
111  int num_bits, bytes;
112  int ret = ERROR_OK;
113 
114  num_bits = jtag_build_buffer(cmd, &data_buf);
115  if (!data_buf) {
116  LOG_ERROR("jtag_build_buffer call failed, data_buf == NULL, "
117  "file %s, line %d", __FILE__, __LINE__);
118  return ERROR_FAIL;
119  }
120 
121  bytes = DIV_ROUND_UP(num_bits, 8);
122  if (cmd->ir_scan) {
123  free(last_ir_buf);
124  last_ir_buf = (uint8_t *)malloc(bytes * sizeof(uint8_t));
125  if (!last_ir_buf) {
126  LOG_ERROR("%s: malloc fail, file %s, line %d",
127  __func__, __FILE__, __LINE__);
128  ret = ERROR_FAIL;
129  goto out;
130  }
131  memcpy(last_ir_buf, data_buf, bytes);
132  last_ir_num_bits = num_bits;
133  }
134  snprintf(buf, sizeof(buf), "%s %d\n", cmd->ir_scan ? "ib" : "db", num_bits);
135  ret = write_sock(buf, strlen(buf));
136  if (ret != ERROR_OK) {
137  LOG_ERROR("write_sock() fail, file %s, line %d",
138  __FILE__, __LINE__);
139  goto out;
140  }
141  ret = write_sock((char *)data_buf, bytes);
142  if (ret != ERROR_OK) {
143  LOG_ERROR("write_sock() fail, file %s, line %d",
144  __FILE__, __LINE__);
145  goto out;
146  }
147  ret = read_sock((char *)data_buf, bytes);
148  if (ret != ERROR_OK) {
149  LOG_ERROR("read_sock() fail, file %s, line %d",
150  __FILE__, __LINE__);
151  goto out;
152  }
153 
154  ret = jtag_read_buffer(data_buf, cmd);
155  if (ret != ERROR_OK) {
156  LOG_ERROR("jtag_read_buffer() fail, file %s, line %d",
157  __FILE__, __LINE__);
158  goto out;
159  }
160 
161 out:
162  free(data_buf);
163  return ret;
164 }
165 
166 static int jtag_dpi_runtest(unsigned int num_cycles)
167 {
168  char buf[20];
169  uint8_t *data_buf = last_ir_buf, *read_scan;
170  int num_bits = last_ir_num_bits, bytes;
171  int ret = ERROR_OK;
172 
173  if (!data_buf) {
174  LOG_ERROR("%s: NULL 'data_buf' argument, file %s, line %d",
175  __func__, __FILE__, __LINE__);
176  return ERROR_FAIL;
177  }
178  if (num_bits <= 0) {
179  LOG_ERROR("%s: 'num_bits' invalid value, file %s, line %d",
180  __func__, __FILE__, __LINE__);
181  return ERROR_FAIL;
182  }
183 
184  bytes = DIV_ROUND_UP(num_bits, 8);
185  read_scan = (uint8_t *)malloc(bytes * sizeof(uint8_t));
186  if (!read_scan) {
187  LOG_ERROR("%s: malloc fail, file %s, line %d",
188  __func__, __FILE__, __LINE__);
189  return ERROR_FAIL;
190  }
191  snprintf(buf, sizeof(buf), "ib %d\n", num_bits);
192  while (num_cycles > 0) {
193  ret = write_sock(buf, strlen(buf));
194  if (ret != ERROR_OK) {
195  LOG_ERROR("write_sock() fail, file %s, line %d",
196  __FILE__, __LINE__);
197  goto out;
198  }
199  ret = write_sock((char *)data_buf, bytes);
200  if (ret != ERROR_OK) {
201  LOG_ERROR("write_sock() fail, file %s, line %d",
202  __FILE__, __LINE__);
203  goto out;
204  }
205  ret = read_sock((char *)read_scan, bytes);
206  if (ret != ERROR_OK) {
207  LOG_ERROR("read_sock() fail, file %s, line %d",
208  __FILE__, __LINE__);
209  goto out;
210  }
211 
212  num_cycles -= num_bits + 6;
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  sockfd = socket(AF_INET, SOCK_STREAM, 0);
270  if (sockfd < 0) {
271  LOG_ERROR("socket: %s, function %s, file %s, line %d",
272  strerror(errno), __func__, __FILE__, __LINE__);
273  return ERROR_FAIL;
274  }
275 
276  memset(&serv_addr, 0, sizeof(serv_addr));
277 
278  serv_addr.sin_family = AF_INET;
279  serv_addr.sin_port = htons(server_port);
280 
281  if (!server_address) {
282  server_address = strdup(SERVER_ADDRESS);
283  if (!server_address) {
284  LOG_ERROR("%s: strdup fail, file %s, line %d",
285  __func__, __FILE__, __LINE__);
286  return ERROR_FAIL;
287  }
288  }
289 
290  serv_addr.sin_addr.s_addr = inet_addr(server_address);
291 
292  if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
293  LOG_ERROR("inet_addr error occurred");
294  return ERROR_FAIL;
295  }
296 
297  if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
298  close(sockfd);
299  LOG_ERROR("Can't connect to %s : %" PRIu16, server_address, server_port);
300  return ERROR_FAIL;
301  }
302  if (serv_addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
303  /* This increases performance dramatically for local
304  * connections, which is the most likely arrangement
305  * for a DPI connection. */
306  int flag = 1;
307  setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
308  }
309 
310  LOG_INFO("Connection to %s : %" PRIu16 " succeed", server_address, server_port);
311 
312  return ERROR_OK;
313 }
314 
315 static int jtag_dpi_quit(void)
316 {
317  free(server_address);
319 
320  return close(sockfd);
321 }
322 
323 COMMAND_HANDLER(jtag_dpi_set_port)
324 {
325  if (CMD_ARGC > 1)
327  else if (CMD_ARGC == 0)
328  LOG_INFO("Using server port %" PRIu16, server_port);
329  else {
331  LOG_INFO("Set server port to %" PRIu16, server_port);
332  }
333 
334  return ERROR_OK;
335 }
336 
337 COMMAND_HANDLER(jtag_dpi_set_address)
338 {
339  if (CMD_ARGC > 1)
341  else if (CMD_ARGC == 0) {
342  if (!server_address) {
343  server_address = strdup(SERVER_ADDRESS);
344  if (!server_address) {
345  LOG_ERROR("%s: strdup fail, file %s, line %d",
346  __func__, __FILE__, __LINE__);
347  return ERROR_FAIL;
348  }
349  }
350  LOG_INFO("Using server address %s", server_address);
351  } else {
352  free(server_address);
353  server_address = strdup(CMD_ARGV[0]);
354  if (!server_address) {
355  LOG_ERROR("%s: strdup fail, file %s, line %d",
356  __func__, __FILE__, __LINE__);
357  return ERROR_FAIL;
358  }
359  LOG_INFO("Set server address to %s", server_address);
360  }
361 
362  return ERROR_OK;
363 }
364 
365 static const struct command_registration jtag_dpi_subcommand_handlers[] = {
366  {
367  .name = "set_port",
368  .handler = &jtag_dpi_set_port,
369  .mode = COMMAND_CONFIG,
370  .help = "set the port of the DPI server",
371  .usage = "[port]",
372  },
373  {
374  .name = "set_address",
375  .handler = &jtag_dpi_set_address,
376  .mode = COMMAND_CONFIG,
377  .help = "set the address of the DPI server",
378  .usage = "[address]",
379  },
381 };
382 
383 static const struct command_registration jtag_dpi_command_handlers[] = {
384  {
385  .name = "jtag_dpi",
386  .mode = COMMAND_ANY,
387  .help = "perform jtag_dpi management",
389  .usage = "",
390  },
392 };
393 
394 static struct jtag_interface jtag_dpi_interface = {
396  .execute_queue = jtag_dpi_execute_queue,
397 };
398 
400  .name = "jtag_dpi",
401  .transports = jtag_only,
402  .commands = jtag_dpi_command_handlers,
403  .init = jtag_dpi_init,
404  .quit = jtag_dpi_quit,
405  .reset = jtag_dpi_reset,
406  .jtag_ops = &jtag_dpi_interface,
407 };
const char *const jtag_only[]
Definition: adapter.c:27
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:156
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:402
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:151
#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:442
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:253
@ 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:187
void jtag_sleep(uint32_t us)
Definition: jtag/core.c:1062
@ TAP_RESET
Definition: jtag.h:56
static struct jtag_interface jtag_dpi_interface
Definition: jtag_dpi.c:394
static int jtag_dpi_runtest(unsigned int num_cycles)
Definition: jtag_dpi.c:166
static int jtag_dpi_reset(int trst, int srst)
jtag_dpi_reset - ask to reset the JTAG device
Definition: jtag_dpi.c:74
static int last_ir_num_bits
Definition: jtag_dpi.c:37
static const struct command_registration jtag_dpi_command_handlers[]
Definition: jtag_dpi.c:383
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:365
static uint8_t * last_ir_buf
Definition: jtag_dpi.c:36
static int write_sock(char *buf, size_t len)
Definition: jtag_dpi.c:39
static uint16_t server_port
Definition: jtag_dpi.c:30
COMMAND_HANDLER(jtag_dpi_set_port)
Definition: jtag_dpi.c:323
static int read_sock(char *buf, size_t len)
Definition: jtag_dpi.c:54
static int jtag_dpi_quit(void)
Definition: jtag_dpi.c:315
#define SERVER_ADDRESS
Definition: jtag_dpi.c:27
static int jtag_dpi_scan(struct scan_command *cmd)
jtag_dpi_scan - launches a DR-scan or IR-scan
Definition: jtag_dpi.c:107
#define SERVER_PORT
Definition: jtag_dpi.c:28
static struct sockaddr_in serv_addr
Definition: jtag_dpi.c:34
static int sockfd
Definition: jtag_dpi.c:33
static int jtag_dpi_init(void)
Definition: jtag_dpi.c:267
static char * server_address
Definition: jtag_dpi.c:31
struct adapter_driver jtag_dpi_adapter_driver
Definition: jtag_dpi.c:399
#define LOG_DEBUG_IO(expr ...)
Definition: log.h:101
#define ERROR_FAIL
Definition: log.h:170
#define LOG_ERROR(expr ...)
Definition: log.h:132
#define LOG_INFO(expr ...)
Definition: log.h:126
#define ERROR_OK
Definition: log.h:164
int flag
Definition: mips64.c:29
Represents a driver for a debugging interface.
Definition: interface.h:207
const char *const name
The name of the interface driver.
Definition: interface.h:209
const char * name
Definition: command.h:235
const char * usage
a string listing the options and arguments, required or optional
Definition: command.h:241
Represents a driver for a debugging interface.
Definition: interface.h:182
unsigned int supported
Bit vector listing capabilities exposed by this driver.
Definition: interface.h:186
The scan_command provide a means of encapsulating a set of scan_field structures that should be scann...
Definition: commands.h:35
#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