jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / jtag / drivers / bitq.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4 * Copyright (C) 2007 by Pavel Chromy *
5 * chromy@asix.cz *
6 ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <jtag/jtag.h>
13 #include "bitq.h"
14 #include <jtag/interface.h>
15
16 struct bitq_interface *bitq_interface; /* low level bit queue interface */
17
18 /* state of input queue */
19 struct bitq_state {
20 struct jtag_command *cmd; /* command currently processed */
21 int field_idx; /* index of field currently being processed */
22 int bit_pos; /* position of bit currently being processed */
23 int status; /* processing status */
24 };
25 static struct bitq_state bitq_in_state;
26
27 /*
28 * input queue processing does not use jtag_read_buffer() to avoid unnecessary overhead
29 * no parameters, makes use of stored state information
30 */
31 static void bitq_in_proc(void)
32 {
33 /* loop through the queue */
34 while (bitq_in_state.cmd) {
35 /* only JTAG_SCAN command may return data */
36 if (bitq_in_state.cmd->type == JTAG_SCAN) {
37 /* loop through the fields */
38 while (bitq_in_state.field_idx < bitq_in_state.cmd->cmd.scan->num_fields) {
39 struct scan_field *field;
40 field = &bitq_in_state.cmd->cmd.scan->fields[bitq_in_state.field_idx];
41 if (field->in_value) {
42 /* field scanning */
43 while (bitq_in_state.bit_pos < field->num_bits) {
44 /* index of byte being scanned */
45 int in_idx = bitq_in_state.bit_pos / 8;
46 /* mask of next bit to be scanned */
47 uint8_t in_mask = 1 << (bitq_in_state.bit_pos % 8);
48
49 int tdo = bitq_interface->in();
50 if (tdo < 0) {
51 LOG_DEBUG_IO("bitq in EOF");
52 return;
53 }
54 if (in_mask == 0x01)
55 field->in_value[in_idx] = 0;
56 if (tdo)
57 field->in_value[in_idx] |= in_mask;
58 bitq_in_state.bit_pos++;
59 }
60 }
61
62 bitq_in_state.field_idx++; /* advance to next field */
63 bitq_in_state.bit_pos = 0; /* start next field from the first bit */
64 }
65 }
66 bitq_in_state.cmd = bitq_in_state.cmd->next; /* advance to next command */
67 bitq_in_state.field_idx = 0; /* preselect first field */
68 }
69 }
70
71 static void bitq_io(int tms, int tdi, int tdo_req)
72 {
73 bitq_interface->out(tms, tdi, tdo_req);
74 /* check and process the input queue */
75 if (bitq_interface->in_rdy())
76 bitq_in_proc();
77 }
78
79 static void bitq_end_state(tap_state_t state)
80 {
81 if (!tap_is_state_stable(state)) {
82 LOG_ERROR("BUG: %i is not a valid end state", state);
83 exit(-1);
84 }
85 tap_set_end_state(state);
86 }
87
88 static void bitq_state_move(tap_state_t new_state)
89 {
90 int i = 0;
91 uint8_t tms_scan;
92
93 if (!tap_is_state_stable(tap_get_state()) || !tap_is_state_stable(new_state)) {
94 LOG_ERROR("TAP move from or to unstable state");
95 exit(-1);
96 }
97
98 tms_scan = tap_get_tms_path(tap_get_state(), new_state);
99 int tms_count = tap_get_tms_path_len(tap_get_state(), new_state);
100
101 for (i = 0; i < tms_count; i++) {
102 bitq_io(tms_scan & 1, 0, 0);
103 tms_scan >>= 1;
104 }
105
106 tap_set_state(new_state);
107 }
108
109 static void bitq_path_move(struct pathmove_command *cmd)
110 {
111 int i;
112
113 for (i = 0; i < cmd->num_states; i++) {
114 if (tap_state_transition(tap_get_state(), false) == cmd->path[i])
115 bitq_io(0, 0, 0);
116 else if (tap_state_transition(tap_get_state(), true) == cmd->path[i])
117 bitq_io(1, 0, 0);
118 else {
119 LOG_ERROR("BUG: %s -> %s isn't a valid TAP transition", tap_state_name(
120 tap_get_state()), tap_state_name(cmd->path[i]));
121 exit(-1);
122 }
123
124 tap_set_state(cmd->path[i]);
125 }
126
127 tap_set_end_state(tap_get_state());
128 }
129
130 static void bitq_runtest(int num_cycles)
131 {
132 int i;
133
134 /* only do a state_move when we're not already in IDLE */
135 if (tap_get_state() != TAP_IDLE)
136 bitq_state_move(TAP_IDLE);
137
138 /* execute num_cycles */
139 for (i = 0; i < num_cycles; i++)
140 bitq_io(0, 0, 0);
141
142 /* finish in end_state */
143 if (tap_get_state() != tap_get_end_state())
144 bitq_state_move(tap_get_end_state());
145 }
146
147 static void bitq_scan_field(struct scan_field *field, int do_pause)
148 {
149 int bit_cnt;
150 int tdo_req;
151
152 const uint8_t *out_ptr;
153 uint8_t out_mask;
154
155 if (field->in_value)
156 tdo_req = 1;
157 else
158 tdo_req = 0;
159
160 if (!field->out_value) {
161 /* just send zeros and request data from TDO */
162 for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--)
163 bitq_io(0, 0, tdo_req);
164
165 bitq_io(do_pause, 0, tdo_req);
166 } else {
167 /* send data, and optionally request TDO */
168 out_mask = 0x01;
169 out_ptr = field->out_value;
170 for (bit_cnt = field->num_bits; bit_cnt > 1; bit_cnt--) {
171 bitq_io(0, ((*out_ptr) & out_mask) != 0, tdo_req);
172 if (out_mask == 0x80) {
173 out_mask = 0x01;
174 out_ptr++;
175 } else
176 out_mask <<= 1;
177 }
178
179 bitq_io(do_pause, ((*out_ptr) & out_mask) != 0, tdo_req);
180 }
181
182 if (do_pause) {
183 bitq_io(0, 0, 0);
184 if (tap_get_state() == TAP_IRSHIFT)
185 tap_set_state(TAP_IRPAUSE);
186 else if (tap_get_state() == TAP_DRSHIFT)
187 tap_set_state(TAP_DRPAUSE);
188 }
189 }
190
191 static void bitq_scan(struct scan_command *cmd)
192 {
193 int i;
194
195 if (cmd->ir_scan)
196 bitq_state_move(TAP_IRSHIFT);
197 else
198 bitq_state_move(TAP_DRSHIFT);
199
200 for (i = 0; i < cmd->num_fields - 1; i++)
201 bitq_scan_field(&cmd->fields[i], 0);
202
203 bitq_scan_field(&cmd->fields[i], 1);
204 }
205
206 int bitq_execute_queue(struct jtag_command *cmd_queue)
207 {
208 struct jtag_command *cmd = cmd_queue; /* currently processed command */
209
210 bitq_in_state.cmd = cmd_queue;
211 bitq_in_state.field_idx = 0;
212 bitq_in_state.bit_pos = 0;
213 bitq_in_state.status = ERROR_OK;
214
215 while (cmd) {
216 switch (cmd->type) {
217 case JTAG_RESET:
218 LOG_DEBUG_IO("reset trst: %i srst %i", cmd->cmd.reset->trst, cmd->cmd.reset->srst);
219 if ((cmd->cmd.reset->trst == 1) ||
220 (cmd->cmd.reset->srst &&
221 (jtag_get_reset_config() & RESET_SRST_PULLS_TRST)))
222 tap_set_state(TAP_RESET);
223 bitq_interface->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst);
224 if (bitq_interface->in_rdy())
225 bitq_in_proc();
226 break;
227
228 case JTAG_RUNTEST:
229 LOG_DEBUG_IO("runtest %i cycles, end in %i", cmd->cmd.runtest->num_cycles, cmd->cmd.runtest->end_state);
230 bitq_end_state(cmd->cmd.runtest->end_state);
231 bitq_runtest(cmd->cmd.runtest->num_cycles);
232 break;
233
234 case JTAG_TLR_RESET:
235 LOG_DEBUG_IO("statemove end in %i", cmd->cmd.statemove->end_state);
236 bitq_end_state(cmd->cmd.statemove->end_state);
237 bitq_state_move(tap_get_end_state()); /* unconditional TAP move */
238 break;
239
240 case JTAG_PATHMOVE:
241 LOG_DEBUG_IO("pathmove: %i states, end in %i", cmd->cmd.pathmove->num_states,
242 cmd->cmd.pathmove->path[cmd->cmd.pathmove->num_states - 1]);
243 bitq_path_move(cmd->cmd.pathmove);
244 break;
245
246 case JTAG_SCAN:
247 LOG_DEBUG_IO("scan end in %i", cmd->cmd.scan->end_state);
248 LOG_DEBUG_IO("scan %s", cmd->cmd.scan->ir_scan ? "ir" : "dr");
249 bitq_end_state(cmd->cmd.scan->end_state);
250 bitq_scan(cmd->cmd.scan);
251 if (tap_get_state() != tap_get_end_state())
252 bitq_state_move(tap_get_end_state());
253 break;
254
255 case JTAG_SLEEP:
256 LOG_DEBUG_IO("sleep %" PRIu32, cmd->cmd.sleep->us);
257 bitq_interface->sleep(cmd->cmd.sleep->us);
258 if (bitq_interface->in_rdy())
259 bitq_in_proc();
260 break;
261
262 default:
263 LOG_ERROR("BUG: unknown JTAG command type encountered");
264 exit(-1);
265 }
266
267 cmd = cmd->next;
268 }
269
270 bitq_interface->flush();
271 bitq_in_proc();
272
273 if (bitq_in_state.cmd) {
274 LOG_ERROR("missing data from bitq interface");
275 return ERROR_JTAG_QUEUE_FAILED;
276 }
277 if (bitq_interface->in() >= 0) {
278 LOG_ERROR("extra data from bitq interface");
279 return ERROR_JTAG_QUEUE_FAILED;
280 }
281
282 return bitq_in_state.status;
283 }
284
285 void bitq_cleanup(void)
286 {
287 }

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)