jtag_command_t -> struct jtag_command
[openocd.git] / src / jtag / commands.c
1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2007,2008 Øyvind Harboe *
6 * oyvind.harboe@zylin.com *
7 * *
8 * Copyright (C) 2009 SoftPLC Corporation *
9 * http://softplc.com *
10 * dick@softplc.com *
11 * *
12 * Copyright (C) 2009 Zachary T Welch *
13 * zw@superlucidity.net *
14 * *
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. *
19 * *
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. *
24 * *
25 * You should have received a copy of the GNU General Public License *
26 * along with this program; if not, write to the *
27 * Free Software Foundation, Inc., *
28 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
29 ***************************************************************************/
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include "commands.h"
35
36 struct cmd_queue_page {
37 void *address;
38 size_t used;
39 struct cmd_queue_page *next;
40 };
41
42 #define CMD_QUEUE_PAGE_SIZE (1024 * 1024)
43 static struct cmd_queue_page *cmd_queue_pages = NULL;
44
45 struct jtag_command *jtag_command_queue = NULL;
46 static struct jtag_command **next_command_pointer = &jtag_command_queue;
47
48 void jtag_queue_command(struct jtag_command * cmd)
49 {
50 // this command goes on the end, so ensure the queue terminates
51 cmd->next = NULL;
52
53 struct jtag_command **last_cmd = next_command_pointer;
54 assert(NULL != last_cmd);
55 assert(NULL == *last_cmd);
56 *last_cmd = cmd;
57
58 // store location where the next command pointer will be stored
59 next_command_pointer = &cmd->next;
60 }
61
62 void* cmd_queue_alloc(size_t size)
63 {
64 struct cmd_queue_page **p_page = &cmd_queue_pages;
65 int offset;
66 uint8_t *t;
67
68 /*
69 * WARNING:
70 * We align/round the *SIZE* per below
71 * so that all pointers returned by
72 * this function are reasonably well
73 * aligned.
74 *
75 * If we did not, then an "odd-length" request would cause the
76 * *next* allocation to be at an *odd* address, and because
77 * this function has the same type of api as malloc() - we
78 * must also return pointers that have the same type of
79 * alignment.
80 *
81 * What I do not/have is a reasonable portable means
82 * to align by...
83 *
84 * The solution here, is based on these suggestions.
85 * http://gcc.gnu.org/ml/gcc-help/2008-12/msg00041.html
86 *
87 */
88 union worse_case_align {
89 int i;
90 long l;
91 float f;
92 void *v;
93 };
94 #define ALIGN_SIZE (sizeof(union worse_case_align))
95
96 /* The alignment process. */
97 size = (size + ALIGN_SIZE -1) & (~(ALIGN_SIZE-1));
98 /* Done... */
99
100 if (*p_page)
101 {
102 while ((*p_page)->next)
103 p_page = &((*p_page)->next);
104 if (CMD_QUEUE_PAGE_SIZE - (*p_page)->used < size)
105 p_page = &((*p_page)->next);
106 }
107
108 if (!*p_page)
109 {
110 *p_page = malloc(sizeof(struct cmd_queue_page));
111 (*p_page)->used = 0;
112 (*p_page)->address = malloc(CMD_QUEUE_PAGE_SIZE);
113 (*p_page)->next = NULL;
114 }
115
116 offset = (*p_page)->used;
117 (*p_page)->used += size;
118
119 t = (uint8_t *)((*p_page)->address);
120 return t + offset;
121 }
122
123 void cmd_queue_free(void)
124 {
125 struct cmd_queue_page *page = cmd_queue_pages;
126
127 while (page)
128 {
129 struct cmd_queue_page *last = page;
130 free(page->address);
131 page = page->next;
132 free(last);
133 }
134
135 cmd_queue_pages = NULL;
136 }
137
138 void jtag_command_queue_reset(void)
139 {
140 cmd_queue_free();
141
142 jtag_command_queue = NULL;
143 next_command_pointer = &jtag_command_queue;
144 }
145
146 enum scan_type jtag_scan_type(const struct scan_command *cmd)
147 {
148 int i;
149 int type = 0;
150
151 for (i = 0; i < cmd->num_fields; i++)
152 {
153 if (cmd->fields[i].in_value)
154 type |= SCAN_IN;
155 if (cmd->fields[i].out_value)
156 type |= SCAN_OUT;
157 }
158
159 return type;
160 }
161
162 int jtag_scan_size(const struct scan_command *cmd)
163 {
164 int bit_count = 0;
165 int i;
166
167 /* count bits in scan command */
168 for (i = 0; i < cmd->num_fields; i++)
169 {
170 bit_count += cmd->fields[i].num_bits;
171 }
172
173 return bit_count;
174 }
175
176 int jtag_build_buffer(const struct scan_command *cmd, uint8_t **buffer)
177 {
178 int bit_count = 0;
179 int i;
180
181 bit_count = jtag_scan_size(cmd);
182 *buffer = calloc(1,CEIL(bit_count, 8));
183
184 bit_count = 0;
185
186 DEBUG_JTAG_IO("%s num_fields: %i",
187 cmd->ir_scan ? "IRSCAN" : "DRSCAN",
188 cmd->num_fields);
189
190 for (i = 0; i < cmd->num_fields; i++)
191 {
192 if (cmd->fields[i].out_value)
193 {
194 #ifdef _DEBUG_JTAG_IO_
195 char *char_buf = buf_to_str(cmd->fields[i].out_value,
196 (cmd->fields[i].num_bits > DEBUG_JTAG_IOZ)
197 ? DEBUG_JTAG_IOZ
198 : cmd->fields[i].num_bits, 16);
199
200 LOG_DEBUG("fields[%i].out_value[%i]: 0x%s", i,
201 cmd->fields[i].num_bits, char_buf);
202 free(char_buf);
203 #endif
204 buf_set_buf(cmd->fields[i].out_value, 0, *buffer,
205 bit_count, cmd->fields[i].num_bits);
206 }
207 else
208 {
209 DEBUG_JTAG_IO("fields[%i].out_value[%i]: NULL",
210 i, cmd->fields[i].num_bits);
211 }
212
213 bit_count += cmd->fields[i].num_bits;
214 }
215
216 //DEBUG_JTAG_IO("bit_count totalling: %i", bit_count);
217
218 return bit_count;
219 }
220
221 int jtag_read_buffer(uint8_t *buffer, const struct scan_command *cmd)
222 {
223 int i;
224 int bit_count = 0;
225 int retval;
226
227 /* we return ERROR_OK, unless a check fails, or a handler reports a problem */
228 retval = ERROR_OK;
229
230 for (i = 0; i < cmd->num_fields; i++)
231 {
232 /* if neither in_value nor in_handler
233 * are specified we don't have to examine this field
234 */
235 if (cmd->fields[i].in_value)
236 {
237 int num_bits = cmd->fields[i].num_bits;
238 uint8_t *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits);
239
240 #ifdef _DEBUG_JTAG_IO_
241 char *char_buf = buf_to_str(captured,
242 (num_bits > DEBUG_JTAG_IOZ)
243 ? DEBUG_JTAG_IOZ
244 : num_bits, 16);
245
246 LOG_DEBUG("fields[%i].in_value[%i]: 0x%s",
247 i, num_bits, char_buf);
248 free(char_buf);
249 #endif
250
251 if (cmd->fields[i].in_value)
252 {
253 buf_cpy(captured, cmd->fields[i].in_value, num_bits);
254 }
255
256 free(captured);
257 }
258 bit_count += cmd->fields[i].num_bits;
259 }
260
261 return retval;
262 }
263
264

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)