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