jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / jtag / drivers / jtag_dpi.c
1 /*
2 * JTAG to DPI driver
3 *
4 * Copyright (C) 2013 Franck Jullien, <elec4fun@gmail.com>
5 *
6 * Copyright (C) 2019-2020, Ampere Computing LLC
7 *
8 * See file CREDITS for list of people who contributed to this
9 * project.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #ifdef HAVE_CONFIG_H
26 #include "config.h"
27 #endif
28
29 #include <jtag/interface.h>
30 #ifdef HAVE_ARPA_INET_H
31 #include <arpa/inet.h>
32 #endif
33
34 #ifndef _WIN32
35 #include <netinet/tcp.h>
36 #endif
37
38 #define SERVER_ADDRESS "127.0.0.1"
39 #define SERVER_PORT 5555
40
41 static uint16_t server_port = SERVER_PORT;
42 static char *server_address;
43
44 static int sockfd;
45 static struct sockaddr_in serv_addr;
46
47 static uint8_t *last_ir_buf;
48 static int last_ir_num_bits;
49
50 static int write_sock(char *buf, size_t len)
51 {
52 if (!buf) {
53 LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
54 __func__, __FILE__, __LINE__);
55 return ERROR_FAIL;
56 }
57 if (write(sockfd, buf, len) != (ssize_t)len) {
58 LOG_ERROR("%s: %s, file %s, line %d", __func__,
59 strerror(errno), __FILE__, __LINE__);
60 return ERROR_FAIL;
61 }
62 return ERROR_OK;
63 }
64
65 static int read_sock(char *buf, size_t len)
66 {
67 if (!buf) {
68 LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
69 __func__, __FILE__, __LINE__);
70 return ERROR_FAIL;
71 }
72 if (read(sockfd, buf, len) != (ssize_t)len) {
73 LOG_ERROR("%s: %s, file %s, line %d", __func__,
74 strerror(errno), __FILE__, __LINE__);
75 return ERROR_FAIL;
76 }
77 return ERROR_OK;
78 }
79
80 /**
81 * jtag_dpi_reset - ask to reset the JTAG device
82 * @param trst 1 if TRST is to be asserted
83 * @param srst 1 if SRST is to be asserted
84 */
85 static int jtag_dpi_reset(int trst, int srst)
86 {
87 char *buf = "reset\n";
88 int ret = ERROR_OK;
89
90 LOG_DEBUG_IO("JTAG DRIVER DEBUG: reset trst: %i srst %i", trst, srst);
91
92 if (trst == 1) {
93 /* reset the JTAG TAP controller */
94 ret = write_sock(buf, strlen(buf));
95 if (ret != ERROR_OK) {
96 LOG_ERROR("write_sock() fail, file %s, line %d",
97 __FILE__, __LINE__);
98 }
99 }
100
101 if (srst == 1) {
102 /* System target reset not supported */
103 LOG_ERROR("DPI SRST not supported");
104 ret = ERROR_FAIL;
105 }
106
107 return ret;
108 }
109
110 /**
111 * jtag_dpi_scan - launches a DR-scan or IR-scan
112 * @param cmd the command to launch
113 *
114 * Launch a JTAG IR-scan or DR-scan
115 *
116 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occurred.
117 */
118 static int jtag_dpi_scan(struct scan_command *cmd)
119 {
120 char buf[20];
121 uint8_t *data_buf;
122 int num_bits, bytes;
123 int ret = ERROR_OK;
124
125 num_bits = jtag_build_buffer(cmd, &data_buf);
126 if (!data_buf) {
127 LOG_ERROR("jtag_build_buffer call failed, data_buf == NULL, "
128 "file %s, line %d", __FILE__, __LINE__);
129 return ERROR_FAIL;
130 }
131
132 bytes = DIV_ROUND_UP(num_bits, 8);
133 if (cmd->ir_scan) {
134 free(last_ir_buf);
135 last_ir_buf = (uint8_t *)malloc(bytes * sizeof(uint8_t));
136 if (!last_ir_buf) {
137 LOG_ERROR("%s: malloc fail, file %s, line %d",
138 __func__, __FILE__, __LINE__);
139 ret = ERROR_FAIL;
140 goto out;
141 }
142 memcpy(last_ir_buf, data_buf, bytes);
143 last_ir_num_bits = num_bits;
144 }
145 snprintf(buf, sizeof(buf), "%s %d\n", cmd->ir_scan ? "ib" : "db", num_bits);
146 ret = write_sock(buf, strlen(buf));
147 if (ret != ERROR_OK) {
148 LOG_ERROR("write_sock() fail, file %s, line %d",
149 __FILE__, __LINE__);
150 goto out;
151 }
152 ret = write_sock((char *)data_buf, bytes);
153 if (ret != ERROR_OK) {
154 LOG_ERROR("write_sock() fail, file %s, line %d",
155 __FILE__, __LINE__);
156 goto out;
157 }
158 ret = read_sock((char *)data_buf, bytes);
159 if (ret != ERROR_OK) {
160 LOG_ERROR("read_sock() fail, file %s, line %d",
161 __FILE__, __LINE__);
162 goto out;
163 }
164
165 ret = jtag_read_buffer(data_buf, cmd);
166 if (ret != ERROR_OK) {
167 LOG_ERROR("jtag_read_buffer() fail, file %s, line %d",
168 __FILE__, __LINE__);
169 goto out;
170 }
171
172 out:
173 free(data_buf);
174 return ret;
175 }
176
177 static int jtag_dpi_runtest(int cycles)
178 {
179 char buf[20];
180 uint8_t *data_buf = last_ir_buf, *read_scan;
181 int num_bits = last_ir_num_bits, bytes;
182 int ret = ERROR_OK;
183
184 if (!data_buf) {
185 LOG_ERROR("%s: NULL 'data_buf' argument, file %s, line %d",
186 __func__, __FILE__, __LINE__);
187 return ERROR_FAIL;
188 }
189 if (num_bits <= 0) {
190 LOG_ERROR("%s: 'num_bits' invalid value, file %s, line %d",
191 __func__, __FILE__, __LINE__);
192 return ERROR_FAIL;
193 }
194
195 bytes = DIV_ROUND_UP(num_bits, 8);
196 read_scan = (uint8_t *)malloc(bytes * sizeof(uint8_t));
197 if (!read_scan) {
198 LOG_ERROR("%s: malloc fail, file %s, line %d",
199 __func__, __FILE__, __LINE__);
200 return ERROR_FAIL;
201 }
202 snprintf(buf, sizeof(buf), "ib %d\n", num_bits);
203 while (cycles > 0) {
204 ret = write_sock(buf, strlen(buf));
205 if (ret != ERROR_OK) {
206 LOG_ERROR("write_sock() fail, file %s, line %d",
207 __FILE__, __LINE__);
208 goto out;
209 }
210 ret = write_sock((char *)data_buf, bytes);
211 if (ret != ERROR_OK) {
212 LOG_ERROR("write_sock() fail, file %s, line %d",
213 __FILE__, __LINE__);
214 goto out;
215 }
216 ret = read_sock((char *)read_scan, bytes);
217 if (ret != ERROR_OK) {
218 LOG_ERROR("read_sock() fail, file %s, line %d",
219 __FILE__, __LINE__);
220 goto out;
221 }
222
223 cycles -= num_bits + 6;
224 }
225
226 out:
227 free(read_scan);
228 return ret;
229 }
230
231 static int jtag_dpi_stableclocks(int cycles)
232 {
233 return jtag_dpi_runtest(cycles);
234 }
235
236 static int jtag_dpi_execute_queue(void)
237 {
238 struct jtag_command *cmd;
239 int ret = ERROR_OK;
240
241 for (cmd = jtag_command_queue; ret == ERROR_OK && cmd;
242 cmd = cmd->next) {
243 switch (cmd->type) {
244 case JTAG_RUNTEST:
245 ret = jtag_dpi_runtest(cmd->cmd.runtest->num_cycles);
246 break;
247 case JTAG_STABLECLOCKS:
248 ret = jtag_dpi_stableclocks(cmd->cmd.stableclocks->num_cycles);
249 break;
250 case JTAG_TLR_RESET:
251 /* Enter Test-Logic-Reset state by asserting TRST */
252 if (cmd->cmd.statemove->end_state == TAP_RESET)
253 jtag_dpi_reset(1, 0);
254 break;
255 case JTAG_PATHMOVE:
256 /* unsupported */
257 break;
258 case JTAG_TMS:
259 /* unsupported */
260 break;
261 case JTAG_SLEEP:
262 jtag_sleep(cmd->cmd.sleep->us);
263 break;
264 case JTAG_SCAN:
265 ret = jtag_dpi_scan(cmd->cmd.scan);
266 break;
267 default:
268 LOG_ERROR("BUG: unknown JTAG command type 0x%X",
269 cmd->type);
270 ret = ERROR_FAIL;
271 break;
272 }
273 }
274
275 return ret;
276 }
277
278 static int jtag_dpi_init(void)
279 {
280 sockfd = socket(AF_INET, SOCK_STREAM, 0);
281 if (sockfd < 0) {
282 LOG_ERROR("socket: %s, function %s, file %s, line %d",
283 strerror(errno), __func__, __FILE__, __LINE__);
284 return ERROR_FAIL;
285 }
286
287 memset(&serv_addr, 0, sizeof(serv_addr));
288
289 serv_addr.sin_family = AF_INET;
290 serv_addr.sin_port = htons(server_port);
291
292 if (!server_address) {
293 server_address = strdup(SERVER_ADDRESS);
294 if (!server_address) {
295 LOG_ERROR("%s: strdup fail, file %s, line %d",
296 __func__, __FILE__, __LINE__);
297 return ERROR_FAIL;
298 }
299 }
300
301 serv_addr.sin_addr.s_addr = inet_addr(server_address);
302
303 if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
304 LOG_ERROR("inet_addr error occurred");
305 return ERROR_FAIL;
306 }
307
308 if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
309 close(sockfd);
310 LOG_ERROR("Can't connect to %s : %" PRIu16, server_address, server_port);
311 return ERROR_FAIL;
312 }
313 if (serv_addr.sin_addr.s_addr == htonl(INADDR_LOOPBACK)) {
314 /* This increases performance dramatically for local
315 * connections, which is the most likely arrangement
316 * for a DPI connection. */
317 int flag = 1;
318 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
319 }
320
321 LOG_INFO("Connection to %s : %" PRIu16 " succeed", server_address, server_port);
322
323 return ERROR_OK;
324 }
325
326 static int jtag_dpi_quit(void)
327 {
328 free(server_address);
329 server_address = NULL;
330
331 return close(sockfd);
332 }
333
334 COMMAND_HANDLER(jtag_dpi_set_port)
335 {
336 if (CMD_ARGC > 1)
337 return ERROR_COMMAND_SYNTAX_ERROR;
338 else if (CMD_ARGC == 0)
339 LOG_INFO("Using server port %" PRIu16, server_port);
340 else {
341 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], server_port);
342 LOG_INFO("Set server port to %" PRIu16, server_port);
343 }
344
345 return ERROR_OK;
346 }
347
348 COMMAND_HANDLER(jtag_dpi_set_address)
349 {
350 if (CMD_ARGC > 1)
351 return ERROR_COMMAND_SYNTAX_ERROR;
352 else if (CMD_ARGC == 0) {
353 if (!server_address) {
354 server_address = strdup(SERVER_ADDRESS);
355 if (!server_address) {
356 LOG_ERROR("%s: strdup fail, file %s, line %d",
357 __func__, __FILE__, __LINE__);
358 return ERROR_FAIL;
359 }
360 }
361 LOG_INFO("Using server address %s", server_address);
362 } else {
363 free(server_address);
364 server_address = strdup(CMD_ARGV[0]);
365 if (!server_address) {
366 LOG_ERROR("%s: strdup fail, file %s, line %d",
367 __func__, __FILE__, __LINE__);
368 return ERROR_FAIL;
369 }
370 LOG_INFO("Set server address to %s", server_address);
371 }
372
373 return ERROR_OK;
374 }
375
376 static const struct command_registration jtag_dpi_subcommand_handlers[] = {
377 {
378 .name = "set_port",
379 .handler = &jtag_dpi_set_port,
380 .mode = COMMAND_CONFIG,
381 .help = "set the port of the DPI server",
382 .usage = "[port]",
383 },
384 {
385 .name = "set_address",
386 .handler = &jtag_dpi_set_address,
387 .mode = COMMAND_CONFIG,
388 .help = "set the address of the DPI server",
389 .usage = "[address]",
390 },
391 COMMAND_REGISTRATION_DONE
392 };
393
394 static const struct command_registration jtag_dpi_command_handlers[] = {
395 {
396 .name = "jtag_dpi",
397 .mode = COMMAND_ANY,
398 .help = "perform jtag_dpi management",
399 .chain = jtag_dpi_subcommand_handlers,
400 .usage = "",
401 },
402 COMMAND_REGISTRATION_DONE
403 };
404
405 static struct jtag_interface jtag_dpi_interface = {
406 .supported = DEBUG_CAP_TMS_SEQ,
407 .execute_queue = jtag_dpi_execute_queue,
408 };
409
410 struct adapter_driver jtag_dpi_adapter_driver = {
411 .name = "jtag_dpi",
412 .transports = jtag_only,
413 .commands = jtag_dpi_command_handlers,
414 .init = jtag_dpi_init,
415 .quit = jtag_dpi_quit,
416 .reset = jtag_dpi_reset,
417 .jtag_ops = &jtag_dpi_interface,
418 };

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)