1 /*
2  * $Id$
3  *
4  * Copyright (C) 2002 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>, 2002.
22  *
23  */
24 
25 #include <sysdep.h>
26 
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #include <urjtag/error.h>
31 #include <urjtag/part.h>
32 #include <urjtag/bssignal.h>
33 #include <urjtag/tap_register.h>
34 #include <urjtag/part_instruction.h>
35 #include <urjtag/data_register.h>
36 #include <urjtag/bsbit.h>
37 
38 urj_part_init_t *urj_part_inits = NULL;
39 
40 /* part */
41 
42 urj_part_t *
urj_part_alloc(const urj_tap_register_t * id)43 urj_part_alloc (const urj_tap_register_t *id)
44 {
45     urj_part_t *p = malloc (sizeof *p);
46     if (!p)
47     {
48         urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails", sizeof *p);
49         return NULL;
50     }
51 
52     p->alias = NULL;            /* djf */
53     /* @@@@ RFHH check result */
54     p->id = urj_tap_register_duplicate (id);
55     p->manufacturer_name[0] = '\0';
56     p->part_name[0] = '\0';
57     p->stepping[0] = '\0';
58     p->signals = NULL;
59     p->saliases = NULL;
60     p->instruction_length = 0;
61     p->instructions = NULL;
62     p->active_instruction = NULL;
63     p->data_registers = NULL;
64     p->boundary_length = 0;
65     p->bsbits = NULL;
66     p->params = NULL;
67 
68     return p;
69 }
70 
71 void
urj_part_free(urj_part_t * p)72 urj_part_free (urj_part_t *p)
73 {
74     int i;
75 
76     if (!p)
77         return;
78 
79     /* id */
80     free (p->id);
81 
82     if (p->alias)
83         free (p->alias);        /* djf */
84 
85     /* signals */
86     while (p->signals)
87     {
88         urj_part_signal_t *s = p->signals;
89         p->signals = s->next;
90         urj_part_signal_free (s);
91     }
92 
93     /* saliases */
94     while (p->saliases)
95     {
96         urj_part_salias_t *sa = p->saliases;
97         p->saliases = sa->next;
98         urj_part_salias_free (sa);
99     }
100 
101     /* instructions */
102     while (p->instructions)
103     {
104         urj_part_instruction_t *i = p->instructions;
105         p->instructions = i->next;
106         urj_part_instruction_free (i);
107     }
108 
109     /* data registers */
110     while (p->data_registers)
111     {
112         urj_data_register_t *dr = p->data_registers;
113         p->data_registers = dr->next;
114         urj_part_data_register_free (dr);
115     }
116 
117     /* bsbits */
118     for (i = 0; i < p->boundary_length; i++)
119         urj_part_bsbit_free (p->bsbits[i]);
120     free (p->bsbits);
121 
122     if (p->params && p->params->free)
123         p->params->free (p->params->data);
124     free (p->params);
125 
126     free (p);
127 }
128 
129 urj_part_instruction_t *
urj_part_find_instruction(urj_part_t * p,const char * iname)130 urj_part_find_instruction (urj_part_t *p, const char *iname)
131 {
132     urj_part_instruction_t *i;
133 
134     if (!p || !iname)
135     {
136         urj_error_set (URJ_ERROR_INVALID, "NULL part or instruction name");
137         return NULL;
138     }
139 
140     i = p->instructions;
141     while (i)
142     {
143         if (strcasecmp (iname, i->name) == 0)
144             break;
145         i = i->next;
146     }
147 
148     return i;
149 }
150 
151 urj_data_register_t *
urj_part_find_data_register(urj_part_t * p,const char * drname)152 urj_part_find_data_register (urj_part_t *p, const char *drname)
153 {
154     urj_data_register_t *dr;
155 
156     if (!p || !drname)
157     {
158         urj_error_set (URJ_ERROR_INVALID, "NULL part or data register name");
159         return NULL;
160     }
161 
162     dr = p->data_registers;
163     while (dr)
164     {
165         if (strcasecmp (drname, dr->name) == 0)
166             break;
167         dr = dr->next;
168     }
169 
170     return dr;
171 }
172 
173 urj_part_signal_t *
urj_part_find_signal(urj_part_t * p,const char * signalname)174 urj_part_find_signal (urj_part_t *p, const char *signalname)
175 {
176     urj_part_signal_t *s;
177     urj_part_salias_t *sa;
178 
179     if (!p || !signalname)
180     {
181         urj_error_set (URJ_ERROR_INVALID, "NULL part or signal name");
182         return NULL;
183     }
184 
185     s = p->signals;
186     while (s)
187     {
188         if (strcasecmp (signalname, s->name) == 0)
189             return s;
190         s = s->next;
191     }
192 
193     sa = p->saliases;
194     while (sa)
195     {
196         if (strcasecmp (signalname, sa->name) == 0)
197             return sa->signal;
198         sa = sa->next;
199     }
200 
201     return NULL;
202 }
203 
204 void
urj_part_set_instruction(urj_part_t * p,const char * iname)205 urj_part_set_instruction (urj_part_t *p, const char *iname)
206 {
207     if (p)
208         p->active_instruction = urj_part_find_instruction (p, iname);
209 }
210 
211 int
urj_part_set_signal(urj_part_t * p,urj_part_signal_t * s,int out,int val)212 urj_part_set_signal (urj_part_t *p, urj_part_signal_t *s, int out, int val)
213 {
214     urj_data_register_t *bsr;
215 
216     if (!p || !s)
217     {
218         urj_error_set (URJ_ERROR_INVALID, "NULL part or signal");
219         return URJ_STATUS_FAIL;
220     }
221 
222     /* search for Boundary Scan Register */
223     bsr = urj_part_find_data_register (p, "BSR");
224     if (!bsr)
225     {
226         urj_error_set (URJ_ERROR_NOTFOUND,
227                        _("Boundary Scan Register (BSR) not found"));
228         return URJ_STATUS_FAIL;
229     }
230 
231     /* setup signal */
232     if (out)
233     {
234         int control;
235         if (!s->output)
236         {
237             urj_error_set (URJ_ERROR_INVALID,
238                            _("signal '%s' cannot be set as output"), s->name);
239             return URJ_STATUS_FAIL;
240         }
241         bsr->in->data[s->output->bit] = val & 1;
242 
243         control = p->bsbits[s->output->bit]->control;
244         if (control >= 0)
245             bsr->in->data[control] =
246                 p->bsbits[s->output->bit]->control_value ^ 1;
247     }
248     else
249     {
250         if (!s->input)
251         {
252             urj_error_set (URJ_ERROR_INVALID,
253                            _("signal '%s' cannot be set as input"), s->name);
254             return URJ_STATUS_FAIL;
255         }
256         if (s->output)
257             bsr->in->data[s->output->control] =
258                 p->bsbits[s->output->bit]->control_value;
259     }
260 
261     return URJ_STATUS_OK;
262 }
263 
264 int
urj_part_get_signal(urj_part_t * p,const urj_part_signal_t * s)265 urj_part_get_signal (urj_part_t *p, const urj_part_signal_t *s)
266 {
267     urj_data_register_t *bsr;
268 
269     if (!p || !s)
270     {
271         urj_error_set (URJ_ERROR_INVALID, "NULL part or signal");
272         return -1;
273     }
274 
275     /* search for Boundary Scan Register */
276     bsr = urj_part_find_data_register (p, "BSR");
277     if (!bsr)
278     {
279         urj_error_set (URJ_ERROR_NOTFOUND,
280                        _("Boundary Scan Register (BSR) not found"));
281         return -1;
282     }
283 
284     if (!s->input)
285     {
286         urj_error_set (URJ_ERROR_INVALID,
287                        _("signal '%s' is not input signal"), s->name);
288         return -1;
289     }
290 
291     return bsr->out->data[s->input->bit];
292 }
293 
294 int
urj_part_print(urj_log_level_t ll,urj_part_t * p)295 urj_part_print (urj_log_level_t ll, urj_part_t *p)
296 {
297     const char *instruction = NULL;
298     const char *dr = NULL;
299     char format[100];
300 
301     if (!p)
302     {
303         urj_error_set (URJ_ERROR_INVALID, "NULL part");
304         return URJ_STATUS_FAIL;
305     }
306 
307     snprintf (format, 100, _("%%-%ds %%-%ds %%-%ds %%-%ds %%-%ds\n"),
308               URJ_PART_MANUFACTURER_MAXLEN, URJ_PART_PART_MAXLEN,
309               URJ_PART_STEPPING_MAXLEN, URJ_INSTRUCTION_MAXLEN_INSTRUCTION,
310               URJ_DATA_REGISTER_MAXLEN);
311 
312     if (p->active_instruction)
313     {
314         instruction = p->active_instruction->name;
315         if (p->active_instruction->data_register != NULL)
316             dr = p->active_instruction->data_register->name;
317     }
318     if (instruction == NULL)
319         instruction = _("(none)");
320     if (dr == NULL)
321         dr = _("(none)");
322     urj_log (ll, format, p->manufacturer_name, p->part_name, p->stepping, instruction,
323              dr);
324 
325     return URJ_STATUS_OK;
326 }
327 
328 
329 int
urj_part_instruction_length_set(urj_part_t * part,int length)330 urj_part_instruction_length_set (urj_part_t *part, int length)
331 {
332     if (part->instructions != NULL)
333     {
334         urj_error_set (URJ_ERROR_ALREADY,
335                        _("instruction length is already set and used"));
336         return URJ_STATUS_FAIL;
337     }
338 
339     part->instruction_length = length;
340 
341     return URJ_STATUS_OK;
342 }
343 
344 
345 urj_part_instruction_t *
urj_part_instruction_define(urj_part_t * part,const char * instruction,const char * code,const char * data_register)346 urj_part_instruction_define (urj_part_t *part, const char *instruction,
347                              const char *code, const char *data_register)
348 {
349     urj_part_instruction_t *i;
350     urj_data_register_t *dr;
351 
352     if (strlen (code) != part->instruction_length)
353     {
354         urj_error_set (URJ_ERROR_INVALID,
355                        _("invalid instruction length"));
356         return NULL;
357     }
358 
359     if (urj_part_find_instruction (part, instruction) != NULL)
360     {
361         urj_error_set (URJ_ERROR_ALREADY,
362                        _("Instruction '%s' already defined"), instruction);
363         return NULL;
364     }
365 
366     dr = urj_part_find_data_register (part, data_register);
367     if (dr == NULL)
368     {
369         urj_error_set(URJ_ERROR_NOTFOUND,
370                       _("unknown data register '%s'"), data_register);
371         return NULL;
372     }
373 
374     i = urj_part_instruction_alloc (instruction, part->instruction_length,
375                                     code);
376     if (!i)
377     {
378         /* retain error state */
379         return NULL;
380     }
381 
382     i->next = part->instructions;
383     part->instructions = i;
384 
385     i->data_register = dr;
386 
387     return i;
388 }
389 
390 
391 /* parts */
392 
393 urj_parts_t *
urj_part_parts_alloc(void)394 urj_part_parts_alloc (void)
395 {
396     urj_parts_t *ps = malloc (sizeof *ps);
397     if (!ps)
398     {
399         urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "malloc(%zd) fails",
400                        sizeof *ps);
401         return NULL;
402     }
403 
404     ps->len = 0;
405     ps->parts = NULL;
406 
407     return ps;
408 }
409 
410 void
urj_part_parts_free(urj_parts_t * ps)411 urj_part_parts_free (urj_parts_t *ps)
412 {
413     int i;
414 
415     if (!ps)
416         return;
417 
418     for (i = 0; i < ps->len; i++)
419         urj_part_free (ps->parts[i]);
420 
421     free (ps->parts);
422     free (ps);
423 }
424 
425 int
urj_part_parts_add_part(urj_parts_t * ps,urj_part_t * p)426 urj_part_parts_add_part (urj_parts_t *ps, urj_part_t *p)
427 {
428     urj_part_t **np = realloc (ps->parts, (ps->len + 1) * sizeof *ps->parts);
429 
430     if (!np)
431     {
432         urj_error_set (URJ_ERROR_OUT_OF_MEMORY, "realloc(%s,%zd) fails",
433                        "ps->parts", (ps->len + 1) * sizeof *ps->parts);
434         return URJ_STATUS_FAIL;
435     }
436 
437     ps->parts = np;
438     ps->parts[ps->len++] = p;
439 
440     return URJ_STATUS_OK;
441 }
442 
443 int
urj_part_parts_set_instruction(urj_parts_t * ps,const char * iname)444 urj_part_parts_set_instruction (urj_parts_t *ps, const char *iname)
445 {
446     int i;
447 
448     if (!ps)
449     {
450         urj_error_set (URJ_ERROR_INVALID, "NULL parts");
451         return URJ_STATUS_FAIL;
452     }
453 
454     for (i = 0; i < ps->len; i++)
455         ps->parts[i]->active_instruction =
456             urj_part_find_instruction (ps->parts[i], iname);
457 
458     return URJ_STATUS_OK;
459 }
460 
461 int
urj_part_parts_print(urj_log_level_t ll,urj_parts_t * ps,int active_part)462 urj_part_parts_print (urj_log_level_t ll, urj_parts_t *ps, int active_part)
463 {
464     int i;
465 
466     if (!ps)
467     {
468         urj_error_set (URJ_ERROR_INVALID, "NULL parts");
469         return URJ_STATUS_FAIL;
470     }
471 
472     for (i = 0; i < ps->len; i++)
473     {
474         urj_part_t *p = ps->parts[i];
475 
476         if (!p)
477             continue;
478 
479         urj_log (ll, "%s%3d ", i == active_part ? "*" : " ", i);
480         urj_part_print (ll, p);
481     }
482 
483     return URJ_STATUS_OK;
484 }
485 
486 void
urj_part_init_register(char * part,urj_part_init_func_t init)487 urj_part_init_register (char *part, urj_part_init_func_t init)
488 {
489     urj_part_init_t *pi;
490 
491     pi = (urj_part_init_t *) malloc (sizeof (urj_part_init_t));
492     strncpy (pi->part, part, URJ_PART_PART_MAXLEN);
493     pi->init = init;
494     pi->next = urj_part_inits;
495     urj_part_inits = pi;
496 }
497 
498 urj_part_init_func_t
urj_part_find_init(char * part)499 urj_part_find_init (char *part)
500 {
501     urj_part_init_t *pi;
502 
503     for (pi = urj_part_inits; pi; pi = pi->next)
504         if (strcmp (pi->part, part) == 0)
505             return pi->init;
506 
507     return NULL;
508 }
509