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, &params[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