1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2007,2008 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
8 * Copyright (C) 2009 SoftPLC Corporation *
12 * Copyright (C) 2009 Zachary T Welch *
13 * zw@superlucidity.net *
15 * This program is free software; you can redistribute it and/or modify *
16 * it under the terms of the GNU General Public License as published by *
17 * the Free Software Foundation; either version 2 of the License, or *
18 * (at your option) any later version. *
20 * This program is distributed in the hope that it will be useful, *
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
23 * GNU General Public License for more details. *
25 * You should have received a copy of the GNU General Public License *
26 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
27 ***************************************************************************/
33 #include <jtag/jtag.h>
34 #include <transport/transport.h>
37 struct cmd_queue_page {
38 struct cmd_queue_page *next;
43 #define CMD_QUEUE_PAGE_SIZE (1024 * 1024)
44 static struct cmd_queue_page *cmd_queue_pages;
45 static struct cmd_queue_page *cmd_queue_pages_tail;
47 struct jtag_command *jtag_command_queue;
48 static struct jtag_command **next_command_pointer = &jtag_command_queue;
50 void jtag_queue_command(struct jtag_command *cmd)
52 if (!transport_is_jtag()) {
54 * FIXME: This should not happen!
55 * There could be old code that queues jtag commands with non jtag interfaces so, for
56 * the moment simply highlight it by log an error.
57 * We should fix it quitting with assert(0) because it is an internal error, or returning
58 * an error after call to jtag_command_queue_reset() to free the jtag queue and avoid
60 * The fix can be applied immediately after next release (v0.11.0 ?)
62 LOG_ERROR("JTAG API jtag_queue_command() called on non JTAG interface");
65 /* this command goes on the end, so ensure the queue terminates */
68 struct jtag_command **last_cmd = next_command_pointer;
73 /* store location where the next command pointer will be stored */
74 next_command_pointer = &cmd->next;
77 void *cmd_queue_alloc(size_t size)
79 struct cmd_queue_page **p_page = &cmd_queue_pages;
85 * We align/round the *SIZE* per below
86 * so that all pointers returned by
87 * this function are reasonably well
90 * If we did not, then an "odd-length" request would cause the
91 * *next* allocation to be at an *odd* address, and because
92 * this function has the same type of api as malloc() - we
93 * must also return pointers that have the same type of
96 * What I do not/have is a reasonable portable means
99 * The solution here, is based on these suggestions.
100 * http://gcc.gnu.org/ml/gcc-help/2008-12/msg00041.html
103 union worse_case_align {
109 #define ALIGN_SIZE (sizeof(union worse_case_align))
111 /* The alignment process. */
112 size = (size + ALIGN_SIZE - 1) & (~(ALIGN_SIZE - 1));
116 p_page = &cmd_queue_pages_tail;
117 if (CMD_QUEUE_PAGE_SIZE - (*p_page)->used < size)
118 p_page = &((*p_page)->next);
122 *p_page = malloc(sizeof(struct cmd_queue_page));
124 size_t alloc_size = (size < CMD_QUEUE_PAGE_SIZE) ?
125 CMD_QUEUE_PAGE_SIZE : size;
126 (*p_page)->address = malloc(alloc_size);
127 (*p_page)->next = NULL;
128 cmd_queue_pages_tail = *p_page;
131 offset = (*p_page)->used;
132 (*p_page)->used += size;
134 t = (*p_page)->address;
138 static void cmd_queue_free(void)
140 struct cmd_queue_page *page = cmd_queue_pages;
143 struct cmd_queue_page *last = page;
149 cmd_queue_pages = NULL;
150 cmd_queue_pages_tail = NULL;
153 void jtag_command_queue_reset(void)
157 jtag_command_queue = NULL;
158 next_command_pointer = &jtag_command_queue;
162 * Copy a struct scan_field for insertion into the queue.
164 * This allocates a new copy of out_value using cmd_queue_alloc.
166 void jtag_scan_field_clone(struct scan_field *dst, const struct scan_field *src)
168 dst->num_bits = src->num_bits;
169 dst->out_value = buf_cpy(src->out_value, cmd_queue_alloc(DIV_ROUND_UP(src->num_bits, 8)), src->num_bits);
170 dst->in_value = src->in_value;
173 enum scan_type jtag_scan_type(const struct scan_command *cmd)
178 for (i = 0; i < cmd->num_fields; i++) {
179 if (cmd->fields[i].in_value)
181 if (cmd->fields[i].out_value)
188 int jtag_scan_size(const struct scan_command *cmd)
193 /* count bits in scan command */
194 for (i = 0; i < cmd->num_fields; i++)
195 bit_count += cmd->fields[i].num_bits;
200 int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer)
205 bit_count = jtag_scan_size(cmd);
206 *buffer = calloc(1, DIV_ROUND_UP(bit_count, 8));
210 LOG_DEBUG_IO("%s num_fields: %i",
211 cmd->ir_scan ? "IRSCAN" : "DRSCAN",
214 for (i = 0; i < cmd->num_fields; i++) {
215 if (cmd->fields[i].out_value) {
216 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
217 char *char_buf = buf_to_hex_str(cmd->fields[i].out_value,
218 (cmd->fields[i].num_bits > DEBUG_JTAG_IOZ)
220 : cmd->fields[i].num_bits);
222 LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i,
223 cmd->fields[i].num_bits, char_buf);
226 buf_set_buf(cmd->fields[i].out_value, 0, *buffer,
227 bit_count, cmd->fields[i].num_bits);
229 LOG_DEBUG_IO("fields[%i].out_value[%i]: NULL",
230 i, cmd->fields[i].num_bits);
233 bit_count += cmd->fields[i].num_bits;
236 /*LOG_DEBUG_IO("bit_count totalling: %i", bit_count); */
241 int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd)
247 /* we return ERROR_OK, unless a check fails, or a handler reports a problem */
250 for (i = 0; i < cmd->num_fields; i++) {
251 /* if neither in_value nor in_handler
252 * are specified we don't have to examine this field
254 if (cmd->fields[i].in_value) {
255 int num_bits = cmd->fields[i].num_bits;
256 uint8_t *captured = buf_set_buf(buffer, bit_count,
257 malloc(DIV_ROUND_UP(num_bits, 8)), 0, num_bits);
259 if (LOG_LEVEL_IS(LOG_LVL_DEBUG_IO)) {
260 char *char_buf = buf_to_hex_str(captured,
261 (num_bits > DEBUG_JTAG_IOZ)
265 LOG_DEBUG("fields[%i].in_value[%i]: 0x%s",
266 i, num_bits, char_buf);
270 if (cmd->fields[i].in_value)
271 buf_cpy(captured, cmd->fields[i].in_value, num_bits);
275 bit_count += cmd->fields[i].num_bits;