4 * Copyright (C) 2013 Franck Jullien, <elec4fun@gmail.com>
6 * Copyright (C) 2019-2020, Ampere Computing LLC
8 * See file CREDITS for list of people who contributed to this
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.
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.
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/>.
29 #include <jtag/interface.h>
30 #ifdef HAVE_ARPA_INET_H
31 #include <arpa/inet.h>
35 #include <netinet/tcp.h>
38 #define SERVER_ADDRESS "127.0.0.1"
39 #define SERVER_PORT 5555
41 static uint16_t server_port = SERVER_PORT;
42 static char *server_address;
45 static struct sockaddr_in serv_addr;
47 static uint8_t *last_ir_buf;
48 static int last_ir_num_bits;
50 static int write_sock(char *buf, size_t len)
53 LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
54 __func__, __FILE__, __LINE__);
57 if (write(sockfd, buf, len) != (ssize_t)len) {
58 LOG_ERROR("%s: %s, file %s, line %d", __func__,
59 strerror(errno), __FILE__, __LINE__);
65 static int read_sock(char *buf, size_t len)
68 LOG_ERROR("%s: NULL 'buf' argument, file %s, line %d",
69 __func__, __FILE__, __LINE__);
72 if (read(sockfd, buf, len) != (ssize_t)len) {
73 LOG_ERROR("%s: %s, file %s, line %d", __func__,
74 strerror(errno), __FILE__, __LINE__);
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
85 static int jtag_dpi_reset(int trst, int srst)
87 char *buf = "reset\n";
90 LOG_DEBUG_IO("JTAG DRIVER DEBUG: reset trst: %i srst %i", trst, srst);
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",
102 /* System target reset not supported */
103 LOG_ERROR("DPI SRST not supported");
111 * jtag_dpi_scan - launches a DR-scan or IR-scan
112 * @param cmd the command to launch
114 * Launch a JTAG IR-scan or DR-scan
116 * Returns ERROR_OK if OK, ERROR_xxx if a read/write error occurred.
118 static int jtag_dpi_scan(struct scan_command *cmd)
125 num_bits = jtag_build_buffer(cmd, &data_buf);
126 if (data_buf == NULL) {
127 LOG_ERROR("jtag_build_buffer call failed, data_buf == NULL, "
128 "file %s, line %d", __FILE__, __LINE__);
132 bytes = DIV_ROUND_UP(num_bits, 8);
135 last_ir_buf = (uint8_t *)malloc(bytes * sizeof(uint8_t));
136 if (last_ir_buf == NULL) {
137 LOG_ERROR("%s: malloc fail, file %s, line %d",
138 __func__, __FILE__, __LINE__);
142 memcpy(last_ir_buf, data_buf, bytes);
143 last_ir_num_bits = num_bits;
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",
152 ret = write_sock((char *)data_buf, bytes);
153 if (ret != ERROR_OK) {
154 LOG_ERROR("write_sock() fail, file %s, line %d",
158 ret = read_sock((char *)data_buf, bytes);
159 if (ret != ERROR_OK) {
160 LOG_ERROR("read_sock() fail, file %s, line %d",
165 ret = jtag_read_buffer(data_buf, cmd);
166 if (ret != ERROR_OK) {
167 LOG_ERROR("jtag_read_buffer() fail, file %s, line %d",
177 static int jtag_dpi_runtest(int cycles)
180 uint8_t *data_buf = last_ir_buf, *read_scan;
181 int num_bits = last_ir_num_bits, bytes;
184 if (data_buf == NULL) {
185 LOG_ERROR("%s: NULL 'data_buf' argument, file %s, line %d",
186 __func__, __FILE__, __LINE__);
190 LOG_ERROR("%s: 'num_bits' invalid value, file %s, line %d",
191 __func__, __FILE__, __LINE__);
195 bytes = DIV_ROUND_UP(num_bits, 8);
196 read_scan = (uint8_t *)malloc(bytes * sizeof(uint8_t));
197 if (read_scan == NULL) {
198 LOG_ERROR("%s: malloc fail, file %s, line %d",
199 __func__, __FILE__, __LINE__);
202 snprintf(buf, sizeof(buf), "ib %d\n", num_bits);
204 ret = write_sock(buf, strlen(buf));
205 if (ret != ERROR_OK) {
206 LOG_ERROR("write_sock() fail, file %s, line %d",
210 ret = write_sock((char *)data_buf, bytes);
211 if (ret != ERROR_OK) {
212 LOG_ERROR("write_sock() fail, file %s, line %d",
216 ret = read_sock((char *)read_scan, bytes);
217 if (ret != ERROR_OK) {
218 LOG_ERROR("read_sock() fail, file %s, line %d",
223 cycles -= num_bits + 6;
231 static int jtag_dpi_stableclocks(int cycles)
233 return jtag_dpi_runtest(cycles);
236 static int jtag_dpi_execute_queue(void)
238 struct jtag_command *cmd;
241 for (cmd = jtag_command_queue; ret == ERROR_OK && cmd != NULL;
245 ret = jtag_dpi_runtest(cmd->cmd.runtest->num_cycles);
247 case JTAG_STABLECLOCKS:
248 ret = jtag_dpi_stableclocks(cmd->cmd.stableclocks->num_cycles);
251 /* Enter Test-Logic-Reset state by asserting TRST */
252 if (cmd->cmd.statemove->end_state == TAP_RESET)
253 jtag_dpi_reset(1, 0);
262 jtag_sleep(cmd->cmd.sleep->us);
265 ret = jtag_dpi_scan(cmd->cmd.scan);
268 LOG_ERROR("BUG: unknown JTAG command type 0x%X",
278 static int jtag_dpi_init(void)
280 sockfd = socket(AF_INET, SOCK_STREAM, 0);
282 LOG_ERROR("socket: %s, function %s, file %s, line %d",
283 strerror(errno), __func__, __FILE__, __LINE__);
287 memset(&serv_addr, 0, sizeof(serv_addr));
289 serv_addr.sin_family = AF_INET;
290 serv_addr.sin_port = htons(server_port);
292 if (server_address == NULL) {
293 server_address = strdup(SERVER_ADDRESS);
294 if (server_address == NULL) {
295 LOG_ERROR("%s: strdup fail, file %s, line %d",
296 __func__, __FILE__, __LINE__);
301 serv_addr.sin_addr.s_addr = inet_addr(server_address);
303 if (serv_addr.sin_addr.s_addr == INADDR_NONE) {
304 LOG_ERROR("inet_addr error occured");
308 if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
310 LOG_ERROR("Can't connect to %s : %" PRIu16, server_address, server_port);
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. */
318 setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
321 LOG_INFO("Connection to %s : %" PRIu16 " succeed", server_address, server_port);
326 static int jtag_dpi_quit(void)
328 free(server_address);
329 server_address = NULL;
331 return close(sockfd);
334 COMMAND_HANDLER(jtag_dpi_set_port)
337 return ERROR_COMMAND_SYNTAX_ERROR;
338 else if (CMD_ARGC == 0)
339 LOG_INFO("Using server port %" PRIu16, server_port);
341 COMMAND_PARSE_NUMBER(u16, CMD_ARGV[0], server_port);
342 LOG_INFO("Set server port to %" PRIu16, server_port);
348 COMMAND_HANDLER(jtag_dpi_set_address)
351 return ERROR_COMMAND_SYNTAX_ERROR;
352 else if (CMD_ARGC == 0) {
353 if (server_address == NULL) {
354 server_address = strdup(SERVER_ADDRESS);
355 if (server_address == NULL) {
356 LOG_ERROR("%s: strdup fail, file %s, line %d",
357 __func__, __FILE__, __LINE__);
361 LOG_INFO("Using server address %s", server_address);
363 free(server_address);
364 server_address = strdup(CMD_ARGV[0]);
365 if (server_address == NULL) {
366 LOG_ERROR("%s: strdup fail, file %s, line %d",
367 __func__, __FILE__, __LINE__);
370 LOG_INFO("Set server address to %s", server_address);
376 static const struct command_registration jtag_dpi_command_handlers[] = {
378 .name = "jtag_dpi_set_port",
379 .handler = &jtag_dpi_set_port,
380 .mode = COMMAND_CONFIG,
381 .help = "set the port of the DPI server",
385 .name = "jtag_dpi_set_address",
386 .handler = &jtag_dpi_set_address,
387 .mode = COMMAND_CONFIG,
388 .help = "set the address of the DPI server",
389 .usage = "[address]",
391 COMMAND_REGISTRATION_DONE
394 static struct jtag_interface jtag_dpi_interface = {
395 .supported = DEBUG_CAP_TMS_SEQ,
396 .execute_queue = jtag_dpi_execute_queue,
399 struct adapter_driver jtag_dpi_adapter_driver = {
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,