1 /*
2 * $Id$
3 *
4 * Copyright (C) 2003 ETC s.r.o.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 * 02111-1307, USA.
20 *
21 * Written by Marcel Telka <marcel@telka.sk>, 2003.
22 *
23 */
24
25 #include <sysdep.h>
26
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include <urjtag/cable.h>
31 #include <urjtag/part.h>
32 #include <urjtag/part_instruction.h>
33 #include <urjtag/tap_state.h>
34 #include <urjtag/tap.h>
35 #include <urjtag/data_register.h>
36 #include <urjtag/cmd.h>
37 #include <urjtag/bsdl.h>
38
39 #include <urjtag/chain.h>
40
41 urj_chain_t *
urj_tap_chain_alloc(void)42 urj_tap_chain_alloc (void)
43 {
44 urj_chain_t *chain = malloc (sizeof (urj_chain_t));
45 if (!chain)
46 {
47 urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails",
48 sizeof (urj_chain_t));
49 return NULL;
50 }
51
52 chain->cable = NULL;
53 chain->parts = NULL;
54 chain->total_instr_len = 0;
55 chain->active_part = 0;
56 URJ_BSDL_GLOBS_INIT (chain->bsdl);
57 urj_tap_state_init (chain);
58
59 return chain;
60 }
61
62 void
urj_tap_chain_free(urj_chain_t * chain)63 urj_tap_chain_free (urj_chain_t *chain)
64 {
65 if (!chain)
66 return;
67
68 urj_tap_chain_disconnect (chain);
69
70 urj_part_parts_free (chain->parts);
71 free (chain);
72 }
73
74 int
urj_tap_chain_connect(urj_chain_t * chain,const char * drivername,char * params[])75 urj_tap_chain_connect (urj_chain_t *chain, const char *drivername, char *params[])
76 {
77 urj_cable_t *cable;
78 int j, paramc;
79 const urj_param_t **cable_params;
80 const urj_cable_driver_t *driver;
81
82 urj_cable_parport_devtype_t devtype;
83 const char *devname;
84 int param_start;
85
86 param_start = 0;
87 paramc = urj_cmd_params (params);
88
89 driver = urj_tap_cable_find (drivername);
90 if (!driver)
91 {
92 urj_error_set (URJ_ERROR_INVALID,
93 "unknown cable driver '%s'", drivername);
94 return URJ_STATUS_FAIL;
95 }
96
97 if (driver->device_type == URJ_CABLE_DEVICE_PARPORT)
98 {
99 if (paramc < 2)
100 {
101 urj_error_set (URJ_ERROR_SYNTAX,
102 "parallel cable requires >= 4 parameters, got %d", paramc);
103 return URJ_STATUS_FAIL;
104 }
105 for (j = 0; j < URJ_CABLE_PARPORT_N_DEVS; j++)
106 if (strcasecmp (params[0],
107 urj_cable_parport_devtype_string (j)) == 0)
108 break;
109 if (j == URJ_CABLE_PARPORT_N_DEVS)
110 {
111 urj_error_set (URJ_ERROR_INVALID,
112 "unknown parallel port device type '%s'",
113 params[0]);
114 return URJ_STATUS_FAIL;
115 }
116
117 devtype = j;
118 devname = params[1];
119 param_start = 2;
120 }
121 else
122 {
123 /* Silence gcc uninitialized warnings */
124 devtype = -1;
125 devname = NULL;
126 }
127
128 if (urj_param_init_list (&cable_params, ¶ms[param_start],
129 &urj_cable_param_list) != URJ_STATUS_OK)
130 return URJ_STATUS_FAIL;
131
132 switch (driver->device_type)
133 {
134 case URJ_CABLE_DEVICE_PARPORT:
135 cable = urj_tap_cable_parport_connect (chain, driver, devtype, devname,
136 cable_params);
137 break;
138 case URJ_CABLE_DEVICE_USB:
139 cable = urj_tap_cable_usb_connect (chain, driver, cable_params);
140 break;
141 case URJ_CABLE_DEVICE_OTHER:
142 cable = urj_tap_cable_other_connect (chain, driver, cable_params);
143 break;
144 default:
145 cable = NULL;
146 break;
147 }
148
149 urj_param_clear (&cable_params);
150
151 if (cable == NULL)
152 return URJ_STATUS_FAIL;
153
154 chain->cable->chain = chain;
155 return URJ_STATUS_OK;
156 }
157
158 void
urj_tap_chain_disconnect(urj_chain_t * chain)159 urj_tap_chain_disconnect (urj_chain_t *chain)
160 {
161 if (!chain->cable)
162 return;
163
164 urj_tap_state_done (chain);
165 urj_tap_cable_done (chain->cable);
166 urj_tap_cable_free (chain->cable);
167 chain->cable = NULL;
168 }
169
170 int
urj_tap_chain_clock(urj_chain_t * chain,int tms,int tdi,int n)171 urj_tap_chain_clock (urj_chain_t *chain, int tms, int tdi, int n)
172 {
173 int i;
174
175 if (!chain || !chain->cable)
176 {
177 urj_error_set (URJ_ERROR_NO_CHAIN, "no chain or no part");
178 return URJ_STATUS_FAIL;
179 }
180
181 urj_tap_cable_clock (chain->cable, tms, tdi, n);
182
183 for (i = 0; i < n; i++)
184 urj_tap_state_clock (chain, tms);
185
186 return URJ_STATUS_OK;
187 }
188
189 int
urj_tap_chain_defer_clock(urj_chain_t * chain,int tms,int tdi,int n)190 urj_tap_chain_defer_clock (urj_chain_t *chain, int tms, int tdi, int n)
191 {
192 int i;
193
194 if (!chain || !chain->cable)
195 {
196 urj_error_set (URJ_ERROR_NO_CHAIN, "no chain or no part");
197 return URJ_STATUS_FAIL;
198 }
199
200 urj_tap_cable_defer_clock (chain->cable, tms, tdi, n);
201
202 for (i = 0; i < n; i++)
203 urj_tap_state_clock (chain, tms);
204
205 return URJ_STATUS_OK;
206 }
207
208 int
urj_tap_chain_set_trst(urj_chain_t * chain,int trst)209 urj_tap_chain_set_trst (urj_chain_t *chain, int trst)
210 {
211 int old_val = urj_tap_cable_set_signal (chain->cable, URJ_POD_CS_TRST,
212 trst ? URJ_POD_CS_TRST : 0);
213 int old_trst = (old_val & URJ_POD_CS_TRST) ? 1 : 0;
214
215 urj_tap_state_set_trst (chain, old_trst, trst);
216
217 return trst;
218 }
219
220 int
urj_tap_chain_get_trst(urj_chain_t * chain)221 urj_tap_chain_get_trst (urj_chain_t *chain)
222 {
223 return urj_tap_cable_get_signal (chain->cable, URJ_POD_CS_TRST);
224 }
225
226 int
urj_tap_chain_set_pod_signal(urj_chain_t * chain,int mask,int val)227 urj_tap_chain_set_pod_signal (urj_chain_t *chain, int mask, int val)
228 {
229 int old_val = urj_tap_cable_set_signal (chain->cable, mask, val);
230 int old_trst = (old_val & URJ_POD_CS_TRST) ? 1 : 0;
231 int new_trst =
232 (((old_val & ~mask) | (val & mask)) & URJ_POD_CS_TRST) ? 1 : 0;
233
234 urj_tap_state_set_trst (chain, old_trst, new_trst);
235
236 return old_val;
237 }
238
239 int
urj_tap_chain_get_pod_signal(urj_chain_t * chain,urj_pod_sigsel_t sig)240 urj_tap_chain_get_pod_signal (urj_chain_t *chain, urj_pod_sigsel_t sig)
241 {
242 return urj_tap_cable_get_signal (chain->cable, sig);
243 }
244
245 int
urj_tap_chain_shift_instructions_mode(urj_chain_t * chain,int capture_output,int capture,int chain_exit)246 urj_tap_chain_shift_instructions_mode (urj_chain_t *chain,
247 int capture_output, int capture,
248 int chain_exit)
249 {
250 int i;
251 urj_parts_t *ps;
252
253 if (!chain || !chain->parts)
254 {
255 urj_error_set (URJ_ERROR_NO_CHAIN, "no chain or no part");
256 return URJ_STATUS_FAIL;
257 }
258
259 ps = chain->parts;
260
261 for (i = 0; i < ps->len; i++)
262 {
263 if (ps->parts[i]->active_instruction == NULL)
264 {
265 urj_error_set (URJ_ERROR_NO_ACTIVE_INSTRUCTION,
266 _("Part %d without active instruction"), i);
267 return URJ_STATUS_FAIL;
268 }
269 }
270
271 if (capture)
272 urj_tap_capture_ir (chain);
273
274 /* new implementation: split into defer + retrieve part
275 shift the data register of each part in the chain one by one */
276
277 for (i = 0; i < ps->len; i++)
278 {
279 urj_tap_defer_shift_register (chain,
280 ps->parts[i]->active_instruction->value,
281 capture_output ? ps->parts[i]->active_instruction->out
282 : NULL,
283 (i + 1) == ps->len ? chain_exit : URJ_CHAIN_EXITMODE_SHIFT);
284 }
285
286 if (capture_output)
287 {
288 for (i = 0; i < ps->len; i++)
289 {
290 urj_tap_shift_register_output (chain,
291 ps->parts[i]->active_instruction->value,
292 ps->parts[i]->active_instruction->out,
293 (i + 1) == ps->len ? chain_exit
294 : URJ_CHAIN_EXITMODE_SHIFT);
295 }
296 }
297 else
298 {
299 /* give the cable driver a chance to flush if it's considered useful */
300 urj_tap_cable_flush (chain->cable, URJ_TAP_CABLE_TO_OUTPUT);
301 }
302
303 return URJ_STATUS_OK;
304 }
305
306 int
urj_tap_chain_shift_instructions(urj_chain_t * chain)307 urj_tap_chain_shift_instructions (urj_chain_t *chain)
308 {
309 return urj_tap_chain_shift_instructions_mode (chain, 0, 1,
310 URJ_CHAIN_EXITMODE_IDLE);
311 }
312
313 int
urj_tap_chain_shift_data_registers_mode(urj_chain_t * chain,int capture_output,int capture,int chain_exit)314 urj_tap_chain_shift_data_registers_mode (urj_chain_t *chain,
315 int capture_output, int capture,
316 int chain_exit)
317 {
318 int i;
319 urj_parts_t *ps;
320
321 if (!chain || !chain->parts)
322 {
323 urj_error_set (URJ_ERROR_NO_CHAIN, "no chain or no part");
324 return URJ_STATUS_FAIL;
325 }
326
327 ps = chain->parts;
328
329 for (i = 0; i < ps->len; i++)
330 {
331 if (ps->parts[i]->active_instruction == NULL)
332 {
333 urj_error_set (URJ_ERROR_NO_ACTIVE_INSTRUCTION,
334 _("Part %d without active instruction"), i);
335 return URJ_STATUS_FAIL;
336 }
337 if (ps->parts[i]->active_instruction->data_register == NULL)
338 {
339 urj_error_set (URJ_ERROR_NO_DATA_REGISTER,
340 _("Part %d without data register"), i);
341 return URJ_STATUS_FAIL;
342 }
343 }
344
345 if (capture)
346 urj_tap_capture_dr (chain);
347
348 /* new implementation: split into defer + retrieve part
349 shift the data register of each part in the chain one by one */
350
351 for (i = 0; i < ps->len; i++)
352 {
353 urj_tap_defer_shift_register (chain,
354 ps->parts[i]->active_instruction->data_register->in,
355 capture_output ?
356 ps->parts[i]->active_instruction->data_register->out
357 : NULL,
358 (i + 1) == ps->len ? chain_exit : URJ_CHAIN_EXITMODE_SHIFT);
359 }
360
361 if (capture_output)
362 {
363 for (i = 0; i < ps->len; i++)
364 {
365 urj_tap_shift_register_output (chain,
366 ps->parts[i]->active_instruction->data_register->in,
367 ps->parts[i]->active_instruction->data_register->out,
368 (i + 1) == ps->len ? chain_exit : URJ_CHAIN_EXITMODE_SHIFT);
369 }
370 }
371 else
372 {
373 /* give the cable driver a chance to flush if it's considered useful */
374 urj_tap_cable_flush (chain->cable, URJ_TAP_CABLE_TO_OUTPUT);
375 }
376
377 return URJ_STATUS_OK;
378 }
379
380 int
urj_tap_chain_shift_data_registers(urj_chain_t * chain,int capture_output)381 urj_tap_chain_shift_data_registers (urj_chain_t *chain, int capture_output)
382 {
383 return urj_tap_chain_shift_data_registers_mode (chain, capture_output, 1,
384 URJ_CHAIN_EXITMODE_IDLE);
385 }
386
387 void
urj_tap_chain_flush(urj_chain_t * chain)388 urj_tap_chain_flush (urj_chain_t *chain)
389 {
390 if (chain->cable != NULL)
391 urj_tap_cable_flush (chain->cable, URJ_TAP_CABLE_COMPLETELY);
392 }
393
394 urj_part_t *
urj_tap_chain_active_part(urj_chain_t * chain)395 urj_tap_chain_active_part (urj_chain_t *chain)
396 {
397 if (chain == NULL)
398 {
399 urj_error_set (URJ_ERROR_NO_CHAIN, "no JTAG chain");
400 return NULL;
401 }
402
403 if (!chain->parts)
404 {
405 urj_error_set (URJ_ERROR_NOTFOUND, _("Run \"detect\" first"));
406 return NULL;
407 }
408 if (chain->active_part >= chain->parts->len)
409 {
410 urj_error_set (URJ_ERROR_ILLEGAL_STATE,
411 _("active part no %d exceeds chain length %d"),
412 chain->active_part, chain->parts->len);
413 return NULL;
414 }
415
416 return chain->parts->parts[chain->active_part];
417 }
418
419 void
urj_tap_chain_wait_ready(urj_chain_t * chain)420 urj_tap_chain_wait_ready (urj_chain_t *chain)
421 {
422 urj_part_t *part;
423
424 if (!chain || !chain->parts)
425 return;
426
427 part = chain->parts->parts[chain->main_part];
428 if (part->params && part->params->wait_ready)
429 part->params->wait_ready (chain);
430 }
431
432